aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-08-04 12:41:11 +0200
committerMattias Andrée <maandree@kth.se>2016-08-04 12:41:11 +0200
commit902aec84e577a2724e35fe00ac73302c2fcd9338 (patch)
tree85e495e848b744ca0ec9237a5bf6bfd3f523afaf
parentList CRTC:s (diff)
downloadcg-tools-902aec84e577a2724e35fe00ac73302c2fcd9338.tar.gz
cg-tools-902aec84e577a2724e35fe00ac73302c2fcd9338.tar.bz2
cg-tools-902aec84e577a2724e35fe00ac73302c2fcd9338.tar.xz
Work on cg-base
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--src/cg-base.c239
-rw-r--r--src/cg-base.h85
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);
+