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
22
23 struct props {
24 int lvl;
25 int step;
26 int rate;
27 int max;
28 int cur;
29 char filebrightness[512];
30 char filemax_bright[512];
31 };
32
33
34 /**
35 * fgeti:
36 * @path
37 *
38 * Reads integer from the specified file. If the file does not contain only an
39 * integer, returns -1.
40 *
41 * returns: Integer read from file, otherwise -1.
42 */
43 int fgeti(char* path) {
44 FILE* fd;
45 char buf[64];
46
47 fd = fopen(path, "r");
48 if(! fd)
49 return -1;
50
51 fgets(buf, 64, fd);
52 fclose(fd);
53 return atoi(buf);
54 }
55
56
57 /**
58 * fadeup:
59 * @props Props struct containing runtime parameters
60 *
61 * Fades brightness down, incremented by props->step every props->rate
62 * milliseconds
63 *
64 * returns: Success (0) or failure (-1)
65 */
66 int fadeup(struct props* props) {
67 struct timespec tim, tim2;
68 int sec; // Number of seconds to sleep
69 int msec; // Number of milliseconds to sleep (less than 1 second)
70
71 sec = props->rate / 1000;
72 msec = props->rate - (sec * 1000);
73
74 tim.tv_sec = sec;
75 tim.tv_nsec = 1000000 * msec;
76
77 while(props->cur < props->lvl) {
78 nanosleep(&tim, &tim2);
79
80 FILE* fd = fopen(props->filebrightness, "w");
81 if(! fd)
82 return -1;
83
84 // Write the new brightness to the brightness file
85 fprintf(fd, "%d\n", props->cur);
86 fclose(fd);
87
88 if(props->cur >= props->max)
89 break;
90 props->cur += props->step;
91 }
92 return 0;
93 }
94
95
96 /**
97 * fadedown:
98 * @props Props struct containing runtime parameters
99 *
100 * Fades brightness down, decremented by props->step every props->rate
101 * milliseconds
102 *
103 * returns: Success (0) or failure (-1)
104 */
105 int fadedown(struct props* props) {
106 struct timespec tim, tim2;
107 int sec; // Number of seconds to sleep
108 int msec; // Number of milliseconds to sleep (less than 1 second)
109
110 sec = props->rate / 1000;
111 msec = props->rate - (sec * 1000);
112
113 tim.tv_sec = sec;
114 tim.tv_nsec = 1000000 * msec;
115
116 while(props->cur > props->lvl) {
117 nanosleep(&tim, &tim2);
118
119 FILE* fd = fopen(props->filebrightness, "w");
120 if(! fd)
121 return -1;
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 <= 0)
128 break;
129 props->cur -= props->step;
130 }
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 = 0;
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 // Some defaults
185 out->rate = 10;
186 out->step = 8;
187
188 for(;i < argc; i++) {
189 if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) {
190 i++;
191 out->rate = atoi(argv[i]);
192 } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--step") == 0) {
193 i++;
194 out->step = atoi(argv[i]);
195 } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--level") == 0) {
196 i++;
197 // Account for relative and absolute increments and decrements
198 if(argv[i][0] == '+') {
199 out->lvl = out->cur + atoi(&argv[i][1]);
200 } else if(argv[i][0] == '-') {
201 out->lvl = out->cur - atoi(&argv[i][1]);
202 } else {
203 out->lvl = atoi(argv[i]);
204 }
205 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
206 usage();
207 return -2;
208 }
209 }
210
211 // Ensure min and max thresholds are respected
212 if(out->lvl > out->max) {
213 out->lvl = out->max;
214 } else if(out->lvl < 0) {
215 out->lvl = 0;
216 }
217 return 0;
218 }
219
220
221 /**
222 * Ye olde main
223 */
224 int main(int argc, char* argv[]) {
225 int r = 0;
226 struct props p;
227
228 if(parseargs(&p, argc, argv) != 0)
229 return 1;
230
231 if(argc == 1) {
232 printf("%d\n", p.cur);
233 return 0;
234 }
235
236 // Determine if we should fade up or fade down
237 if(p.lvl > p.cur) {
238 r = fadeup(&p);
239 } else if (p.lvl < p.cur) {
240 r = fadedown(&p);
241 }
242
243 if(r < 0) {
244 fprintf(stderr, "ERROR: Could not open brightness file\n");
245 return 1;
246 }
247 return 0;
248 }
|