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