diff options
Diffstat (limited to 'redshift/gamma.c')
-rw-r--r-- | redshift/gamma.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/redshift/gamma.c b/redshift/gamma.c new file mode 100644 index 0000000..8dbb99b --- /dev/null +++ b/redshift/gamma.c @@ -0,0 +1,139 @@ +/*- + * 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" + + +const struct gamma_method *gamma_methods[] = { +#ifdef ENABLE_COOPGAMMA + &coopgamma_gamma_method, +#endif + &drm_gamma_method, + &randr_gamma_method, + &vidmode_gamma_method, + &quartz_gamma_method, + &wingdi_gamma_method, + &dummy_gamma_method, + NULL +}; + + +/** + * Attempt to start a specific adjustment method + * + * @param method The adjustment method + * @param state_out Output parameter for the adjustment method state + * @param config Loaded information file + * @param args `NULL` or option part of the command line argument for the adjustment method + * @return 0 on success, -1 on failure + */ +static int +try_start(const struct gamma_method *method, GAMMA_STATE **state_out, struct config_ini_state *config, char *args) +{ + struct config_ini_section *section; + struct config_ini_setting *setting; + char *next_arg, *value; + const char *key; + + if (method->create(state_out) < 0) { + weprintf(_("Initialization of %s failed."), method->name); + goto fail; + } + + /* Set method options from config file */ + if ((section = config_ini_get_section(config, method->name))) + for (setting = section->settings; setting; setting = setting->next) + if (method->set_option(*state_out, setting->name, setting->value) < 0) + goto set_option_fail; + + /* Set method options from command line */ + for (; args && *args; args = next_arg) { + if (!strncasecmp(args, "display=", sizeof("display=") - 1U)) + next_arg = &args[strcspn(args, ";")]; + else + next_arg = &args[strcspn(args, ";:")]; + if (*next_arg) + *next_arg++ = '\0'; + + key = args; + value = strchr(args, '='); + if (!value) { + weprintf(_("Failed to parse option `%s'."), args); + goto fail; + } + *value++ = '\0'; + + if (method->set_option(*state_out, key, value) < 0) + goto set_option_fail; + } + + /* Start method */ + if (method->start(*state_out) < 0) { + weprintf(_("Failed to start adjustment method %s."), method->name); + goto fail; + } + + return 0; + +set_option_fail: + weprintf(_("Failed to set %s option."), method->name); + /* TRANSLATORS: `help' must not be translated. */ + weprintf(_("Try `-m %s:help' for more information."), method->name); +fail: + if (*state_out) { + method->free(*state_out); + *state_out = NULL; + } + return -1; +} + + +void +acquire_adjustment_method(struct settings *settings, GAMMA_STATE **method_state_out) +{ + size_t i; + + if (settings->method) { + /* Use method specified on command line */ + if (try_start(settings->method, method_state_out, &settings->config, settings->method_args) < 0) + exit(1); + } else { + /* Try all methods, use the first that works */ + for (i = 0; gamma_methods[i]; i++) { + if (!gamma_methods[i]->autostart) + continue; + if (!gamma_methods[i]->is_available()) + continue; + + if (try_start(gamma_methods[i], method_state_out, &settings->config, NULL) < 0) { + weprintf(_("Trying next method...")); + continue; + } + + /* Found method that works */ + printf(_("Using method `%s'.\n"), gamma_methods[i]->name); + settings->method = gamma_methods[i]; + break; + } + + /* Failure if no methods were successful at this point */ + if (!settings->method) + eprintf(_("No more methods to try.")); + } +} |