diff options
author | Daniel Caujolle-Bert <f1rmb@users.sourceforge.net> | 2004-03-12 16:19:29 +0000 |
---|---|---|
committer | Daniel Caujolle-Bert <f1rmb@users.sourceforge.net> | 2004-03-12 16:19:29 +0000 |
commit | ec6cb1e218af514e070afe4007d11e3c7a9889ab (patch) | |
tree | a0b2e73119e6f9ca11083f4d239734acecc296d0 | |
parent | e7ef4c2bd94e68660cf5be840c7dc4814871d9e6 (diff) | |
download | xine-lib-ec6cb1e218af514e070afe4007d11e3c7a9889ab.tar.gz xine-lib-ec6cb1e218af514e070afe4007d11e3c7a9889ab.tar.bz2 |
big cleanup/fix of mute status/events. Bastien, can you check if the event thread still lockup on Totem?
CVS patchset: 6244
CVS date: 2004/03/12 16:19:29
-rw-r--r-- | src/audio_out/audio_alsa_out.c | 207 |
1 files changed, 131 insertions, 76 deletions
diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c index 3c443070f..a0f59ed30 100644 --- a/src/audio_out/audio_alsa_out.c +++ b/src/audio_out/audio_alsa_out.c @@ -26,7 +26,7 @@ * (c) 2001 James Courtier-Dutton <James@superbug.demon.co.uk> * * - * $Id: audio_alsa_out.c,v 1.128 2004/03/05 23:44:39 f1rmb Exp $ + * $Id: audio_alsa_out.c,v 1.129 2004/03/12 16:19:29 f1rmb Exp $ */ #ifdef HAVE_CONFIG_H @@ -75,9 +75,11 @@ #define BUFFER_TIME 1000*1000 #define GAP_TOLERANCE 5000 -#define MIXER_MASK_LEFT (1 << 0) -#define MIXER_MASK_RIGHT (1 << 1) -#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT) +#define MIXER_MASK_LEFT 0x0001 +#define MIXER_MASK_RIGHT 0x0002 +#define MIXER_MASK_MUTE 0x0004 +#define MIXER_MASK_STEREO 0x0008 +#define MIXER_HAS_MUTE_SWITCH 0x0010 typedef struct { audio_driver_class_t driver_class; @@ -134,68 +136,108 @@ static int ao_alsa_get_percent_from_volume(long val, long min, long max) { return tmp; } +/* Stolen from alsa-lib */ +static int __snd_mixer_wait(snd_mixer_t *mixer, int timeout) { + struct pollfd spfds[16]; + struct pollfd *pfds = spfds; + int err, count; + + count = snd_mixer_poll_descriptors(mixer, pfds, sizeof(spfds) / sizeof(spfds[0])); + + if (count < 0) + return count; + + if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) { + pfds = malloc(count * sizeof(*pfds)); + + if (!pfds) + return -ENOMEM; + + err = snd_mixer_poll_descriptors(mixer, pfds, (unsigned int) count); + assert(err == count); + } + + err = poll(pfds, (unsigned int) count, timeout); + + if (err < 0) + return -errno; + + return err; +} + /* - * Wait (blocking) till a mixer event happen + * Wait (non blocking) till a mixer event happen */ static void *ao_alsa_handle_event_thread(void *data) { alsa_driver_t *this = (alsa_driver_t *) data; do { - int err, mute, sw, sw2; - long right_vol, left_vol; - - if(snd_mixer_wait(this->mixer.handle, 333) == 0) { + + if(__snd_mixer_wait(this->mixer.handle, 333) > 0) { + int err, mute = 0, swl = 0, swr = 0; + long right_vol, left_vol; + int old_mute; + pthread_mutex_lock(&this->mixer.mutex); - snd_mixer_handle_events(this->mixer.handle); - if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, - &left_vol)) < 0) { + old_mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0; + + if((err = snd_mixer_handle_events(this->mixer.handle)) < 0) { + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + "audio_alsa_out: snd_mixer_handle_events(): %s\n", snd_strerror(err)); + pthread_mutex_unlock(&this->mixer.mutex); + continue; + } + + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &left_vol)) < 0) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); + pthread_mutex_unlock(&this->mixer.mutex); continue; } - if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, - &right_vol)) < 0) { + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_vol)) < 0) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); + pthread_mutex_unlock(&this->mixer.mutex); continue; } - if(snd_mixer_selem_has_playback_switch(this->mixer.elem)) { + if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) { - if(snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - mute = (sw) ? 0 : 1; + if(this->mixer.mute & MIXER_MASK_STEREO) { + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); + mute = (swl) ? 0 : 1; } else { + if (this->mixer.mute & MIXER_MASK_LEFT) - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN && - (this->mixer.mute & MIXER_MASK_RIGHT)) - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &sw2); + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); + + if ((SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) && (this->mixer.mute & MIXER_MASK_RIGHT)) + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr); - mute = (sw || sw2) ? 0 : 1; + mute = (swl || swr) ? 0 : 1; } } - else - mute = (this->mixer.mute) ? 1 : 0; - - if((this->mixer.right_vol != right_vol) || (this->mixer.left_vol != left_vol) || - (this->mixer.mute != mute)) { + + if((this->mixer.right_vol != right_vol) || (this->mixer.left_vol != left_vol) || (old_mute != mute)) { xine_event_t event; xine_audio_level_data_t data; xine_stream_t *stream; this->mixer.right_vol = right_vol; this->mixer.left_vol = left_vol; - this->mixer.mute = (mute) ? MIXER_MASK_STEREO : 0; + if(mute) + this->mixer.mute |= MIXER_MASK_MUTE; + else + this->mixer.mute &= ~MIXER_MASK_MUTE; data.right = ao_alsa_get_percent_from_volume(this->mixer.right_vol, this->mixer.min, this->mixer.max); data.left = ao_alsa_get_percent_from_volume(this->mixer.left_vol, this->mixer.min, this->mixer.max); - data.mute = (this->mixer.mute == MIXER_MASK_STEREO) ? 1 : 0; + data.mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0; event.type = XINE_EVENT_AUDIO_LEVEL; event.data = &data; @@ -209,9 +251,10 @@ static void *ao_alsa_handle_event_thread(void *data) { } pthread_mutex_unlock(&this->class->xine->streams_lock); } + pthread_mutex_unlock(&this->mixer.mutex); } - + } while(1); pthread_exit(NULL); @@ -853,7 +896,8 @@ static int ao_alsa_get_property (ao_driver_t *this_gen, int property) { case AO_PROP_MIXER_VOL: case AO_PROP_PCM_VOL: if(this->mixer.elem) { - + int vol; + pthread_mutex_lock(&this->mixer.mutex); if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, @@ -871,17 +915,24 @@ static int ao_alsa_get_property (ao_driver_t *this_gen, int property) { } __done: + vol = (((ao_alsa_get_percent_from_volume(this->mixer.left_vol, this->mixer.min, this->mixer.max)) + + (ao_alsa_get_percent_from_volume(this->mixer.right_vol, this->mixer.min, this->mixer.max))) /2); pthread_mutex_unlock(&this->mixer.mutex); - - return (((ao_alsa_get_percent_from_volume(this->mixer.left_vol, - this->mixer.min, this->mixer.max)) + - (ao_alsa_get_percent_from_volume(this->mixer.right_vol, - this->mixer.min, this->mixer.max))) /2); + + return vol; } break; case AO_PROP_MUTE_VOL: - return (this->mixer.mute) ? 1 : 0; + { + int mute; + + pthread_mutex_lock(&this->mixer.mutex); + mute = ((this->mixer.mute & MIXER_HAS_MUTE_SWITCH) && (this->mixer.mute & MIXER_MASK_MUTE)) ? 1 : 0; + pthread_mutex_unlock(&this->mixer.mutex); + + return mute; + } break; } @@ -926,32 +977,38 @@ static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value) case AO_PROP_MUTE_VOL: if(this->mixer.elem) { - int sw; - int old_mute = this->mixer.mute; - - pthread_mutex_lock(&this->mixer.mutex); - this->mixer.mute = (value) ? MIXER_MASK_STEREO : 0; - - if ((this->mixer.mute != old_mute) - && snd_mixer_selem_has_playback_switch(this->mixer.elem)) { - if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - snd_mixer_selem_set_playback_switch_all(this->mixer.elem, !sw); - } else { - if (this->mixer.mute & MIXER_MASK_LEFT) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, !sw); - } - if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN && - (this->mixer.mute & MIXER_MASK_RIGHT)) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &sw); - snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, !sw); + if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) { + int swl = 0, swr = 0; + int old_mute; + + pthread_mutex_lock(&this->mixer.mutex); + + old_mute = this->mixer.mute; + if(value) + this->mixer.mute |= MIXER_MASK_MUTE; + else + this->mixer.mute &= ~MIXER_MASK_MUTE; + + if ((this->mixer.mute & MIXER_MASK_MUTE) != (old_mute & MIXER_MASK_MUTE)) { + if(this->mixer.mute & MIXER_MASK_STEREO) { + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); + snd_mixer_selem_set_playback_switch_all(this->mixer.elem, !swl); + } + else { + if (this->mixer.mute & MIXER_MASK_LEFT) { + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); + snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, !swl); + } + if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN && (this->mixer.mute & MIXER_MASK_RIGHT)) { + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr); + snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, !swr); + } } } + + pthread_mutex_unlock(&this->mixer.mutex); } - - pthread_mutex_unlock(&this->mixer.mutex); return value; } return ~value; @@ -1050,7 +1107,7 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { snd_mixer_selem_id_t *sid; int loop = 0; int found; - int sw; + int swl = 0, swr = 0; this->mixer.elem = 0; snd_ctl_card_info_alloca(&hw_info); @@ -1159,24 +1216,23 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { /* Channels mute */ this->mixer.mute = 0; if(snd_mixer_selem_has_playback_switch(this->mixer.elem)) { - + this->mixer.mute |= MIXER_HAS_MUTE_SWITCH; + if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - if(!sw) - this->mixer.mute = MIXER_MASK_STEREO; + this->mixer.mute |= MIXER_MASK_STEREO; + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); } else { - if (this->mixer.mute & MIXER_MASK_LEFT) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw); - if(!sw) - this->mixer.mute |= MIXER_MASK_LEFT; - } - if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN && - (this->mixer.mute & MIXER_MASK_RIGHT)) { - snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &sw); - if(!sw) - this->mixer.mute |= MIXER_MASK_RIGHT; + this->mixer.mute |= MIXER_MASK_LEFT; + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); + + if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) { + this->mixer.mute |= MIXER_MASK_RIGHT; + snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr); } + + if(!swl || !swr) + this->mixer.mute |= MIXER_MASK_MUTE; } this->capabilities |= AO_CAP_MUTE_VOL; @@ -1240,7 +1296,6 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { pthread_create(&this->mixer.thread, &pth_attrs, ao_alsa_handle_event_thread, (void *) this); pthread_attr_destroy(&pth_attrs); } - } static void alsa_passthru_cb (void *user_data, |