-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSNDENUM.C
256 lines (223 loc) · 7.19 KB
/
SNDENUM.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
* SndEnum.c
*
* This file is part of Emu42
*
* Copyright (C) 2016 Christoph Gießelink
*
*/
#include "pch.h"
#include "Emu42.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;
}