static BOOL get_driver_name(IMMDeviceEnumerator *devenum, PROPVARIANT *pv) { IMMDevice *device; IPropertyStore *ps; HRESULT hr; static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ', 'i','n','f','o',' ','d','e','v','i','c','e',0}; hr = IMMDeviceEnumerator_GetDevice(devenum, wine_info_deviceW, &device); if(FAILED(hr)) return FALSE; hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); if(FAILED(hr)){ IMMDevice_Release(device); return FALSE; } hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY *)&DEVPKEY_Device_Driver, pv); IPropertyStore_Release(ps); IMMDevice_Release(device); if(FAILED(hr)) return FALSE; return TRUE; }
static void apply_speaker_configs(void) { UINT i; IMMDeviceEnumerator *devenum; IMMDevice *dev; IPropertyStore *ps; PROPVARIANT pv; HRESULT hr; hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum); if(FAILED(hr)){ ERR("Unable to create MMDeviceEnumerator: 0x%08x\n", hr); return; } PropVariantInit(&pv); pv.vt = VT_UI4; for (i = 0; i < num_render_devs; i++) { hr = IMMDeviceEnumerator_GetDevice(devenum, render_devs[i].id, &dev); if(FAILED(hr)){ WARN("Could not get MMDevice for %s: 0x%08x\n", wine_dbgstr_w(render_devs[i].id), hr); continue; } hr = IMMDevice_OpenPropertyStore(dev, STGM_WRITE, &ps); if(FAILED(hr)){ WARN("Could not open property store for %s: 0x%08x\n", wine_dbgstr_w(render_devs[i].id), hr); IMMDevice_Release(dev); continue; } pv.u.ulVal = speaker_configs[render_devs[i].speaker_config].speaker_mask; hr = IPropertyStore_SetValue(ps, &PKEY_AudioEndpoint_PhysicalSpeakers, &pv); if (FAILED(hr)) WARN("IPropertyStore_SetValue failed for %s: 0x%08x\n", wine_dbgstr_w(render_devs[i].id), hr); IPropertyStore_Release(ps); IMMDevice_Release(dev); } IMMDeviceEnumerator_Release(devenum); }
JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_protocol_wasapi_WASAPI_IMMDeviceEnumerator_1GetDevice (JNIEnv *env, jclass clazz, jlong thiz, jstring pwstrId) { const jchar *pwstrId_; HRESULT hr; IMMDevice *pDevice; if (pwstrId) { pwstrId_ = (*env)->GetStringChars(env, pwstrId, NULL); hr = pwstrId_ ? S_OK : E_OUTOFMEMORY; } else { pwstrId_ = NULL; hr = S_OK; } if (SUCCEEDED(hr)) { hr = IMMDeviceEnumerator_GetDevice( (IMMDeviceEnumerator *) (intptr_t) thiz, (LPCWSTR) pwstrId_, &pDevice); if (pwstrId_) (*env)->ReleaseStringChars(env, pwstrId, pwstrId_); if (FAILED(hr)) { pDevice = NULL; WASAPI_throwNewHResultException(env, hr, __func__, __LINE__); } } else pDevice = NULL; return (jlong) (intptr_t) pDevice; }
static HRESULT WINAPI MMDevEnum_GetDefaultAudioEndpoint(IMMDeviceEnumerator *iface, EDataFlow flow, ERole role, IMMDevice **device) { MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface); WCHAR reg_key[256]; HKEY key; HRESULT hr; TRACE("(%p)->(%u,%u,%p)\n", This, flow, role, device); if (!device) return E_POINTER; if((flow != eRender && flow != eCapture) || (role != eConsole && role != eMultimedia && role != eCommunications)){ WARN("Unknown flow (%u) or role (%u)\n", flow, role); return E_INVALIDARG; } *device = NULL; if(!drvs.module_name[0]) return E_NOTFOUND; lstrcpyW(reg_key, drv_keyW); lstrcatW(reg_key, slashW); lstrcatW(reg_key, drvs.module_name); if(RegOpenKeyW(HKEY_CURRENT_USER, reg_key, &key) == ERROR_SUCCESS){ const WCHAR *reg_x_name, *reg_vx_name; WCHAR def_id[256]; DWORD size = sizeof(def_id), state; if(flow == eRender){ reg_x_name = reg_out_nameW; reg_vx_name = reg_vout_nameW; }else{ reg_x_name = reg_in_nameW; reg_vx_name = reg_vin_nameW; } if(role == eCommunications && RegQueryValueExW(key, reg_vx_name, 0, NULL, (BYTE*)def_id, &size) == ERROR_SUCCESS){ hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device); if(SUCCEEDED(hr)){ if(SUCCEEDED(IMMDevice_GetState(*device, &state)) && state == DEVICE_STATE_ACTIVE){ RegCloseKey(key); return S_OK; } } TRACE("Unable to find voice device %s\n", wine_dbgstr_w(def_id)); } if(RegQueryValueExW(key, reg_x_name, 0, NULL, (BYTE*)def_id, &size) == ERROR_SUCCESS){ hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device); if(SUCCEEDED(hr)){ if(SUCCEEDED(IMMDevice_GetState(*device, &state)) && state == DEVICE_STATE_ACTIVE){ RegCloseKey(key); return S_OK; } } TRACE("Unable to find device %s\n", wine_dbgstr_w(def_id)); } RegCloseKey(key); } if (flow == eRender) *device = &MMDevice_def_play->IMMDevice_iface; else *device = &MMDevice_def_rec->IMMDevice_iface; if (!*device) return E_NOTFOUND; IMMDevice_AddRef(*device); return S_OK; }
int open_ep_mixers(px_mixer *Px, UINT deviceIn, UINT deviceOut) { PxEPInfo *info; IMMDeviceEnumerator *denum = NULL; IMMDevice *device = NULL; HRESULT hr; MMRESULT res; LPWSTR idStr; size_t idLen; if (!initialize(Px)) { goto fail; } info = (PxEPInfo *) Px->info; info->inputEP = NULL; info->outputEP = NULL; // Create an audio endpoint device enumerator. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, &denum); if (FAILED(hr)) { goto fail; } if (deviceIn == WAVE_MAPPER) { hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(denum, eCapture, eMultimedia, &device); if (SUCCEEDED(hr)) { hr = IMMDevice_Activate(device, &IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, &info->inputEP); IUnknown_Release(device); } if (FAILED(hr)) { goto fail; } } else { res = waveInMessage((HWAVEIN)IntToPtr(deviceIn), DRV_QUERYFUNCTIONINSTANCEIDSIZE, (DWORD_PTR)&idLen, (DWORD_PTR)NULL); if (res != MMSYSERR_NOERROR) { goto fail; } idStr = (WCHAR *) CoTaskMemAlloc(idLen + sizeof(WCHAR)); if (idStr == NULL) { goto fail; } res = waveInMessage((HWAVEIN)IntToPtr(deviceIn), DRV_QUERYFUNCTIONINSTANCEID, (DWORD_PTR)idStr, (DWORD_PTR)idLen); if (res != MMSYSERR_NOERROR) { CoTaskMemFree(idStr); goto fail; } hr = IMMDeviceEnumerator_GetDevice(denum, idStr, &device); if (SUCCEEDED(hr)) { hr = IMMDevice_Activate(device, &IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, &info->inputEP); IUnknown_Release(device); } CoTaskMemFree(idStr); if (FAILED(hr)) { goto fail; } } if (deviceOut == WAVE_MAPPER) { hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(denum, eRender, eMultimedia, &device); if (SUCCEEDED(hr)) { hr = IMMDevice_Activate(device, &IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, &info->outputEP); IUnknown_Release(device); } if (FAILED(hr)) { goto fail; } } else { res = waveOutMessage((HWAVEOUT)IntToPtr(deviceOut), DRV_QUERYFUNCTIONINSTANCEIDSIZE, (DWORD_PTR)&idLen, (DWORD_PTR)NULL); if (res != MMSYSERR_NOERROR) { goto fail; } idStr = (WCHAR *) CoTaskMemAlloc(idLen + sizeof(WCHAR)); if (idStr == NULL) { goto fail; } res = waveOutMessage((HWAVEOUT)IntToPtr(deviceOut), DRV_QUERYFUNCTIONINSTANCEID, (DWORD_PTR)idStr, (DWORD_PTR)idLen); if (res != MMSYSERR_NOERROR) { CoTaskMemFree(idStr); goto fail; } hr = IMMDeviceEnumerator_GetDevice(denum, idStr, &device); if (SUCCEEDED(hr)) { hr = IMMDevice_Activate(device, &IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, &info->outputEP); IUnknown_Release(device); } CoTaskMemFree(idStr); if (FAILED(hr)) { goto fail; } } if (denum) { IUnknown_Release(denum); } return TRUE; fail: if (denum) { IUnknown_Release(denum); } return cleanup(Px); }
static DWORD CALLBACK MMDevApiMsgProc(void *ptr) { ThreadRequest *req = ptr; IMMDeviceEnumerator *Enumerator; ALuint deviceCount = 0; MMDevApiData *data; ALCdevice *device; HRESULT hr, cohr; MSG msg; TRACE("Starting message thread\n"); cohr = CoInitialize(NULL); if(FAILED(cohr)) { WARN("Failed to initialize COM: 0x%08lx\n", cohr); req->result = cohr; SetEvent(req->FinishedEvt); return 0; } hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); if(FAILED(hr)) { WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); CoUninitialize(); req->result = hr; SetEvent(req->FinishedEvt); return 0; } Enumerator = ptr; IMMDeviceEnumerator_Release(Enumerator); Enumerator = NULL; CoUninitialize(); req->result = S_OK; SetEvent(req->FinishedEvt); TRACE("Starting message loop\n"); while(GetMessage(&msg, NULL, 0, 0)) { TRACE("Got message %u\n", msg.message); switch(msg.message) { case WM_USER_OpenDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; data = device->ExtraData; hr = cohr = S_OK; if(++deviceCount == 1) hr = cohr = CoInitialize(NULL); if(SUCCEEDED(hr)) hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); if(SUCCEEDED(hr)) { Enumerator = ptr; if(!data->devid) hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev); else hr = IMMDeviceEnumerator_GetDevice(Enumerator, data->devid, &data->mmdev); IMMDeviceEnumerator_Release(Enumerator); Enumerator = NULL; } if(SUCCEEDED(hr)) hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); if(SUCCEEDED(hr)) { data->client = ptr; device->DeviceName = get_device_name(data->mmdev); } if(FAILED(hr)) { if(data->mmdev) IMMDevice_Release(data->mmdev); data->mmdev = NULL; if(--deviceCount == 0 && SUCCEEDED(cohr)) CoUninitialize(); } req->result = hr; SetEvent(req->FinishedEvt); continue; case WM_USER_ResetDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; req->result = DoReset(device); SetEvent(req->FinishedEvt); continue; case WM_USER_StartDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; data = device->ExtraData; ResetEvent(data->NotifyEvent); hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent); if(FAILED(hr)) ERR("Failed to set event handle: 0x%08lx\n", hr); else { hr = IAudioClient_Start(data->client); if(FAILED(hr)) ERR("Failed to start audio client: 0x%08lx\n", hr); } if(SUCCEEDED(hr)) hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr); if(SUCCEEDED(hr)) { data->render = ptr; data->thread = StartThread(MMDevApiProc, device); if(!data->thread) { if(data->render) IAudioRenderClient_Release(data->render); data->render = NULL; IAudioClient_Stop(data->client); ERR("Failed to start thread\n"); hr = E_FAIL; } } req->result = hr; SetEvent(req->FinishedEvt); continue; case WM_USER_StopDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; data = device->ExtraData; if(data->thread) { data->killNow = 1; StopThread(data->thread); data->thread = NULL; data->killNow = 0; IAudioRenderClient_Release(data->render); data->render = NULL; IAudioClient_Stop(data->client); } req->result = S_OK; SetEvent(req->FinishedEvt); continue; case WM_USER_CloseDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; data = device->ExtraData; IAudioClient_Release(data->client); data->client = NULL; IMMDevice_Release(data->mmdev); data->mmdev = NULL; if(--deviceCount == 0) CoUninitialize(); req->result = S_OK; SetEvent(req->FinishedEvt); continue; case WM_USER_Enumerate: req = (ThreadRequest*)msg.wParam; hr = cohr = S_OK; if(++deviceCount == 1) hr = cohr = CoInitialize(NULL); if(SUCCEEDED(hr)) hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); if(SUCCEEDED(hr)) { EDataFlow flowdir; DevMap **devlist; ALuint *numdevs; ALuint i; Enumerator = ptr; if(msg.lParam == CAPTURE_DEVICE_PROBE) { flowdir = eCapture; devlist = &CaptureDeviceList; numdevs = &NumCaptureDevices; } else { flowdir = eRender; devlist = &PlaybackDeviceList; numdevs = &NumPlaybackDevices; } for(i = 0;i < *numdevs;i++) { free((*devlist)[i].name); free((*devlist)[i].devid); } free(*devlist); *devlist = NULL; *numdevs = 0; *devlist = ProbeDevices(Enumerator, flowdir, numdevs); IMMDeviceEnumerator_Release(Enumerator); Enumerator = NULL; } if(--deviceCount == 0 && SUCCEEDED(cohr)) CoUninitialize(); req->result = S_OK; SetEvent(req->FinishedEvt); continue; default: ERR("Unexpected message: %u\n", msg.message); continue; } } TRACE("Message loop finished\n"); return 0; }
/* 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); }