ctemp

Set color temperature
git clone git://git.akobets.xyz/ctemp
Log | Files | Refs | README | LICENSE

commit 4d4dfb362883b3ce1284224046aadab4603243c2
parent 54fb5cec01bba5ff251aba19363a293c20c328b3
Author: Artem Kobets <artem@akobets.xyz>
Date:   Wed,  4 Mar 2020 19:01:04 +0200

refactor: put all interfaces in ctemp.c

Diffstat:
MMakefile | 5+----
Mcolors.c | 4+---
Mctemp.c | 275+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Dctemp.h | 24------------------------
Dif-drm.c | 89-------------------------------------------------------------------------------
Dif-quartz.c | 79-------------------------------------------------------------------------------
Dif-x.c | 61-------------------------------------------------------------
7 files changed, 245 insertions(+), 292 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,9 +2,6 @@ include config.mk SRC = \ colors.c \ - if-drm.c \ - if-quartz.c \ - if-x.c \ ctemp.c \ util.c OBJ = $(SRC:.c=.o) @@ -17,7 +14,7 @@ config.h: .c.o: $(CC) -o $@ -c $< $(CFLAGS) -$(OBJ): config.mk ctemp.h util.h +$(OBJ): config.mk util.h ctemp: config.h $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) diff --git a/colors.c b/colors.c @@ -1,10 +1,8 @@ -#include "ctemp.h" - /* Whitepoint values for temperatures at 100K intervals. These will be interpolated for the actual temperature. This table was originally provided by Ingo Thies, 2013, for Redshift */ -const WhitePoint whitepoints[] = { +const struct { float r; float g; float b; } whitepoints[] = { { 1.00000000, 0.18172716, 0.00000000, }, /* 1000K */ { 1.00000000, 0.25503671, 0.00000000, }, /* 1100K */ { 1.00000000, 0.30942099, 0.00000000, }, /* 1200K */ diff --git a/ctemp.c b/ctemp.c @@ -2,32 +2,255 @@ #error "No supported interface configured" #endif +#include <fcntl.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "arg.h" -#include "ctemp.h" #include "util.h" +#define LEN(x) (sizeof(x) / sizeof(x[0])) #define MAX_INTERFACE_STR_LEN 1024 -static void usage(const Interface **interfaces); +#define TEMP_MIN 1000 +#define TEMP_MAX 25000 +#define TEMP_INTERVAL 100 +#define TEMP_DEFAULT 6500 + +typedef struct { + char *name; + void (*handler)(int temp); +} Interface; + +#ifdef DRM_SUPPORT +static void drm_handler(int temp); +#endif +#ifdef QUARTZ_SUPPORT +static void quartz_handler(int temp); +#endif +#ifdef X_SUPPORT +static void x_handler(int temp); +#endif +static void usage(); + +Interface interfaces[] = { +#ifdef DRM_SUPPORT + { "drm", drm_handler }, +#endif +#ifdef QUARTZ_SUPPORT + { "quartz", quartz_handler }, +#endif +#ifdef X_SUPPORT + { "x", x_handler }, +#endif +}; #include "config.h" +extern const struct { float r; float g; float b; } whitepoints[]; char *argv0; +#ifdef DRM_SUPPORT +#include <xf86drm.h> +#include <xf86drmMode.h> + +#define MAX_DRM_NODE_LEN (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ + + sizeof(DRM_PRIMARY_MINOR_NAME) \ + + sizeof("15") /* highest possible node number */ \ + + 1) /* NULL-terminator */ + +static void +drm_handler(int temp) +{ + unsigned int i; + float ratio_red, ratio_green, ratio_blue; + char dev_name[MAX_DRM_NODE_LEN]; + int fd; + drmModeResPtr res; + uint16_t *colors, *red, *green, *blue; + int gamma_size, prev_gamma_size; + int n; + + i = (temp - TEMP_MIN) / TEMP_INTERVAL; + ratio_red = whitepoints[i].r; + ratio_green = whitepoints[i].g; + ratio_blue = whitepoints[i].b; + + /* open DRM device with minor number 0 */ + snprintf(dev_name, sizeof(dev_name), DRM_DEV_NAME, DRM_DIR_NAME, 0); + fd = open(dev_name, O_RDWR | O_CLOEXEC, 0); + if (fd < 0) + die("cannot open %s: %s\n", dev_name, strerror(errno)); + + res = drmModeGetResources(fd); + + colors = NULL; + prev_gamma_size = 0; + for (n = 0; n < res->count_crtcs; n++) { + uint32_t crtc_id; + drmModeCrtcPtr crtc; + int i; + + crtc_id = res->crtcs[n]; + crtc = drmModeGetCrtc(fd, crtc_id); + gamma_size = crtc->gamma_size; + + if (colors == NULL) { + colors = malloc(3 * gamma_size * sizeof(uint16_t)); + if (colors == NULL) + die("malloc: %s\n", strerror(errno)); + } else if (gamma_size > prev_gamma_size) { + colors = realloc(colors, 3 * gamma_size * sizeof(uint16_t)); + if (colors == NULL) + die("realloc: %s\n", strerror(errno)); + } + red = colors; + green = red + gamma_size; + blue = green + gamma_size; + + for (i = 0; i < gamma_size; i++) { + float r = 65535.0 * i / gamma_size; + red[i] = r * ratio_red; + green[i] = r * ratio_green; + blue[i] = r * ratio_blue; + } + drmModeCrtcSetGamma(fd, crtc_id, gamma_size, red, green, blue); + + prev_gamma_size = gamma_size; + } + + if (colors != NULL) + free(colors); +} +#endif /* DRM_SUPPORT */ + +#ifdef QUARTZ_SUPPORT +#include <CoreGraphics/CoreGraphics.h> + +static void +quartz_handler(int temp) +{ + unsigned int i; + float ratio_red, ratio_green, ratio_blue; + CGDirectDisplayID *displays; + uint32_t display_count, n; + float *colors, *red, *green, *blue; + uint32_t gamma_size, prev_gamma_size; + + i = (temp - TEMP_MIN) / TEMP_INTERVAL; + ratio_red = whitepoints[i].r; + ratio_green = whitepoints[i].g; + ratio_blue = whitepoints[i].b; + + CGGetOnlineDisplayList(0, NULL, &display_count); + displays = malloc(display_count * sizeof(CGDirectDisplayID)); + if (displays == NULL) + die("malloc: %s\n", strerror(errno)); + CGGetOnlineDisplayList(display_count, displays, &display_count); + + colors = NULL; + prev_gamma_size = 0; + for (n = 0; n < display_count; n++) { + CGDirectDisplayID display_id; + uint32_t i; + + display_id = displays[n]; + gamma_size = CGDisplayGammaTableCapacity(display_id); + + if (colors == NULL) { + colors = malloc(3 * gamma_size * sizeof(uint16_t)); + if (colors == NULL) + die("malloc: %s\n", strerror(errno)); + } else if (gamma_size > prev_gamma_size) { + colors = realloc(colors, 3 * gamma_size * sizeof(uint16_t)); + if (colors == NULL) + die("realloc: %s\n", strerror(errno)); + } + red = colors; + green = red + gamma_size; + blue = green + gamma_size; + + for (i = 0; i < gamma_size; i++) { + float r = (float) i / gamma_size; + red[i] = r * ratio_red; + green[i] = r * ratio_green; + blue[i] = r * ratio_blue; + } + CGSetDisplayTransferByTable(display_id, gamma_size, red, green, blue); + + prev_gamma_size = gamma_size; + } + + if (colors != NULL) + free(colors); + + /* OS X resets gamma settings on exit, so never quit */ + pause(); +} +#endif /* QUARTZ_SUPPORT */ + +#ifdef X_SUPPORT +#include <X11/Xlib.h> +#include <X11/extensions/Xrandr.h> + +static void +x_handler(int temp) +{ + unsigned int i; + float ratio_red, ratio_green, ratio_blue; + Display *dpy; + XRRScreenResources *res; + int n; + + i = (temp - TEMP_MIN) / TEMP_INTERVAL; + ratio_red = whitepoints[i].r; + ratio_green = whitepoints[i].g; + ratio_blue = whitepoints[i].b; + + dpy = XOpenDisplay(NULL); + if (dpy == NULL) + die("cannot open display\n"); + res = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); + + for (n = 0; n < res->ncrtc; n++) { + RRCrtc crtc_id; + int gamma_size, i; + XRRCrtcGamma *crtc_gamma; + + crtc_id = res->crtcs[n]; + gamma_size = XRRGetCrtcGammaSize(dpy, crtc_id); + crtc_gamma = XRRAllocGamma(gamma_size); + if (crtc_gamma == NULL) + die("XRandR alloc: %s\n", strerror(errno)); + + for (i = 0; i < gamma_size; i++) { + float r = 65535.0 * i / gamma_size; + crtc_gamma->red[i] = r * ratio_red; + crtc_gamma->green[i] = r * ratio_green; + crtc_gamma->blue[i] = r * ratio_blue; + } + XRRSetCrtcGamma(dpy, crtc_id, crtc_gamma); + + XFree(crtc_gamma); + } + + XCloseDisplay(dpy); +} +#endif /* X_SUPPORT */ + static void -usage(const Interface **interfaces) +usage() { char ifStr[MAX_INTERFACE_STR_LEN]; unsigned int i; ifStr[0] = '\0'; - for (i = 0; interfaces[i] != NULL; i++) { - strcat(ifStr, interfaces[i]->name); - if (interfaces[i + 1] != NULL) + for (i = 0; i < LEN(interfaces); i++) { + strcat(ifStr, interfaces[i].name); + if (i + 1 < LEN(interfaces)) strcat(ifStr, " "); } @@ -44,31 +267,19 @@ usage(const Interface **interfaces) int main(int argc, char **argv) { - const Interface *interfaces[] = { -#ifdef DRM_SUPPORT - drm_interface, -#endif -#ifdef QUARTZ_SUPPORT - quartz_interface, -#endif -#ifdef X_SUPPORT - x_interface, -#endif - NULL - }; - SetGammaFunc set_gamma; + void (*handler)(int temp); char *if_name; unsigned int i; int temp; - set_gamma = NULL; + handler = NULL; ARGBEGIN { case 'i': { - if_name = EARGF(usage(interfaces)); - for (i = 0; interfaces[i] != NULL; i++) { - if (strcmp(if_name, interfaces[i]->name) == 0) - set_gamma = interfaces[i]->set_gamma; + if_name = EARGF(usage()); + for (i = 0; i < LEN(interfaces); i++) { + if (strcmp(if_name, interfaces[i].name) == 0) + handler = interfaces[i].handler; } break; } @@ -76,20 +287,20 @@ main(int argc, char **argv) { puts("ctemp "VERSION); return 0; default: - usage(interfaces); + usage(); break; } ARGEND - if (set_gamma == NULL) { - for (i = 0; interfaces[i] != NULL; i++) { - if (strcmp(DEFAULT_INTERFACE, interfaces[i]->name) == 0) { - set_gamma = interfaces[i]->set_gamma; + if (handler == NULL) { + for (i = 0; i < LEN(interfaces); i++) { + if (strcmp(DEFAULT_INTERFACE, interfaces[i].name) == 0) { + handler = interfaces[i].handler; } } } - if (set_gamma == NULL) - usage(interfaces); + if (handler == NULL) + usage(); temp = 0; if (argc == 0) @@ -100,5 +311,5 @@ main(int argc, char **argv) { usage(interfaces); } - set_gamma(temp); + handler(temp); } diff --git a/ctemp.h b/ctemp.h @@ -1,24 +0,0 @@ -#define TEMP_MIN 1000 -#define TEMP_MAX 25000 -#define TEMP_INTERVAL 100 -#define TEMP_DEFAULT 6500 - -/* colors.c */ -typedef struct { - float r; - float g; - float b; -} WhitePoint; - -extern const WhitePoint whitepoints[]; - -/* interfaces */ -typedef void (*SetGammaFunc)(int temp); -typedef struct { - char *name; - SetGammaFunc set_gamma; -} Interface; - -extern const Interface *drm_interface; -extern const Interface *quartz_interface; -extern const Interface *x_interface; diff --git a/if-drm.c b/if-drm.c @@ -1,89 +0,0 @@ -#ifdef DRM_SUPPORT -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "util.h" - -#define MAX_DRM_NODE_LEN (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ - + sizeof(DRM_PRIMARY_MINOR_NAME) \ - + sizeof("15") /* highest possible node number */ \ - + 1) /* NULL-terminator */ -#endif /* DRM_SUPPORT */ - -#include "ctemp.h" - -static void drm_set_gamma(int temp); - -static const Interface drm_interface_ = { "drm", drm_set_gamma }; -const Interface *drm_interface = &drm_interface_; - -static void -drm_set_gamma(int temp) -{ -#ifdef DRM_SUPPORT - unsigned int i; - float ratio_red, ratio_green, ratio_blue; - char dev_name[MAX_DRM_NODE_LEN]; - int fd; - drmModeResPtr res; - uint16_t *colors, *red, *green, *blue; - int gamma_size, prev_gamma_size; - int n; - - i = (temp - TEMP_MIN) / TEMP_INTERVAL; - ratio_red = whitepoints[i].r; - ratio_green = whitepoints[i].g; - ratio_blue = whitepoints[i].b; - - /* open DRM device with minor number 0 */ - snprintf(dev_name, sizeof(dev_name), DRM_DEV_NAME, DRM_DIR_NAME, 0); - fd = open(dev_name, O_RDWR | O_CLOEXEC, 0); - if (fd < 0) - die("cannot open %s: %s\n", dev_name, strerror(errno)); - - res = drmModeGetResources(fd); - - colors = NULL; - prev_gamma_size = 0; - for (n = 0; n < res->count_crtcs; n++) { - uint32_t crtc_id; - drmModeCrtcPtr crtc; - int i; - - crtc_id = res->crtcs[n]; - crtc = drmModeGetCrtc(fd, crtc_id); - gamma_size = crtc->gamma_size; - - if (colors == NULL) { - colors = malloc(3 * gamma_size * sizeof(uint16_t)); - if (colors == NULL) - die("malloc: %s\n", strerror(errno)); - } else if (gamma_size > prev_gamma_size) { - colors = realloc(colors, 3 * gamma_size * sizeof(uint16_t)); - if (colors == NULL) - die("realloc: %s\n", strerror(errno)); - } - red = colors; - green = red + gamma_size; - blue = green + gamma_size; - - for (i = 0; i < gamma_size; i++) { - float r = 65535.0 * i / gamma_size; - red[i] = r * ratio_red; - green[i] = r * ratio_green; - blue[i] = r * ratio_blue; - } - drmModeCrtcSetGamma(fd, crtc_id, gamma_size, red, green, blue); - - prev_gamma_size = gamma_size; - } - - if (colors != NULL) - free(colors); -#endif /* DRM_SUPPORT */ -} diff --git a/if-quartz.c b/if-quartz.c @@ -1,79 +0,0 @@ -#ifdef QUARTZ_SUPPORT -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <CoreGraphics/CoreGraphics.h> - -#include "util.h" -#endif /* QUARTZ_SUPPORT */ - -#include "ctemp.h" - -static void quartz_set_gamma(int temp); - -static const Interface quartz_interface_ = { "quartz", quartz_set_gamma }; -const Interface *quartz_interface = &quartz_interface_; - -static void -quartz_set_gamma(int temp) -{ -#ifdef QUARTZ_SUPPORT - unsigned int i; - float ratio_red, ratio_green, ratio_blue; - CGDirectDisplayID *displays; - uint32_t display_count, n; - float *colors, *red, *green, *blue; - uint32_t gamma_size, prev_gamma_size; - - i = (temp - TEMP_MIN) / TEMP_INTERVAL; - ratio_red = whitepoints[i].r; - ratio_green = whitepoints[i].g; - ratio_blue = whitepoints[i].b; - - CGGetOnlineDisplayList(0, NULL, &display_count); - displays = malloc(display_count * sizeof(CGDirectDisplayID)); - if (displays == NULL) - die("malloc: %s\n", strerror(errno)); - CGGetOnlineDisplayList(display_count, displays, &display_count); - - colors = NULL; - prev_gamma_size = 0; - for (n = 0; n < display_count; n++) { - CGDirectDisplayID display_id; - uint32_t i; - - display_id = displays[n]; - gamma_size = CGDisplayGammaTableCapacity(display_id); - - if (colors == NULL) { - colors = malloc(3 * gamma_size * sizeof(uint16_t)); - if (colors == NULL) - die("malloc: %s\n", strerror(errno)); - } else if (gamma_size > prev_gamma_size) { - colors = realloc(colors, 3 * gamma_size * sizeof(uint16_t)); - if (colors == NULL) - die("realloc: %s\n", strerror(errno)); - } - red = colors; - green = red + gamma_size; - blue = green + gamma_size; - - for (i = 0; i < gamma_size; i++) { - float r = (float) i / gamma_size; - red[i] = r * ratio_red; - green[i] = r * ratio_green; - blue[i] = r * ratio_blue; - } - CGSetDisplayTransferByTable(display_id, gamma_size, red, green, blue); - - prev_gamma_size = gamma_size; - } - - if (colors != NULL) - free(colors); - - /* OS X resets gamma settings on exit, so never quit */ - pause(); -#endif /* QUARTZ_SUPPORT */ -} diff --git a/if-x.c b/if-x.c @@ -1,61 +0,0 @@ -#ifdef X_SUPPORT -#include <errno.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/extensions/Xrandr.h> - -#include "util.h" -#endif /* X_SUPPORT */ - -#include "ctemp.h" - -static void x_set_gamma(int temp); - -static const Interface x_interface_ = { "x", x_set_gamma }; -const Interface *x_interface = &x_interface_; - -static void -x_set_gamma(int temp) -{ -#ifdef X_SUPPORT - unsigned int i; - float ratio_red, ratio_green, ratio_blue; - Display *dpy; - XRRScreenResources *res; - int n; - - i = (temp - TEMP_MIN) / TEMP_INTERVAL; - ratio_red = whitepoints[i].r; - ratio_green = whitepoints[i].g; - ratio_blue = whitepoints[i].b; - - dpy = XOpenDisplay(NULL); - if (dpy == NULL) - die("cannot open display\n"); - res = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); - - for (n = 0; n < res->ncrtc; n++) { - RRCrtc crtc_id; - int gamma_size, i; - XRRCrtcGamma *crtc_gamma; - - crtc_id = res->crtcs[n]; - gamma_size = XRRGetCrtcGammaSize(dpy, crtc_id); - crtc_gamma = XRRAllocGamma(gamma_size); - if (crtc_gamma == NULL) - die("XRandR alloc: %s\n", strerror(errno)); - - for (i = 0; i < gamma_size; i++) { - float r = 65535.0 * i / gamma_size; - crtc_gamma->red[i] = r * ratio_red; - crtc_gamma->green[i] = r * ratio_green; - crtc_gamma->blue[i] = r * ratio_blue; - } - XRRSetCrtcGamma(dpy, crtc_id, crtc_gamma); - - XFree(crtc_gamma); - } - - XCloseDisplay(dpy); -#endif /* X_SUPPORT */ -}