2 * Direct Sound Audio Renderer
4 * Copyright 2004 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "quartz_private.h"
24 #include "control_private.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
43 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
45 static const IBaseFilterVtbl DSoundRender_Vtbl
;
46 static const IPinVtbl DSoundRender_InputPin_Vtbl
;
47 static const IMemInputPinVtbl MemInputPin_Vtbl
;
48 static const IBasicAudioVtbl IBasicAudio_Vtbl
;
50 typedef struct DSoundRenderImpl
52 const IBaseFilterVtbl
* lpVtbl
;
53 const IBasicAudioVtbl
*IBasicAudio_vtbl
;
56 CRITICAL_SECTION csFilter
;
58 REFERENCE_TIME rtStreamStart
;
59 IReferenceClock
* pClock
;
60 FILTER_INFO filterInfo
;
66 LPDIRECTSOUNDBUFFER dsbuffer
;
74 static HRESULT
DSoundRender_InputPin_Construct(const PIN_INFO
* pPinInfo
, SAMPLEPROC pSampleProc
, LPVOID pUserData
, QUERYACCEPTPROC pQueryAccept
, LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
80 if (pPinInfo
->dir
!= PINDIR_INPUT
)
82 ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo
->dir
);
86 pPinImpl
= CoTaskMemAlloc(sizeof(*pPinImpl
));
91 if (SUCCEEDED(InputPin_Init(pPinInfo
, pSampleProc
, pUserData
, pQueryAccept
, pCritSec
, pPinImpl
)))
93 pPinImpl
->pin
.lpVtbl
= &DSoundRender_InputPin_Vtbl
;
94 pPinImpl
->lpVtblMemInput
= &MemInputPin_Vtbl
;
96 *ppPin
= (IPin
*)(&pPinImpl
->pin
.lpVtbl
);
103 #define DSBUFFERSIZE 8192
105 static HRESULT
DSoundRender_CreateSoundBuffer(IBaseFilter
* iface
)
108 WAVEFORMATEX wav_fmt
;
110 WAVEFORMATEX
* format
;
111 DSBUFFERDESC buf_desc
;
112 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
114 hr
= IPin_ConnectionMediaType(This
->ppPins
[0], &amt
);
116 ERR("Unable to retrieve media type\n");
120 TRACE("MajorType %s\n", debugstr_guid(&amt
.majortype
));
121 TRACE("SubType %s\n", debugstr_guid(&amt
.subtype
));
122 TRACE("Format %s\n", debugstr_guid(&amt
.formattype
));
123 TRACE("Size %d\n", amt
.cbFormat
);
125 dump_AM_MEDIA_TYPE(&amt
);
127 format
= (WAVEFORMATEX
*)amt
.pbFormat
;
128 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
129 TRACE("nChannels = %d\n", format
->nChannels
);
130 TRACE("nSamplesPerSec = %u\n", format
->nSamplesPerSec
);
131 TRACE("nAvgBytesPerSec = %u\n", format
->nAvgBytesPerSec
);
132 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
133 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
134 TRACE("cbSize = %d\n", format
->cbSize
);
136 /* Lock the critical section to make sure we're still marked to play while
137 setting up the playback buffer */
138 EnterCriticalSection(&This
->csFilter
);
140 if (This
->state
!= State_Running
) {
141 hr
= VFW_E_WRONG_STATE
;
145 hr
= DirectSoundCreate(NULL
, &This
->dsound
, NULL
);
147 ERR("Cannot create Direct Sound object\n");
154 memset(&buf_desc
,0,sizeof(DSBUFFERDESC
));
155 buf_desc
.dwSize
= sizeof(DSBUFFERDESC
);
156 buf_desc
.dwFlags
= DSBCAPS_CTRLVOLUME
| DSBCAPS_CTRLPAN
| DSBCAPS_CTRLFREQUENCY
;
157 buf_desc
.dwBufferBytes
= DSBUFFERSIZE
;
158 buf_desc
.lpwfxFormat
= &wav_fmt
;
159 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &buf_desc
, &This
->dsbuffer
, NULL
);
161 ERR("Can't create sound buffer !\n");
162 IDirectSound_Release(This
->dsound
);
166 hr
= IDirectSoundBuffer_SetVolume(This
->dsbuffer
, This
->volume
);
168 ERR("Can't set volume to %ld (%x)!\n", This
->volume
, hr
);
170 hr
= IDirectSoundBuffer_SetPan(This
->dsbuffer
, This
->pan
);
172 ERR("Can't set pan to %ld (%x)!\n", This
->pan
, hr
);
174 hr
= IDirectSoundBuffer_Play(This
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
176 ERR("Can't start sound buffer (%x)!\n", hr
);
177 IDirectSoundBuffer_Release(This
->dsbuffer
);
178 IDirectSound_Release(This
->dsound
);
185 LeaveCriticalSection(&This
->csFilter
);
189 static HRESULT
DSoundRender_SendSampleData(DSoundRenderImpl
* This
, LPBYTE data
, DWORD size
)
192 LPBYTE lpbuf1
= NULL
;
193 LPBYTE lpbuf2
= NULL
;
197 DWORD play_pos
,buf_free
;
200 hr
= IDirectSoundBuffer_GetCurrentPosition(This
->dsbuffer
, &play_pos
, NULL
);
203 ERR("Error GetCurrentPosition: %x\n", hr
);
206 if (This
->write_pos
< play_pos
)
207 buf_free
= play_pos
-This
->write_pos
;
209 buf_free
= DSBUFFERSIZE
- This
->write_pos
+ play_pos
;
211 /* This situation is ambiguous; Assume full when playing */
212 if(buf_free
== DSBUFFERSIZE
)
218 size2
= min(buf_free
, size
);
219 hr
= IDirectSoundBuffer_Lock(This
->dsbuffer
, This
->write_pos
, size2
, (LPVOID
*)&lpbuf1
, &dwsize1
, (LPVOID
*)&lpbuf2
, &dwsize2
, 0);
221 ERR("Unable to lock sound buffer! (%x)\n", hr
);
224 /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */
226 memcpy(lpbuf1
, data
, dwsize1
);
228 memcpy(lpbuf2
, data
+ dwsize1
, dwsize2
);
230 hr
= IDirectSoundBuffer_Unlock(This
->dsbuffer
, lpbuf1
, dwsize1
, lpbuf2
, dwsize2
);
232 ERR("Unable to unlock sound buffer! (%x)\n", hr
);
234 size
-= dwsize1
+ dwsize2
;
235 data
+= dwsize1
+ dwsize2
;
236 This
->write_pos
= (This
->write_pos
+ dwsize1
+ dwsize2
) % DSBUFFERSIZE
;
241 } while (This
->state
== State_Running
);
246 static HRESULT
DSoundRender_Sample(LPVOID iface
, IMediaSample
* pSample
)
248 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
249 LPBYTE pbSrcStream
= NULL
;
250 long cbSrcStream
= 0;
251 REFERENCE_TIME tStart
, tStop
;
254 TRACE("%p %p\n", iface
, pSample
);
256 if (This
->state
!= State_Running
)
257 return VFW_E_WRONG_STATE
;
259 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
262 ERR("Cannot get pointer to sample data (%x)\n", hr
);
266 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
268 ERR("Cannot get sample time (%x)\n", hr
);
270 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
272 TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream
, cbSrcStream
);
274 #if 0 /* For debugging purpose */
277 for(i
= 0; i
< cbSrcStream
; i
++)
279 if ((i
!=0) && !(i
%16))
281 TRACE("%02x ", pbSrcStream
[i
]);
289 hr
= DSoundRender_CreateSoundBuffer(iface
);
294 ERR("Unable to create DSound buffer\n");
299 hr
= DSoundRender_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
304 static HRESULT
DSoundRender_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
306 WAVEFORMATEX
* format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
307 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
308 TRACE("nChannels = %d\n", format
->nChannels
);
309 TRACE("nSamplesPerSec = %d\n", format
->nAvgBytesPerSec
);
310 TRACE("nAvgBytesPerSec = %d\n", format
->nAvgBytesPerSec
);
311 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
312 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
314 if (IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) && IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
319 HRESULT
DSoundRender_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
323 DSoundRenderImpl
* pDSoundRender
;
325 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
330 return CLASS_E_NOAGGREGATION
;
332 pDSoundRender
= CoTaskMemAlloc(sizeof(DSoundRenderImpl
));
334 return E_OUTOFMEMORY
;
335 ZeroMemory(pDSoundRender
, sizeof(DSoundRenderImpl
));
337 pDSoundRender
->lpVtbl
= &DSoundRender_Vtbl
;
338 pDSoundRender
->IBasicAudio_vtbl
= &IBasicAudio_Vtbl
;
339 pDSoundRender
->refCount
= 1;
340 InitializeCriticalSection(&pDSoundRender
->csFilter
);
341 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSoundRenderImpl.csFilter");
342 pDSoundRender
->state
= State_Stopped
;
344 pDSoundRender
->ppPins
= CoTaskMemAlloc(1 * sizeof(IPin
*));
345 if (!pDSoundRender
->ppPins
)
347 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = 0;
348 DeleteCriticalSection(&pDSoundRender
->csFilter
);
349 CoTaskMemFree(pDSoundRender
);
350 return E_OUTOFMEMORY
;
353 /* construct input pin */
354 piInput
.dir
= PINDIR_INPUT
;
355 piInput
.pFilter
= (IBaseFilter
*)pDSoundRender
;
356 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
357 hr
= DSoundRender_InputPin_Construct(&piInput
, DSoundRender_Sample
, (LPVOID
)pDSoundRender
, DSoundRender_QueryAccept
, &pDSoundRender
->csFilter
, (IPin
**)&pDSoundRender
->pInputPin
);
361 pDSoundRender
->ppPins
[0] = (IPin
*)pDSoundRender
->pInputPin
;
362 *ppv
= (LPVOID
)pDSoundRender
;
366 CoTaskMemFree(pDSoundRender
->ppPins
);
367 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = 0;
368 DeleteCriticalSection(&pDSoundRender
->csFilter
);
369 CoTaskMemFree(pDSoundRender
);
375 static HRESULT WINAPI
DSoundRender_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
377 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
378 TRACE("(%p, %p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
382 if (IsEqualIID(riid
, &IID_IUnknown
))
384 else if (IsEqualIID(riid
, &IID_IPersist
))
386 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
388 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
390 else if (IsEqualIID(riid
, &IID_IBasicAudio
))
391 *ppv
= (LPVOID
)&(This
->IBasicAudio_vtbl
);
395 IUnknown_AddRef((IUnknown
*)(*ppv
));
399 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
401 return E_NOINTERFACE
;
404 static ULONG WINAPI
DSoundRender_AddRef(IBaseFilter
* iface
)
406 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
407 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
409 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
414 static ULONG WINAPI
DSoundRender_Release(IBaseFilter
* iface
)
416 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
417 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
419 TRACE("(%p)->() Release from %d\n", This
, refCount
+ 1);
426 IReferenceClock_Release(This
->pClock
);
429 IDirectSoundBuffer_Release(This
->dsbuffer
);
430 This
->dsbuffer
= NULL
;
432 IDirectSound_Release(This
->dsound
);
435 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[0], &pConnectedTo
)))
437 IPin_Disconnect(pConnectedTo
);
438 IPin_Release(pConnectedTo
);
440 IPin_Disconnect(This
->ppPins
[0]);
442 IPin_Release(This
->ppPins
[0]);
444 CoTaskMemFree(This
->ppPins
);
446 This
->IBasicAudio_vtbl
= NULL
;
448 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
449 DeleteCriticalSection(&This
->csFilter
);
451 TRACE("Destroying Audio Renderer\n");
460 /** IPersist methods **/
462 static HRESULT WINAPI
DSoundRender_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
464 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
465 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
467 *pClsid
= CLSID_DSoundRender
;
472 /** IMediaFilter methods **/
474 static HRESULT WINAPI
DSoundRender_Stop(IBaseFilter
* iface
)
477 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
479 TRACE("(%p/%p)->()\n", This
, iface
);
481 EnterCriticalSection(&This
->csFilter
);
486 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
489 if (state
& DSBSTATUS_PLAYING
)
490 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
494 This
->state
= State_Stopped
;
496 LeaveCriticalSection(&This
->csFilter
);
501 static HRESULT WINAPI
DSoundRender_Pause(IBaseFilter
* iface
)
504 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
506 TRACE("(%p/%p)->()\n", This
, iface
);
508 EnterCriticalSection(&This
->csFilter
);
513 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
516 if (state
& DSBSTATUS_PLAYING
)
517 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
521 This
->state
= State_Paused
;
523 LeaveCriticalSection(&This
->csFilter
);
528 static HRESULT WINAPI
DSoundRender_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
531 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
533 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
535 EnterCriticalSection(&This
->csFilter
);
537 /* It's okay if there's no buffer yet. It'll start when it's created */
540 hr
= IDirectSoundBuffer_Play(This
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
542 ERR("Can't start playing! (%x)\n", hr
);
546 This
->rtStreamStart
= tStart
;
547 This
->state
= State_Running
;
550 LeaveCriticalSection(&This
->csFilter
);
555 static HRESULT WINAPI
DSoundRender_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
557 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
559 TRACE("(%p/%p)->(%d, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
561 EnterCriticalSection(&This
->csFilter
);
563 *pState
= This
->state
;
565 LeaveCriticalSection(&This
->csFilter
);
570 static HRESULT WINAPI
DSoundRender_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
572 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
574 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
576 EnterCriticalSection(&This
->csFilter
);
579 IReferenceClock_Release(This
->pClock
);
580 This
->pClock
= pClock
;
582 IReferenceClock_AddRef(This
->pClock
);
584 LeaveCriticalSection(&This
->csFilter
);
589 static HRESULT WINAPI
DSoundRender_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
591 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
593 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
595 EnterCriticalSection(&This
->csFilter
);
597 *ppClock
= This
->pClock
;
598 IReferenceClock_AddRef(This
->pClock
);
600 LeaveCriticalSection(&This
->csFilter
);
605 /** IBaseFilter implementation **/
607 static HRESULT WINAPI
DSoundRender_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
610 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
612 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
614 epd
.cPins
= 1; /* input pin */
615 epd
.ppPins
= This
->ppPins
;
616 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
619 static HRESULT WINAPI
DSoundRender_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
621 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
623 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
625 FIXME("DSoundRender::FindPin(...)\n");
627 /* FIXME: critical section */
632 static HRESULT WINAPI
DSoundRender_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
634 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
636 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
638 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
639 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
642 IFilterGraph_AddRef(pInfo
->pGraph
);
647 static HRESULT WINAPI
DSoundRender_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
649 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
651 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
653 EnterCriticalSection(&This
->csFilter
);
656 strcpyW(This
->filterInfo
.achName
, pName
);
658 *This
->filterInfo
.achName
= '\0';
659 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
661 LeaveCriticalSection(&This
->csFilter
);
666 static HRESULT WINAPI
DSoundRender_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
668 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
669 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
673 static const IBaseFilterVtbl DSoundRender_Vtbl
=
675 DSoundRender_QueryInterface
,
677 DSoundRender_Release
,
678 DSoundRender_GetClassID
,
682 DSoundRender_GetState
,
683 DSoundRender_SetSyncSource
,
684 DSoundRender_GetSyncSource
,
685 DSoundRender_EnumPins
,
686 DSoundRender_FindPin
,
687 DSoundRender_QueryFilterInfo
,
688 DSoundRender_JoinFilterGraph
,
689 DSoundRender_QueryVendorInfo
692 static HRESULT WINAPI
DSoundRender_InputPin_EndOfStream(IPin
* iface
)
694 InputPin
* This
= (InputPin
*)iface
;
695 IMediaEventSink
* pEventSink
;
698 TRACE("(%p/%p)->()\n", This
, iface
);
700 hr
= IFilterGraph_QueryInterface(((DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
)->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
703 /* FIXME: We should wait that all audio data has been played */
704 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
705 IMediaEventSink_Release(pEventSink
);
711 static const IPinVtbl DSoundRender_InputPin_Vtbl
=
713 InputPin_QueryInterface
,
717 InputPin_ReceiveConnection
,
719 IPinImpl_ConnectedTo
,
720 IPinImpl_ConnectionMediaType
,
721 IPinImpl_QueryPinInfo
,
722 IPinImpl_QueryDirection
,
724 IPinImpl_QueryAccept
,
725 IPinImpl_EnumMediaTypes
,
726 IPinImpl_QueryInternalConnections
,
727 DSoundRender_InputPin_EndOfStream
,
733 static const IMemInputPinVtbl MemInputPin_Vtbl
=
735 MemInputPin_QueryInterface
,
738 MemInputPin_GetAllocator
,
739 MemInputPin_NotifyAllocator
,
740 MemInputPin_GetAllocatorRequirements
,
742 MemInputPin_ReceiveMultiple
,
743 MemInputPin_ReceiveCanBlock
746 /*** IUnknown methods ***/
747 static HRESULT WINAPI
Basicaudio_QueryInterface(IBasicAudio
*iface
,
750 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
752 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
754 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
757 static ULONG WINAPI
Basicaudio_AddRef(IBasicAudio
*iface
) {
758 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
760 TRACE("(%p/%p)->()\n", This
, iface
);
762 return DSoundRender_AddRef((IBaseFilter
*)This
);
765 static ULONG WINAPI
Basicaudio_Release(IBasicAudio
*iface
) {
766 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
768 TRACE("(%p/%p)->()\n", This
, iface
);
770 return DSoundRender_Release((IBaseFilter
*)This
);
773 /*** IDispatch methods ***/
774 static HRESULT WINAPI
Basicaudio_GetTypeInfoCount(IBasicAudio
*iface
,
776 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
778 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, pctinfo
);
783 static HRESULT WINAPI
Basicaudio_GetTypeInfo(IBasicAudio
*iface
,
786 ITypeInfo
**ppTInfo
) {
787 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
789 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This
, iface
, iTInfo
, lcid
, ppTInfo
);
794 static HRESULT WINAPI
Basicaudio_GetIDsOfNames(IBasicAudio
*iface
,
800 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
802 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This
, iface
, debugstr_guid(riid
), riid
, rgszNames
, cNames
, lcid
, rgDispId
);
807 static HRESULT WINAPI
Basicaudio_Invoke(IBasicAudio
*iface
,
812 DISPPARAMS
*pDispParams
,
816 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
818 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This
, iface
, dispIdMember
, debugstr_guid(riid
), riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExepInfo
, puArgErr
);
823 /*** IBasicAudio methods ***/
824 static HRESULT WINAPI
Basicaudio_put_Volume(IBasicAudio
*iface
,
826 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
828 TRACE("(%p/%p)->(%ld)\n", This
, iface
, lVolume
);
830 if (lVolume
> DSBVOLUME_MAX
|| lVolume
< DSBVOLUME_MIN
)
833 if (This
->dsbuffer
) {
834 if (FAILED(IDirectSoundBuffer_SetVolume(This
->dsbuffer
, lVolume
)))
838 This
->volume
= lVolume
;
842 static HRESULT WINAPI
Basicaudio_get_Volume(IBasicAudio
*iface
,
844 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
846 TRACE("(%p/%p)->(%p)\n", This
, iface
, plVolume
);
851 *plVolume
= This
->volume
;
855 static HRESULT WINAPI
Basicaudio_put_Balance(IBasicAudio
*iface
,
857 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
859 TRACE("(%p/%p)->(%ld)\n", This
, iface
, lBalance
);
861 if (lBalance
< DSBPAN_LEFT
|| lBalance
> DSBPAN_RIGHT
)
864 if (This
->dsbuffer
) {
865 if (FAILED(IDirectSoundBuffer_SetPan(This
->dsbuffer
, lBalance
)))
869 This
->pan
= lBalance
;
873 static HRESULT WINAPI
Basicaudio_get_Balance(IBasicAudio
*iface
,
875 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
877 TRACE("(%p/%p)->(%p)\n", This
, iface
, plBalance
);
882 *plBalance
= This
->pan
;
886 static const IBasicAudioVtbl IBasicAudio_Vtbl
=
888 Basicaudio_QueryInterface
,
891 Basicaudio_GetTypeInfoCount
,
892 Basicaudio_GetTypeInfo
,
893 Basicaudio_GetIDsOfNames
,
895 Basicaudio_put_Volume
,
896 Basicaudio_get_Volume
,
897 Basicaudio_put_Balance
,
898 Basicaudio_get_Balance