diff options
-rw-r--r-- | cg-base.c | 1324 | ||||
-rw-r--r-- | cg-base.h | 143 |
2 files changed, 700 insertions, 767 deletions
@@ -1,20 +1,4 @@ -/** - * cg-tools -- Cooperative gamma-enabled tools - * Copyright (C) 2016, 2018 Mattias Andrée (maandree@kth.se) - * - * This program 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. - * - * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. - */ +/* See LICENSE file for copyright and license details. */ #include "cg-base.h" #include <libclut.h> @@ -33,7 +17,7 @@ /** * The process's name */ -const char* argv0 = NULL; +const char *argv0 = NULL; /** * The libcoopgamma context @@ -43,18 +27,18 @@ libcoopgamma_context_t cg; /** * The names of the selected CRTC:s */ -char** crtcs = NULL; +char **crtcs = NULL; /** * Gamma ramp updates for each CRTC */ -filter_update_t* crtc_updates = NULL; +filter_update_t *crtc_updates = NULL; /** * CRTC and monitor information about * each selected CRTC and connect monitor */ -libcoopgamma_crtc_info_t* crtc_info = NULL; +libcoopgamma_crtc_info_t *crtc_info = NULL; /** * The number of selected CRTC:s @@ -70,7 +54,7 @@ size_t filters_n = 0; /** * Contexts for asynchronous ramp updates */ -static libcoopgamma_async_context_t* asyncs = NULL; +static libcoopgamma_async_context_t *asyncs = NULL; /** * The number of pending receives @@ -89,35 +73,35 @@ static int flush_pending = 0; */ struct crtc_sort_data { - /** - * The gamma ramp type - */ - libcoopgamma_depth_t depth; - - /** - * Should be 0 - */ - int __padding; - - /** - * The size of the red gamma ramp - */ - size_t red_size; - - /** - * The size of the green gamma ramp - */ - size_t green_size; - - /** - * The size of the blue gamma ramp - */ - size_t blue_size; - - /** - * The index of the CRTC - */ - size_t index; + /** + * The gamma ramp type + */ + libcoopgamma_depth_t depth; + + /** + * Should be 0 + */ + int __padding; + + /** + * The size of the red gamma ramp + */ + size_t red_size; + + /** + * The size of the green gamma ramp + */ + size_t green_size; + + /** + * The size of the blue gamma ramp + */ + size_t blue_size; + + /** + * The index of the CRTC + */ + size_t index; }; @@ -129,9 +113,10 @@ struct crtc_sort_data * @param b Return +1 if this string is less than `a` * @return See `a` and `b`, 0 is returned if `a` and `b` are equal */ -static int nulstrcmp(const char *a, const char *b) +static int +nulstrcmp(const char *a, const char *b) { - return (a == NULL) ? -1 : strcmp(a, b); + return !a ? -1 : strcmp(a, b); } @@ -142,12 +127,13 @@ static int nulstrcmp(const char *a, const char *b) * @param b_ Return +1 if this one is higher * @return See `a_` and `b_`, only -1 or +1 can be returned */ -static int crtc_sort_data_cmp(const void* a_, const void* b_) +static int +crtc_sort_data_cmp(const void *a_, const void *b_) { - const struct crtc_sort_data* a = a_; - const struct crtc_sort_data* b = b_; - int cmp = memcmp(a, b, sizeof(*a) - sizeof(a->index)); - return cmp ? cmp : a->index < b->index ? -1 : +1; + const struct crtc_sort_data *a = a_; + const struct crtc_sort_data *b = b_; + int cmp = memcmp(a, b, sizeof(*a) - sizeof(a->index)); + return cmp ? cmp : a->index < b->index ? -1 : +1; } @@ -156,62 +142,58 @@ static int crtc_sort_data_cmp(const void* a_, const void* b_) * * @return Zero on success, -1 on error */ -int make_slaves(void) +int +make_slaves(void) { - struct crtc_sort_data* data; - size_t i, j, n = 0, master = 0, master_i; - - data = alloca(filters_n * sizeof(*data)); - memset(data, 0, filters_n * sizeof(*data)); - for (i = 0; i < filters_n; i++) - { - if (!(crtc_info[crtc_updates[i].crtc].supported)) - continue; - - data[n].depth = crtc_updates[i].filter.depth; - data[n].red_size = crtc_updates[i].filter.ramps.u8.red_size; - data[n].green_size = crtc_updates[i].filter.ramps.u8.green_size; - data[n].blue_size = crtc_updates[i].filter.ramps.u8.blue_size; - data[n].index = i; - n++; - } - - qsort(data, n, sizeof(*data), crtc_sort_data_cmp); - if (n == 0) - return 0; - - master_i = data[0].index; - for (i = 1; i < n; i++) - if (memcmp(data + i, data + master, sizeof(*data) - sizeof(data->index))) - { - if (master + 1 < i) - { - crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); - if (crtc_updates[master_i].slaves == NULL) - return -1; - for (j = 1; master + j < i; j++) - crtc_updates[master_i].slaves[j - 1] = data[master + j].index; - } - master = i; - master_i = data[master].index; - } - else - { - libcoopgamma_ramps_destroy(&(crtc_updates[data[i].index].filter.ramps.u8)); - crtc_updates[data[i].index].master = 0; - crtc_updates[data[i].index].filter.ramps.u8 = crtc_updates[master_i].filter.ramps.u8; - } - - if (master + 1 < i) - { - crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); - if (crtc_updates[master_i].slaves == NULL) - return -1; - for (j = 1; master + j < i; j++) - crtc_updates[master_i].slaves[j - 1] = data[master + j].index; - } - - return 0; + struct crtc_sort_data *data; + size_t i, j, n = 0, master = 0, master_i; + + data = alloca(filters_n * sizeof(*data)); + memset(data, 0, filters_n * sizeof(*data)); + for (i = 0; i < filters_n; i++) { + if (!crtc_info[crtc_updates[i].crtc].supported) + continue; + + data[n].depth = crtc_updates[i].filter.depth; + data[n].red_size = crtc_updates[i].filter.ramps.u8.red_size; + data[n].green_size = crtc_updates[i].filter.ramps.u8.green_size; + data[n].blue_size = crtc_updates[i].filter.ramps.u8.blue_size; + data[n].index = i; + n++; + } + + qsort(data, n, sizeof(*data), crtc_sort_data_cmp); + if (!n) + return 0; + + master_i = data[0].index; + for (i = 1; i < n; i++) { + if (memcmp(data + i, data + master, sizeof(*data) - sizeof(data->index))) { + if (master + 1 < i) { + crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); + if (!crtc_updates[master_i].slaves) + return -1; + for (j = 1; master + j < i; j++) + crtc_updates[master_i].slaves[j - 1] = data[master + j].index; + } + master = i; + master_i = data[master].index; + } else { + libcoopgamma_ramps_destroy(&crtc_updates[data[i].index].filter.ramps.u8); + crtc_updates[data[i].index].master = 0; + crtc_updates[data[i].index].filter.ramps.u8 = crtc_updates[master_i].filter.ramps.u8; + } + } + + if (master + 1 < i) { + crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); + if (!crtc_updates[master_i].slaves) + return -1; + for (j = 1; master + j < i; j++) + crtc_updates[master_i].slaves[j - 1] = data[master + j].index; + } + + return 0; } @@ -229,31 +211,32 @@ int make_slaves(void) * @throws EINTR Call to `poll` was interrupted by a signal * @throws EAGAIN Call to `poll` timed out */ -int update_filter(size_t index, int timeout) +int +update_filter(size_t index, int timeout) { - filter_update_t* filter = crtc_updates + index; - - if (!(filter->synced) || filter->failed) - abort(); - - pending_recvs += 1; - - if (libcoopgamma_set_gamma_send(&(filter->filter), &cg, asyncs + index) < 0) - switch (errno) - { - case EINTR: - case EAGAIN: + filter_update_t *filter = crtc_updates + index; + + if (!filter->synced || filter->failed) + abort(); + + pending_recvs += 1; + + if (libcoopgamma_set_gamma_send(&filter->filter, &cg, asyncs + index) < 0) { + switch (errno) { + case EINTR: + case EAGAIN: #if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: + case EWOULDBLOCK: #endif - flush_pending = 1; - break; - default: - return -1; - } + flush_pending = 1; + break; + default: + return -1; + } + } - filter->synced = 0; - return synchronise(timeout); + filter->synced = 0; + return synchronise(timeout); } @@ -270,78 +253,73 @@ int update_filter(size_t index, int timeout) * @throws EINTR Call to `poll` was interrupted by a signal * @throws EAGAIN Call to `poll` timed out */ -int synchronise(int timeout) +int +synchronise(int timeout) { - struct pollfd pollfd; - size_t selected; - - pollfd.fd = cg.fd; - pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; - if (flush_pending > 0) - pollfd.events |= POLLOUT; - - pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, timeout) < 0) - return -1; - - if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) - { - if (libcoopgamma_flush(&cg) < 0) - goto sync; - flush_pending = 0; - } - - if ((timeout < 0) && (pending_recvs > 0)) - if (!(pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI))) - { + struct pollfd pollfd; + size_t selected; + + pollfd.fd = cg.fd; + pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; + if (flush_pending > 0) + pollfd.events |= POLLOUT; + pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, -1) < 0) - return -1; - } - + if (poll(&pollfd, (nfds_t)1, timeout) < 0) + return -1; + + if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) { + if (libcoopgamma_flush(&cg) < 0) + goto sync; + flush_pending = 0; + } + + if (timeout < 0 && pending_recvs > 0) { + if (!(pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI))) { + pollfd.revents = 0; + if (poll(&pollfd, (nfds_t)1, -1) < 0) + return -1; + } + } + sync: - if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLERR | POLLHUP | POLLNVAL)) - for (;;) - { - if (libcoopgamma_synchronise(&cg, asyncs, filters_n, &selected) < 0) - { - if (errno == 0) - continue; - else - goto fail; - } - if (crtc_updates[selected].synced) - continue; - crtc_updates[selected].synced = 1; - pending_recvs -= 1; - if (libcoopgamma_set_gamma_recv(&cg, asyncs + selected) < 0) - { - if (cg.error.server_side) - { - crtc_updates[selected].error = cg.error; - crtc_updates[selected].failed = 1; - memset(&(cg.error), 0, sizeof(cg.error)); - } - else - goto cg_fail; - } - } - - return pending_recvs == 0; - cg_fail: - return -2; - fail: - switch (errno) - { - case EINTR: - case EAGAIN: + if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLERR | POLLHUP | POLLNVAL)) { + for (;;) { + if (libcoopgamma_synchronise(&cg, asyncs, filters_n, &selected) < 0) { + if (!errno) + continue; + goto fail; + } + if (crtc_updates[selected].synced) + continue; + crtc_updates[selected].synced = 1; + pending_recvs -= 1; + if (libcoopgamma_set_gamma_recv(&cg, asyncs + selected) < 0) { + if (cg.error.server_side) { + crtc_updates[selected].error = cg.error; + crtc_updates[selected].failed = 1; + memset(&cg.error, 0, sizeof(cg.error)); + } else { + goto cg_fail; + } + } + } + } + + return !pending_recvs; +cg_fail: + return -2; +fail: + switch (errno) { + case EINTR: + case EAGAIN: #if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: + case EWOULDBLOCK: #endif - return pending_recvs == 0; - default: - return -1; - } + return !pending_recvs; + default: + return -1; + } } @@ -351,22 +329,23 @@ int synchronise(int timeout) * * @return Zero on success, -1 on error */ -static int initialise_proc(void) +static int +initialise_proc(void) { - sigset_t sigmask; - int sig; - - for (sig = 1; sig < _NSIG; sig++) - if (signal(sig, SIG_DFL) == SIG_ERR) - if (sig == SIGCHLD) - return -1; - - if (sigemptyset(&sigmask) < 0) - return -1; - if (sigprocmask(SIG_SETMASK, &sigmask, NULL) < 0) - return -1; - - return 0; + sigset_t sigmask; + int sig; + + for (sig = 1; sig < _NSIG; sig++) + if (signal(sig, SIG_DFL) == SIG_ERR) + if (sig == SIGCHLD) + return -1; + + if (sigemptyset(&sigmask) < 0) + return -1; + if (sigprocmask(SIG_SETMASK, &sigmask, NULL) < 0) + return -1; + + return 0; } @@ -376,21 +355,22 @@ static int initialise_proc(void) * * @return Zero on success, -1 on error */ -static int list_methods(void) +static int +list_methods(void) { - char** list; - size_t i; - - list = libcoopgamma_get_methods(); - if (list == NULL) - return -1; - for (i = 0; list[i]; i++) - printf("%s\n", list[i]); - free(list); - if (fflush(stdout) < 0) - return -1; - - return 0; + char **list; + size_t i; + + list = libcoopgamma_get_methods(); + if (!list) + return -1; + for (i = 0; list[i]; i++) + printf("%s\n", list[i]); + free(list); + if (fflush(stdout) < 0) + return -1; + + return 0; } @@ -403,21 +383,22 @@ static int list_methods(void) * @return Zero on success, -1 on error, -2 * on libcoopgamma error */ -static int list_crtcs(void) +static int +list_crtcs(void) { - char** list; - size_t i; - - list = libcoopgamma_get_crtcs_sync(&cg); - if (list == NULL) - return -2; - for (i = 0; list[i]; i++) - printf("%s\n", list[i]); - free(list); - if (fflush(stdout) < 0) - return -1; - - return 0; + char **list; + size_t i; + + list = libcoopgamma_get_crtcs_sync(&cg); + if (!list) + return -2; + for (i = 0; list[i]; i++) + printf("%s\n", list[i]); + free(list); + if (fflush(stdout) < 0) + return -1; + + return 0; } @@ -427,99 +408,97 @@ static int list_crtcs(void) * @return Zero on success, -1 on error, -2 * on libcoopgamma error */ -static int get_crtc_info(void) +static int +get_crtc_info(void) { - size_t i, unsynced = 0, selected; - char* synced; - int need_flush = 0; - struct pollfd pollfd; - - synced = alloca(crtcs_n * sizeof(*synced)); - memset(synced, 0, crtcs_n * sizeof(*synced)); - - i = 0; - pollfd.fd = cg.fd; - pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; - - while ((unsynced > 0) || (i < crtcs_n)) - { - wait: - if (i < crtcs_n) - pollfd.events |= POLLOUT; - else - pollfd.events &= ~POLLOUT; + size_t i, unsynced = 0, selected; + char *synced; + int need_flush = 0; + struct pollfd pollfd; + + synced = alloca(crtcs_n * sizeof(*synced)); + memset(synced, 0, crtcs_n * sizeof(*synced)); + + i = 0; + pollfd.fd = cg.fd; + pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; + + while (unsynced > 0 || i < crtcs_n) { + wait: + if (i < crtcs_n) + pollfd.events |= POLLOUT; + else + pollfd.events &= ~POLLOUT; - pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, -1) < 0) - goto fail; + pollfd.revents = 0; + if (poll(&pollfd, (nfds_t)1, -1) < 0) + goto fail; - if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) - { - if (need_flush && (libcoopgamma_flush(&cg) < 0)) - goto send_fail; - need_flush = 0; - for (; i < crtcs_n; i++) - if (unsynced++, libcoopgamma_get_gamma_info_send(crtcs[i], &cg, asyncs + i) < 0) - goto send_fail; - goto send_done; - send_fail: - switch (errno) - { - case EINTR: - case EAGAIN: + if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) { + if (need_flush && (libcoopgamma_flush(&cg) < 0)) + goto send_fail; + need_flush = 0; + for (; i < crtcs_n; i++) + if (unsynced++, libcoopgamma_get_gamma_info_send(crtcs[i], &cg, asyncs + i) < 0) + goto send_fail; + goto send_done; + send_fail: + switch (errno) { + case EINTR: + case EAGAIN: #if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: + case EWOULDBLOCK: #endif - i++; - need_flush = 1; - break; - default: - goto fail; - } - } - send_done: - - if ((unsynced == 0) && (i == crtcs_n)) - break; - - if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) - while (unsynced > 0) - switch (libcoopgamma_synchronise(&cg, asyncs, i, &selected)) - { - case 0: - if (synced[selected]) - { - libcoopgamma_skip_message(&cg); - break; + i++; + need_flush = 1; + break; + default: + goto fail; + } } - synced[selected] = 1; - unsynced -= 1; - if (libcoopgamma_get_gamma_info_recv(crtc_info + selected, &cg, asyncs + selected) < 0) - goto cg_fail; - break; - case -1: - switch (errno) - { - case 0: - break; - case EINTR: - case EAGAIN: + send_done: + + if (!unsynced && i == crtcs_n) + break; + + if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { + while (unsynced > 0) { + switch (libcoopgamma_synchronise(&cg, asyncs, i, &selected)) { + case 0: + if (synced[selected]) { + libcoopgamma_skip_message(&cg); + break; + } + synced[selected] = 1; + unsynced -= 1; + if (libcoopgamma_get_gamma_info_recv(crtc_info + selected, &cg, asyncs + selected) < 0) + goto cg_fail; + break; + case -1: + switch (errno) + { + case 0: + break; + case EINTR: + case EAGAIN: #if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: + case EWOULDBLOCK: #endif - goto wait; - default: - goto fail; + goto wait; + default: + goto fail; + } + break; + } + } } - break; - } - } - - return 0; - fail: - return -1; - cg_fail: - return -2; + } + + return 0; +fail: + return -1; +cg_fail: + return -2; } @@ -555,373 +534,344 @@ static int get_crtc_info(void) * @param argv The command line arguments * @return 0 on success, 1 on error */ -int main(int argc, char* argv[]) +int +main(int argc, char *argv[]) { - int stage = 0; - int dealloc_crtcs = 0; - int rc = 0; - char* method = NULL; - char* site = NULL; - size_t crtc_i = 0; - int64_t priority = default_priority; - char* prio = NULL; - char* rule = NULL; - char* class = default_class; - char** classes = NULL; - size_t classes_n = 0; - int explicit_crtcs = 0; - int have_crtc_q = 0; - size_t i, filter_i; - - argv0 = *argv++, argc--; - - if (initialise_proc() < 0) - goto fail; - - crtcs = alloca(argc * sizeof(*crtcs)); - - for (; *argv; argv++, argc--) - { - char* args = *argv; - char opt[3]; - if (!strcmp(args, "--")) - { - argv++, argc--; - break; + int stage = 0; + int dealloc_crtcs = 0; + int rc = 0; + char *method = NULL; + char *site = NULL; + size_t crtc_i = 0; + int64_t priority = default_priority; + char *prio = NULL; + char *rule = NULL; + char *class = default_class; + char **classes = NULL; + size_t classes_n = 0; + int explicit_crtcs = 0; + int have_crtc_q = 0; + size_t i, filter_i; + const char *side, *crtc; + size_t len, n; + char *args, *arg, *end, *p, opt[3]; + int at_end; + + argv0 = *argv++, argc--; + + if (initialise_proc() < 0) + goto fail; + + crtcs = alloca((size_t)argc * sizeof(*crtcs)); + + for (; *argv; argv++, argc--) { + args = *argv; + if (!strcmp(args, "--")) { + argv++, argc--; + break; + } + opt[0] = *args++; + opt[2] = '\0'; + if (*opt != '-' && *opt != '+') + break; + if (!*args) + break; + while (*args) { + opt[1] = *args++; + arg = args; + if ((at_end = !*arg)) + arg = argv[1]; + if (!strcmp(opt, "-M")) { + if (method || !(method = arg)) + usage(); + } else if (!strcmp(opt, "-S")) { + if (site || !(site = arg)) + usage(); + } else if (!strcmp(opt, "-c")) { + if (!arg) + usage(); + crtcs[crtc_i++] = arg; + explicit_crtcs = 1; + if (!have_crtc_q && !strcmp(arg, "?")) + have_crtc_q = 1; + } else if (!strcmp(opt, "-p")) { + if (prio || !(prio = arg)) + usage(); + } else if (!strcmp(opt, "-R")) { + if (rule || !(rule = arg)) + usage(); + } else { + switch (handle_opt(opt, arg)) { + case 0: + goto next_opt; + case 1: + break; + default: + goto fail; + } + } + argv += at_end; + argc -= at_end; + break; + next_opt:; + } } - opt[0] = *args++; - opt[2] = '\0'; - if ((*opt != '-') && (*opt != '+')) - break; - while (*args) - { - char* arg; - int at_end; - opt[1] = *args++; - arg = args; - if ((at_end = !*arg)) - arg = argv[1]; - if (!strcmp(opt, "-M")) - { - if ((method != NULL) || ((method = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-S")) - { - if ((site != NULL) || ((site = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-c")) - { - if (arg == NULL) - usage(); - crtcs[crtc_i++] = arg; - explicit_crtcs = 1; - if (!have_crtc_q && !strcmp(arg, "?")) - have_crtc_q = 1; - } - else if (!strcmp(opt, "-p")) - { - if ((prio != NULL) || ((prio = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-R")) - { - if ((rule != NULL) || ((rule = arg) == NULL)) - usage(); - } - else - switch (handle_opt(opt, arg)) - { - case 0: - goto next_opt; - case 1: - break; - default: + + crtcs_n = crtc_i; + crtcs[crtc_i] = NULL; + if (!have_crtc_q && nulstrcmp(method, "?") && + nulstrcmp(rule, "?") && nulstrcmp(rule, "??") && + (default_priority == NO_DEFAULT_PRIORITY || nulstrcmp(prio, "?"))) + if (handle_args(argc, argv, prio) < 0) + goto fail; + + if (default_priority != NO_DEFAULT_PRIORITY) { + if (!nulstrcmp(prio, "?")) { + printf("%" PRIi64 "\n", priority); + return 0; + } else if (prio) { + errno = 0; + priority = (int64_t)strtoll(prio, &end, 10); + if (errno || *end || !*prio) + usage(); + } + } + + if (!nulstrcmp(rule, "??")) { + if (!*class_suffixes) + printf("%s\n", class); + else + for (i = 0; class_suffixes[i]; i++) + printf("%s%s\n", class, class_suffixes[i]); + return 0; + } else if (!nulstrcmp(rule, "?")) { + printf("%s\n", strstr(strstr(class, "::") + 2, "::") + 2); + return 0; + } else if (rule) { + p = strstr(strstr(class, "::") + 2, "::") + 2; + n = (size_t)(p - class); + class = alloca(strlen(rule) + n + (size_t)1); + memcpy(class, default_class, n); + strcpy(class + n, rule); + if (strchr(class, '\n')) { + fprintf(stderr, "%s: LF character is not allowed in the filter's class\n", argv0); + goto custom_fail; + } + } + + if (!nulstrcmp(method, "?")) { + if (list_methods() < 0) + goto fail; + return 0; + } + + if (libcoopgamma_context_initialise(&cg) < 0) goto fail; - } - argv += at_end; - argc -= at_end; - break; - next_opt:; + stage++; + if (libcoopgamma_connect(method, site, &cg) < 0) { + fprintf(stderr, "%s: server failed to initialise\n", argv0); + goto custom_fail; } - } - - crtcs_n = crtc_i; - crtcs[crtc_i] = NULL; - if (!have_crtc_q && nulstrcmp(method, "?") && - nulstrcmp(rule, "?") && nulstrcmp(rule, "??") && - ((default_priority == NO_DEFAULT_PRIORITY) || nulstrcmp(prio, "?"))) - if (handle_args(argc, argv, prio) < 0) - goto fail; - - if (default_priority != NO_DEFAULT_PRIORITY) - { - if (!nulstrcmp(prio, "?")) - { - printf("%" PRIi64 "\n", priority); - return 0; + stage++; + + if (have_crtc_q) { + switch (list_crtcs()) { + case 0: + goto done; + case -1: + goto fail; + default: + goto cg_fail; + } } - else if (prio != NULL) - { - char *end; - errno = 0; - priority = (int64_t)strtoll(prio, &end, 10); - if (errno || *end || !*prio) - usage(); + + if (!crtcs_n) { + crtcs = libcoopgamma_get_crtcs_sync(&cg); + if (!crtcs) + goto cg_fail; + dealloc_crtcs = 1; + for (; crtcs[crtcs_n]; crtcs_n++); } - } - - if (!nulstrcmp(rule, "??")) - { - size_t i; - if (*class_suffixes == NULL) - printf("%s\n", class); - else - for (i = 0; class_suffixes[i] != NULL; i++) - printf("%s%s\n", class, class_suffixes[i]); - return 0; - } - else if (!nulstrcmp(rule, "?")) - { - printf("%s\n", strstr(strstr(class, "::") + 2, "::") + 2); - return 0; - } - else if (rule != NULL) - { - char* p = strstr(strstr(class, "::") + 2, "::") + 2; - size_t n = (size_t)(p - class); - class = alloca(strlen(rule) + n + (size_t)1); - memcpy(class, default_class, n); - strcpy(class + n, rule); - if (strchr(class, '\n')) - { - fprintf(stderr, "%s: LF character is not allowed in the filter's class\n", argv0); - goto custom_fail; + + if (!crtcs_n) { + fprintf(stderr, "%s: no CRTC:s are available\n", argv0); + goto custom_fail; } - } - - if (!nulstrcmp(method, "?")) - { - if (list_methods() < 0) - goto fail; - return 0; - } - - if (libcoopgamma_context_initialise(&cg) < 0) - goto fail; - stage++; - if (libcoopgamma_connect(method, site, &cg) < 0) - { - fprintf(stderr, "%s: server failed to initialise\n", argv0); - goto custom_fail; - } - stage++; - - if (have_crtc_q) - switch (list_crtcs()) - { - case 0: - goto done; - case -1: - goto fail; - default: - goto cg_fail; - } - - if (crtcs_n == 0) - { - crtcs = libcoopgamma_get_crtcs_sync(&cg); - if (crtcs == NULL) - goto cg_fail; - dealloc_crtcs = 1; - for (; crtcs[crtcs_n] != NULL; crtcs_n++); - } - - if (crtcs_n == 0) - { - fprintf(stderr, "%s: no CRTC:s are available\n", argv0); - goto custom_fail; - } - - if (*class_suffixes == NULL) - { - classes = &class; - classes_n = 1; - } - else - { - size_t len = strlen(class); - while (class_suffixes[classes_n]) - classes_n++; - classes = alloca(classes_n * sizeof(*classes)); - for (i = 0; i < classes_n; i++) - { - classes[i] = alloca(len + strlen(class_suffixes[i]) + sizeof(":")); - stpcpy(stpcpy(stpcpy(classes[i], class), ":"), class_suffixes[i]); + + if (!*class_suffixes) { + classes = &class; + classes_n = 1; + } else { + len = strlen(class); + while (class_suffixes[classes_n]) + classes_n++; + classes = alloca(classes_n * sizeof(*classes)); + for (i = 0; i < classes_n; i++) { + classes[i] = alloca(len + strlen(class_suffixes[i]) + sizeof(":")); + stpcpy(stpcpy(stpcpy(classes[i], class), ":"), class_suffixes[i]); + } } - } - filters_n = classes_n * crtcs_n; - - crtc_info = alloca(crtcs_n * sizeof(*crtc_info)); - memset(crtc_info, 0, crtcs_n * sizeof(*crtc_info)); - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - if (libcoopgamma_crtc_info_initialise(crtc_info + crtc_i) < 0) - goto cg_fail; - - if (libcoopgamma_set_nonblocking(&cg, 1) < 0) - goto fail; - - asyncs = alloca(filters_n * sizeof(*asyncs)); - memset(asyncs, 0, filters_n * sizeof(*asyncs)); - for (filter_i = 0; filter_i < filters_n; filter_i++) - if (libcoopgamma_async_context_initialise(asyncs + filter_i) < 0) - goto fail; - - switch (get_crtc_info()) - { - case 0: - break; - case -1: - goto fail; - case -2: - goto cg_fail; - } - - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - { - if (explicit_crtcs && !(crtc_info[crtc_i].supported)) - fprintf(stderr, "%s: warning: gamma adjustments not supported on CRTC: %s\n", - argv0, crtcs[crtc_i]); - if (crtc_info[crtc_i].cooperative == 0) - fprintf(stderr, "%s: warning: cooperative gamma server not running for CRTC: %s\n", - argv0, crtcs[crtc_i]); - } - - crtc_updates = alloca(filters_n * sizeof(*crtc_updates)); - memset(crtc_updates, 0, filters_n * sizeof(*crtc_updates)); - for (filter_i = i = 0; i < classes_n; i++) - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++, filter_i++) - { - if (libcoopgamma_filter_initialise(&(crtc_updates[filter_i].filter)) < 0) - goto fail; - if (libcoopgamma_error_initialise(&(crtc_updates[filter_i].error)) < 0) - goto fail; - crtc_updates[filter_i].crtc = crtc_i; - crtc_updates[filter_i].synced = 1; - crtc_updates[filter_i].failed = 0; - crtc_updates[filter_i].master = 1; - crtc_updates[filter_i].slaves = NULL; - crtc_updates[filter_i].filter.crtc = crtcs[crtc_i]; - crtc_updates[filter_i].filter.class = classes[i]; - crtc_updates[filter_i].filter.priority = priority; - crtc_updates[filter_i].filter.depth = crtc_info[crtc_i].depth; - crtc_updates[filter_i].filter.ramps.u8.red_size = crtc_info[crtc_i].red_size; - crtc_updates[filter_i].filter.ramps.u8.green_size = crtc_info[crtc_i].green_size; - crtc_updates[filter_i].filter.ramps.u8.blue_size = crtc_info[crtc_i].blue_size; - switch (crtc_updates[filter_i].filter.depth) - { + filters_n = classes_n * crtcs_n; + + crtc_info = alloca(crtcs_n * sizeof(*crtc_info)); + memset(crtc_info, 0, crtcs_n * sizeof(*crtc_info)); + for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) + if (libcoopgamma_crtc_info_initialise(crtc_info + crtc_i) < 0) + goto cg_fail; + + if (libcoopgamma_set_nonblocking(&cg, 1) < 0) + goto fail; + + asyncs = alloca(filters_n * sizeof(*asyncs)); + memset(asyncs, 0, filters_n * sizeof(*asyncs)); + for (filter_i = 0; filter_i < filters_n; filter_i++) + if (libcoopgamma_async_context_initialise(asyncs + filter_i) < 0) + goto fail; + + switch (get_crtc_info()) { + case 0: + break; + case -1: + goto fail; + case -2: + goto cg_fail; + } + + for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) { + if (explicit_crtcs && !crtc_info[crtc_i].supported) { + fprintf(stderr, "%s: warning: gamma adjustments not supported on CRTC: %s\n", + argv0, crtcs[crtc_i]); + } + if (!crtc_info[crtc_i].cooperative) { + fprintf(stderr, "%s: warning: cooperative gamma server not running for CRTC: %s\n", + argv0, crtcs[crtc_i]); + } + } + + crtc_updates = alloca(filters_n * sizeof(*crtc_updates)); + memset(crtc_updates, 0, filters_n * sizeof(*crtc_updates)); + for (filter_i = i = 0; i < classes_n; i++) { + for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++, filter_i++) { + if (libcoopgamma_filter_initialise(&crtc_updates[filter_i].filter) < 0) + goto fail; + if (libcoopgamma_error_initialise(&crtc_updates[filter_i].error) < 0) + goto fail; + crtc_updates[filter_i].crtc = crtc_i; + crtc_updates[filter_i].synced = 1; + crtc_updates[filter_i].failed = 0; + crtc_updates[filter_i].master = 1; + crtc_updates[filter_i].slaves = NULL; + crtc_updates[filter_i].filter.crtc = crtcs[crtc_i]; + crtc_updates[filter_i].filter.class = classes[i]; + crtc_updates[filter_i].filter.priority = priority; + crtc_updates[filter_i].filter.depth = crtc_info[crtc_i].depth; + crtc_updates[filter_i].filter.ramps.u8.red_size = crtc_info[crtc_i].red_size; + crtc_updates[filter_i].filter.ramps.u8.green_size = crtc_info[crtc_i].green_size; + crtc_updates[filter_i].filter.ramps.u8.blue_size = crtc_info[crtc_i].blue_size; + switch (crtc_updates[filter_i].filter.depth) { #define X(CONST, MEMBER, MAX, TYPE)\ - case CONST:\ - libcoopgamma_ramps_initialise(&(crtc_updates[filter_i].filter.ramps.MEMBER));\ - libclut_start_over(&(crtc_updates[filter_i].filter.ramps.MEMBER), MAX, TYPE, 1, 1, 1);\ - break; -LIST_DEPTHS + case CONST:\ + libcoopgamma_ramps_initialise(&crtc_updates[filter_i].filter.ramps.MEMBER);\ + libclut_start_over(&crtc_updates[filter_i].filter.ramps.MEMBER, MAX, TYPE, 1, 1, 1);\ + break; + LIST_DEPTHS #undef X - default: - fprintf(stderr, "%s: internal error: gamma ramp type is unrecognised: %i\n", - argv0, crtc_updates[filter_i].filter.depth); - goto custom_fail; - } - } - - switch (start()) - { - case 0: - break; - case -1: - goto fail; - case -2: - goto cg_fail; - case -3: - goto custom_fail; - } - - for (filter_i = 0; filter_i < filters_n; filter_i++) - if (crtc_updates[filter_i].failed) - { - const char* side = cg.error.server_side ? "server" : "client"; - const char* crtc = crtc_updates[filter_i].filter.crtc; - if (cg.error.custom) - { - if ((cg.error.number != 0) && (cg.error.description != NULL)) - fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s: %s\n", - argv0, side, cg.error.number, crtc, cg.error.description); - else if (cg.error.number != 0) - fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s\n", - argv0, side, cg.error.number, crtc); - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, cg.error.description); - } - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, cg.error.description); - else - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, strerror(cg.error.number)); - } - - done: - if (dealloc_crtcs) - free(crtcs); - if (crtc_info != NULL) - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - libcoopgamma_crtc_info_destroy(crtc_info + crtc_i); - if (asyncs != NULL) - for (filter_i = 0; filter_i < filters_n; filter_i++) - libcoopgamma_async_context_destroy(asyncs + filter_i); - if (stage >= 1) - libcoopgamma_context_destroy(&cg, stage >= 2); - if (crtc_updates != NULL) - for (filter_i = 0; filter_i < filters_n; filter_i++) - { - if (crtc_updates[filter_i].master == 0) - memset(&(crtc_updates[filter_i].filter.ramps.u8), 0, sizeof(crtc_updates[filter_i].filter.ramps.u8)); - crtc_updates[filter_i].filter.crtc = NULL; - crtc_updates[filter_i].filter.class = NULL; - libcoopgamma_filter_destroy(&(crtc_updates[filter_i].filter)); - libcoopgamma_error_destroy(&(crtc_updates[filter_i].error)); - free(crtc_updates[filter_i].slaves); - } - return rc; - - custom_fail: - rc = 1; - goto done; - - fail: - rc = 1; - if (errno) - perror(argv0); - goto done; - - cg_fail: - rc = 1; - { - const char* side = cg.error.server_side ? "server" : "client"; - if (cg.error.custom) - { - if ((cg.error.number != 0) && (cg.error.description != NULL)) - fprintf(stderr, "%s: %s-side error number %" PRIu64 ": %s\n", - argv0, side, cg.error.number, cg.error.description); - else if (cg.error.number != 0) - fprintf(stderr, "%s: %s-side error number %" PRIu64 "\n", argv0, side, cg.error.number); - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); - } - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); - else - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, strerror(cg.error.number)); - } - goto done; -} + default: + fprintf(stderr, "%s: internal error: gamma ramp type is unrecognised: %i\n", + argv0, crtc_updates[filter_i].filter.depth); + goto custom_fail; + } + } + } + switch (start()) { + case 0: + break; + case -1: + goto fail; + case -2: + goto cg_fail; + case -3: + goto custom_fail; + } + + for (filter_i = 0; filter_i < filters_n; filter_i++) { + if (crtc_updates[filter_i].failed) { + side = cg.error.server_side ? "server" : "client"; + crtc = crtc_updates[filter_i].filter.crtc; + if (cg.error.custom) { + if (cg.error.number && cg.error.description) { + fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s: %s\n", + argv0, side, cg.error.number, crtc, cg.error.description); + } else if (cg.error.number) { + fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s\n", + argv0, side, cg.error.number, crtc); + } else if (cg.error.description) { + fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", + argv0, side, crtc, cg.error.description); + } + } else if (cg.error.description) { + fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", + argv0, side, crtc, cg.error.description); + } else { + fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", + argv0, side, crtc, strerror((int)cg.error.number)); + } + } + } + +done: + if (dealloc_crtcs) + free(crtcs); + if (crtc_info) + for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) + libcoopgamma_crtc_info_destroy(crtc_info + crtc_i); + if (asyncs) + for (filter_i = 0; filter_i < filters_n; filter_i++) + libcoopgamma_async_context_destroy(asyncs + filter_i); + if (stage >= 1) + libcoopgamma_context_destroy(&cg, stage >= 2); + if (crtc_updates) { + for (filter_i = 0; filter_i < filters_n; filter_i++) { + if (!crtc_updates[filter_i].master) { + memset(&crtc_updates[filter_i].filter.ramps.u8, 0, + sizeof(crtc_updates[filter_i].filter.ramps.u8)); + } + crtc_updates[filter_i].filter.crtc = NULL; + crtc_updates[filter_i].filter.class = NULL; + libcoopgamma_filter_destroy(&crtc_updates[filter_i].filter); + libcoopgamma_error_destroy(&crtc_updates[filter_i].error); + free(crtc_updates[filter_i].slaves); + } + } + return rc; + +custom_fail: + rc = 1; + goto done; + +fail: + rc = 1; + if (errno) + perror(argv0); + goto done; + +cg_fail: + rc = 1; + side = cg.error.server_side ? "server" : "client"; + if (cg.error.custom) { + if (cg.error.number && cg.error.description) { + fprintf(stderr, "%s: %s-side error number %" PRIu64 ": %s\n", + argv0, side, cg.error.number, cg.error.description); + } else if (cg.error.number) { + fprintf(stderr, "%s: %s-side error number %" PRIu64 "\n", argv0, side, cg.error.number); + } else if (cg.error.description) { + fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); + } + } else if (cg.error.description) { + fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); + } else { + fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, strerror((int)cg.error.number)); + } + goto done; +} @@ -1,20 +1,4 @@ -/** - * cg-tools -- Cooperative gamma-enabled tools - * Copyright (C) 2016 Mattias Andrée (maandree@kth.se) - * - * This program 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. - * - * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. - */ +/* See LICENSE file for copyright and license details. */ #include <libcoopgamma.h> #include <inttypes.h> @@ -25,7 +9,7 @@ * Value of `default_priority` that indicates * that there is no default priority */ -#define NO_DEFAULT_PRIORITY INT64_MAX +#define NO_DEFAULT_PRIORITY INT64_MAX @@ -40,12 +24,12 @@ * 4) The type of the ramp stops */ #define LIST_DEPTHS\ - X(LIBCOOPGAMMA_UINT8, u8, UINT8_MAX, uint8_t)\ - X(LIBCOOPGAMMA_UINT16, u16, UINT16_MAX, uint16_t)\ - X(LIBCOOPGAMMA_UINT32, u32, UINT32_MAX, uint32_t)\ - X(LIBCOOPGAMMA_UINT64, u64, UINT64_MAX, uint64_t)\ - X(LIBCOOPGAMMA_FLOAT, f, ((float)1), float)\ - X(LIBCOOPGAMMA_DOUBLE, d, ((double)1), double) + X(LIBCOOPGAMMA_UINT8, u8, UINT8_MAX, uint8_t)\ + X(LIBCOOPGAMMA_UINT16, u16, UINT16_MAX, uint16_t)\ + X(LIBCOOPGAMMA_UINT32, u32, UINT32_MAX, uint32_t)\ + X(LIBCOOPGAMMA_UINT64, u64, UINT64_MAX, uint64_t)\ + X(LIBCOOPGAMMA_FLOAT, f, ((float)1), float)\ + X(LIBCOOPGAMMA_DOUBLE, d, ((double)1), double) @@ -55,54 +39,54 @@ */ typedef struct filter_update { - /** - * The filter to update - * - * `.filter.crtc`, `.filter.class`, and - * `.filter.priority` (unless `default_priority` - * is `NO_DEFAULT_PRIORITY`), `.filter.depth` - * are preconfigured, and `.filter.ramps` - * is preinitialised and preset to an - * identity ramp - */ - libcoopgamma_filter_t filter; - - /** - * The index of the CRTC - */ - size_t crtc; - - /** - * Has the update been synchronised? - */ - int synced; - - /** - * Did the update fail? - */ - int failed; - - /** - * Error description if `.failed` is true - */ - libcoopgamma_error_t error; - - /** - * If zero, the ramps in `.filter` shall - * neither be modified nor freed - */ - int master; - - /** - * 0-terminated list of elements in - * `.crtc_updates` which shares gamma - * ramps with this instance - * - * This will only be set if `.master` - * is true - */ - size_t* slaves; - + /** + * The filter to update + * + * `.filter.crtc`, `.filter.class`, and + * `.filter.priority` (unless `default_priority` + * is `NO_DEFAULT_PRIORITY`), `.filter.depth` + * are preconfigured, and `.filter.ramps` + * is preinitialised and preset to an + * identity ramp + */ + libcoopgamma_filter_t filter; + + /** + * The index of the CRTC + */ + size_t crtc; + + /** + * Has the update been synchronised? + */ + int synced; + + /** + * Did the update fail? + */ + int failed; + + /** + * Error description if `.failed` is true + */ + libcoopgamma_error_t error; + + /** + * If zero, the ramps in `.filter` shall + * neither be modified nor freed + */ + int master; + + /** + * 0-terminated list of elements in + * `.crtc_updates` which shares gamma + * ramps with this instance + * + * This will only be set if `.master` + * is true + */ + size_t *slaves; + } filter_update_t; @@ -110,7 +94,7 @@ typedef struct filter_update /** * The process's name */ -extern const char* argv0; +extern const char *argv0; /** * The libcoopgamma context @@ -120,18 +104,18 @@ extern libcoopgamma_context_t cg; /** * The names of the selected CRTC:s */ -extern char** crtcs; +extern char **crtcs; /** * Gamma ramp updates for each CRTC */ -extern filter_update_t* crtc_updates; +extern filter_update_t *crtc_updates; /** * CRTC and monitor information about * each selected CRTC and connect monitor */ -extern libcoopgamma_crtc_info_t* crtc_info; +extern libcoopgamma_crtc_info_t *crtc_info; /** * The number of selected CRTC:s @@ -158,7 +142,7 @@ extern char default_class[]; /** * Class suffixes */ -extern const char* const* class_suffixes; +extern const char *const *class_suffixes; @@ -226,7 +210,7 @@ extern void usage(void); #if defined(__GNUC__) __attribute__((__nonnull__(1))) #endif -extern int handle_opt(char* opt, char* arg); +extern int handle_opt(char *opt, char *arg); /** * This function is called after the last @@ -240,7 +224,7 @@ extern int handle_opt(char* opt, char* arg); #if defined(__GNUC__) __attribute__((__nonnull__(2))) #endif -extern int handle_args(int argc, char* argv[], char* prio); +extern int handle_args(int argc, char *argv[], char *prio); /** * The main function for the program-specific code @@ -251,4 +235,3 @@ extern int handle_args(int argc, char* argv[], char* prio); * -3: Error, message already printed */ extern int start(void); - |