Xinqi Bao's Git

cd2def6d8acca751a77b76d01c19287031fd0bc5
[slstatus.git] / slstatus.c
1 /* See LICENSE file for copyright and license details. */
2
3 /* global libraries */
4 #include <alsa/asoundlib.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <X11/Xlib.h>
12
13 /* local libraries */
14 #include "config.h"
15
16 /* functions */
17 void setstatus(char *str);
18 char *get_battery();
19 char *get_cpu_temperature();
20 char *get_cpu_usage();
21 char *get_datetime();
22 char *get_ram_usage();
23 char *smprintf(char *fmt, ...);
24 char *get_volume();
25 char *get_wifi_signal();
26
27 /* global variables */
28 static Display *dpy;
29
30 /* set statusbar (WM_NAME) */
31 void
32 setstatus(char *str)
33 {
34 XStoreName(dpy, DefaultRootWindow(dpy), str);
35 XSync(dpy, False);
36 }
37
38 /* battery percentage */
39 char *
40 get_battery()
41 {
42 int battery_now, battery_full, battery_perc;
43 FILE *fp;
44
45 /* open battery now file */
46 if (!(fp = fopen(batterynowfile, "r"))) {
47 fprintf(stderr, "Error opening battery file.");
48 exit(1);
49 }
50
51 /* read value */
52 fscanf(fp, "%i", &battery_now);
53
54 /* close battery now file */
55 fclose(fp);
56
57 /* open battery full file */
58 if (!(fp = fopen(batteryfullfile, "r"))) {
59 fprintf(stderr, "Error opening battery file.");
60 exit(1);
61 }
62
63 /* read value */
64 fscanf(fp, "%i", &battery_full);
65
66 /* close battery full file */
67 fclose(fp);
68
69 /* calculate percent */
70 battery_perc = battery_now / (battery_full / 100);
71
72 /* return batt_perc as string */
73 return smprintf("%d%%", battery_perc);
74 }
75
76 /* cpu temperature */
77 char *
78 get_cpu_temperature()
79 {
80 int temperature;
81 FILE *fp;
82
83 /* open temperature file */
84 if (!(fp = fopen(tempfile, "r"))) {
85 fprintf(stderr, "Could not open temperature file.\n");
86 exit(1);
87 }
88
89 /* extract temperature */
90 fscanf(fp, "%d", &temperature);
91
92 /* close temperature file */
93 fclose(fp);
94
95 /* return temperature in degrees */
96 return smprintf("%d°C", temperature / 1000);
97 }
98
99 /* cpu percentage */
100 char *
101 get_cpu_usage()
102 {
103 int cpu_perc;
104 long double a[4], b[4];
105 FILE *fp;
106
107 /* open stat file */
108 if (!(fp = fopen("/proc/stat","r"))) {
109 fprintf(stderr, "Error opening stat file.");
110 exit(1);
111 }
112
113 /* read values */
114 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
115
116 /* close stat file */
117 fclose(fp);
118
119 /* wait a second (for avg values) */
120 sleep(1);
121
122 /* open stat file */
123 if (!(fp = fopen("/proc/stat","r"))) {
124 fprintf(stderr, "Error opening stat file.");
125 exit(1);
126 }
127
128 /* read values */
129 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
130
131 /* close stat file */
132 fclose(fp);
133
134 /* calculate avg in this second */
135 cpu_perc = 100 * ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
136
137 /* return cpu_perc as string */
138 return smprintf("%d%%", cpu_perc);
139 }
140
141 /* date and time */
142 char *
143 get_datetime()
144 {
145 time_t tm;
146 size_t bufsize = 19;
147 char *buf = malloc(bufsize);
148
149 /* get time in format */
150 time(&tm);
151 if(!strftime(buf, bufsize, timeformat, localtime(&tm))) {
152 fprintf(stderr, "Strftime failed.\n");
153 exit(1);
154 }
155
156 /* return time */
157 return buf;
158 }
159
160 /* ram percentage */
161 char *
162 get_ram_usage()
163 {
164 int ram_perc;
165 long total, free, available;
166 FILE *fp;
167
168 /* open meminfo file */
169 if (!(fp = fopen("/proc/meminfo", "r"))) {
170 fprintf(stderr, "Error opening meminfo file.");
171 exit(1);
172 }
173
174 /* read the values */
175 fscanf(fp, "MemTotal: %ld kB\n", &total);
176 fscanf(fp, "MemFree: %ld kB\n", &free);
177 fscanf(fp, "MemAvailable: %ld kB\n", &available);
178
179 /* close meminfo file */
180 fclose(fp);
181
182 /* calculate percentage */
183 ram_perc = 100 * (total - available) / total;
184
185 /* return ram_perc as string */
186 return smprintf("%d%%",ram_perc);
187 }
188
189 /* smprintf function */
190 char *
191 smprintf(char *fmt, ...)
192 {
193 va_list fmtargs;
194 char *ret;
195 int len;
196
197 va_start(fmtargs, fmt);
198 len = vsnprintf(NULL, 0, fmt, fmtargs);
199 va_end(fmtargs);
200
201 ret = malloc(++len);
202 if (ret == NULL) {
203 fprintf(stderr, "Malloc error.");
204 exit(1);
205 }
206
207 va_start(fmtargs, fmt);
208 vsnprintf(ret, len, fmt, fmtargs);
209 va_end(fmtargs);
210
211 return ret;
212 }
213
214 /* alsa volume percentage */
215 char *
216 get_volume()
217 {
218 int mute = 0;
219 long vol = 0, max = 0, min = 0;
220
221 /* get volume from alsa */
222 snd_mixer_t *handle;
223 snd_mixer_elem_t *pcm_mixer, *mas_mixer;
224 snd_mixer_selem_id_t *vol_info, *mute_info;
225 snd_mixer_open(&handle, 0);
226 snd_mixer_attach(handle, soundcard);
227 snd_mixer_selem_register(handle, NULL, NULL);
228 snd_mixer_load(handle);
229 snd_mixer_selem_id_malloc(&vol_info);
230 snd_mixer_selem_id_malloc(&mute_info);
231 snd_mixer_selem_id_set_name(vol_info, channel);
232 snd_mixer_selem_id_set_name(mute_info, channel);
233 pcm_mixer = snd_mixer_find_selem(handle, vol_info);
234 mas_mixer = snd_mixer_find_selem(handle, mute_info);
235 snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t *)pcm_mixer, &min, &max);
236 snd_mixer_selem_get_playback_volume((snd_mixer_elem_t *)pcm_mixer, SND_MIXER_SCHN_MONO, &vol);
237 snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO, &mute);
238 if (vol_info)
239 snd_mixer_selem_id_free(vol_info);
240 if (mute_info)
241 snd_mixer_selem_id_free(mute_info);
242 if (handle)
243 snd_mixer_close(handle);
244
245 /* return the string (mute) */
246 if (!mute)
247 return smprintf("mute");
248 else
249 return smprintf("%d%%", (vol * 100) / max);
250 }
251
252 /* wifi percentage */
253 char *
254 get_wifi_signal()
255 {
256 int bufsize = 255;
257 int strength;
258 char buf[bufsize];
259 char *datastart;
260 char path_start[16] = "/sys/class/net/";
261 char path_end[11] = "/operstate";
262 char path[32];
263 char status[5];
264 char needle[sizeof wificard + 1];
265 FILE *fp;
266
267 /* generate the path name */
268
269 memset(path, 0, sizeof path);
270 strcat(path, path_start);
271 strcat(path, wificard);
272 strcat(path, path_end);
273
274 /* open wifi file */
275 if(!(fp = fopen(path, "r"))) {
276 fprintf(stderr, "Error opening wifi operstate file.");
277 exit(1);
278 }
279
280 /* read the status */
281 fgets(status, 5, fp);
282
283 /* close wifi file */
284 fclose(fp);
285
286 /* check if interface down */
287 if(strcmp(status, "up\n") != 0){
288 return "n/a";
289 }
290
291 /* open wifi file */
292 if (!(fp = fopen("/proc/net/wireless", "r"))) {
293 fprintf(stderr, "Error opening wireless file.");
294 exit(1);
295 }
296
297 /* extract the signal strength */
298 strcpy(needle, wificard);
299 strcat(needle, ":");
300 fgets(buf, bufsize, fp);
301 fgets(buf, bufsize, fp);
302 fgets(buf, bufsize, fp);
303 if ((datastart = strstr(buf, needle)) != NULL) {
304 datastart = strstr(buf, ":");
305 sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &strength);
306 }
307
308 /* close wifi file */
309 fclose(fp);
310
311 /* return strength in percent */
312 return smprintf("%d%%", strength);
313 }
314
315 /* main function */
316 int
317 main()
318 {
319 char status[1024];
320 char *wifi_signal = NULL;
321 char *battery = NULL;
322 char *cpu_usage = NULL;
323 char *cpu_temperature = NULL;
324 char *ram_usage = NULL;
325 char *volume = NULL;
326 char *datetime = NULL;
327
328 /* open display */
329 if (!(dpy = XOpenDisplay(0x0))) {
330 fprintf(stderr, "Cannot open display!\n");
331 exit(1);
332 }
333
334 /* return status every second */
335 for (;;) {
336 /* assign the values */
337 wifi_signal = get_wifi_signal();
338 battery = get_battery();
339 cpu_usage = get_cpu_usage();
340 cpu_temperature = get_cpu_temperature();
341 ram_usage = get_ram_usage();
342 volume = get_volume();
343 datetime = get_datetime();
344
345 /* return the status */
346 sprintf(status, FORMATSTRING, ARGUMENTS);
347 setstatus(status);
348
349 /* free the values */
350 free(wifi_signal);
351 free(battery);
352 free(cpu_usage);
353 free(cpu_temperature);
354 free(ram_usage);
355 free(volume);
356 free(datetime);
357 }
358
359 /* close display */
360 XCloseDisplay(dpy);
361
362 /* exit successfully */
363 return 0;
364 }