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(&currentVolume);
	printf("Current volume in dB is: %f\n", currentVolume);

	hr = endpointVolume->GetMasterVolumeLevelScalar(&currentVolume);
	printf("Current volume as a scalar is: %f\n", currentVolume);
}
bool GetWin7AudioState(const VolumeAction action)
{
	IMMDevice * pEndpoint = 0;
	IAudioEndpointVolume * pEndptVol = 0;
	bool success = false;

	if (InitCom())
	{
		if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK)
		{
			if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK)
			{
				if (pEndptVol->GetMute(&is_mute) == S_OK && action == TOGGLE_MUTE)
				{
					success = pEndptVol->SetMute(is_mute == TRUE ? FALSE : TRUE, 0) == S_OK;
				}
				// get current volume
				float vol = 0.0f;
				if (action != TOGGLE_MUTE && pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK)
				{
					master_volume = vol;
				}
			}
		}
	}

	SAFE_RELEASE(pEndptVol)
	SAFE_RELEASE(pEndpoint)
	UnInitCom();
	return success;
}
Example #3
0
// Public method
//   Sets the volume level of the default audio session
//   of the currently selected endpoint rendering device.
// float fVolume: the range of the value from 0.0 to 1.0
AUDIO_DEVICE_API HRESULT SetCaptureListDeviceVolume(DeviceInfo *pDeviceInfo, int index, float fVolume)
{
	InternalDeviceInfo *pInternalDeviceInfo = (InternalDeviceInfo *) pDeviceInfo;

    HRESULT hr;
	IMMDevice *pDevice = NULL;
	IAudioEndpointVolume *pAudioVolume = NULL;

    if (pInternalDeviceInfo->pCaptureCollection != NULL) {
        hr = pInternalDeviceInfo->pCaptureCollection->Item(index, &pDevice);
    }
	if (hr != S_OK) goto errors;

    hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioVolume);
	if (hr != S_OK) goto errors;

    // EventContext is used to identify the action owner when client receive volume change notification.
	// See the details in MSSDK/Samples/MultiMedia/Audio/WinAudio/player.cpp
    hr = pAudioVolume->SetMasterVolumeLevelScalar(fVolume, &g_EventContext); 

errors:
    SAFE_RELEASE(pAudioVolume);
    SAFE_RELEASE(pDevice);
	return hr;
}
Example #4
0
// 获取设备音量
int CCoreAudioVolume::GetDevicePlayVol(void)
{
    IMMDeviceEnumerator* pEnumerator;
    IMMDeviceCollection* pCollection = NULL;
    IMMDevice *pDevice = NULL;
    IAudioEndpointVolume *pVolumeAPI=NULL;
    UINT deviceCount = 0;
    HRESULT hr;
    float fVolume = -1;

    CoInitializeEx( NULL , COINIT_MULTITHREADED );
    //实例化 MMDeviceEnumerator 枚举器
    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
    if (hr != S_OK)
    {
        goto FreeEnumerator;
    }
    // 枚举 设备到设备容器 eRander:放音设备,DEVICE_STATE_ACTIVE 为当前已激活的设备,禁用和无连接的用其他状态参数
    hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATE_ACTIVE , &pCollection );
    if (hr != S_OK)
    {
        goto FreeCollection;
    }
    // 设备容器里的总数
    hr = pCollection->GetCount(&deviceCount);
    if (hr != S_OK)
    {
        goto FreeCollection;
    }

    for (UINT dev=0; dev<deviceCount; dev++)
    {
        pDevice = NULL;
        hr = pCollection->Item(dev,&pDevice);
        if (hr == S_OK)
        {
            if (VerifyDev(pDevice,eRender))
            {   // 用 pDevice 的 Activate 方法初始一个 IAudioEndpointVolume 接口
                hr = pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
                // 使用 IAudioEndpintVolume 的方法获取音量,设置音量,设置静音等
                hr = pVolumeAPI->GetMasterVolumeLevelScalar(&fVolume);
                break;
            }
        }
    }

FreeCollection:
    SAFE_RELEASE(pCollection);
FreeEnumerator:
    SAFE_RELEASE(pEnumerator);
    CoUninitialize();
    if (fVolume > 0)
        return fVolume*100;
    else
        return fVolume;

    return 0;
}
// ----------------------------------------------------------------------------
//
AudioVolumeController* AudioVolumeController::createVolumeController( )
{
    HRESULT hr;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDefaultDevice = NULL;
    IAudioEndpointVolume *endpointVolume = NULL;
    LPWSTR pstrDefaultId = NULL;
    IPropertyStore *pProperties = NULL;

    try {
        hr = CoCreateInstance(
               CLSID_MMDeviceEnumerator, NULL,
               CLSCTX_ALL, IID_IMMDeviceEnumerator,
               (void**)&pEnumerator);
        AUDIO_VOLUME_ASSERT( hr, "Cannot create COM device enumerator instance" );

        // Get the default audio endpoint (if we don't get one its not an error)
        hr = pEnumerator->GetDefaultAudioEndpoint( eRender, eConsole, &pDefaultDevice );
        AUDIO_VOLUME_ASSERT( hr, "Cannot get default audio render device" );

        hr = pDefaultDevice->OpenPropertyStore( STGM_READ, &pProperties );
        AUDIO_VOLUME_ASSERT( hr, "Cannot open IMMDevice property store" );

        PROPVARIANT varName;
        // Initialize container for property value.
        PropVariantInit(&varName);

        // Get the endpoint's friendly-name property.
        hr = pProperties->GetValue( PKEY_Device_DeviceDesc , &varName);
        AUDIO_VOLUME_ASSERT( hr, "Cannot open IMMDevice name property" );

        CString render_name = CW2A( varName.pwszVal );

        DMXStudio::log_status( "Default audio render device '%s'", render_name );

        PropVariantClear(&varName);

        hr = pDefaultDevice->Activate( IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume );
        AUDIO_VOLUME_ASSERT( hr, "Cannot activate default render device" );

        SAFE_RELEASE( pDefaultDevice );
        SAFE_RELEASE( pProperties );
        SAFE_RELEASE( pEnumerator );

        CoTaskMemFree( pstrDefaultId );

        return new AudioVolumeController( endpointVolume, render_name );
    }
    catch ( ... ) {
        CoTaskMemFree( pstrDefaultId );

        SAFE_RELEASE( pDefaultDevice );
        SAFE_RELEASE( pProperties );
        SAFE_RELEASE( pEnumerator );

        throw;
    }
}
Example #6
0
    BlankAudioPlayback(CTSTR lpDevice)
    {
        const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
        const IID IID_IMMDeviceEnumerator    = __uuidof(IMMDeviceEnumerator);
        const IID IID_IAudioClient           = __uuidof(IAudioClient);
        const IID IID_IAudioRenderClient     = __uuidof(IAudioRenderClient);

        HRESULT err;
        err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator);
        if(FAILED(err))
            CrashError(TEXT("Could not create IMMDeviceEnumerator: 0x%08lx"), err);

        if (scmpi(lpDevice, TEXT("Default")) == 0)
            err = mmEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &mmDevice);
        else
            err = mmEnumerator->GetDevice(lpDevice, &mmDevice);
        if(FAILED(err))
            CrashError(TEXT("Could not create IMMDevice"));

        err = mmDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&mmClient);
        if(FAILED(err))
            CrashError(TEXT("Could not create IAudioClient"));

        WAVEFORMATEX *pwfx;
        err = mmClient->GetMixFormat(&pwfx);
        if(FAILED(err))
            CrashError(TEXT("Could not get mix format from audio client"));

        UINT inputBlockSize = pwfx->nBlockAlign;

        err = mmClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, ConvertMSTo100NanoSec(1000), 0, pwfx, NULL);
        if(FAILED(err))
            CrashError(TEXT("Could not initialize audio client, error = %08lX"), err);

        err = mmClient->GetService(IID_IAudioRenderClient, (void**)&mmRender);
        if(FAILED(err))
            CrashError(TEXT("Could not get audio render client"));

        //----------------------------------------------------------------

        UINT bufferFrameCount;
        err = mmClient->GetBufferSize(&bufferFrameCount);
        if(FAILED(err))
            CrashError(TEXT("Could not get audio buffer size"));

        BYTE *lpData;
        err = mmRender->GetBuffer(bufferFrameCount, &lpData);
        if(FAILED(err))
            CrashError(TEXT("Could not get audio buffer"));

        zero(lpData, bufferFrameCount*inputBlockSize);

        mmRender->ReleaseBuffer(bufferFrameCount, 0);//AUDCLNT_BUFFERFLAGS_SILENT); //probably better if it doesn't know

        if(FAILED(mmClient->Start()))
            CrashError(TEXT("Could not start audio source"));
    }
HRESULT CAudioSessionVolume::Initialize()
{
    HRESULT hr = S_OK;

    IMMDeviceEnumerator *pDeviceEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioSessionManager *pAudioSessionManager = NULL;

    // Get the enumerator for the audio endpoint devices.
    hr = CoCreateInstance( 
        __uuidof(MMDeviceEnumerator), 
        NULL, 
        CLSCTX_INPROC_SERVER, 
        IID_PPV_ARGS(&pDeviceEnumerator)
        );

    if (FAILED(hr)) { 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 (FAILED(hr)) { goto done; }

    // Get the session manager for this device.
    hr = pDevice->Activate( 
        __uuidof(IAudioSessionManager), 
        CLSCTX_INPROC_SERVER, 
        NULL, 
        (void**) &pAudioSessionManager 
        );
    if (FAILED(hr)) { goto done; }

    // Get the audio session. 
    hr = pAudioSessionManager->GetAudioSessionControl( 
        &GUID_NULL,     // Get the default audio session. 
        FALSE,          // The session is not cross-process.
        &m_pAudioSession 
        );
    if (FAILED(hr)) { goto done; }

    hr = pAudioSessionManager->GetSimpleAudioVolume( 
        &GUID_NULL, 0, &m_pSimpleAudioVolume 
        );

done:
    SafeRelease(&pDeviceEnumerator);
    SafeRelease(&pDevice);
    SafeRelease(&pAudioSessionManager);
    return hr;
}
Example #8
0
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(&currentVolume);
		//printf("Current volume in dB is: %f\n", currentVolume);

		hr = endpointVolume->GetMasterVolumeLevelScalar(&currentVolume);
		//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;
}
Example #9
0
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;
}
Example #10
0
HRESULT GetAudioMeterInformation(IAudioMeterInformation **ppAudioMeterInformation) {
    if (NULL == ppAudioMeterInformation) {
        ERR(L"GetAudioMeterInformation was passed a NULL pointer");
        return E_POINTER;
    }

    // CoCreate an IMMDeviceEnumerator
    IMMDeviceEnumerator *pMMDeviceEnumerator = NULL;
    HRESULT hr = CoCreateInstance(
        __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, 
        __uuidof(IMMDeviceEnumerator),
        (void**)&pMMDeviceEnumerator
    );
    if (FAILED(hr)) {
        ERR(L"CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x", hr);
        return hr;
    }
    ReleaseOnExit releaseMMDeviceEnumerator(pMMDeviceEnumerator);
    
    // Get the default console render endpoint
    IMMDevice *pMMDevice = NULL;
    hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pMMDevice);
    if (FAILED(hr)) {
        ERR(L"IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: hr = 0x%08x", hr);
        return hr;
    }
    ReleaseOnExit releaseMMDevice(pMMDevice);
    
    // Activate an IAudioMeterInformation
    IAudioMeterInformation *pAudioMeterInformation = NULL;
    hr = pMMDevice->Activate(
        __uuidof(IAudioMeterInformation),
        CLSCTX_ALL,
        NULL,
        reinterpret_cast<void**>(&pAudioMeterInformation)
    );
    if (FAILED(hr)) {
        ERR(L"IMMDevice::Activate(IAudioMeterInformation) failed: hr = 0x%08x", hr);
        return hr;
    }
    ReleaseOnExit releaseAudioMeterInformation(pAudioMeterInformation);

    pAudioMeterInformation->AddRef();
    *ppAudioMeterInformation = pAudioMeterInformation;
 
    return S_OK;
}
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;
}
Example #12
0
	//-------------------------------------------------------------------
	//  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;
	}
Example #13
0
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();
}
Example #14
0
/**
* 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;
    }
}
Example #15
0
//设置应用程序静音
bool CCoreAudioVolume::SetMute(BOOL bMute)
{
    //IAudioSessionControl *pAudioSection = NULL;
    ISimpleAudioVolume	 *pAudioVolume = NULL;
    IAudioSessionManager *pManager = NULL;
    IMMDevice			 *pDevice = NULL;
    HRESULT hr;

    std::vector<IMMDevice*>::iterator iter = m_vArrayDevice.begin();
    for(; iter != m_vArrayDevice.end(); iter++)
    {
        pDevice = *iter;
        ATLASSERT(pDevice != NULL);

        hr = pDevice->Activate(__uuidof(IAudioSessionManager),
                               CLSCTX_INPROC_SERVER, NULL,
                               (void**)&pManager);

        if(FAILED(hr)) continue;

        hr = pManager->GetAudioSessionControl(NULL, 0, &m_pAudioSection);
        CMutedSessionEvents* pMutedse=new CMutedSessionEvents(pManager);
        hr = m_pAudioSection->RegisterAudioSessionNotification(pMutedse);
        hr = pManager->GetSimpleAudioVolume(NULL, 0, &pAudioVolume);

        if(SUCCEEDED(hr))
        {
            pAudioVolume->SetMute(bMute, &GUID_NULL);
            //pAudioVolume->SetMasterVolume()
        }
        else
        {
            ATLASSERT(FALSE);
        }
    }

    SAFE_RELEASE(pManager);
    SAFE_RELEASE(pAudioVolume);

    return true;
}
Example #16
0
//
//  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;
}
Example #17
0
//
//  Initialize the capturer.
//
bool CWASAPICapture::Initialize(UINT32 EngineLatency)
{
    //
    //  Create our shutdown event - we want auto reset events that start in the not-signaled state.
    //
    _ShutdownEvent = CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
    PersistentAssert(_ShutdownEvent != NULL, "CreateEventEx failed");
    
    //
    //  Create our stream switch event- we want auto reset events that start in the not-signaled state.
    //  Note that we create this event even if we're not going to stream switch - that's because the event is used
    //  in the main loop of the capturer and thus it has to be set.
    //
    _StreamSwitchEvent = CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
    PersistentAssert(_StreamSwitchEvent != NULL, "CreateEventEx failed");
    
    //
    //  Now activate an IAudioClient object on our preferred endpoint and retrieve the mix format for that endpoint.
    //
    HRESULT hr = _Endpoint->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&_AudioClient));
    PersistentAssert(SUCCEEDED(hr), "_Endpoint->Activate failed");

    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&_DeviceEnumerator));
    PersistentAssert(SUCCEEDED(hr), "CoCreateInstance failed");

    //
    // Load the MixFormat.  This may differ depending on the shared mode used
    //
    LoadFormat();
    
    //
    //  Remember our configured latency in case we'll need it for a stream switch later.
    //
    _EngineLatencyInMS = EngineLatency;

    InitializeAudioEngine();
    return true;
}
Example #18
0
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);
	}
}
Example #19
0
// This method will set the specified channel volume.
// float fVolume: the range of the value from 0.0 to 1.0
AUDIO_DEVICE_API HRESULT SetCaptureListDeviceChannelVolume(DeviceInfo *pDeviceInfo, int index, float fVolume, UINT iChannel)
{
	InternalDeviceInfo *pInternalDeviceInfo = (InternalDeviceInfo *) pDeviceInfo;

    HRESULT hr;
	IMMDevice *pDevice = NULL;
	IAudioEndpointVolume *pAudioVolume = NULL;

    if (pInternalDeviceInfo->pCaptureCollection != NULL) {
        hr = pInternalDeviceInfo->pCaptureCollection->Item(index, &pDevice);
    }
	if (hr != S_OK) goto errors;

    hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioVolume);
	if (hr != S_OK) goto errors;

    hr = pAudioVolume->SetChannelVolumeLevelScalar(iChannel, fVolume, &g_EventContext);

errors:
    SAFE_RELEASE(pAudioVolume);
    SAFE_RELEASE(pDevice);
	return hr;
}
Example #20
0
// This method will get the number of channels.
AUDIO_DEVICE_API HRESULT GetCaptureListDeviceChannelCount(DeviceInfo *pDeviceInfo, int index, UINT *iCount)
{
	InternalDeviceInfo *pInternalDeviceInfo = (InternalDeviceInfo *) pDeviceInfo;

    HRESULT hr;
	IMMDevice *pDevice = NULL;
	IAudioEndpointVolume *pAudioVolume = NULL;

    if (pInternalDeviceInfo->pCaptureCollection != NULL) {
        hr = pInternalDeviceInfo->pCaptureCollection->Item(index, &pDevice);
    }
	if (hr != S_OK) goto errors;

    hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioVolume);
	if (hr != S_OK) goto errors;

    hr = pAudioVolume->GetChannelCount(iCount);

errors:
    SAFE_RELEASE(pAudioVolume);
    SAFE_RELEASE(pDevice);
	return hr;
}
bool SetWin7Volume(UINT volume, int offset = 0)
{
	IMMDevice * pEndpoint = 0;
	IAudioEndpointVolume * pEndptVol = 0;
	bool success = false;

	if (InitCom())
	{
		if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK)
		{
			if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK)
			{
				pEndptVol->SetMute(FALSE, 0);
				float vol = 0.0f;
				if (offset != 0) // change master volume + offset
				{
					float off = static_cast<float>(offset) / 100.0f;
					vol = master_volume + off;
					vol = (vol < 0.0f) ? 0.0f : ((vol > 1.0f) ? 1.0f : vol);
				}
				else
				{
					vol = (float)volume / 100.0f;
				}
				// set to volume
				success = pEndptVol->SetMasterVolumeLevelScalar(vol, 0) == S_OK;
				if (success) success = pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK;
				if (success) master_volume = vol;
			}
		}
	}

	SAFE_RELEASE(pEndptVol)
	SAFE_RELEASE(pEndpoint)
	UnInitCom();
	return success;
}
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); 
}
Example #23
0
void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
{
  CAEDeviceInfo        deviceInfo;

  IMMDeviceEnumerator* pEnumerator = NULL;
  IMMDeviceCollection* pEnumDevices = NULL;

  HRESULT                hr;

  std::string strDD = GetDefaultDevice();

  /* Windows Vista or later - supporting WASAPI device probing */
  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;

  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 DirectSound endpoint failed.");
      goto failed;
    }

    hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed.");
      SAFE_RELEASE(pDevice);
      goto failed;
    }

    hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound 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 DirectSound 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 DirectSound 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);

    /* In shared mode Windows tells us what format the audio must be in. */
    IAudioClient *pClient;
    hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr));
      goto failed;
    }

    //hr = pClient->GetMixFormat(&pwfxex);
    hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName);
    if (SUCCEEDED(hr) && varName.blob.cbSize > 0)
    {
      WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData;
      deviceInfo.m_channels = layoutsByChCount[std::max(std::min(smpwfxex->nChannels, (WORD) DS_SPEAKER_COUNT), (WORD) 2)];
      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT));
      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
      deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 192000));
    }
    else
    {
      CLog::Log(LOGERROR, __FUNCTION__": Getting DeviceFormat failed (%s)", WASAPIErrToStr(hr));
    }
    pClient->Release();

    SAFE_RELEASE(pDevice);
    SAFE_RELEASE(pProperty);

    deviceInfo.m_deviceName       = strDevName;
    deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
    deviceInfo.m_displayNameExtra = std::string("DirectSound: ").append(strFriendlyName);
    deviceInfo.m_deviceType       = aeDeviceType;

    deviceInfoList.push_back(deviceInfo);

    // add the default device with m_deviceName = default
    if(strDD == strDevName)
    {
      deviceInfo.m_deviceName = std::string("default");
      deviceInfo.m_displayName = std::string("default");
      deviceInfo.m_displayNameExtra = std::string("");
      deviceInfoList.push_back(deviceInfo);
    }
  }

  return;

failed:

  if (FAILED(hr))
    CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));

  SAFE_RELEASE(pEnumDevices);
  SAFE_RELEASE(pEnumerator);

}
Example #24
0
bool MMDeviceAudioSource::Initialize(bool bMic, CTSTR lpID)
{
    const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
    const IID IID_IMMDeviceEnumerator    = __uuidof(IMMDeviceEnumerator);
    const IID IID_IAudioClient           = __uuidof(IAudioClient);
    const IID IID_IAudioCaptureClient    = __uuidof(IAudioCaptureClient);

    HRESULT err;
    err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator);
    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IMMDeviceEnumerator = %08lX"), (BOOL)bMic, err);
        return false;
    }

    bIsMic = bMic;

    if (bIsMic) {
        BOOL bMicSyncFixHack = GlobalConfig->GetInt(TEXT("Audio"), TEXT("UseMicSyncFixHack"));
        angerThreshold = bMicSyncFixHack ? 40 : 1000;
    }

    if (scmpi(lpID, TEXT("Default")) == 0)
        err = mmEnumerator->GetDefaultAudioEndpoint(bMic ? eCapture : eRender, bMic ? eCommunications : eConsole, &mmDevice);
    else
        err = mmEnumerator->GetDevice(lpID, &mmDevice);

    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IMMDevice = %08lX"), (BOOL)bMic, err);
        return false;
    }

    err = mmDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&mmClient);
    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IAudioClient = %08lX"), (BOOL)bMic, err);
        return false;
    }

    //-----------------------------------------------------------------
    // get name

    IPropertyStore *store;
    if(SUCCEEDED(mmDevice->OpenPropertyStore(STGM_READ, &store)))
    {
        PROPVARIANT varName;

        PropVariantInit(&varName);
        if(SUCCEEDED(store->GetValue(PKEY_Device_FriendlyName, &varName)))
        {
            CWSTR wstrName = varName.pwszVal;
            strDeviceName = wstrName;
        }

        store->Release();
    }

    if(bMic)
    {
        Log(TEXT("------------------------------------------"));
        Log(TEXT("Using auxilary audio input: %s"), GetDeviceName());

        bUseQPC = GlobalConfig->GetInt(TEXT("Audio"), TEXT("UseMicQPC")) != 0;
        if (bUseQPC)
            Log(TEXT("Using Mic QPC timestamps"));
    }
    else
    {
        Log(TEXT("------------------------------------------"));
        Log(TEXT("Using desktop audio input: %s"), GetDeviceName());

        bUseVideoTime = AppConfig->GetInt(TEXT("Audio"), TEXT("SyncToVideoTime")) != 0;
        SetTimeOffset(GlobalConfig->GetInt(TEXT("Audio"), TEXT("GlobalAudioTimeAdjust")));
    }

    //-----------------------------------------------------------------
    // get format

    WAVEFORMATEX *pwfx;
    err = mmClient->GetMixFormat(&pwfx);
    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get mix format from audio client = %08lX"), (BOOL)bMic, err);
        return false;
    }

    bool  bFloat;
    UINT  inputChannels;
    UINT  inputSamplesPerSec;
    UINT  inputBitsPerSample;
    UINT  inputBlockSize;
    DWORD inputChannelMask = 0;
    WAVEFORMATEXTENSIBLE *wfext = NULL;

    //the internal audio engine should always use floats (or so I read), but I suppose just to be safe better check
    if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
    {
        wfext = (WAVEFORMATEXTENSIBLE*)pwfx;
        inputChannelMask = wfext->dwChannelMask;

        if(wfext->SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
        {
            AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Unsupported wave format"), (BOOL)bMic);
            return false;
        }
    }
    else if(pwfx->wFormatTag != WAVE_FORMAT_IEEE_FLOAT)
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Unsupported wave format"), (BOOL)bMic);
        return false;
    }

    bFloat                = true;
    inputChannels         = pwfx->nChannels;
    inputBitsPerSample    = 32;
    inputBlockSize        = pwfx->nBlockAlign;
    inputSamplesPerSec    = pwfx->nSamplesPerSec;
    sampleWindowSize      = (inputSamplesPerSec/100);

    DWORD flags = bMic ? 0 : AUDCLNT_STREAMFLAGS_LOOPBACK;

    err = mmClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, ConvertMSTo100NanoSec(5000), 0, pwfx, NULL);
    //err = AUDCLNT_E_UNSUPPORTED_FORMAT;

    if (err == AUDCLNT_E_UNSUPPORTED_FORMAT) { //workaround for razer kraken headset (bad drivers)
        pwfx->nBlockAlign     = 2*pwfx->nChannels;
        pwfx->nAvgBytesPerSec = inputSamplesPerSec*pwfx->nBlockAlign;
        pwfx->wBitsPerSample  = 16;

        wfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
        wfext->Samples.wValidBitsPerSample = 16;

        bConvert = true;

        err = mmClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, ConvertMSTo100NanoSec(5000), 0, pwfx, NULL);
    }

    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not initialize audio client, result = %08lX"), (BOOL)bMic, err);
        return false;
    }

    //-----------------------------------------------------------------
    // acquire services

    err = mmClient->GetService(IID_IAudioCaptureClient, (void**)&mmCapture);
    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get audio capture client, result = %08lX"), (BOOL)bMic, err);
        return false;
    }

    err = mmClient->GetService(__uuidof(IAudioClock), (void**)&mmClock);
    if(FAILED(err))
    {
        AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get audio capture clock, result = %08lX"), (BOOL)bMic, err);
        return false;
    }

    CoTaskMemFree(pwfx);

    //-----------------------------------------------------------------

    InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, inputChannelMask);

    return true;
}
Example #25
0
void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
{
  CAEDeviceInfo        deviceInfo;

  IMMDeviceEnumerator* pEnumerator = NULL;
  IMMDeviceCollection* pEnumDevices = NULL;

  HRESULT                hr;

  /* See if we are on Windows XP */
  if (!g_sysinfo.IsWindowsVersionAtLeast(CSysInfo::WindowsVersionVista))
  {
    /* We are on XP - WASAPI not supported - enumerate using DS devices */
    LPGUID deviceGUID = NULL;
    RPC_CSTR cszGUID;
    std::string szGUID;
    std::list<DSDevice> DSDeviceList;
    DirectSoundEnumerate(DSEnumCallback, &DSDeviceList);

    for(std::list<DSDevice>::iterator itt = DSDeviceList.begin(); itt != DSDeviceList.end(); ++itt)
    {
      if (UuidToString((*itt).lpGuid, &cszGUID) != RPC_S_OK)
        continue;  /* could not convert GUID to string - skip device */

      deviceInfo.m_channels.Reset();
      deviceInfo.m_dataFormats.clear();
      deviceInfo.m_sampleRates.clear();

      szGUID = (LPSTR)cszGUID;

      deviceInfo.m_deviceName = "{" + szGUID + "}";
      deviceInfo.m_displayName = (*itt).name;
      deviceInfo.m_displayNameExtra = std::string("DirectSound: ") + (*itt).name;

      deviceInfo.m_deviceType = AE_DEVTYPE_PCM;
      deviceInfo.m_channels   = layoutsByChCount[2];

      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT));
      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));

      deviceInfo.m_sampleRates.push_back((DWORD) 96000);

      deviceInfoList.push_back(deviceInfo);
    }

    RpcStringFree(&cszGUID);
    return;
  }

  /* Windows Vista or later - supporting WASAPI device probing */
  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;

  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 DirectSound endpoint failed.");
      goto failed;
    }

    hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed.");
      SAFE_RELEASE(pDevice);
      goto failed;
    }

    hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound 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 DirectSound 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 DirectSound 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);

    /* In shared mode Windows tells us what format the audio must be in. */
    IAudioClient *pClient;
    hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
    if (FAILED(hr))
    {
      CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr));
      goto failed;
    }

    //hr = pClient->GetMixFormat(&pwfxex);
    hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName);
    if (SUCCEEDED(hr) && varName.blob.cbSize > 0)
    {
      WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData;
      deviceInfo.m_channels = layoutsByChCount[std::max(std::min(smpwfxex->nChannels, (WORD) DS_SPEAKER_COUNT), (WORD) 2)];
      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT));
      deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
      deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 192000));
    }
    else
    {
      CLog::Log(LOGERROR, __FUNCTION__": Getting DeviceFormat failed (%s)", WASAPIErrToStr(hr));
    }
    pClient->Release();

    SAFE_RELEASE(pDevice);
    SAFE_RELEASE(pProperty);

    deviceInfo.m_deviceName       = strDevName;
    deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
    deviceInfo.m_displayNameExtra = std::string("DirectSound: ").append(strFriendlyName);
    deviceInfo.m_deviceType       = aeDeviceType;

    deviceInfoList.push_back(deviceInfo);
  }

  // since AE takes the first device in deviceInfoList as default audio device we need
  // to sort it in order to use the real default device
  if(deviceInfoList.size() > 1)
  {
    std::string strDD = GetDefaultDevice();
    for (AEDeviceInfoList::iterator itt = deviceInfoList.begin(); itt != deviceInfoList.end(); ++itt)
    {
      CAEDeviceInfo devInfo = *itt;
      if(devInfo.m_deviceName == strDD)
      {
        deviceInfoList.erase(itt);
        deviceInfoList.insert(deviceInfoList.begin(), devInfo);
        break;
      }
    }
  }

  return;

failed:

  if (FAILED(hr))
    CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));

  SAFE_RELEASE(pEnumDevices);
  SAFE_RELEASE(pEnumerator);

}
Example #26
0
void PlayAudio()
{
	REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;	// microseconds, so this is 1 seconds
	REFERENCE_TIME hnsActualDuration;

	HRESULT hr;

	IMMDeviceEnumerator *pEnumerator = NULL;
	IMMDevice *pDevice = NULL;
	IAudioClient *pAudioClient = NULL;
	IAudioRenderClient *pRenderClient = NULL;
	WAVEFORMATEX *pwfx = NULL;
	UINT32 bufferFrameCount;
	UINT32 numFramesAvailable;
	UINT32 numFramesPadding;
	BYTE *pData;
	DWORD flags = 0;


	hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
	EXIT_ON_ERROR(hr);

	hr = pEnumerator->GetDefaultAudioEndpoint(
		eRender, eConsole, &pDevice);
	EXIT_ON_ERROR(hr);

	hr = pDevice->Activate(
			IID_IAudioClient, CLSCTX_ALL,
			NULL, (void**)&pAudioClient);
	EXIT_ON_ERROR(hr);

	hr = pAudioClient->GetMixFormat(&pwfx);
	EXIT_ON_ERROR(hr);

	hr = pAudioClient->Initialize(
			AUDCLNT_SHAREMODE_SHARED,
			0,
			hnsRequestedDuration,
			0,
			pwfx,
			NULL);
	EXIT_ON_ERROR(hr);

	// Get the actual size of the allocated buffer.
    hr = pAudioClient->GetBufferSize(&bufferFrameCount);
	EXIT_ON_ERROR(hr);

    hr = pAudioClient->GetService(
                         IID_IAudioRenderClient,
                         (void**)&pRenderClient);
	EXIT_ON_ERROR(hr);

    // Grab the entire buffer for the initial fill operation.
    hr = pRenderClient->GetBuffer(bufferFrameCount, &pData);
	EXIT_ON_ERROR(hr);

	// load initial data
	hr = LoadAudioBuffer(bufferFrameCount, pData, pwfx, &flags);
	EXIT_ON_ERROR(hr);

	hr = pRenderClient->ReleaseBuffer(bufferFrameCount, flags);
	EXIT_ON_ERROR(hr);

	// Calculate the actual duration of the allocated buffer.
    hnsActualDuration = (REFERENCE_TIME)((double)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec);

    hr = pAudioClient->Start();  // Start playing.
	EXIT_ON_ERROR(hr);

    // Each loop fills about half of the shared buffer.
	while (flags != AUDCLNT_BUFFERFLAGS_SILENT)
	{
		        // Sleep for half the buffer duration.
        Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2));

        // See how much buffer space is available.
        hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
        EXIT_ON_ERROR(hr)

        numFramesAvailable = bufferFrameCount - numFramesPadding;

        // Grab all the available space in the shared buffer.
        hr = pRenderClient->GetBuffer(numFramesAvailable, &pData);
        EXIT_ON_ERROR(hr)

        // Get next 1/2-second of data from the audio source.
		hr = LoadAudioBuffer(numFramesAvailable, pData, pwfx, &flags);
        EXIT_ON_ERROR(hr)

        hr = pRenderClient->ReleaseBuffer(numFramesAvailable, flags);
        EXIT_ON_ERROR(hr)
    }

    // Wait for last data in buffer to play before stopping.
    Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2));

    hr = pAudioClient->Stop();  // Stop playing.
	EXIT_ON_ERROR(hr);


Exit:
	CoTaskMemFree(pwfx);
	SAFE_RELEASE(pEnumerator);
	SAFE_RELEASE(pDevice);
	SAFE_RELEASE(pAudioClient);
	SAFE_RELEASE(pRenderClient);
}
Example #27
0
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 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(&currentVolume);
	//printf("Current volume in dB is: %f\n", currentVolume);

	hr = endpointVolume->GetMasterVolumeLevelScalar(&currentVolume);

	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();
}
Example #29
0
void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
{
    CAEDeviceInfo        deviceInfo;
    OSVERSIONINFO        osvi;

    IMMDeviceEnumerator* pEnumerator = NULL;
    IMMDeviceCollection* pEnumDevices = NULL;

    WAVEFORMATEX*          pwfxex = NULL;
    HRESULT                hr;

    /* See if we are on Windows XP */
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);

    if (osvi.dwMajorVersion == 5)
    {
        /* We are on XP - WASAPI not supported - enumerate using DS devices */
        LPGUID deviceGUID = NULL;
        RPC_CSTR cszGUID;
        std::string szGUID;
        std::list<DSDevice> DSDeviceList;
        DirectSoundEnumerate(DSEnumCallback, &DSDeviceList);

        for(std::list<DSDevice>::iterator itt = DSDeviceList.begin(); itt != DSDeviceList.end(); itt++)
        {
            if (UuidToString((*itt).lpGuid, &cszGUID) != RPC_S_OK)
                continue;  /* could not convert GUID to string - skip device */

            deviceInfo.m_channels.Reset();
            deviceInfo.m_dataFormats.clear();
            deviceInfo.m_sampleRates.clear();

            szGUID = (LPSTR)cszGUID;

            deviceInfo.m_deviceName = "{" + szGUID + "}";
            deviceInfo.m_displayName = (*itt).name;
            deviceInfo.m_displayNameExtra = std::string("DirectSound: ") + (*itt).name;

            deviceInfo.m_deviceType = AE_DEVTYPE_PCM;
            deviceInfo.m_channels   = layoutsByChCount[2];

            deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT));
            deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));

            deviceInfo.m_sampleRates.push_back((DWORD) 96000);

            deviceInfoList.push_back(deviceInfo);
        }

        RpcStringFree(&cszGUID);
        return;
    }

    /* Windows Vista or later - supporting WASAPI device probing */
    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;

    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 DirectSound endpoint failed.");
            goto failed;
        }

        hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
        if (FAILED(hr))
        {
            CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed.");
            SAFE_RELEASE(pDevice);
            goto failed;
        }

        hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
        if (FAILED(hr))
        {
            CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint device name failed.");
            SAFE_RELEASE(pDevice);
            SAFE_RELEASE(pProperty);
            goto failed;
        }

        std::wstring strRawFriendlyName(varName.pwszVal);
        std::string strFriendlyName = std::string(strRawFriendlyName.begin(), strRawFriendlyName.end());

        PropVariantClear(&varName);

        hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
        if (FAILED(hr))
        {
            CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint GUID failed.");
            SAFE_RELEASE(pDevice);
            SAFE_RELEASE(pProperty);
            goto failed;
        }

        std::wstring strRawDevName(varName.pwszVal);
        std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end());
        PropVariantClear(&varName);

        hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName);
        if (FAILED(hr))
        {
            CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound 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);

        /* In shared mode Windows tells us what format the audio must be in. */
        IAudioClient *pClient;
        hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
        if (FAILED(hr))
        {
            CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr));
        }

        //hr = pClient->GetMixFormat(&pwfxex);
        hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName);
        if (SUCCEEDED(hr))
        {
            WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData;
            deviceInfo.m_channels = layoutsByChCount[std::min(smpwfxex->nChannels, (WORD) 2)];
            deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT));
            deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
            deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 96000));
        }
        else
        {
            CLog::Log(LOGERROR, __FUNCTION__": GetMixFormat failed (%s)", WASAPIErrToStr(hr));
        }
        pClient->Release();

        SAFE_RELEASE(pDevice);
        SAFE_RELEASE(pProperty);

        deviceInfo.m_deviceName       = strDevName;
        deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
        deviceInfo.m_displayNameExtra = std::string("DirectSound: ").append(strFriendlyName);
        deviceInfo.m_deviceType       = aeDeviceType;

        /* Now logged by AESinkFactory on startup */
        //CLog::Log(LOGDEBUG,"Audio Device %d:    %s", i, ((std::string)deviceInfo).c_str());

        deviceInfoList.push_back(deviceInfo);
    }

    return;

failed:

    if (FAILED(hr))
        CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));

    SAFE_RELEASE(pEnumDevices);
    SAFE_RELEASE(pEnumerator);

}
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
}