- Start rewrite of DirectSound
[reactos.git] / reactos / dll / directx / dsound_new / directsound.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/directsound.c
5 * PURPOSE: Handles IDirectSound interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10 #include "precomp.h"
11
12 typedef struct
13 {
14 IDirectSound8Vtbl *lpVtbl;
15 LONG ref;
16 GUID DeviceGUID;
17 BOOL bInitialized;
18 DWORD dwLevel;
19 LPFILTERINFO Filter;
20 LPDIRECTSOUNDBUFFER8 PrimaryBuffer;
21
22
23 }CDirectSoundImpl, *LPCDirectSoundImpl;
24
25 HRESULT
26 WINAPI
27 IDirectSound8_fnQueryInterface(
28 LPDIRECTSOUND8 iface,
29 REFIID riid,
30 LPVOID * ppobj)
31 {
32 LPOLESTR pStr;
33 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
34
35
36 if (IsEqualIID(riid, &IID_IUnknown) ||
37 IsEqualIID(riid, &IID_IDirectSound) ||
38 IsEqualIID(riid, &IID_IDirectSound8))
39 {
40 *ppobj = (LPVOID)&This->lpVtbl;
41 InterlockedIncrement(&This->ref);
42 return S_OK;
43 }
44
45 if (SUCCEEDED(StringFromIID(riid, &pStr)))
46 {
47 DPRINT("No Interface for class %s\n", pStr);
48 CoTaskMemFree(pStr);
49 }
50 return E_NOINTERFACE;
51 }
52
53 ULONG
54 WINAPI
55 IDirectSound8_fnAddRef(
56 LPDIRECTSOUND8 iface)
57 {
58 ULONG ref;
59 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
60
61 ref = InterlockedIncrement(&This->ref);
62
63 return ref;
64 }
65
66 ULONG
67 WINAPI
68 IDirectSound8_fnRelease(
69 LPDIRECTSOUND8 iface)
70 {
71 ULONG ref;
72 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
73
74 ref = InterlockedDecrement(&(This->ref));
75
76 if (!ref)
77 {
78 HeapFree(GetProcessHeap(), 0, This);
79 }
80
81 return ref;
82 }
83
84 HRESULT
85 WINAPI
86 IDirectSound8_fnCreateSoundBuffer(
87 LPDIRECTSOUND8 iface,
88 LPCDSBUFFERDESC lpcDSBufferDesc,
89 LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer,
90 IUnknown FAR* pUnkOuter)
91 {
92 HRESULT hResult;
93 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
94
95 if (!This->bInitialized)
96 {
97 /* object not yet initialized */
98 return DSERR_UNINITIALIZED;
99 }
100
101 if (!lpcDSBufferDesc || !lplpDirectSoundBuffer || pUnkOuter != NULL)
102 {
103 DPRINT("Invalid parameter %p %p %p\n", lpcDSBufferDesc, lplpDirectSoundBuffer, pUnkOuter);
104 return DSERR_INVALIDPARAM;
105 }
106
107 /* check buffer description */
108 if ((lpcDSBufferDesc->dwSize != sizeof(DSBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSBUFFERDESC1)) || lpcDSBufferDesc->dwReserved != 0)
109 {
110 DPRINT("Invalid buffer description size %u expected %u dwReserved %u\n", lpcDSBufferDesc->dwSize, sizeof(DSBUFFERDESC1), lpcDSBufferDesc->dwReserved);
111 return DSERR_INVALIDPARAM;
112 }
113
114 DPRINT("This %p dwFlags %x dwBufferBytes %u lpwfxFormat %p dwSize %u\n", This, lpcDSBufferDesc->dwFlags, lpcDSBufferDesc->dwBufferBytes, lpcDSBufferDesc->lpwfxFormat, lpcDSBufferDesc->dwSize);
115
116 if (lpcDSBufferDesc->dwFlags & DSBCAPS_PRIMARYBUFFER)
117 {
118 if (lpcDSBufferDesc->lpwfxFormat != NULL)
119 {
120 /* format must be null for primary sound buffer */
121 return DSERR_INVALIDPARAM;
122 }
123
124 if (This->PrimaryBuffer)
125 {
126 /* primary buffer already exists */
127 IDirectSoundBuffer8_AddRef(This->PrimaryBuffer);
128 *lplpDirectSoundBuffer = (LPDIRECTSOUNDBUFFER)This->PrimaryBuffer;
129 return S_OK;
130 }
131
132 hResult = NewPrimarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel);
133 if (SUCCEEDED(hResult))
134 {
135 /* store primary buffer */
136 This->PrimaryBuffer = (LPDIRECTSOUNDBUFFER8)*lplpDirectSoundBuffer;
137 }
138 return hResult;
139 }
140 else
141 {
142 if (lpcDSBufferDesc->lpwfxFormat == NULL)
143 {
144 /* format must not be null */
145 return DSERR_INVALIDPARAM;
146 }
147
148 if (!This->PrimaryBuffer)
149 {
150 hResult = NewPrimarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel);
151 if (SUCCEEDED(hResult))
152 {
153 /* store primary buffer */
154 This->PrimaryBuffer = (LPDIRECTSOUNDBUFFER8)*lplpDirectSoundBuffer;
155 }
156 else
157 {
158 DPRINT("Failed to create primary buffer with %x\n", hResult);
159 return hResult;
160 }
161
162 }
163
164 ASSERT(This->PrimaryBuffer);
165
166 DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n",
167 This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize);
168
169 hResult = NewSecondarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel, lpcDSBufferDesc, This->PrimaryBuffer);
170 return hResult;
171 }
172 }
173
174 HRESULT
175 WINAPI
176 IDirectSound8_fnGetCaps(
177 LPDIRECTSOUND8 iface,
178 LPDSCAPS lpDSCaps)
179 {
180 UNIMPLEMENTED;
181 return DSERR_GENERIC;
182 }
183
184 HRESULT
185 WINAPI
186 IDirectSound8_fnDuplicateSoundBuffer(
187 LPDIRECTSOUND8 iface,
188 LPDIRECTSOUNDBUFFER lpDsbOriginal,
189 LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate)
190 {
191 UNIMPLEMENTED;
192 return DSERR_OUTOFMEMORY;
193 }
194
195 HRESULT
196 WINAPI
197 IDirectSound8_fnSetCooperativeLevel(
198 LPDIRECTSOUND8 iface,
199 HWND hwnd,
200 DWORD dwLevel)
201 {
202 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
203
204 if (!This->bInitialized)
205 {
206 /* object not yet initialized */
207 return DSERR_UNINITIALIZED;
208 }
209
210 /* store cooperation level */
211 This->dwLevel = dwLevel;
212 return DS_OK;
213 }
214
215 HRESULT
216 WINAPI
217 IDirectSound8_fnCompact(
218 LPDIRECTSOUND8 iface)
219 {
220 UNIMPLEMENTED;
221 return DSERR_INVALIDPARAM;
222 }
223
224 HRESULT
225 WINAPI
226 IDirectSound8_fnGetSpeakerConfig(
227 LPDIRECTSOUND8 iface,
228 LPDWORD pdwSpeakerConfig)
229 {
230 UNIMPLEMENTED;
231 return DSERR_INVALIDPARAM;
232 }
233
234 HRESULT
235 WINAPI
236 IDirectSound8_fnSetSpeakerConfig(
237 LPDIRECTSOUND8 iface,
238 DWORD dwSpeakerConfig)
239 {
240 UNIMPLEMENTED;
241 return DSERR_INVALIDPARAM;
242 }
243
244
245 HRESULT
246 WINAPI
247 IDirectSound8_fnInitialize(
248 LPDIRECTSOUND8 iface,
249 LPCGUID pcGuidDevice)
250 {
251 GUID DeviceGuid;
252 LPOLESTR pGuidStr;
253 HRESULT hr;
254 LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
255
256 /* sanity check */
257 ASSERT(RootInfo);
258
259 if (This->bInitialized)
260 {
261 /* object has already been initialized */
262 return DSERR_ALREADYINITIALIZED;
263 }
264
265 /* fixme mutual exlucsion */
266
267 if (pcGuidDevice == NULL || IsEqualGUID(pcGuidDevice, &GUID_NULL))
268 {
269 /* use default playback device id */
270 pcGuidDevice = &DSDEVID_DefaultPlayback;
271 }
272
273 /* now verify the guid */
274 if (GetDeviceID(pcGuidDevice, &DeviceGuid) != DS_OK)
275 {
276 if (SUCCEEDED(StringFromIID(pcGuidDevice, &pGuidStr)))
277 {
278 DPRINT("IDirectSound8_fnInitialize: Unknown GUID %ws\n", pGuidStr);
279 CoTaskMemFree(pGuidStr);
280 }
281 return DSERR_INVALIDPARAM;
282 }
283
284 hr = FindDeviceByGuid(&DeviceGuid, &This->Filter);
285
286 if (SUCCEEDED(hr))
287 {
288 This->bInitialized = TRUE;
289 return DS_OK;
290 }
291
292 DPRINT("Failed to find device\n");
293 return DSERR_INVALIDPARAM;
294 }
295
296 HRESULT
297 WINAPI
298 IDirectSound8_fnVerifyCertification(
299 LPDIRECTSOUND8 iface,
300 LPDWORD pdwCertified)
301 {
302 UNIMPLEMENTED;
303 return DS_CERTIFIED;
304 }
305
306 static IDirectSound8Vtbl vt_DirectSound8 =
307 {
308 /* IUnknown methods */
309 IDirectSound8_fnQueryInterface,
310 IDirectSound8_fnAddRef,
311 IDirectSound8_fnRelease,
312 /* IDirectSound methods */
313 IDirectSound8_fnCreateSoundBuffer,
314 IDirectSound8_fnGetCaps,
315 IDirectSound8_fnDuplicateSoundBuffer,
316 IDirectSound8_fnSetCooperativeLevel,
317 IDirectSound8_fnCompact,
318 IDirectSound8_fnGetSpeakerConfig,
319 IDirectSound8_fnSetSpeakerConfig,
320 IDirectSound8_fnInitialize,
321 /* IDirectSound8 methods */
322 IDirectSound8_fnVerifyCertification
323 };
324
325 HRESULT
326 InternalDirectSoundCreate(
327 LPCGUID lpcGUID,
328 LPDIRECTSOUND8 *ppDS,
329 IUnknown *pUnkOuter)
330 {
331 LPCDirectSoundImpl This;
332 HRESULT hr;
333
334 if (!ppDS || pUnkOuter != NULL)
335 {
336 /* invalid parameter passed */
337 return DSERR_INVALIDPARAM;
338 }
339
340 /* allocate CDirectSoundImpl struct */
341 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundImpl));
342 if (!This)
343 {
344 /* not enough memory */
345 return DSERR_OUTOFMEMORY;
346 }
347
348 /* initialize IDirectSound object */
349 This->ref = 1;
350 This->lpVtbl = &vt_DirectSound8;
351
352
353 /* initialize direct sound interface */
354 hr = IDirectSound8_Initialize((LPDIRECTSOUND8)&This->lpVtbl, lpcGUID);
355
356 /* check for success */
357 if (!SUCCEEDED(hr))
358 {
359 /* failed */
360 DPRINT("Failed to initialize DirectSound object with %x\n", hr);
361 IDirectSound8_Release((LPDIRECTSOUND8)&This->lpVtbl);
362 return hr;
363 }
364
365 /* store result */
366 *ppDS = (LPDIRECTSOUND8)&This->lpVtbl;
367 DPRINT("DirectSound object %p\n", *ppDS);
368 return DS_OK;
369 }
370
371 HRESULT
372 WINAPI
373 DirectSoundCreate(
374 LPCGUID lpcGUID,
375 LPDIRECTSOUND *ppDS,
376 IUnknown *pUnkOuter)
377 {
378 return InternalDirectSoundCreate(lpcGUID, (LPDIRECTSOUND8*)ppDS, pUnkOuter);
379 }
380
381 HRESULT
382 WINAPI
383 DirectSoundCreate8(
384 LPCGUID lpcGUID,
385 LPDIRECTSOUND8 *ppDS,
386 IUnknown *pUnkOuter)
387 {
388 return InternalDirectSoundCreate(lpcGUID, ppDS, pUnkOuter);
389 }