/** * 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 . */ #define _DEFAULT_SOURCE #define _BSD_SOURCE #include "cg-base.h" #include #include #include #include #include #include #include /** * The process's name */ const char* argv0 = NULL; /** * The libcoopgamma context */ libcoopgamma_context_t cg; /** * The names of the selected CRTC:s */ char** crtcs = NULL; /** * CRTC and monitor information about * each selected CRTC and connect monitor */ libcoopgamma_crtc_info_t* crtc_info = NULL; /** * The number of selected CRTC:s */ size_t crtcs_n = 0; /** * Initialise the process, specifically * reset the signal mask and signal handlers * * @return Zero on success, -1 on error */ 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; } /** * Print, to stdout, a list of all * recognised adjustment methods * * @return Zero on success, -1 on error */ 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; } /** * Print, to stdout, a list of all CRTC:s * * A connection to the coopgamma server * must have been made * * @return Zero on success, -1 on error, -2 * on libcoopgamma error */ 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; } /** * Fill the list of CRTC information * * @return Zero on success, -1 on libcoopgamma error */ static int get_crtc_info(void) { /* TODO */ return 0; } /** * -m METHOD * Select adjustment method. If METHOD is "?", * available methods will be printed to stdout. * * -s SITE * Select site (display server instance). * * -c CRTC * Select CRT controller. If CRTC is "?", CRTC:s * will be printed to stdout. * * This option can be used multiple times. If it * is not used at all, all CRTC:s will be selected. * * @param argc The number of command line arguments * @param argv The command line arguments * @return 0 on success, 1 on error */ int main(int argc, char* argv[]) { int init_failed = 0; int stage = 0; int dealloc_crtcs = 0; int rc = 0; char* method = NULL; char* site = NULL; size_t crtcs_i = 0; 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; } opt[0] = *args++; opt[2] = '\0'; if ((*opt != '-') && (*opt != '+')) break; while (*args) { char* arg; int at_end; opt[1] = *args++; arg = args + 1; if ((at_end = !*arg)) arg = argv[1]; if (!strcmp(opt, "-m")) { if ((method = arg) == NULL) usage(); } else if (!strcmp(opt, "-s")) { if ((site = arg) == NULL) usage(); } else if (!strcmp(opt, "-c")) { if (arg == NULL) usage(); crtcs[crtcs_i++] = arg; } else switch (handle_opt(opt, arg)) { case 0: goto next_arg; case 1: break; default: goto fail; } argv += at_end; argc -= at_end; goto next_arg; } next_arg:; } crtcs_n = crtcs_i; crtcs[crtcs_i] = NULL; if (handle_args(argc, argv, method, site, crtcs) < 0) goto fail; if ((method != NULL) && !strcmp(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) { init_failed = (errno == 0); goto fail; } stage++; while (crtcs_i--) if (!strcmp(crtcs[crtcs_i], "?")) 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++); } crtc_info = calloc(crtcs_n + 1, sizeof(*crtc_info)); if (crtc_info == NULL) goto fail; for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) if (libcoopgamma_crtc_info_initialise(crtc_info + crtcs_i) < 0) goto cg_fail; if (get_crtc_info() < 0) goto cg_fail; /* TODO start */ done: if (dealloc_crtcs) free(crtcs); if (crtc_info != NULL) for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) libcoopgamma_crtc_info_destroy(crtc_info + crtcs_i); free(crtc_info); if (stage >= 1) libcoopgamma_context_destroy(&cg, stage >= 2); return rc; fail: rc = 1; if (init_failed) fprintf(stderr, "%s: server failed to initialise\n", argv0); else 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; }