summaryrefslogtreecommitdiff
path: root/src/main.c
blob: f3ab73ac6edb48c01cb4266ec9a403c617d75e60 (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;
   30   int step;
   31   int rate;
   32   int max;
   33   int cur;
   34   char filebrightness[512];
   35   char filemax_bright[512];
   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
   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  * fadeup:
   75  * @props Props struct containing runtime parameters
   76  *
   77  * Fades brightness down, incremented by props->step every props->rate
   78  * milliseconds
   79  *
   80  * returns: Success (0) or failure (-1)
   81  */
   82 int fadeup(struct props* props) {
   83   struct timespec tim, tim2;
   84   int sec;  // Number of seconds to sleep
   85   int msec; // Number of milliseconds to sleep (less than 1 second)
   86 
   87   sec = props->rate / 1000;
   88   msec = props->rate - (sec * 1000);
   89 
   90   tim.tv_sec = sec;
   91   tim.tv_nsec = 1000000 * msec;
   92 
   93   while(props->cur < props->lvl) {
   94     nanosleep(&tim, &tim2);
   95 
   96     FILE* fd = fopen(props->filebrightness, "w");
   97     if(! fd) {
   98       if(errno == EACCES) {
   99         fprintf(stderr, "Permission denied: %s\n", props->filebrightness);
  100       } else {
  101         fprintf(stderr, "Could not open file %s\n", props->filebrightness);
  102       }
  103       return -1;
  104     }
  105 
  106     // Write the new brightness to the brightness file
  107     fprintf(fd, "%d\n", props->cur);
  108     fclose(fd);
  109 
  110     if(props->cur >= props->max)
  111       break;
  112     props->cur += props->step;
  113   }
  114   return 0;
  115 }
  116 
  117 
  118 /**
  119  * fadedown:
  120  * @props Props struct containing runtime parameters
  121  *
  122  * Fades brightness down, decremented by props->step every props->rate
  123  * milliseconds
  124  *
  125  * returns: Success (0) or failure (-1)
  126  */
  127 int fadedown(struct props* props) {
  128   struct timespec tim, tim2;
  129   int sec;  // Number of seconds to sleep
  130   int msec; // Number of milliseconds to sleep (less than 1 second)
  131 
  132   sec = props->rate / 1000;
  133   msec = props->rate - (sec * 1000);
  134 
  135   tim.tv_sec = sec;
  136   tim.tv_nsec = 1000000 * msec;
  137 
  138   while(props->cur > props->lvl) {
  139     nanosleep(&tim, &tim2);
  140 
  141     FILE* fd = fopen(props->filebrightness, "w");
  142     if(! fd) {
  143       if(errno == EACCES) {
  144         fprintf(stderr, "Permission denied: %s\n", props->filebrightness);
  145       } else {
  146         fprintf(stderr, "Could not open file %s\n", props->filebrightness);
  147       }
  148       return -1;
  149     }
  150 
  151     // Write the new brightness to the brightness file
  152     fprintf(fd, "%d\n", props->cur);
  153     fclose(fd);
  154 
  155     if(props->cur <= 0)
  156       break;
  157     props->cur -= props->step;
  158   }
  159   return 0;
  160 }
  161 
  162 
  163 /**
  164  * usage:
  165  *
  166  * Nothing to see here. Just the help text printer.
  167  */
  168 void usage() {
  169   printf(
  170 "Luminous is a backlight manager that supports fading the backlight at\n"
  171 "varying rates and steps. It manages backlight via the kenerl interfaces\n"
  172 "provided in /sys to adjust screen backlight levels. Consequently, it\n"
  173 "requires write access to the brightness property in \n"
  174 "/sys/class/backlight/<device>/brightness.\n"
  175 "\n"
  176 "Usage:\n"
  177 "  luminous --rate 10 --step 8 --level [+-]400\n"
  178 "\n"
  179 "Arguments:\n"
  180 "  -h,--help  Print this helptext\n"
  181 "  -s,--step  Fade step (default: 6)\n"
  182 "  -r,--rate  Time in milliseconds between fade steps (default: 10)\n"
  183 "  -l,--level Brightness level to change to. Supports absolute values and\n"
  184 "             relative values prefixed with + and -."
  185 "\n\n"
  186 );
  187 }
  188 
  189 
  190 /**
  191  * parseargs:
  192  * @out   Output properties struct
  193  * @argc  Number of arguments passed
  194  * @argv  Arguments char array
  195  *
  196  * Parses command line arguments into a props struct.
  197  *
  198  * returns: Success (0), failure (-1), or incomplete (-2)
  199  */
  200 int parseargs(struct props* out, int argc, char* argv[]) {
  201   int i;
  202   
  203   strcpy(out->filebrightness,
  204          "/sys/class/backlight/intel_backlight/brightness");
  205   strcpy(out->filemax_bright,
  206          "/sys/class/backlight/intel_backlight/max_brightness");
  207 
  208   // Read the system values for current and maximum brightness
  209   out->cur = fgeti(out->filebrightness);
  210   out->max = fgeti(out->filemax_bright);
  211 
  212   for(i = 0; i < argc; i++) {
  213     if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) {
  214       i++;
  215       out->rate = atoi(argv[i]);
  216     } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--step") == 0) {
  217       i++;
  218       out->step = atoi(argv[i]);
  219     } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--level") == 0) {
  220       i++;
  221       // Account for relative and absolute increments and decrements
  222       if(argv[i][0] == '+') {
  223         out->lvl = out->cur + atoi(&argv[i][1]);
  224       } else if(argv[i][0] == '-') {
  225         out->lvl = out->cur - atoi(&argv[i][1]);
  226       } else {
  227         out->lvl = atoi(argv[i]);
  228       }
  229     } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
  230       usage();
  231       return -2;
  232     }
  233   }
  234 
  235   // Some defaults, if no values are set yet
  236   if(out->rate < 0)
  237    out->rate = 20;
  238   if(out->step < 0)
  239    out->step = 12;
  240   if(out->lvl == -1)
  241     out->lvl = 200;
  242 
  243   // Ensure min and max thresholds are respected
  244   if(out->lvl > out->max) {
  245     out->lvl = out->max;
  246   } else if(out->lvl < 0) {
  247     out->lvl = 0;
  248   }
  249   return 0;
  250 }
  251 
  252 
  253 int config_to_props(char* confpath, struct props* p) {
  254   struct config c;
  255   char lvlbuf[32];  // Buffer to store config value for "level" if found
  256   char ratebuf[32]; // Buffer to store config value for "rate" if found
  257   char stepbuf[32]; // Buffer to store config value for "step" if found
  258 
  259   if(config_new(&c, confpath) == 0) {
  260     config_load(&c);
  261   } else {
  262     // Config file not found, return -2 code
  263     return -2;
  264   }
  265 
  266   // If the config specifies a "level" key, set it to the props object
  267   if(config_get(&c, "level", lvlbuf) == 0)
  268     p->lvl = atoi(lvlbuf);
  269 
  270   // If the config specifies a "step" key, set it to the props object
  271   if(config_get(&c, "step", stepbuf) == 0)
  272     p->step = atoi(stepbuf);
  273 
  274   // If the config specifies a "rate" key, set it to the props object
  275   if(config_get(&c, "rate", ratebuf) == 0)
  276     p->rate = atoi(ratebuf);
  277 
  278   // Don't forget to clean up!
  279   config_free(&c);
  280 
  281   return 0;
  282 }
  283 
  284 
  285 /**
  286  * Ye olde main
  287  */
  288 int main(int argc, char* argv[]) {
  289   int r = 0;
  290   struct props p;
  291 
  292   props_new(&p);
  293 
  294   // Load configs into properties struct
  295   config_to_props(CONF, &p);
  296 
  297   // Parse cli arguments (overriding any configs if specified at runtime)
  298   if(parseargs(&p, argc, argv) != 0)
  299     return 1;
  300 
  301   // Determine if we should fade up or fade down
  302   if(p.lvl < 0) {
  303     printf("%d\n", p.cur);
  304   } else if(p.lvl > p.cur) {
  305     r = fadeup(&p);
  306   } else if (p.lvl < p.cur) {
  307     r = fadedown(&p);
  308   }
  309 
  310   if(r < 0) {
  311     fprintf(stderr, "ERROR: Could not open brightness file\n");
  312     return 1;
  313   }
  314   return 0;
  315 }

Generated by cgit