My slstatus configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

335 lines
7.1 KiB

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