aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arg.h65
-rw-r--r--src/cg-query.c346
2 files changed, 411 insertions, 0 deletions
diff --git a/src/arg.h b/src/arg.h
new file mode 100644
index 0000000..0b23c53
--- /dev/null
+++ b/src/arg.h
@@ -0,0 +1,65 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][0] == '-'\
+ && argv[0][1];\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+/* Handles obsolete -NUM syntax */
+#define ARGNUM case '0':\
+ case '1':\
+ case '2':\
+ case '3':\
+ case '4':\
+ case '5':\
+ case '6':\
+ case '7':\
+ case '8':\
+ case '9'
+
+#define ARGEND }\
+ }
+
+#define ARGC() argc_
+
+#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define LNGARG() &argv[0][0]
+
+#endif
diff --git a/src/cg-query.c b/src/cg-query.c
new file mode 100644
index 0000000..b43613c
--- /dev/null
+++ b/src/cg-query.c
@@ -0,0 +1,346 @@
+/**
+ * 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/>.
+ */
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+
+#include "arg.h"
+
+#include <libcoopgamma.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+/**
+ * The libcoopgamma context
+ */
+static libcoopgamma_context_t cg;
+
+/**
+ * The name of the selected CRTC
+ */
+static char* crtc = NULL;
+
+
+
+/**
+ * Print usage information and exit
+ */
+void usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-M method] [-S site] -c crtc\n",
+ argv0);
+ exit(1);
+}
+
+
+/**
+ * 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;
+}
+
+
+/**
+ * Print, to stdout, information about
+ * the selected CRTC
+ *
+ * @return Zero on success, -1 on error, -2
+ * on libcoopgamma error
+ */
+static int print_info(void)
+{
+ libcoopgamma_crtc_info_t info;
+ char* str;
+ int saved_errno;
+
+ libcoopgamma_crtc_info_initialise(&info);
+
+ if (libcoopgamma_get_gamma_info_sync(crtc, &info, &cg) < 0)
+ goto cg_fail;;
+
+ printf("Cooperative gamma server running: %s\n",
+ info.cooperative ? "yes" : "no");
+
+ printf("Gamma adjustments supported: %s\n",
+ info.supported == LIBCOOPGAMMA_MAYBE ? "maybe" : info.supported ? "yes" : "no");
+
+ printf("Gamma ramps stops (red green blue): %zu %zu %zu\n",
+ info.red_size, info.green_size, info.blue_size);
+
+ switch (info.depth)
+ {
+ case LIBCOOPGAMMA_DOUBLE: str = "double-precision floating-point"; break;
+ case LIBCOOPGAMMA_FLOAT: str = "single-precision floating-point"; break;
+ case LIBCOOPGAMMA_UINT8: str = "unsigned 8-bit integer"; break;
+ case LIBCOOPGAMMA_UINT16: str = "unsigned 16-bit integer"; break;
+ case LIBCOOPGAMMA_UINT32: str = "unsigned 32-bit integer"; break;
+ case LIBCOOPGAMMA_UINT64: str = "unsigned 64-bit integer"; break;
+ default:
+ errno = EPROTO;
+ goto fail;
+ }
+ printf("Gamma ramps stops value type: %s\n", str);
+
+ if (info.colourspace != LIBCOOPGAMMA_UNKNOWN)
+ {
+ switch (info.colourspace)
+ {
+ case LIBCOOPGAMMA_SRGB: str = "sRGB"; break;
+ case LIBCOOPGAMMA_RGB: str = "non-standard RGB"; break;
+ case LIBCOOPGAMMA_NON_RGB: str = "non-RGB multicolour"; break;
+ case LIBCOOPGAMMA_GREY: str = "monochrome or singlecolour scale"; break;
+ default:
+ errno = EPROTO;
+ goto fail;
+ }
+ printf("Monitor's colourspace: %s\n", str);
+ }
+
+ if (info.have_gamut)
+ {
+ printf("Monitor's red colour: %lf, %lf\n",
+ info.red_x / (double)1024, info.red_y / (double)1024);
+
+ printf("Monitor's green colour: %lf, %lf\n",
+ info.green_x / (double)1024, info.green_y / (double)1024);
+
+ printf("Monitor's blue colour: %lf, %lf\n",
+ info.blue_x / (double)1024, info.blue_y / (double)1024);
+ }
+
+ return 0;
+ fail:
+ saved_errno = errno;
+ libcoopgamma_crtc_info_destroy(&info);
+ errno = saved_errno;
+ return -1;
+ cg_fail:
+ saved_errno = errno;
+ libcoopgamma_crtc_info_destroy(&info);
+ errno = saved_errno;
+ return -2;
+}
+
+
+/**
+ * -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.
+ *
+ * @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 stage = 0;
+ int rc = 0;
+ char* method = NULL;
+ char* site = NULL;
+
+ ARGBEGIN
+ {
+ case 'M':
+ if (method != NULL)
+ usage();
+ method = EARGF(usage());
+ break;
+ case 'S':
+ if (site != NULL)
+ usage();
+ site = EARGF(usage());
+ break;
+ case 'c':
+ if (crtc != NULL)
+ usage();
+ crtc = EARGF(usage());
+ break;
+ }
+ ARGEND;
+
+ if (initialise_proc() < 0)
+ goto fail;
+
+ if ((method != NULL) && !strcmp(method, "?"))
+ {
+ if ((site != NULL) || (crtc != NULL))
+ usage();
+ 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 (!crtc)
+ usage();
+
+ if (!strcmp(crtc, "?"))
+ switch (list_crtcs())
+ {
+ case 0:
+ goto done;
+ case -1:
+ goto fail;
+ default:
+ goto cg_fail;
+ }
+
+ switch (print_info())
+ {
+ case 0:
+ goto done;
+ case -1:
+ goto fail;
+ default:
+ goto cg_fail;
+ }
+
+ fflush(stdout);
+ if (ferror(stdout))
+ goto fail;
+ if (fclose(stdout) < 0)
+ goto fail;
+
+ done:
+ if (stage >= 1)
+ libcoopgamma_context_destroy(&cg, stage >= 2);
+ return rc;
+
+ custom_fail:
+ rc = 1;
+ goto done;
+
+ fail:
+ rc = 1;
+ 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;
+}
+