emu48-mirror/Sources/Emu48/SNDENUM.C
Gwenhael Le Moine ed59d66683
2016-09-11: Updated to version 1.58
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
2024-03-19 23:35:30 +01:00

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