diff --git a/i3status.c b/i3status.c index 401db89..2bc6410 100644 --- a/i3status.c +++ b/i3status.c @@ -820,11 +820,17 @@ int main(int argc, char *argv[]) { CASE_SEC_TITLE("volume") { SEC_OPEN_MAP("volume"); - print_volume(json_gen, buffer, cfg_getstr(sec, "format"), - cfg_getstr(sec, "format_muted"), - cfg_getstr(sec, "device"), - cfg_getstr(sec, "mixer"), - cfg_getint(sec, "mixer_idx")); + volume_ctx_t ctx = { + .json_gen = json_gen, + .buf = buffer, + .buflen = sizeof(buffer), + .fmt = cfg_getstr(sec, "format"), + .fmt_muted = cfg_getstr(sec, "format_muted"), + .device = cfg_getstr(sec, "device"), + .mixer = cfg_getstr(sec, "mixer"), + .mixer_idx = cfg_getint(sec, "mixer_idx"), + }; + print_volume(&ctx); SEC_CLOSE_MAP; } diff --git a/include/i3status.h b/include/i3status.h index e87eb5c..6d7fbc6 100644 --- a/include/i3status.h +++ b/include/i3status.h @@ -326,7 +326,20 @@ void print_eth_info(eth_info_ctx_t *ctx); void print_load(yajl_gen json_gen, char *buffer, const char *format, const char *format_above_threshold, const float max_threshold); void print_memory(yajl_gen json_gen, char *buffer, const char *format, const char *format_degraded, const char *threshold_degraded, const char *threshold_critical, const char *memory_used_method, const char *unit, const int decimals); -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); + +typedef struct { + yajl_gen json_gen; + char *buf; + const size_t buflen; + const char *fmt; + const char *fmt_muted; + const char *device; + const char *mixer; + int mixer_idx; +} volume_ctx_t; + +void print_volume(volume_ctx_t *ctx); + bool process_runs(const char *path); int volume_pulseaudio(uint32_t sink_idx, const char *sink_name); bool description_pulseaudio(uint32_t sink_idx, const char *sink_name, char buffer[MAX_SINK_DESCRIPTION_LEN]); diff --git a/src/print_volume.c b/src/print_volume.c index 0331ed5..3d2cc92 100644 --- a/src/print_volume.c +++ b/src/print_volume.c @@ -47,10 +47,10 @@ fprintf(stderr, "i3status: ALSA: " #channel "_switch: %s\n", snd_strerror(err)); \ if (!pbval) { \ START_COLOR("color_degraded"); \ - fmt = fmt_muted; \ + ctx->fmt = ctx->fmt_muted; \ } -static char *apply_volume_format(const char *fmt, char *buffer, int ivolume, const char *devicename) { +static char *apply_volume_format(const char *fmt, int ivolume, const char *devicename) { char string_volume[STRING_SIZE]; snprintf(string_volume, STRING_SIZE, "%d%s", ivolume, pct_mark); @@ -61,19 +61,18 @@ static char *apply_volume_format(const char *fmt, char *buffer, int ivolume, con {.name = "%devicename", .value = devicename}}; const size_t num = sizeof(placeholders) / sizeof(placeholder_t); - buffer = format_placeholders(fmt, &placeholders[0], num); - - return buffer; + return format_placeholders(fmt, &placeholders[0], num); } -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; +void print_volume(volume_ctx_t *ctx) { + char *outwalk = ctx->buf; int pbval = 1; +#define json_gen ctx->json_gen /* 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); + asprintf(&instance, "%s.%s.%d", ctx->device, ctx->mixer, ctx->mixer_idx); INSTANCE(instance); free(instance); } @@ -84,11 +83,11 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * /* 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[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:") + if (!strncasecmp(ctx->device, "pulse", strlen("pulse"))) { + uint32_t sink_idx = ctx->device[strlen("pulse")] == ':' ? (uint32_t)atoi(ctx->device + strlen("pulse:")) : DEFAULT_SINK_INDEX; + const char *sink_name = ctx->device[strlen("pulse")] == ':' && + !isdigit(ctx->device[strlen("pulse:")]) + ? ctx->device + strlen("pulse:") : NULL; int cvolume = 0; char description[MAX_SINK_DESCRIPTION_LEN] = {'\0'}; @@ -111,12 +110,13 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * /* negative result means error, stick to 0 */ if (ivolume < 0) ivolume = 0; - buffer = apply_volume_format(muted ? fmt_muted : fmt, - buffer, - ivolume, - description); + char *formatted = apply_volume_format(muted ? ctx->fmt_muted : ctx->fmt, + ivolume, + description); + OUTPUT_FORMATTED; + free(formatted); goto out_with_format; - } else if (!strcasecmp(device, "default") && pulse_initialize()) { + } else if (!strcasecmp(ctx->device, "default") && pulse_initialize()) { /* no device specified or "default" set */ char description[MAX_SINK_DESCRIPTION_LEN]; bool success = description_pulseaudio(DEFAULT_SINK_INDEX, NULL, description); @@ -128,10 +128,11 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * START_COLOR("color_degraded"); pbval = 0; } - buffer = apply_volume_format(muted ? fmt_muted : fmt, - buffer, - ivolume, - description); + char *formatted = apply_volume_format(muted ? ctx->fmt_muted : ctx->fmt, + ivolume, + description); + OUTPUT_FORMATTED; + free(formatted); goto out_with_format; } /* negative result or NULL description means error, fail PulseAudio attempt */ @@ -157,7 +158,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * } /* Attach this mixer handle to the given device */ - if ((err = snd_mixer_attach(m, device)) < 0) { + if ((err = snd_mixer_attach(m, ctx->device)) < 0) { fprintf(stderr, "i3status: ALSA: Cannot attach mixer to device: %s\n", snd_strerror(err)); snd_mixer_close(m); goto out; @@ -183,8 +184,8 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * } /* Find the given mixer */ - snd_mixer_selem_id_set_index(sid, mixer_idx); - snd_mixer_selem_id_set_name(sid, mixer); + snd_mixer_selem_id_set_index(sid, ctx->mixer_idx); + snd_mixer_selem_id_set_name(sid, ctx->mixer); if (!(elem = snd_mixer_find_selem(m, sid))) { 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)); @@ -195,7 +196,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * /* Get the volume range to convert the volume later */ snd_mixer_handle_events(m); - if (!strncasecmp(mixer, "capture", strlen("capture"))) { + if (!strncasecmp(ctx->mixer, "capture", strlen("capture"))) { ALSA_VOLUME(capture) } else { ALSA_VOLUME(playback) @@ -234,7 +235,9 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * ALSA_MUTE_SWITCH(capture) } - buffer = apply_volume_format(fmt, buffer, avg, mixer_name); + char *formatted = apply_volume_format(ctx->fmt, avg, mixer_name); + OUTPUT_FORMATTED; + free(formatted); snd_mixer_close(m); snd_mixer_selem_id_free(sid); @@ -357,12 +360,11 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char * out: if (!pbval) END_COLOR; - OUTPUT_FULL_TEXT(buffer); + OUTPUT_FULL_TEXT(ctx->buf); return; out_with_format: if (!pbval) END_COLOR; - OUTPUT_FULL_TEXT(buffer); - free(buffer); + OUTPUT_FULL_TEXT(ctx->buf); }