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; }
void printVolume() { HRESULT hr; bool decibels = false; bool scalar = false; double newVolume = 10; // ------------------------- CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; // ------------------------- float currentVolume = 0; endpointVolume->GetMasterVolumeLevel(¤tVolume); printf("Current volume in dB is: %f\n", currentVolume); hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume); printf("Current volume as a scalar is: %f\n", currentVolume); }
static void fillDeviceSelector(QComboBox *const deviceSelector) { IMMDeviceEnumerator *pEnumerator = 0; IMMDeviceCollection *pCollection = 0; UINT count = 0; CoCreateInstance(CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void **>(&pEnumerator)); if (pEnumerator) { pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pCollection); } if (pCollection && FAILED(pCollection->GetCount(&count))) count = 0; for (ULONG i = 0; i < count; ++i) { IMMDevice *pEndpoint = 0; pCollection->Item(i, &pEndpoint); if (pEndpoint) { addDeviceSelectorItem(deviceSelector, pEndpoint); pEndpoint->Release(); } } safeRelease(pCollection); safeRelease(pEnumerator); }
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; }
bool ChangeVolume(double nVolume,bool bScalar) { HRESULT hr=NULL; bool decibels = false; bool scalar = false; double newVolume=nVolume; CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; // ------------------------- float currentVolume = 0; endpointVolume->GetMasterVolumeLevel(¤tVolume); //printf("Current volume in dB is: %f\n", currentVolume); hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume); //CString strCur=L""; //strCur.Format(L"%f",currentVolume); //AfxMessageBox(strCur); // printf("Current volume as a scalar is: %f\n", currentVolume); if (bScalar==false) { hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL); } else if (bScalar==true) { hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL); } endpointVolume->Release(); CoUninitialize(); return FALSE; }
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; }
IAudioEndpointVolume * GetEndpointVolume() { HRESULT hr; IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; return endpointVolume; }
Array AudioDriverWASAPI::audio_device_get_list(bool p_capture) { Array list; IMMDeviceCollection *devices = NULL; IMMDeviceEnumerator *enumerator = NULL; list.push_back(String("Default")); CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, Array()); hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, Array()); UINT count = 0; hr = devices->GetCount(&count); ERR_FAIL_COND_V(hr != S_OK, Array()); for (ULONG i = 0; i < count; 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); list.push_back(String(propvar.pwszVal)); PropVariantClear(&propvar); props->Release(); device->Release(); } devices->Release(); enumerator->Release(); return list; }
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(); } }
IAudioSessionEnumerator* GetAudioSessionEnumerator() { IMMDeviceEnumerator* deviceEnumerator = nullptr; CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice* device = nullptr; deviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &device); IAudioSessionManager2* sessionManager = nullptr; device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, nullptr, (void**)&sessionManager); IAudioSessionEnumerator* enumerator = nullptr; sessionManager->GetSessionEnumerator(&enumerator); deviceEnumerator->Release(); device->Release(); sessionManager->Release(); return enumerator; }
//------------------------------------------------------------------- // Initializes the CAudioSessionEventHandler object. long CAudioSessionEventHandler::Initialize() { _WINQ_FCONTEXT( "CAudioSessionEventHandler::Initialize" ); long hr = 0; IMMDeviceEnumerator* pDeviceEnumerator = 0; IMMDevice* pDevice = 0; IAudioSessionManager* pAudioSessionManager = 0; // Get the enumerator for the audio endpoint devices. hr = nsWinQAPI::COLE32::Instance().CoCreateInstance( reinterpret_cast< const ::IID& >( CLASS_MMDEVICEENUMERATOR ), 0, CLSCTX_INPROC_SERVER, reinterpret_cast< const ::IID& >( IMMDeviceEnumerator::_IID ), reinterpret_cast< void** >( &pDeviceEnumerator ) ); if( hr < 0 ) { goto done; } // Get the default audio endpoint that the SAR will use. hr = pDeviceEnumerator->GetDefaultAudioEndpoint( eRender, eConsole, // The SAR uses 'eConsole' by default. &pDevice ); if( hr < 0 ) { goto done; } // Get the session manager for this device. hr = pDevice->Activate( IAudioSessionManager::_IID, CLSCTX_INPROC_SERVER, 0, (void**) &pAudioSessionManager ); if( hr < 0 ) { goto done; } // Get the audio session. hr = pAudioSessionManager->GetAudioSessionControl(reinterpret_cast< const nsWin32::GUID* >(&NULL_GUID), // Get the default audio session. 0, // The session is not cross-process. &m_pAudioSession ); if( hr < 0 ) { goto done; } hr = pAudioSessionManager->GetSimpleAudioVolume(reinterpret_cast< const nsWin32::GUID* >(&NULL_GUID), 0, &m_pSimpleAudioVolume); done: pDeviceEnumerator->Release(); pDevice->Release(); pAudioSessionManager->Release(); return hr; }
// // Utility function to retrieve the session manager for the default audio endpoint. // HRESULT CMediaPlayer::GetSessionManager2() { HRESULT hr = S_OK; if (_SessionManager2 == NULL) { IMMDeviceEnumerator *deviceEnumerator; IMMDevice *endpoint = NULL; // // Start with the default endpoint. // hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&deviceEnumerator)); if (SUCCEEDED(hr)) { hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endpoint); deviceEnumerator->Release(); deviceEnumerator = NULL; } else { MessageBox(_AppWindow, L"Unable to instantiate MMDeviceEnumerator", L"Get SessionManager Error", MB_OK); } if (SUCCEEDED(hr)) { hr = endpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&_SessionManager2)); endpoint->Release(); if (FAILED(hr)) { MessageBox(_AppWindow, L"Unable to Activate session manager", L"Get SessionManager Error", MB_OK); } } else { MessageBox(_AppWindow, L"Unable to get default endpoint", L"Get SessionManager Error", MB_OK); } } return hr; }
/** * Initialize the EndpointVolume (volume controller). */ void master_volume::loadVolumeController() { m_endpointVolume = nullptr; HRESULT hr; IMMDeviceEnumerator *deviceEnumerator = nullptr; IMMDevice *defaultDevice = nullptr; // Get the list of audio devices hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); if (hr != S_OK) { logger.Error("master_volume::loadVolumeController(), CoCreateInstance failed with error: " + hr); return; } // Get the default audio device hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); if (hr != S_OK) { logger.Error("GetDefaultAudioEndpoint failed with error: " + hr); return; } // Free the device list if (deviceEnumerator) { deviceEnumerator->Release(); deviceEnumerator = nullptr; } // Load EndpointVolume (volume controller) hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)&m_endpointVolume); if (hr != S_OK) { logger.Error("master_volume::loadVolumeController(), defaultDevice->Activate failed with error: " + hr); return; } // Release the default device if (defaultDevice) { defaultDevice->Release(); defaultDevice = nullptr; } }
void SetMuteStatus() { HRESULT hr; CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); if (!SUCCEEDED(hr)) { CoUninitialize(); } IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; if (!SUCCEEDED(hr)) { CoUninitialize(); } IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; if (!SUCCEEDED(hr)) { CoUninitialize(); } // ------------------------- BOOL b; endpointVolume->GetMute(&b); b=!b; endpointVolume->SetMute(b, NULL); endpointVolume->Release(); CoUninitialize(); }
void InitializeAudioEndpoint(IAudioEndpointVolume **audioEndpoint) { HRESULT hr; // Initialize the COM library CoInitialize(nullptr); // Get audio device enumerator IMMDeviceEnumerator *deviceEnumerator = nullptr; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); if (hr != S_OK) { printf("Unable to create instance of MMDeviceEnumerator (error code: 0x%08lx)\n", hr); CoUninitialize(); exit(-1); } // Ask device enumerator for the default audio renderer IMMDevice *defaultDevice = nullptr; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = nullptr; if (hr != S_OK) { printf("Unable to get default audio endpoint (error code: 0x%08lx)\n", hr); CoUninitialize(); exit(-1); } // Ask default audio renderer for volume controller //IAudioEndpointVolume *endpointVolume = nullptr; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)audioEndpoint); defaultDevice->Release(); defaultDevice = nullptr; if (hr != S_OK) { printf("Unable to get default audio volume controller (error code: 0x%08lx)\n", hr); CoUninitialize(); exit(-1); } }
void propagateWithRawCurrentFormat(WAVEFORMATEX *toThis) { WAVEFORMATEX *pwfx; IMMDevice *pMMDevice; IAudioClient *pAudioClient; HANDLE hTask; DWORD nTaskIndex = 0; hTask = AvSetMmThreadCharacteristics(L"Capture", &nTaskIndex); HRESULT hr = get_default_device(&pMMDevice); if (FAILED(hr)) { assert(false); } // activate an (the default, for us, since we want loopback) IAudioClient hr = pMMDevice->Activate( __uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient ); if (FAILED(hr)) { ShowOutput("IMMDevice::Activate(IAudioClient) failed: hr = 0x%08x", hr); assert(false); } hr = pAudioClient->GetMixFormat(&pwfx); if (FAILED(hr)) { ShowOutput("IAudioClient::GetMixFormat failed: hr = 0x%08x\n", hr); CoTaskMemFree(pwfx); pAudioClient->Release(); assert(false); } pAudioClient->Stop(); AvRevertMmThreadCharacteristics(hTask); pAudioClient->Release(); pMMDevice->Release(); memcpy(toThis, pwfx, sizeof(WAVEFORMATEX)); CoTaskMemFree(pwfx); }
static MFDevice *NewDevice(LPCWSTR pwstrDeviceId) { MFDevice *pDev = NULL; IMMDevice *pDevice; gpEnumerator->GetDevice(pwstrDeviceId, &pDevice); if(pDevice) { // TODO: don't know if it's a capture device or not! if(1) { pDev = MFDevice_AllocDevice(MFDT_AudioRender, NULL); pDev->pInternal = gDevices.AllocAndZero(); GetDeviceInfo(pDevice, pDev); } else { pDev = MFDevice_AllocDevice(MFDT_AudioCapture, NULL); pDev->pInternal = gCaptureDevices.AllocAndZero(); GetDeviceInfo(pDevice, pDev); } pDevice->Release(); } return pDev; }
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(); } }
HRESULT get_specific_device(LPCWSTR szLongName, IMMDevice **ppMMDevice) { HRESULT hr = S_OK; *ppMMDevice = NULL; // get an enumerator IMMDeviceEnumerator *pMMDeviceEnumerator; hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator ); if (FAILED(hr)) { printf("CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x\n", hr); return hr; } IMMDeviceCollection *pMMDeviceCollection; // get all the active render endpoints hr = pMMDeviceEnumerator->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &pMMDeviceCollection ); pMMDeviceEnumerator->Release(); if (FAILED(hr)) { printf("IMMDeviceEnumerator::EnumAudioEndpoints failed: hr = 0x%08x\n", hr); return hr; } UINT count; hr = pMMDeviceCollection->GetCount(&count); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IMMDeviceCollection::GetCount failed: hr = 0x%08x\n", hr); return hr; } for (UINT i = 0; i < count; i++) { IMMDevice *pMMDevice; // get the "n"th device hr = pMMDeviceCollection->Item(i, &pMMDevice); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IMMDeviceCollection::Item failed: hr = 0x%08x\n", hr); return hr; } // open the property store on that device IPropertyStore *pPropertyStore; hr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore); if (FAILED(hr)) { pMMDevice->Release(); pMMDeviceCollection->Release(); printf("IMMDevice::OpenPropertyStore failed: hr = 0x%08x\n", hr); return hr; } // get the long name property PROPVARIANT pv; PropVariantInit(&pv); hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); pPropertyStore->Release(); if (FAILED(hr)) { pMMDevice->Release(); pMMDeviceCollection->Release(); printf("IPropertyStore::GetValue failed: hr = 0x%08x\n", hr); return hr; } if (VT_LPWSTR != pv.vt) { printf("PKEY_Device_FriendlyName variant type is %u - expected VT_LPWSTR", pv.vt); PropVariantClear(&pv); pMMDevice->Release(); pMMDeviceCollection->Release(); return E_UNEXPECTED; } // is it a match? if (0 == _wcsicmp(pv.pwszVal, szLongName)) { // did we already find it? if (NULL == *ppMMDevice) { *ppMMDevice = pMMDevice; pMMDevice->AddRef(); } else { printf("Found (at least) two devices named %ls\n", szLongName); PropVariantClear(&pv); pMMDevice->Release(); pMMDeviceCollection->Release(); return E_UNEXPECTED; } } pMMDevice->Release(); PropVariantClear(&pv); } pMMDeviceCollection->Release(); if (NULL == *ppMMDevice) { printf("Could not find a device named %ls\n", szLongName); return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); } return S_OK; }
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 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(); } }
void VolumeControl::init() { //initialize audio mixer interface #if defined (__APPLE__) #warning TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) //try to open mixer device if (mixerHandle == nullptr) { snd_mixer_selem_id_alloca(&mixerSelemId); //sets simple-mixer index and name snd_mixer_selem_id_set_index(mixerSelemId, mixerIndex); snd_mixer_selem_id_set_name(mixerSelemId, mixerName); //open mixer if (snd_mixer_open(&mixerHandle, 0) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Opened ALSA mixer"; //ok. attach to defualt card if (snd_mixer_attach(mixerHandle, mixerCard) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Attached to default card"; //ok. register simple element class if (snd_mixer_selem_register(mixerHandle, NULL, NULL) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Registered simple element class"; //ok. load registered elements if (snd_mixer_load(mixerHandle) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Loaded mixer elements"; //ok. find elements now mixerElem = snd_mixer_find_selem(mixerHandle, mixerSelemId); if (mixerElem != nullptr) { //wohoo. good to go... LOG(LogDebug) << "VolumeControl::init() - Mixer initialized"; } else { LOG(LogError) << "VolumeControl::init() - Failed to find mixer elements!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to load mixer elements!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to register simple element class!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to attach to default card!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to open ALSA mixer!"; } } #elif defined(WIN32) || defined(_WIN32) //get windows version information OSVERSIONINFOEXA osVer = {sizeof(OSVERSIONINFO)}; ::GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&osVer)); //check windows version if(osVer.dwMajorVersion < 6) { //Windows older than Vista. use mixer API. open default mixer if (mixerHandle == nullptr) { if (mixerOpen(&mixerHandle, 0, NULL, 0, 0) == MMSYSERR_NOERROR) { //retrieve info on the volume slider control for the "Speaker Out" line MIXERLINECONTROLS mixerLineControls; mixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS); mixerLineControls.dwLineID = 0xFFFF0000; //Id of "Speaker Out" line mixerLineControls.cControls = 1; //mixerLineControls.dwControlID = 0x00000000; //Id of "Speaker Out" line's volume slider mixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; //Get volume control mixerLineControls.pamxctrl = &mixerControl; mixerLineControls.cbmxctrl = sizeof(MIXERCONTROL); if (mixerGetLineControls((HMIXEROBJ)mixerHandle, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR) { LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume control!"; mixerClose(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to open mixer!"; } } } else { //Windows Vista or above. use EndpointVolume API. get device enumerator if (endpointVolume == nullptr) { CoInitialize(nullptr); IMMDeviceEnumerator * deviceEnumerator = nullptr; CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); if (deviceEnumerator != nullptr) { //get default endpoint IMMDevice * defaultDevice = nullptr; deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); if (defaultDevice != nullptr) { //retrieve endpoint volume defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)&endpointVolume); if (endpointVolume == nullptr) { LOG(LogError) << "VolumeControl::init() - Failed to get default audio endpoint volume!"; } //release default device. we don't need it anymore defaultDevice->Release(); } else { LOG(LogError) << "VolumeControl::init() - Failed to get default audio endpoint!"; } //release device enumerator. we don't need it anymore deviceEnumerator->Release(); } else { LOG(LogError) << "VolumeControl::init() - Failed to get audio endpoint enumerator!"; CoUninitialize(); } } } #endif }
void modifyVolume(char ch) { HRESULT hr; bool decibels = false; bool scalar = true; double newVolume = 10; // ------------------------- CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; // ------------------------- float currentVolume = 0; endpointVolume->GetMasterVolumeLevel(¤tVolume); //printf("Current volume in dB is: %f\n", currentVolume); hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume); float min, max, inc; endpointVolume->GetVolumeRange(&min, &max, &inc); //printf("Current volume as a scalar is: %f\n", currentVolume); if (ch == 'u') newVolume = currentVolume + 0.1; else if (ch == 'd') newVolume = currentVolume - 0.1; if (ch == 'm') { endpointVolume->SetMute(TRUE, NULL); } else if (ch == 'n') { endpointVolume->SetMute(FALSE, NULL); } else { if (decibels) { hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL); //endpointVolume->VolumeStepUp(NULL); } else if (scalar) { hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL); //endpointVolume->VolumeStepUp(NULL); } } endpointVolume->Release(); CoUninitialize(); }
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(); } } } }
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); }
std::vector<AudioDevice> EnumerateAudioDevices(_Out_opt_ AudioDevice* defaultDevice = nullptr) { UINT32 deviceCount = 0; IMMDeviceEnumerator *immDevEnum = nullptr; IMMDeviceCollection *immDevCollection = nullptr; IMMDevice *immDev = nullptr; std::vector<AudioDevice> vAudioDevices; HRESULT hResult = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**) &immDevEnum); if (FAILED(hResult)) { idLib::Warning( "Failed to get audio enumerator" ); return std::move(vAudioDevices); } if (defaultDevice != nullptr) { ZeroMemory(defaultDevice, sizeof(AudioDevice)); IMMDevice *defaultImmDev = nullptr; // @pjb: get the default audio endpoint and make it the first one in the list if (SUCCEEDED(immDevEnum->GetDefaultAudioEndpoint(eRender, eConsole, &defaultImmDev))) { GetAudioDeviceDetails(defaultImmDev, defaultDevice); defaultImmDev->Release(); } } hResult = immDevEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &immDevCollection); if (FAILED(hResult)) { idLib::Warning( "Failed to get audio endpoints" ); return std::move(vAudioDevices); } hResult = immDevCollection->GetCount(&deviceCount); if (FAILED(hResult)) { idLib::Warning( "No audio devices found" ); return std::move(vAudioDevices); } for (UINT i = 0; i < deviceCount; i++) { AudioDevice ad; hResult = immDevCollection->Item(i, &immDev); if (SUCCEEDED(hResult)) { hResult = GetAudioDeviceDetails(immDev, &ad); } if (SUCCEEDED(hResult)) { vAudioDevices.push_back(ad); } if (immDev != nullptr) { immDev->Release(); } } immDevCollection->Release(); immDevEnum->Release(); return std::move(vAudioDevices); }
long WasapiEngine::doInit(long rate, int const latency) { { IMMDevice *pDevice = 0; IMMDeviceEnumerator *pEnumerator = 0; HRESULT hr; if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void **>(&pEnumerator)))) { std::cerr << "CoCreateInstance failed" << std::endl; return -1; } if (deviceSelector->count() > 1) { hr = pEnumerator->GetDevice( deviceSelector->itemData(deviceIndex).value<std::wstring>().c_str(), &pDevice); } else hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); pEnumerator->Release(); if (FAILED(hr)) { std::cerr << "pEnumerator->GetDefaultAudioEndpoint failed" << std::endl; return -1; } hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, 0, reinterpret_cast<void **>(&pAudioClient)); pDevice->Release(); if (FAILED(hr)) { std::cerr << "pDevice->Activate failed" << std::endl; return -1; } } { static GUID const ksdataformat_subtype_pcm = { WAVE_FORMAT_PCM, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; WAVEFORMATEXTENSIBLE wfext; std::memset(&wfext, 0, sizeof wfext); wfext.Format.cbSize = sizeof wfext - sizeof wfext.Format; wfext.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfext.Format.nChannels = 2; wfext.Format.nSamplesPerSec = rate; wfext.Format.wBitsPerSample = 16; wfext.Samples.wValidBitsPerSample = 16; wfext.SubFormat = ksdataformat_subtype_pcm; wfext.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; if (!exclusive_.value()) { WAVEFORMATEX *mwfe = 0; if (SUCCEEDED(pAudioClient->GetMixFormat(&mwfe)) && mwfe) { wfext.Format.nChannels = std::max<int>(mwfe->nChannels, 2); wfext.Format.nSamplesPerSec = mwfe->nSamplesPerSec; if (mwfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { wfext.dwChannelMask = reinterpret_cast<WAVEFORMATEXTENSIBLE *>(mwfe)->dwChannelMask; } CoTaskMemFree(mwfe); } else std::cerr << "pAudioClient->GetMixFormat failed\r\n"; if (!(eventHandle_ = CreateEventA(0, false, false, 0))) std::cerr << "CreateEvent failed\r\n"; } wfext.Format.nBlockAlign = wfext.Format.nChannels * wfext.Format.wBitsPerSample >> 3; wfext.Format.nAvgBytesPerSec = wfext.Format.nSamplesPerSec * wfext.Format.nBlockAlign; nchannels_ = wfext.Format.nChannels; rate = wfext.Format.nSamplesPerSec; HRESULT hr = pAudioClient->Initialize( exclusive_.value() ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED, eventHandle_ ? AUDCLNT_STREAMFLAGS_EVENTCALLBACK : 0, latency * 10000, 0, &wfext.Format, 0); if (FAILED(hr)) { std::cerr << "pAudioClient->Initialize failed: " << hr << "\r\n"; return -1; } } if (eventHandle_ && FAILED(pAudioClient->SetEventHandle(eventHandle_))) { std::cerr << "pAudioClient->SetEventHandle failed\r\n"; return -1; } if (FAILED(pAudioClient->GetBufferSize(&bufferFrameCount))) { std::cerr << "pAudioClient->GetBufferSize failed" << std::endl; return -1; } if (FAILED(pAudioClient->GetService(IID_IAudioRenderClient, reinterpret_cast<void **>(&pRenderClient)))) { std::cerr << "pAudioClient->GetService failed" << std::endl; return -1; } if (FAILED(pAudioClient->GetService(IID_IAudioClock, reinterpret_cast<void **>(&pAudioClock)))) { std::cerr << "pAudioClient->GetService failed" << std::endl; return -1; } { UINT64 freq = 0; pAudioClock->GetFrequency(&freq); posFrames = freq / (rate ? rate : 1); } pos_ = 0; est = RateEst(rate, bufferFrameCount); return rate; }
/* ======================== idSoundHardware_XAudio2::Init ======================== */ void idSoundHardware_XAudio2::Init() { cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL ); DWORD xAudioCreateFlags = 0; // RB: not available on Windows 8 SDK #if !defined(USE_WINRT) && defined(_DEBUG) // (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG) xAudioCreateFlags |= XAUDIO2_DEBUG_ENGINE; #endif // RB end XAUDIO2_PROCESSOR xAudioProcessor = XAUDIO2_DEFAULT_PROCESSOR; // RB: not available on Windows 8 SDK if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) ) { #if !defined(USE_WINRT) && defined(_DEBUG) // (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG) if( xAudioCreateFlags & XAUDIO2_DEBUG_ENGINE ) { // in case the debug engine isn't installed xAudioCreateFlags &= ~XAUDIO2_DEBUG_ENGINE; if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) ) { idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." ); return; } } else #endif // RB end { idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." ); return; } } #ifdef _DEBUG XAUDIO2_DEBUG_CONFIGURATION debugConfiguration = { 0 }; debugConfiguration.TraceMask = XAUDIO2_LOG_WARNINGS; debugConfiguration.BreakMask = XAUDIO2_LOG_ERRORS; pXAudio2->SetDebugConfiguration( &debugConfiguration ); #endif // Register the sound engine callback pXAudio2->RegisterForCallbacks( &soundEngineCallback ); soundEngineCallback.hardware = this; UINT32 deviceCount = 0; DWORD outputSampleRate = 44100; // Max( (DWORD)XAUDIO2FX_REVERB_MIN_FRAMERATE, Min( (DWORD)XAUDIO2FX_REVERB_MAX_FRAMERATE, deviceDetails.OutputFormat.Format.nSamplesPerSec ) ); // RB: not available on Windows 8 SDK #if defined(USE_WINRT) //(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) IMMDeviceEnumerator* immDevEnum = nullptr; IMMDeviceCollection* immDevCollection = nullptr; IMMDevice* immDev = nullptr; std::vector<AudioDevice> vAudioDevices; HRESULT hResult = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), ( void** ) &immDevEnum ); if( FAILED( hResult ) ) { idLib::Warning( "Failed to get audio enumerator" ); pXAudio2->Release(); pXAudio2 = NULL; return; } hResult = immDevEnum->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &immDevCollection ); if( FAILED( hResult ) ) { idLib::Warning( "Failed to get audio endpoints" ); pXAudio2->Release(); pXAudio2 = NULL; return; } hResult = immDevCollection->GetCount( &deviceCount ); if( FAILED( hResult ) ) { idLib::Warning( "No audio devices found" ); pXAudio2->Release(); pXAudio2 = NULL; return; } for( UINT i = 0; i < deviceCount; i++ ) { IPropertyStore* propStore = nullptr; PROPVARIANT varName; PROPVARIANT varId; PropVariantInit( &varId ); PropVariantInit( &varName ); hResult = immDevCollection->Item( i, &immDev ); if( SUCCEEDED( hResult ) ) { hResult = immDev->OpenPropertyStore( STGM_READ, &propStore ); } if( SUCCEEDED( hResult ) ) { hResult = propStore->GetValue( PKEY_AudioEndpoint_Path, &varId ); } if( SUCCEEDED( hResult ) ) { hResult = propStore->GetValue( PKEY_Device_FriendlyName, &varName ); } if( SUCCEEDED( hResult ) ) { assert( varId.vt == VT_LPWSTR ); assert( varName.vt == VT_LPWSTR ); // Now save somewhere the device display name & id AudioDevice ad; ad.name = varName.pwszVal; ad.id = varId.pwszVal; vAudioDevices.push_back( ad ); } PropVariantClear( &varName ); PropVariantClear( &varId ); if( propStore != nullptr ) { propStore->Release(); } if( immDev != nullptr ) { immDev->Release(); } } immDevCollection->Release(); immDevEnum->Release(); int preferredDevice = s_device.GetInteger(); if( !vAudioDevices.empty() ) { if( SUCCEEDED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, vAudioDevices.at( 0 ).id.c_str(), NULL, AudioCategory_GameEffects ) ) ) { XAUDIO2_VOICE_DETAILS deviceDetails; pMasterVoice->GetVoiceDetails( &deviceDetails ); pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) ); outputChannels = deviceDetails.InputChannels; DWORD win8_channelMask; pMasterVoice->GetChannelMask( &win8_channelMask ); channelMask = ( unsigned int )win8_channelMask; idLib::Printf( "Using device %s\n", vAudioDevices.at( 0 ).name ); } else { idLib::Warning( "Failed to create master voice" ); pXAudio2->Release(); pXAudio2 = NULL; return; } } #else if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 ) { idLib::Warning( "No audio devices found" ); pXAudio2->Release(); pXAudio2 = NULL; return; } idCmdArgs args; listDevices_f( args ); int preferredDevice = s_device.GetInteger(); if( preferredDevice < 0 || preferredDevice >= ( int )deviceCount ) { int preferredChannels = 0; for( unsigned int i = 0; i < deviceCount; i++ ) { XAUDIO2_DEVICE_DETAILS deviceDetails; if( pXAudio2->GetDeviceDetails( i, &deviceDetails ) != S_OK ) { continue; } if( deviceDetails.Role & DefaultGameDevice ) { // if we find a device the user marked as their preferred 'game' device, then always use that preferredDevice = i; preferredChannels = deviceDetails.OutputFormat.Format.nChannels; break; } if( deviceDetails.OutputFormat.Format.nChannels > preferredChannels ) { preferredDevice = i; preferredChannels = deviceDetails.OutputFormat.Format.nChannels; } } } idLib::Printf( "Using device %d\n", preferredDevice ); XAUDIO2_DEVICE_DETAILS deviceDetails; if( pXAudio2->GetDeviceDetails( preferredDevice, &deviceDetails ) != S_OK ) { // One way this could happen is if a device is removed between the loop and this line of code // Highly unlikely but possible idLib::Warning( "Failed to get device details" ); pXAudio2->Release(); pXAudio2 = NULL; return; } if( FAILED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, preferredDevice, NULL ) ) ) { idLib::Warning( "Failed to create master voice" ); pXAudio2->Release(); pXAudio2 = NULL; return; } pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) ); outputChannels = deviceDetails.OutputFormat.Format.nChannels; channelMask = deviceDetails.OutputFormat.dwChannelMask; #endif // #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) idSoundVoice::InitSurround( outputChannels, channelMask ); // --------------------- // Create VU Meter Effect // --------------------- IUnknown* vuMeter = NULL; XAudio2CreateVolumeMeter( &vuMeter, 0 ); XAUDIO2_EFFECT_DESCRIPTOR descriptor; descriptor.InitialState = true; descriptor.OutputChannels = outputChannels; descriptor.pEffect = vuMeter; XAUDIO2_EFFECT_CHAIN chain; chain.EffectCount = 1; chain.pEffectDescriptors = &descriptor; pMasterVoice->SetEffectChain( &chain ); vuMeter->Release(); // --------------------- // Create VU Meter Graph // --------------------- vuMeterRMS = console->CreateGraph( outputChannels ); vuMeterPeak = console->CreateGraph( outputChannels ); // DG: make sure they're not NULL (as it's currently the case with the cegui-based console) if( vuMeterRMS && vuMeterPeak ) { vuMeterRMS->Enable( false ); vuMeterPeak->Enable( false ); memset( vuMeterPeakTimes, 0, sizeof( vuMeterPeakTimes ) ); vuMeterPeak->SetFillMode( idDebugGraph::GRAPH_LINE ); vuMeterPeak->SetBackgroundColor( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) ); vuMeterRMS->AddGridLine( 0.500f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.250f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.125f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); const char* channelNames[] = { "L", "R", "C", "S", "Lb", "Rb", "Lf", "Rf", "Cb", "Ls", "Rs" }; for( int i = 0, ci = 0; ci < sizeof( channelNames ) / sizeof( channelNames[0] ); ci++ ) { if( ( channelMask & BIT( ci ) ) == 0 ) { continue; } vuMeterRMS->SetLabel( i, channelNames[ci] ); i++; } } // --------------------- // Create submix buffer // --------------------- if( FAILED( pXAudio2->CreateSubmixVoice( &pSubmixVoice, 1, outputSampleRate, 0, 0, NULL, NULL ) ) ) { idLib::FatalError( "Failed to create submix voice" ); } // XAudio doesn't really impose a maximum number of voices voices.SetNum( voices.Max() ); freeVoices.SetNum( voices.Max() ); zombieVoices.SetNum( 0 ); for( int i = 0; i < voices.Num(); i++ ) { freeVoices[i] = &voices[i]; } // RB end }
HRESULT list_devices() { HRESULT hr = S_OK; // get an enumerator IMMDeviceEnumerator *pMMDeviceEnumerator; hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator ); if (FAILED(hr)) { printf("CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x\n", hr); return hr; } IMMDeviceCollection *pMMDeviceCollection; // get all the active render endpoints hr = pMMDeviceEnumerator->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &pMMDeviceCollection ); pMMDeviceEnumerator->Release(); if (FAILED(hr)) { printf("IMMDeviceEnumerator::EnumAudioEndpoints failed: hr = 0x%08x\n", hr); return hr; } UINT count; hr = pMMDeviceCollection->GetCount(&count); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IMMDeviceCollection::GetCount failed: hr = 0x%08x\n", hr); return hr; } printf("Active render endpoints found: %u\n", count); for (UINT i = 0; i < count; i++) { IMMDevice *pMMDevice; // get the "n"th device hr = pMMDeviceCollection->Item(i, &pMMDevice); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IMMDeviceCollection::Item failed: hr = 0x%08x\n", hr); return hr; } // open the property store on that device IPropertyStore *pPropertyStore; hr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore); pMMDevice->Release(); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IMMDevice::OpenPropertyStore failed: hr = 0x%08x\n", hr); return hr; } // get the long name property PROPVARIANT pv; PropVariantInit(&pv); hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); pPropertyStore->Release(); if (FAILED(hr)) { pMMDeviceCollection->Release(); printf("IPropertyStore::GetValue failed: hr = 0x%08x\n", hr); return hr; } if (VT_LPWSTR != pv.vt) { printf("PKEY_Device_FriendlyName variant type is %u - expected VT_LPWSTR", pv.vt); PropVariantClear(&pv); pMMDeviceCollection->Release(); return E_UNEXPECTED; } printf(" %ls\n", pv.pwszVal); PropVariantClear(&pv); } pMMDeviceCollection->Release(); return S_OK; }