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