#include "i3status.h"
#include "queue.h"
+static char *apply_volume_format(const char *fmt, char *outwalk, int ivolume) {
+ const char *walk = fmt;
+
+ for (; *walk != '\0'; walk++) {
+ if (*walk != '%') {
+ *(outwalk++) = *walk;
+ continue;
+ }
+ if (BEGINS_WITH(walk + 1, "%")) {
+ outwalk += sprintf(outwalk, "%%");
+ walk += strlen("%");
+ }
+ if (BEGINS_WITH(walk + 1, "volume")) {
+ outwalk += sprintf(outwalk, "%d%%", ivolume);
+ walk += strlen("volume");
+ }
+ }
+ return outwalk;
+}
+
void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_muted, const char *device, const char *mixer, int mixer_idx) {
char *outwalk = buffer;
int pbval = 1;
- /* Printing volume only works with ALSA at the moment */
+ /* Printing volume works with ALSA and PulseAudio at the moment */
if (output_format == O_I3BAR) {
char *instance;
asprintf(&instance, "%s.%s.%d", device, mixer, mixer_idx);
INSTANCE(instance);
free(instance);
}
+
+ /* Try PulseAudio first */
+
+ /* If the device name has the format "pulse[:N]" where N is the
+ * 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;
+ int ivolume = DECOMPOSE_VOLUME(cvolume);
+ bool muted = DECOMPOSE_MUTED(cvolume);
+ if (muted) {
+ START_COLOR("color_degraded");
+ pbval = 0;
+ }
+ /* negative result means error, stick to 0 */
+ if (ivolume < 0)
+ ivolume = 0;
+ outwalk = apply_volume_format(muted ? fmt_muted : fmt,
+ outwalk,
+ ivolume);
+ goto out;
+ } else if (!strcasecmp(device, "default") && pulse_initialize()) {
+ /* no device specified or "default" set */
+ int cvolume = volume_pulseaudio(DEFAULT_SINK_INDEX);
+ int ivolume = DECOMPOSE_VOLUME(cvolume);
+ bool muted = DECOMPOSE_MUTED(cvolume);
+ if (ivolume >= 0) {
+ if (muted) {
+ START_COLOR("color_degraded");
+ pbval = 0;
+ }
+ outwalk = apply_volume_format(muted ? fmt_muted : fmt,
+ outwalk,
+ ivolume);
+ goto out;
+ }
+ /* negative result means error, fail PulseAudio attempt */
+ }
+/* If some other device was specified or PulseAudio is not detected,
+ * proceed to ALSA / OSS */
+
#ifdef LINUX
int err;
snd_mixer_t *m;
snd_mixer_close(m);
snd_mixer_selem_id_free(sid);
- const char *walk = fmt;
- for (; *walk != '\0'; walk++) {
- if (*walk != '%') {
- *(outwalk++) = *walk;
- continue;
- }
- if (BEGINS_WITH(walk + 1, "%")) {
- outwalk += sprintf(outwalk, "%%");
- walk += strlen("%");
- }
- if (BEGINS_WITH(walk + 1, "volume")) {
- outwalk += sprintf(outwalk, "%d%%", avg);
- walk += strlen("volume");
- }
- }
+ outwalk = apply_volume_format(fmt, outwalk, avg);
+
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
char *mixerpath;
pbval = 0;
}
- const char *walk = fmt;
- for (; *walk != '\0'; walk++) {
- if (*walk != '%') {
- *(outwalk++) = *walk;
- continue;
- }
- if (BEGINS_WITH(walk + 1, "%")) {
- outwalk += sprintf(outwalk, "%%");
- walk += strlen("%");
- }
- if (BEGINS_WITH(walk + 1, "volume")) {
- outwalk += sprintf(outwalk, "%d%%", vol & 0x7f);
- walk += strlen("volume");
- }
- }
+ outwalk = apply_volume_format(fmt, outwalk, vol & 0x7f);
close(mixfd);
#endif