summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_wasapi.c
diff options
context:
space:
mode:
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-11 02:50:49 -0300
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-11 16:37:21 -0300
commitf8bdada77f992410deb4fc12652cf406d95e3657 (patch)
tree7d47a7100c192cdbba55dbe05962e47d47b52ca6 /audio/out/ao_wasapi.c
parentf3e9b9462210021286bfbe98eef228ab74c8b490 (diff)
downloadmpv-f8bdada77f992410deb4fc12652cf406d95e3657.tar.bz2
mpv-f8bdada77f992410deb4fc12652cf406d95e3657.tar.xz
ao_wasapi: Implement per-application mixing
The volume controls in mpv now affect the session's volume (the application's volume in the mixer). Since we do not request a non-persistent session, the volume and mute status persist across mpv invocations and system reboots. In exclusive mode, WASAPI doesn't have access to a mixer so the endpoint (sound card)'s master volume is modified instead. Since by definition mpv is the only thing outputting audio in exclusive mode, this causes no conflict, and ao_wasapi restores the last user-set volume when it's uninitialized.
Diffstat (limited to 'audio/out/ao_wasapi.c')
-rw-r--r--audio/out/ao_wasapi.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index a496ff9aa6..ec04cedcd6 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -195,6 +195,7 @@ static int init(struct ao *ao)
wasapi_enumerate_devices(state->log);
}
+ ao->per_application_mixer = true;
if (state->opt_exclusive) {
state->share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;
} else {
@@ -235,22 +236,54 @@ static int init(struct ao *ao)
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
struct wasapi_state *state = (struct wasapi_state *)ao->priv;
- if (!state->share_mode && !(state->vol_hw_support & ENDPOINT_HARDWARE_SUPPORT_VOLUME)) {
- return CONTROL_UNKNOWN; /* hw does not support volume controls in exclusive mode */
- }
-
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
+ BOOL mute;
switch (cmd) {
case AOCONTROL_GET_VOLUME:
- IAudioEndpointVolume_GetMasterVolumeLevelScalar(state->pEndpointVolumeProxy,
- &state->audio_volume);
+ if (state->opt_exclusive)
+ IAudioEndpointVolume_GetMasterVolumeLevelScalar(state->pEndpointVolumeProxy,
+ &state->audio_volume);
+ else
+ ISimpleAudioVolume_GetMasterVolume(state->pAudioVolumeProxy,
+ &state->audio_volume);
+
+ /* check to see if user manually changed volume through mixer;
+ this information is used in exclusive mode for restoring the mixer volume on uninit */
+ if (state->audio_volume != state->previous_volume) {
+ MP_VERBOSE(state, "mixer difference: %.2g now, expected %.2g\n",
+ state->audio_volume, state->previous_volume);
+ state->initial_volume = state->audio_volume;
+ }
+
vol->left = vol->right = 100.0f * state->audio_volume;
return CONTROL_OK;
case AOCONTROL_SET_VOLUME:
state->audio_volume = vol->left / 100.f;
- IAudioEndpointVolume_SetMasterVolumeLevelScalar(state->pEndpointVolumeProxy,
- state->audio_volume, NULL);
+ if (state->opt_exclusive)
+ IAudioEndpointVolume_SetMasterVolumeLevelScalar(state->pEndpointVolumeProxy,
+ state->audio_volume, NULL);
+ else
+ ISimpleAudioVolume_SetMasterVolume(state->pAudioVolumeProxy,
+ state->audio_volume, NULL);
+
+ state->previous_volume = state->audio_volume;
+ return CONTROL_OK;
+ case AOCONTROL_GET_MUTE:
+ if (state->opt_exclusive)
+ IAudioEndpointVolume_GetMute(state->pEndpointVolumeProxy, &mute);
+ else
+ ISimpleAudioVolume_GetMute(state->pAudioVolumeProxy, &mute);
+ *(bool*)arg = mute;
+
+ return CONTROL_OK;
+ case AOCONTROL_SET_MUTE:
+ mute = *(bool*)arg;
+ if (state->opt_exclusive)
+ IAudioEndpointVolume_SetMute(state->pEndpointVolumeProxy, mute, NULL);
+ else
+ ISimpleAudioVolume_SetMute(state->pAudioVolumeProxy, mute, NULL);
+
return CONTROL_OK;
default:
return CONTROL_UNKNOWN;