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

Generated by cgit