xref: /reactos/dll/directx/dsound_new/primary.c (revision 9393fc32)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Configuration of network devices
4  * FILE:            dll/directx/dsound_new/primary.c
5  * PURPOSE:         Primary IDirectSoundBuffer8 implementation
6  *
7  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@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     WAVEFORMATEX Format;
25     HANDLE hPin;
26     CRITICAL_SECTION Lock;
27     KSSTATE State;
28 }CDirectSoundBuffer, *LPCDirectSoundBuffer;
29 
30 HRESULT
31 WINAPI
PrimaryDirectSoundBuffer8Impl_fnQueryInterface(LPDIRECTSOUNDBUFFER8 iface,IN REFIID riid,LPVOID * ppobj)32 PrimaryDirectSoundBuffer8Impl_fnQueryInterface(
33     LPDIRECTSOUNDBUFFER8 iface,
34     IN REFIID riid,
35     LPVOID* ppobj)
36 {
37     LPOLESTR pStr;
38     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
39 
40     if (IsEqualIID(riid, &IID_IUnknown) ||
41         IsEqualIID(riid, &IID_IDirectSoundBuffer) ||
42         IsEqualIID(riid, &IID_IDirectSoundBuffer8))
43     {
44         *ppobj = (LPVOID)&This->lpVtbl;
45         InterlockedIncrement(&This->ref);
46         return S_OK;
47     }
48 
49     if (SUCCEEDED(StringFromIID(riid, &pStr)))
50     {
51         DPRINT("No Interface for class %s\n", pStr);
52         CoTaskMemFree(pStr);
53     }
54     return E_NOINTERFACE;
55 }
56 
57 ULONG
58 WINAPI
PrimaryDirectSoundBuffer8Impl_fnAddRef(LPDIRECTSOUNDBUFFER8 iface)59 PrimaryDirectSoundBuffer8Impl_fnAddRef(
60     LPDIRECTSOUNDBUFFER8 iface)
61 {
62     ULONG ref;
63     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
64 
65     ref = InterlockedIncrement(&This->ref);
66 
67     return ref;
68 
69 }
70 
71 ULONG
72 WINAPI
PrimaryDirectSoundBuffer8Impl_fnRelease(LPDIRECTSOUNDBUFFER8 iface)73 PrimaryDirectSoundBuffer8Impl_fnRelease(
74     LPDIRECTSOUNDBUFFER8 iface)
75 {
76     ULONG ref;
77     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
78 
79     ref = InterlockedDecrement(&(This->ref));
80 
81     if (!ref)
82     {
83         if (This->hPin)
84         {
85             /* close pin handle */
86             CloseHandle(This->hPin);
87         }
88         /* free primary buffer */
89         HeapFree(GetProcessHeap(), 0, This);
90     }
91 
92     return ref;
93 }
94 
95 HRESULT
96 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetCaps(LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS pDSBufferCaps)97 PrimaryDirectSoundBuffer8Impl_fnGetCaps(
98     LPDIRECTSOUNDBUFFER8 iface,
99     LPDSBCAPS pDSBufferCaps)
100 {
101     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
102 
103     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetCaps\n");
104 
105     if (!pDSBufferCaps)
106     {
107         /* invalid parameter */
108         return DSERR_INVALIDPARAM;
109     }
110 
111     if (pDSBufferCaps->dwSize < sizeof(DSBCAPS))
112     {
113         /* invalid buffer size */
114         return DSERR_INVALIDPARAM;
115     }
116 
117     /* get buffer details */
118     pDSBufferCaps->dwUnlockTransferRate = 0;
119     pDSBufferCaps->dwPlayCpuOverhead = 0;
120     pDSBufferCaps->dwSize = 0; //FIXME
121     pDSBufferCaps->dwFlags = This->dwFlags;
122 
123     return DS_OK;
124 }
125 
126 HRESULT
127 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition(LPDIRECTSOUNDBUFFER8 iface,LPDWORD pdwCurrentPlayCursor,LPDWORD pdwCurrentWriteCursor)128 PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition(
129     LPDIRECTSOUNDBUFFER8 iface,
130     LPDWORD pdwCurrentPlayCursor,
131     LPDWORD pdwCurrentWriteCursor)
132 {
133     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
134 
135     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition\n");
136 
137     if (This->dwLevel < DSSCL_PRIORITY)
138     {
139         /* needs priority level */
140         return DSERR_PRIOLEVELNEEDED;
141     }
142 
143     if (!pdwCurrentPlayCursor && !pdwCurrentWriteCursor)
144     {
145         /* all parameters are null */
146         return DSERR_INVALIDPARAM;
147     }
148 
149     UNIMPLEMENTED;
150     return DSERR_INVALIDPARAM;
151 }
152 
153 HRESULT
154 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetFormat(LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX pwfxFormat,DWORD dwSizeAllocated,LPDWORD pdwSizeWritten)155 PrimaryDirectSoundBuffer8Impl_fnGetFormat(
156     LPDIRECTSOUNDBUFFER8 iface,
157     LPWAVEFORMATEX pwfxFormat,
158     DWORD dwSizeAllocated,
159     LPDWORD pdwSizeWritten)
160 {
161     DWORD FormatSize;
162     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
163 
164     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetFormat\n");
165 
166     FormatSize = sizeof(WAVEFORMATEX) + This->Format.cbSize;
167 
168     if (!pwfxFormat && !pdwSizeWritten)
169     {
170         /* invalid parameter */
171         return DSERR_INVALIDPARAM;
172     }
173 
174     if (!pwfxFormat)
175     {
176         /* return required format size */
177         *pdwSizeWritten = FormatSize;
178         return DS_OK;
179     }
180     else
181     {
182         if (dwSizeAllocated >= FormatSize)
183         {
184             /* copy format */
185             CopyMemory(pwfxFormat, &This->Format, FormatSize);
186 
187             if (pdwSizeWritten)
188                 *pdwSizeWritten = FormatSize;
189 
190             return DS_OK;
191         }
192         /* buffer too small */
193         if (pdwSizeWritten)
194             *pdwSizeWritten = 0;
195 
196         return DSERR_INVALIDPARAM;
197     }
198 }
199 
200 HRESULT
201 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetVolume(LPDIRECTSOUNDBUFFER8 iface,LPLONG plVolume)202 PrimaryDirectSoundBuffer8Impl_fnGetVolume(
203     LPDIRECTSOUNDBUFFER8 iface,
204     LPLONG plVolume)
205 {
206     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
207 
208     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetVolume\n");
209 
210     if (!plVolume)
211     {
212         /* invalid parameter */
213         return DSERR_INVALIDPARAM;
214     }
215 
216     /* get volume */
217     *plVolume = This->Volume;
218 
219     return DS_OK;
220 }
221 
222 HRESULT
223 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetPan(LPDIRECTSOUNDBUFFER8 iface,LPLONG plPan)224 PrimaryDirectSoundBuffer8Impl_fnGetPan(
225     LPDIRECTSOUNDBUFFER8 iface,
226     LPLONG plPan)
227 {
228     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
229 
230     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetPan\n");
231 
232     if (!plPan)
233     {
234         /* invalid parameter */
235         return DSERR_INVALIDPARAM;
236     }
237 
238     /* get frequency */
239     *plPan = This->VolumePan;
240 
241     return DS_OK;
242 }
243 
244 HRESULT
245 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetFrequency(LPDIRECTSOUNDBUFFER8 iface,LPDWORD pdwFrequency)246 PrimaryDirectSoundBuffer8Impl_fnGetFrequency(
247     LPDIRECTSOUNDBUFFER8 iface,
248     LPDWORD pdwFrequency)
249 {
250     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
251 
252     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetFrequency\n");
253 
254     if (!pdwFrequency)
255     {
256         /* invalid parameter */
257         return DSERR_INVALIDPARAM;
258     }
259 
260     /* get frequency */
261     *pdwFrequency = This->dwFrequency;
262 
263     return DS_OK;
264 }
265 
266 HRESULT
267 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetStatus(LPDIRECTSOUNDBUFFER8 iface,LPDWORD pdwStatus)268 PrimaryDirectSoundBuffer8Impl_fnGetStatus(
269     LPDIRECTSOUNDBUFFER8 iface,
270     LPDWORD pdwStatus)
271 {
272     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
273 
274     DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetStatus\n");
275 
276     if (!pdwStatus)
277     {
278         /* invalid parameter */
279         return DSERR_INVALIDPARAM;
280     }
281 
282     *pdwStatus = 0;
283     if (This->State == KSSTATE_RUN || This->State == KSSTATE_ACQUIRE)
284     {
285         /* buffer is playing */
286         *pdwStatus |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
287     }
288 
289     return DS_OK;
290 }
291 
292 HRESULT
293 WINAPI
PrimaryDirectSoundBuffer8Impl_fnInitialize(LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND pDirectSound,LPCDSBUFFERDESC pcDSBufferDesc)294 PrimaryDirectSoundBuffer8Impl_fnInitialize(
295     LPDIRECTSOUNDBUFFER8 iface,
296     LPDIRECTSOUND pDirectSound,
297     LPCDSBUFFERDESC pcDSBufferDesc)
298 {
299     /* RTFM */
300     return DSERR_ALREADYINITIALIZED;
301 }
302 
303 HRESULT
304 WINAPI
PrimaryDirectSoundBuffer8Impl_fnLock(LPDIRECTSOUNDBUFFER8 iface,DWORD dwOffset,DWORD dwBytes,LPVOID * ppvAudioPtr1,LPDWORD pdwAudioBytes1,LPVOID * ppvAudioPtr2,LPDWORD pdwAudioBytes2,DWORD dwFlags)305 PrimaryDirectSoundBuffer8Impl_fnLock(
306     LPDIRECTSOUNDBUFFER8 iface,
307     DWORD dwOffset,
308     DWORD dwBytes,
309     LPVOID *ppvAudioPtr1,
310     LPDWORD pdwAudioBytes1,
311     LPVOID *ppvAudioPtr2,
312     LPDWORD pdwAudioBytes2,
313     DWORD dwFlags)
314 {
315     UNIMPLEMENTED;
316     return DSERR_INVALIDPARAM;
317 }
318 
319 HRESULT
320 WINAPI
PrimaryDirectSoundBuffer8Impl_fnPlay(LPDIRECTSOUNDBUFFER8 iface,DWORD dwReserved1,DWORD dwPriority,DWORD dwFlags)321 PrimaryDirectSoundBuffer8Impl_fnPlay(
322     LPDIRECTSOUNDBUFFER8 iface,
323     DWORD dwReserved1,
324     DWORD dwPriority,
325     DWORD dwFlags)
326 {
327     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
328 
329     DPRINT("PrimaryDirectSoundBuffer8Impl_fnPlay dwFlags %x\n", dwFlags);
330 
331     if (dwReserved1 != 0 || !(dwFlags & DSBPLAY_LOOPING))
332     {
333         /* invalid parameter */
334         return DSERR_INVALIDPARAM;
335     }
336 
337     PrimaryDirectSoundBuffer_AcquireLock(iface);
338 
339     if (This->State == KSSTATE_STOP)
340     {
341         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_ACQUIRE);
342         ASSERT(This->State == KSSTATE_ACQUIRE);
343     }
344 
345     if (This->State == KSSTATE_ACQUIRE)
346     {
347         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_PAUSE);
348         ASSERT(This->State == KSSTATE_PAUSE);
349     }
350 
351     if (This->State == KSSTATE_PAUSE)
352     {
353         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_RUN);
354         ASSERT(This->State == KSSTATE_RUN);
355     }
356 
357     PrimaryDirectSoundBuffer_ReleaseLock(iface);
358 
359     return DS_OK;
360 }
361 
362 HRESULT
363 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition(LPDIRECTSOUNDBUFFER8 iface,DWORD dwNewPosition)364 PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition(
365     LPDIRECTSOUNDBUFFER8 iface,
366     DWORD dwNewPosition)
367 {
368     /* The position of a primary buffer can't be set */
369     return DSERR_INVALIDCALL;
370 }
371 
372 HRESULT
373 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetFormat(LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX pcfxFormat)374 PrimaryDirectSoundBuffer8Impl_fnSetFormat(
375     LPDIRECTSOUNDBUFFER8 iface,
376     LPCWAVEFORMATEX pcfxFormat)
377 {
378     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
379 
380     if (This->dwLevel == DSSCL_NORMAL)
381     {
382         /* can't change format with this level */
383         return DSERR_PRIOLEVELNEEDED;
384     }
385 
386     ASSERT(pcfxFormat->cbSize == 0);
387 
388 
389     DPRINT("This %p Format: Tag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u nBlockAlign %u wBitsPerSample %u cbSize %u\n", This,
390           pcfxFormat->wFormatTag, pcfxFormat->nChannels, pcfxFormat->nSamplesPerSec, pcfxFormat->nAvgBytesPerSec, pcfxFormat->nBlockAlign, pcfxFormat->wBitsPerSample, pcfxFormat->cbSize);
391 
392     CopyMemory(&This->Format, pcfxFormat, sizeof(WAVEFORMATEX));
393 
394     return DS_OK;
395 }
396 
397 HRESULT
398 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetVolume(LPDIRECTSOUNDBUFFER8 iface,LONG lVolume)399 PrimaryDirectSoundBuffer8Impl_fnSetVolume(
400     LPDIRECTSOUNDBUFFER8 iface,
401     LONG lVolume)
402 {
403     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
404 
405     if (lVolume < DSBVOLUME_MIN || lVolume > DSBVOLUME_MAX)
406     {
407         /* invalid parameter */
408         return DSERR_INVALIDPARAM;
409     }
410 
411     /* TODO: call volume node */
412 
413     /* Store volume */
414     This->Volume = lVolume;
415 
416     return DS_OK;
417 }
418 
419 HRESULT
420 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetPan(LPDIRECTSOUNDBUFFER8 iface,LONG lPan)421 PrimaryDirectSoundBuffer8Impl_fnSetPan(
422     LPDIRECTSOUNDBUFFER8 iface,
423     LONG lPan)
424 {
425     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
426 
427     if (lPan < DSBPAN_LEFT || lPan > DSBPAN_RIGHT)
428     {
429         /* invalid parameter */
430         return DSERR_INVALIDPARAM;
431     }
432 
433     /* TODO: call volume node */
434 
435     /* Store volume pan */
436     This->VolumePan = lPan;
437 
438     return DS_OK;
439 }
440 
441 HRESULT
442 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetFrequency(LPDIRECTSOUNDBUFFER8 iface,DWORD dwFrequency)443 PrimaryDirectSoundBuffer8Impl_fnSetFrequency(
444     LPDIRECTSOUNDBUFFER8 iface,
445     DWORD dwFrequency)
446 {
447     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
448 
449     if (This->dwLevel < DSSCL_PRIORITY)
450     {
451         /* needs priority level */
452         return DSERR_PRIOLEVELNEEDED;
453     }
454 
455     /* invalid request */
456     return DSERR_CONTROLUNAVAIL;
457 }
458 
459 HRESULT
460 WINAPI
PrimaryDirectSoundBuffer8Impl_fnStop(LPDIRECTSOUNDBUFFER8 iface)461 PrimaryDirectSoundBuffer8Impl_fnStop(
462     LPDIRECTSOUNDBUFFER8 iface)
463 {
464     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
465 
466     DPRINT("PrimaryDirectSoundBuffer8Impl_fnStop\n");
467 
468     PrimaryDirectSoundBuffer_AcquireLock(iface);
469 
470     if (This->State == KSSTATE_RUN)
471     {
472         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_PAUSE);
473         ASSERT(This->State == KSSTATE_PAUSE);
474     }
475 
476     if (This->State == KSSTATE_PAUSE)
477     {
478         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_ACQUIRE);
479         ASSERT(This->State == KSSTATE_ACQUIRE);
480     }
481 
482     if (This->State == KSSTATE_ACQUIRE)
483     {
484         PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_STOP);
485         ASSERT(This->State == KSSTATE_STOP);
486     }
487 
488     PrimaryDirectSoundBuffer_ReleaseLock(iface);
489 
490     return DS_OK;
491 }
492 
493 
494 HRESULT
495 WINAPI
PrimaryDirectSoundBuffer8Impl_fnUnlock(LPDIRECTSOUNDBUFFER8 iface,LPVOID pvAudioPtr1,DWORD dwAudioBytes1,LPVOID pvAudioPtr2,DWORD dwAudioBytes2)496 PrimaryDirectSoundBuffer8Impl_fnUnlock(
497     LPDIRECTSOUNDBUFFER8 iface,
498     LPVOID pvAudioPtr1,
499     DWORD dwAudioBytes1,
500     LPVOID pvAudioPtr2,
501     DWORD dwAudioBytes2)
502 {
503     UNIMPLEMENTED;
504     return DSERR_INVALIDPARAM;
505 }
506 
507 
508 HRESULT
509 WINAPI
PrimaryDirectSoundBuffer8Impl_fnRestore(LPDIRECTSOUNDBUFFER8 iface)510 PrimaryDirectSoundBuffer8Impl_fnRestore(
511     LPDIRECTSOUNDBUFFER8 iface)
512 {
513     UNIMPLEMENTED;
514     return DSERR_INVALIDPARAM;
515 }
516 
517 
518 HRESULT
519 WINAPI
PrimaryDirectSoundBuffer8Impl_fnSetFX(LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes)520 PrimaryDirectSoundBuffer8Impl_fnSetFX(
521     LPDIRECTSOUNDBUFFER8 iface,
522     DWORD dwEffectsCount,
523     LPDSEFFECTDESC pDSFXDesc,
524     LPDWORD pdwResultCodes)
525 {
526     UNIMPLEMENTED;
527     return DSERR_INVALIDPARAM;
528 }
529 
530 HRESULT
531 WINAPI
PrimaryDirectSoundBuffer8Impl_fnAcquireResources(LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes)532 PrimaryDirectSoundBuffer8Impl_fnAcquireResources(
533     LPDIRECTSOUNDBUFFER8 iface,
534     DWORD dwFlags,
535     DWORD dwEffectsCount,
536     LPDWORD pdwResultCodes)
537 {
538     UNIMPLEMENTED;
539     return DSERR_INVALIDPARAM;
540 }
541 
542 HRESULT
543 WINAPI
PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath(LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID * ppObject)544 PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath(
545     LPDIRECTSOUNDBUFFER8 iface,
546     REFGUID rguidObject,
547     DWORD dwIndex,
548     REFGUID rguidInterface,
549     LPVOID *ppObject)
550 {
551     UNIMPLEMENTED;
552     return DSERR_INVALIDPARAM;
553 }
554 
555 static IDirectSoundBuffer8Vtbl vt_DirectSoundBuffer8 =
556 {
557     /* IUnknown methods */
558     PrimaryDirectSoundBuffer8Impl_fnQueryInterface,
559     PrimaryDirectSoundBuffer8Impl_fnAddRef,
560     PrimaryDirectSoundBuffer8Impl_fnRelease,
561     /* IDirectSoundBuffer methods */
562     PrimaryDirectSoundBuffer8Impl_fnGetCaps,
563     PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition,
564     PrimaryDirectSoundBuffer8Impl_fnGetFormat,
565     PrimaryDirectSoundBuffer8Impl_fnGetVolume,
566     PrimaryDirectSoundBuffer8Impl_fnGetPan,
567     PrimaryDirectSoundBuffer8Impl_fnGetFrequency,
568     PrimaryDirectSoundBuffer8Impl_fnGetStatus,
569     PrimaryDirectSoundBuffer8Impl_fnInitialize,
570     PrimaryDirectSoundBuffer8Impl_fnLock,
571     PrimaryDirectSoundBuffer8Impl_fnPlay,
572     PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition,
573     PrimaryDirectSoundBuffer8Impl_fnSetFormat,
574     PrimaryDirectSoundBuffer8Impl_fnSetVolume,
575     PrimaryDirectSoundBuffer8Impl_fnSetPan,
576     PrimaryDirectSoundBuffer8Impl_fnSetFrequency,
577     PrimaryDirectSoundBuffer8Impl_fnStop,
578     PrimaryDirectSoundBuffer8Impl_fnUnlock,
579     PrimaryDirectSoundBuffer8Impl_fnRestore,
580     /* IDirectSoundBuffer8 methods */
581     PrimaryDirectSoundBuffer8Impl_fnSetFX,
582     PrimaryDirectSoundBuffer8Impl_fnAcquireResources,
583     PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath
584 };
585 
586 DWORD
PrimaryDirectSoundBuffer_Write(LPDIRECTSOUNDBUFFER8 iface,LPVOID Buffer,DWORD BufferSize)587 PrimaryDirectSoundBuffer_Write(
588     LPDIRECTSOUNDBUFFER8 iface,
589     LPVOID Buffer,
590     DWORD  BufferSize)
591 {
592     KSSTREAM_HEADER Header;
593     DWORD Result, BytesTransferred;
594     OVERLAPPED Overlapped;
595 
596     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
597 
598     ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
599     Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
600 
601 
602     ASSERT(This->hPin);
603     ZeroMemory(&Header, sizeof(KSSTREAM_HEADER));
604 
605     Header.FrameExtent = BufferSize;
606     Header.DataUsed = BufferSize;
607     Header.Data = Buffer;
608     Header.Size = sizeof(KSSTREAM_HEADER);
609     Header.PresentationTime.Numerator = 1;
610     Header.PresentationTime.Denominator = 1;
611 
612     Result = DeviceIoControl(This->hPin, IOCTL_KS_WRITE_STREAM, NULL, 0, &Header, sizeof(KSSTREAM_HEADER), &BytesTransferred, &Overlapped);
613 
614     if (Result != ERROR_SUCCESS)
615         return 0;
616 
617     return BytesTransferred;
618 }
619 
620 VOID
PrimaryDirectSoundBuffer_SetState(LPDIRECTSOUNDBUFFER8 iface,KSSTATE State)621 PrimaryDirectSoundBuffer_SetState(
622     LPDIRECTSOUNDBUFFER8 iface,
623     KSSTATE State)
624 {
625     KSPROPERTY Property;
626     DWORD Result, BytesTransferred;
627     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
628 
629     if (This->State == State)
630         return;
631 
632     Property.Set = KSPROPSETID_Connection;
633     Property.Id = KSPROPERTY_CONNECTION_STATE;
634     Property.Flags = KSPROPERTY_TYPE_SET;
635 
636     Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesTransferred);
637     if (Result == ERROR_SUCCESS)
638     {
639         This->State = State;
640     }
641 }
642 
643 HRESULT
PrimaryDirectSoundBuffer_GetPosition(LPDIRECTSOUNDBUFFER8 iface,LPDWORD pdwCurrentPlayCursor,LPDWORD pdwCurrentWriteCursor)644 PrimaryDirectSoundBuffer_GetPosition(
645     LPDIRECTSOUNDBUFFER8 iface,
646     LPDWORD pdwCurrentPlayCursor,
647     LPDWORD pdwCurrentWriteCursor)
648 {
649     KSAUDIO_POSITION Position;
650     KSPROPERTY Request;
651     DWORD Result;
652     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
653 
654     //DPRINT("PrimaryDirectSoundBuffer_GetPosition\n");
655 
656     if (!This->hPin)
657     {
658         if (pdwCurrentPlayCursor)
659             *pdwCurrentPlayCursor = 0;
660 
661         if (pdwCurrentWriteCursor)
662             *pdwCurrentWriteCursor = 0;
663 
664         DPRINT("No Audio Pin\n");
665         return DS_OK;
666     }
667 
668     /* setup audio position property request */
669     Request.Id = KSPROPERTY_AUDIO_POSITION;
670     Request.Set = KSPROPSETID_Audio;
671     Request.Flags = KSPROPERTY_TYPE_GET;
672 
673 
674     Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL);
675 
676     if (Result != ERROR_SUCCESS)
677     {
678         DPRINT("GetPosition failed with %x\n", Result);
679         return DSERR_UNSUPPORTED;
680     }
681 
682     //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset);
683 
684     if (pdwCurrentPlayCursor)
685         *pdwCurrentPlayCursor = (DWORD)Position.PlayOffset;
686 
687     if (pdwCurrentWriteCursor)
688         *pdwCurrentWriteCursor = (DWORD)Position.WriteOffset;
689 
690     return DS_OK;
691 }
692 
693 HRESULT
PrimaryDirectSoundBuffer_SetFormat(LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX pcfxFormat,BOOL bLooped)694 PrimaryDirectSoundBuffer_SetFormat(
695     LPDIRECTSOUNDBUFFER8 iface,
696     LPWAVEFORMATEX pcfxFormat,
697     BOOL bLooped)
698 {
699     ULONG PinId, DeviceId = 0, Result;
700     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
701 
702     if (This->hPin)
703     {
704         // FIXME
705         // check if multiple buffers are active
706         // in that case need mixing
707 
708         if (SetPinFormat(This->hPin, pcfxFormat))
709             return DS_OK;
710         else
711             return DSERR_GENERIC;
712     }
713 
714     do
715     {
716         /* try all available recording pins on that filter */
717         PinId = GetPinIdFromFilter(This->Filter, FALSE, DeviceId);
718         DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId);
719 
720         if (PinId == ULONG_MAX)
721             break;
722 
723         Result = OpenPin(This->Filter->hFilter, PinId, (LPWAVEFORMATEX)pcfxFormat, &This->hPin, bLooped);
724         DPRINT("PinId %u Result %u\n", PinId, Result);
725         if (Result == ERROR_SUCCESS)
726         {
727             This->dwFrequency = pcfxFormat->nSamplesPerSec;
728             break;
729         }
730 
731         This->hPin = NULL;
732         DeviceId++;
733     }while(TRUE);
734 
735     if (!This->hPin)
736     {
737         DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat failed\n");
738         return DSERR_INVALIDPARAM;
739     }
740 
741     DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat success\n");
742     return DS_OK;
743 }
744 
745 VOID
PrimaryDirectSoundBuffer_AcquireLock(LPDIRECTSOUNDBUFFER8 iface)746 PrimaryDirectSoundBuffer_AcquireLock(
747     LPDIRECTSOUNDBUFFER8 iface)
748 {
749     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
750 
751     EnterCriticalSection(&This->Lock);
752 
753 
754 }
755 
756 VOID
PrimaryDirectSoundBuffer_ReleaseLock(LPDIRECTSOUNDBUFFER8 iface)757 PrimaryDirectSoundBuffer_ReleaseLock(
758     LPDIRECTSOUNDBUFFER8 iface)
759 {
760     LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
761 
762     LeaveCriticalSection(&This->Lock);
763 
764 }
765 
766 
767 HRESULT
NewPrimarySoundBuffer(LPDIRECTSOUNDBUFFER8 * OutBuffer,LPFILTERINFO Filter,DWORD dwLevel,DWORD dwFlags)768 NewPrimarySoundBuffer(
769     LPDIRECTSOUNDBUFFER8 *OutBuffer,
770     LPFILTERINFO Filter,
771     DWORD dwLevel,
772     DWORD dwFlags)
773 {
774     LPCDirectSoundBuffer This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundBuffer));
775 
776     if (!This)
777     {
778         /* not enough memory */
779         return DSERR_OUTOFMEMORY;
780     }
781 
782     This->ref = 1;
783     This->lpVtbl = &vt_DirectSoundBuffer8;
784     This->Filter = Filter;
785     This->dwLevel = dwLevel;
786     This->dwFlags = dwFlags;
787     This->dwFrequency = 0;
788     This->Volume = DSBVOLUME_MAX;
789     This->VolumePan = DSBPAN_CENTER;
790     This->hPin = NULL;
791 
792     /* FIXME: determine default format for audio device */
793     This->Format.cbSize = sizeof(WAVEFORMATEX);
794     This->Format.nChannels = 2;
795     This->Format.nSamplesPerSec = 44100;
796     This->Format.wBitsPerSample = 16;
797     This->Format.wFormatTag = WAVE_FORMAT_PCM;
798     This->Format.nBlockAlign = (This->Format.nChannels * This->Format.wBitsPerSample) / 8;
799     This->Format.nAvgBytesPerSec = (This->Format.nChannels * This->Format.nSamplesPerSec * This->Format.wBitsPerSample) / 8;
800 
801     InitializeCriticalSection(&This->Lock);
802 
803     *OutBuffer = (LPDIRECTSOUNDBUFFER8)&This->lpVtbl;
804     return DS_OK;
805 }
806 
807