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
24 struct props {
25 int lvl;
26 int step;
27 int rate;
28 int max;
29 int cur;
30 char filebrightness[512];
31 char filemax_bright[512];
32 };
33
34
35 /**
36 * fgeti:
37 * @path
38 *
39 * Reads integer from the specified file. If the file does not contain only an
40 * integer, returns -1.
41 *
42 * returns: Integer read from file, otherwise -1.
43 */
44 int fgeti(char* path) {
45 FILE* fd;
46 char buf[64];
47
48 fd = fopen(path, "r");
49 if(! fd)
50 return -1;
51
52 fgets(buf, 64, fd);
53 fclose(fd);
54 return atoi(buf);
55 }
56
57
58 /**
59 * fadeup:
60 * @props Props struct containing runtime parameters
61 *
62 * Fades brightness down, incremented by props->step every props->rate
63 * milliseconds
64 *
65 * returns: Success (0) or failure (-1)
66 */
67 int fadeup(struct props* props) {
68 struct timespec tim, tim2;
69 int sec; // Number of seconds to sleep
70 int msec; // Number of milliseconds to sleep (less than 1 second)
71
72 sec = props->rate / 1000;
73 msec = props->rate - (sec * 1000);
74
75 tim.tv_sec = sec;
76 tim.tv_nsec = 1000000 * msec;
77
78 while(props->cur < props->lvl) {
79 nanosleep(&tim, &tim2);
80
81 FILE* fd = fopen(props->filebrightness, "w");
82 if(! fd) {
83 if(errno == EACCES) {
84 fprintf(stderr, "Permission denied: %s\n", props->filebrightness);
85 } else {
86 fprintf(stderr, "Could not open file %s\n", props->filebrightness);
87 }
88 return -1;
89 }
90
91 // Write the new brightness to the brightness file
92 fprintf(fd, "%d\n", props->cur);
93 fclose(fd);
94
95 if(props->cur >= props->max)
96 break;
97 props->cur += props->step;
98 }
99 return 0;
100 }
101
102
103 /**
104 * fadedown:
105 * @props Props struct containing runtime parameters
106 *
107 * Fades brightness down, decremented by props->step every props->rate
108 * milliseconds
109 *
110 * returns: Success (0) or failure (-1)
111 */
112 int fadedown(struct props* props) {
113 struct timespec tim, tim2;
114 int sec; // Number of seconds to sleep
115 int msec; // Number of milliseconds to sleep (less than 1 second)
116
117 sec = props->rate / 1000;
118 msec = props->rate - (sec * 1000);
119
120 tim.tv_sec = sec;
121 tim.tv_nsec = 1000000 * msec;
122
123 while(props->cur > props->lvl) {
124 nanosleep(&tim, &tim2);
125
126 FILE* fd = fopen(props->filebrightness, "w");
127 if(! fd) {
128 if(errno == EACCES) {
129 fprintf(stderr, "Permission denied: %s\n", props->filebrightness);
130 } else {
131 fprintf(stderr, "Could not open file %s\n", props->filebrightness);
132 }
133 return -1;
134 }
135
136 // Write the new brightness to the brightness file
137 fprintf(fd, "%d\n", props->cur);
138 fclose(fd);
139
140 if(props->cur <= 0)
141 break;
142 props->cur -= props->step;
143 }
144 return 0;
145 }
146
147
148 /**
149 * usage:
150 *
151 * Nothing to see here. Just the help text printer.
152 */
153 void usage() {
154 printf(
155 "Luminous is a backlight manager that supports fading the backlight at\n"
156 "varying rates and steps. It manages backlight via the kenerl interfaces\n"
157 "provided in /sys to adjust screen backlight levels. Consequently, it\n"
158 "requires write access to the brightness property in \n"
159 "/sys/class/backlight/<device>/brightness.\n"
160 "\n"
161 "Usage:\n"
162 " luminous --rate 10 --step 8 --level [+-]400\n"
163 "\n"
164 "Arguments:\n"
165 " -h,--help Print this helptext\n"
166 " -s,--step Fade step (default: 6)\n"
167 " -r,--rate Time in milliseconds between fade steps (default: 10)\n"
168 " -l,--level Brightness level to change to. Supports absolute values and\n"
169 " relative values prefixed with + and -."
170 "\n\n"
171 );
172 }
173
174
175 /**
176 * parseargs:
177 * @out Output properties struct
178 * @argc Number of arguments passed
179 * @argv Arguments char array
180 *
181 * Parses command line arguments into a props struct.
182 *
183 * returns: Success (0), failure (-1), or incomplete (-2)
184 */
185 int parseargs(struct props* out, int argc, char* argv[]) {
186 int i = 0;
187
188 strcpy(out->filebrightness,
189 "/sys/class/backlight/intel_backlight/brightness");
190 strcpy(out->filemax_bright,
191 "/sys/class/backlight/intel_backlight/max_brightness");
192
193 // Read the system values for current and maximum brightness
194 out->cur = fgeti(out->filebrightness);
195 out->max = fgeti(out->filemax_bright);
196
197 // Some defaults
198 out->rate = 10;
199 out->step = 8;
200
201 for(;i < argc; i++) {
202 if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) {
203 i++;
204 out->rate = atoi(argv[i]);
205 } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--step") == 0) {
206 i++;
207 out->step = atoi(argv[i]);
208 } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--level") == 0) {
209 i++;
210 // Account for relative and absolute increments and decrements
211 if(argv[i][0] == '+') {
212 out->lvl = out->cur + atoi(&argv[i][1]);
213 } else if(argv[i][0] == '-') {
214 out->lvl = out->cur - atoi(&argv[i][1]);
215 } else {
216 out->lvl = atoi(argv[i]);
217 }
218 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
219 usage();
220 return -2;
221 }
222 }
223
224 // Ensure min and max thresholds are respected
225 if(out->lvl > out->max) {
226 out->lvl = out->max;
227 } else if(out->lvl < 0) {
228 out->lvl = 0;
229 }
230 return 0;
231 }
232
233
234 /**
235 * Ye olde main
236 */
237 int main(int argc, char* argv[]) {
238 int r = 0;
239 struct props p;
240
241 if(parseargs(&p, argc, argv) != 0)
242 return 1;
243
244 if(argc == 1) {
245 printf("%d\n", p.cur);
246 return 0;
247 }
248
249 // Determine if we should fade up or fade down
250 if(p.lvl > p.cur) {
251 r = fadeup(&p);
252 } else if (p.lvl < p.cur) {
253 r = fadedown(&p);
254 }
255
256 if(r < 0) {
257 fprintf(stderr, "ERROR: Could not open brightness file\n");
258 return 1;
259 }
260 return 0;
261 }
|