diff options
| author | oblique | 2013-05-12 20:44:27 +0300 | 
|---|---|---|
| committer | Michael Stapelberg | 2013-05-19 19:48:07 +0200 | 
| commit | 8445d6a929303ca8d63f8d04fd7594a05a2734d6 (patch) | |
| tree | d6e50a88b5556cb9a9018d444732ba90b061d2b2 | |
| parent | fix #1017: i3status uses generic battery instance (diff) | |
print_volume(linux): Open a new mixer every time.
This fix the following bug:
    If you switch your sound card on-the-fly, print_volume continued to
    use the old sound card.
| -rw-r--r-- | src/print_volume.c | 155 | 
1 files changed, 52 insertions, 103 deletions
| diff --git a/src/print_volume.c b/src/print_volume.c index d3a9708..d84b3ec 100644 --- a/src/print_volume.c +++ b/src/print_volume.c @@ -26,29 +26,6 @@  #include "i3status.h"  #include "queue.h" -#ifdef LINUX -struct mixer_hdl { -	char *device; -	char *mixer; -	int mixer_idx; -	snd_mixer_selem_id_t *sid; -	snd_mixer_t *m; -	snd_mixer_elem_t *elem; -	long min; -	long max; - -	TAILQ_ENTRY(mixer_hdl) handles; -}; - -TAILQ_HEAD(handles_head, mixer_hdl) cached = TAILQ_HEAD_INITIALIZER(cached); - -static void free_hdl(struct mixer_hdl *hdl) { -	free(hdl->device); -	free(hdl->mixer); -	free(hdl); -} -#endif -  void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *device, const char *mixer, int mixer_idx) {          char *outwalk = buffer;  	int pbval = 1; @@ -61,100 +38,69 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *                  free(instance);          }  #ifdef LINUX -	/* Check if we already opened the mixer and get the handle -	 * from cache if so */ -	bool found = false;  	int err; -	struct mixer_hdl *hdl; -	TAILQ_FOREACH(hdl, &cached, handles) { -		if (strcmp(hdl->device, device) != 0 || -		    strcmp(hdl->mixer, mixer) != 0 || -		    hdl->mixer_idx != mixer_idx) -			continue; -		found = true; -		break; -	} - -	if (!found) { -		if ((hdl = calloc(sizeof(struct mixer_hdl), 1)) == NULL) -			goto out; - -		if ((hdl->device = strdup(device)) == NULL) { -			free(hdl); -			goto out; -		} - -		if ((hdl->mixer = strdup(mixer)) == NULL) { -			free(hdl->device); -			free(hdl); -			goto out; -		} - -		hdl->mixer_idx = mixer_idx; -		snd_mixer_selem_id_malloc(&(hdl->sid)); -		if (hdl->sid == NULL) { -			free_hdl(hdl); -			goto out; -		} +	snd_mixer_t *m; +	snd_mixer_selem_id_t *sid; +	snd_mixer_elem_t *elem; +	long min, max, val; +	int avg; -		if ((err = snd_mixer_open(&(hdl->m), 0)) < 0) { -			fprintf(stderr, "i3status: ALSA: Cannot open mixer: %s\n", snd_strerror(err)); -			free_hdl(hdl); -			goto out; -		} +	if ((err = snd_mixer_open(&m, 0)) < 0) { +		fprintf(stderr, "i3status: ALSA: Cannot open mixer: %s\n", snd_strerror(err)); +		goto out; +	} -		/* Attach this mixer handle to the given device */ -		if ((err = snd_mixer_attach(hdl->m, device)) < 0) { -			fprintf(stderr, "i3status: ALSA: Cannot attach mixer to device: %s\n", snd_strerror(err)); -			snd_mixer_close(hdl->m); -			free_hdl(hdl); -			goto out; -		} +	/* Attach this mixer handle to the given device */ +	if ((err = snd_mixer_attach(m, device)) < 0) { +		fprintf(stderr, "i3status: ALSA: Cannot attach mixer to device: %s\n", snd_strerror(err)); +		snd_mixer_close(m); +		goto out; +	} -		/* Register this mixer */ -		if ((err = snd_mixer_selem_register(hdl->m, NULL, NULL)) < 0) { -			fprintf(stderr, "i3status: ALSA: snd_mixer_selem_register: %s\n", snd_strerror(err)); -			snd_mixer_close(hdl->m); -			free_hdl(hdl); -			goto out; -		} +	/* Register this mixer */ +	if ((err = snd_mixer_selem_register(m, NULL, NULL)) < 0) { +		fprintf(stderr, "i3status: ALSA: snd_mixer_selem_register: %s\n", snd_strerror(err)); +		snd_mixer_close(m); +		goto out; +	} -		if ((err = snd_mixer_load(hdl->m)) < 0) { -			fprintf(stderr, "i3status: ALSA: snd_mixer_load: %s\n", snd_strerror(err)); -			snd_mixer_close(hdl->m); -			free_hdl(hdl); -			goto out; -		} +	if ((err = snd_mixer_load(m)) < 0) { +		fprintf(stderr, "i3status: ALSA: snd_mixer_load: %s\n", snd_strerror(err)); +		snd_mixer_close(m); +		goto out; +	} -		/* Find the given mixer */ -		snd_mixer_selem_id_set_index(hdl->sid, mixer_idx); -		snd_mixer_selem_id_set_name(hdl->sid, mixer); -		if (!(hdl->elem = snd_mixer_find_selem(hdl->m, hdl->sid))) { -			fprintf(stderr, "i3status: ALSA: Cannot find mixer %s (index %i)\n", -				snd_mixer_selem_id_get_name(hdl->sid), snd_mixer_selem_id_get_index(hdl->sid)); -			snd_mixer_close(hdl->m); -			free_hdl(hdl); -			goto out; -		} +	snd_mixer_selem_id_malloc(&sid); +	if (sid == NULL) { +		snd_mixer_close(m); +		goto out; +	} -		/* Get the volume range to convert the volume later */ -		snd_mixer_selem_get_playback_volume_range(hdl->elem, &(hdl->min), &(hdl->max)); -		TAILQ_INSERT_TAIL(&cached, hdl, handles); +	/* Find the given mixer */ +	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", +			snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); +		snd_mixer_close(m); +		snd_mixer_selem_id_free(sid); +		goto out;  	} -	long val; -	snd_mixer_handle_events (hdl->m); -	snd_mixer_selem_get_playback_volume (hdl->elem, 0, &val); -	int avg; -	if (hdl->max != 100) { -		float avgf = ((float)val / hdl->max) * 100; +	/* Get the volume range to convert the volume later */ +	snd_mixer_selem_get_playback_volume_range(elem, &min, &max); + +	snd_mixer_handle_events (m); +	snd_mixer_selem_get_playback_volume (elem, 0, &val); +	if (max != 100) { +		float avgf = ((float)val / max) * 100;  		avg = (int)avgf;  		avg = (avgf - avg < 0.5 ? avg : (avg+1));  	} else avg = (int)val;  	/* Check for mute */ -	if (snd_mixer_selem_has_playback_switch(hdl->elem)) { -		if ((err = snd_mixer_selem_get_playback_switch(hdl->elem, 0, &pbval)) < 0) +	if (snd_mixer_selem_has_playback_switch(elem)) { +		if ((err = snd_mixer_selem_get_playback_switch(elem, 0, &pbval)) < 0)  			fprintf (stderr, "i3status: ALSA: playback_switch: %s\n", snd_strerror(err));  		if (!pbval)  {  			START_COLOR("color_degraded"); @@ -162,6 +108,9 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *  		}  	} +	snd_mixer_close(m); +	snd_mixer_selem_id_free(sid); +  	const char *walk = fmt;  	for (; *walk != '\0'; walk++) {  		if (*walk != '%') { | 
