summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_wasapi_changenotify.c
diff options
context:
space:
mode:
authorKevin Mitchell <kevmitch@gmail.com>2015-03-31 01:56:17 -0700
committerKevin Mitchell <kevmitch@gmail.com>2015-03-31 02:02:54 -0700
commita6bf38bcadafd3f7b08b63d8ea1642a9f351f6e6 (patch)
treee7fb5b2f4d13d452499ac45022444f63c17a336a /audio/out/ao_wasapi_changenotify.c
parent1091353d476b7187c8cfd350dbb98d2d1ad6d07c (diff)
downloadmpv-a6bf38bcadafd3f7b08b63d8ea1642a9f351f6e6.tar.bz2
mpv-a6bf38bcadafd3f7b08b63d8ea1642a9f351f6e6.tar.xz
ao/wasapi: add ao hotplug
Create a second copy of the change_notify structure for the hotplug ao. change_notify->is_hotplug distinguishes the hotplug version from the regular one monitoring the currently playing ao. Also make the change notification less verbose now that there might be two of them around.
Diffstat (limited to 'audio/out/ao_wasapi_changenotify.c')
-rwxr-xr-xaudio/out/ao_wasapi_changenotify.c129
1 files changed, 67 insertions, 62 deletions
diff --git a/audio/out/ao_wasapi_changenotify.c b/audio/out/ao_wasapi_changenotify.c
index 6f2263a3ec..26c3c7ed0d 100755
--- a/audio/out/ao_wasapi_changenotify.c
+++ b/audio/out/ao_wasapi_changenotify.c
@@ -27,26 +27,6 @@
#include "ao_wasapi.h"
#include "ao_wasapi_utils.h"
-static char* ERole_to_str(ERole role)
-{
- switch (role) {
- case eConsole: return "console";
- case eMultimedia: return "multimedia";
- case eCommunications: return "communications";
- default: return "<Unknown>";
- }
-}
-
-static char* EDataFlow_to_str(EDataFlow flow)
-{
- switch (flow) {
- case eRender: return "render";
- case eCapture: return "capture";
- case eAll: return "all";
- default: return "<Unknown>";
- }
-}
-
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_QueryInterface(
IMMNotificationClient* This, REFIID riid, void **ppvObject)
{
@@ -84,19 +64,23 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceStateChanged(
change_notify *change = (change_notify *)This;
struct ao *ao = change->ao;
- if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
+ if (change->is_hotplug) {
+ MP_VERBOSE(ao, "OnDeviceStateChanged triggered: sending hotplug event\n");
+ ao_hotplug_event(ao);
+ } else if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
switch (dwNewState) {
case DEVICE_STATE_DISABLED:
case DEVICE_STATE_NOTPRESENT:
case DEVICE_STATE_UNPLUGGED:
- MP_VERBOSE(ao,
- "OnDeviceStateChange triggered - requesting ao reload\n");
+ MP_VERBOSE(ao, "OnDeviceStateChanged triggered on device %S: "
+ "requesting ao reload\n", pwstrDeviceId);
ao_request_reload(ao);
+ break;
case DEVICE_STATE_ACTIVE:
- default:
- return S_OK;
+ break;
}
}
+
return S_OK;
}
@@ -107,9 +91,11 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceAdded(
change_notify *change = (change_notify *)This;
struct ao *ao = change->ao;
- MP_VERBOSE(ao, "OnDeviceAdded triggered\n");
- if(pwstrDeviceId)
- MP_VERBOSE(ao, "New device %S\n",pwstrDeviceId);
+ if (change->is_hotplug) {
+ MP_VERBOSE(ao, "OnDeviceAdded triggered: sending hotplug event\n");
+ ao_hotplug_event(ao);
+ }
+
return S_OK;
}
@@ -121,10 +107,15 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceRemoved(
change_notify *change = (change_notify *)This;
struct ao *ao = change->ao;
- if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
- MP_VERBOSE(ao, "OnDeviceRemoved triggered - requesting ao reload\n");
+ if (change->is_hotplug) {
+ MP_VERBOSE(ao, "OnDeviceRemoved triggered: sending hotplug event\n");
+ ao_hotplug_event(ao);
+ } else if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
+ MP_VERBOSE(ao, "OnDeviceRemoved triggered for device %S: "
+ "requesting ao reload\n", pwstrDeviceId);
ao_request_reload(ao);
}
+
return S_OK;
}
@@ -138,29 +129,32 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDefaultDeviceChanged(
struct ao *ao = change->ao;
struct wasapi_state *state = (struct wasapi_state *)ao->priv;
- MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered for role:%s flow:%s\n",
- ERole_to_str(role), EDataFlow_to_str(flow));
- if(pwstrDeviceId)
- MP_VERBOSE(ao, "New default device %S\n", pwstrDeviceId);
-
/* don't care about "eCapture" or non-"eMultimedia" roles */
if (flow == eCapture || role != eMultimedia) return S_OK;
- /* stay on the device the user specified */
- if (state->opt_device) {
- MP_VERBOSE(ao, "Staying on specified device \"%s\"", state->opt_device);
- return S_OK;
- }
+ if (change->is_hotplug) {
+ MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: sending hotplug event\n");
+ ao_hotplug_event(ao);
+ } else {
+ /* stay on the device the user specified */
+ if (state->opt_device) {
+ MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
+ "staying on specified device %s\n", state->opt_device);
+ return S_OK;
+ }
- /* don't reload if already on the new default */
- if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
- MP_VERBOSE(ao, "Already using default device, no reload required\n");
- return S_OK;
+ /* don't reload if already on the new default */
+ if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
+ MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
+ "already using default device, no reload required\n");
+ return S_OK;
+ }
+
+ /* if we got here, we need to reload */
+ MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: requesting ao reload\n");
+ ao_request_reload(ao);
}
- /* if we got here, we need to reload */
- ao_request_reload(ao);
- MP_VERBOSE(ao, "Requesting ao reload\n");
return S_OK;
}
@@ -172,17 +166,21 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnPropertyValueChanged(
change_notify *change = (change_notify *)This;
struct ao *ao = change->ao;
- if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
- MP_VERBOSE(ao, "OnPropertyValueChanged triggered\n");
- MP_VERBOSE(ao, "Changed property: ");
+ if (!change->is_hotplug && pwstrDeviceId &&
+ !wcscmp(pwstrDeviceId, change->monitored))
+ {
+ MP_VERBOSE(ao, "OnPropertyValueChanged triggered on device %S\n",
+ pwstrDeviceId);
if (IsEqualPropertyKey(PKEY_AudioEngine_DeviceFormat, key)) {
MP_VERBOSE(change->ao,
- "PKEY_AudioEngine_DeviceFormat - requesting ao reload\n");
+ "Changed property: PKEY_AudioEngine_DeviceFormat "
+ "- requesting ao reload\n");
ao_request_reload(change->ao);
} else {
- MP_VERBOSE(ao, "%s\n", mp_PKEY_to_str(&key));
+ MP_VERBOSE(ao, "Changed property: %s\n", mp_PKEY_to_str(&key));
}
}
+
return S_OK;
}
@@ -198,27 +196,34 @@ static CONST_VTBL IMMNotificationClientVtbl sIMMDeviceEnumeratorVtbl_vtbl = {
};
-HRESULT wasapi_change_init(struct ao *ao)
+HRESULT wasapi_change_init(struct ao *ao, bool is_hotplug)
{
- MP_DBG(ao, "Setting up monitoring on playback device\n");
struct wasapi_state *state = (struct wasapi_state *)ao->priv;
struct change_notify *change = &state->change;
+ HRESULT hr;
/* COM voodoo to emulate c++ class */
change->client.lpVtbl = &sIMMDeviceEnumeratorVtbl_vtbl;
- /* so the callbacks can access the ao */
- change->ao = ao;
-
- /* get the device string to compare with the pwstrDeviceId argument in callbacks */
- HRESULT hr = IMMDevice_GetId(state->pDevice, &change->monitored);
- EXIT_ON_ERROR(hr);
-
/* register the change notification client */
hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(
state->pEnumerator, (IMMNotificationClient *)change);
EXIT_ON_ERROR(hr);
- MP_VERBOSE(state, "Monitoring changes in device: %S\n", state->change.monitored);
+ /* so the callbacks can access the ao */
+ change->ao = ao;
+
+ /* whether or not this is the hotplug instance */
+ change->is_hotplug = is_hotplug;
+
+ if (is_hotplug) {
+ MP_DBG(ao, "Monitoring for hotplug events\n");
+ } else {
+ /* Get the device string to compare with the pwstrDeviceId */
+ hr = IMMDevice_GetId(state->pDevice, &change->monitored);
+ EXIT_ON_ERROR(hr);
+ MP_VERBOSE(ao, "Monitoring changes in device %S\n", change->monitored);
+ }
+
return hr;
exit_label:
MP_ERR(state, "Error setting up device change monitoring: %s\n",