d048b845e4
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
256 lines
7.2 KiB
C
256 lines
7.2 KiB
C
/*
|
|
* SndEnum.c
|
|
*
|
|
* This file is part of Emu48
|
|
*
|
|
* Copyright (C) 2015 Christoph Gießelink
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
#include "Emu48.h"
|
|
#include "snddef.h"
|
|
|
|
typedef HRESULT (WINAPI *LPFNDLLGETCLASSOBJECT)(REFCLSID,REFIID,LPVOID *);
|
|
static LPFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
|
|
|
|
//
|
|
// create a IKsPropertySet interface
|
|
//
|
|
static __inline HRESULT DirectSoundPrivateCreate(LPKSPROPERTYSET *ppKsPropertySet)
|
|
{
|
|
LPCLASSFACTORY pClassFactory = NULL;
|
|
HRESULT hr;
|
|
|
|
// create a class factory object
|
|
#if defined __cplusplus
|
|
hr = pfnDllGetClassObject(CLSID_DirectSoundPrivate,IID_IClassFactory,(LPVOID *) &pClassFactory);
|
|
#else
|
|
hr = pfnDllGetClassObject(&CLSID_DirectSoundPrivate,&IID_IClassFactory,(LPVOID *) &pClassFactory);
|
|
#endif
|
|
|
|
// create the DirectSoundPrivate object and query for an IKsPropertySet interface
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
#if defined __cplusplus
|
|
hr = pClassFactory->CreateInstance(NULL,IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
|
#else
|
|
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory,NULL,&IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
|
#endif
|
|
}
|
|
|
|
if (pClassFactory) // release the class factory object
|
|
{
|
|
#if defined __cplusplus
|
|
pClassFactory->Release();
|
|
#else
|
|
pClassFactory->lpVtbl->Release(pClassFactory);
|
|
#endif
|
|
}
|
|
|
|
if (FAILED(hr) && *ppKsPropertySet) // handle failure
|
|
{
|
|
#if defined __cplusplus
|
|
(*ppKsPropertySet)->Release();
|
|
#else
|
|
(*ppKsPropertySet)->lpVtbl->Release(*ppKsPropertySet);
|
|
#endif
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// get the device information about a DirectSound GUID.
|
|
//
|
|
static BOOL GetInfoFromDSoundGUID(CONST GUID *lpGUID, UINT *puWaveDeviceID)
|
|
{
|
|
LPKSPROPERTYSET pKsPropertySet = NULL;
|
|
HRESULT hr;
|
|
BOOL bSuccess = FALSE;
|
|
|
|
hr = DirectSoundPrivateCreate(&pKsPropertySet);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG ulBytesReturned = 0;
|
|
|
|
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA sDirectSoundDeviceDescription;
|
|
|
|
ZeroMemory(&sDirectSoundDeviceDescription,sizeof(sDirectSoundDeviceDescription));
|
|
sDirectSoundDeviceDescription.DeviceId = *lpGUID;
|
|
|
|
// get the size of the direct sound device description
|
|
#if defined __cplusplus
|
|
hr = pKsPropertySet->Get(
|
|
DSPROPSETID_DirectSoundDevice,
|
|
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
|
NULL,
|
|
0,
|
|
&sDirectSoundDeviceDescription,
|
|
sizeof(sDirectSoundDeviceDescription),
|
|
&ulBytesReturned
|
|
);
|
|
#else
|
|
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
|
&DSPROPSETID_DirectSoundDevice,
|
|
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
|
NULL,
|
|
0,
|
|
&sDirectSoundDeviceDescription,
|
|
sizeof(sDirectSoundDeviceDescription),
|
|
&ulBytesReturned
|
|
);
|
|
#endif
|
|
|
|
if (SUCCEEDED(hr) && ulBytesReturned)
|
|
{
|
|
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA psDirectSoundDeviceDescription = NULL;
|
|
|
|
// fetch the direct sound device description
|
|
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA) malloc(ulBytesReturned);
|
|
if (psDirectSoundDeviceDescription != NULL)
|
|
{
|
|
// init structure with data from length request
|
|
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
|
|
|
|
#if defined __cplusplus
|
|
hr = pKsPropertySet->Get(
|
|
DSPROPSETID_DirectSoundDevice,
|
|
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
|
NULL,
|
|
0,
|
|
psDirectSoundDeviceDescription,
|
|
ulBytesReturned,
|
|
&ulBytesReturned
|
|
);
|
|
#else
|
|
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
|
&DSPROPSETID_DirectSoundDevice,
|
|
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
|
NULL,
|
|
0,
|
|
psDirectSoundDeviceDescription,
|
|
ulBytesReturned,
|
|
&ulBytesReturned
|
|
);
|
|
#endif
|
|
|
|
if ((bSuccess = SUCCEEDED(hr)))
|
|
{
|
|
// the requested device ID
|
|
*puWaveDeviceID = psDirectSoundDeviceDescription->WaveDeviceId;
|
|
}
|
|
free(psDirectSoundDeviceDescription);
|
|
}
|
|
}
|
|
|
|
#if defined __cplusplus
|
|
pKsPropertySet->Release();
|
|
#else
|
|
pKsPropertySet->lpVtbl->Release(pKsPropertySet);
|
|
#endif
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
//
|
|
// callback function for DirectSoundEnumerate()
|
|
//
|
|
static BOOL CALLBACK DSEnumProc(LPGUID lpGUID,LPCTSTR lpszDesc,LPCTSTR lpszDrvName,LPVOID lpContext)
|
|
{
|
|
HWND hWnd = (HWND) lpContext; // window handle of the combo box
|
|
|
|
if (lpGUID != NULL) // NULL only for "Primary Sound Driver"
|
|
{
|
|
UINT uDevID;
|
|
|
|
if (GetInfoFromDSoundGUID(lpGUID,&uDevID))
|
|
{
|
|
WAVEOUTCAPS woc;
|
|
|
|
// has device the necessary capabilities?
|
|
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
|
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
|
{
|
|
// copy product name and wave device ID to combo box
|
|
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) lpszDesc);
|
|
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
UNREFERENCED_PARAMETER(lpszDrvName);
|
|
}
|
|
|
|
// set listfield for sound device combo box
|
|
VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID)
|
|
{
|
|
typedef BOOL (CALLBACK *LPDSENUMCALLBACK)(LPGUID, LPCTSTR, LPCTSTR, LPVOID);
|
|
typedef HRESULT (WINAPI *LPFN_SDE)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext);
|
|
LPFN_SDE pfnDirectSoundEnumerate = NULL;
|
|
|
|
UINT uSelectDevice,uDevID,uDevNo;
|
|
|
|
HMODULE hDSound = LoadLibrary(_T("dsound.dll"));
|
|
|
|
if (hDSound != NULL) // direct sound dll found
|
|
{
|
|
#if defined _UNICODE
|
|
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateW");
|
|
#else
|
|
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateA");
|
|
#endif
|
|
pfnDllGetClassObject = (LPFNDLLGETCLASSOBJECT) GetProcAddress(hDSound,"DllGetClassObject");
|
|
}
|
|
|
|
SendMessage(hWnd,CB_RESETCONTENT,0,0);
|
|
|
|
// preset selector
|
|
uSelectDevice = (UINT) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) _T("Standard Audio"));
|
|
SendMessage(hWnd,CB_SETITEMDATA,uSelectDevice,WAVE_MAPPER);
|
|
|
|
// check for direct sound interface functions
|
|
if (pfnDirectSoundEnumerate != NULL && pfnDllGetClassObject != NULL)
|
|
{
|
|
// copy product name and wave device ID to combo box
|
|
if (SUCCEEDED(pfnDirectSoundEnumerate((LPDSENUMCALLBACK) DSEnumProc,hWnd)))
|
|
{
|
|
UINT i;
|
|
|
|
uDevNo = (UINT) SendMessage(hWnd,CB_GETCOUNT,0,0);
|
|
for (i = 0; i < uDevNo; ++i)
|
|
{
|
|
// translate device ID to combo box position
|
|
uDevID = (UINT) SendMessage(hWnd,CB_GETITEMDATA,i,0);
|
|
|
|
if (uDevID == uDeviceID) uSelectDevice = i;
|
|
}
|
|
}
|
|
}
|
|
else // direct sound not available, detect over wave capabilities
|
|
{
|
|
WAVEOUTCAPS woc;
|
|
|
|
uDevNo = waveOutGetNumDevs();
|
|
for (uDevID = 0; uDevID < uDevNo; ++uDevID)
|
|
{
|
|
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
|
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
|
{
|
|
// copy product name and wave device ID to combo box
|
|
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) woc.szPname);
|
|
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
|
|
|
if (uDevID == uDeviceID) uSelectDevice = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
// activate last selected combo box item
|
|
SendMessage(hWnd,CB_SETCURSEL,uSelectDevice,0L);
|
|
|
|
if (hDSound != NULL) // direct sound dll loaded
|
|
{
|
|
pfnDllGetClassObject = NULL;
|
|
VERIFY(FreeLibrary(hDSound));
|
|
}
|
|
return;
|
|
}
|