sct

set color temperature
git clone anongit@rnpnr.xyz:sct.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 9387d1d4e2255287f58c9379a0379b703fc53635
Parent: c7e708c311d09e51986dcf07b9125084ccfe6145
Author: Randy Palamar
Date:   Sun,  2 Apr 2023 19:03:31 -0600

cleanup flag handling

Diffstat:
Aarg.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Mssct.1 | 33+++++++++++++++------------------
Mssct.c | 234++++++++++++++++++++++++++++++++++++--------------------------------------------
Mssct.h | 47++++++++++++++++++-----------------------------
4 files changed, 188 insertions(+), 176 deletions(-)

diff --git a/arg.h b/arg.h @@ -0,0 +1,50 @@ +/* + * 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;\ + }\ + int i_;\ + for (i_ = 1, brk_ = 0, argv_ = argv;\ + argv[0][i_] && !brk_;\ + i_++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][i_];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/ssct.1 b/ssct.1 @@ -1,45 +1,42 @@ -.TH xsct 1 "Dec 2022" "1.9" "User Manual" +.TH SSCT 1 ssct\-VERSION .SH NAME -xsct \- X11 set screen color temperature +ssct \- set screen color temperature (X11) .SH SYNOPSIS -.B xsct -[options] -.I [temperature] -.I [brightness] +.B ssct +.RB [options] +.RB [temperature] +.RB [brightness] .SH DESCRIPTION -.B xsct +.B ssct sets the screen's color temperature. .SH OPTIONS .TP -.B -h, --help -Display usage information and exit +.B -v +verbose output. .TP -.B -v, --verbose -Display debugging information -.TP -.B -d, --delta +.B -d Shift temperature by temperature value .TP -.B -s, --screen N +.B -s N Zero-based index of screen to use. .TP -.B -c, --crtc N +.B -c N Zero-based index of CRTC to use. .TP -.I [temperature] +.BI [temperature] Black body temperature .br If the value is 0, xsct sets the color temperature to the default of 6500 .br If no arguments are passed, xsct estimates the current display temperature and brightness .TP -.I [brightness] +.BI [brightness] Linear brightness between 0.0 (inclusive) and 1.0 (inclusive). The default value is 1.0 if no parameter is passed. .SH AUTHOR -xsct is based on sct by Ted Unangst <tedu@openbsd.org> +ssct is based on sct by Ted Unangst <tedu@openbsd.org> .SH SEE ALSO redshift(1), xtemp(1) diff --git a/ssct.c b/ssct.c @@ -3,28 +3,31 @@ * * Public domain, do as you wish. */ +#include <stdarg.h> +#include "arg.h" #include "ssct.h" +static Display *dpy; +static int vflag; +char *argv0; + +static void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + static void -usage(char *pname) +usage(void) { - printf("Xsct (%s)\n" - "Usage: %s [options] [temperature] [brightness]\n" - "\tIf the argument is 0, xsct resets the display to the default " - "temperature (6500K)\n" - "\tIf no arguments are passed, xsct estimates the current " - "display temperature and brightness\n" - "Options:\n" - "\t-h, --help \t xsct will display this usage information\n" - "\t-v, --verbose \t xsct will display debugging information\n" - "\t-d, --delta\t xsct will shift temperature by the temperature " - "value\n" - "\t-s, --screen N\t xsct will only select screen specified by " - "given zero-based index\n" - "\t-c, --crtc N\t xsct will only select CRTC specified by given " - "zero-based index\n", - XSCT_VERSION, pname); + die("usage: %s [-vd] [-c CRTC] [-s screen] [temperature] " + "[brightness]\n", argv0); } static double @@ -35,7 +38,7 @@ DoubleTrim(double x, double a, double b) } static struct temp_status -get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug) +get_sct_for_screen(int screen, int icrtc) { Window root = RootWindow(dpy, screen); XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); @@ -75,7 +78,7 @@ get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug) temp.brightness /= n; temp.brightness /= BRIGHTHESS_DIV; temp.brightness = DoubleTrim(temp.brightness, 0.0, 1.0); - if (fdebug > 0) + if (vflag) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f, brightness: %f\n", gammar, gammag, gammab, temp.brightness); @@ -107,8 +110,7 @@ get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug) } static void -sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, - int fdebug) +sct_for_screen(int screen, int icrtc, struct temp_status temp) { double t = 0.0, b = 1.0, g = 0.0, gammar, gammag, gammab; int n, c; @@ -135,7 +137,7 @@ sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, gammag = DoubleTrim(GAMMA_K0GB + GAMMA_K1GB * g, 0.0, 1.0); gammab = 1.0; } - if (fdebug > 0) + if (vflag) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f, brightness: %f\n", gammar, gammag, gammab, b); n = res->ncrtc; @@ -172,128 +174,102 @@ sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, int main(int argc, char **argv) { - int i, screen, screens; + int screen, screens; int screen_specified, screen_first, screen_last, crtc_specified; - struct temp_status temp; - int fdebug = 0, fdelta = 0, fhelp = 0; - Display *dpy = XOpenDisplay(NULL); + struct temp_status temp = { .temp = DELTA_MIN, .brightness = -1.0 }; + int dflag = 0; + + argv0 = argv[0]; - if (!dpy) { - perror("XOpenDisplay(NULL) failed"); - fprintf(stderr, "ERROR! Ensure DISPLAY is set correctly!\n"); - return EXIT_FAILURE; + ARGBEGIN { + case 'd': + dflag = 1; + break; + case 'v': + vflag = 1; + break; + case 's': + screen_specified = atoi(EARGF(usage())); + break; + case 'c': + crtc_specified = atoi(EARGF(usage())); + break; + default: + usage(); + break; + } ARGEND; + + switch (argc) { + case 2: + temp.brightness = atof(argv[1]); + /* FALLTHROUGH */ + case 1: + temp.temp = atoi(argv[0]); + /* FALLTHROUGH */ + default: + break; } + + if (!(dpy = XOpenDisplay(NULL))) + die("XOpenDisplay: can't open display\n"); + screens = XScreenCount(dpy); screen_first = 0; screen_last = screens - 1; screen_specified = -1; crtc_specified = -1; - temp.temp = DELTA_MIN; - temp.brightness = -1.0; - for (i = 1; i < argc; i++) { - if ((strcmp(argv[i], "-h") == 0) - || (strcmp(argv[i], "--help") == 0)) - fhelp = 1; - else if ((strcmp(argv[i], "-v") == 0) - || (strcmp(argv[i], "--verbose") == 0)) - fdebug = 1; - else if ((strcmp(argv[i], "-d") == 0) - || (strcmp(argv[i], "--delta") == 0)) - fdelta = 1; - else if ((strcmp(argv[i], "-s") == 0) - || (strcmp(argv[i], "--screen") == 0)) { - i++; - if (i < argc) { - screen_specified = atoi(argv[i]); - } else { - fprintf(stderr, "ERROR! Required value for " - "screen not specified!\n"); - fhelp = 1; - } - } else if ((strcmp(argv[i], "-c") == 0) - || (strcmp(argv[i], "--crtc") == 0)) { - i++; - if (i < argc) { - crtc_specified = atoi(argv[i]); - } else { - fprintf(stderr, "ERROR! Required value for " - "crtc not specified!\n"); - fhelp = 1; - } - } else if (temp.temp == DELTA_MIN) - temp.temp = atoi(argv[i]); - else if (temp.brightness < 0.0) - temp.brightness = atof(argv[i]); - else { - fprintf(stderr, "ERROR! Unknown parameter: %s\n!", - argv[i]); - fhelp = 1; - } - } - if (fhelp > 0) { - usage(argv[0]); - } else if (screen_specified >= screens) { - fprintf(stderr, "ERROR! Invalid screen index: %d!\n", - screen_specified); - } else { - if (temp.brightness < 0.0) - temp.brightness = 1.0; - if (screen_specified >= 0) { - screen_first = screen_specified; - screen_last = screen_specified; + if (screen_specified >= screens) { + XCloseDisplay(dpy); + die("Invalid screen: %d\n", screen_specified); + } + if (temp.brightness < 0.0) + temp.brightness = 1.0; + if (screen_specified >= 0) { + screen_first = screen_specified; + screen_last = screen_specified; + } + if ((temp.temp < 0) && !dflag) { + // No arguments, so print estimated temperature for each + // screen + for (screen = screen_first; screen <= screen_last; screen++) { + temp = get_sct_for_screen(screen, crtc_specified); + printf("Screen %d: temperature ~ %d %f\n", screen, + temp.temp, temp.brightness); } - if ((temp.temp < 0) && (fdelta == 0)) { - // No arguments, so print estimated temperature for each - // screen - for (screen = screen_first; screen <= screen_last; - screen++) { - temp = get_sct_for_screen( - dpy, screen, crtc_specified, fdebug); - printf("Screen %d: temperature ~ %d %f\n", - screen, temp.temp, temp.brightness); + } else { + if (!dflag) { + // Set temperature to given value or default for + // a value of 0 + if (temp.temp == 0) { + temp.temp = TEMPERATURE_NORM; + } else if (temp.temp < TEMPERATURE_ZERO) { + fprintf(stderr, + "WARNING! Temperatures below " + "%d cannot be displayed.\n", + TEMPERATURE_ZERO); + temp.temp = TEMPERATURE_ZERO; } + for (screen = screen_first; screen <= screen_last; + screen++) + sct_for_screen(screen, crtc_specified, temp); } else { - if (fdelta == 0) { - // Set temperature to given value or default for - // a value of 0 - if (temp.temp == 0) { - temp.temp = TEMPERATURE_NORM; - } else if (temp.temp < TEMPERATURE_ZERO) { + // Delta mode: Shift temperature of each screen + // by given value + for (screen = screen_first; screen <= screen_last; + screen++) { + struct temp_status tempd = get_sct_for_screen( + screen, crtc_specified); + tempd.temp += temp.temp; + if (tempd.temp < TEMPERATURE_ZERO) { fprintf(stderr, - "WARNING! Temperatures below " - "%d cannot be displayed.\n", + "WARNING! Temperatures " + "below %d cannot be " + "displayed.\n", TEMPERATURE_ZERO); - temp.temp = TEMPERATURE_ZERO; - } - for (screen = screen_first; - screen <= screen_last; screen++) { - sct_for_screen(dpy, screen, - crtc_specified, temp, - fdebug); - } - } else { - // Delta mode: Shift temperature of each screen - // by given value - for (screen = screen_first; - screen <= screen_last; screen++) { - struct temp_status tempd = - get_sct_for_screen(dpy, screen, - crtc_specified, - fdebug); - tempd.temp += temp.temp; - if (tempd.temp < TEMPERATURE_ZERO) { - fprintf(stderr, - "WARNING! Temperatures " - "below %d cannot be " - "displayed.\n", - TEMPERATURE_ZERO); - tempd.temp = TEMPERATURE_ZERO; - } - sct_for_screen(dpy, screen, - crtc_specified, tempd, - fdebug); + tempd.temp = TEMPERATURE_ZERO; } + sct_for_screen(screen, crtc_specified, tempd); } } } diff --git a/ssct.h b/ssct.h @@ -9,49 +9,38 @@ #include <X11/Xproto.h> #include <X11/extensions/Xrandr.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> - -#ifndef __XSCT_H -#define __XSCT_H #define XSCT_VERSION "1.9" -#define TEMPERATURE_NORM 6500 -#define TEMPERATURE_ZERO 700 -#define GAMMA_MULT 65535.0 +#define TEMPERATURE_NORM 6500 +#define TEMPERATURE_ZERO 700 +#define GAMMA_MULT 65535.0 // Approximation of the `redshift` table from // https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273 // without limits: // GAMMA = K0 + K1 * ln(T - T0) // Red range (T0 = TEMPERATURE_ZERO) // Green color -#define GAMMA_K0GR -1.47751309139817 -#define GAMMA_K1GR 0.28590164772055 +#define GAMMA_K0GR -1.47751309139817 +#define GAMMA_K1GR 0.28590164772055 // Blue color -#define GAMMA_K0BR -4.38321650114872 -#define GAMMA_K1BR 0.6212158769447 +#define GAMMA_K0BR -4.38321650114872 +#define GAMMA_K1BR 0.6212158769447 // Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO) // Red color -#define GAMMA_K0RB 1.75390204039018 -#define GAMMA_K1RB -0.1150805671482 +#define GAMMA_K0RB 1.75390204039018 +#define GAMMA_K1RB -0.1150805671482 // Green color -#define GAMMA_K0GB 1.49221604915144 -#define GAMMA_K1GB -0.07513509588921 -#define BRIGHTHESS_DIV 65470.988 -#define DELTA_MIN -1000000 - -struct temp_status -{ - int temp; - double brightness; +#define GAMMA_K0GB 1.49221604915144 +#define GAMMA_K1GB -0.07513509588921 +#define BRIGHTHESS_DIV 65470.988 +#define DELTA_MIN -1000000 + +struct temp_status { + int temp; + double brightness; }; - -static void usage(char * pname); -static double DoubleTrim(double x, double a, double b); -static struct temp_status get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug); -static void sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, int fdebug); - -#endif /* __XSCT_H */