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; }
JNIEXPORT jstring JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_protocol_wasapi_WASAPI_IMMDevice_1GetId (JNIEnv *env, jclass clazz, jlong thiz) { LPWSTR pstrId; HRESULT hr = IMMDevice_GetId((IMMDevice *) (intptr_t) thiz, &pstrId); jstring ret; if (SUCCEEDED(hr)) { if (pstrId) { ret = (*env)->NewString(env, pstrId, wcslen(pstrId)); CoTaskMemFree(pstrId); } else ret = NULL; } else { ret = NULL; WASAPI_throwNewHResultException(env, hr, __func__, __LINE__); } return ret; }
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 BOOL load_device(IMMDevice *dev, struct DeviceInfo *info) { IPropertyStore *ps; HRESULT hr; hr = IMMDevice_GetId(dev, &info->id); if(FAILED(hr)){ info->id = NULL; return FALSE; } hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &ps); if(FAILED(hr)){ CoTaskMemFree(info->id); info->id = NULL; return FALSE; } PropVariantInit(&info->name); hr = IPropertyStore_GetValue(ps, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &info->name); IPropertyStore_Release(ps); if(FAILED(hr)){ CoTaskMemFree(info->id); info->id = NULL; return FALSE; } return TRUE; }
static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHAR *name, IMMDevice **device) { MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface); DWORD i=0; IMMDevice *dev = NULL; TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device); for (i = 0; i < MMDevice_count; ++i) { WCHAR *str; dev = &MMDevice_head[i]->IMMDevice_iface; IMMDevice_GetId(dev, &str); if (str && !lstrcmpW(str, name)) { CoTaskMemFree(str); break; } CoTaskMemFree(str); } if (dev) { IUnknown_AddRef(dev); *device = dev; return S_OK; } WARN("Could not find device %s\n", debugstr_w(name)); return E_NOTFOUND; }
static BOOL load_device(IMMDevice *dev, struct DeviceInfo *info) { IPropertyStore *ps; HRESULT hr; PROPVARIANT pv; UINT i; hr = IMMDevice_GetId(dev, &info->id); if(FAILED(hr)){ info->id = NULL; return FALSE; } hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &ps); if(FAILED(hr)){ CoTaskMemFree(info->id); info->id = NULL; return FALSE; } PropVariantInit(&info->name); hr = IPropertyStore_GetValue(ps, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &info->name); if(FAILED(hr)){ CoTaskMemFree(info->id); info->id = NULL; IPropertyStore_Release(ps); return FALSE; } PropVariantInit(&pv); hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_PhysicalSpeakers, &pv); info->speaker_config = -1; if(SUCCEEDED(hr) && pv.vt == VT_UI4){ i = 0; while (speaker_configs[i].text_id != 0) { if ((speaker_configs[i].speaker_mask & pv.u.ulVal) == speaker_configs[i].speaker_mask) { info->speaker_config = i; break; } i++; } } /* fallback to stereo */ if(info->speaker_config == -1) info->speaker_config = 2; IPropertyStore_Release(ps); return TRUE; }
static LPWSTR get_device_id(IMMDevice *device) { LPWSTR devid; HRESULT hr; hr = IMMDevice_GetId(device, &devid); if(FAILED(hr)) { ERR("Failed to get device id: %lx\n", hr); return NULL; } return devid; }
static void add_device(IMMDevice *device, DevMap *devmap) { LPWSTR devid; HRESULT hr; hr = IMMDevice_GetId(device, &devid); if(SUCCEEDED(hr)) { devmap->devid = strdupW(devid); devmap->name = get_device_name(device); TRACE("Got device \"%s\", \"%ls\"\n", devmap->name, devmap->devid); CoTaskMemFree(devid); } }
static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHAR *name, IMMDevice **device) { MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface); DWORD i=0; IMMDevice *dev = NULL; static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ', 'i','n','f','o',' ','d','e','v','i','c','e',0}; TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device); if(!name || !device) return E_POINTER; if(!lstrcmpW(name, wine_info_deviceW)){ *device = &info_device; return S_OK; } for (i = 0; i < MMDevice_count; ++i) { HRESULT hr; WCHAR *str; dev = &MMDevice_head[i]->IMMDevice_iface; hr = IMMDevice_GetId(dev, &str); if (FAILED(hr)) { WARN("GetId failed: %08x\n", hr); continue; } if (str && !lstrcmpW(str, name)) { CoTaskMemFree(str); IMMDevice_AddRef(dev); *device = dev; return S_OK; } CoTaskMemFree(str); } TRACE("Could not find device %s\n", debugstr_w(name)); return E_INVALIDARG; }
static void add_device(IMMDevice *device, vector_DevMap *list) { LPWSTR devid; HRESULT hr; hr = IMMDevice_GetId(device, &devid); if(SUCCEEDED(hr)) { DevMap entry; AL_STRING_INIT(entry.name); entry.devid = strdupW(devid); get_device_name(device, &entry.name); CoTaskMemFree(devid); TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid); VECTOR_PUSH_BACK(*list, entry); } }
/* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col) { IMMDeviceCollection *col2; IMMDeviceEnumerator *mme2; IUnknown *unk; HRESULT hr; ULONG ref; UINT numdev; IMMDevice *dev; /* collection doesn't keep a ref on parent */ IMMDeviceEnumerator_AddRef(mme); ref = IMMDeviceEnumerator_Release(mme); ok(ref == 2, "Reference count on parent is %u\n", ref); ref = IMMDeviceCollection_AddRef(col); IMMDeviceCollection_Release(col); ok(ref == 2, "Invalid reference count %u on collection\n", ref); hr = IMMDeviceCollection_QueryInterface(col, &IID_IUnknown, NULL); ok(hr == E_POINTER, "Null ppv returns %08x\n", hr); hr = IMMDeviceCollection_QueryInterface(col, &IID_IUnknown, (void**)&unk); ok(hr == S_OK, "Cannot query for IID_IUnknown: 0x%08x\n", hr); if (hr == S_OK) { ok((IUnknown*)col == unk, "Pointers are not identical %p/%p/%p\n", col, unk, mme); IUnknown_Release(unk); } hr = IMMDeviceCollection_QueryInterface(col, &IID_IMMDeviceCollection, (void**)&col2); ok(hr == S_OK, "Cannot query for IID_IMMDeviceCollection: 0x%08x\n", hr); if (hr == S_OK) IMMDeviceCollection_Release(col2); hr = IMMDeviceCollection_QueryInterface(col, &IID_IMMDeviceEnumerator, (void**)&mme2); ok(hr == E_NOINTERFACE, "Query for IID_IMMDeviceEnumerator returned: 0x%08x\n", hr); if (hr == S_OK) IMMDeviceEnumerator_Release(mme2); hr = IMMDeviceCollection_GetCount(col, NULL); ok(hr == E_POINTER, "GetCount returned 0x%08x\n", hr); hr = IMMDeviceCollection_GetCount(col, &numdev); ok(hr == S_OK, "GetCount returned 0x%08x\n", hr); dev = (void*)(LONG_PTR)0x12345678; hr = IMMDeviceCollection_Item(col, numdev, &dev); ok(hr == E_INVALIDARG, "Asking for too high device returned 0x%08x\n", hr); ok(dev == NULL, "Returned non-null device\n"); if (numdev) { hr = IMMDeviceCollection_Item(col, 0, NULL); ok(hr == E_POINTER, "Query with null pointer returned 0x%08x\n", hr); hr = IMMDeviceCollection_Item(col, 0, &dev); ok(hr == S_OK, "Valid Item returned 0x%08x\n", hr); ok(dev != NULL, "Device is null!\n"); if (dev != NULL) { char temp[128]; WCHAR *id = NULL; if (IMMDevice_GetId(dev, &id) == S_OK) { IMMDevice *dev2; temp[sizeof(temp)-1] = 0; WideCharToMultiByte(CP_ACP, 0, id, -1, temp, sizeof(temp)-1, NULL, NULL); trace("Device found: %s\n", temp); hr = IMMDeviceEnumerator_GetDevice(mme, id, &dev2); ok(hr == S_OK, "GetDevice failed: %08x\n", hr); IMMDevice_Release(dev2); CoTaskMemFree(id); } } if (dev) IMMDevice_Release(dev); } IMMDeviceCollection_Release(col); }