diff options
-rw-r--r-- | src/cg-base.c | 239 | ||||
-rw-r--r-- | src/cg-base.h | 85 |
2 files changed, 309 insertions, 15 deletions
diff --git a/src/cg-base.c b/src/cg-base.c index 18f782e..95ded72 100644 --- a/src/cg-base.c +++ b/src/cg-base.c @@ -18,18 +18,52 @@ #define _DEFAULT_SOURCE #define _BSD_SOURCE -#include <libcoopgamma.h> +#include "cg-base.h" +#include <alloca.h> #include <errno.h> +#include <inttypes.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> -const char* argv0; + +/** + * 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; @@ -49,6 +83,12 @@ static int initialise_proc(void) } +/** + * Print, to stdout, a list of all + * recognised adjustment methods + * + * @return Zero on success, -1 on error + */ static int list_methods(void) { char** list; @@ -67,14 +107,23 @@ static int list_methods(void) } -static int list_crtcs(libcoopgamma_context_t* restrict cg) +/** + * 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); + list = libcoopgamma_get_crtcs_sync(&cg); if (list == NULL) - return -1; + return -2; for (i = 0; list[i]; i++) printf("%s\n", list[i]); free(list); @@ -85,41 +134,201 @@ static int list_crtcs(libcoopgamma_context_t* restrict cg) } +/** + * 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[]) { - libcoopgamma_context_t cg; 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[0]; + argv0 = *argv++, argc--; if (initialise_proc() < 0) goto fail; - if (list_methods() < 0) + 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(NULL, NULL, &cg) < 0) + if (libcoopgamma_connect(method, site, &cg) < 0) { init_failed = (errno == 0); goto fail; } stage++; - if (list_crtcs(&cg) < 0) + 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; - libcoopgamma_context_destroy(&cg, 1); - return 0; fail: + rc = 1; if (init_failed) fprintf(stderr, "%s: server failed to initialise\n", argv0); else perror(argv0); - if (stage >= 1) - libcoopgamma_context_destroy(&cg, stage >= 2); - return 1; + 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; } diff --git a/src/cg-base.h b/src/cg-base.h new file mode 100644 index 0000000..74b5550 --- /dev/null +++ b/src/cg-base.h @@ -0,0 +1,85 @@ +/** + * 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/>. + */ +#include <libcoopgamma.h> + + + +/** + * The process's name + */ +extern const char* argv0; + +/** + * The libcoopgamma context + */ +extern libcoopgamma_context_t cg; + +/** + * The names of the selected CRTC:s + */ +extern char** crtcs; + +/** + * CRTC and monitor information about + * each selected CRTC and connect monitor + */ +extern libcoopgamma_crtc_info_t* crtc_info; + +/** + * The number of selected CRTC:s + */ +extern size_t crtcs_n; + + +/** + * Print usage information and exit + */ +#if defined(__GNUC__) +__attribute__((__noreturn__)) +#endif +extern void usage(void); + +/** + * Handle a command line option + * + * @param opt The option, it is a NUL-terminate two-character + * string starting with either '-' or '+', if the + * argument is not recognised, call `usage`. This + * string will not be "-m", "-s", or "-c". + * @param arg The argument associated with `opt`, + * `NULL` there is no next argument, if this + * parameter is `NULL` but needed, call `usage` + * @return 0 if `arg` was not used, + * 1 if `arg` was used, + * -1 on error + */ +extern int handle_opt(char* opt, char* arg); + +/** + * This function is called after the last + * call to `handle_opt` + * + * @param argc The number of unparsed arguments + * @param argv `NULL` terminated list of unparsed arguments + * @param method The argument associated with the "-m" option + * @param site The argument associated with the "-s" option + * @param crtcs The arguments associated with the "-c" options, `NULL`-terminated + * @return Zero on success, -1 on error + */ +extern int handle_args(int argc, char* argv[], char* method, char* site, char** crtcs); + |