diff options
-rw-r--r-- | libao2/ao_coreaudio.c | 2 | ||||
-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_sdl.c | 2 | ||||
-rw-r--r-- | libao2/audio_out.h | 1 | ||||
-rw-r--r-- | mixer.c | 27 | ||||
-rw-r--r-- | mixer.h | 4 | ||||
-rw-r--r-- | mplayer.c | 2 |
10 files changed, 44 insertions, 1 deletions
diff --git a/libao2/ao_coreaudio.c b/libao2/ao_coreaudio.c index 34374f4c9c..50e943e9ac 100644 --- a/libao2/ao_coreaudio.c +++ b/libao2/ao_coreaudio.c @@ -450,6 +450,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 63cc02e92c..b33f2949fd 100644 --- a/libao2/ao_dsound.c +++ b/libao2/ao_dsound.c @@ -420,6 +420,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_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 2e59c42aa4..5a9d52def3 100644 --- a/libao2/audio_out.h +++ b/libao2/audio_out.h @@ -99,6 +99,7 @@ struct ao { int buffer_playable_size; bool initialized; bool untimed; + bool no_persistent_volume; const struct ao_driver *driver; void *priv; struct MPOpts *opts; @@ -76,11 +76,17 @@ static void setvolume_internal(mixer_t *mixer, float l, float r) { struct ao_control_vol vol = {.left = l, .right = r}; if (!mixer->softvol) { + // relies on the driver data being permanent (so ptr stays valid) + mixer->restore_volume = mixer->ao->no_persistent_volume ? + mixer->ao->driver->info->short_name : NULL; if (ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol) != CONTROL_OK) mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] Failed to change audio output volume.\n"); return; } + mixer->restore_volume = "softvol"; + if (!mixer->afilter) + return; // af_volume uses values in dB float db_vals[AF_NCH]; int i; @@ -197,3 +203,24 @@ void mixer_setbalance(mixer_t *mixer, float val) af_pan_balance->control(af_pan_balance, AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val); } + +// Called after the audio filter chain is built or rebuilt. +void mixer_reinit(struct mixer *mixer, struct ao *ao) +{ + mixer->ao = ao; + /* Use checkvolume() to see if softvol needs to be enabled because of + * lacking AO support, but first store values it could overwrite. */ + float left = mixer->vol_l, right = mixer->vol_r; + bool muted = mixer->muted; + checkvolume(mixer); + /* Try to avoid restoring volume stored from one control method with + * another. Especially, restoring softvol volume (typically high) on + * system mixer could have very nasty effects. */ + const char *restore_reason = mixer->softvol ? "softvol" : + mixer->ao->driver->info->short_name; + if (mixer->restore_volume && !strcmp(mixer->restore_volume, + restore_reason)) { + mixer_setvolume(mixer, left, right); + mixer_setmute(mixer, muted); + } +} @@ -32,8 +32,12 @@ typedef struct mixer { float softvol_max; bool muted; float vol_l, vol_r; + /* Contains ao driver name or "softvol" if volume is not persistent + * and needs to be restored after the driver is reinitialized. */ + const char *restore_volume; } mixer_t; +void mixer_reinit(struct mixer *mixer, struct ao *ao); void mixer_getvolume(mixer_t *mixer, float *l, float *r); void mixer_setvolume(mixer_t *mixer, float l, float r); void mixer_incvolume(mixer_t *mixer); @@ -1821,10 +1821,10 @@ void reinit_audio_chain(struct MPContext *mpctx) "Couldn't find matching filter/ao format!\n"); goto init_error; } - mpctx->mixer.ao = ao; mpctx->mixer.volstep = volstep; mpctx->mixer.softvol = opts->softvol; mpctx->mixer.softvol_max = opts->softvol_max; + mixer_reinit(&mpctx->mixer, ao); mpctx->syncing_audio = true; return; |