aboutsummaryrefslogtreecommitdiffstats
path: root/src/gamma-coopgamma.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-03-27 18:36:26 +0100
committerMattias Andrée <m@maandree.se>2025-03-27 18:36:26 +0100
commit037b945a9f253b97faffc02d8475574e75203516 (patch)
treeb008e7d77e9daaeaaa8e7854728d715df5aafb77 /src/gamma-coopgamma.c
parenttodo list housekeeping (diff)
downloadredshift-ng-037b945a9f253b97faffc02d8475574e75203516.tar.gz
redshift-ng-037b945a9f253b97faffc02d8475574e75203516.tar.bz2
redshift-ng-037b945a9f253b97faffc02d8475574e75203516.tar.xz
one dir per subproject
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'src/gamma-coopgamma.c')
-rw-r--r--src/gamma-coopgamma.c535
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);