Xinqi Bao's Git

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