Xinqi Bao's Git

77f900d678f645c6e2861f758cf75f2ca33346cc
[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 snd_mixer_t *handle;
69 snd_mixer_elem_t *pcm_mixer, *mas_mixer;
70 snd_mixer_selem_id_t *vol_info, *mute_info;
71 snd_mixer_open(&handle, 0);
72 snd_mixer_attach(handle, soundcard);
73 snd_mixer_selem_register(handle, NULL, NULL);
74 snd_mixer_load(handle);
75 snd_mixer_selem_id_malloc(&vol_info);
76 snd_mixer_selem_id_malloc(&mute_info);
77 snd_mixer_selem_id_set_name(vol_info, channel);
78 snd_mixer_selem_id_set_name(mute_info, channel);
79 pcm_mixer = snd_mixer_find_selem(handle, vol_info);
80 mas_mixer = snd_mixer_find_selem(handle, mute_info);
81 snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t *)pcm_mixer,
82 &min, &max);
83 snd_mixer_selem_get_playback_volume((snd_mixer_elem_t *)pcm_mixer,
84 SND_MIXER_SCHN_MONO, &vol);
85 snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO,
86 &mute);
87
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 if (!mute)
96 return "mute";
97 else
98 return smprintf("%d%%", (vol * 100) / max);
99 }
100
101 /* cpu temperature */
102 char *
103 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, close file */
115 fscanf(fp, "%d", &temperature);
116 fclose(fp);
117
118 /* return temperature in degrees */
119 return smprintf("%d°C", temperature / 1000);
120 }
121
122 /* wifi percentage */
123 char *
124 wifi_signal()
125 {
126 int bufsize = 255;
127 int strength;
128 char buf[bufsize];
129 char *datastart;
130 char path_start[16] = "/sys/class/net/";
131 char path_end[11] = "/operstate";
132 char path[32];
133 FILE *fp;
134
135 /* generate the path name */
136 strcat(path, path_start);
137 strcat(path, wificard);
138 strcat(path, path_end);
139
140 /* open wifi file, extract status, close file */
141 if(!(fp = fopen(path, "r"))) {
142 fprintf(stderr, "Error opening wifi operstate file.");
143 exit(1);
144 }
145 char status[5];
146 fgets(status, 5, fp);
147 fclose(fp);
148
149 /* check if interface down */
150 if(strcmp(status, "up\n") != 0){
151 return "n/a";
152 }
153
154 /* open wifi file */
155 if (!(fp = fopen("/proc/net/wireless", "r"))) {
156 fprintf(stderr, "Error opening wireless file.");
157 exit(1);
158 }
159
160 /* extract the signal strength and close the file */
161 fgets(buf, bufsize, fp);
162 fgets(buf, bufsize, fp);
163 fgets(buf, bufsize, fp);
164 if ((datastart = strstr(buf, "wlp3s0:")) != NULL) {
165 datastart = strstr(buf, ":");
166 sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d",
167 &strength);
168 }
169 fclose(fp);
170
171 /* return strength in percent */
172 return smprintf("%d%%", strength);
173 }
174
175 /* battery percentage */
176 char *
177 battery()
178 {
179 int batt_now;
180 int batt_full;
181 int batt_perc;
182 FILE *fp;
183
184 /* open battery now file, extract and close */
185 if (!(fp = fopen(batterynowfile, "r"))) {
186 fprintf(stderr, "Error opening battery file.");
187 exit(1);
188 }
189 fscanf(fp, "%i", &batt_now);
190 fclose(fp);
191
192 /* extract battery full file, extract and close */
193 if (!(fp = fopen(batteryfullfile, "r"))) {
194 fprintf(stderr, "Error opening battery file.");
195 exit(1);
196 }
197 fscanf(fp, "%i", &batt_full);
198 fclose(fp);
199
200 /* calculate percent */
201 batt_perc = batt_now / (batt_full / 100);
202
203 /* return percent */
204 return smprintf("%d%%", batt_perc);
205 }
206
207 /* date and time */
208 char *
209 datetime()
210 {
211 time_t tm;
212 size_t bufsize = 19;
213 char *buf = malloc(bufsize);
214
215 /* get time in format */
216 time(&tm);
217 if(!strftime(buf, bufsize, timeformat, localtime(&tm))) {
218 fprintf(stderr, "Strftime failed.\n");
219 exit(1);
220 }
221
222 /* return time */
223 return buf;
224 }
225
226 /* cpu percentage */
227 char *
228 cpu_usage()
229 {
230 FILE *fp;
231 long double a[4], b[4], cpu_perc;
232
233 /* open stat file, read and close, do same after 1 second */
234 if (!(fp = fopen("/proc/stat","r"))) {
235 fprintf(stderr, "Error opening stat file.");
236 exit(1);
237 }
238 fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&a[0],&a[1],&a[2],&a[3]);
239 fclose(fp);
240 sleep(1);
241 if (!(fp = fopen("/proc/stat","r"))) {
242 fprintf(stderr, "Error opening stat file.");
243 exit(1);
244 }
245 fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&b[0],&b[1],&b[2],&b[3]);
246 fclose(fp);
247
248 /* calculate average in 1 second */
249 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]));
250
251 /* return avg cpu percentage */
252 return smprintf("%d%%", (int)cpu_perc);
253 }
254
255 /* ram percentage */
256 char *
257 ram_usage()
258 {
259 FILE *fp;
260 long total, free, available;
261 int ram_perc;
262
263 /* read meminfo file, extract and close */
264 if (!(fp = fopen("/proc/meminfo", "r"))) {
265 fprintf(stderr, "Error opening meminfo file.");
266 exit(1);
267 }
268 fscanf(fp, "MemTotal: %ld kB\n", &total);
269 fscanf(fp, "MemFree: %ld kB\n", &free);
270 fscanf(fp, "MemAvailable: %ld kB\n", &available);
271 fclose(fp);
272
273 /* calculate percentage */
274 ram_perc = 100 * (total - available) / total;
275
276 /* return in percent */
277 return smprintf("%d%%",ram_perc);
278 }
279
280 int
281 main()
282 {
283 char status[1024];
284
285 /* open display */
286 if (( dpy = XOpenDisplay(0x0)) == NULL ) {
287 fprintf(stderr, "Cannot open display!\n");
288 exit(1);
289 }
290
291 /* return status every second */
292 for (;;) {
293 sprintf(status, FORMATSTRING, ARGUMENTS);
294 setstatus(status);
295 }
296
297 /* close display */
298 XCloseDisplay(dpy);
299
300 /* exit successfully */
301 return 0;
302 }