x

Programs, configuration and documentation that don't fit anywhere else
Log | Files | Refs | README | LICENSE

sct.c (3617B)


      1 /*
      2  * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
      3  * Copyright (c) 2016-2020 Joerg Jung <jung@openbsd.org>
      4  *
      5  * Permission to use, copy, modify, and distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  */
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #include <err.h>
     21 #include <errno.h>
     22 #include <limits.h>
     23 #include <unistd.h>
     24 #include <X11/Xlib.h>
     25 #include <X11/Xproto.h>
     26 #include <X11/Xatom.h>
     27 #include <X11/extensions/Xrandr.h>
     28 
     29 #define S_V "0.5"
     30 #define S_YR "2015-2020"
     31 
     32 enum { S_RED, S_GREEN, S_BLUE, S_MAX };
     33 
     34 static const float s_wp[][S_MAX] = { /* whitepoint values from redshift */
     35     { 1.00000000, 0.18172716, 0.00000000 }, /* 1000K */
     36     { 1.00000000, 0.42322816, 0.00000000 },
     37     { 1.00000000, 0.54360078, 0.08679949 },
     38     { 1.00000000, 0.64373109, 0.28819679 },
     39     { 1.00000000, 0.71976951, 0.42860152 },
     40     { 1.00000000, 0.77987699, 0.54642268 },
     41     { 1.00000000, 0.82854786, 0.64816570 },
     42     { 1.00000000, 0.86860704, 0.73688797 },
     43     { 1.00000000, 0.90198230, 0.81465502 },
     44     { 1.00000000, 0.93853986, 0.88130458 },
     45     { 1.00000000, 0.97107439, 0.94305985 },
     46     { 1.00000000, 1.00000000, 1.00000000 }, /* 6500K */
     47     { 0.95160805, 0.96983355, 1.00000000 },
     48     { 0.91194747, 0.94470005, 1.00000000 },
     49     { 0.87906581, 0.92357340, 1.00000000 },
     50     { 0.85139976, 0.90559011, 1.00000000 },
     51     { 0.82782969, 0.89011714, 1.00000000 },
     52     { 0.80753191, 0.87667891, 1.00000000 },
     53     { 0.78988728, 0.86491137, 1.00000000 }, /* 10000K */
     54     { 0.77442176, 0.85453121, 1.00000000 } };
     55 
     56 static double s_avg(int t, double r, int c) {
     57     return s_wp[t / 500][c] * (1 - r) + s_wp[t / 500 + 1][c] * r;
     58 }
     59 
     60 static void s_run(const char *s) {
     61     Display *d;
     62     XRRScreenResources *sr = NULL;
     63     XRRCrtcGamma *cg;
     64     unsigned long t;
     65     double r, g;
     66     int i, j, sz;
     67     char *e;
     68 
     69     errno = 0, t = strtoul(s, &e, 10);
     70     if (s[0] == '\0' || *e != '\0' || (errno == ERANGE && t == ULONG_MAX))
     71         errx(1, "temp failed");
     72     if (t < 1000 || t > 10000)
     73         t = 6500, warnx("temp range");
     74     t -= 1000, r = t % 500 / 500.0;
     75     if (!(d = XOpenDisplay(NULL)) || !(sr = XRRGetScreenResourcesCurrent(d,
     76         RootWindow(d, DefaultScreen(d)))))
     77         err(1, "XOpenDisplay or XRRGetScreenResourcesCurrent failed");
     78     for (i = 0; i < sr->ncrtc; i++) {
     79         sz = XRRGetCrtcGammaSize(d, sr->crtcs[i]);
     80         if (!(cg = XRRAllocGamma(sz)))
     81             err(1, "XRRAllocGamma failed");
     82         for (j = 0; j < sz; j++) {
     83             g = 65535.0 * j / sz;
     84             cg->red[j] = g * s_avg(t, r, S_RED);
     85             cg->green[j] = g * s_avg(t, r, S_GREEN);
     86             cg->blue[j] = g * s_avg(t, r, S_BLUE);
     87         }
     88         XRRSetCrtcGamma(d, sr->crtcs[i], cg);
     89         XFree(cg);
     90     }
     91     printf("%luK\n", t + 1000);
     92     XFree(sr), XCloseDisplay(d);
     93 }
     94 
     95 int main(int argc, char *argv[]) {
     96     if (argc > 2)
     97         errx(1, "usage: sct [<temp>]\n%12ssct version", "");
     98     s_run((argc == 2) ? argv[1] : "6500");
     99     return 0;
    100 }