]> git.sur5r.net Git - i3/i3status/blobdiff - src/print_volume.c
Stop requiring CAP_NET_ADMIN
[i3/i3status] / src / print_volume.c
index 86b3505713303d304d31bff1676c8cd6c20c0c1b..e28a132fdb3ba5ad76710f6c4c342315c19aa4ae 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <err.h>
+#include <ctype.h>
 #include <yajl/yajl_gen.h>
 #include <yajl/yajl_version.h>
 
@@ -37,11 +38,11 @@ static char *apply_volume_format(const char *fmt, char *outwalk, int ivolume) {
             continue;
         }
         if (BEGINS_WITH(walk + 1, "%")) {
-            outwalk += sprintf(outwalk, "%%");
+            outwalk += sprintf(outwalk, "%s", pct_mark);
             walk += strlen("%");
         }
         if (BEGINS_WITH(walk + 1, "volume")) {
-            outwalk += sprintf(outwalk, "%d%%", ivolume);
+            outwalk += sprintf(outwalk, "%d%s", ivolume, pct_mark);
             walk += strlen("volume");
         }
     }
@@ -67,9 +68,12 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
      * index of the PulseAudio sink then force PulseAudio, optionally
      * overriding the default sink */
     if (!strncasecmp(device, "pulse", strlen("pulse"))) {
-        uint32_t sink_idx = device[5] == ':' ? (uint32_t)atoi(device + 6)
-                                             : DEFAULT_SINK_INDEX;
-        int cvolume = pulse_initialize() ? volume_pulseaudio(sink_idx) : 0;
+        uint32_t sink_idx = device[strlen("pulse")] == ':' ? (uint32_t)atoi(device + strlen("pulse:")) : DEFAULT_SINK_INDEX;
+        const char *sink_name = device[strlen("pulse")] == ':' &&
+                                        !isdigit(device[strlen("pulse:")])
+                                    ? device + strlen("pulse:")
+                                    : NULL;
+        int cvolume = pulse_initialize() ? volume_pulseaudio(sink_idx, sink_name) : 0;
         int ivolume = DECOMPOSE_VOLUME(cvolume);
         bool muted = DECOMPOSE_MUTED(cvolume);
         if (muted) {
@@ -85,7 +89,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
         goto out;
     } else if (!strcasecmp(device, "default") && pulse_initialize()) {
         /* no device specified or "default" set */
-        int cvolume = volume_pulseaudio(DEFAULT_SINK_INDEX);
+        int cvolume = volume_pulseaudio(DEFAULT_SINK_INDEX, NULL);
         int ivolume = DECOMPOSE_VOLUME(cvolume);
         bool muted = DECOMPOSE_MUTED(cvolume);
         if (ivolume >= 0) {
@@ -147,7 +151,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
     snd_mixer_selem_id_set_index(sid, mixer_idx);
     snd_mixer_selem_id_set_name(sid, mixer);
     if (!(elem = snd_mixer_find_selem(m, sid))) {
-        fprintf(stderr, "i3status: ALSA: Cannot find mixer %s (index %i)\n",
+        fprintf(stderr, "i3status: ALSA: Cannot find mixer %s (index %u)\n",
                 snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
         snd_mixer_close(m);
         snd_mixer_selem_id_free(sid);
@@ -207,6 +211,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
 
 #if defined(__OpenBSD__)
     int oclass_idx = -1, master_idx = -1, master_mute_idx = -1;
+    int master_next = AUDIO_MIXER_LAST;
     mixer_devinfo_t devinfo, devinfo2;
     mixer_ctrl_t vinfo;
 
@@ -224,12 +229,17 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
 
     devinfo2.index = 0;
     while (ioctl(mixfd, AUDIO_MIXER_DEVINFO, &devinfo2) >= 0) {
-        if ((devinfo2.type == AUDIO_MIXER_VALUE) && (devinfo2.mixer_class == oclass_idx) && (strncmp(devinfo2.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) == 0))
+        if ((devinfo2.type == AUDIO_MIXER_VALUE) && (devinfo2.mixer_class == oclass_idx) && (strncmp(devinfo2.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) == 0)) {
             master_idx = devinfo2.index;
+            master_next = devinfo2.next;
+        }
 
         if ((devinfo2.type == AUDIO_MIXER_ENUM) && (devinfo2.mixer_class == oclass_idx) && (strncmp(devinfo2.label.name, AudioNmute, MAX_AUDIO_DEV_LEN) == 0))
-            master_mute_idx = devinfo2.index;
+            if (master_next == devinfo2.index)
+                master_mute_idx = devinfo2.index;
 
+        if (master_next != AUDIO_MIXER_LAST)
+            master_next = devinfo2.next;
         devinfo2.index++;
     }
 
@@ -242,6 +252,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
 
     vinfo.dev = master_idx;
     vinfo.type = AUDIO_MIXER_VALUE;
+    vinfo.un.value.num_channels = devinfo.un.v.num_channels;
     if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
         goto out;