[DSOUND]
[reactos.git] / reactos / dll / directx / dsound_new / secondary.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/secondary.c
5 * PURPOSE: Secondary IDirectSoundBuffer8 implementation
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10
11 #include "precomp.h"
12
13 typedef struct
14 {
15 const IDirectSoundBuffer8Vtbl *lpVtbl;
16 LONG ref;
17
18 LPFILTERINFO Filter;
19 DWORD dwLevel;
20 LPWAVEFORMATEX Format;
21 PUCHAR Buffer;
22 DWORD BufferSize;
23 KSSTATE State;
24 DWORD Flags;
25 DWORD Position;
26 DWORD PlayPosition;
27
28 LPDIRECTSOUNDBUFFER8 PrimaryBuffer;
29
30
31 }CDirectSoundBuffer, *LPCDirectSoundBuffer;
32
33 HRESULT
34 WINAPI
35 SecondaryDirectSoundBuffer8Impl_fnQueryInterface(
36 LPDIRECTSOUNDBUFFER8 iface,
37 IN REFIID riid,
38 LPVOID* ppobj)
39 {
40 LPOLESTR pStr;
41 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
42
43 if (IsEqualIID(riid, &IID_IUnknown) ||
44 IsEqualIID(riid, &IID_IDirectSoundBuffer) ||
45 IsEqualIID(riid, &IID_IDirectSoundBuffer8))
46 {
47 *ppobj = (LPVOID)&This->lpVtbl;
48 InterlockedIncrement(&This->ref);
49 return S_OK;
50 }
51
52 if (SUCCEEDED(StringFromIID(riid, &pStr)))
53 {
54 DPRINT("No Interface for class %s\n", pStr);
55 CoTaskMemFree(pStr);
56 }
57 return E_NOINTERFACE;
58 }
59
60 ULONG
61 WINAPI
62 SecondaryDirectSoundBuffer8Impl_fnAddRef(
63 LPDIRECTSOUNDBUFFER8 iface)
64 {
65 ULONG ref;
66 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
67
68 ref = InterlockedIncrement(&This->ref);
69
70 return ref;
71
72 }
73
74 ULONG
75 WINAPI
76 SecondaryDirectSoundBuffer8Impl_fnRelease(
77 LPDIRECTSOUNDBUFFER8 iface)
78 {
79 ULONG ref;
80 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
81
82 ref = InterlockedDecrement(&(This->ref));
83
84 if (!ref)
85 {
86 HeapFree(GetProcessHeap(), 0, This->Buffer);
87 HeapFree(GetProcessHeap(), 0, This->Format);
88 HeapFree(GetProcessHeap(), 0, This);
89 }
90
91 return ref;
92 }
93
94 HRESULT
95 WINAPI
96 SecondaryDirectSoundBuffer8Impl_fnGetCaps(
97 LPDIRECTSOUNDBUFFER8 iface,
98 LPDSBCAPS pDSBufferCaps)
99 {
100 UNIMPLEMENTED
101 return DSERR_INVALIDPARAM;
102 }
103
104 HRESULT
105 WINAPI
106 SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition(
107 LPDIRECTSOUNDBUFFER8 iface,
108 LPDWORD pdwCurrentPlayCursor,
109 LPDWORD pdwCurrentWriteCursor)
110 {
111 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
112
113 //DPRINT("SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition This %p Play %p Write %p\n", This, pdwCurrentPlayCursor, pdwCurrentWriteCursor);
114
115 return PrimaryDirectSoundBuffer_GetPosition(This->PrimaryBuffer, pdwCurrentPlayCursor, pdwCurrentWriteCursor);
116 }
117
118 HRESULT
119 WINAPI
120 SecondaryDirectSoundBuffer8Impl_fnGetFormat(
121 LPDIRECTSOUNDBUFFER8 iface,
122 LPWAVEFORMATEX pwfxFormat,
123 DWORD dwSizeAllocated,
124 LPDWORD pdwSizeWritten)
125 {
126 DWORD FormatSize;
127 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
128
129 FormatSize = sizeof(WAVEFORMATEX) + This->Format->cbSize;
130
131 if (!pwfxFormat && !pdwSizeWritten)
132 {
133 /* invalid parameter */
134 return DSERR_INVALIDPARAM;
135 }
136
137 if (!pwfxFormat)
138 {
139 /* return required format size */
140 *pdwSizeWritten = FormatSize;
141 return DS_OK;
142 }
143 else
144 {
145 if (dwSizeAllocated >= FormatSize)
146 {
147 /* copy format */
148 CopyMemory(pwfxFormat, This->Format, FormatSize);
149
150 if (pdwSizeWritten)
151 *pdwSizeWritten = FormatSize;
152
153 return DS_OK;
154 }
155 /* buffer too small */
156 if (pdwSizeWritten)
157 *pdwSizeWritten = 0;
158
159 return DSERR_INVALIDPARAM;
160 }
161 }
162
163 HRESULT
164 WINAPI
165 SecondaryDirectSoundBuffer8Impl_fnGetVolume(
166 LPDIRECTSOUNDBUFFER8 iface,
167 LPLONG plVolume)
168 {
169 UNIMPLEMENTED
170 return DSERR_INVALIDPARAM;
171 }
172
173 HRESULT
174 WINAPI
175 SecondaryDirectSoundBuffer8Impl_fnGetPan(
176 LPDIRECTSOUNDBUFFER8 iface,
177 LPLONG plPan)
178 {
179 UNIMPLEMENTED
180 return DSERR_INVALIDPARAM;
181 }
182
183 HRESULT
184 WINAPI
185 SecondaryDirectSoundBuffer8Impl_fnGetFrequency(
186 LPDIRECTSOUNDBUFFER8 iface,
187 LPDWORD pdwFrequency)
188 {
189 UNIMPLEMENTED
190 return DSERR_INVALIDPARAM;
191 }
192
193 HRESULT
194 WINAPI
195 SecondaryDirectSoundBuffer8Impl_fnGetStatus(
196 LPDIRECTSOUNDBUFFER8 iface,
197 LPDWORD pdwStatus)
198 {
199 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
200
201 if (!pdwStatus)
202 {
203 /* invalid parameter */
204 return DSERR_INVALIDPARAM;
205 }
206
207 *pdwStatus = 0;
208 if (This->State == KSSTATE_RUN || This->State == KSSTATE_ACQUIRE)
209 {
210 /* buffer is playing */
211 *pdwStatus |= DSBSTATUS_PLAYING;
212 if (This->Flags & DSBPLAY_LOOPING)
213 *pdwStatus |= DSBSTATUS_LOOPING;
214 }
215
216 return DS_OK;
217 }
218
219 HRESULT
220 WINAPI
221 SecondaryDirectSoundBuffer8Impl_fnInitialize(
222 LPDIRECTSOUNDBUFFER8 iface,
223 LPDIRECTSOUND pDirectSound,
224 LPCDSBUFFERDESC pcDSBufferDesc)
225 {
226 UNIMPLEMENTED
227 return DSERR_INVALIDPARAM;
228 }
229
230 HRESULT
231 WINAPI
232 SecondaryDirectSoundBuffer8Impl_fnLock(
233 LPDIRECTSOUNDBUFFER8 iface,
234 DWORD dwOffset,
235 DWORD dwBytes,
236 LPVOID *ppvAudioPtr1,
237 LPDWORD pdwAudioBytes1,
238 LPVOID *ppvAudioPtr2,
239 LPDWORD pdwAudioBytes2,
240 DWORD dwFlags)
241 {
242 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
243
244 DPRINT("This %p dwOffset %u dwBytes %u ppvAudioPtr1 %p pdwAudioBytes1 %p ppvAudioPtr2 %p pdwAudioBytes2 %p dwFlags %x This->BufferSize %u\n",
245 This, dwOffset, dwBytes, ppvAudioPtr1, pdwAudioBytes1, ppvAudioPtr2, pdwAudioBytes2, dwFlags, This->BufferSize);
246
247 if (dwFlags == DSBLOCK_ENTIREBUFFER)
248 {
249 *ppvAudioPtr1 = (LPVOID)This->Buffer;
250 *pdwAudioBytes1 = This->BufferSize;
251 if (ppvAudioPtr2)
252 *ppvAudioPtr2 = NULL;
253 if (pdwAudioBytes2)
254 *pdwAudioBytes2 = 0;
255
256 return DS_OK;
257 }
258 else if (dwFlags == DSBLOCK_FROMWRITECURSOR)
259 {
260 UNIMPLEMENTED
261 return DSERR_UNSUPPORTED;
262 }
263 else
264 {
265 ASSERT(dwOffset < This->BufferSize);
266 ASSERT(dwBytes <= This->BufferSize);
267
268 dwBytes = min(This->BufferSize - dwOffset, dwBytes);
269
270 *ppvAudioPtr1 = This->Buffer + dwOffset;
271 *pdwAudioBytes1 = dwBytes;
272 if (ppvAudioPtr2)
273 *ppvAudioPtr2 = NULL;
274 if (pdwAudioBytes2)
275 *pdwAudioBytes2 = 0;
276
277 return DS_OK;
278 }
279 }
280
281 HRESULT
282 WINAPI
283 SecondaryDirectSoundBuffer8Impl_fnPlay(
284 LPDIRECTSOUNDBUFFER8 iface,
285 DWORD dwReserved1,
286 DWORD dwPriority,
287 DWORD dwFlags)
288 {
289 HRESULT hResult;
290 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
291
292 if (dwReserved1 != 0)
293 {
294 /* must be zero */
295 return DSERR_INVALIDPARAM;
296 }
297
298 /* sanity check */
299 ASSERT(dwFlags & DSBPLAY_LOOPING);
300
301 /* set dataformat */
302 hResult = PrimaryDirectSoundBuffer_SetFormat(This->PrimaryBuffer, This->Format, TRUE);
303
304 if (!SUCCEEDED(hResult))
305 {
306 /* failed */
307 DPRINT1("Failed to set format Tag %u Samples %u Bytes %u nChannels %u\n", This->Format->wFormatTag, This->Format->nSamplesPerSec, This->Format->wBitsPerSample, This->Format->nChannels);
308 return hResult;
309 }
310
311 /* start primary buffer */
312 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_RUN);
313 /* acquire primary buffer */
314 PrimaryDirectSoundBuffer_AcquireLock(This->PrimaryBuffer);
315 /* HACK write buffer */
316 PrimaryDirectSoundBuffer_Write(This->PrimaryBuffer, This->Buffer, This->BufferSize);
317 /* release primary buffer */
318 PrimaryDirectSoundBuffer_ReleaseLock(This->PrimaryBuffer);
319
320 DPRINT("SetFormatSuccess PrimaryBuffer %p\n", This->PrimaryBuffer);
321 return DS_OK;
322 }
323
324 HRESULT
325 WINAPI
326 SecondaryDirectSoundBuffer8Impl_fnSetCurrentPosition(
327 LPDIRECTSOUNDBUFFER8 iface,
328 DWORD dwNewPosition)
329 {
330 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
331
332 DPRINT("Setting position %u\n", dwNewPosition);
333 This->Position = dwNewPosition;
334
335 return DS_OK;
336 }
337
338 HRESULT
339 WINAPI
340 SecondaryDirectSoundBuffer8Impl_fnSetFormat(
341 LPDIRECTSOUNDBUFFER8 iface,
342 LPCWAVEFORMATEX pcfxFormat)
343 {
344 return DSERR_INVALIDCALL;
345 }
346
347 HRESULT
348 WINAPI
349 SecondaryDirectSoundBuffer8Impl_fnSetVolume(
350 LPDIRECTSOUNDBUFFER8 iface,
351 LONG lVolume)
352 {
353 UNIMPLEMENTED
354 return DSERR_INVALIDPARAM;
355 }
356
357 HRESULT
358 WINAPI
359 SecondaryDirectSoundBuffer8Impl_fnSetPan(
360 LPDIRECTSOUNDBUFFER8 iface,
361 LONG lPan)
362 {
363 UNIMPLEMENTED
364 return DSERR_INVALIDPARAM;
365 }
366
367 HRESULT
368 WINAPI
369 SecondaryDirectSoundBuffer8Impl_fnSetFrequency(
370 LPDIRECTSOUNDBUFFER8 iface,
371 DWORD dwFrequency)
372 {
373 UNIMPLEMENTED
374 return DSERR_INVALIDPARAM;
375 }
376
377 HRESULT
378 WINAPI
379 SecondaryDirectSoundBuffer8Impl_fnStop(
380 LPDIRECTSOUNDBUFFER8 iface)
381 {
382 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
383
384 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_PAUSE);
385 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_ACQUIRE);
386 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_STOP);
387
388 return DS_OK;
389 }
390
391
392 HRESULT
393 WINAPI
394 SecondaryDirectSoundBuffer8Impl_fnUnlock(
395 LPDIRECTSOUNDBUFFER8 iface,
396 LPVOID pvAudioPtr1,
397 DWORD dwAudioBytes1,
398 LPVOID pvAudioPtr2,
399 DWORD dwAudioBytes2)
400 {
401 //DPRINT("SecondaryDirectSoundBuffer8Impl_fnUnlock pvAudioPtr1 %p dwAudioBytes1 %u pvAudioPtr2 %p dwAudioBytes2 %u Unimplemented\n");
402 return DS_OK;
403 }
404
405
406
407
408 HRESULT
409 WINAPI
410 SecondaryDirectSoundBuffer8Impl_fnRestore(
411 LPDIRECTSOUNDBUFFER8 iface)
412 {
413 UNIMPLEMENTED
414 return DSERR_INVALIDPARAM;
415 }
416
417
418 HRESULT
419 WINAPI
420 SecondaryDirectSoundBuffer8Impl_fnSetFX(
421 LPDIRECTSOUNDBUFFER8 iface,
422 DWORD dwEffectsCount,
423 LPDSEFFECTDESC pDSFXDesc,
424 LPDWORD pdwResultCodes)
425 {
426 UNIMPLEMENTED
427 return DSERR_INVALIDPARAM;
428 }
429
430 HRESULT
431 WINAPI
432 SecondaryDirectSoundBuffer8Impl_fnAcquireResources(
433 LPDIRECTSOUNDBUFFER8 iface,
434 DWORD dwFlags,
435 DWORD dwEffectsCount,
436 LPDWORD pdwResultCodes)
437 {
438 UNIMPLEMENTED
439 return DSERR_INVALIDPARAM;
440 }
441
442 HRESULT
443 WINAPI
444 SecondaryDirectSoundBuffer8Impl_fnGetObjectInPath(
445 LPDIRECTSOUNDBUFFER8 iface,
446 REFGUID rguidObject,
447 DWORD dwIndex,
448 REFGUID rguidInterface,
449 LPVOID *ppObject)
450 {
451 UNIMPLEMENTED
452 return DSERR_INVALIDPARAM;
453 }
454
455 static IDirectSoundBuffer8Vtbl vt_DirectSoundBuffer8 =
456 {
457 /* IUnknown methods */
458 SecondaryDirectSoundBuffer8Impl_fnQueryInterface,
459 SecondaryDirectSoundBuffer8Impl_fnAddRef,
460 SecondaryDirectSoundBuffer8Impl_fnRelease,
461 /* IDirectSoundBuffer methods */
462 SecondaryDirectSoundBuffer8Impl_fnGetCaps,
463 SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition,
464 SecondaryDirectSoundBuffer8Impl_fnGetFormat,
465 SecondaryDirectSoundBuffer8Impl_fnGetVolume,
466 SecondaryDirectSoundBuffer8Impl_fnGetPan,
467 SecondaryDirectSoundBuffer8Impl_fnGetFrequency,
468 SecondaryDirectSoundBuffer8Impl_fnGetStatus,
469 SecondaryDirectSoundBuffer8Impl_fnInitialize,
470 SecondaryDirectSoundBuffer8Impl_fnLock,
471 SecondaryDirectSoundBuffer8Impl_fnPlay,
472 SecondaryDirectSoundBuffer8Impl_fnSetCurrentPosition,
473 SecondaryDirectSoundBuffer8Impl_fnSetFormat,
474 SecondaryDirectSoundBuffer8Impl_fnSetVolume,
475 SecondaryDirectSoundBuffer8Impl_fnSetPan,
476 SecondaryDirectSoundBuffer8Impl_fnSetFrequency,
477 SecondaryDirectSoundBuffer8Impl_fnStop,
478 SecondaryDirectSoundBuffer8Impl_fnUnlock,
479 SecondaryDirectSoundBuffer8Impl_fnRestore,
480 /* IDirectSoundBuffer8 methods */
481 SecondaryDirectSoundBuffer8Impl_fnSetFX,
482 SecondaryDirectSoundBuffer8Impl_fnAcquireResources,
483 SecondaryDirectSoundBuffer8Impl_fnGetObjectInPath
484 };
485
486 HRESULT
487 NewSecondarySoundBuffer(
488 LPDIRECTSOUNDBUFFER8 *OutBuffer,
489 LPFILTERINFO Filter,
490 DWORD dwLevel,
491 LPCDSBUFFERDESC lpcDSBufferDesc,
492 LPDIRECTSOUNDBUFFER8 PrimaryBuffer)
493 {
494 ULONG FormatSize;
495 LPCDirectSoundBuffer This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundBuffer));
496
497 if (!This)
498 {
499 /* not enough memory */
500 return DSERR_OUTOFMEMORY;
501 }
502
503 FormatSize = sizeof(WAVEFORMATEX) + lpcDSBufferDesc->lpwfxFormat->cbSize;
504
505 This->Format = HeapAlloc(GetProcessHeap(), 0, FormatSize);
506 if (!This->Format)
507 {
508 /* not enough memory */
509 HeapFree(GetProcessHeap(), 0, This);
510 return DSERR_OUTOFMEMORY;
511 }
512
513 /* sanity check */
514 ASSERT(lpcDSBufferDesc->dwBufferBytes);
515
516 /* allocate sound buffer */
517 This->Buffer = HeapAlloc(GetProcessHeap(), 0, lpcDSBufferDesc->dwBufferBytes);
518 if (!This->Buffer)
519 {
520 /* not enough memory */
521 HeapFree(GetProcessHeap(), 0, This->Format);
522 HeapFree(GetProcessHeap(), 0, This);
523 return DSERR_OUTOFMEMORY;
524 }
525
526
527 This->ref = 1;
528 This->lpVtbl = &vt_DirectSoundBuffer8;
529 This->Filter = Filter;
530 This->dwLevel = dwLevel;
531 This->State = KSSTATE_STOP;
532 This->Flags = 0;
533 This->Position = 0;
534 This->BufferSize = lpcDSBufferDesc->dwBufferBytes;
535 This->PrimaryBuffer = PrimaryBuffer;
536
537 CopyMemory(This->Format, lpcDSBufferDesc->lpwfxFormat, FormatSize);
538
539 *OutBuffer = (LPDIRECTSOUNDBUFFER8)&This->lpVtbl;
540 return DS_OK;
541 }
542