summaryrefslogtreecommitdiff
path: root/src/main.c
blob: 196914ba3aa9e249ae38dfe7cd2702cfc8f1351c (plain)
    1 /**
    2  * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io>
    3  *
    4  * Luminous is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 3 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * Luminous is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with noteless.  If not, see <http://www.gnu.org/licenses/>.
   16  */
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 #include <string.h>
   20 #include <time.h>
   21 #include <errno.h>
   22 
   23 #include "config.h"
   24 
   25 #define CONF "/etc/luminous.conf"
   26 
   27 
   28 struct props {
   29   int lvl;  // Destination brightness
   30   int step; // Step size
   31   int rate; // Time in milliseconds between steps
   32   int max;  // Maximum brightness of screen device
   33   int cur;  // Current brightness prior to fade operation
   34   char filebrightness[512]; // Path to the sysfs ent for brightness
   35   char filemax_bright[512]; // Path to the sysfs ent for max brightness
   36 };
   37 
   38 
   39 void props_new(struct props* p) {
   40   p->lvl  = -1;
   41   p->step = -1;
   42   p->rate = -1;
   43   p->max  = -1;
   44   p->cur  = -1;
   45   p->filebrightness[0] = '\0';
   46   p->filemax_bright[0] = '\0';
   47 }
   48 
   49 
   50 /**
   51  * fgeti:
   52  * @path Path to the file from which to read the integer
   53  *
   54  * Reads integer from the specified file. If the file does not contain only an
   55  * integer, returns -1.
   56  *
   57  * returns: Integer read from file, otherwise -1.
   58  */
   59 int fgeti(char* path) {
   60   FILE* fd;
   61   char buf[64];
   62 
   63   fd = fopen(path, "r");
   64   if(! fd)
   65     return -1;
   66 
   67   fgets(buf, 64, fd);
   68   fclose(fd);
   69   return atoi(buf);
   70 }
   71 
   72 
   73 /**
   74  * fade:
   75  * @props Props struct containing runtime parameters
   76  *
   77  * Fades brightness up or down, based on positive (fade up) or negative value
   78  * (fade down) contained in `step` property. Rate of fade is controled by
   79  * `props->rate`.
   80  *
   81  * returns: Success (0) or failure (-1)
   82  */
   83 int fade(struct props* props) {
   84   struct timespec tim, tim2;
   85   int sec;  // Number of seconds to sleep
   86   int msec; // Number of milliseconds to sleep (less than 1 second)
   87   int direction = 0; // Direction of fade. Positive for up, negative for down
   88   int opcount   = 0;
   89 
   90   sec = props->rate / 1000;
   91   msec = props->rate - (sec * 1000);
   92 
   93   tim.tv_sec = sec;
   94   tim.tv_nsec = 1000000 * msec;
   95 
   96   // Determine direction
   97   if(props->lvl > props->cur) {
   98     // Dest brightness is higher than current
   99     direction = 1;
  100     opcount = (props->lvl - props->cur) / props->step;
  101   } else if(props->lvl < props->cur) {
  102     // Dest brightness is lower than current
  103     direction = -1;
  104     opcount = (props->cur - props->lvl) / props->step;
  105   }
  106 
  107   FILE* fd = fopen(props->filebrightness, "w");
  108   if(! fd) {
  109     if(errno == EACCES) {
  110       fprintf(stderr, "Permission denied: %s\n", props->filebrightness);
  111     } else {
  112       fprintf(stderr, "Could not open file %s\n", props->filebrightness);
  113     }
  114     return -1;
  115   }
  116 
  117   while(opcount > 0) {
  118     nanosleep(&tim, &tim2);
  119 
  120     // Write the new brightness to the brightness file
  121     fprintf(fd, "%d\n", props->cur);
  122 
  123     // Flush the toil...er...buffer!
  124     fflush(fd);
  125 
  126     props->cur += props->step * direction;
  127     opcount--;
  128   }
  129 
  130   fclose(fd);
  131   return 0;
  132 }
  133 
  134 
  135 /**
  136  * usage:
  137  *
  138  * Nothing to see here. Just the help text printer.
  139  */
  140 void usage() {
  141   printf(
  142 "Luminous is a backlight manager that supports fading the backlight at\n"
  143 "varying rates and steps. It manages backlight via the kenerl interfaces\n"
  144 "provided in /sys to adjust screen backlight levels. Consequently, it\n"
  145 "requires write access to the brightness property in \n"
  146 "/sys/class/backlight/<device>/brightness.\n"
  147 "\n"
  148 "Usage:\n"
  149 "  luminous --rate 10 --step 8 --level [+-]400\n"
  150 "\n"
  151 "Arguments:\n"
  152 "  -h,--help  Print this helptext\n"
  153 "  -s,--step  Fade step (default: 6)\n"
  154 "  -r,--rate  Time in milliseconds between fade steps (default: 10)\n"
  155 "  -l,--level Brightness level to change to. Supports absolute values and\n"
  156 "             relative values prefixed with + and -."
  157 "\n\n"
  158 );
  159 }
  160 
  161 
  162 /**
  163  * parseargs:
  164  * @out   Output properties struct
  165  * @argc  Number of arguments passed
  166  * @argv  Arguments char array
  167  *
  168  * Parses command line arguments into a props struct.
  169  *
  170  * returns: Success (0), failure (-1), or incomplete (-2)
  171  */
  172 int parseargs(struct props* out, int argc, char* argv[]) {
  173   int i;
  174   
  175   strcpy(out->filebrightness,
  176          "/sys/class/backlight/intel_backlight/brightness");
  177   strcpy(out->filemax_bright,
  178          "/sys/class/backlight/intel_backlight/max_brightness");
  179 
  180   // Read the system values for current and maximum brightness
  181   out->cur = fgeti(out->filebrightness);
  182   out->max = fgeti(out->filemax_bright);
  183 
  184   for(i = 0; i < argc; i++) {
  185     if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) {
  186       i++;
  187       out->rate = atoi(argv[i]);
  188     } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--step") == 0) {
  189       i++;
  190       out->step = atoi(argv[i]);
  191     } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--level") == 0) {
  192       i++;
  193       // Account for relative and absolute increments and decrements
  194       if(argv[i][0] == '+') {
  195         out->lvl = out->cur + atoi(&argv[i][1]);
  196       } else if(argv[i][0] == '-') {
  197         out->lvl = out->cur - atoi(&argv[i][1]);
  198       } else {
  199         out->lvl = atoi(argv[i]);
  200       }
  201     } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
  202       usage();
  203       return -2;
  204     }
  205   }
  206 
  207   // Some defaults, if no values are set yet
  208   if(out->rate < 0)
  209    out->rate = 20;
  210   if(out->step < 0)
  211    out->step = 12;
  212   if(out->lvl == -1)
  213     out->lvl = 200;
  214 
  215   // Ensure min and max thresholds are respected
  216   if(out->lvl > out->max) {
  217     out->lvl = out->max;
  218   } else if(out->lvl < 0) {
  219     out->lvl = 0;
  220   }
  221   return 0;
  222 }
  223 
  224 
  225 int config_to_props(char* confpath, struct props* p) {
  226   struct config c;
  227   char lvlbuf[32];  // Buffer to store config value for "level" if found
  228   char ratebuf[32]; // Buffer to store config value for "rate" if found
  229   char stepbuf[32]; // Buffer to store config value for "step" if found
  230 
  231   if(config_new(&c, confpath) == 0) {
  232     config_load(&c);
  233   } else {
  234     // Config file not found, return -2 code
  235     return -2;
  236   }
  237 
  238   // If the config specifies a "level" key, set it to the props object
  239   if(config_get(&c, "level", lvlbuf) == 0)
  240     p->lvl = atoi(lvlbuf);
  241 
  242   // If the config specifies a "step" key, set it to the props object
  243   if(config_get(&c, "step", stepbuf) == 0)
  244     p->step = atoi(stepbuf);
  245 
  246   // If the config specifies a "rate" key, set it to the props object
  247   if(config_get(&c, "rate", ratebuf) == 0)
  248     p->rate = atoi(ratebuf);
  249 
  250   // Don't forget to clean up!
  251   config_free(&c);
  252 
  253   return 0;
  254 }
  255 
  256 
  257 /**
  258  * Ye olde main
  259  */
  260 int main(int argc, char* argv[]) {
  261   int r = 0;
  262   struct props p;
  263 
  264   props_new(&p);
  265 
  266   // Load configs into properties struct
  267   config_to_props(CONF, &p);
  268 
  269   // Parse cli arguments (overriding any configs if specified at runtime)
  270   if(parseargs(&p, argc, argv) != 0)
  271     return 1;
  272 
  273   // Determine if we should fade up or fade down
  274   if(p.lvl < 0) {
  275     printf("%d\n", p.cur);
  276   } else {
  277     r = fade(&p);
  278   }
  279 
  280   if(r < 0) {
  281     fprintf(stderr, "ERROR: Could not open brightness file\n");
  282     return 1;
  283   }
  284   return 0;
  285 }

Generated by cgit