257 lines
7.2 KiB
C
257 lines
7.2 KiB
C
|
/*
|
|||
|
* SndEnum.c
|
|||
|
*
|
|||
|
* This file is part of Emu48
|
|||
|
*
|
|||
|
* Copyright (C) 2015 Christoph Gie<EFBFBD>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;
|
|||
|
}
|