-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbacklight.cpp
More file actions
165 lines (136 loc) · 4.73 KB
/
backlight.cpp
File metadata and controls
165 lines (136 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <filesystem>
#include <algorithm>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
const std::string base_path = "/sys/class/backlight/";
// CLI options
struct options {
int level;
bool list;
int device = -1;
};
class display {
public:
int id;
std::string path;
display(int _id, std::string _path) {
id = _id;
path = _path;
};
};
struct options parse_args(int argc, char* argv[]) {
options options;
for (int i = 0; i < argc; i++) {
std::string arg = argv[i];
// help/usage
if(argc < 2 || arg == "-h" || arg == "-help") {
std::cout << "backlight is a simple display backlight utility\n"
<< "usage: backlight <-l[evel> <level>]\n"
<< "<-l[evel]> <level> brightness level as a percentage\n"
<< "[-d[evices]] list all available display devices (by default all devices are adjusted)\n"
<< "[-D[evice] <id>] set a specific display brightness\n";
exit(1);
};
// level
if (arg == "-l" || arg == "-level") {
// check presence of level argument
if(!argv[i + 1]) {
std::cerr << "error: no level provided\n";
exit(1);
} else {
// parse level
options.level = atoi(argv[i + 1]);
};
};
// device id list
options.list = (arg == "-d" || arg == "-devices");
// set specific id
if(arg == "-D" || arg == "-Device") {
if(!argv[i + 1]) {
std::cerr << "error: no device ID provided, use -d to list all available displays" << std::endl;
exit(1);
} else {
// parse device ID
options.device = atoi(argv[i + 1]);
};
};
};
return options;
}
// simplify reading display parameters
long int read_file_int(std::string path) {
std::string val;
std::ifstream file(path);
if(file.is_open() == 0) return 1;
else std::getline(file, val);
if(val.empty())
return -1;
return std::stoi(val);
}
int main(int argc, char* argv[]) {
int last_id = -1; // keep track of displays
// check if argc sufficient
if(argc < 2) {
std::cerr << "usage: backlight <-l[evel]> <level>\n"
<< "use -h for more options\n";
return 1;
};
// parse arguments into options struct
options opts = parse_args(argc, argv);
// check if level provided and check range
if(opts.device != -1) {
if(!opts.level) {
std::cerr << "error: no brightness level provided\n";
exit(1);
} else if(opts.level < 1 || opts.level > 100) {
std::cerr << "error: invalid level range (1 - 100)\n";
exit(1);
};
};
// index all sysfs backlight interfaces
std::vector <display> displays; // index of interfaces in /sys/class/backlight
DIR *sysfs = opendir(base_path.c_str()); // sysfs directory
struct dirent *sysfs_ent; // sysfs directory entry
while((sysfs_ent = readdir(sysfs)) != NULL) {
std::string path(sysfs_ent->d_name);
if(path == "." || path == "..") continue; // skip links
else last_id++;
display d(last_id, path);
displays.push_back(d);
};
for (display disp : displays) {
// list displays
if(opts.list == true) {
std::cout << disp.id << ": " << disp.path << std::endl;
continue;
};
// specific device
if(opts.device != -1 && disp.id != opts.device) continue; // skip if not selected ID
// get display capabilities and current brightness
int max = read_file_int(base_path + disp.path + "/max_brightness");
// ensure parameters are in tact
if(!max) {
std::cerr << "error: could not determine max brightness of device: " << disp.path << std::endl;
return 1;
};
// calculate desired screen brightness as a percentage of display maximum
double des = max * (double)opts.level / 100;
std::string set = std::to_string((int)des);
// set brightness using the sysfs backlight interface
std::ofstream brightness(base_path + disp.path + "/brightness");
if(brightness.is_open()) {
brightness << set << std::endl;
brightness.close();
} else if(brightness.fail()) {
std::cerr << "error: failed to write to " << disp.path << std::endl;
return 1;
};
};
return 0;
}