Beispiel #1
0
// Obtain the use of the native multimedia device.
TBool AudioDriver::GetMultimediaDevice(IMMDevice **DeviceToUse)
{
    HRESULT hr;
    TBool   retValue = true;

    IMMDeviceEnumerator *deviceEnumerator = NULL;

    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_PPV_ARGS(&deviceEnumerator));
    if (hr != S_OK)
    {
        Log::Print("Unable to instantiate device enumerator: %x\n", hr);
        retValue = false;
        goto Exit;
    }

    IMMDevice *device      = NULL;
    ERole      deviceRole  = eMultimedia;

    hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender,
                                                   deviceRole,
                                                  &device);
    if (hr != S_OK)
    {
        Log::Print("Unable to get default multimedia device: %x\n", hr);
        retValue = false;
        goto Exit;
    }

    *DeviceToUse = device;
    retValue     = true;
Exit:
    SafeRelease(&deviceEnumerator);

    return retValue;
}
Beispiel #2
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);
	}
}
Beispiel #3
0
	void do_unregister( XAudio2_Output * p_instance )
	{
		if ( InterlockedDecrement( &registered ) == 0 )
		{
			if (pEnumerator)
			{
				pEnumerator->UnregisterEndpointNotificationCallback( this );
				pEnumerator->Release();
				pEnumerator = NULL;
			}
		}

		EnterCriticalSection( &lock );
		for ( std::vector<XAudio2_Output*>::iterator it = instances.begin(); it < instances.end(); ++it )
		{
			if ( *it == p_instance )
			{
				instances.erase( it );
				break;
			}
		}
		LeaveCriticalSection( &lock );
	}
Beispiel #4
0
//
//  Based on the input switches, pick the specified device to use.
//
bool PickDevice(IMMDevice **DeviceToUse, UINT AudioDeviceIndex)
{
    IMMDeviceEnumerator *deviceEnumerator = NULL;
    IMMDeviceCollection *deviceCollection = NULL;

    HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&deviceEnumerator));
    PersistentAssert(SUCCEEDED(hr), "CoCreateInstance failed");
    
    IMMDevice *device = NULL;

    //
    //  The user didn't specify an output device, prompt the user for a device and use that.
    //
    hr = deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &deviceCollection);
    PersistentAssert(SUCCEEDED(hr), "deviceEnumerator->EnumAudioEndpoints failed");
    
    UINT deviceCount;
    hr = deviceCollection->GetCount(&deviceCount);
    PersistentAssert(SUCCEEDED(hr), "deviceCollection->GetCount failed");
    for (UINT DeviceIndex = 0 ; DeviceIndex < deviceCount; DeviceIndex++)
    {
        String deviceName = GetDeviceName(deviceCollection, DeviceIndex);
        //Console::WriteLine(String(DeviceIndex) + String(": ") + deviceName);
    }
    
    int deviceIndex = 0;
    if(AudioDeviceIndex < deviceCount)
    {
        deviceIndex = AudioDeviceIndex;
    }
    hr = deviceCollection->Item(deviceIndex, DeviceToUse);
    PersistentAssert(DeviceToUse != NULL && SUCCEEDED(hr), "deviceCollection->Item failed");
    
    SafeRelease(&deviceCollection);
    SafeRelease(&deviceEnumerator);
    return true;
}
HRESULT get_default_device(IMMDevice **ppMMDevice) {
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pMMDeviceEnumerator;
    // activate a device enumerator
    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;
    }

    // get the default render endpoint
    hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, ppMMDevice);
    pMMDeviceEnumerator->Release();
    if (FAILED(hr)) {
        printf("IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: hr = 0x%08x\n", hr);
        return hr;
    }

    return S_OK;
}
HRESULT unregister_notification_callback(IMMNotificationClient *pClient) {
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pMMDeviceEnumerator;

    // activate a device enumerator
    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;
    }

    // get the default render endpoint
    hr = pMMDeviceEnumerator->UnregisterEndpointNotificationCallback(pClient);
    pMMDeviceEnumerator->Release();
    if (FAILED(hr)) {
        printf("IMMDeviceEnumerator::UnregisterEndpointNotificationCallback failed: hr = 0x%08x\n", hr);
        return hr;
    }
    return S_OK;
}
Beispiel #7
0
bool GetDefaultDevice(String &strVal, EDataFlow df )
{
    const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
    const IID IID_IMMDeviceEnumerator    = __uuidof(IMMDeviceEnumerator);
    IMMDeviceEnumerator *mmEnumerator;
    HRESULT err;

    err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator);
    if(FAILED(err))
        return false;

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

    IMMDevice *defDevice;
    if(FAILED(mmEnumerator->GetDefaultAudioEndpoint(df, eCommunications, &defDevice)))
    {
        SafeRelease(mmEnumerator);
        return false;
    }

    CWSTR wstrDefaultID;
    if(FAILED(defDevice->GetId((LPWSTR*)&wstrDefaultID)))
    {
        SafeRelease(defDevice);
        SafeRelease(mmEnumerator);
        return false;
    }

    strVal = wstrDefaultID;

    CoTaskMemFree((LPVOID)wstrDefaultID);
    SafeRelease(defDevice);
    SafeRelease(mmEnumerator);

    return true;
}
void MFAudioEndpointControl::updateEndpoints()
{
    m_defaultEndpoint = QString::fromLatin1("Default");
    m_devices.insert(m_defaultEndpoint, NULL);

    IMMDeviceEnumerator *pEnum = NULL;
    HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                          NULL, CLSCTX_ALL,
                          __uuidof(IMMDeviceEnumerator),
                         (void**)&pEnum);
    if (SUCCEEDED(hr)) {
        IMMDeviceCollection *pDevices = NULL;
        hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices);
        if (SUCCEEDED(hr)) {
            UINT count;
            hr = pDevices->GetCount(&count);
            if (SUCCEEDED(hr)) {
                for (UINT i = 0; i < count; ++i) {
                    IMMDevice *pDevice = NULL;
                    hr = pDevices->Item(i, &pDevice);
                    if (SUCCEEDED(hr)) {
                        LPWSTR wstrID = NULL;
                        hr = pDevice->GetId(&wstrID);
                        if (SUCCEEDED(hr)) {
                            QString deviceId = QString::fromWCharArray(wstrID);
                            m_devices.insert(deviceId, wstrID);
                        }
                        pDevice->Release();
                    }
                }
            }
            pDevices->Release();
        }
        pEnum->Release();
    }
}
Beispiel #9
0
	void do_register(XAudio2_Output * p_instance)
	{
		if ( InterlockedIncrement( &registered ) == 1 )
		{
			pEnumerator = NULL;
			HRESULT hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, CLSCTX_INPROC_SERVER, __uuidof( IMMDeviceEnumerator ), ( void** ) &pEnumerator );
			if ( SUCCEEDED( hr ) )
			{
				pEnumerator->RegisterEndpointNotificationCallback( this );
			}
		}

		EnterCriticalSection( &lock );
		instances.push_back( p_instance );
		LeaveCriticalSection( &lock );
	}
Beispiel #10
0
int wasapi_init(cubeb ** context, char const * context_name)
{
  HRESULT hr;
  IMMDeviceEnumerator * enumerator = NULL;

  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  if (FAILED(hr)) {
    LOG("Could not init COM.");
    return CUBEB_ERROR;
  }

  cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));

  ctx->ops = &wasapi_ops;

  hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                        NULL, CLSCTX_INPROC_SERVER,
                        IID_PPV_ARGS(&enumerator));
  if (FAILED(hr)) {
    LOG("Could not get device enumerator.");
    wasapi_destroy(ctx);
    return CUBEB_ERROR;
  }

  /* eMultimedia is okay for now ("Music, movies, narration, [...]").
   * We will need to change this when we distinguish streams by use-case, other
   * possible values being eConsole ("Games, system notification sounds [...]")
   * and eCommunication ("Voice communication"). */
  hr = enumerator->GetDefaultAudioEndpoint(eRender,
                                           eMultimedia,
                                           &ctx->device);
  if (FAILED(hr)) {
    LOG("Could not get default audio endpoint.");
    SafeRelease(enumerator);
    wasapi_destroy(ctx);
    return CUBEB_ERROR;
  }

  ctx->mmcss_module = LoadLibraryA("Avrt.dll");

  if (ctx->mmcss_module) {
    ctx->set_mm_thread_characteristics =
      (set_mm_thread_characteristics_function) GetProcAddress(
          ctx->mmcss_module, "AvSetMmThreadCharacteristicsA");
    ctx->revert_mm_thread_characteristics =
      (revert_mm_thread_characteristics_function) GetProcAddress(
          ctx->mmcss_module, "AvRevertMmThreadCharacteristics");
    if (!(ctx->set_mm_thread_characteristics && ctx->revert_mm_thread_characteristics)) {
      LOG("Could not load AvSetMmThreadCharacteristics or AvRevertMmThreadCharacteristics: %d", GetLastError());
      FreeLibrary(ctx->mmcss_module);
    }
  } else {
    // This is not a fatal error, but we might end up glitching when
    // the system is under high load.
    LOG("Could not load Avrt.dll");
    ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop;
    ctx->revert_mm_thread_characteristics = &revert_mm_thread_characteristics_noop;
  }
  
  SafeRelease(enumerator);

  *context = ctx;

  return CUBEB_OK;
}
Beispiel #11
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);
}
Beispiel #12
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);
  }
Beispiel #13
0
bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device)
{
  if (m_initialized)
    return false;

  m_device = device;
  bool bdefault = false;

  /* Save requested format */
  /* Clear returned format */
  sinkReqFormat = format.m_dataFormat;
  sinkRetFormat = AE_FMT_INVALID;

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

  HRESULT 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)

  /* Get our device. First try to find the named device. */
  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.")

  if(StringUtils::EndsWithNoCase(device, std::string("default")))
    bdefault = true;

  if(!bdefault)
  {
    for (UINT i = 0; i < uiCount; i++)
    {
      IPropertyStore *pProperty = NULL;
      PROPVARIANT varName;

      hr = pEnumDevices->Item(i, &m_pDevice);
      EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")

      hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
      EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")

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

      std::string strDevName = localWideToUtf(varName.pwszVal);

      if (device == strDevName)
        i = uiCount;
      else
        SAFE_RELEASE(m_pDevice);

      PropVariantClear(&varName);
      SAFE_RELEASE(pProperty);
    }
  }
  SAFE_RELEASE(pEnumDevices);

  if (!m_pDevice)
  {
    if(!bdefault)
      CLog::Log(LOGINFO, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices.  Trying the default device...", device.c_str());
    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")

    IPropertyStore *pProperty = NULL;
    PROPVARIANT varName;

    hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")

    hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);

    device = localWideToUtf(varName.pwszVal);
    PropVariantClear(&varName);
    SAFE_RELEASE(pProperty);
  }

  SAFE_RELEASE(pEnumerator);

  hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")

  if (!InitializeExclusive(format))
  {
    CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format");
    goto failed;
  }

  /* get the buffer size and calculate the frames for AE */
  m_pAudioClient->GetBufferSize(&m_uiBufferLen);

  format.m_frames       = m_uiBufferLen;
  format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
  m_format              = format;
  sinkRetFormat         = format.m_dataFormat;

  hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")

  m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  hr = m_pAudioClient->SetEventHandle(m_needDataEvent);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler.");

  m_initialized = true;
  m_isDirty     = false;

  // allow feeding less samples than buffer size
  // if the device is opened exclusive and event driven, provided samples must match buffersize
  // ActiveAE tries to align provided samples with buffer size but cannot guarantee (e.g. transcoding)
  // this can be avoided by dropping the event mode which has not much benefit; SoftAE polls anyway
  delete [] m_pBuffer;
  m_pBuffer = new uint8_t[format.m_frames * format.m_frameSize];
  m_bufferPtr = 0;

  return true;

failed:
  CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
  SAFE_RELEASE(pEnumDevices);
  SAFE_RELEASE(pEnumerator);
  SAFE_RELEASE(m_pRenderClient);
  SAFE_RELEASE(m_pAudioClient);
  SAFE_RELEASE(m_pDevice);
  if(m_needDataEvent)
  {
    CloseHandle(m_needDataEvent);
    m_needDataEvent = 0;
  }

  return false;
}
Beispiel #14
0
bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bAudioPassthrough)
{
    CLog::Log(LOGDEBUG, __FUNCTION__": endpoint device %s", device.c_str());

    //First check if the version of Windows we are running on even supports WASAPI.
    if (!g_sysinfo.IsVistaOrHigher())
    {
        CLog::Log(LOGERROR, __FUNCTION__": WASAPI output requires Vista or higher.");
        return false;
    }

    //Only one exclusive stream may be initialized at one time.
    if(m_bIsAllocated)
    {
        CLog::Log(LOGERROR, __FUNCTION__": Cannot create more then one WASAPI stream at one time.");
        return false;
    }

    int layoutChannels = 0;

    if(!bAudioPassthrough)
    {
        //If no channel map is specified, use the default.
        if(!channelMap)
            channelMap = (PCMChannels *)wasapi_default_channel_layout[iChannels - 1];

        PCMChannels *outLayout = m_remap.SetInputFormat(iChannels, channelMap, uiBitsPerSample / 8);

        for(PCMChannels *channel = outLayout; *channel != PCM_INVALID; channel++)
            ++layoutChannels;

        //Expand monural to stereo as most devices don't seem to like 1 channel PCM streams.
        //Stereo sources should be sent explicitly as two channels so that the external hardware
        //can apply ProLogic/5CH Stereo/etc processing on it.
        if(iChannels <= 2)
        {
            BuildChannelMapping(2, (PCMChannels *)wasapi_default_channel_layout[1]);

            layoutChannels = 2;
            m_remap.SetOutputFormat(2, m_SpeakerOrder, false);
        }
        else //Do the standard remapping.
        {
            BuildChannelMapping(layoutChannels, outLayout);
            m_remap.SetOutputFormat(layoutChannels, m_SpeakerOrder, false);
        }
    }

    m_bPlaying = false;
    m_bPause = false;
    m_bMuting = false;
    m_uiChannels = iChannels;
    m_uiBitsPerSample = uiBitsPerSample;
    m_bPassthrough = bAudioPassthrough;

    m_nCurrentVolume = g_settings.m_nVolumeLevel;
    m_pcmAmplifier.SetVolume(m_nCurrentVolume);

    WAVEFORMATEXTENSIBLE wfxex = {0};

    //fill waveformatex
    ZeroMemory(&wfxex, sizeof(WAVEFORMATEXTENSIBLE));
    wfxex.Format.cbSize          =  sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
    wfxex.Format.nChannels       = layoutChannels;
    wfxex.Format.nSamplesPerSec  = uiSamplesPerSec;
    if (bAudioPassthrough == true)
    {
        wfxex.dwChannelMask          = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
        wfxex.Format.wFormatTag      = WAVE_FORMAT_DOLBY_AC3_SPDIF;
        wfxex.SubFormat              = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
        wfxex.Format.wBitsPerSample  = 16;
        wfxex.Format.nChannels       = 2;
    }
    else
    {
        wfxex.dwChannelMask          = m_uiSpeakerMask;
        wfxex.Format.wFormatTag      = WAVE_FORMAT_EXTENSIBLE;
        wfxex.SubFormat              = KSDATAFORMAT_SUBTYPE_PCM;
        wfxex.Format.wBitsPerSample  = uiBitsPerSample;
    }

    wfxex.Samples.wValidBitsPerSample = uiBitsPerSample == 32 ? 24 : uiBitsPerSample;
    wfxex.Format.nBlockAlign       = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
    wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;

    m_uiAvgBytesPerSec = wfxex.Format.nAvgBytesPerSec;

    m_uiBytesPerFrame = wfxex.Format.nBlockAlign;
    m_uiBytesPerSrcFrame = bAudioPassthrough ? m_uiBytesPerFrame : iChannels * wfxex.Format.wBitsPerSample >> 3;

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

    //Shut down Directsound.
    g_audioContext.SetActiveDevice(CAudioContext::NONE);

    HRESULT 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: %i", hr)

    //Get our device.
    //First try to find the named device.
    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++)
    {
        IPropertyStore *pProperty = NULL;
        PROPVARIANT varName;

        hr = pEnumDevices->Item(i, &m_pDevice);
        EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")

        hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
        EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")

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

        CStdStringW strRawDevName(varName.pwszVal);
        CStdString strDevName;
        g_charsetConverter.wToUTF8(strRawDevName, strDevName);

        if(device == strDevName)
            i = uiCount;
        else
            SAFE_RELEASE(m_pDevice);

        PropVariantClear(&varName);
        SAFE_RELEASE(pProperty);
    }

    SAFE_RELEASE(pEnumDevices);

    if(!m_pDevice)
    {
        CLog::Log(LOGDEBUG, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices.  Trying the default device...", device.c_str());
        hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
        EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
    }
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();
}
Beispiel #16
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;
}
/*
========================
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
}
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
}
Beispiel #19
0
void GetAudioDevices(AudioDeviceList &deviceList, AudioDeviceType deviceType)
{
    const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
    const IID IID_IMMDeviceEnumerator    = __uuidof(IMMDeviceEnumerator);
    IMMDeviceEnumerator *mmEnumerator;
    HRESULT err;

    err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator);
    if(FAILED(err))
    {
        AppWarning(TEXT("GetAudioDevices: Could not create IMMDeviceEnumerator"));
        return;
    }

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

    AudioDeviceInfo *info;

    if(deviceType == ADT_RECORDING) {
      info = deviceList.devices.CreateNew();
      info->strID = TEXT("Disable");
      info->strName = Str("Disable");
    }

    info = deviceList.devices.CreateNew();
    info->strID = TEXT("Default");
    info->strName = Str("Default");

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

    IMMDeviceCollection *collection;

    EDataFlow audioDeviceType;
    switch(deviceType)
    {
    case ADT_RECORDING:
        audioDeviceType = eCapture;
        break;
    case ADT_PLAYBACK:
        audioDeviceType = eRender;
        break;
    default:
        audioDeviceType = eAll;
        break;
    }

    err = mmEnumerator->EnumAudioEndpoints(audioDeviceType, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &collection);
    if(FAILED(err))
    {
        AppWarning(TEXT("GetAudioDevices: Could not enumerate audio endpoints"));
        SafeRelease(mmEnumerator);
        return;
    }

    UINT count;
    if(SUCCEEDED(collection->GetCount(&count)))
    {
        for(UINT i=0; i<count; i++)
        {
            IMMDevice *device;
            if(SUCCEEDED(collection->Item(i, &device)))
            {
                CWSTR wstrID;
                if(SUCCEEDED(device->GetId((LPWSTR*)&wstrID)))
                {
                    IPropertyStore *store;
                    if(SUCCEEDED(device->OpenPropertyStore(STGM_READ, &store)))
                    {
                        PROPVARIANT varName;

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

                            AudioDeviceInfo *info = deviceList.devices.CreateNew();
                            info->strID = wstrID;
                            info->strName = wstrName;
                        }
                    }

                    CoTaskMemFree((LPVOID)wstrID);
                }

                SafeRelease(device);
            }
        }
    }

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

    SafeRelease(collection);
    SafeRelease(mmEnumerator);
}
Beispiel #20
0
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR commandLine, INT )
{
  // set up some xbmc specific relationships
  XBMC::Context context;

  //this can't be set from CAdvancedSettings::Initialize() because it will overwrite
  //the loglevel set with the --debug flag
#ifdef _DEBUG
  g_advancedSettings.m_logLevel     = LOG_LEVEL_DEBUG;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_DEBUG;
#else
  g_advancedSettings.m_logLevel     = LOG_LEVEL_NORMAL;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_NORMAL;
#endif
  CLog::SetLogLevel(g_advancedSettings.m_logLevel);

  // Initializes CreateMiniDump to handle exceptions.
  win32_exception::set_version(g_infoManager.GetVersion());
  SetUnhandledExceptionFilter( CreateMiniDump );

  // check if Kodi is already running
  std::string appName = CSysInfo::GetAppName();
  CreateMutex(NULL, FALSE, (appName + " Media Center").c_str());
  if(GetLastError() == ERROR_ALREADY_EXISTS)
  {
    HWND m_hwnd = FindWindow(appName.c_str(), appName.c_str());
    if(m_hwnd != NULL)
    {
      // switch to the running instance
      ShowWindow(m_hwnd,SW_RESTORE);
      SetForegroundWindow(m_hwnd);
    }
    return 0;
  }

#ifndef HAS_DX
  if(CWIN32Util::GetDesktopColorDepth() < 32)
  {
    //FIXME: replace it by a SDL window for all ports
    MessageBox(NULL, "Desktop Color Depth isn't 32Bit", (appName + ": Fatal Error").c_str(), MB_OK|MB_ICONERROR);
    return 0;
  }
#endif

  if((g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_SSE2) == 0)
  {
    MessageBox(NULL, "No SSE2 support detected", (appName + ": Fatal Error").c_str(), MB_OK|MB_ICONERROR);
    return 0;
  }

  //Initialize COM
  CoInitializeEx(NULL, COINIT_MULTITHREADED);

  // Handle numeric values using the default/POSIX standard
  setlocale(LC_NUMERIC, "C");

  // If the command line passed to WinMain, commandLine, is not "" we need
  // to process the command line arguments.
  // Note that commandLine does not include the program name and can be
  // equal to "" if no arguments were supplied. By contrast GetCommandLineW()
  // does include the program name and is never equal to "".
  g_advancedSettings.Initialize();
  if (strlen(commandLine) != 0)
  {
    int argc;
    LPWSTR* argvW = CommandLineToArgvW(GetCommandLineW(), &argc);

    std::vector<std::string> strargvA;
    strargvA.resize(argc);
    const char** argv = (const char**) LocalAlloc(LMEM_FIXED, argc*sizeof(char*));
    if (!argv)
      return 20;
    for (int i = 0; i < argc; i++)
    {
      g_charsetConverter.wToUTF8(argvW[i], strargvA[i]);
      argv[i] = strargvA[i].c_str();
    }

    // Parse the arguments
    CAppParamParser appParamParser;
    appParamParser.Parse(argv, argc);

    // Clean up the storage we've used
    LocalFree(argvW);
    LocalFree(argv);
  }

  // Initialise Winsock
  WSADATA wd;
  WSAStartup(MAKEWORD(2,2), &wd);

  // use 1 ms timer precision - like SDL initialization used to do
  timeBeginPeriod(1);

#ifdef XBMC_TRACK_EXCEPTIONS
  try
  {
#endif
    // Create and run the app
    if(!g_application.Create())
    {
      MessageBox(NULL, "ERROR: Unable to create application. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
      return 1;
    }
#ifdef XBMC_TRACK_EXCEPTIONS
  }
  catch (const XbmcCommons::UncheckedException &e)
  {
    e.LogThrowMessage("CApplication::Create()");
    MessageBox(NULL, "ERROR: Unable to create application. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "exception in CApplication::Create()");
    MessageBox(NULL, "ERROR: Unable to create application. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
#endif

#ifndef _DEBUG
  // we don't want to see the "no disc in drive" windows message box
  SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
#endif

#ifdef XBMC_TRACK_EXCEPTIONS
  try
  {
#endif
    if (!g_application.CreateGUI())
    {
      MessageBox(NULL, "ERROR: Unable to create GUI. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
      return 1;
    }
#ifdef XBMC_TRACK_EXCEPTIONS
  }
  catch (const XbmcCommons::UncheckedException &e)
  {
    e.LogThrowMessage("CApplication::CreateGUI()");
    MessageBox(NULL, "ERROR: Unable to create GUI. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "exception in CApplication::CreateGUI()");
    MessageBox(NULL, "ERROR: Unable to create GUI. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
#endif

#ifdef XBMC_TRACK_EXCEPTIONS
  try
  {
#endif
    if (!g_application.Initialize())
    {
      MessageBox(NULL, "ERROR: Unable to Initialize. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
      return 1;
    }
#ifdef XBMC_TRACK_EXCEPTIONS
  }
  catch (const XbmcCommons::UncheckedException &e)
  {
    e.LogThrowMessage("CApplication::Initialize()");
    MessageBox(NULL, "ERROR: Unable to Initialize. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "exception in CApplication::Initialize()");
    MessageBox(NULL, "ERROR: Unable to Initialize. Exiting.", (appName + ": Error").c_str(), MB_OK|MB_ICONERROR);
    return 1;
  }
#endif

  IMMDeviceEnumerator *pEnumerator = NULL;
  CMMNotificationClient cMMNC;
  HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  if(SUCCEEDED(hr))
  {
    pEnumerator->RegisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }

  g_application.Run();

  // clear previously set timer resolution
  timeEndPeriod(1);		

  // the end
  hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  if(SUCCEEDED(hr))
  {
    pEnumerator->UnregisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }
  WSACleanup();
  CoUninitialize();

  return 0;
}
Beispiel #21
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);

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

}
BOOL SetDefaultAudioDevice_Vista(LPCTSTR lpszHardwareId, LPCTSTR lpszName)
{
	HRESULT hr = S_FALSE;
	BOOL bSuccessful = FALSE;

	IMMDeviceEnumerator *pDeviceEnumerator = NULL;
	IMMDeviceCollection* pCollection = NULL;
	IPolicyConfigVista *pPolicyConfigVista = NULL;

	do {
		CElcAudioDeviceEnumerator enumerator;
		if (!enumerator.Enumerate(FALSE))
			break;
		CElcDeviceItem * pAudioItem = enumerator.FindItemByPnpId(lpszHardwareId, lpszName);
		if (!pAudioItem)
			break;

		if (FAILED(CoCreateInstance(
			__uuidof(MMDeviceEnumerator), 
			NULL, 
			CLSCTX_INPROC_SERVER, 
			__uuidof(IMMDeviceEnumerator), 
			(LPVOID *)&pDeviceEnumerator)))
		{
			break;
		}

		if (FAILED(pDeviceEnumerator->EnumAudioEndpoints(
			eRender, 
			DEVICE_STATE_ACTIVE, 
			&pCollection)))
		{
			break;
		}

		LPWSTR lpszId = NULL;
		UINT nCount = 0;
		pCollection->GetCount(&nCount);

		for (UINT i=0; i<nCount; i++) {
			IMMDevice* pDevice = NULL;
			if (SUCCEEDED(pCollection->Item(i, &pDevice))) {

				pDevice->GetId(&lpszId);
				SAFE_RELEASE(pDevice);

				LPCWSTR lpszIdDup = lpszId + 17;
				if (pAudioItem->m_strDeviceId.CompareNoCase(lpszIdDup) == 0)
					break;

				CoTaskMemFree(lpszId);
				lpszId = NULL;
			}
		}

		if (lpszId && SUCCEEDED(CoCreateInstance(
			__uuidof(CPolicyConfigVistaClient), 
			NULL, 
			CLSCTX_ALL, 
			__uuidof(IPolicyConfigVista), 
			(LPVOID *)&pPolicyConfigVista)))
		{
			if (SUCCEEDED(pPolicyConfigVista->SetDefaultEndpoint(lpszId, eMultimedia))
				&& SUCCEEDED(pPolicyConfigVista->SetDefaultEndpoint(lpszId, eCommunications)))
				bSuccessful = TRUE;
		}

		if (lpszId)
			CoTaskMemFree(lpszId);

	} while (0);

	SAFE_RELEASE(pPolicyConfigVista);
	SAFE_RELEASE(pCollection);
	SAFE_RELEASE(pDeviceEnumerator);

	return bSuccessful;
}
Beispiel #24
0
extern "C" int XBMC_Run(bool renderGUI)
{
  int status = -1;

  if (!g_advancedSettings.Initialized())
  {
#ifdef _DEBUG
  g_advancedSettings.m_logLevel     = LOG_LEVEL_DEBUG;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_DEBUG;
#else
  g_advancedSettings.m_logLevel     = LOG_LEVEL_NORMAL;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_NORMAL;
#endif
    g_advancedSettings.Initialize();
  }

  if (!g_application.Create())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to create application. Exiting");
    return status;
  }

#ifdef TARGET_RASPBERRY_PI
  if(!g_RBP.Initialize())
    return false;
  g_RBP.LogFirmwareVerison();
#endif

  if (renderGUI && !g_application.CreateGUI())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to create GUI. Exiting");
    return status;
  }
  if (!g_application.Initialize())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to Initialize. Exiting");
    return status;
  }

#ifdef TARGET_WINDOWS
  IMMDeviceEnumerator *pEnumerator = nullptr;
  CMMNotificationClient cMMNC;
  HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator,
                                reinterpret_cast<void**>(&pEnumerator));
  if (SUCCEEDED(hr))
  {
    pEnumerator->RegisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }
#endif

  try
  {
    status = g_application.Run();
  }
#ifdef TARGET_WINDOWS
  catch (const XbmcCommons::UncheckedException &e)
  {
    e.LogThrowMessage("CApplication::Create()");
    CMessagePrinter::DisplayError("ERROR: Exception caught on main loop. Exiting");
    status = -1;
  }
#endif
  catch(...)
  {
    CMessagePrinter::DisplayError("ERROR: Exception caught on main loop. Exiting");
    status = -1;
  }

#ifdef TARGET_WINDOWS
  // the end
  hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator,
                        reinterpret_cast<void**>(&pEnumerator));
  if (SUCCEEDED(hr))
  {
    pEnumerator->UnregisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }
#endif

#ifdef TARGET_RASPBERRY_PI
  g_RBP.Deinitialize();
#endif

  return status;
}
Beispiel #25
0
int main(int argc, char** argv)
{
	if (!Initialize())
	{
		cout << "Failed to initialize socket layer\n";
		system("pause");
		return -1;
	}
	if (!Bind(PORT))
	{
		cout << "Failed to bind listening socket\n";
		system("pause");
		Cleanup();
		return -1;
	}
	Connection SendingSocket;

	char choice;
	char IP[16];
	cout << "Host or Join (h/j)\n";
	cin >> choice;
	if (choice == 'h')
	{
		if (!ReceivingSocket.Accept())
		{
			cout << "Error while connecting to partner\n";
			system("pause");
			Cleanup();
			return -1;
		}
		if(!SendingSocket.Accept())
		{
			cout << "Error while connecting to partner\n";
			system("pause");
			Cleanup();
			return -1;
		}
	}
	else
	{
		cout << "IP: ";
		cin >> IP;
		if (!SendingSocket.Connect(IP, PORT))
		{
			cout << "Error while connecting to partner\n";
			cout << StringError() << endl;
			system("pause");
			Cleanup();
			return -1;
		}
		if(!ReceivingSocket.Connect(IP, PORT))
		{
			cout << "Error while connecting to partner\n";
			cout << StringError() << endl;
			system("pause");
			Cleanup();
			return -1;
		}
	}

	HRESULT result;
	IAudioCaptureClient* capture_client = NULL;
	IAudioClient* audio_client_capture = NULL;
	IMMDevice* capture_device = NULL;
	IMMDeviceEnumerator* enumerator = NULL;
	IPropertyStore* propstore_capture = NULL;
	PROPVARIANT pv_capture;
	WAVEFORMATEX* wf_capture = NULL;
	UINT32 packSize;
	UINT32 availableFrames;
	UINT32 timeIntervalForBuffer = 1000000;
	UINT32 timeIntervalInMilliseconds = timeIntervalForBuffer / 10000;
	BYTE* pData = NULL;
	DWORD flags;
	float index = 0;

	result = CoInitialize(0);
	if (FAILED(result))
	{
		printf("Failed to initialize\n");
		goto Exit;
	}
	result = CoCreateInstance(
		__uuidof(MMDeviceEnumerator), NULL,
		CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
		(void**)&enumerator);
	if (FAILED(result))
	{
		printf("Failed to create device enumerator\n");
		goto Exit;
	}
	result = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &capture_device);
	if (FAILED(result))
	{
		printf("Failed to get capture endpoint handle\n");
		goto Exit;
	}
	PropVariantInit(&pv_capture);
	result = capture_device->OpenPropertyStore(STGM_READ, &propstore_capture);
	if (FAILED(result))
	{
		printf("Failed to read device properties\n");
		goto Exit;
	}
	propstore_capture->GetValue(PKEY_Device_FriendlyName, &pv_capture);
	printf("Opening capture device: %S\n", pv_capture.pwszVal);
	PropVariantClear(&pv_capture);
	result = capture_device->Activate(
		__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&audio_client_capture);
	if (FAILED(result))
	{
		printf("Failed to activate capture device\n");
		goto Exit;
	}
	result = audio_client_capture->GetMixFormat(&wf_capture);
	if (FAILED(result))
	{
		printf("Failed to get mix format\n");
		goto Exit;
	}
	result = audio_client_capture->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, timeIntervalForBuffer, 0, wf_capture, NULL);
	if (FAILED(result))
	{
		printf("Failed to initialize audio client\n");
		goto Exit;
	}
	printf("Sample rate: %u Hz\n", wf_capture->nSamplesPerSec);
	printf("Sample size: %u bits\n", wf_capture->wBitsPerSample);
	printf("Size of audio frame: %u bytes\n", wf_capture->nBlockAlign);
	printf("Number of channels: %u\n", wf_capture->nChannels);
	result = audio_client_capture->Start();
	if (FAILED(result))
	{
		printf("Failed to start recording\n");
		goto Exit;
	}
	result = audio_client_capture->GetService(__uuidof(IAudioCaptureClient), (void**)&capture_client);
	if (FAILED(result))
	{
		printf("Failed to get capture service\n");
		goto Exit;
	}
	
	// Get render endpoint interface
	result = enumerator->GetDefaultAudioEndpoint(eRender, eCommunications, &render_device);
	if (FAILED(result))
	{
		printf("Failed to get render endpoint handle\n");
		goto Exit;
	}
	PropVariantInit(&pv_render);
	result = render_device->OpenPropertyStore(STGM_READ, &propstore_render);
	if (FAILED(result))
	{
		printf("Failed to read device properties\n");
		goto Exit;
	}
	propstore_render->GetValue(PKEY_Device_FriendlyName, &pv_render);
	printf("Opening render device: %S\n", pv_render.pwszVal);
	PropVariantClear(&pv_render);
	result = render_device->Activate(
		__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&audio_client_render);
	if (FAILED(result))
	{
		printf("Failed to activate render device\n");
		goto Exit;
	}
	result = audio_client_render->GetMixFormat(&wf_render);
	if (FAILED(result))
	{
		printf("Failed to get mix format\n");
		goto Exit;
	}
	result = audio_client_render->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, timeIntervalForBuffer, 0, wf_render, NULL);
	if (FAILED(result))
	{
		printf("Failed to initialize audio client\n");
		goto Exit;
	}
	printf("Sample rate: %u Hz\n", wf_render->nSamplesPerSec);
	printf("Sample size: %u bits\n", wf_render->wBitsPerSample);
	printf("Size of audio frame: %u bytes\n", wf_render->nBlockAlign);
	printf("Number of channels: %u\n", wf_render->nChannels);
	result = audio_client_render->Start();
	if (FAILED(result))
	{
		printf("Failed to start recording\n");
		goto Exit;
	}
	result = audio_client_render->GetService(__uuidof(IAudioRenderClient), (void**)&render_client);
	if (FAILED(result))
	{
		printf("Failed to get render service\n");
		goto Exit;
	}

	int partner_format_received_size;
	SendingSocket.Send((const char*)wf_capture, sizeof(*wf_capture));
	ReceivingSocket.Recv((char*)&partner_format, sizeof(partner_format), partner_format_received_size);
	if (last_error != _NO_ERROR)
	{
		printf("Connection failed\n");
		goto Exit;
	}
	if (partner_format.nSamplesPerSec != wf_render->nSamplesPerSec)
	{
		/*cout << "Partned format:\n";
		cout << partner_format.wBitsPerSample << endl;
		cout << partner_format.nSamplesPerSec << endl;
		cout << "My format:\n";
		cout << wf_render->wBitsPerSample << endl;
		cout << wf_render->nSamplesPerSec << endl;*/
		printf("Partner capture format unsupported\n");
		//goto Exit;
	}
	LPTHREAD_START_ROUTINE StartRoutine = (LPTHREAD_START_ROUTINE)RenderAudio;
	DWORD threadID;
	HANDLE hThread = CreateThread(NULL, 0, StartRoutine, NULL, 0, &threadID);
	while (true)
	{
		Sleep(timeIntervalInMilliseconds);
		result = capture_client->GetNextPacketSize(&packSize);
		if (FAILED(result))
		{
			printf("Failed to get next pack size\n");
			break;
		}
		while (packSize)
		{
			result = capture_client->GetBuffer(&pData, &availableFrames, &flags, NULL, NULL);
			if (FAILED(result))
			{
				printf("Failed to get buffer\n");
				goto Exit;
			}
			if (!SendingSocket.Send((const char*)pData, availableFrames * wf_capture->nBlockAlign))
			{
				if (last_error == SOCKET_CLOSED)
				{
					printf("Disconnect\n");
				}
				else
				{
					printf("Connection broke\n");
				}
				goto Exit;
			}
			result = capture_client->ReleaseBuffer(packSize);
			result = capture_client->GetNextPacketSize(&packSize);
			if (FAILED(result))
			{
				printf("Failed to release buffer\n");
				goto Exit;
			}
		}
		result = capture_client->ReleaseBuffer(packSize);
		if (GetAsyncKeyState(VK_ESCAPE))
		{
			break;
		}
	}
	
Exit:
	audio_client_capture->Stop();
	//TerminateThread(hThread, 0);
	audio_client_render->Stop();

	SendingSocket.Disconnect();
	ReceivingSocket.Disconnect();
	SAFE_RELEASE(capture_device);
	SAFE_RELEASE(render_device);
	SAFE_RELEASE(enumerator);
	SAFE_RELEASE(propstore_capture);
	SAFE_RELEASE(propstore_render);
	SAFE_RELEASE(capture_client);
	SAFE_RELEASE(render_client);
	SAFE_RELEASE(audio_client_capture);
	SAFE_RELEASE(audio_client_render);
	system("pause");
	return 0;
}
Beispiel #26
0
extern "C" int XBMC_Run(bool renderGUI)
{
  int status = -1;

  if (!g_advancedSettings.Initialized())
  {
#ifdef _DEBUG
  g_advancedSettings.m_logLevel     = LOG_LEVEL_DEBUG;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_DEBUG;
#else
  g_advancedSettings.m_logLevel     = LOG_LEVEL_NORMAL;
  g_advancedSettings.m_logLevelHint = LOG_LEVEL_NORMAL;
#endif
    g_advancedSettings.Initialize();
  }

  if (!g_application.Create())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to create application. Exiting");
    return status;
  }

#if defined(HAVE_BREAKPAD)
  // Must have our TEMP dir fixed first
  std::string tempPath = CSpecialProtocol::TranslatePath("special://temp/");
  google_breakpad::MinidumpDescriptor descriptor(tempPath.c_str());
  google_breakpad::ExceptionHandler eh(descriptor,
                                       NULL,
                                       NULL,
                                       NULL,
                                       true,
                                       -1);
#endif

#ifdef TARGET_RASPBERRY_PI
  if(!g_RBP.Initialize())
    return false;
  g_RBP.LogFirmwareVerison();
#endif

  if (renderGUI && !g_application.CreateGUI())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to create GUI. Exiting");
    return status;
  }
  if (!g_application.Initialize())
  {
    CMessagePrinter::DisplayError("ERROR: Unable to Initialize. Exiting");
    return status;
  }

#ifdef TARGET_WINDOWS
  IMMDeviceEnumerator *pEnumerator = nullptr;
  CMMNotificationClient cMMNC;
  HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator,
                                reinterpret_cast<void**>(&pEnumerator));
  if (SUCCEEDED(hr))
  {
    pEnumerator->RegisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }
#endif

  try
  {
    status = g_application.Run();
  }
#ifdef TARGET_WINDOWS
  catch (const XbmcCommons::UncheckedException &e)
  {
    e.LogThrowMessage("CApplication::Create()");
    CMessagePrinter::DisplayError("ERROR: Exception caught on main loop. Exiting");
    status = -1;
  }
#endif
  catch(...)
  {
    CMessagePrinter::DisplayError("ERROR: Exception caught on main loop. Exiting");
    status = -1;
  }

#ifdef TARGET_WINDOWS
  // the end
  hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator,
                        reinterpret_cast<void**>(&pEnumerator));
  if (SUCCEEDED(hr))
  {
    pEnumerator->UnregisterEndpointNotificationCallback(&cMMNC);
    SAFE_RELEASE(pEnumerator);
  }
#endif

#ifdef TARGET_RASPBERRY_PI
  g_RBP.Deinitialize();
#endif

  return status;
}
Beispiel #27
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);

}
Beispiel #28
0
bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device)
{
  if (m_initialized)
    return false;

  CLog::Log(LOGDEBUG, __FUNCTION__": Initializing WASAPI Sink Rev. 1.0.5");

  m_device = device;

  /* Save requested format */
  /* Clear returned format */
  sinkReqFormat = format.m_dataFormat;
  sinkRetFormat = AE_FMT_INVALID;

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

  HRESULT 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)

  //Get our device.
  //First try to find the named device.
  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++)
  {
    IPropertyStore *pProperty = NULL;
    PROPVARIANT varName;

    hr = pEnumDevices->Item(i, &m_pDevice);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")

    hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")

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

    std::wstring strRawDevName(varName.pwszVal);
    std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end());
    //g_charsetConverter.ucs2CharsetToStringCharset(strRawDevName, strDevName.c_str());

    if (device == strDevName)
      i = uiCount;
    else
      SAFE_RELEASE(m_pDevice);

    PropVariantClear(&varName);
    SAFE_RELEASE(pProperty);
  }

  SAFE_RELEASE(pEnumDevices);

  if (!m_pDevice)
  {
    CLog::Log(LOGINFO, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices.  Trying the default device...", device.c_str());
    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")

    IPropertyStore *pProperty = NULL;
    PROPVARIANT varName;

    hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
    EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")

    hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);

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

    PropVariantClear(&varName);
    SAFE_RELEASE(pProperty);
  }

  //We are done with the enumerator.
  SAFE_RELEASE(pEnumerator);

  hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")

  if (!InitializeExclusive(format))
  {
    CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format");
    goto failed;
  }

  /* get the buffer size and calculate the frames for AE */
  m_pAudioClient->GetBufferSize(&m_uiBufferLen);

  format.m_frames       = m_uiBufferLen;
  format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
  m_format              = format;
  sinkRetFormat         = format.m_dataFormat;

  CLog::Log(LOGDEBUG, __FUNCTION__": Buffer Size     = %d Bytes", m_uiBufferLen * format.m_frameSize);

  hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")

  m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  hr = m_pAudioClient->SetEventHandle(m_needDataEvent);
  EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler.");

  m_initialized = true;
  m_isDirty     = false;

  return true;

failed:
  CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
  SAFE_RELEASE(pEnumDevices);
  SAFE_RELEASE(pEnumerator);
  SAFE_RELEASE(m_pRenderClient);
  SAFE_RELEASE(m_pAudioClient);
  SAFE_RELEASE(m_pDevice);
  CloseHandle(m_needDataEvent);

  return false;
}
Beispiel #29
0
RTC::ReturnCode_t RTCKinect::onActivated(RTC::UniqueId ec_id)
{
    /**
	 * The configured values should be reflected to the initialization process.
	 *
	 * m_enable_camera -> camera image
	 * m_enable_depth  -> depth image
	 * m_player_index  -> player index detection
	 *
	 * important: if player indexing is enabled, depth map image is limited up to 320x240
	 */

	DWORD dwFlag = NUI_INITIALIZE_FLAG_USES_SKELETON;
	if(m_enable_camera) {
		dwFlag |= NUI_INITIALIZE_FLAG_USES_COLOR;
	}
	if(m_enable_depth) {
		if(m_player_index) {
			dwFlag |= NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX;
		} else {
			dwFlag |= NUI_INITIALIZE_FLAG_USES_DEPTH;
		}
	}


	HRESULT hr = NuiInitialize(dwFlag); 
    if( FAILED( hr ) ) {
		std::cout << "NUI Initialize Failed." << std::endl;
		return RTC::RTC_ERROR;
    }

	if(m_depth_width == 640 && m_depth_height == 480 && m_enable_depth && m_player_index) {
		std::cout << "If PlayerIndex and Depth Map is ON, resolution should be 320X240" << std::endl;
		return RTC::RTC_ERROR;
	}
	NUI_IMAGE_RESOLUTION eResolution;
	if(m_camera_width == 640 && m_camera_height == 480) {
		eResolution = NUI_IMAGE_RESOLUTION_640x480;
	} else {
		std::cout << "Invalid Image Resolution" << std::endl;
		return RTC::RTC_ERROR;
	}
	if(m_enable_camera) {
		hr = NuiImageStreamOpen(::NUI_IMAGE_TYPE_COLOR, eResolution, 0, 2, NULL, &m_pVideoStreamHandle );
		if( FAILED( hr ) )
		{
			std::cout << "NUI Image Stream Open Failed." << std::endl;
			return RTC::RTC_ERROR;
		}
	}

	if(m_depth_width == 640 && m_depth_height == 480) {
		eResolution = NUI_IMAGE_RESOLUTION_640x480;
	} else if(m_depth_width == 320 && m_depth_height == 240) {
		eResolution = NUI_IMAGE_RESOLUTION_320x240;
	} else {
		std::cout << "Invalid Image Resolution" << std::endl;
		return RTC::RTC_ERROR;
	}
	if(m_enable_depth) {
		if(m_player_index) {
			hr = NuiImageStreamOpen(::NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, eResolution, 0, 2, NULL, &m_pDepthStreamHandle );
		} else {
			hr = NuiImageStreamOpen(::NUI_IMAGE_TYPE_DEPTH, eResolution, 0, 2, NULL, &m_pDepthStreamHandle );
		}
	}
    if( FAILED( hr ) ) {
		std::cout << "NUI Image Stream Open Failed." << std::endl;
		return RTC::RTC_ERROR;
    }

	this->m_image.width = m_camera_width;
	this->m_image.height = m_camera_height;
	this->m_image.pixels.length(m_camera_width*m_camera_height*3);

	this->m_depth.width = m_depth_width;
	this->m_depth.height = m_depth_height;
	this->m_depth.pixels.length(m_depth_width*m_depth_height*3);

    /**
	 * Initialization for raw sound input.
	 */
	if (m_enable_microphone) {
		UINT deviceCount;
		IMMDeviceEnumerator *deviceEnumerator = NULL;
		IMMDeviceCollection *deviceCollection = NULL;

		hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&deviceEnumerator));
		if (FAILED(hr)) {
			std::cout << "Unable to instantiate device enumerator." << std::endl;
			return RTC::RTC_ERROR;
		}
		hr = deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &deviceCollection);
		if (FAILED(hr)) {
			std::cout << "Unable to retrieve device collection." << std::endl;
			return RTC::RTC_ERROR;
		}
		hr = deviceCollection->GetCount(&deviceCount);
		if (FAILED(hr)) {
			std::cout << "Unable to get device collection length." << std::endl;
			return RTC::RTC_ERROR;
		}
		for (UINT i = 0; i < deviceCount; i++) {
			IPropertyStore *propertyStore;
			PROPVARIANT friendlyName;
			IMMDevice *endpoint;
			PropVariantInit(&friendlyName);

			hr = deviceCollection->Item(i, &endpoint);
			if (FAILED(hr)) {
				std::cout << "Unable to get device collection item." << std::endl;
				return RTC::RTC_ERROR;
			}

			hr = endpoint->OpenPropertyStore(STGM_READ, &propertyStore);
			if (FAILED(hr)) {
				std::cout << "Unable to open device property store." << std::endl;
				return RTC::RTC_ERROR;
			}

			hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
			SafeRelease(&propertyStore);
			if (FAILED(hr)) {
				std::cout << "Unable to retrieve friendly name for device." << std::endl;
				return RTC::RTC_ERROR;
			}

			std::cout << "Scanning for Kinect Audio device..." << std::endl;
			if (friendlyName.vt == VT_LPWSTR) {
				wprintf(L"  %s\n", friendlyName.pwszVal);
				if (wcscmp(friendlyName.pwszVal, L"Kinect USB Audio") != 0) {
					std::cout << "  Found Kinect Audio device" << std::endl;
					m_pAudioEndpoint = endpoint;
					m_pAudioEndpoint->AddRef();
					PropVariantClear(&friendlyName);
					SafeRelease(&endpoint);
					break;
				}
			}
			PropVariantClear(&friendlyName);
			SafeRelease(&endpoint);
		}
		SafeRelease(&deviceCollection);
		SafeRelease(&deviceEnumerator);

		m_AudioShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (m_AudioShutdownEvent == NULL) {
			std::cout << "Unable to create shutdown event." << std::endl;
			return RTC::RTC_ERROR;
		}    
		hr = m_pAudioEndpoint->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&m_pAudioClient));
		if (FAILED(hr)) {
			std::cout << "Unable to activate audio client." << std::endl;
			return RTC::RTC_ERROR;
		}
		hr = m_pAudioClient->GetMixFormat(&m_pAudioMixFormat);
		if (FAILED(hr)) {
			std::cout << "Unable to get mix format on audio client." << std::endl;
			return RTC::RTC_ERROR;
		}
	    m_AudioFrameSize = (m_pAudioMixFormat->wBitsPerSample / 8) * m_pAudioMixFormat->nChannels;
		m_AudioCaptureBufferSize = m_pAudioMixFormat->nSamplesPerSec * 5 * m_AudioFrameSize;
		m_pAudioCaptureBuffer = new (std::nothrow) BYTE[m_AudioCaptureBufferSize];
		if (m_pAudioCaptureBuffer == NULL) {
			std::cout << "Unable to allocate capture buffer." << std::endl;
			return RTC::RTC_ERROR;
		}
		m_AudioCurrentCaptureIndex = 0;
		std::cout << "Audio capture format (" << m_pAudioMixFormat->nChannels << " channels, " << m_pAudioMixFormat->wBitsPerSample << " bits)"<< std::endl;
		m_AudioLatency = 10;
		hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST, m_AudioLatency*10000, 0, m_pAudioMixFormat, NULL);
		if (FAILED(hr)) {
			std::cout << "Unable to initialize audio client." << std::endl;
			return RTC::RTC_ERROR;
		}
		hr = m_pAudioClient->GetService(IID_PPV_ARGS(&m_pAudioCaptureClient));
		if (FAILED(hr)) {
			std::cout << "Unable to get audio capture client." << std::endl;
			return RTC::RTC_ERROR;
		}
		m_AudioCaptureThread = CreateThread(NULL, 0, AudioCaptureThread, this, 0, NULL);
		if (m_AudioCaptureThread == NULL) {
			std::cout << "Unable to create transport thread: " << GetLastError() << std::endl;
			return RTC::RTC_ERROR;
		}
		hr = m_pAudioClient->Start();
		if (FAILED(hr)) {
			std::cout << "Unable to start audio capture client." << std::endl;
			return RTC::RTC_ERROR;
		}
	}

	return RTC::RTC_OK;
}
bool EnumBuiltinDevices_w64(const uint32_t deviceType, STUDIO_LINK_DEVICE_LIST* devices)
{
    PRECONDITION_RETURN(deviceType != INVALID_DEVICE_TYPE, false);
    PRECONDITION_RETURN(devices != 0, false);

    bool result = false;

    HRESULT hr = CoInitialize(0);
    if(SUCCEEDED(hr))
    {
        IMMDeviceEnumerator* pDeviceEnumerator = 0;
        hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 0, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
        if(SUCCEEDED(hr) && (pDeviceEnumerator != 0))
        {
            EDataFlow dataFlow = eAll;
            if(deviceType == HEADPHONE)
            {
                dataFlow = eRender;
            }
            else if(deviceType == MICROPHONE)
            {
                dataFlow = eCapture;
            }

            IMMDeviceCollection* pDeviceCollection = 0;
            hr = pDeviceEnumerator->EnumAudioEndpoints(dataFlow, DEVICE_STATE_ACTIVE, &pDeviceCollection);
            if(SUCCEEDED(hr) && (pDeviceCollection != 0))
            {
                UINT deviceCount = 0;
                hr = pDeviceCollection->GetCount(&deviceCount);
                if(SUCCEEDED(hr))
                {
                    size_t foundDevices = 0;
                    for(UINT i = 0; (i < deviceCount) && (foundDevices < deviceCount); i++)
                    {
                        IMMDevice* pDevice = 0;
                        hr = pDeviceCollection->Item(i, &pDevice);
                        if(SUCCEEDED(hr) && (pDevice != 0))
                        {
                            IPropertyStore* pProperties = 0;
                            hr = pDevice->OpenPropertyStore(STGM_READ, &pProperties);
                            if(SUCCEEDED(hr))
                            {
                                PROPVARIANT deviceFormatProperty;
                                PropVariantInit(&deviceFormatProperty);
                                hr = pProperties->GetValue(PKEY_AudioEngine_DeviceFormat, &deviceFormatProperty);
                                if(SUCCEEDED(hr) && (VT_BLOB == deviceFormatProperty.vt))
                                {
                                    WAVEFORMATEX* deviceFormat = (WAVEFORMATEX*)deviceFormatProperty.blob.pBlobData;
                                    devices->devices[foundDevices].channelCount = deviceFormat->nChannels;
                                    devices->devices[foundDevices].sampleRate = deviceFormat->nSamplesPerSec;

                                    if((WAVE_FORMAT_EXTENSIBLE == deviceFormat->wFormatTag) && (deviceFormat->cbSize >= 22))
                                    {
                                        //WAVEFORMATEXTENSIBLE* extensibleDeviceFormat = (WAVEFORMATEXTENSIBLE*)deviceFormat;
                                    }

                                    PropVariantClear(&deviceFormatProperty);

                                    PROPVARIANT deviceNameProperty;
                                    PropVariantInit(&deviceNameProperty);
                                    hr = pProperties->GetValue(PKEY_Device_FriendlyName, &deviceNameProperty);
                                    if(SUCCEEDED(hr))
                                    {
                                        PWSTR deviceName = 0;
                                        hr = PropVariantToStringAlloc(deviceNameProperty, &deviceName);
                                        if(SUCCEEDED(hr))
                                        {
                                            memset(devices->devices[foundDevices].name, 0, STUDIO_LINK_DEVICE_NAME_LENGTH);
                                            size_t numOfCharsConverted = 0;
                                            const size_t deviceNameLength = wcslen(deviceName);
                                            wcstombs_s(&numOfCharsConverted, devices->devices[foundDevices].name,
                                                STUDIO_LINK_DEVICE_NAME_LENGTH, deviceName, deviceNameLength);

                                            foundDevices++;

                                            CoTaskMemFree(deviceName);
                                            deviceName = 0;
                                        }

                                        PropVariantClear(&deviceNameProperty);
                                    }
                                }

                                SafeRelease(pProperties);
                            }

                            SafeRelease(pDevice);
                        }
                    }

                    devices->deviceCount = foundDevices;
                }

                SafeRelease(pDeviceCollection);
            }

            SafeRelease(pDeviceEnumerator);
        }

        CoUninitialize();
    }

    if(devices->deviceCount > 0)
    {
        result = true;
    }

    return result;
}