808 lines
22 KiB
C++
808 lines
22 KiB
C++
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 1999 - 1999 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: devmap.cpp
|
||
|
* Content: Maps various default devices GUIDs to real guids.
|
||
|
*
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 11-24-99 pnewson Created
|
||
|
* 12-02-99 rodtoll Added new functions for mapping device IDs and finding default
|
||
|
* devices.
|
||
|
* rodtoll Updated mapping function to map default devices to real GUIDs
|
||
|
* for non-DX7.1 platforms.
|
||
|
* 01/25/2000 pnewson Added DV_MapWaveIDToGUID
|
||
|
* 04/14/2000 rodtoll Bug #32341 GUID_NULL and NULL map to different devices
|
||
|
* Updated so both map to default voice device
|
||
|
* 04/19/2000 pnewson Error handling cleanup
|
||
|
* 04/20/2000 rodtoll Bug #32889 - Unable to run on non-admin accounts on Win2k
|
||
|
* 06/28/2000 rodtoll Prefix Bug #38022
|
||
|
* rodtoll Whistler Bug #128427 - Unable to run voice wizard from multimedia control panel
|
||
|
* 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h, added STR_* and strutils.h
|
||
|
* 01/08/2001 rodtoll WINBUG #256541 Pseudo: Loss of functionality: Voice Wizrd can't be launched.
|
||
|
* 04/02/2001 simonpow Fixes for PREfast bugs #354859
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "dxvutilspch.h"
|
||
|
|
||
|
|
||
|
#undef DPF_SUBCOMP
|
||
|
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
|
||
|
|
||
|
|
||
|
#define REGSTR_WAVEMAPPER L"Software\\Microsoft\\Multimedia\\Sound Mapper"
|
||
|
#define REGSTR_PLAYBACK L"Playback"
|
||
|
#define REGSTR_RECORD L"Record"
|
||
|
|
||
|
// function pointer typedefs
|
||
|
typedef HRESULT (* PFGETDEVICEID)(LPCGUID, LPGUID);
|
||
|
|
||
|
typedef HRESULT (WINAPI *DSENUM)( LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext );
|
||
|
|
||
|
struct DSWaveDeviceFind_Param
|
||
|
{
|
||
|
GUID guidDevice;
|
||
|
UINT uiDevice;
|
||
|
UINT uiCounter;
|
||
|
BOOL fCapture;
|
||
|
};
|
||
|
|
||
|
// DSWaveDeviceFind
|
||
|
//
|
||
|
// This callback function is used to try and match the GUID of the device to a
|
||
|
// wave ID#. Once it finds the entry that matches the device GUID it determines
|
||
|
// the waveIN ID by one of two methods:
|
||
|
//
|
||
|
// 1. Looks at the driver name, and looks for WaveIN X and uses X as the device ID.
|
||
|
// (Only works on english versions). (WaveIN only)
|
||
|
// 2. Fuzzy Matching - Order in enumeration determines device ID. The first device
|
||
|
// which is not the default is device 0, second is device 1, etc.. etc...
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DSWaveDeviceFind"
|
||
|
|
||
|
BOOL CALLBACK DSWaveDeviceFind(
|
||
|
LPGUID lpGUID,
|
||
|
LPCTSTR lpszDesc,
|
||
|
LPCTSTR lpszDrvName,
|
||
|
LPVOID lpContext
|
||
|
) {
|
||
|
|
||
|
DSWaveDeviceFind_Param *pParam = (DSWaveDeviceFind_Param *) lpContext;
|
||
|
|
||
|
if( lpGUID == NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Ignoring default" );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if( *lpGUID == pParam->guidDevice )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Device found id=%x", pParam->uiCounter );
|
||
|
|
||
|
if( pParam->fCapture && sscanf( lpszDrvName, "WaveIn %u", &pParam->uiDevice ) == 1 )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Emulated Driver, Positive match found id=%d", pParam->uiDevice );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParam->uiDevice = pParam->uiCounter;
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Fuzzy match found id=%d", pParam->uiDevice );
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
pParam->uiCounter++;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// This function uses DSWaveDeviceFind to do a fuzzy map from GUID --> device ID on
|
||
|
// old operating systems.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_LegacyFuzzyGUIDMap"
|
||
|
HRESULT DV_LegacyFuzzyGUIDMap( BOOL fCapture, const GUID &guidDevice, DWORD *pdwDeviceID )
|
||
|
{
|
||
|
DSENUM enumFunc;
|
||
|
HINSTANCE hinstds;
|
||
|
DSWaveDeviceFind_Param findParam;
|
||
|
HRESULT hr;
|
||
|
|
||
|
hinstds = NULL;
|
||
|
|
||
|
// Attempt to load the directsound DLL
|
||
|
hinstds = LoadLibraryA( "DSOUND.DLL" );
|
||
|
|
||
|
// If it couldn't be loaded, this sub system is not supported
|
||
|
// on this system.
|
||
|
if( hinstds == NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Unable to load dsound.dll to enum devices" );
|
||
|
return DVERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
// Attempt to get the DirectSoundCaptureEnumerateA function from the
|
||
|
// DSOUND.DLL. If it's not available then this class assumes it's
|
||
|
// not supported on this system.
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
#ifdef UNICODE
|
||
|
enumFunc = (DSENUM) GetProcAddress( hinstds, "DirectSoundCaptureEnumerateW" );
|
||
|
#else
|
||
|
enumFunc = (DSENUM) GetProcAddress( hinstds, "DirectSoundCaptureEnumerateA" );
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#ifdef UNICODE
|
||
|
enumFunc = (DSENUM) GetProcAddress( hinstds, "DirectSoundEnumerateW" );
|
||
|
#else
|
||
|
enumFunc = (DSENUM) GetProcAddress( hinstds, "DirectSoundEnumerateA" );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if( enumFunc == NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Unable to find enum func for enumerate" );
|
||
|
FreeLibrary( hinstds );
|
||
|
return DVERR_NOTSUPPORTED;
|
||
|
}
|
||
|
|
||
|
findParam.guidDevice = guidDevice;
|
||
|
findParam.uiDevice = 0xFFFFFFFF;
|
||
|
findParam.uiCounter = 0;
|
||
|
findParam.fCapture = fCapture;
|
||
|
|
||
|
hr = (*enumFunc)( DSWaveDeviceFind, &findParam );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Error enumerating capture devices hr = 0x%x", hr );
|
||
|
}
|
||
|
|
||
|
if( findParam.uiDevice == 0xFFFFFFFF )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to map the capture device. Defaulting to 0" );
|
||
|
|
||
|
*pdwDeviceID = 0;
|
||
|
hr = DVERR_INVALIDDEVICE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pdwDeviceID = findParam.uiDevice;
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Found the device during enum, id=%d", findParam.uiDevice );
|
||
|
}
|
||
|
|
||
|
FreeLibrary( hinstds );
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_CheckDeviceGUID"
|
||
|
HRESULT DV_CheckDeviceGUID( BOOL fCapture, const GUID &guidDevice )
|
||
|
{
|
||
|
DWORD dwDeviceID;
|
||
|
|
||
|
return DV_MapGUIDToWaveID( fCapture, guidDevice, &dwDeviceID );
|
||
|
}
|
||
|
|
||
|
// DV_MapGUIDToWaveID
|
||
|
//
|
||
|
// This function maps the specified GUID to the corresponding waveIN/waveOut device
|
||
|
// ID. For default devices it looks up the system's default device, for other devices
|
||
|
// it uses the private interface.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_MapGUIDToWaveID"
|
||
|
HRESULT DV_MapGUIDToWaveID( BOOL fCapture, const GUID &guidDevice, DWORD *pdwDevice )
|
||
|
{
|
||
|
LPKSPROPERTYSET pPropertySet;
|
||
|
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pData;
|
||
|
GUID tmpGUID;
|
||
|
HRESULT hr;
|
||
|
|
||
|
// We're running on pre-private interface, no way to map default
|
||
|
// device.
|
||
|
if( guidDevice == GUID_NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Mapping GUID to WaveID. Mapping GUID_NULL" );
|
||
|
|
||
|
hr = DV_LegacyGetDefaultDeviceID( fCapture, pdwDevice );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to determine default system waveIN ID hr = 0x%x", hr );
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Mapping non GUID_NULL to Wave ID" );
|
||
|
|
||
|
hr = DirectSoundPrivateCreate( &pPropertySet );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to map GUID, attempting fuzzy map" );
|
||
|
|
||
|
hr = DV_LegacyFuzzyGUIDMap( fCapture, guidDevice, pdwDevice );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to map GUID to wave. Defaulting to ID 0 hr=0x%x", hr );
|
||
|
*pdwDevice = 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmpGUID = guidDevice;
|
||
|
|
||
|
hr = PrvGetDeviceDescription( pPropertySet, tmpGUID, &pData );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to find GUID. Defaulting to ID 0 hr=0x%x", hr );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pdwDevice = pData->WaveDeviceId;
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Mapped GUID to Wave ID %d", *pdwDevice );
|
||
|
delete pData;
|
||
|
}
|
||
|
|
||
|
pPropertySet->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// DV_MapWaveIDToGUID
|
||
|
//
|
||
|
// This function maps the specified waveIN/waveOut device ID to the corresponding DirectSound
|
||
|
// GUID.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_MapWaveIDToGUID"
|
||
|
HRESULT DV_MapWaveIDToGUID( BOOL fCapture, DWORD dwDevice, GUID &guidDevice )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
LPKSPROPERTYSET ppKsPropertySet;
|
||
|
HMODULE hModule;
|
||
|
|
||
|
hModule = LoadLibraryA( "dsound.dll " );
|
||
|
|
||
|
if( hModule == NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Could not load dsound.dll" );
|
||
|
return DVERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
hr = DirectSoundPrivateCreate( &ppKsPropertySet );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
FreeLibrary( hModule );
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get interface for ID<-->GUID Map hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if( DNGetOSType() == VER_PLATFORM_WIN32_NT )
|
||
|
{
|
||
|
WAVEINCAPSW wiCapsW;
|
||
|
WAVEOUTCAPSW woCapsW;
|
||
|
MMRESULT mmr;
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
mmr = waveInGetDevCapsW( dwDevice, &wiCapsW, sizeof( WAVEINCAPSW ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = waveOutGetDevCapsW( dwDevice, &woCapsW, sizeof( WAVEOUTCAPSW ) );
|
||
|
}
|
||
|
|
||
|
if( mmr != MMSYSERR_NOERROR )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Specified device is invalid hr=0x%x", mmr );
|
||
|
ppKsPropertySet->Release();
|
||
|
FreeLibrary( hModule );
|
||
|
return DVERR_INVALIDPARAM;
|
||
|
}
|
||
|
|
||
|
hr = PrvGetWaveDeviceMappingW( ppKsPropertySet, (fCapture) ? wiCapsW.szPname : woCapsW.szPname , fCapture, &guidDevice );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WAVEINCAPSA wiCapsA;
|
||
|
WAVEOUTCAPSA woCapsA;
|
||
|
MMRESULT mmr;
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
mmr = waveInGetDevCapsA( dwDevice, &wiCapsA, sizeof( WAVEINCAPSA ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = waveOutGetDevCapsA( dwDevice, &woCapsA, sizeof( WAVEOUTCAPSA ) );
|
||
|
}
|
||
|
|
||
|
if( mmr != MMSYSERR_NOERROR )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Specified device is invalid hr=0x%x", mmr );
|
||
|
ppKsPropertySet->Release();
|
||
|
FreeLibrary( hModule );
|
||
|
return DVERR_INVALIDPARAM;
|
||
|
}
|
||
|
|
||
|
hr = PrvGetWaveDeviceMapping( ppKsPropertySet, (fCapture) ? wiCapsA.szPname : woCapsA.szPname , fCapture, &guidDevice );
|
||
|
}
|
||
|
|
||
|
ppKsPropertySet->Release();
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to map ID-->GUID hr=0x%x", hr );
|
||
|
}
|
||
|
|
||
|
FreeLibrary( hModule );
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
// DV_GetDefaultDeviceID_Win2000
|
||
|
//
|
||
|
// Looks up the default waveIN or waveOut device ID for the system under
|
||
|
// Windows 2000.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_GetDefaultDeviceID_Win2000"
|
||
|
HRESULT DV_GetDefaultDeviceID_Win2000( BOOL fCapture, DWORD *pdwDeviceID )
|
||
|
{
|
||
|
MMRESULT mmr;
|
||
|
DWORD dwFlags = 0;
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
mmr = waveInMessage((HWAVEIN) ((UINT_PTR) WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) pdwDeviceID, (DWORD_PTR) &dwFlags);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = waveOutMessage((HWAVEOUT) ((UINT_PTR) WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) pdwDeviceID, (DWORD_PTR) &dwFlags);
|
||
|
}
|
||
|
|
||
|
if( mmr != 0 )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to retrieve default device (Method A)" );
|
||
|
}
|
||
|
|
||
|
return CMixerLine::MMRESULTtoHRESULT(mmr);
|
||
|
}
|
||
|
|
||
|
// DV_GetDefaultWaveInID_Win2k
|
||
|
//
|
||
|
// Looks up the default waveIN or waveOut device ID for Win9x/Millenium
|
||
|
// systems.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_GetDefaultWaveInID_Win2k"
|
||
|
HRESULT DV_GetDefaultDeviceID_Win9X( BOOL fCapture, DWORD *pdwDeviceID )
|
||
|
{
|
||
|
CRegistry reg;
|
||
|
wchar_t lpwszDeviceName[MAX_REGISTRY_STRING_SIZE+1];
|
||
|
char lpszDeviceName[MAX_REGISTRY_STRING_SIZE+1];
|
||
|
DWORD dwSize;
|
||
|
DWORD dwIndex;
|
||
|
UINT uiNumDevices;
|
||
|
WAVEINCAPS wiCaps;
|
||
|
WAVEOUTCAPS woCaps;
|
||
|
MMRESULT mmr;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if( !reg.Open( HKEY_CURRENT_USER, REGSTR_WAVEMAPPER, TRUE, FALSE ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to retrieve default device, cannot open (Method B)" );
|
||
|
return DVERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
dwSize = MAX_REGISTRY_STRING_SIZE+1;
|
||
|
|
||
|
if( !reg.ReadString( fCapture ? REGSTR_RECORD : REGSTR_PLAYBACK, lpwszDeviceName, &dwSize ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to retrieve default device, cannot find (Method B)" );
|
||
|
return DVERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
uiNumDevices = waveInGetNumDevs();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uiNumDevices = waveOutGetNumDevs();
|
||
|
}
|
||
|
|
||
|
#if !defined(_UNICODE) && !defined(UNICODE)
|
||
|
hr = STR_jkWideToAnsi( lpszDeviceName, lpwszDeviceName, MAX_REGISTRY_STRING_SIZE );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to convert device name ansi", lpszDeviceName );
|
||
|
return hr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
for( dwIndex = 0; dwIndex < uiNumDevices; dwIndex++ )
|
||
|
{
|
||
|
if( fCapture )
|
||
|
{
|
||
|
mmr = waveInGetDevCaps( dwIndex, &wiCaps, sizeof( WAVEINCAPS ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = waveOutGetDevCaps( dwIndex, &woCaps, sizeof( WAVEOUTCAPS ) );
|
||
|
}
|
||
|
|
||
|
if( FAILED( mmr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Error querying device mmr=0x%x", mmr );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( _tcscmp( (fCapture) ? wiCaps.szPname : woCaps.szPname, lpszDeviceName ) == 0 )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Found default device, id=%d", dwIndex );
|
||
|
*pdwDeviceID = dwIndex;
|
||
|
return DV_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to retrieve default device, could not match default device. (Method B)" );
|
||
|
|
||
|
return DVERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
// DV_LegacyGetDefaultDeviceID
|
||
|
//
|
||
|
// This function finds the default playback or capture device in the
|
||
|
// system. (It's waveIN/waveOut device ID).
|
||
|
//
|
||
|
// This function will work on all Win9X platforms, Windows 2000.
|
||
|
//
|
||
|
// Not tested on Windows NT 4.0.
|
||
|
//
|
||
|
HRESULT DV_LegacyGetDefaultDeviceID( BOOL fCapture, DWORD *pdwDeviceID )
|
||
|
{
|
||
|
DNASSERT( pdwDeviceID != NULL );
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = DV_GetDefaultDeviceID_Win2000( fCapture, pdwDeviceID );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Failed method A hr = 0x%x", hr );
|
||
|
|
||
|
hr = DV_GetDefaultDeviceID_Win9X( fCapture, pdwDeviceID );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Failed method B hr = 0x%x" , hr );
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
}
|
||
|
|
||
|
// DV_LegacyMapDefaultGUID
|
||
|
//
|
||
|
// For systems that don't have DX7.1, determines the GUID for the default
|
||
|
// playback or record devices. It does this by:
|
||
|
//
|
||
|
// 1. Looking up the system's default waveIn/waveOut ID
|
||
|
// 2. Looking up the device's name
|
||
|
// 3. Uses the private interface to map to a GUID
|
||
|
//
|
||
|
// This function will not work for systems without the private interface.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_LegacyMapDefaultGUID"
|
||
|
HRESULT DV_LegacyMapDefaultGUID( BOOL fCapture, GUID* lpguidDevice)
|
||
|
{
|
||
|
DWORD dwDeviceID = 0;
|
||
|
HRESULT hr = DV_OK;
|
||
|
LPKSPROPERTYSET pPropertySet = NULL;
|
||
|
WAVEINCAPS wiCaps;
|
||
|
WAVEOUTCAPS woCaps;
|
||
|
MMRESULT mmr = 0;
|
||
|
|
||
|
hr = DV_LegacyGetDefaultDeviceID( fCapture, &dwDeviceID );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Could not determine default device ID hr=0x%x", hr );
|
||
|
*lpguidDevice = GUID_NULL;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "MapDefCapDev: Default device is device ID#%d", dwDeviceID );
|
||
|
DPFX(DPFPREP, DVF_INFOLEVEL, "MapDefCapDev: Searching for matching GUID" );
|
||
|
|
||
|
hr = DirectSoundPrivateCreate( &pPropertySet );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "MapDefCapDev: Unable to access search. (Defaulting to GUID_NULL) hr=0x%x", hr );
|
||
|
*lpguidDevice = GUID_NULL;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if( fCapture )
|
||
|
{
|
||
|
mmr = waveInGetDevCaps( dwDeviceID, &wiCaps, sizeof( WAVEINCAPS ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = waveOutGetDevCaps( dwDeviceID, &woCaps, sizeof( WAVEOUTCAPS ) );
|
||
|
}
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DNASSERT( FALSE );
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "MapDefCapDev: Retrieving device info failed default to GUID_NULL mmr=0x%x", mmr );
|
||
|
pPropertySet->Release();
|
||
|
*lpguidDevice = GUID_NULL;
|
||
|
return CMixerLine::MMRESULTtoHRESULT( mmr );
|
||
|
}
|
||
|
|
||
|
hr = PrvGetWaveDeviceMapping( pPropertySet, (fCapture) ? wiCaps.szPname : woCaps.szPname, fCapture, lpguidDevice );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "MapDefCapDev: Unable to map from ID to GUID, defaulting to GUID_NULL hr=0x%x" , hr );
|
||
|
*lpguidDevice = GUID_NULL;
|
||
|
}
|
||
|
|
||
|
pPropertySet->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_MapCaptureDevice"
|
||
|
HRESULT DV_MapCaptureDevice(const GUID* lpguidCaptureDeviceIn, GUID* lpguidCaptureDeviceOut)
|
||
|
{
|
||
|
LONG lRet;
|
||
|
HRESULT hr;
|
||
|
PFGETDEVICEID pfGetDeviceID;
|
||
|
|
||
|
// attempt to map any default guids to real guids...
|
||
|
HINSTANCE hDSound = LoadLibraryA("dsound.dll");
|
||
|
if (hDSound == NULL)
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get instance handle to DirectSound dll: %s", "dsound.dll");
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "LoadLibrary error code: %i", lRet);
|
||
|
hr = DVERR_GENERIC;
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
|
||
|
// attempt to get a pointer to the GetDeviceId function
|
||
|
pfGetDeviceID = (PFGETDEVICEID)GetProcAddress(hDSound, "GetDeviceID");
|
||
|
if (pfGetDeviceID == NULL)
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get a pointer to GetDeviceID function: %s", "GetDeviceID" );
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "GetProcAddress error code: %i", lRet);
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Assuming that we are running on a Pre-DX7.1 DirectSound", lRet);
|
||
|
|
||
|
// On a pre-DX 7.1 system, we map NULL to GUID_NULL, and that's all, since
|
||
|
// the other "default" guids don't really exist on this system (i.e. if I were
|
||
|
// to pass them to DirectSound, it wouldn't understand.).
|
||
|
if (lpguidCaptureDeviceIn == NULL ||
|
||
|
*lpguidCaptureDeviceIn == DSDEVID_DefaultCapture ||
|
||
|
*lpguidCaptureDeviceIn == DSDEVID_DefaultVoiceCapture ||
|
||
|
*lpguidCaptureDeviceIn == GUID_NULL )
|
||
|
{
|
||
|
hr = DV_LegacyMapDefaultGUID( TRUE, lpguidCaptureDeviceOut );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DNASSERT( FALSE );
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to perform old mapping. Assuming GUID_NULL" );
|
||
|
*lpguidCaptureDeviceOut = GUID_NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpguidCaptureDeviceOut = *lpguidCaptureDeviceIn;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Use the GetDeviceID function to map the devices.
|
||
|
if (lpguidCaptureDeviceIn == NULL)
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: Mapping null device pointer to DSDEVID_DefaultCapture");
|
||
|
lpguidCaptureDeviceIn = &DSDEVID_DefaultCapture;
|
||
|
}
|
||
|
else if (*lpguidCaptureDeviceIn == GUID_NULL)
|
||
|
{
|
||
|
// GetDeviceID does not accept GUID_NULL, since it does not know
|
||
|
// if we are asking for a capture or playback device. So we map
|
||
|
// GUID_NULL to the system default capture device here. Then
|
||
|
// GetDeviceID can map it to the real device.
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: Mapping GUID_NULL to DSDEVID_DefaultCapture");
|
||
|
lpguidCaptureDeviceIn = &DSDEVID_DefaultCapture;
|
||
|
}
|
||
|
|
||
|
GUID guidTemp;
|
||
|
hr = pfGetDeviceID(lpguidCaptureDeviceIn, &guidTemp);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "GetDeviceID failed: %i", hr);
|
||
|
if (hr == DSERR_NODRIVER)
|
||
|
{
|
||
|
hr = DVERR_INVALIDDEVICE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = DVERR_GENERIC;
|
||
|
}
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
if (*lpguidCaptureDeviceIn != guidTemp)
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: GetDeviceID mapped device GUID");
|
||
|
*lpguidCaptureDeviceOut = guidTemp;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpguidCaptureDeviceOut = *lpguidCaptureDeviceIn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!FreeLibrary(hDSound))
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "FreeLibrary failed, code: %i", lRet);
|
||
|
hr = DVERR_GENERIC;
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
|
||
|
error_cleanup:
|
||
|
if (hDSound != NULL)
|
||
|
{
|
||
|
FreeLibrary(hDSound);
|
||
|
}
|
||
|
DPF_EXIT();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DV_MapPlaybackDevice"
|
||
|
HRESULT DV_MapPlaybackDevice(const GUID* lpguidPlaybackDeviceIn, GUID* lpguidPlaybackDeviceOut)
|
||
|
{
|
||
|
LONG lRet;
|
||
|
HRESULT hr;
|
||
|
PFGETDEVICEID pfGetDeviceID;
|
||
|
|
||
|
// attempt to map any default guids to real guids...
|
||
|
HINSTANCE hDSound = LoadLibraryA("dsound.dll");
|
||
|
if (hDSound == NULL)
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get instance handle to DirectSound dll: %s", "dsound.dll");
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "LoadLibrary error code: %i", lRet);
|
||
|
hr = DVERR_GENERIC;
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
|
||
|
// attempt to get a pointer to the GetDeviceId function
|
||
|
pfGetDeviceID = (PFGETDEVICEID)GetProcAddress(hDSound, "GetDeviceID");
|
||
|
if (pfGetDeviceID == NULL)
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get a pointer to GetDeviceID function: %s", "GetDeviceID");
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "GetProcAddress error code: %i", lRet);
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Assuming that we are running on a Pre-DX7.1 DirectSound", lRet);
|
||
|
|
||
|
// On a pre-DX 7.1 system, we map NULL to GUID_NULL, and that's all, since
|
||
|
// the other "default" guids don't really exist on this system (i.e. if I were
|
||
|
// to pass them to DirectSound, it wouldn't understand.).
|
||
|
|
||
|
if (lpguidPlaybackDeviceIn == NULL ||
|
||
|
*lpguidPlaybackDeviceIn == DSDEVID_DefaultPlayback ||
|
||
|
*lpguidPlaybackDeviceIn == DSDEVID_DefaultVoicePlayback ||
|
||
|
*lpguidPlaybackDeviceIn == GUID_NULL )
|
||
|
{
|
||
|
hr = DV_LegacyMapDefaultGUID( FALSE, lpguidPlaybackDeviceOut );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DNASSERT( FALSE );
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to perform old mapping. Assuming GUID_NULL" );
|
||
|
*lpguidPlaybackDeviceOut = GUID_NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpguidPlaybackDeviceOut = *lpguidPlaybackDeviceIn;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Use the GetDeviceID function to map the devices.
|
||
|
if (lpguidPlaybackDeviceIn == NULL)
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: Mapping null device pointer to DSDEVID_DefaultPlayback");
|
||
|
lpguidPlaybackDeviceIn = &DSDEVID_DefaultPlayback;
|
||
|
}
|
||
|
else if (*lpguidPlaybackDeviceIn == GUID_NULL)
|
||
|
{
|
||
|
// GetDeviceID does not accept GUID_NULL, since it does not know
|
||
|
// if we are asking for a capture or playback device. So we map
|
||
|
// GUID_NULL to the system default playback device here. Then
|
||
|
// GetDeviceID can map it to the real device.
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: Mapping GUID_NULL to DSDEVID_DefaultPlayback");
|
||
|
lpguidPlaybackDeviceIn = &DSDEVID_DefaultPlayback;
|
||
|
}
|
||
|
|
||
|
GUID guidTemp;
|
||
|
hr = pfGetDeviceID(lpguidPlaybackDeviceIn, &guidTemp);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "GetDeviceID failed: %i", hr);
|
||
|
if (hr == DSERR_NODRIVER)
|
||
|
{
|
||
|
hr = DVERR_INVALIDDEVICE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = DVERR_GENERIC;
|
||
|
}
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
if (*lpguidPlaybackDeviceIn != guidTemp)
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: GetDeviceID mapped device GUID");
|
||
|
*lpguidPlaybackDeviceOut = guidTemp;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpguidPlaybackDeviceOut = *lpguidPlaybackDeviceIn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!FreeLibrary(hDSound))
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "FreeLibrary failed, code: %i", lRet);
|
||
|
hr = DVERR_GENERIC;
|
||
|
goto error_cleanup;
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
|
||
|
error_cleanup:
|
||
|
if (hDSound != NULL)
|
||
|
{
|
||
|
FreeLibrary(hDSound);
|
||
|
}
|
||
|
DPF_EXIT();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|