// // Retrieves the device friendly name for a particular device in a device collection. // // The returned string was allocated using malloc() so it should be freed using free(); // String GetDeviceName(IMMDeviceCollection *DeviceCollection, UINT DeviceIndex) { IMMDevice *device; LPWSTR deviceId; HRESULT hr; hr = DeviceCollection->Item(DeviceIndex, &device); PersistentAssert(SUCCEEDED(hr), "DeviceCollection->Item failed"); hr = device->GetId(&deviceId); PersistentAssert(SUCCEEDED(hr), "device->GetId failed"); IPropertyStore *propertyStore; hr = device->OpenPropertyStore(STGM_READ, &propertyStore); SafeRelease(&device); PersistentAssert(SUCCEEDED(hr), "device->OpenPropertyStore failed"); PROPVARIANT friendlyName; PropVariantInit(&friendlyName); hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName); SafeRelease(&propertyStore); PersistentAssert(SUCCEEDED(hr), "propertyStore->GetValue failed"); String Result = String(UnicodeString(friendlyName.pwszVal)); // + String(" (") + String( UnicodeString(deviceId) ) + String(")") PropVariantClear(&friendlyName); CoTaskMemFree(deviceId); return Result; }
OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInGuidStr(WCHAR deviceInStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]) { if (!deviceInStrBuffer) return ovrError_InvalidParameter; IMMDeviceEnumerator* pEnumerator; const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); HRESULT hr = CoCreateInstance( CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); if (FAILED(hr)) return ovrError_RuntimeException; IMMDevice* pDevice; hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice); if (FAILED(hr)) return ovrError_RuntimeException; LPWSTR pGuid; hr = pDevice->GetId(&pGuid); if (FAILED(hr)) return ovrError_RuntimeException; wcsncpy(deviceInStrBuffer, pGuid, OVR_AUDIO_MAX_DEVICE_STR_SIZE); // Cleanup pDevice->Release(); pEnumerator->Release(); return ovrSuccess; }
static HRESULT DeviceIdStringGet(IMMDeviceCollection *dc, UINT id, wchar_t *deviceIdStr, size_t deviceIdStrBytes) { HRESULT hr = 0; IMMDevice *device = nullptr; LPWSTR s = nullptr; assert(dc); assert(deviceIdStr); assert(0 < deviceIdStrBytes); deviceIdStr[0] = 0; HRG(dc->Item(id, &device)); HRG(device->GetId(&s)); wcsncpy_s(deviceIdStr, deviceIdStrBytes/2, s, deviceIdStrBytes/2 -1); end: CoTaskMemFree(s); s = nullptr; SafeRelease(&device); return hr; }
static HRESULT DeviceNameGet( IMMDeviceCollection *dc, UINT id, wchar_t *name, size_t nameBytes) { HRESULT hr = 0; IMMDevice *device = nullptr; LPWSTR deviceId = nullptr; IPropertyStore *ps = nullptr; PROPVARIANT pv; assert(dc); assert(name); name[0] = 0; assert(0 < nameBytes); PropVariantInit(&pv); HRR(dc->Item(id, &device)); HRR(device->GetId(&deviceId)); HRR(device->OpenPropertyStore(STGM_READ, &ps)); HRG(ps->GetValue(PKEY_Device_FriendlyName, &pv)); SafeRelease(&ps); wcsncpy_s(name, nameBytes / sizeof name[0], pv.pwszVal, _TRUNCATE); end: PropVariantClear(&pv); CoTaskMemFree(deviceId); SafeRelease(&ps); return hr; }
// // Retrieves the device friendly name for a particular device in a device collection. // LPWSTR GetDeviceName(IMMDeviceCollection *DeviceCollection, UINT DeviceIndex) { IMMDevice *device; LPWSTR deviceId; HRESULT hr; hr = DeviceCollection->Item(DeviceIndex, &device); if (FAILED(hr)) { printf("Unable to get device %d: %x\n", DeviceIndex, hr); return NULL; } hr = device->GetId(&deviceId); if (FAILED(hr)) { printf("Unable to get device %d id: %x\n", DeviceIndex, hr); return NULL; } IPropertyStore *propertyStore; hr = device->OpenPropertyStore(STGM_READ, &propertyStore); SafeRelease(&device); if (FAILED(hr)) { printf("Unable to open device %d property store: %x\n", DeviceIndex, hr); return NULL; } PROPVARIANT friendlyName; PropVariantInit(&friendlyName); hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName); SafeRelease(&propertyStore); if (FAILED(hr)) { printf("Unable to retrieve friendly name for device %d : %x\n", DeviceIndex, hr); return NULL; } wchar_t deviceName[128]; hr = StringCbPrintf(deviceName, sizeof(deviceName), L"%s (%s)", friendlyName.vt != VT_LPWSTR ? L"Unknown" : friendlyName.pwszVal, deviceId); if (FAILED(hr)) { printf("Unable to format friendly name for device %d : %x\n", DeviceIndex, hr); return NULL; } PropVariantClear(&friendlyName); CoTaskMemFree(deviceId); wchar_t *returnValue = _wcsdup(deviceName); if (returnValue == NULL) { printf("Unable to allocate buffer for return\n"); return NULL; } return returnValue; }
const QHash<QString, QString> WASAPISystem::getDevices(EDataFlow dataflow) { QHash<QString, QString> devices; HRESULT hr; IMMDeviceEnumerator *pEnumerator = NULL; IMMDeviceCollection *pCollection = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast<void **>(&pEnumerator)); if (! pEnumerator || FAILED(hr)) { qWarning("WASAPI: Failed to instatiate enumerator"); } else { hr = pEnumerator->EnumAudioEndpoints(dataflow, DEVICE_STATE_ACTIVE, &pCollection); if (! pCollection || FAILED(hr)) { qWarning("WASAPI: Failed to enumerate"); } else { devices.insert(QString(), tr("Default Device")); UINT ndev = 0; pCollection->GetCount(&ndev); for (unsigned int idx=0;idx<ndev;++idx) { IMMDevice *pDevice = NULL; IPropertyStore *pStore = NULL; pCollection->Item(idx, &pDevice); pDevice->OpenPropertyStore(STGM_READ, &pStore); LPWSTR strid = NULL; pDevice->GetId(&strid); PROPVARIANT varName; PropVariantInit(&varName); pStore->GetValue(PKEY_Device_FriendlyName, &varName); devices.insert(QString::fromWCharArray(strid), QString::fromWCharArray(varName.pwszVal)); PropVariantClear(&varName); CoTaskMemFree(strid); pStore->Release(); pDevice->Release(); } pCollection->Release(); } pEnumerator->Release(); } return devices; }
LPWSTR GetDeviceName(IMMDeviceCollection *DeviceCollection, UINT DeviceIndex) { IMMDevice *device; LPWSTR deviceId; HRESULT hr; hr = DeviceCollection->Item(DeviceIndex, &device); if (FAILED(hr)) { printf("Unable to get device %d: %x\n", DeviceIndex, hr); return nullptr; } hr = device->GetId(&deviceId); if (FAILED(hr)) { printf("Unable to get device %d id: %x\n", DeviceIndex, hr); return nullptr; } IPropertyStore *propertyStore; hr = device->OpenPropertyStore(STGM_READ, &propertyStore); if (FAILED(hr)) { printf("Unable to open device %d property store: %x\n", DeviceIndex, hr); return nullptr; } PROPVARIANT friendlyName; PropVariantInit(&friendlyName); hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName); if (FAILED(hr)) { printf("Unable to retrieve friendly name for device %d : %x\n", DeviceIndex, hr); return nullptr; } DVAR(friendlyName.vt); if (friendlyName.vt != VT_LPWSTR) DVAR("Unknown"); else DVAR((const wchar_t *)friendlyName.pwszVal); PropVariantClear(&friendlyName); CoTaskMemFree(deviceId); return nullptr; }
HRESULT GetDefaultDeviceID(IMMDeviceEnumerator *pEnum, LPWSTR *ppOutID) { IMMDevice *pDevice = NULL; HRESULT hr = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); if(FAILED(hr)) { *ppOutID = NULL; return hr; } hr = pDevice->GetId(ppOutID); pDevice->Release(); return hr; }
std::wstring GetDefaultID() { std::wstring id_default; IMMDevice * pEndpoint = 0; if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) { LPWSTR pwszID = 0; if (pEndpoint->GetId(&pwszID) == S_OK) { id_default = pwszID; } CoTaskMemFree(pwszID); } SAFE_RELEASE(pEndpoint) return id_default; }
OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutGuidStr(WCHAR deviceOutStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]) { REV_TRACE(ovr_GetAudioDeviceOutGuidStr); if (!deviceOutStrBuffer) return ovrError_InvalidParameter; // Query and cache the result static WCHAR cachedBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE] = {}; if (wcslen(cachedBuffer) == 0) { HRESULT com = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); IMMDeviceEnumerator* pEnumerator; const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); HRESULT hr = CoCreateInstance( CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); if (FAILED(hr)) return ovrError_AudioComError; IMMDevice* pDevice; hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); if (FAILED(hr)) return ovrError_AudioDeviceNotFound; LPWSTR pGuid; hr = pDevice->GetId(&pGuid); if (FAILED(hr)) return ovrError_AudioComError; wcsncpy(cachedBuffer, pGuid, OVR_AUDIO_MAX_DEVICE_STR_SIZE); // Cleanup pDevice->Release(); pEnumerator->Release(); if (SUCCEEDED(com)) CoUninitialize(); } wcsncpy(deviceOutStrBuffer, cachedBuffer, OVR_AUDIO_MAX_DEVICE_STR_SIZE); return ovrSuccess; }
AudioEndpoint::AudioEndpoint(IMMDeviceEnumerator *aDeviceEnumerator) { Set(L"\0"); IMMDevice *pDevice; HRESULT hr = aDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); if (SUCCEEDED(hr)) { LPWSTR id; hr = pDevice->GetId(&id); if (SUCCEEDED(hr)) { Set(id); CoTaskMemFree(id); } pDevice->Release(); } }
AUDIO_DEVICE_API void GetDefaultCaptureDeviceId(DeviceInfo *pDeviceInfo, LPWSTR szBuffer, int bufferLen) { InternalDeviceInfo *pInternalDeviceInfo = (InternalDeviceInfo *) pDeviceInfo; HRESULT hr = S_OK; IMMDevice *pDevice = NULL; hr = pInternalDeviceInfo->pEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &pDevice); // assert(hr == S_OK); // Copy and return the Id String. WCHAR *szTempId; pDevice->GetId(&szTempId); wcsncpy_s(szBuffer, bufferLen, szTempId, _TRUNCATE); SAFE_RELEASE(pDevice); return; }
AUDIO_DEVICE_API void GetCaptureListDeviceId(DeviceInfo *pDeviceInfo, int index, LPWSTR szBuffer, int bufferLen) { InternalDeviceInfo *pInternalDeviceInfo = (InternalDeviceInfo *) pDeviceInfo; HRESULT hr = S_OK; IMMDevice *pDevice = NULL; if (pInternalDeviceInfo->pCaptureCollection != NULL) { hr = pInternalDeviceInfo->pCaptureCollection->Item(index, &pDevice); } // assert(hr == S_OK); // Copy and return the Id String. WCHAR *szTempId; pDevice->GetId(&szTempId); wcsncpy_s(szBuffer, bufferLen, szTempId, _TRUNCATE); SAFE_RELEASE(pDevice); return; }
PLUGIN_EXPORT void Initialize(void** data, void* rm) { if (!InitCom()) { UnInitCom(); return; } UINT count; if (!pCollection || (S_OK != pCollection->GetCount(&count))) { UnInitCom(); return; } endpointIDs = std::vector<std::wstring>(count); for (UINT i = 0; i < count; ++i) { IMMDevice *pEndpoint = 0; // Get pointer to endpoint number i. if (pCollection->Item(i, &pEndpoint) == S_OK) { // Get the endpoint ID string. LPWSTR pwszID = 0; if (pEndpoint->GetId(&pwszID) == S_OK) { endpointIDs[i] = pwszID; } CoTaskMemFree(pwszID); } SAFE_RELEASE(pEndpoint) } UnInitCom(); GetWin7AudioState(INIT); }
bool GetDefaultDevice(String &strVal, EDataFlow df ) { const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); IMMDeviceEnumerator *mmEnumerator; HRESULT err; err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator); if(FAILED(err)) return false; //------------------------------------------------------- IMMDevice *defDevice; if(FAILED(mmEnumerator->GetDefaultAudioEndpoint(df, eCommunications, &defDevice))) { SafeRelease(mmEnumerator); return false; } CWSTR wstrDefaultID; if(FAILED(defDevice->GetId((LPWSTR*)&wstrDefaultID))) { SafeRelease(defDevice); SafeRelease(mmEnumerator); return false; } strVal = wstrDefaultID; CoTaskMemFree((LPVOID)wstrDefaultID); SafeRelease(defDevice); SafeRelease(mmEnumerator); return true; }
void MFAudioEndpointControl::updateEndpoints() { m_defaultEndpoint = QString::fromLatin1("Default"); m_devices.insert(m_defaultEndpoint, NULL); IMMDeviceEnumerator *pEnum = NULL; HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum); if (SUCCEEDED(hr)) { IMMDeviceCollection *pDevices = NULL; hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices); if (SUCCEEDED(hr)) { UINT count; hr = pDevices->GetCount(&count); if (SUCCEEDED(hr)) { for (UINT i = 0; i < count; ++i) { IMMDevice *pDevice = NULL; hr = pDevices->Item(i, &pDevice); if (SUCCEEDED(hr)) { LPWSTR wstrID = NULL; hr = pDevice->GetId(&wstrID); if (SUCCEEDED(hr)) { QString deviceId = QString::fromWCharArray(wstrID); m_devices.insert(deviceId, wstrID); } pDevice->Release(); } } } pDevices->Release(); } pEnum->Release(); } }
TBool OhmSenderDriverWindows::FindEndpoint(const char* aManufacturer) { bool uninitialise = true; HRESULT hr = CoInitialize(NULL); printf("CoInitialize %d\n", hr); if (hr == 0x80010106) { uninitialise = false; } else if (!SUCCEEDED(hr)) { return (false); } // Create a multimedia device enumerator. hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&iDeviceEnumerator); printf("CoCreateInstance %d\n", hr); if (SUCCEEDED(hr)) { IMMDeviceCollection *pDevices; // Enumerate the output devices. hr = iDeviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL | 0x10000000, &pDevices); printf("EnumAudioEndpoints %d\n", hr); if (SUCCEEDED(hr)) { UINT count; pDevices->GetCount(&count); printf("count: %d\n", count); if (SUCCEEDED(hr)) { for (unsigned i = 0; i < count; i++) { IMMDevice *pDevice; hr = pDevices->Item(i, &pDevice); if (SUCCEEDED(hr)) { LPWSTR wstrID = NULL; hr = pDevice->GetId(&wstrID); wprintf(L"id: %s\n", wstrID); if (SUCCEEDED(hr)) { IPropertyStore *pStore; hr = pDevice->OpenPropertyStore(STGM_READ, &pStore); if (SUCCEEDED(hr)) { PROPVARIANT var; PropVariantInit(&var); hr = pStore->GetValue(PKEY_AudioEndpoint_GUID, &var); wprintf(L"%s\n", var.pwszVal); PROPVARIANT friendlyName; PropVariantInit(&friendlyName); hr = pStore->GetValue(PKEY_DeviceInterface_FriendlyName, &friendlyName); wprintf(L"friendlyName: %s\n", friendlyName.pwszVal); if (SUCCEEDED(hr)) { wchar_t model[200]; MultiByteToWideChar(CP_ACP, 0, aManufacturer, -1, model, sizeof(model)); wcscpy(model + wcslen(model), L" Songcast"); if (!wcscmp(friendlyName.pwszVal, model)) { iSongcastEndpoint.Set(wstrID); PropVariantClear(&friendlyName); pStore->Release(); pDevice->Release(); pDevices->Release(); if (uninitialise) { CoUninitialize(); } return (true); } PropVariantClear(&friendlyName); } pStore->Release(); } CoTaskMemFree(wstrID); } pDevice->Release(); } } } pDevices->Release(); } iDeviceEnumerator->Release(); } if (uninitialise) { CoUninitialize(); } return (false); }
void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) { IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; IMMDevice* pDefaultDevice = NULL; CAEDeviceInfo deviceInfo; CAEChannelInfo deviceChannels; LPWSTR pwszID = NULL; std::wstring wstrDDID; WAVEFORMATEXTENSIBLE wfxex = {0}; HRESULT hr; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr) UINT uiCount = 0; // get the default audio endpoint if(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDefaultDevice) == S_OK) { if(pDefaultDevice->GetId(&pwszID) == S_OK) { wstrDDID = pwszID; CoTaskMemFree(pwszID); } SAFE_RELEASE(pDefaultDevice); } // enumerate over all audio endpoints hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.") hr = pEnumDevices->GetCount(&uiCount); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.") for (UINT i = 0; i < uiCount; i++) { IMMDevice *pDevice = NULL; IPropertyStore *pProperty = NULL; PROPVARIANT varName; PropVariantInit(&varName); deviceInfo.m_channels.Reset(); deviceInfo.m_dataFormats.clear(); deviceInfo.m_sampleRates.clear(); hr = pEnumDevices->Item(i, &pDevice); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint failed."); goto failed; } hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint properties failed."); SAFE_RELEASE(pDevice); goto failed; } hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint device name failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strFriendlyName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); if(FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strDevName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint form factor failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType; AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType; PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint speaker layout failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } unsigned int uiChannelMask = std::max(varName.uintVal, (unsigned int) KSAUDIO_SPEAKER_STEREO); deviceChannels.Reset(); for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++) { if (uiChannelMask & WASAPIChannelOrder[c]) deviceChannels += AEChannelNames[c]; } PropVariantClear(&varName); IAudioClient *pClient; hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient); if (SUCCEEDED(hr)) { /* Test format DTS-HD */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.Format.nSamplesPerSec = 192000; wfxex.dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 8; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTSHD)); /* Test format Dolby TrueHD */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_TRUEHD)); /* Test format Dolby EAC3 */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_EAC3)); /* Test format DTS */ wfxex.Format.nSamplesPerSec = 48000; wfxex.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DTS; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS)); /* Test format Dolby AC3 */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); /* Test format AAC */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_AAC; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AAC)); /* Test format for PCM format iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; for (int p = AE_FMT_FLOAT; p > AE_FMT_INVALID; p--) { if (p < AE_FMT_FLOAT) wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.wBitsPerSample = CAEUtil::DataFormatToBits((AEDataFormat) p); wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4) { wfxex.Samples.wValidBitsPerSample = 24; } else { wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample; } hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back((AEDataFormat) p); } /* Test format for sample rate iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; for (int j = 0; j < WASAPISampleRateCount; j++) { wfxex.Format.nSamplesPerSec = WASAPISampleRates[j]; wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_sampleRates.push_back(WASAPISampleRates[j]); } /* Test format for channels iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.nSamplesPerSec = 48000; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; bool hasLpcm = false; // Try with KSAUDIO_SPEAKER_DIRECTOUT for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--) { wfxex.dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; wfxex.Format.nChannels = k; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if (k > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } break; } } /* Try with reported channel mask */ for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--) { wfxex.dwChannelMask = uiChannelMask; wfxex.Format.nChannels = k; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if ( !hasLpcm && k > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } break; } } /* Try with specific speakers configurations */ for (unsigned int i = 0; i < ARRAYSIZE(layoutsList); i++) { unsigned int nmbOfCh; wfxex.dwChannelMask = ChLayoutToChMask(layoutsList[i], &nmbOfCh); wfxex.Format.nChannels = nmbOfCh; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if ( deviceChannels.Count() < nmbOfCh) deviceChannels = layoutsList[i]; if ( !hasLpcm && nmbOfCh > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } } } pClient->Release(); } else { CLog::Log(LOGDEBUG, __FUNCTION__": Failed to activate device for passthrough capability testing."); } deviceInfo.m_deviceName = strDevName; deviceInfo.m_displayName = strWinDevType.append(strFriendlyName); deviceInfo.m_displayNameExtra = std::string("WASAPI: ").append(strFriendlyName); deviceInfo.m_deviceType = aeDeviceType; deviceInfo.m_channels = deviceChannels; /* Store the device info */ deviceInfoList.push_back(deviceInfo); if(pDevice->GetId(&pwszID) == S_OK) { if(wstrDDID.compare(pwszID) == 0) { deviceInfo.m_deviceName = std::string("default"); deviceInfo.m_displayName = std::string("default"); deviceInfo.m_displayNameExtra = std::string(""); deviceInfoList.push_back(deviceInfo); } CoTaskMemFree(pwszID); } SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); }
void GetAudioDevices(AudioDeviceList &deviceList, AudioDeviceType deviceType) { const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); IMMDeviceEnumerator *mmEnumerator; HRESULT err; err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator); if(FAILED(err)) { AppWarning(TEXT("GetAudioDevices: Could not create IMMDeviceEnumerator")); return; } //------------------------------------------------------- AudioDeviceInfo *info; if(deviceType == ADT_RECORDING) { info = deviceList.devices.CreateNew(); info->strID = TEXT("Disable"); info->strName = Str("Disable"); } info = deviceList.devices.CreateNew(); info->strID = TEXT("Default"); info->strName = Str("Default"); //------------------------------------------------------- IMMDeviceCollection *collection; EDataFlow audioDeviceType; switch(deviceType) { case ADT_RECORDING: audioDeviceType = eCapture; break; case ADT_PLAYBACK: audioDeviceType = eRender; break; default: audioDeviceType = eAll; break; } err = mmEnumerator->EnumAudioEndpoints(audioDeviceType, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &collection); if(FAILED(err)) { AppWarning(TEXT("GetAudioDevices: Could not enumerate audio endpoints")); SafeRelease(mmEnumerator); return; } UINT count; if(SUCCEEDED(collection->GetCount(&count))) { for(UINT i=0; i<count; i++) { IMMDevice *device; if(SUCCEEDED(collection->Item(i, &device))) { CWSTR wstrID; if(SUCCEEDED(device->GetId((LPWSTR*)&wstrID))) { IPropertyStore *store; if(SUCCEEDED(device->OpenPropertyStore(STGM_READ, &store))) { PROPVARIANT varName; PropVariantInit(&varName); if(SUCCEEDED(store->GetValue(PKEY_Device_FriendlyName, &varName))) { CWSTR wstrName = varName.pwszVal; AudioDeviceInfo *info = deviceList.devices.CreateNew(); info->strID = wstrID; info->strName = wstrName; } } CoTaskMemFree((LPVOID)wstrID); } SafeRelease(device); } } } //------------------------------------------------------- SafeRelease(collection); SafeRelease(mmEnumerator); }
//------------------------------------------------------------------------------------------------- void FMain() { if (const HWND hWnd = FindWindowW(g_wGuidClass, nullptr)) PostMessageW(hWnd, WM_CLOSE, 0, 0); if (SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) { IMMDeviceEnumerator *immDeviceEnumerator; if (CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast<LPVOID*>(&immDeviceEnumerator)) == S_OK) { IMMDevice *immDeviceDefault; if (immDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &immDeviceDefault) == S_OK) { wchar_t *wIdDefaultOld; HRESULT hr = immDeviceDefault->GetId(&wIdDefaultOld); immDeviceDefault->Release(); if (hr == S_OK) { IMMDeviceCollection *immDeviceCollection; hr = immDeviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &immDeviceCollection); immDeviceEnumerator->Release(); if (hr == S_OK) { UINT iCount; if (immDeviceCollection->GetCount(&iCount) == S_OK) { bool bFail = true; for (UINT i = 0; i < iCount; ++i) { IMMDevice *immDevice; if (immDeviceCollection->Item(i, &immDevice) == S_OK) { wchar_t *wIdEnum; hr = immDevice->GetId(&wIdEnum); immDevice->Release(); if (hr == S_OK) { if (FCompareMemoryW(wIdDefaultOld, wIdEnum)) { bFail = false; if (++i >= iCount) i = 0; hr = immDeviceCollection->Item(i, &immDevice); immDeviceCollection->Release(); if (hr == S_OK) { wchar_t *wIdDefaultNew; if (immDevice->GetId(&wIdDefaultNew) == S_OK) { IPropertyStore *ipStore; hr = immDevice->OpenPropertyStore(STGM_READ, &ipStore); immDevice->Release(); if (hr == S_OK) { PROPVARIANT propFriendlyName; PropVariantInitFix(&propFriendlyName); PROPERTYKEY propKeyFriendlyName; propKeyFriendlyName.fmtid.Data1 = 0xA45C254E; propKeyFriendlyName.fmtid.Data2 = 0xDF1C; propKeyFriendlyName.fmtid.Data3 = 0x4EFD; FCopyMemory(propKeyFriendlyName.fmtid.Data4); propKeyFriendlyName.pid = 14; hr = ipStore->GetValue(propKeyFriendlyName, &propFriendlyName); ipStore->Release(); if (SUCCEEDED(hr)) { IPolicyConfig *pPolicyConfig; if (CoCreateInstance(__uuidof(CPolicyConfigClient), nullptr, CLSCTX_ALL, (GetVersion() & 0xFF) >= 10 ? __uuidof(IPolicyConfigWin10) : __uuidof(IPolicyConfig), reinterpret_cast<LPVOID*>(&pPolicyConfig)) == S_OK) { hr = pPolicyConfig->SetDefaultEndpoint(wIdDefaultNew, eConsole); if (hr == S_OK) { pPolicyConfig->SetDefaultEndpoint(wIdDefaultNew, eMultimedia); pPolicyConfig->SetDefaultEndpoint(wIdDefaultNew, eCommunications); } pPolicyConfig->Release(); if (hr == S_OK) { WNDCLASSEX wndCl; wndCl.cbSize = sizeof(WNDCLASSEX); wndCl.style = 0; wndCl.lpfnWndProc = WindowProc; wndCl.cbClsExtra = 0; wndCl.cbWndExtra = 0; wndCl.hInstance = GetModuleHandleW(nullptr); wndCl.hIcon = nullptr; wndCl.hCursor = nullptr; wndCl.hbrBackground = nullptr; wndCl.lpszMenuName = nullptr; wndCl.lpszClassName = g_wGuidClass; wndCl.hIconSm = nullptr; if (RegisterClassExW(&wndCl)) { if (CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST, g_wGuidClass, nullptr, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, nullptr, nullptr, wndCl.hInstance, propFriendlyName.pwszVal)) { MSG msg; while (GetMessageW(&msg, nullptr, 0, 0) > 0) DispatchMessageW(&msg); } UnregisterClassW(g_wGuidClass, wndCl.hInstance); } } } } PropVariantClear(&propFriendlyName); } CoTaskMemFree(wIdDefaultNew); } else immDevice->Release(); } break; } CoTaskMemFree(wIdEnum); } } } if (bFail) immDeviceCollection->Release(); } else immDeviceCollection->Release(); } CoTaskMemFree(wIdDefaultOld); } else immDeviceEnumerator->Release(); } else immDeviceEnumerator->Release(); } CoUninitialize(); } }
int __cdecl wmain(void) { HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { LOG(L"Failed CoInitializeEx: hr = 0x%08x", hr); return __LINE__; } CoUninitializeOnExit cuoe; // get active devices IMMDeviceEnumerator *pEnum = NULL; hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum ); if (FAILED(hr)) { LOG(L"Couldn't get device enumerator: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseEnum(pEnum); IMMDeviceCollection *pDeviceCollection = NULL; hr = pEnum->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDeviceCollection); if (FAILED(hr)) { LOG(L"Couldn't get device collection: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDeviceCollection(pDeviceCollection); UINT nDevices = 0; hr = pDeviceCollection->GetCount(&nDevices); if (FAILED(hr)) { LOG(L"Couldn't get device collection count: hr = 0x%08x", hr); return __LINE__; } for (UINT i = 0; i < nDevices; i++) { IMMDevice *pDevice = NULL; hr = pDeviceCollection->Item(i, &pDevice); if (FAILED(hr)) { LOG(L"Couldn't get device: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDevice(pDevice); IMMEndpoint *pEndpoint = NULL; hr = pDevice->QueryInterface(IID_PPV_ARGS(&pEndpoint)); if (FAILED(hr)) { LOG(L"Couldn't get endpoint: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseEndpoint(pEndpoint); EDataFlow eDirection = eAll; hr = pEndpoint->GetDataFlow(&eDirection); if (FAILED(hr)) { LOG(L"Couldn't get data flow: hr = 0x%08x", hr); return __LINE__; } LOG(L"%s endpoint", StringFromDataFlow(eDirection)); IPropertyStore *pPropertyStore = NULL; hr = pDevice->OpenPropertyStore(STGM_READ, &pPropertyStore); if (FAILED(hr)) { LOG(L"Couldn't get property store: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releasePropertyStore(pPropertyStore); // get the long name property PROPVARIANT pv; PropVariantInit(&pv); hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); if (FAILED(hr)) { LOG(L"Couldn't get friendly name: hr = 0x%08x", hr); return hr; } PropVariantClearOnExit clearPropVariant(&pv); LOG(L"Name: %s", pv.pwszVal); // get the ID WCHAR *wszId = NULL; hr = pDevice->GetId(&wszId); if (FAILED(hr)) { LOG(L"Couldn't get device ID: hr = 0x%08x", hr); return __LINE__; } CoTaskMemFreeOnExit releaseId(wszId); LOG(L"Endpoint ID: %s", wszId); // get device topology object for that endpoint IDeviceTopology *pDT = NULL; hr = pDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&pDT); if (FAILED(hr)) { LOG(L"Couldn't get device topology object: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDT(pDT); // get the single connector for that endpoint IConnector *pConnector = NULL; hr = pDT->GetConnector(0, &pConnector); if (FAILED(hr)) { LOG(L"Couldn't get the connector on the endpoint: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseConnector(pConnector); // QI on the device's connector for IPart IPart *pPart = NULL; hr = pConnector->QueryInterface(IID_PPV_ARGS(&pPart)); if (FAILED(hr)) { LOG(L"Couldn't get the part: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releasePart(pPart); // all the real work is done in this function // follow the connector from this trivial endpoint topology // over to the rest of the topologies hr = WalkTreeFromPart(pPart, eDirection, true, 1); if (FAILED(hr)) { LOG(L"Couldn't walk the tree: hr = 0x%08x", hr); return __LINE__; } LOG(L""); } return 0; }
BOOL SetDefaultAudioDevice_Vista(LPCTSTR lpszHardwareId, LPCTSTR lpszName) { HRESULT hr = S_FALSE; BOOL bSuccessful = FALSE; IMMDeviceEnumerator *pDeviceEnumerator = NULL; IMMDeviceCollection* pCollection = NULL; IPolicyConfigVista *pPolicyConfigVista = NULL; do { CElcAudioDeviceEnumerator enumerator; if (!enumerator.Enumerate(FALSE)) break; CElcDeviceItem * pAudioItem = enumerator.FindItemByPnpId(lpszHardwareId, lpszName); if (!pAudioItem) break; if (FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pDeviceEnumerator))) { break; } if (FAILED(pDeviceEnumerator->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &pCollection))) { break; } LPWSTR lpszId = NULL; UINT nCount = 0; pCollection->GetCount(&nCount); for (UINT i=0; i<nCount; i++) { IMMDevice* pDevice = NULL; if (SUCCEEDED(pCollection->Item(i, &pDevice))) { pDevice->GetId(&lpszId); SAFE_RELEASE(pDevice); LPCWSTR lpszIdDup = lpszId + 17; if (pAudioItem->m_strDeviceId.CompareNoCase(lpszIdDup) == 0) break; CoTaskMemFree(lpszId); lpszId = NULL; } } if (lpszId && SUCCEEDED(CoCreateInstance( __uuidof(CPolicyConfigVistaClient), NULL, CLSCTX_ALL, __uuidof(IPolicyConfigVista), (LPVOID *)&pPolicyConfigVista))) { if (SUCCEEDED(pPolicyConfigVista->SetDefaultEndpoint(lpszId, eMultimedia)) && SUCCEEDED(pPolicyConfigVista->SetDefaultEndpoint(lpszId, eCommunications))) bSuccessful = TRUE; } if (lpszId) CoTaskMemFree(lpszId); } while (0); SAFE_RELEASE(pPolicyConfigVista); SAFE_RELEASE(pCollection); SAFE_RELEASE(pDeviceEnumerator); return bSuccessful; }
void MFSound_InitWASAPI() { gDevices.Init(sizeof(MFAudioDevice), 8, 8); gCaptureDevices.Init(sizeof(MFAudioCaptureDevice), 8, 8); HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&gpEnumerator); if(FAILED(hr)) { MFDebug_Assert(false, "Couldn't create multimedia device enumerator!"); return; } // enumerate audio devices... gpNotification = new MFAudioDeviceNotification; gpEnumerator->RegisterEndpointNotificationCallback(gpNotification); // enumerate render devices IMMDeviceCollection *pDevices; gpEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDevices); if(pDevices) { UINT count; pDevices->GetCount(&count); for(UINT i=0; i<count; ++i) { IMMDevice *pDevice; pDevices->Item(i, &pDevice); MFDevice *pDev = MFDevice_AllocDevice(MFDT_AudioRender, NULL); pDev->pInternal = gDevices.AllocAndZero(); MFAudioDevice &device = *(MFAudioDevice*)pDev->pInternal; GetDeviceInfo(pDevice, pDev); pDevice->Release(); MFDebug_Log(0, MFStr("Found audio device: %s, %s - state: %d (%s)", pDev->strings[MFDS_DeviceName], pDev->strings[MFDS_Manufacturer], device.state, pDev->strings[MFDS_ID])); } pDevices->Release(); } // enumerate capture devices gpEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDevices); if(pDevices) { UINT count; pDevices->GetCount(&count); for(UINT i=0; i<count; ++i) { IMMDevice *pDevice; pDevices->Item(i, &pDevice); MFDevice *pDev = MFDevice_AllocDevice(MFDT_AudioCapture, NULL); pDev->pInternal = gCaptureDevices.AllocAndZero(); MFAudioCaptureDevice &device = *(MFAudioCaptureDevice*)pDev->pInternal; GetDeviceInfo(pDevice, pDev); pDevice->Release(); MFDebug_Log(0, MFStr("Found audio capture device: %s, %s - state: %d (%s)", pDev->strings[MFDS_DeviceName], pDev->strings[MFDS_Manufacturer], device.state, pDev->strings[MFDS_ID])); } pDevices->Release(); } // set defaults (this is some awkward windows code!) for(int i=0; i<2; ++i) { for(int j=0; j<3; ++j) { IMMDevice *pDevice; gpEnumerator->GetDefaultAudioEndpoint(gDirection[i], gRole[j], &pDevice); if(pDevice) { wchar_t *pDefaultId; pDevice->GetId(&pDefaultId); char temp[128]; MFString_CopyUTF16ToUTF8(temp, pDefaultId); MFDevice *pDev = MFDevice_GetDeviceById(temp); MFDevice_SetDefaultDevice(gDt[i], gDef[j], pDev); CoTaskMemFree(pDefaultId); pDevice->Release(); } } } }
int _tmain(int argc, _TCHAR* argv[]) { // read the command line option, -1 indicates list devices. int option = -1; if (argc == 2) option = atoi((char*)argv[1]); std::wcout << "SoundSwitch Audio Interface Changer\r\n"; bool setOutput = false; HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { IMMDeviceEnumerator *pEnum = NULL; // Create a multimedia device enumerator. hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum); if (SUCCEEDED(hr)) { LPWSTR wstrDefaultID = NULL; hr = GetDefaultDeviceID(pEnum, &wstrDefaultID); if(FAILED(hr)) { wstrDefaultID = NULL; } IMMDeviceCollection *pDevices; // Get default device IMMDevice *pDevice = NULL; hr = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); // Enumerate the output devices. hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED | DEVICE_STATE_DISABLED, &pDevices); if (SUCCEEDED(hr)) { UINT count; pDevices->GetCount(&count); if (SUCCEEDED(hr)) { for (int i = 0; i < count; i++) { IMMDevice *pDevice; hr = pDevices->Item(i, &pDevice); if (SUCCEEDED(hr)) { LPWSTR wstrID = NULL; hr = pDevice->GetId(&wstrID); if (SUCCEEDED(hr)) { IPropertyStore *pStore; hr = pDevice->OpenPropertyStore(STGM_READ, &pStore); if (SUCCEEDED(hr)) { bool isDefault = false; if(wstrDefaultID != NULL) { LPWSTR wstrID = NULL; HRESULT hr = pDevice->GetId(&wstrID); if(!_wcsicmp(wstrID, wstrDefaultID)) { isDefault = true; } CoTaskMemFree(wstrID); } PROPVARIANT friendlyName; PropVariantInit(&friendlyName); hr = pStore->GetValue(PKEY_Device_FriendlyName, &friendlyName); if (SUCCEEDED(hr)) { // if no options, print the device // otherwise, find the selected device and set it to be default if (option == -1) { //printf("Audio Device %d: %ws\n",i, friendlyName.pwszVal); std::wcout << i << ": " << friendlyName.pwszVal; if (isDefault == true) { std::wcout << " (default)"; } std::wcout << "\r\n"; } if (i == option) { std::wcout << "Setting output to: " << i << ": " << friendlyName.pwszVal << "\r\n"; SetDefaultAudioPlaybackDevice(wstrID); setOutput = true; } PropVariantClear(&friendlyName); } pStore->Release(); } } pDevice->Release(); } } } pDevices->Release(); } //WTF? If Release() gets called, then redirecting this .exe's output stops working. No idea why.. // pEnum->Release(); } } if (option >= 0 && !setOutput) { std::cout << "Failed to select device " << option << "\r\n"; return 1; } return hr; }
static bool UpdateAudioDucking(bool bDuckingOptOutChecked) { HRESULT hr = S_OK; // Start with the default endpoint. IMMDeviceEnumerator* pDeviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDeviceEnumerator)); if (SUCCEEDED(hr)) { { IMMDevice* pEndpoint = NULL; hr = pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint); if (SUCCEEDED(hr)) { LPWSTR Desc; pEndpoint->GetId(&Desc); UE_LOG(LogVoiceCapture, Display, TEXT("%s ducking on audio device. Desc: %s"), bDuckingOptOutChecked ? TEXT("Disabling") : TEXT("Enabling"), Desc); CoTaskMemFree(Desc); FAudioDuckingWindows::EnableDuckingOptOut(pEndpoint, bDuckingOptOutChecked); pEndpoint->Release(); pEndpoint = NULL; } } if (0) // reference for enumerating all endpoints in case its necessary { IMMDeviceCollection* pDeviceCollection = NULL; IMMDevice* pCollEndpoint = NULL; hr = pDeviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDeviceCollection); if (SUCCEEDED(hr)) { IPropertyStore *pProps = NULL; ::UINT DeviceCount = 0; pDeviceCollection->GetCount(&DeviceCount); for (::UINT i = 0; i < DeviceCount; ++i) { hr = pDeviceCollection->Item(i, &pCollEndpoint); if (SUCCEEDED(hr) && pCollEndpoint) { LPWSTR Desc; pCollEndpoint->GetId(&Desc); hr = pCollEndpoint->OpenPropertyStore(STGM_READ, &pProps); if (SUCCEEDED(hr)) { PROPVARIANT varName; // Initialize container for property value. PropVariantInit(&varName); // Get the endpoint's friendly-name property. hr = pProps->GetValue( PKEY_Device_FriendlyName, &varName); if (SUCCEEDED(hr)) { // Print endpoint friendly name and endpoint ID. UE_LOG(LogVoiceCapture, Display, TEXT("%s ducking on audio device [%d]: \"%s\" (%s)"), bDuckingOptOutChecked ? TEXT("Disabling") : TEXT("Enabling"), i, varName.pwszVal, Desc); CoTaskMemFree(Desc); Desc = NULL; PropVariantClear(&varName); pProps->Release(); pProps = NULL; } } FAudioDuckingWindows::EnableDuckingOptOut(pCollEndpoint, bDuckingOptOutChecked); pCollEndpoint->Release(); pCollEndpoint = NULL; } } pDeviceCollection->Release(); pDeviceCollection = NULL; } } pDeviceEnumerator->Release(); pDeviceEnumerator = NULL; } if (FAILED(hr)) { UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to duck audio endpoint. Error: %0x08x"), hr); } return SUCCEEDED(hr); }
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = NULL; IMMDevice *device = NULL; CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_device->device_name == "Default") { hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); } else { IMMDeviceCollection *devices = NULL; hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); LPWSTR strId = NULL; bool found = false; UINT count = 0; hr = devices->GetCount(&count); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); for (ULONG i = 0; i < count && !found; i++) { IMMDevice *device = NULL; hr = devices->Item(i, &device); ERR_BREAK(hr != S_OK); IPropertyStore *props = NULL; hr = device->OpenPropertyStore(STGM_READ, &props); ERR_BREAK(hr != S_OK); PROPVARIANT propvar; PropVariantInit(&propvar); hr = props->GetValue(PKEY_Device_FriendlyName, &propvar); ERR_BREAK(hr != S_OK); if (p_device->device_name == String(propvar.pwszVal)) { hr = device->GetId(&strId); ERR_BREAK(hr != S_OK); found = true; } PropVariantClear(&propvar); props->Release(); device->Release(); } if (found) { hr = enumerator->GetDevice(strId, &device); } if (strId) { CoTaskMemFree(strId); } if (device == NULL) { hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); } } if (reinit) { // In case we're trying to re-initialize the device prevent throwing this error on the console, // otherwise if there is currently no device available this will spam the console. if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = enumerator->RegisterEndpointNotificationCallback(¬if_client); SAFE_RELEASE(enumerator) if (hr != S_OK) { ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error"); } hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&p_device->audio_client); SAFE_RELEASE(device) if (reinit) { if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = p_device->audio_client->GetMixFormat(&pwfex); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along p_device->channels = pwfex->nChannels; p_device->format_tag = pwfex->wFormatTag; p_device->bits_per_sample = pwfex->wBitsPerSample; p_device->frame_size = (p_device->bits_per_sample / 8) * p_device->channels; if (p_device->format_tag == WAVE_FORMAT_EXTENSIBLE) { WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex; if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) { p_device->format_tag = WAVE_FORMAT_PCM; } else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) { p_device->format_tag = WAVE_FORMAT_IEEE_FLOAT; } else { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } else { if (p_device->format_tag != WAVE_FORMAT_PCM && p_device->format_tag != WAVE_FORMAT_IEEE_FLOAT) { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } DWORD streamflags = 0; if (mix_rate != pwfex->nSamplesPerSec) { streamflags |= AUDCLNT_STREAMFLAGS_RATEADJUST; pwfex->nSamplesPerSec = mix_rate; pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8); } hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, NULL); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_capture) { hr = p_device->audio_client->GetService(IID_IAudioCaptureClient, (void **)&p_device->capture_client); } else { hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client); } ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Free memory CoTaskMemFree(pwfex); SAFE_RELEASE(device) return OK; }
HRESULT CMpcAudioRenderer::GetAudioDevice(IMMDevice **ppMMDevice) { TRACE(_T("CMpcAudioRenderer::GetAudioDevice\n")); CComPtr<IMMDeviceEnumerator> enumerator; IMMDeviceCollection* devices; IPropertyStore* pProps = NULL; HRESULT hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); if (hr != S_OK) { TRACE(_T("CMpcAudioRenderer::GetAudioDevice - failed to create MMDeviceEnumerator!\n")); return hr; } TRACE(_T("CMpcAudioRenderer::GetAudioDevice - Target end point: %s\n"), m_csSound_Device); if (GetAvailableAudioDevices(&devices) == S_OK && devices) { UINT count(0); hr = devices->GetCount(&count); if (hr != S_OK) { TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetCount failed: (0x%08x)\n"), hr); return hr; } for (ULONG i = 0 ; i < count ; i++) { LPWSTR pwszID = NULL; IMMDevice *endpoint = NULL; hr = devices->Item(i, &endpoint); if (hr == S_OK) { hr = endpoint->GetId(&pwszID); if (hr == S_OK) { if (endpoint->OpenPropertyStore(STGM_READ, &pProps) == S_OK) { PROPVARIANT varName; PropVariantInit(&varName); // Found the configured audio endpoint if ((pProps->GetValue(PKEY_Device_FriendlyName, &varName) == S_OK) && (m_csSound_Device == varName.pwszVal)) { TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetId OK, num: (%d), pwszVal: %s, pwszID: %s\n"), i, varName.pwszVal, pwszID); enumerator->GetDevice(pwszID, ppMMDevice); SAFE_RELEASE(devices); *(ppMMDevice) = endpoint; CoTaskMemFree(pwszID); pwszID = NULL; PropVariantClear(&varName); SAFE_RELEASE(pProps); return S_OK; } else { PropVariantClear(&varName); SAFE_RELEASE(pProps); SAFE_RELEASE(endpoint); CoTaskMemFree(pwszID); pwszID = NULL; } } } else { TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetId failed: (0x%08x)\n"), hr); } } else { TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->Item failed: (0x%08x)\n"), hr); } CoTaskMemFree(pwszID); pwszID = NULL; } } TRACE(_T("CMpcAudioRenderer::GetAudioDevice - Unable to find selected audio device, using the default end point!\n")); hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, ppMMDevice); SAFE_RELEASE(devices); return hr; }
HRESULT AudioRendererSettings::GetAudioDevice(IMMDevice** ppMMDevice) { Log("CWASAPIRenderFilter::GetAudioDevice"); CComPtr<IMMDeviceEnumerator> enumerator; IMMDeviceCollection* devices; HRESULT hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); if (FAILED(hr)) { Log(" failed to create MMDeviceEnumerator!"); return hr; } Log("Target end point: %S", m_wWASAPIPreferredDeviceId); if (GetAvailableAudioDevices(&devices, NULL, false) == S_OK) { UINT count = 0; hr = devices->GetCount(&count); if (FAILED(hr)) { Log(" devices->GetCount failed: (0x%08x)", hr); return hr; } for (UINT i = 0; i < count; i++) { LPWSTR pwszID = NULL; IMMDevice* endpoint = NULL; hr = devices->Item(i, &endpoint); if (SUCCEEDED(hr)) { hr = endpoint->GetId(&pwszID); if (SUCCEEDED(hr)) { // Found the configured audio endpoint if (wcscmp(pwszID, m_wWASAPIPreferredDeviceId) == 0) { enumerator->GetDevice(m_wWASAPIPreferredDeviceId, ppMMDevice); SAFE_RELEASE(devices); *ppMMDevice = endpoint; CoTaskMemFree(pwszID); pwszID = NULL; return S_OK; } else { SAFE_RELEASE(endpoint); CoTaskMemFree(pwszID); pwszID = NULL; } } else Log(" devices->GetId failed: (0x%08x)", hr); } else Log(" devices->Item failed: (0x%08x)", hr); CoTaskMemFree(pwszID); pwszID = NULL; } } Log("Unable to find selected audio device, using the default end point!"); hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, ppMMDevice); IPropertyStore* pProps = NULL; if (SUCCEEDED((*ppMMDevice)->OpenPropertyStore(STGM_READ, &pProps))) { LPWSTR pwszID = NULL; PROPVARIANT varName; PropVariantInit(&varName); PROPVARIANT eventDriven; PropVariantInit(&eventDriven); PROPVARIANT speakerMask; PropVariantInit(&speakerMask); if (SUCCEEDED(pProps->GetValue(PKEY_Device_FriendlyName, &varName)) && SUCCEEDED(pProps->GetValue(PKEY_AudioEndpoint_Supports_EventDriven_Mode, &eventDriven)) && SUCCEEDED((*ppMMDevice)->GetId(&pwszID))) { pProps->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &speakerMask); Log("Default audio endpoint: \"%S\" (%S) - pull mode: %d sprk mask: %d" ,varName.pwszVal, pwszID, eventDriven.intVal, speakerMask.uintVal); } CoTaskMemFree(pwszID); pwszID = NULL; PropVariantClear(&varName); PropVariantClear(&eventDriven); PropVariantClear(&speakerMask); SAFE_RELEASE(pProps) }