summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libao2/ao_coreaudio.c2
-rw-r--r--libao2/ao_dsound.c2
-rw-r--r--libao2/ao_esd.c2
-rw-r--r--libao2/ao_nas.c2
-rw-r--r--libao2/ao_openal.c1
-rw-r--r--libao2/ao_sdl.c2
-rw-r--r--libao2/audio_out.h1
-rw-r--r--mixer.c27
-rw-r--r--mixer.h4
-rw-r--r--mplayer.c2
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;
diff --git a/mixer.c b/mixer.c
index 0c92447c62..b231563026 100644
--- a/mixer.c
+++ b/mixer.c
@@ -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);
+ }
+}
diff --git a/mixer.h b/mixer.h
index 0c6d6a91db..fc5b6c1e71 100644
--- a/mixer.h
+++ b/mixer.h
@@ -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);
diff --git a/mplayer.c b/mplayer.c
index 7696b92ce8..9140b16bca 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -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;