diff options
Diffstat (limited to 'src/gamma-coopgamma.c')
-rw-r--r-- | src/gamma-coopgamma.c | 535 |
1 files changed, 0 insertions, 535 deletions
diff --git a/src/gamma-coopgamma.c b/src/gamma-coopgamma.c deleted file mode 100644 index f51c0ee..0000000 --- a/src/gamma-coopgamma.c +++ /dev/null @@ -1,535 +0,0 @@ -/*- - * redshift-ng - Automatically adjust display colour temperature according the Sun - * - * Copyright (c) 2009-2018 Jon Lund Steffensen <jonlst@gmail.com> - * Copyright (c) 2014-2016, 2025 Mattias Andrée <m@maandree.se> - * - * redshift-ng is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * redshift-ng is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with redshift-ng. If not, see <http://www.gnu.org/licenses/>. - */ -#include "common.h" - -#include <libcoopgamma.h> - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wkeyword-macro" -#endif - - -struct coopgamma_output_id { - char *edid; - size_t index; -}; - - -struct coopgamma_crtc_state { - libcoopgamma_filter_t filter; - libcoopgamma_ramps_t plain_ramps; - size_t rampsize; -}; - - -struct gamma_state { - libcoopgamma_context_t ctx; - struct coopgamma_crtc_state *crtcs; - size_t n_crtcs; - char **methods; - char *method; - char *site; - int64_t priority; - int list_outputs; - struct coopgamma_output_id *outputs; - size_t n_outputs; - size_t a_outputs; -}; - - -struct signal_blockage {int dummy;}; - - -static int -unblocked_signal(int signo, struct signal_blockage *prev) -{ - /* TODO */ - (void) signo; - (void) prev; - return 0; -} - - -static int -restore_signal_blockage(int signo, const struct signal_blockage *blockage) -{ - /* TODO */ - (void) signo; - (void) blockage; - return 0; -} - - -static int -update(struct gamma_state *state) -{ - size_t i; - for (i = 0; i < state->n_crtcs; i++) - libcoopgamma_set_gamma_sync(&state->crtcs[i].filter, &state->ctx); - return 0; -} - - -static void -print_error(struct gamma_state *state) -{ - unsigned long long int ec = (unsigned long long int)state->ctx.error.number; - if (state->ctx.error.custom) { - if (ec && state->ctx.error.description) { - if (state->ctx.error.server_side) - weprintf(_("Server-side error number %llu: %s."), ec, state->ctx.error.description); - else - weprintf(_("Client-side error number %llu: %s."), ec, state->ctx.error.description); - } else if (ec) { - if (state->ctx.error.server_side) - weprintf(_("Server-side error number %llu."), ec); - else - weprintf(_("Client-side error number %llu."), ec); - } else if (state->ctx.error.description) { - if (state->ctx.error.server_side) - weprintf(_("Server-side error: %s."), state->ctx.error.description); - else - weprintf(_("Client-side error: %s."), state->ctx.error.description); - } - } else if (state->ctx.error.description) { - if (state->ctx.error.server_side) - weprintf(_("Server-side error: %s."), state->ctx.error.description); - else - weprintf(_("Client-side error: %s."), state->ctx.error.description); - } else { - if (state->ctx.error.server_side) - weprintf(_("Server-side error: %s."), strerror(state->ctx.error.number)); - else - weprintf(_("Client-side error: %s."), strerror(state->ctx.error.number)); - } -} - - -static int -coopgamma_is_available(void) -{ - return 1; -} - - -static int -coopgamma_create(struct gamma_state **state_out) -{ - struct gamma_state *state; - struct signal_blockage signal_blockage; - - state = *state_out = ecalloc(1, sizeof(**state_out)); - - if (libcoopgamma_context_initialise(&state->ctx)) { - weprintf("libcoopgamma_context_initialise:"); - return -1; - } - - /* This is done this early to check if coopgamma is available */ - if (unblocked_signal(SIGCHLD, &signal_blockage) < 0) - return -1; - state->methods = libcoopgamma_get_methods(); - if (state->methods == NULL) { - weprintf("libcoopgamma_get_methods:"); - if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0) - exit(1); - return -1; - } - if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0) - return -1; - - state->priority = 0x0800000000000000LL; - - return 0; -} - - -static int -coopgamma_start(struct gamma_state *state) -{ - struct signal_blockage signal_blockage; - libcoopgamma_lifespan_t lifespan; - char** outputs; - size_t i, j, n_outputs; - int r; - double d; - - switch (mode) { - case PROGRAM_MODE_RESET: - lifespan = LIBCOOPGAMMA_REMOVE; - break; - case PROGRAM_MODE_ONE_SHOT: - lifespan = LIBCOOPGAMMA_UNTIL_REMOVAL; - break; - case PROGRAM_MODE_CONTINUAL: - case PROGRAM_MODE_UNTIL_DEATH: - lifespan = LIBCOOPGAMMA_UNTIL_DEATH; - break; - default: - case PROGRAM_MODE_PRINT: - abort(); - } - - free(state->methods); - state->methods = NULL; - - /* Connect to server */ - if (unblocked_signal(SIGCHLD, &signal_blockage) < 0) - return -1; - if (libcoopgamma_connect(state->method, state->site, &state->ctx) < 0) { - if (errno) - weprintf("libcoopgamma_connect:"); - else - weprintf(_("libcoopgamma_connect: could not start coopgamma server.")); - if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0) - exit(1); - return -1; - } - if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0) - return -1; - free(state->method); - state->method = NULL; - free(state->site); - state->site = NULL; - - /* Get available outputs */ - outputs = libcoopgamma_get_crtcs_sync(&state->ctx); - for (n_outputs = 0; outputs[n_outputs]; n_outputs++); - - /* List available output if edid=list was used */ - if (state->list_outputs) { - if (!outputs) { - print_error(state); - return -1; - } - printf(_("Available outputs:\n")); - for (i = 0; outputs[i]; i++) - printf(" %s\n", outputs[i]); - if (ferror(stdout)) - eprintf("printf:"); - exit(0); - } - - /* Translate crtc=N to edid=EDID */ - for (i = 0; i < state->n_outputs; i++) { - if (state->outputs[i].edid) - continue; - if (state->outputs[i].index >= n_outputs) { - weprintf(_("Monitor number %zu does not exist, available monitors are [0, %zu]"), - state->outputs[i].index, n_outputs - 1); - return -1; - } - state->outputs[i].edid = estrdup(outputs[state->outputs[i].index]); - } - - /* Use all outputs if none were specified */ - if (state->n_outputs == 0) { - state->n_outputs = state->a_outputs = n_outputs; - state->outputs = emalloc(n_outputs * sizeof(*state->outputs)); - for (i = 0; i < n_outputs; i++) - state->outputs[i].edid = estrdup(outputs[i]); - } - - free(outputs); - - /* Initialise information for each output */ - state->crtcs = ecalloc(state->n_outputs, sizeof(*state->crtcs)); - for (i = 0; i < state->n_outputs; i++) { - libcoopgamma_crtc_info_t info; - struct coopgamma_crtc_state *crtc = state->crtcs + state->n_crtcs; - - crtc->filter.priority = state->priority; - crtc->filter.crtc = state->outputs[i].edid; - crtc->filter.lifespan = lifespan; -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -#endif - crtc->filter.class = PACKAGE "::redshift::standard"; -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif - - if (libcoopgamma_get_gamma_info_sync(crtc->filter.crtc, &info, &state->ctx) < 0) { - int saved_errno = errno; - weprintf(_("Failed to retrieve information for output `%s':\n"), outputs[i]); - errno = saved_errno; - print_error(state); - return -1; - } - if (!info.cooperative) { - weprintf(_("coopgamma is not available.\n")); - return -1; - } - if (info.supported == LIBCOOPGAMMA_NO) { - weprintf(_("Output `%s' does not support gamma adjustments, skipping."), outputs[i]); - continue; - } - - /* Get total size of the ramps */ - switch (info.depth) { -#define X(SUFFIX, RAMPS, TYPE, MAX, DEPTH)\ - case DEPTH:\ - crtc->rampsize = sizeof(TYPE);\ - break - LIST_RAMPS_STOP_VALUE_TYPES(X, ;); -#undef X - default: - if (info.depth > 0) { - weprintf(_("output `%s' uses an unsupported depth " - "for its gamma ramps: %i bits, skipping\n"), - outputs[i], info.depth); - } else { - weprintf(_("output `%s' uses an unrecognised depth, " - "for its gamma ramps, with the code %i, " - "skipping\n"), outputs[i], info.depth); - } - continue; - } - crtc->rampsize *= info.red_size + info.green_size + info.blue_size; - - crtc->filter.depth = info.depth; - crtc->filter.ramps.u8.red_size = info.red_size; - crtc->filter.ramps.u8.green_size = info.green_size; - crtc->filter.ramps.u8.blue_size = info.blue_size; - crtc->plain_ramps.u8.red_size = info.red_size; - crtc->plain_ramps.u8.green_size = info.green_size; - crtc->plain_ramps.u8.blue_size = info.blue_size; - - /* Initialise plain ramp and working ramp */ -#define float f -#define double d - switch (info.depth) { -#define X(SUFFIX, RAMPS, TYPE, MAX, DEPTH)\ - case DEPTH:\ - r = libcoopgamma_ramps_initialise(&crtc->filter.ramps.SUFFIX);\ - if (r < 0) {\ - perror("libcoopgamma_ramps_initialise");\ - return -1;\ - }\ - r = libcoopgamma_ramps_initialise(&crtc->plain_ramps.SUFFIX);\ - if (r < 0) {\ - perror("libcoopgamma_ramps_initialise");\ - return -1;\ - }\ - for (j = 0; j < crtc->plain_ramps.SUFFIX.red_size; j++) {\ - d = j;\ - d /= crtc->plain_ramps.SUFFIX.red_size;\ - crtc->plain_ramps.SUFFIX.red[j] = d * (MAX);\ - }\ - for (j = 0; j < crtc->plain_ramps.SUFFIX.green_size; j++) {\ - d = j;\ - d /= crtc->plain_ramps.SUFFIX.green_size;\ - crtc->plain_ramps.SUFFIX.green[j] = d * (MAX);\ - }\ - for (j = 0; j < crtc->plain_ramps.SUFFIX.blue_size; j++) {\ - d = j;\ - d /= crtc->plain_ramps.SUFFIX.blue_size;\ - crtc->plain_ramps.SUFFIX.blue[j] = d * (MAX);\ - }\ - break - LIST_RAMPS_STOP_VALUE_TYPES(X, ;); -#undef X - default: - abort(); - } -#undef float -#undef double - - state->outputs[i].edid = NULL; - state->n_crtcs++; - } - - free(state->outputs); - state->outputs = NULL; - state->n_outputs = 0; - - return 0; -} - - -static void -coopgamma_free(struct gamma_state *state) -{ - free(state->methods); - free(state->method); - free(state->site); - - while (state->n_crtcs--) { - state->crtcs[state->n_crtcs].filter.class = NULL; - libcoopgamma_filter_destroy(&state->crtcs[state->n_crtcs].filter); - libcoopgamma_ramps_destroy(&state->crtcs[state->n_crtcs].plain_ramps); - } - free(state->crtcs); - - libcoopgamma_context_destroy(&state->ctx, 1); - while (state->n_outputs--) - free(state->outputs[state->n_outputs].edid); - state->n_outputs = 0; - free(state->outputs); - - free(state); -} - - -static void -coopgamma_print_help(void) /* TODO not documented in readme and manpage */ -{ - printf(_("Adjust gamma ramps with coopgamma.\n")); - printf("\n"); - - printf(" display=%s %s\n", _("NAME "), _("Display server instance to apply adjustments to")); - printf(" crtc=%s %s\n", _("N "), _("Index of CRTC to apply adjustments to")); - printf(" edid=%s %s\n", _("EDID "), _("EDID of monitor to apply adjustments to, " - "enter `list' to list available monitors")); - printf(" priority=%s %s\n", _("N "), _("The application order of the adjustments, " - "default value is 576460752303423488")); - printf(" method=%s %s\n", _("NAME "), _("Underlaying adjustment method, " - "enter `list' to list available methods")); - printf("\n"); -} - - -static int -coopgamma_set_option(struct gamma_state *state, const char *key, const char *value) -{ - size_t i; - char *end; - long long int priority; - - if (!strcasecmp(key, "priority")) { - errno = 0; - priority = strtoll(value, &end, 10); - if (errno || *end || priority < INT64_MIN || priority > INT64_MAX) { - weprintf(_("Value of method parameter `crtc' must be a integer in [%lli, %lli]."), - (long long int)INT64_MIN, (long long int)INT64_MAX); - return -1; - } - state->priority = priority; - } else if (!strcasecmp(key, "method")) { - if (state->method != NULL) { - weprintf(_("Method parameter `method' can only be used once.")); - return -1; - } - if (!strcasecmp(value, "list")) { - /* TRANSLATORS: coopgamma help output the word "coopgamma" must not be translated */ - printf(_("Available adjustment methods for coopgamma:\n")); - for (i = 0; state->methods[i]; i++) - printf(" %s\n", state->methods[i]); - if (ferror(stdout)) - eprintf("printf:"); - exit(0); - } - state->method = estrdup(value); - } else if (!strcasecmp(key, "display")) { - if (state->site != NULL) { - weprintf(_("Method parameter `display' can only be used once.")); - return -1; - } - state->site = estrdup(value); - } else if (!strcasecmp(key, "edid") || !strcasecmp(key, "crtc")) { - if (state->n_outputs == state->a_outputs) { - state->a_outputs += 8; - state->outputs = erealloc(state->outputs, state->a_outputs * sizeof(*state->outputs)); - } - if (!strcasecmp(key, "edid")) { - state->outputs[state->n_outputs].edid = estrdup(value); - if (!strcasecmp(state->outputs[state->n_outputs].edid, "list")) - state->list_outputs = 1; - } else { - state->outputs[state->n_outputs].edid = NULL; - errno = 0; - state->outputs[state->n_outputs].index = (size_t)strtoul(value, &end, 10); - if (!*end && errno == ERANGE && state->outputs[state->n_outputs].index == SIZE_MAX) { - state->outputs[state->n_outputs].index = SIZE_MAX; - } else if (errno || *end) { - weprintf(_("Value of method parameter `crtc' must be a non-negative integer.")); - return -1; - } - } - state->n_outputs++; - } else { - weprintf(_("Unknown method parameter: `%s'."), key); - return -1; - } - - return 0; -} - - -static void -coopgamma_restore(struct gamma_state *state) -{ - size_t i; - for (i = 0; i < state->n_crtcs; i++) - state->crtcs[i].filter.lifespan = LIBCOOPGAMMA_REMOVE; - update(state); - for (i = 0; i < state->n_crtcs; i++) - state->crtcs[i].filter.lifespan = LIBCOOPGAMMA_UNTIL_DEATH; -} - - -static int -coopgamma_apply(struct gamma_state *state, const struct colour_setting *setting, int perserve) -{ - libcoopgamma_filter_t *filter; - libcoopgamma_filter_t *last_filter = NULL; - size_t i; - - (void) perserve; - - for (i = 0; i < state->n_crtcs; i++, last_filter = filter) { - filter = &state->crtcs[i].filter; - - /* Copy ramps for previous CRTC if its ramps is of same size and depth */ - if (last_filter && - last_filter->ramps.u8.red_size == filter->ramps.u8.red_size && - last_filter->ramps.u8.green_size == filter->ramps.u8.green_size && - last_filter->ramps.u8.blue_size == filter->ramps.u8.blue_size) { - memcpy(filter->ramps.u8.red, last_filter->ramps.u8.red, state->crtcs[i].rampsize); - continue; - } - - /* Otherwise, create calculate the ramps */ - memcpy(filter->ramps.u8.red, state->crtcs[i].plain_ramps.u8.red, state->crtcs[i].rampsize); - switch (filter->depth) { -#define X(SUFFIX, RAMPS, TYPE, MAX, DEPTH)\ - case DEPTH:\ - fill_ramps_##SUFFIX((void *)(filter->ramps.u8.red),\ - (void *)(filter->ramps.u8.green),\ - (void *)(filter->ramps.u8.blue),\ - NULL, NULL, NULL,\ - filter->ramps.u8.red_size,\ - filter->ramps.u8.green_size,\ - filter->ramps.u8.blue_size,\ - setting);\ - break - LIST_RAMPS_STOP_VALUE_TYPES(X, ;); -#undef X - default: - abort(); - } - } - - return update(state); -} - - -const struct gamma_method coopgamma_gamma_method = GAMMA_METHOD_INIT("coopgamma", 1, 0, coopgamma); |