|
1 #include <stdio.h> |
|
2 #include <stdlib.h> |
|
3 #include <math.h> |
|
4 |
|
5 #include <sys/types.h> |
|
6 #include <sys/stat.h> |
|
7 #include <fcntl.h> |
|
8 #include <assert.h> |
|
9 #include <string.h> |
|
10 #include <limits.h> |
|
11 #include <unistd.h> |
|
12 #include <errno.h> |
|
13 |
|
14 #include "config.h" |
|
15 #ifdef USE_UDEV |
|
16 #include <poll.h> |
|
17 #include <libudev.h> |
|
18 #endif |
|
19 |
|
20 char *eights[] = { "ø", "▁", "▂", "▃", "▄", "▅", "▆","▇", "█" }; |
|
21 |
|
22 char *catfile(char *name) { |
|
23 struct stat buffer; |
|
24 int status; |
|
25 int f; |
|
26 char* resbuf; |
|
27 f = open(name, O_RDONLY); |
|
28 if (f == -1) return NULL; |
|
29 status = fstat(f, &buffer); |
|
30 if (status != 0) return NULL; |
|
31 resbuf = malloc(buffer.st_size+1); |
|
32 if (resbuf == NULL) return NULL; |
|
33 status = read(f,resbuf,buffer.st_size); |
|
34 if (status == -1) { |
|
35 free(resbuf); |
|
36 return NULL; |
|
37 } |
|
38 if ((status>0)&&(resbuf[status-1]=='\n')) |
|
39 resbuf[status-1]='\0'; |
|
40 resbuf[status]='\0'; |
|
41 return resbuf; |
|
42 } |
|
43 |
|
44 int catint(char *name) { |
|
45 char *cont = catfile(name); |
|
46 assert (cont != NULL); |
|
47 int res = atoi(cont); |
|
48 free(cont); |
|
49 return res; |
|
50 } |
|
51 |
|
52 char *color_stop; |
|
53 char *color_red; |
|
54 char *color_orange; |
|
55 char *color_green; |
|
56 char *color_none; |
|
57 |
|
58 char *color(int low,int mid,int rev,int value) { |
|
59 if (value>mid) { |
|
60 return rev ? color_red : color_green; |
|
61 } else if (value>low) { |
|
62 return color_orange; |
|
63 } |
|
64 return rev ? color_green : color_red; |
|
65 } |
|
66 |
|
67 int main(int argc, char *argv[]) { |
|
68 if (argc<=1) { |
|
69 fprintf(stderr, "Usage: %s <BAT1> [term|pango]\n", argv[0]); |
|
70 fflush(stderr); |
|
71 return 1; |
|
72 } |
|
73 |
|
74 char *arrow_color; |
|
75 char *eights_color; |
|
76 char *percent_color; |
|
77 char *remtimes_color; |
|
78 if (argc>2 && !strcmp(argv[2],"term")) { |
|
79 color_stop = "\x1b[0m"; |
|
80 color_red = "\x1b[1;31m"; |
|
81 color_green = "\x1b[1;32m"; |
|
82 color_orange = "\x1b[1;33m"; |
|
83 color_none = color_stop; |
|
84 } else if (argc>2 && !strcmp(argv[2],"pango")) { |
|
85 color_stop = "</span>"; |
|
86 color_red = "<span color='#f33'>"; |
|
87 color_green = "<span color='#0f0'>"; |
|
88 color_orange = "<span color='#fa0'>"; |
|
89 color_none = "<span>"; |
|
90 } else { |
|
91 color_stop = color_red = color_green = color_orange = color_none = ""; |
|
92 } |
|
93 |
|
94 #ifdef USE_UDEV |
|
95 struct udev *udev; |
|
96 struct udev_device *dev; |
|
97 |
|
98 struct udev_monitor *mon; |
|
99 int mon_fd; |
|
100 |
|
101 udev = udev_new(); |
|
102 if (!udev) { |
|
103 printf("Can't create udev\n"); |
|
104 exit(1); |
|
105 } |
|
106 mon = udev_monitor_new_from_netlink(udev, "udev"); |
|
107 udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL); |
|
108 udev_monitor_enable_receiving(mon); |
|
109 mon_fd = udev_monitor_get_fd(mon); |
|
110 static struct pollfd fds[1]; |
|
111 fds[0].fd = mon_fd; |
|
112 fds[0].events = POLLIN; |
|
113 #endif |
|
114 while (1) { |
|
115 char filename[PATH_MAX+1]; |
|
116 |
|
117 snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/charge_now",argv[1]); |
|
118 int charge_now = catint(filename); |
|
119 |
|
120 snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/current_now",argv[1]); |
|
121 int current_now = catint(filename); |
|
122 |
|
123 snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/charge_full",argv[1]); |
|
124 int charge_full = catint(filename); |
|
125 |
|
126 snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/status",argv[1]); |
|
127 char *status = catfile(filename); |
|
128 |
|
129 int remtime = 0; |
|
130 char remtimes[128]; |
|
131 char *arrow; |
|
132 |
|
133 remtimes_color = color_none; |
|
134 if (!strcmp(status,"Charging")) { |
|
135 if (current_now != 0) |
|
136 remtime = ((charge_full-charge_now) * 60) / current_now; |
|
137 arrow = "↑"; |
|
138 arrow_color = color_orange; |
|
139 } |
|
140 else if (!strcmp(status,"Discharging")) { |
|
141 if (current_now != 0) |
|
142 remtime = (charge_now * 60) / current_now; |
|
143 arrow = "↓"; |
|
144 arrow_color = color_none; |
|
145 remtimes_color = color(20,120,0,remtime); |
|
146 } else { |
|
147 arrow = "—"; |
|
148 arrow_color = color_green; |
|
149 } |
|
150 free(status); |
|
151 snprintf(remtimes,127,"%d:%02d",remtime/60,remtime%60); |
|
152 //printf("%d %d %d %s %d %s %s\n",charge_now,current_now,charge_full, |
|
153 // eights[charge_now*8/charge_full], charge_now*100/charge_full,status,remtimes); |
|
154 |
|
155 |
|
156 int percent = charge_now*100/charge_full; |
|
157 eights_color = percent_color = color(15,40,0,percent); |
|
158 printf("%s%s%s ",eights_color,eights[charge_now*8/charge_full],color_stop); |
|
159 printf("%s%d%%%s ",percent_color,percent,color_stop); |
|
160 printf("%s%s%s ",arrow_color,arrow,color_stop); |
|
161 printf("%s%s%s\n",remtimes_color,remtimes,color_stop); |
|
162 fflush(stdout); |
|
163 #ifdef USE_UDEV |
|
164 int poll_status = poll(fds,1, UPDATE_PERIOD*1000); |
|
165 if (poll_status < 0) { |
|
166 if (poll_status != EINTR) { |
|
167 perror("poll"); |
|
168 exit(12); |
|
169 } |
|
170 } |
|
171 if (fds[0].revents & POLLIN) { |
|
172 dev = udev_monitor_receive_device(mon); |
|
173 if (dev) { |
|
174 udev_device_unref(dev); |
|
175 } else { |
|
176 printf("UDEV DC\n"); |
|
177 exit(13); |
|
178 } |
|
179 } |
|
180 #else |
|
181 sleep(UPDATE_PERIOD); |
|
182 #endif |
|
183 } |
|
184 } |