diff options
-rw-r--r-- | src/gamma-quartz.c | 160 | ||||
-rw-r--r-- | src/gamma-quartz.h | 14 |
2 files changed, 133 insertions, 41 deletions
diff --git a/src/gamma-quartz.c b/src/gamma-quartz.c index 4eeac4d..6691c91 100644 --- a/src/gamma-quartz.c +++ b/src/gamma-quartz.c @@ -40,12 +40,95 @@ int quartz_init(quartz_state_t *state) { + state->preserve = 0; + state->displays = NULL; + return 0; } int quartz_start(quartz_state_t *state) { + int r; + CGError error; + uint32_t display_count; + + /* Get display count */ + error = CGGetOnlineDisplayList(0, NULL, &display_count); + if (error != kCGErrorSuccess) return -1; + + state->display_count = display_count; + + CGDirectDisplayID* displays = + malloc(sizeof(CGDirectDisplayID)*display_count); + if (displays == NULL) { + perror("malloc"); + return -1; + } + + /* Get list of displays */ + error = CGGetOnlineDisplayList(display_count, displays, + &display_count); + if (error != kCGErrorSuccess) { + free(displays); + return -1; + } + + /* Allocate list of display state */ + state->displays = malloc(display_count * + sizeof(quartz_display_state_t)); + if (state->displays == NULL) { + perror("malloc"); + free(displays); + return -1; + } + + /* Copy display indentifiers to display state */ + for (int i = 0; i < display_count; i++) { + state->displays[i].display = displays[i]; + state->displays[i].saved_ramps = NULL; + } + + free(displays); + + /* Save gamma ramps for all displays in display state */ + for (int i = 0; i < display_count; i++) { + CGDirectDisplayID display = state->displays[i].display; + + uint32_t ramp_size = CGDisplayGammaTableCapacity(display); + if (ramp_size == 0) { + fprintf(stderr, _("Gamma ramp size too small: %i\n"), + ramp_size); + return -1; + } + + state->displays[i].ramp_size = ramp_size; + + /* Allocate space for saved ramps */ + state->displays[i].saved_ramps = + malloc(3 * ramp_size * sizeof(float)); + if (state->displays[i].saved_ramps == NULL) { + perror("malloc"); + return -1; + } + + float *gamma_r = &state->displays[i].saved_ramps[0*ramp_size]; + float *gamma_g = &state->displays[i].saved_ramps[1*ramp_size]; + float *gamma_b = &state->displays[i].saved_ramps[2*ramp_size]; + + /* Copy the ramps to allocated space */ + uint32_t sample_count; + error = CGGetDisplayTransferByTable(display, ramp_size, + gamma_r, gamma_g, gamma_b, + &sample_count); + if (error != kCGErrorSuccess || + sample_count != ramp_size) { + fputs(_("Unable to save current gamma ramp.\n"), + stderr); + return -1; + } + } + return 0; } @@ -58,6 +141,12 @@ quartz_restore(quartz_state_t *state) void quartz_free(quartz_state_t *state) { + if (state->displays != NULL) { + for (int i = 0; i < state->display_count; i++) { + free(state->displays[i].saved_ramps); + } + } + free(state->displays); } void @@ -65,25 +154,33 @@ quartz_print_help(FILE *f) { fputs(_("Adjust gamma ramps on OSX using Quartz.\n"), f); fputs("\n", f); + + /* TRANSLATORS: Quartz help output + left column must not be translated */ + fputs(_(" preserve={0,1}\tWhether existing gamma should be" + " preserved\n"), + f); + fputs("\n", f); } int quartz_set_option(quartz_state_t *state, const char *key, const char *value) { - fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key); - return -1; + if (strcasecmp(key, "preserve") == 0) { + state->preserve = atoi(value); + } else { + fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key); + return -1; + } + + return 0; } static void -quartz_set_temperature_for_display(CGDirectDisplayID display, +quartz_set_temperature_for_display(quartz_state_t *state, int display, const color_setting_t *setting) { - uint32_t ramp_size = CGDisplayGammaTableCapacity(display); - if (ramp_size == 0) { - fprintf(stderr, _("Gamma ramp size too small: %i\n"), - ramp_size); - return; - } + uint32_t ramp_size = state->displays[display].ramp_size; /* Create new gamma ramps */ float *gamma_ramps = malloc(3*ramp_size*sizeof(float)); @@ -96,12 +193,18 @@ quartz_set_temperature_for_display(CGDirectDisplayID display, float *gamma_g = &gamma_ramps[1*ramp_size]; float *gamma_b = &gamma_ramps[2*ramp_size]; - /* Initialize gamma ramps to pure state */ - for (int i = 0; i < ramp_size; i++) { - float value = (double)i/ramp_size; - gamma_r[i] = value; - gamma_g[i] = value; - gamma_b[i] = value; + if (state->preserve) { + /* Initialize gamma ramps from saved state */ + memcpy(gamma_ramps, state->displays[display].saved_ramps, + 3*ramp_size*sizeof(float)); + } else { + /* Initialize gamma ramps to pure state */ + for (int i = 0; i < ramp_size; i++) { + float value = (double)i/ramp_size; + gamma_r[i] = value; + gamma_g[i] = value; + gamma_b[i] = value; + } } colorramp_fill_float(gamma_r, gamma_g, gamma_b, ramp_size, @@ -122,32 +225,9 @@ int quartz_set_temperature(quartz_state_t *state, const color_setting_t *setting) { - int r; - CGError error; - uint32_t display_count; - - error = CGGetOnlineDisplayList(0, NULL, &display_count); - if (error != kCGErrorSuccess) return -1; - - CGDirectDisplayID* displays = - malloc(sizeof(CGDirectDisplayID)*display_count); - if (displays == NULL) { - perror("malloc"); - return -1; + for (int i = 0; i < state->display_count; i++) { + quartz_set_temperature_for_display(state, i, setting); } - error = CGGetOnlineDisplayList(display_count, displays, - &display_count); - if (error != kCGErrorSuccess) { - free(displays); - return -1; - } - - for (int i = 0; i < display_count; i++) { - quartz_set_temperature_for_display(displays[i], setting); - } - - free(displays); - return 0; } diff --git a/src/gamma-quartz.h b/src/gamma-quartz.h index b5bc213..cd29d54 100644 --- a/src/gamma-quartz.h +++ b/src/gamma-quartz.h @@ -20,11 +20,23 @@ #ifndef REDSHIFT_GAMMA_QUARTZ_H #define REDSHIFT_GAMMA_QUARTZ_H +#include <stdint.h> + +#include <ApplicationServices/ApplicationServices.h> + #include "redshift.h" typedef struct { - int dummy; + CGDirectDisplayID display; + uint32_t ramp_size; + float *saved_ramps; +} quartz_display_state_t; + +typedef struct { + quartz_display_state_t *displays; + uint32_t display_count; + int preserve; } quartz_state_t; |