diff --git a/Makefile b/Makefile index 0797b83..9b7d4c7 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ PREFIX ?= /usr/local BINPREFIX = ${PREFIX}/bin LIBS = -lasound -lX11 `pkg-config --cflags --libs glib-2.0 dbus-glib-1 audclient` -CFLAGS += -pedantic -Wall -Wextra +CFLAGS += -std=c99 -pedantic -Wall -Wextra debug: CFLAGS += -O0 -g debug: ${PROG} diff --git a/README.md b/README.md index 1248a80..21c46cc 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ DWMST **Forked from TrilbyWhite's dwmStatus:** https://github.com/TrilbyWhite/dwmStatus A great inspiration for many code optimizations has been OK100. Thanks! +The last rewrite also took major inspiration and code from Suckless. This is a hardcoded statusbar for my system and, like Trilby's dwmStatus from which this is forked, it was not meant to be flexible. Flexibility costs memory and processor time. This can, however, be used as a template for your own status bar app. @@ -20,12 +21,8 @@ To built and install, simply run $ make # make clean install -To (re)launch dwmst after suspending your computer, you have to enable the systemd service file: -`systemctl enable dwmst@.service` - ToDo ---- * Code left to clean up: * Alsa; * Improve handling when no battery is present -* Look into empty spaces when Skype/Network is not present diff --git a/dwmst.c b/dwmst.c index cf3a9ea..5962683 100644 --- a/dwmst.c +++ b/dwmst.c @@ -1,185 +1,277 @@ +#include #include #include #include -#include #include +#include #include #include -#include "dwmst.h" +#include "dwmstatus.h" -char *get_aud (char *buf, DBusGProxy *session) { - char *psong = NULL; +static Display *dpy; - psong = audacious_remote_get_playlist_title (session, audacious_remote_get_playlist_pos (session)); - if (psong) { - snprintf (buf, 160, AUD_STR, psong); - free (psong); - } else - buf[0] = '\0'; - return buf; -} +char * +smprintf(char *fmt, ...) { + va_list fmtargs; + char *ret; + int len; -char *get_skype (char *buf) { - if (access (SKYPE_LOCK, F_OK) == 0) - snprintf (buf, 6, SKYPE_STR); - else - buf[0] = '\0'; - return buf; + va_start(fmtargs, fmt); + len = vsnprintf(NULL, 0, fmt, fmtargs); + va_end(fmtargs); + + ret = malloc(++len); + if (ret == NULL) { + perror("malloc"); + exit(1); + } + + va_start(fmtargs, fmt); + vsnprintf(ret, len, fmt, fmtargs); + va_end(fmtargs); + + return ret; } -int is_up (char *device) { +int +is_up (char *device) { char devpath[32], state[5]; FILE *infile; - snprintf (devpath, 32, "/sys/class/net/%s/operstate", device); - if ((infile = fopen (devpath, "r")) != NULL) { - fscanf (infile, "%s", state); fclose (infile); + snprintf(devpath, sizeof(devpath), "/sys/class/net/%s/operstate", device); + infile = fopen(devpath, "r"); + if(infile != NULL) { + fscanf(infile, "%s", state); + fclose(infile); if (strncmp (state, "up", 2) == 0) return 1; } return 0; } -char *get_net (char *buf, struct iwreq wreq, int socket) { - char ssid[30] = ""; +char * +get_aud(DBusGProxy *session) { + char *music = NULL; /*ToDo: free?*/ + int pos; - if (is_up (WIRELESS_DEVICE)) { - wreq.u.essid.pointer = ssid; - wreq.u.essid.length = sizeof (ssid); - ioctl (socket, SIOCGIWESSID, &wreq); - snprintf (buf, 30, WLAN_STR, ssid); - } else if (is_up (WIRED_DEVICE)) - snprintf (buf, 10, LAN_STR); + pos = audacious_remote_get_playlist_pos(session); + music = audacious_remote_get_playlist_title(session, pos); + if(music != NULL) + return smprintf(AUD_STR, music); else - snprintf (buf, 16, NO_CON_STR); - return buf; + return NULL; /*ToDo: fix this*/ } -char *get_volume (char *buf, snd_mixer_t *handle) { - snd_mixer_elem_t *pcm_mixer, *mas_mixer; - snd_mixer_selem_id_t *vol_info, *mute_info; - long vol = 0, max = 0, min = 0; +char * +get_skype(void) { + if(access (SKYPE_LOCK, F_OK) == 0) + return smprintf("%s", SKYPE_STR); + else + return NULL; /*ToDo: fix this*/ +} + +char * +get_net(struct iwreq wreq, int socket) { + if(is_up (WIRELESS_DEVICE)) { + char essid[30]; + + memset(essid, 0, sizeof(essid)); + wreq.u.essid.pointer = essid; + wreq.u.essid.length = sizeof(essid); + ioctl(socket, SIOCGIWESSID, &wreq); + return smprintf(WLAN_STR, essid); + } else if(is_up (WIRED_DEVICE)) + return smprintf("%s", LAN_STR); + else + return smprintf("%s", NO_CON_STR); +} + +char * +get_vol(snd_mixer_t *handle) { int mute = 0, realvol = 0; + long vol = 0, max = 0, min = 0; + snd_mixer_elem_t *pcm_mixer, *max_mixer; + snd_mixer_selem_id_t *vol_info, *mute_info; + + /*ToDo: maybe move all this to main?*/ + snd_mixer_handle_events(handle); + snd_mixer_selem_id_malloc(&vol_info); + snd_mixer_selem_id_malloc(&mute_info); + snd_mixer_selem_id_set_name(vol_info, VOL_CH); + snd_mixer_selem_id_set_name(mute_info, VOL_CH); + pcm_mixer = snd_mixer_find_selem(handle, vol_info); + max_mixer = snd_mixer_find_selem(handle, mute_info); + snd_mixer_selem_get_playback_volume_range(pcm_mixer, &min, &max); + snd_mixer_selem_get_playback_volume(pcm_mixer, 0, &vol); + snd_mixer_selem_get_playback_switch(max_mixer, 0, &mute); + snd_mixer_selem_id_free(vol_info); + snd_mixer_selem_id_free(mute_info); - snd_mixer_handle_events (handle); - snd_mixer_selem_id_malloc (&vol_info); - snd_mixer_selem_id_malloc (&mute_info); - snd_mixer_selem_id_set_name (vol_info, VOL_CH); - snd_mixer_selem_id_set_name (mute_info, VOL_CH); - pcm_mixer = snd_mixer_find_selem (handle, vol_info); - mas_mixer = snd_mixer_find_selem (handle, mute_info); - snd_mixer_selem_get_playback_volume_range ((snd_mixer_elem_t *)pcm_mixer, &min, &max); - snd_mixer_selem_get_playback_volume ((snd_mixer_elem_t *)pcm_mixer, 0, &vol); - snd_mixer_selem_get_playback_switch (mas_mixer, 0, &mute); - if (!mute) - snprintf (buf, 9, VOL_MUTE_STR); + realvol = (vol * 100) / max; + if(mute == 0) + return smprintf(VOL_MUTE_STR, realvol); else { - realvol = (vol * 100) / max; - snprintf (buf, 12, VOL_STR, realvol); + if (realvol < 20) + return smprintf(VOL_LOW_STR, realvol); + else if (realvol > 60) + return smprintf(VOL_HIGH_STR, realvol); + else + return smprintf(VOL_MID_STR, realvol); } - snd_mixer_selem_id_free (vol_info); - snd_mixer_selem_id_free (mute_info); - return buf; } -char *get_battery (char *buf) { - FILE *infile; +char * +get_batt(void) { /*ToDo: fix many strncmps*/ + FILE *f1, *f2, *f3, *f4; char state[11]; - long now = -1, full = -1, voltage = -1, rate = -1; - int perc, hours, minutes, seconds = -1; - - if (access ("/sys/class/power_supply/BAT1/", F_OK) == 0) { - infile = fopen (BATT_STAT, "r"); fscanf (infile, "%s\n", state); fclose (infile); - if (strncmp (state, "Full", 4) == 0) - snprintf (buf, 11, BAT_FULL_STR); - else if (strncmp (state, "Unknown", 7) == 0) - snprintf (buf, 11, BAT_UNK_STR); + + if(access("/sys/class/power_supply/BAT1/", F_OK) != 0) + return smprintf("%s", NO_BAT_STR); + + memset(state, 0, sizeof(state)); + f1 = fopen(BATT_STAT, "r"); + if(f1 != NULL) { + fscanf(f1, "%s\n", state); + fclose(f1); + } else + return NULL; /*ToDo: fix this*/ + + if(strncmp(state, "Full", 4) == 0) + return smprintf("%s", BAT_FULL_STR); + else if(strncmp(state, "Unknown", 7) == 0) + return smprintf("%s", BAT_UNK_STR); + else { + long now = -1, full = -1, voltage = -1, rate = -1; + int perc = -1, seconds = -1, minutes, hours; + + f1 = fopen(BATT_NOW, "r"); + f2 = fopen(BATT_FULL, "r"); + f3 = fopen(BATT_VOLT, "r"); + f4 = fopen(BATT_CNOW, "r"); + if(f1 != NULL && f2 != NULL && f3 != NULL && f4 != NULL) { + fscanf(f1, "%ld\n", &now); fclose(f1); + fscanf(f2, "%ld\n", &full); fclose(f2); + fscanf(f3, "%ld\n", &voltage); fclose(f3); + fscanf(f4, "%ld\n", &rate); fclose(f4); + } + + now = voltage * now; + full = voltage * full; + rate = voltage * rate; + perc = ((float)now * 100) / (float)full; + + if(perc > 100) perc = 100; + if(perc < 0) perc = 0; + + if(strncmp(state, "Charging", 8) == 0) + seconds = 3600 * ((full - now) / rate); + else + seconds = 3600 * (now / rate); + hours = seconds / 3600; + seconds -= 3600 * hours; + minutes = seconds / 60; + seconds -= 60 * minutes; + + if(strncmp(state, "Charging", 8) == 0) + return smprintf(BAT_CHRG_STR, perc, hours, minutes); else { - infile = fopen (BATT_NOW, "r"); fscanf (infile, "%ld\n", &now); fclose (infile); - infile = fopen (BATT_FULL, "r"); fscanf (infile, "%ld\n", &full); fclose (infile); - infile = fopen (BATT_VOLT, "r"); fscanf (infile, "%ld\n", &voltage); fclose (infile); - infile = fopen (BATT_CNOW, "r"); fscanf (infile, "%ld\n", &rate); fclose (infile); - now = ((float)voltage * (float)now); - full = ((float)voltage * (float)full); - rate = ((float)voltage * (float)rate); - perc = (now * 100) / full; - - if (strncmp (state, "Charging", 8) == 0) - seconds = 3600 * (((float)full - (float)now) / (float)rate); + if(perc < 5) + return smprintf(BAT_EMPTY_STR, perc, hours, minutes); + /*notify*/ + else if(perc > 5 && perc < 50) + return smprintf(BAT_LOW_STR, perc, hours, minutes); + else if(perc > 50 && perc < 95) + return smprintf(BAT_HIGH_STR, perc, hours, minutes); else - seconds = 3600 * ((float)now / (float)rate); - hours = seconds / 3600; - seconds -= 3600 * hours; - minutes = seconds / 60; - seconds -= 60 * minutes; - if (strncmp (state, "Charging", 8) == 0) - snprintf (buf, 24, BAT_CHRG_STR, perc, hours, minutes); - else { - /*if (perc < BAT_LOW_P || minutes < BAT_LOW_T) - notify*/ - snprintf (buf, 24, BAT_STR, perc, hours, minutes); - } + return smprintf(BAT_FULL_STR, perc, hours, minutes); } - } else - snprintf (buf, 14, NO_BAT_STR); + } +} - return buf; +void +setstatus(char *str) { + XStoreName(dpy, DefaultRootWindow(dpy), str); + XSync(dpy, False); } -int main(void) { - Display *dpy; - Window root; - char status[256], music[160], skype[6], net[30], volume[12], battery[24]; - int netloops = 60, musicloops = 10; - DBusGProxy *session = NULL; - DBusGConnection *connection = NULL; - int sockfd; + +/*char **/ +void +read_stdin(void) { + char inbuf[256]; + char *status; + + memset(inbuf, 0, sizeof(inbuf)); + if(fgets(inbuf, sizeof(inbuf), stdin) != NULL) { + inbuf[strlen(inbuf) - 1] = '\0'; + status = smprintf("%s", inbuf); + setstatus(status); + free(status); + /*return smprintf("%s", inbuf);*/ + sleep(3); + } + /*return NULL;*/ +} + +int +main(void) { + int sockfd, netloops = 60, musicloops = 60; struct iwreq wreq; snd_mixer_t *handle; + char *status, *pipe, *aud, *skype, *net, *vol, *batt; + DBusGProxy *session = NULL; + DBusGConnection *conn = NULL; - if (!(dpy = XOpenDisplay (NULL))) { - fprintf (stderr, "Error: could not open display.\n"); + if(!(dpy = XOpenDisplay(NULL))) { + fprintf(stderr, "dwmst: cannot open display.\n"); return 1; } - root = XRootWindow (dpy, DefaultScreen (dpy)); - - connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); - session = dbus_g_proxy_new_for_name (connection, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); - memset (&wreq, 0, sizeof (struct iwreq)); - snprintf (wreq.ifr_name, 7, WIRELESS_DEVICE); - sockfd = socket (AF_INET, SOCK_DGRAM, 0); + conn = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + session = dbus_g_proxy_new_for_name(conn, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); - snd_mixer_open (&handle, 0); - snd_mixer_attach (handle, "default"); - snd_mixer_selem_register (handle, NULL, NULL); - snd_mixer_load (handle); + memset(&wreq, 0, sizeof(struct iwreq)); + snprintf(wreq.ifr_name, sizeof(WIRELESS_DEVICE), WIRELESS_DEVICE); /*ToDo: what with multiple devices?*/ + sockfd = socket (AF_INET, SOCK_DGRAM, 0); /*ToDo: what do these mean?*/ - while (1) { - if (++musicloops > 10) { - musicloops = 0; - get_aud (music, session); - } - get_skype (skype); - if (++netloops > 60 && sockfd != -1) { - netloops = 0; - get_net (net, wreq, sockfd); - } - get_volume (volume, handle); - get_battery (battery); + snd_mixer_open(&handle, 0); + snd_mixer_attach(handle, "default"); + snd_mixer_selem_register(handle, NULL, NULL); + snd_mixer_load(handle); - snprintf (status, 256, "%s %s %s %s %s", music, skype, net, volume, battery); + for(;;sleep(INTERVAL)) { + /*pipe = read_stdin(); + if(strlen(pipe) > 2) { + status = smprintf("%s", pipe); + setstatus(status); + free(pipe); + free(status); + sleep(3); + }*/ + /*read_stdin();*/ + if(++musicloops > 60 && session != NULL) + aud = get_aud(session); + skype = get_skype(); + if(++netloops > 60 && sockfd != -1) + net = get_net(wreq, sockfd); + vol = get_vol(handle); + batt = get_batt(); - XStoreName (dpy, root, status); - XFlush (dpy); - sleep (INTERVAL); + status = smprintf("%s %s %s %s %s", aud, skype, net, vol, batt); + setstatus(status); + if(++musicloops > 60 && session != NULL) + free(aud); + free(skype); + if(++netloops > 60 && sockfd != -1) + free(net); + free(vol); + free(batt); + free(status); } - XCloseDisplay (dpy); - dbus_g_connection_unref (connection); - g_object_unref (session); - close (sockfd); - snd_mixer_close (handle); + XCloseDisplay(dpy); + close(sockfd); + snd_mixer_close(handle); return 0; } diff --git a/dwmst.h b/dwmst.h index 5913bc5..e15741b 100644 --- a/dwmst.h +++ b/dwmst.h @@ -12,17 +12,25 @@ #define BATT_VOLT "/sys/class/power_supply/BAT1/voltage_now" #define BATT_CNOW "/sys/class/power_supply/BAT1/power_now" -#define AUD_STR "%s" +#define AUD_STR "\uF240 %s" #define NO_AUD_STR "" -#define SKYPE_STR "Skype" + +#define SKYPE_STR "\uF17E" #define NO_SKYPE_STR "" -#define LAN_STR "Verbonden" -#define WLAN_STR "%s" + +#define LAN_STR "\uF3AC Verbonden" +#define WLAN_STR "\uF405 %s" #define NO_CON_STR "Geen verbinding" -#define VOL_STR "Volume %d%%" -#define VOL_MUTE_STR "Volume M" -#define BAT_FULL_STR "Batterij F" -#define BAT_STR "Batterij D%d%%, %02d:%02d" -#define BAT_CHRG_STR "Batterij C%d%%, %02d:%02d" -#define BAT_UNK_STR "Batterij U" -#define NO_BAT_STR "Geen batterij" + +#define VOL_HIGH_STR "\uF357 %d%%" +#define VOL_MID_STR "\uF359 %d%%" +#define VOL_LOW_STR "\uF358 %d%%" +#define VOL_MUTE_STR "\uF35A %d%%" + +#define BAT_EMPTY_STR "\uF212 %d%%, %02d:%02d" +#define BAT_LOW_STR "\uF215 %d%%, %02d:%02d" +#define BAT_HIGH_STR "\uF214 %d%%, %02d:%02d" +#define BAT_FULL_STR "\uF213 %d%%, %02d:%02d" +#define BAT_CHRG_STR "\uF211 %d%%, %02d:%02d" +#define BAT_UNK_STR "\uF242 U" +#define NO_BAT_STR "\uF200 G"