[DSOUND_NEW]
[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 DWORD dwFlags;
21 DWORD dwFrequency;
22 LONG Volume;
23 LONG VolumePan;
24 LPWAVEFORMATEX Format;
25 PUCHAR Buffer;
26 DWORD BufferSize;
27 KSSTATE State;
28 DWORD Flags;
29 DWORD Position;
30 DWORD PlayPosition;
31
32 LPDIRECTSOUNDBUFFER8 PrimaryBuffer;
33
34
35 }CDirectSoundBuffer, *LPCDirectSoundBuffer;
36
37 HRESULT
38 WINAPI
39 SecondaryDirectSoundBuffer8Impl_fnQueryInterface(
40 LPDIRECTSOUNDBUFFER8 iface,
41 IN REFIID riid,
42 LPVOID* ppobj)
43 {
44 LPOLESTR pStr;
45 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
46
47 if (IsEqualIID(riid, &IID_IUnknown) ||
48 IsEqualIID(riid, &IID_IDirectSoundBuffer) ||
49 IsEqualIID(riid, &IID_IDirectSoundBuffer8))
50 {
51 *ppobj = (LPVOID)&This->lpVtbl;
52 InterlockedIncrement(&This->ref);
53 return S_OK;
54 }
55
56 if (SUCCEEDED(StringFromIID(riid, &pStr)))
57 {
58 DPRINT("No Interface for class %s\n", pStr);
59 CoTaskMemFree(pStr);
60 }
61 return E_NOINTERFACE;
62 }
63
64 ULONG
65 WINAPI
66 SecondaryDirectSoundBuffer8Impl_fnAddRef(
67 LPDIRECTSOUNDBUFFER8 iface)
68 {
69 ULONG ref;
70 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
71
72 ref = InterlockedIncrement(&This->ref);
73
74 return ref;
75
76 }
77
78 ULONG
79 WINAPI
80 SecondaryDirectSoundBuffer8Impl_fnRelease(
81 LPDIRECTSOUNDBUFFER8 iface)
82 {
83 ULONG ref;
84 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
85
86 ref = InterlockedDecrement(&(This->ref));
87
88 if (!ref)
89 {
90 HeapFree(GetProcessHeap(), 0, This->Buffer);
91 HeapFree(GetProcessHeap(), 0, This->Format);
92 HeapFree(GetProcessHeap(), 0, This);
93 }
94
95 return ref;
96 }
97
98 HRESULT
99 WINAPI
100 SecondaryDirectSoundBuffer8Impl_fnGetCaps(
101 LPDIRECTSOUNDBUFFER8 iface,
102 LPDSBCAPS pDSBufferCaps)
103 {
104 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
105
106 if (!pDSBufferCaps)
107 {
108 /* invalid parameter */
109 return DSERR_INVALIDPARAM;
110 }
111
112 if (pDSBufferCaps->dwSize < sizeof(DSBCAPS))
113 {
114 /* invalid buffer size */
115 return DSERR_INVALIDPARAM;
116 }
117
118 /* get buffer details */
119 pDSBufferCaps->dwUnlockTransferRate = 0;
120 pDSBufferCaps->dwPlayCpuOverhead = 0;
121 pDSBufferCaps->dwSize = This->BufferSize;
122 pDSBufferCaps->dwFlags = This->dwFlags;
123
124 return DS_OK;
125 }
126
127 HRESULT
128 WINAPI
129 SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition(
130 LPDIRECTSOUNDBUFFER8 iface,
131 LPDWORD pdwCurrentPlayCursor,
132 LPDWORD pdwCurrentWriteCursor)
133 {
134 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
135
136 //DPRINT("SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition This %p Play %p Write %p\n", This, pdwCurrentPlayCursor, pdwCurrentWriteCursor);
137
138 return PrimaryDirectSoundBuffer_GetPosition(This->PrimaryBuffer, pdwCurrentPlayCursor, pdwCurrentWriteCursor);
139 }
140
141 HRESULT
142 WINAPI
143 SecondaryDirectSoundBuffer8Impl_fnGetFormat(
144 LPDIRECTSOUNDBUFFER8 iface,
145 LPWAVEFORMATEX pwfxFormat,
146 DWORD dwSizeAllocated,
147 LPDWORD pdwSizeWritten)
148 {
149 DWORD FormatSize;
150 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
151
152 FormatSize = sizeof(WAVEFORMATEX) + This->Format->cbSize;
153
154 if (!pwfxFormat && !pdwSizeWritten)
155 {
156 /* invalid parameter */
157 return DSERR_INVALIDPARAM;
158 }
159
160 if (!pwfxFormat)
161 {
162 /* return required format size */
163 *pdwSizeWritten = FormatSize;
164 return DS_OK;
165 }
166 else
167 {
168 if (dwSizeAllocated >= FormatSize)
169 {
170 /* copy format */
171 CopyMemory(pwfxFormat, This->Format, FormatSize);
172
173 if (pdwSizeWritten)
174 *pdwSizeWritten = FormatSize;
175
176 return DS_OK;
177 }
178 /* buffer too small */
179 if (pdwSizeWritten)
180 *pdwSizeWritten = 0;
181
182 return DSERR_INVALIDPARAM;
183 }
184 }
185
186 HRESULT
187 WINAPI
188 SecondaryDirectSoundBuffer8Impl_fnGetVolume(
189 LPDIRECTSOUNDBUFFER8 iface,
190 LPLONG plVolume)
191 {
192 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
193
194 if (!plVolume)
195 {
196 /* invalid parameter */
197 return DSERR_INVALIDPARAM;
198 }
199
200 /* get volume */
201 *plVolume = This->Volume;
202
203 return DS_OK;
204 }
205
206 HRESULT
207 WINAPI
208 SecondaryDirectSoundBuffer8Impl_fnGetPan(
209 LPDIRECTSOUNDBUFFER8 iface,
210 LPLONG plPan)
211 {
212 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
213
214 if (!plPan)
215 {
216 /* invalid parameter */
217 return DSERR_INVALIDPARAM;
218 }
219
220 /* get frequency */
221 *plPan = This->VolumePan;
222
223 return DS_OK;
224 }
225
226 HRESULT
227 WINAPI
228 SecondaryDirectSoundBuffer8Impl_fnGetFrequency(
229 LPDIRECTSOUNDBUFFER8 iface,
230 LPDWORD pdwFrequency)
231 {
232 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
233
234 if (!pdwFrequency)
235 {
236 /* invalid parameter */
237 return DSERR_INVALIDPARAM;
238 }
239
240 /* get frequency */
241 *pdwFrequency = This->dwFrequency;
242
243 return DS_OK;
244 }
245
246 HRESULT
247 WINAPI
248 SecondaryDirectSoundBuffer8Impl_fnGetStatus(
249 LPDIRECTSOUNDBUFFER8 iface,
250 LPDWORD pdwStatus)
251 {
252 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
253
254 if (!pdwStatus)
255 {
256 /* invalid parameter */
257 return DSERR_INVALIDPARAM;
258 }
259
260 *pdwStatus = 0;
261 if (This->State == KSSTATE_RUN || This->State == KSSTATE_ACQUIRE)
262 {
263 /* buffer is playing */
264 *pdwStatus |= DSBSTATUS_PLAYING;
265 if (This->Flags & DSBPLAY_LOOPING)
266 *pdwStatus |= DSBSTATUS_LOOPING;
267 }
268
269 return DS_OK;
270 }
271
272 HRESULT
273 WINAPI
274 SecondaryDirectSoundBuffer8Impl_fnInitialize(
275 LPDIRECTSOUNDBUFFER8 iface,
276 LPDIRECTSOUND pDirectSound,
277 LPCDSBUFFERDESC pcDSBufferDesc)
278 {
279 /* RTFM */
280 return DSERR_ALREADYINITIALIZED;
281 }
282
283 HRESULT
284 WINAPI
285 SecondaryDirectSoundBuffer8Impl_fnLock(
286 LPDIRECTSOUNDBUFFER8 iface,
287 DWORD dwOffset,
288 DWORD dwBytes,
289 LPVOID *ppvAudioPtr1,
290 LPDWORD pdwAudioBytes1,
291 LPVOID *ppvAudioPtr2,
292 LPDWORD pdwAudioBytes2,
293 DWORD dwFlags)
294 {
295 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
296
297 DPRINT("This %p dwOffset %u dwBytes %u ppvAudioPtr1 %p pdwAudioBytes1 %p ppvAudioPtr2 %p pdwAudioBytes2 %p dwFlags %x This->BufferSize %u\n",
298 This, dwOffset, dwBytes, ppvAudioPtr1, pdwAudioBytes1, ppvAudioPtr2, pdwAudioBytes2, dwFlags, This->BufferSize);
299
300 if (dwFlags == DSBLOCK_ENTIREBUFFER)
301 {
302 *ppvAudioPtr1 = (LPVOID)This->Buffer;
303 *pdwAudioBytes1 = This->BufferSize;
304 if (ppvAudioPtr2)
305 *ppvAudioPtr2 = NULL;
306 if (pdwAudioBytes2)
307 *pdwAudioBytes2 = 0;
308
309 return DS_OK;
310 }
311 else if (dwFlags == DSBLOCK_FROMWRITECURSOR)
312 {
313 UNIMPLEMENTED
314 return DSERR_UNSUPPORTED;
315 }
316 else
317 {
318 ASSERT(dwOffset < This->BufferSize);
319 ASSERT(dwBytes <= This->BufferSize);
320
321 dwBytes = min(This->BufferSize - dwOffset, dwBytes);
322
323 *ppvAudioPtr1 = This->Buffer + dwOffset;
324 *pdwAudioBytes1 = dwBytes;
325 if (ppvAudioPtr2)
326 *ppvAudioPtr2 = NULL;
327 if (pdwAudioBytes2)
328 *pdwAudioBytes2 = 0;
329
330 return DS_OK;
331 }
332 }
333
334 HRESULT
335 WINAPI
336 SecondaryDirectSoundBuffer8Impl_fnPlay(
337 LPDIRECTSOUNDBUFFER8 iface,
338 DWORD dwReserved1,
339 DWORD dwPriority,
340 DWORD dwFlags)
341 {
342 HRESULT hResult;
343 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
344
345 if (dwReserved1 != 0)
346 {
347 /* must be zero */
348 return DSERR_INVALIDPARAM;
349 }
350
351 /* sanity check */
352 ASSERT(dwFlags & DSBPLAY_LOOPING);
353
354 /* set dataformat */
355 hResult = PrimaryDirectSoundBuffer_SetFormat(This->PrimaryBuffer, This->Format, TRUE);
356
357 if (!SUCCEEDED(hResult))
358 {
359 /* failed */
360 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);
361 return hResult;
362 }
363
364 /* start primary buffer */
365 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_RUN);
366 /* acquire primary buffer */
367 PrimaryDirectSoundBuffer_AcquireLock(This->PrimaryBuffer);
368 /* HACK write buffer */
369 PrimaryDirectSoundBuffer_Write(This->PrimaryBuffer, This->Buffer, This->BufferSize);
370 /* release primary buffer */
371 PrimaryDirectSoundBuffer_ReleaseLock(This->PrimaryBuffer);
372
373 DPRINT("SetFormatSuccess PrimaryBuffer %p\n", This->PrimaryBuffer);
374 return DS_OK;
375 }
376
377 HRESULT
378 WINAPI
379 SecondaryDirectSoundBuffer8Impl_fnSetCurrentPosition(
380 LPDIRECTSOUNDBUFFER8 iface,
381 DWORD dwNewPosition)
382 {
383 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
384
385 DPRINT("Setting position %u\n", dwNewPosition);
386 This->Position = dwNewPosition;
387
388 return DS_OK;
389 }
390
391 HRESULT
392 WINAPI
393 SecondaryDirectSoundBuffer8Impl_fnSetFormat(
394 LPDIRECTSOUNDBUFFER8 iface,
395 LPCWAVEFORMATEX pcfxFormat)
396 {
397 /* RTFM */
398 return DSERR_INVALIDCALL;
399 }
400
401 HRESULT
402 WINAPI
403 SecondaryDirectSoundBuffer8Impl_fnSetVolume(
404 LPDIRECTSOUNDBUFFER8 iface,
405 LONG lVolume)
406 {
407 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
408
409 if (lVolume < DSBVOLUME_MIN || lVolume > DSBVOLUME_MAX)
410 {
411 /* invalid parameter */
412 return DSERR_INVALIDPARAM;
413 }
414
415
416 /* Store volume */
417 This->Volume = lVolume;
418
419 return DS_OK;
420 }
421
422 HRESULT
423 WINAPI
424 SecondaryDirectSoundBuffer8Impl_fnSetPan(
425 LPDIRECTSOUNDBUFFER8 iface,
426 LONG lPan)
427 {
428 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
429
430 if (lPan < DSBPAN_LEFT || lPan > DSBPAN_RIGHT)
431 {
432 /* invalid parameter */
433 return DSERR_INVALIDPARAM;
434 }
435
436 /* Store volume pan */
437 This->VolumePan = lPan;
438
439 return DS_OK;
440 }
441
442 HRESULT
443 WINAPI
444 SecondaryDirectSoundBuffer8Impl_fnSetFrequency(
445 LPDIRECTSOUNDBUFFER8 iface,
446 DWORD dwFrequency)
447 {
448 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
449
450 if (dwFrequency == DSBFREQUENCY_ORIGINAL)
451 {
452 /* restore original frequency */
453 dwFrequency = This->Format->nSamplesPerSec;
454 }
455
456 if (dwFrequency < DSBFREQUENCY_MIN || dwFrequency > DSBFREQUENCY_MAX)
457 {
458 /* invalid frequency */
459 return DSERR_INVALIDPARAM;
460 }
461
462 if (dwFrequency != This->dwFrequency)
463 {
464 /* FIXME handle frequency change */
465 }
466
467 /* store frequency */
468 This->dwFrequency = dwFrequency;
469
470 return DS_OK;
471 }
472
473 HRESULT
474 WINAPI
475 SecondaryDirectSoundBuffer8Impl_fnStop(
476 LPDIRECTSOUNDBUFFER8 iface)
477 {
478 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
479
480 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_PAUSE);
481 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_ACQUIRE);
482 PrimaryDirectSoundBuffer_SetState(This->PrimaryBuffer, KSSTATE_STOP);
483
484 return DS_OK;
485 }
486
487
488 HRESULT
489 WINAPI
490 SecondaryDirectSoundBuffer8Impl_fnUnlock(
491 LPDIRECTSOUNDBUFFER8 iface,
492 LPVOID pvAudioPtr1,
493 DWORD dwAudioBytes1,
494 LPVOID pvAudioPtr2,
495 DWORD dwAudioBytes2)
496 {
497 //DPRINT("SecondaryDirectSoundBuffer8Impl_fnUnlock pvAudioPtr1 %p dwAudioBytes1 %u pvAudioPtr2 %p dwAudioBytes2 %u Unimplemented\n");
498 return DS_OK;
499 }
500
501
502
503
504 HRESULT
505 WINAPI
506 SecondaryDirectSoundBuffer8Impl_fnRestore(
507 LPDIRECTSOUNDBUFFER8 iface)
508 {
509 UNIMPLEMENTED
510 return DSERR_INVALIDPARAM;
511 }
512
513
514 HRESULT
515 WINAPI
516 SecondaryDirectSoundBuffer8Impl_fnSetFX(
517 LPDIRECTSOUNDBUFFER8 iface,
518 DWORD dwEffectsCount,
519 LPDSEFFECTDESC pDSFXDesc,
520 LPDWORD pdwResultCodes)
521 {
522 UNIMPLEMENTED
523 return DSERR_INVALIDPARAM;
524 }
525
526 HRESULT
527 WINAPI
528 SecondaryDirectSoundBuffer8Impl_fnAcquireResources(
529 LPDIRECTSOUNDBUFFER8 iface,
530 DWORD dwFlags,
531 DWORD dwEffectsCount,
532 LPDWORD pdwResultCodes)
533 {
534 UNIMPLEMENTED
535 return DSERR_INVALIDPARAM;
536 }
537
538 HRESULT
539 WINAPI
540 SecondaryDirectSoundBuffer8Impl_fnGetObjectInPath(
541 LPDIRECTSOUNDBUFFER8 iface,
542 REFGUID rguidObject,
543 DWORD dwIndex,
544 REFGUID rguidInterface,
545 LPVOID *ppObject)
546 {
547 UNIMPLEMENTED
548 return DSERR_INVALIDPARAM;
549 }
550
551 static IDirectSoundBuffer8Vtbl vt_DirectSoundBuffer8 =
552 {
553 /* IUnknown methods */
554 SecondaryDirectSoundBuffer8Impl_fnQueryInterface,
555 SecondaryDirectSoundBuffer8Impl_fnAddRef,
556 SecondaryDirectSoundBuffer8Impl_fnRelease,
557 /* IDirectSoundBuffer methods */
558 SecondaryDirectSoundBuffer8Impl_fnGetCaps,
559 SecondaryDirectSoundBuffer8Impl_fnGetCurrentPosition,
560 SecondaryDirectSoundBuffer8Impl_fnGetFormat,
561 SecondaryDirectSoundBuffer8Impl_fnGetVolume,
562 SecondaryDirectSoundBuffer8Impl_fnGetPan,
563 SecondaryDirectSoundBuffer8Impl_fnGetFrequency,
564 SecondaryDirectSoundBuffer8Impl_fnGetStatus,
565 SecondaryDirectSoundBuffer8Impl_fnInitialize,
566 SecondaryDirectSoundBuffer8Impl_fnLock,
567 SecondaryDirectSoundBuffer8Impl_fnPlay,
568 SecondaryDirectSoundBuffer8Impl_fnSetCurrentPosition,
569 SecondaryDirectSoundBuffer8Impl_fnSetFormat,
570 SecondaryDirectSoundBuffer8Impl_fnSetVolume,
571 SecondaryDirectSoundBuffer8Impl_fnSetPan,
572 SecondaryDirectSoundBuffer8Impl_fnSetFrequency,
573 SecondaryDirectSoundBuffer8Impl_fnStop,
574 SecondaryDirectSoundBuffer8Impl_fnUnlock,
575 SecondaryDirectSoundBuffer8Impl_fnRestore,
576 /* IDirectSoundBuffer8 methods */
577 SecondaryDirectSoundBuffer8Impl_fnSetFX,
578 SecondaryDirectSoundBuffer8Impl_fnAcquireResources,
579 SecondaryDirectSoundBuffer8Impl_fnGetObjectInPath
580 };
581
582 HRESULT
583 NewSecondarySoundBuffer(
584 LPDIRECTSOUNDBUFFER8 *OutBuffer,
585 LPFILTERINFO Filter,
586 DWORD dwLevel,
587 LPCDSBUFFERDESC lpcDSBufferDesc,
588 LPDIRECTSOUNDBUFFER8 PrimaryBuffer)
589 {
590 ULONG FormatSize;
591 LPCDirectSoundBuffer This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundBuffer));
592
593 if (!This)
594 {
595 /* not enough memory */
596 return DSERR_OUTOFMEMORY;
597 }
598
599 FormatSize = sizeof(WAVEFORMATEX) + lpcDSBufferDesc->lpwfxFormat->cbSize;
600
601 This->Format = HeapAlloc(GetProcessHeap(), 0, FormatSize);
602 if (!This->Format)
603 {
604 /* not enough memory */
605 HeapFree(GetProcessHeap(), 0, This);
606 return DSERR_OUTOFMEMORY;
607 }
608
609 /* sanity check */
610 ASSERT(lpcDSBufferDesc->dwBufferBytes);
611
612 /* allocate sound buffer */
613 This->Buffer = HeapAlloc(GetProcessHeap(), 0, lpcDSBufferDesc->dwBufferBytes);
614 if (!This->Buffer)
615 {
616 /* not enough memory */
617 HeapFree(GetProcessHeap(), 0, This->Format);
618 HeapFree(GetProcessHeap(), 0, This);
619 return DSERR_OUTOFMEMORY;
620 }
621
622
623 This->ref = 1;
624 This->lpVtbl = &vt_DirectSoundBuffer8;
625 This->Filter = Filter;
626 This->dwLevel = dwLevel;
627 This->dwFlags = lpcDSBufferDesc->dwFlags;
628 This->dwFrequency = lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec;
629 This->State = KSSTATE_STOP;
630 This->Volume = DSBVOLUME_MAX;
631 This->VolumePan = DSBPAN_CENTER;
632 This->Flags = 0;
633 This->Position = 0;
634 This->BufferSize = lpcDSBufferDesc->dwBufferBytes;
635 This->PrimaryBuffer = PrimaryBuffer;
636
637 CopyMemory(This->Format, lpcDSBufferDesc->lpwfxFormat, FormatSize);
638
639 *OutBuffer = (LPDIRECTSOUNDBUFFER8)&This->lpVtbl;
640 return DS_OK;
641 }
642