HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) { IMMDeviceEnumerator *devenum; IMMDeviceCollection *coll; UINT count, i; HRESULT hr, init_hr; init_hr = get_mmdevenum(&devenum); if(!devenum) return init_hr; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)){ WARN("EnumAudioEndpoints failed: %08x\n", hr); release_mmdevenum(devenum, init_hr); return hr; } hr = IMMDeviceCollection_GetCount(coll, &count); if(FAILED(hr)){ IMMDeviceCollection_Release(coll); release_mmdevenum(devenum, init_hr); WARN("GetCount failed: %08x\n", hr); return hr; } for(i = 0; i < count; ++i){ GUID guid; hr = IMMDeviceCollection_Item(coll, i, device); if(FAILED(hr)) continue; hr = get_mmdevice_guid(*device, NULL, &guid); if(FAILED(hr)){ IMMDevice_Release(*device); continue; } if(IsEqualGUID(&guid, tgt)){ IMMDeviceCollection_Release(coll); release_mmdevenum(devenum, init_hr); return DS_OK; } IMMDevice_Release(*device); } WARN("No device with GUID %s found!\n", wine_dbgstr_guid(tgt)); IMMDeviceCollection_Release(coll); release_mmdevenum(devenum, init_hr); return DSERR_INVALIDPARAM; }
static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs) { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; DevMap *devlist = NULL; HRESULT hr; UINT count; UINT idx; UINT i; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); return NULL; } idx = count = 0; hr = IMMDeviceCollection_GetCount(coll, &count); if(SUCCEEDED(hr) && count > 0) { devlist = calloc(count, sizeof(*devlist)); if(!devlist) { IMMDeviceCollection_Release(coll); return NULL; } hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, eMultimedia, &defdev); } if(SUCCEEDED(hr) && defdev != NULL) add_device(defdev, &devlist[idx++]); for(i = 0;i < count && idx < count;++i) { IMMDevice *device; if(FAILED(IMMDeviceCollection_Item(coll, i, &device))) continue; if(device != defdev) add_device(device, &devlist[idx++]); IMMDevice_Release(device); } if(defdev) IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); *numdevs = idx; return devlist; }
static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; HRESULT hr; UINT count; UINT i; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); return hr; } count = 0; hr = IMMDeviceCollection_GetCount(coll, &count); if(SUCCEEDED(hr) && count > 0) { clear_devlist(list); if(!VECTOR_RESERVE(*list, count+1)) { IMMDeviceCollection_Release(coll); return E_OUTOFMEMORY; } hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, eMultimedia, &defdev); } if(SUCCEEDED(hr) && defdev != NULL) add_device(defdev, list); for(i = 0;i < count;++i) { IMMDevice *device; if(FAILED(IMMDeviceCollection_Item(coll, i, &device))) continue; if(device != defdev) add_device(device, list); IMMDevice_Release(device); } if(defdev) IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); return S_OK; }
static BOOL load_devices(IMMDeviceEnumerator *devenum, EDataFlow dataflow, UINT *ndevs, struct DeviceInfo **out) { IMMDeviceCollection *coll; UINT i; HRESULT hr; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, dataflow, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)) return FALSE; hr = IMMDeviceCollection_GetCount(coll, ndevs); if(FAILED(hr)){ IMMDeviceCollection_Release(coll); return FALSE; } if(*ndevs > 0){ *out = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfo) * (*ndevs)); if(!*out){ IMMDeviceCollection_Release(coll); return FALSE; } for(i = 0; i < *ndevs; ++i){ IMMDevice *dev; hr = IMMDeviceCollection_Item(coll, i, &dev); if(FAILED(hr)){ (*out)[i].id = NULL; continue; } load_device(dev, &(*out)[i]); IMMDevice_Release(dev); } }else *out = NULL; IMMDeviceCollection_Release(coll); return TRUE; }
JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_protocol_wasapi_WASAPI_IMMDeviceCollection_1GetCount (JNIEnv *env, jclass clazz, jlong thiz) { UINT cDevices; HRESULT hr = IMMDeviceCollection_GetCount( (IMMDeviceCollection *) (intptr_t) thiz, &cDevices); if (FAILED(hr)) { cDevices = 0; WASAPI_throwNewHResultException(env, hr, __func__, __LINE__); } return (jint) cDevices; }
/* S_FALSE means the callback returned FALSE at some point * S_OK means the callback always returned TRUE */ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, LPDSENUMCALLBACKW cb, void *user) { IMMDeviceEnumerator *devenum; IMMDeviceCollection *coll; IMMDevice *defdev = NULL; UINT count, i, n; BOOL keep_going; HRESULT hr, init_hr; static const WCHAR primary_desc[] = {'P','r','i','m','a','r','y',' ', 'S','o','u','n','d',' ','D','r','i','v','e','r',0}; static const WCHAR empty_drv[] = {0}; init_hr = get_mmdevenum(&devenum); if(!devenum) return init_hr; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)){ release_mmdevenum(devenum, init_hr); WARN("EnumAudioEndpoints failed: %08x\n", hr); return DS_OK; } hr = IMMDeviceCollection_GetCount(coll, &count); if(FAILED(hr)){ IMMDeviceCollection_Release(coll); release_mmdevenum(devenum, init_hr); WARN("GetCount failed: %08x\n", hr); return DS_OK; } if(count == 0){ release_mmdevenum(devenum, init_hr); return DS_OK; } TRACE("Calling back with NULL (%s)\n", wine_dbgstr_w(primary_desc)); keep_going = cb(NULL, primary_desc, empty_drv, user); /* always send the default device first */ if(keep_going){ hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flow, eMultimedia, &defdev); if(FAILED(hr)){ defdev = NULL; n = 0; }else{ keep_going = send_device(defdev, &guids[0], cb, user); n = 1; } } for(i = 0; keep_going && i < count; ++i){ IMMDevice *device; hr = IMMDeviceCollection_Item(coll, i, &device); if(FAILED(hr)){ WARN("Item failed: %08x\n", hr); continue; } if(device != defdev){ send_device(device, &guids[n], cb, user); ++n; } IMMDevice_Release(device); } if(defdev) IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); release_mmdevenum(devenum, init_hr); return (keep_going == TRUE) ? S_OK : S_FALSE; }
/* 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); }