Xinqi Bao's Git

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