diff options
author | wm4 <wm4@mplayer2.org> | 2012-01-18 04:21:58 +0100 |
---|---|---|
committer | wm4 <wm4@mplayer2.org> | 2012-01-18 04:21:58 +0100 |
commit | 6e41497d5be1f107c18b2143fa45b3c46d6e95d3 (patch) | |
tree | ba18bcab5e209d3c48658bac046fa48a9c5f053a /libao2 | |
parent | 064f8c2fb656462db9662c67bdbc6716958a4de4 (diff) | |
parent | f7c2ecebccc4b3c5d6299aee5b8f4d382fa78987 (diff) | |
download | mpv-6e41497d5be1f107c18b2143fa45b3c46d6e95d3.tar.bz2 mpv-6e41497d5be1f107c18b2143fa45b3c46d6e95d3.tar.xz |
Merge branch 'softvol' into my_master
Diffstat (limited to 'libao2')
-rw-r--r-- | libao2/ao_alsa.c | 68 | ||||
-rw-r--r-- | libao2/ao_coreaudio.c | 8 | ||||
-rw-r--r-- | libao2/ao_dsound.c | 2 | ||||
-rw-r--r-- | libao2/ao_esd.c | 2 | ||||
-rw-r--r-- | libao2/ao_nas.c | 2 | ||||
-rw-r--r-- | libao2/ao_openal.c | 1 | ||||
-rw-r--r-- | libao2/ao_pulse.c | 55 | ||||
-rw-r--r-- | libao2/ao_sdl.c | 2 | ||||
-rw-r--r-- | libao2/audio_out.h | 14 |
9 files changed, 109 insertions, 45 deletions
diff --git a/libao2/ao_alsa.c b/libao2/ao_alsa.c index 1806a36d56..61837066d5 100644 --- a/libao2/ao_alsa.c +++ b/libao2/ao_alsa.c @@ -106,6 +106,8 @@ static int control(int cmd, void *arg) switch(cmd) { case AOCONTROL_QUERY_FORMAT: return CONTROL_TRUE; + case AOCONTROL_GET_MUTE: + case AOCONTROL_SET_MUTE: case AOCONTROL_GET_VOLUME: case AOCONTROL_SET_VOLUME: { @@ -116,7 +118,7 @@ static int control(int cmd, void *arg) snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; - char *mix_name = "PCM"; + char *mix_name = "Master"; char *card = "default"; int mix_index = 0; @@ -192,16 +194,15 @@ static int control(int cmd, void *arg) snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax); f_multi = (100 / (float)(pmax - pmin)); - if (cmd == AOCONTROL_SET_VOLUME) { - + switch (cmd) { + case AOCONTROL_SET_VOLUME: { set_vol = vol->left / f_multi + pmin + 0.5; //setting channels if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol)) < 0) { mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] Error setting left channel, %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return CONTROL_ERROR; + goto mixer_error; } mp_msg(MSGT_AO,MSGL_DBG2,"left=%li, ", set_vol); @@ -210,33 +211,52 @@ static int control(int cmd, void *arg) if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol)) < 0) { mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] Error setting right channel, %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return CONTROL_ERROR; + goto mixer_error; } mp_msg(MSGT_AO,MSGL_DBG2,"right=%li, pmin=%li, pmax=%li, mult=%f\n", set_vol, pmin, pmax, f_multi); - - if (snd_mixer_selem_has_playback_switch(elem)) { - int lmute = (vol->left == 0.0); - int rmute = (vol->right == 0.0); - if (snd_mixer_selem_has_playback_switch_joined(elem)) { - lmute = rmute = lmute && rmute; - } else { - snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !rmute); - } - snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !lmute); + break; + } + case AOCONTROL_GET_VOLUME: { + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol); + vol->left = (get_vol - pmin) * f_multi; + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol); + vol->right = (get_vol - pmin) * f_multi; + mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right); + break; + } + case AOCONTROL_SET_MUTE: { + if (!snd_mixer_selem_has_playback_switch(elem)) + goto mixer_error; + bool m_l = vol->left == 0.0f, m_r = vol->right == 0.0f; + if (snd_mixer_selem_has_playback_switch_joined(elem)) { + m_l = m_l || m_r; + } else { + snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !m_r); } + snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !m_l); + break; + } + case AOCONTROL_GET_MUTE: { + if (!snd_mixer_selem_has_playback_switch(elem)) + goto mixer_error; + int tmp = 1; + snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp); + vol->left = tmp ? 1.0f : 0.0f; + if (snd_mixer_selem_has_playback_switch_joined(elem)) { + vol->right = vol->left; + } else { + snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp); + vol->right = tmp ? 1.0f : 0.0f; + } + break; } - else { - snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol); - vol->left = (get_vol - pmin) * f_multi; - snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol); - vol->right = (get_vol - pmin) * f_multi; - - mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right); } snd_mixer_close(handle); return CONTROL_OK; + mixer_error: + snd_mixer_close(handle); + return CONTROL_ERROR; } } //end switch diff --git a/libao2/ao_coreaudio.c b/libao2/ao_coreaudio.c index 34374f4c9c..d1a93c85e2 100644 --- a/libao2/ao_coreaudio.c +++ b/libao2/ao_coreaudio.c @@ -169,7 +169,11 @@ Float32 vol; control_vol = (ao_control_vol_t*)arg; if (ao->b_digital) { // Digital output has no volume adjust. - return CONTROL_FALSE; + int vol = ao->b_muted ? 0 : 100; + *control_vol = (ao_control_vol_t) { + .left = vol, .right = vol, + }; + return CONTROL_TRUE; } err = AudioUnitGetParameter(ao->theOutputUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &vol); @@ -450,6 +454,8 @@ int device_id, display_help = 0; ao->b_revert = 0; ao->b_changed_mixing = 0; + global_ao->no_persistent_volume = true; + if (device_id == 0) { /* Find the ID of the default Device. */ err = GetAudioProperty(kAudioObjectSystemObject, diff --git a/libao2/ao_dsound.c b/libao2/ao_dsound.c index 605b0f16e0..a7d30ec357 100644 --- a/libao2/ao_dsound.c +++ b/libao2/ao_dsound.c @@ -418,6 +418,8 @@ static int init(int rate, int channels, int format, int flags) int res; if (!InitDirectSound()) return 0; + global_ao->no_persistent_volume = true; + // ok, now create the buffers WAVEFORMATEXTENSIBLE wformat; DSBUFFERDESC dsbpridesc; diff --git a/libao2/ao_esd.c b/libao2/ao_esd.c index d5423991bd..e7c6701aa0 100644 --- a/libao2/ao_esd.c +++ b/libao2/ao_esd.c @@ -164,6 +164,8 @@ static int init(int rate_hz, int channels, int format, int flags) float lag_seconds, lag_net = 0., lag_serv; struct timeval proto_start, proto_end; + global_ao->no_persistent_volume = true; + if (esd_fd < 0) { esd_fd = esd_open_sound(server); if (esd_fd < 0) { diff --git a/libao2/ao_nas.c b/libao2/ao_nas.c index fb49c5e60e..d3274df9a5 100644 --- a/libao2/ao_nas.c +++ b/libao2/ao_nas.c @@ -424,6 +424,8 @@ static int init(int rate,int channels,int format,int flags) (void)flags; /* shut up 'unused parameter' warning */ + global_ao->no_persistent_volume = true; + nas_data=malloc(sizeof(struct ao_nas_data)); memset(nas_data, 0, sizeof(struct ao_nas_data)); diff --git a/libao2/ao_openal.c b/libao2/ao_openal.c index e425b5769c..490aac0eb8 100644 --- a/libao2/ao_openal.c +++ b/libao2/ao_openal.c @@ -108,6 +108,7 @@ static int init(int rate, int channels, int format, int flags) { const opt_t subopts[] = { {NULL} }; + global_ao->no_persistent_volume = true; if (subopt_parse(ao_subdevice, subopts) != 0) { print_help(); return 0; diff --git a/libao2/ao_pulse.c b/libao2/ao_pulse.c index a07bf31da0..24a448b5f9 100644 --- a/libao2/ao_pulse.c +++ b/libao2/ao_pulse.c @@ -21,6 +21,7 @@ */ #include <string.h> +#include <stdlib.h> #include <pulse/pulseaudio.h> @@ -342,42 +343,49 @@ static float get_delay(void) { } /** A callback function that is called when the - * pa_context_get_sink_input_info() operation completes. Saves the - * volume field of the specified structure to the global variable volume. */ + * pa_context_get_sink_input_info() operation completes. */ static void info_func(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { - struct pa_cvolume *volume = userdata; + struct pa_sink_input_info *pi = userdata; if (is_last < 0) { GENERIC_ERR_MSG(context, "Failed to get sink input info"); return; } if (!i) return; - *volume = i->volume; + *pi = *i; pa_threaded_mainloop_signal(mainloop, 0); } static int control(int cmd, void *arg) { switch (cmd) { + case AOCONTROL_GET_MUTE: // fallthrough case AOCONTROL_GET_VOLUME: { + struct pa_sink_input_info pi; ao_control_vol_t *vol = arg; uint32_t devidx = pa_stream_get_index(stream); - struct pa_cvolume volume; pa_threaded_mainloop_lock(mainloop); - if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, &volume))) { + if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, &pi))) { GENERIC_ERR_MSG(context, "pa_stream_get_sink_input_info() failed"); return CONTROL_ERROR; } - - if (volume.channels != 2) - vol->left = vol->right = pa_cvolume_avg(&volume)*100/PA_VOLUME_NORM; - else { - vol->left = volume.values[0]*100/PA_VOLUME_NORM; - vol->right = volume.values[1]*100/PA_VOLUME_NORM; + // Warning: some information in pi might be unaccessible, because + // we naively copied the struct, without updating pointers etc. + // Pointers might point to invalid data, accessors might fail. + if (cmd == AOCONTROL_GET_VOLUME) { + if (pi.volume.channels != 2) + vol->left = vol->right = pa_cvolume_avg(&pi.volume)*100/PA_VOLUME_NORM; + else { + vol->left = pi.volume.values[0]*100/PA_VOLUME_NORM; + vol->right = pi.volume.values[1]*100/PA_VOLUME_NORM; + } + } else if (cmd == AOCONTROL_GET_MUTE) { + vol->left = vol->right = pi.mute ? 0.0f : 1.0f; } return CONTROL_OK; } + case AOCONTROL_SET_MUTE: // fallthrough case AOCONTROL_SET_VOLUME: { const ao_control_vol_t *vol = arg; pa_operation *o; @@ -392,12 +400,23 @@ static int control(int cmd, void *arg) { } pa_threaded_mainloop_lock(mainloop); - o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL); - if (!o) { - pa_threaded_mainloop_unlock(mainloop); - GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed"); - return CONTROL_ERROR; - } + if (cmd == AOCONTROL_SET_VOLUME) { + o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL); + if (!o) { + pa_threaded_mainloop_unlock(mainloop); + GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed"); + return CONTROL_ERROR; + } + } else if (cmd == AOCONTROL_SET_MUTE) { + int mute = vol->left == 0.0f || vol->right == 0.0f; + o = pa_context_set_sink_input_mute(context, pa_stream_get_index(stream), mute, NULL, NULL); + if (!o) { + pa_threaded_mainloop_unlock(mainloop); + GENERIC_ERR_MSG(context, "pa_context_set_sink_input_mute() failed"); + return CONTROL_ERROR; + } + } else + abort(); /* We don't wait for completion here */ pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); diff --git a/libao2/ao_sdl.c b/libao2/ao_sdl.c index e9ae7298d5..6ff8b83cb3 100644 --- a/libao2/ao_sdl.c +++ b/libao2/ao_sdl.c @@ -135,6 +135,8 @@ static int init(int rate,int channels,int format,int flags){ /* SDL Audio Specifications */ SDL_AudioSpec aspec, obtained; + global_ao->no_persistent_volume = true; + /* Allocate ring-buffer memory */ buffer = av_fifo_alloc(BUFFSIZE); diff --git a/libao2/audio_out.h b/libao2/audio_out.h index e96e123700..c5ddb5bf60 100644 --- a/libao2/audio_out.h +++ b/libao2/audio_out.h @@ -78,6 +78,7 @@ struct ao { int buffer_playable_size; bool initialized; bool untimed; + bool no_persistent_volume; const struct ao_driver *driver; void *priv; }; @@ -96,10 +97,19 @@ void list_audio_out(void); #define AOCONTROL_SET_DEVICE 1 #define AOCONTROL_GET_DEVICE 2 #define AOCONTROL_QUERY_FORMAT 3 /* test for availabilty of a format */ +// Uses ao_control_vol_t* as arg. +// If the volume controls are joint, the average of both volumes should be used. #define AOCONTROL_GET_VOLUME 4 #define AOCONTROL_SET_VOLUME 5 -#define AOCONTROL_SET_PLUGIN_DRIVER 6 -#define AOCONTROL_SET_PLUGIN_LIST 7 +// Uses ao_control_vol_t* as arg. +// left==0.0f means muted, left==1.0f means not muted (right likewise) +// Other values between are invalid. +// If the mtue controls are joint, the output should be muted if either of the +// two channels are muted. +#define AOCONTROL_GET_MUTE 6 +#define AOCONTROL_SET_MUTE 7 +#define AOCONTROL_SET_PLUGIN_DRIVER 8 +#define AOCONTROL_SET_PLUGIN_LIST 9 #define AOPLAY_FINAL_CHUNK 1 |