HRESULT wasapi_change_init(struct ao *ao) { 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; /* 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); return hr; exit_label: MP_ERR(state, "Error setting up device change monitoring: %s\n", wasapi_explain_err(hr)); wasapi_change_uninit(ao); return hr; }
static void uninit(struct ao *ao) { MP_DBG(ao, "Uninit wasapi\n"); struct wasapi_state *state = ao->priv; wasapi_release_proxies(state); if (state->hWake) set_thread_state(ao, WASAPI_THREAD_SHUTDOWN); // wait up to 10 seconds if (state->hAudioThread && WaitForSingleObject(state->hAudioThread, 10000) == WAIT_TIMEOUT) { MP_ERR(ao, "Audio loop thread refuses to abort\n"); return; } SAFE_RELEASE(state->hInitDone, CloseHandle(state->hInitDone)); SAFE_RELEASE(state->hWake, CloseHandle(state->hWake)); SAFE_RELEASE(state->hAudioThread,CloseHandle(state->hAudioThread)); wasapi_change_uninit(ao); talloc_free(state->deviceID); CoUninitialize(); MP_DBG(ao, "Uninit wasapi done\n"); }
HRESULT wasapi_change_init(struct ao *ao, bool is_hotplug) { struct wasapi_state *state = ao->priv; struct change_notify *change = &state->change; HRESULT hr; /* COM voodoo to emulate c++ class */ change->client.lpVtbl = &sIMMDeviceEnumeratorVtbl_vtbl; /* register the change notification client */ hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback( state->pEnumerator, (IMMNotificationClient *)change); EXIT_ON_ERROR(hr); /* 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", mp_HRESULT_to_str(hr)); wasapi_change_uninit(ao); return hr; }
static void hotplug_uninit(struct ao *ao) { MP_DBG(ao, "Hotplug uninit\n"); struct wasapi_state *state = ao->priv; wasapi_change_uninit(ao); SAFE_RELEASE(state->pEnumerator, IMMDeviceEnumerator_Release(state->pEnumerator)); CoUninitialize(); }
HRESULT wasapi_change_init(struct ao *ao, bool is_hotplug) { struct wasapi_state *state = ao->priv; struct change_notify *change = &state->change; HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **)&change->pEnumerator); EXIT_ON_ERROR(hr); // COM voodoo to emulate c++ class change->client.lpVtbl = &sIMMNotificationClientVtbl; // register the change notification client hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback( change->pEnumerator, (IMMNotificationClient *)change); EXIT_ON_ERROR(hr); // 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 change->monitored = state->deviceID; 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", mp_HRESULT_to_str(hr)); wasapi_change_uninit(ao); return hr; }
static void hotplug_uninit(struct ao *ao) { MP_DBG(ao, "Hotplug uninit\n"); wasapi_change_uninit(ao); CoUninitialize(); }