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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
;
71 static HRESULT
DSoundRender_InputPin_Construct(const PIN_INFO
* pPinInfo
, SAMPLEPROC pSampleProc
, LPVOID pUserData
, QUERYACCEPTPROC pQueryAccept
, LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
77 if (pPinInfo
->dir
!= PINDIR_INPUT
)
79 ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo
->dir
);
83 pPinImpl
= CoTaskMemAlloc(sizeof(*pPinImpl
));
88 if (SUCCEEDED(InputPin_Init(pPinInfo
, pSampleProc
, pUserData
, pQueryAccept
, pCritSec
, pPinImpl
)))
90 pPinImpl
->pin
.lpVtbl
= &DSoundRender_InputPin_Vtbl
;
91 pPinImpl
->lpVtblMemInput
= &MemInputPin_Vtbl
;
93 *ppPin
= (IPin
*)(&pPinImpl
->pin
.lpVtbl
);
100 #define DSBUFFERSIZE 8192
102 static HRESULT
DSoundRender_CreateSoundBuffer(IBaseFilter
* iface
)
105 WAVEFORMATEX wav_fmt
;
107 WAVEFORMATEX
* format
;
108 DSBUFFERDESC buf_desc
;
109 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
111 hr
= IPin_ConnectionMediaType(This
->ppPins
[0], &amt
);
113 ERR("Unable to retrieve media type\n");
117 TRACE("MajorType %s\n", debugstr_guid(&amt
.majortype
));
118 TRACE("SubType %s\n", debugstr_guid(&amt
.subtype
));
119 TRACE("Format %s\n", debugstr_guid(&amt
.formattype
));
120 TRACE("Size %ld\n", amt
.cbFormat
);
122 dump_AM_MEDIA_TYPE(&amt
);
124 format
= (WAVEFORMATEX
*)amt
.pbFormat
;
125 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
126 TRACE("nChannels = %d\n", format
->nChannels
);
127 TRACE("nSamplesPerSec = %lu\n", format
->nSamplesPerSec
);
128 TRACE("nAvgBytesPerSec = %lu\n", format
->nAvgBytesPerSec
);
129 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
130 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
131 TRACE("cbSize = %d\n", format
->cbSize
);
133 hr
= DirectSoundCreate(NULL
, &This
->dsound
, NULL
);
135 ERR("Cannot create Direct Sound object\n");
142 memset(&buf_desc
,0,sizeof(DSBUFFERDESC
));
143 buf_desc
.dwSize
= sizeof(DSBUFFERDESC
);
144 buf_desc
.dwBufferBytes
= DSBUFFERSIZE
;
145 buf_desc
.lpwfxFormat
= &wav_fmt
;
146 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &buf_desc
, &This
->dsbuffer
, NULL
);
148 ERR("Can't create sound buffer !\n");
157 static DWORD
DSoundRender_SendSampleData(DSoundRenderImpl
* This
, LPBYTE data
, DWORD size
)
160 LPBYTE lpbuf1
= NULL
;
161 LPBYTE lpbuf2
= NULL
;
166 DWORD play_pos
,buf_free
;
170 result
=IDirectSoundBuffer_GetCurrentPosition(This
->dsbuffer
, &play_pos
, NULL
);
171 if (result
!= DS_OK
) {
172 ERR("Error GetCurrentPosition: %lx\n", result
);
175 if (This
->write_pos
< play_pos
)
176 buf_free
= play_pos
-This
->write_pos
;
178 buf_free
= DSBUFFERSIZE
- This
->write_pos
+ play_pos
;
180 size2
= min(buf_free
, size
);
181 result
= IDirectSoundBuffer_Lock(This
->dsbuffer
, This
->write_pos
, size2
, &lpbuf1
, &dwsize1
, &lpbuf2
, &dwsize2
, 0);
182 if (result
!= DS_OK
) {
183 ERR("Unable to lock sound buffer !\n");
186 /* TRACE("write_pos=%ld, size=%ld, sz1=%ld, sz2=%ld\n", This->write_pos, size2, dwsize1, dwsize2); */
188 memcpy(lpbuf1
, data
, dwsize1
);
190 memcpy(lpbuf2
, data
+ dwsize1
, dwsize2
);
193 result
= IDirectSoundBuffer_Unlock(This
->dsbuffer
, lpbuf1
, dwsize1
, lpbuf2
, dwsize2
);
195 ERR("Unable to unlock sound buffer !\n");
198 result
= IDirectSoundBuffer_Play(This
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
199 if (result
!= DS_OK
) {
200 ERR("Can't start playing !\n");
203 size
-= dwsize1
+ dwsize2
;
204 data
+= dwsize1
+ dwsize2
;
205 This
->write_pos
= (This
->write_pos
+ dwsize1
+ dwsize2
) % DSBUFFERSIZE
;
214 static HRESULT
DSoundRender_Sample(LPVOID iface
, IMediaSample
* pSample
)
216 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
217 LPBYTE pbSrcStream
= NULL
;
218 long cbSrcStream
= 0;
219 REFERENCE_TIME tStart
, tStop
;
222 TRACE("%p %p\n", iface
, pSample
);
224 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
227 ERR("Cannot get pointer to sample data (%lx)\n", hr
);
231 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
233 ERR("Cannot get sample time (%lx)\n", hr
);
235 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
237 TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream
, cbSrcStream
);
239 #if 0 /* For debugging purpose */
242 for(i
= 0; i
< cbSrcStream
; i
++)
244 if ((i
!=0) && !(i
%16))
246 DPRINTF("%02x ", pbSrcStream
[i
]);
255 hr
= DSoundRender_CreateSoundBuffer(iface
);
258 ERR("Unable to create DSound buffer\n");
261 DSoundRender_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
266 static HRESULT
DSoundRender_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
268 WAVEFORMATEX
* format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
269 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
270 TRACE("nChannels = %d\n", format
->nChannels
);
271 TRACE("nSamplesPerSec = %ld\n", format
->nAvgBytesPerSec
);
272 TRACE("nAvgBytesPerSec = %ld\n", format
->nAvgBytesPerSec
);
273 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
274 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
276 if (IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) && IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
281 HRESULT
DSoundRender_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
285 DSoundRenderImpl
* pDSoundRender
;
287 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
292 return CLASS_E_NOAGGREGATION
;
294 pDSoundRender
= CoTaskMemAlloc(sizeof(DSoundRenderImpl
));
296 pDSoundRender
->lpVtbl
= &DSoundRender_Vtbl
;
297 pDSoundRender
->IBasicAudio_vtbl
= &IBasicAudio_Vtbl
;
298 pDSoundRender
->refCount
= 1;
299 InitializeCriticalSection(&pDSoundRender
->csFilter
);
300 pDSoundRender
->state
= State_Stopped
;
301 pDSoundRender
->pClock
= NULL
;
302 pDSoundRender
->init
= 0;
303 ZeroMemory(&pDSoundRender
->filterInfo
, sizeof(FILTER_INFO
));
305 pDSoundRender
->ppPins
= CoTaskMemAlloc(1 * sizeof(IPin
*));
307 /* construct input pin */
308 piInput
.dir
= PINDIR_INPUT
;
309 piInput
.pFilter
= (IBaseFilter
*)pDSoundRender
;
310 strncpyW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
311 hr
= DSoundRender_InputPin_Construct(&piInput
, DSoundRender_Sample
, (LPVOID
)pDSoundRender
, DSoundRender_QueryAccept
, &pDSoundRender
->csFilter
, (IPin
**)&pDSoundRender
->pInputPin
);
315 pDSoundRender
->ppPins
[0] = (IPin
*)pDSoundRender
->pInputPin
;
316 *ppv
= (LPVOID
)pDSoundRender
;
320 CoTaskMemFree(pDSoundRender
->ppPins
);
321 DeleteCriticalSection(&pDSoundRender
->csFilter
);
322 CoTaskMemFree(pDSoundRender
);
328 static HRESULT WINAPI
DSoundRender_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
330 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
331 TRACE("(%p, %p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
335 if (IsEqualIID(riid
, &IID_IUnknown
))
337 else if (IsEqualIID(riid
, &IID_IPersist
))
339 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
341 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
343 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
344 *ppv
= (LPVOID
)&(This
->IBasicAudio_vtbl
);
348 IUnknown_AddRef((IUnknown
*)(*ppv
));
352 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
354 return E_NOINTERFACE
;
357 static ULONG WINAPI
DSoundRender_AddRef(IBaseFilter
* iface
)
359 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
360 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
362 TRACE("(%p/%p)->() AddRef from %ld\n", This
, iface
, refCount
- 1);
367 static ULONG WINAPI
DSoundRender_Release(IBaseFilter
* iface
)
369 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
370 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
372 TRACE("(%p/%p)->() Release from %ld\n", This
, iface
, refCount
+ 1);
376 DeleteCriticalSection(&This
->csFilter
);
378 IReferenceClock_Release(This
->pClock
);
380 IPin_Release(This
->ppPins
[0]);
382 HeapFree(GetProcessHeap(), 0, This
->ppPins
);
384 This
->IBasicAudio_vtbl
= NULL
;
386 TRACE("Destroying Audio Renderer\n");
395 /** IPersist methods **/
397 static HRESULT WINAPI
DSoundRender_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
399 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
400 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
402 *pClsid
= CLSID_DSoundRender
;
407 /** IMediaFilter methods **/
409 static HRESULT WINAPI
DSoundRender_Stop(IBaseFilter
* iface
)
412 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
414 TRACE("(%p/%p)->()\n", This
, iface
);
416 EnterCriticalSection(&This
->csFilter
);
418 This
->state
= State_Stopped
;
420 LeaveCriticalSection(&This
->csFilter
);
425 static HRESULT WINAPI
DSoundRender_Pause(IBaseFilter
* iface
)
428 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
430 TRACE("(%p/%p)->()\n", This
, iface
);
432 EnterCriticalSection(&This
->csFilter
);
434 This
->state
= State_Paused
;
436 LeaveCriticalSection(&This
->csFilter
);
441 static HRESULT WINAPI
DSoundRender_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
444 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
446 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
448 EnterCriticalSection(&This
->csFilter
);
450 This
->rtStreamStart
= tStart
;
451 This
->state
= State_Running
;
453 LeaveCriticalSection(&This
->csFilter
);
458 static HRESULT WINAPI
DSoundRender_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
460 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
462 TRACE("(%p/%p)->(%ld, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
464 EnterCriticalSection(&This
->csFilter
);
466 *pState
= This
->state
;
468 LeaveCriticalSection(&This
->csFilter
);
473 static HRESULT WINAPI
DSoundRender_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
475 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
477 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
479 EnterCriticalSection(&This
->csFilter
);
482 IReferenceClock_Release(This
->pClock
);
483 This
->pClock
= pClock
;
485 IReferenceClock_AddRef(This
->pClock
);
487 LeaveCriticalSection(&This
->csFilter
);
492 static HRESULT WINAPI
DSoundRender_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
494 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
496 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
498 EnterCriticalSection(&This
->csFilter
);
500 *ppClock
= This
->pClock
;
501 IReferenceClock_AddRef(This
->pClock
);
503 LeaveCriticalSection(&This
->csFilter
);
508 /** IBaseFilter implementation **/
510 static HRESULT WINAPI
DSoundRender_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
513 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
515 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
517 epd
.cPins
= 1; /* input pin */
518 epd
.ppPins
= This
->ppPins
;
519 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
522 static HRESULT WINAPI
DSoundRender_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
524 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
526 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
528 FIXME("DSoundRender::FindPin(...)\n");
530 /* FIXME: critical section */
535 static HRESULT WINAPI
DSoundRender_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
537 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
539 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
541 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
542 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
545 IFilterGraph_AddRef(pInfo
->pGraph
);
550 static HRESULT WINAPI
DSoundRender_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
552 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
554 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
556 EnterCriticalSection(&This
->csFilter
);
559 strcpyW(This
->filterInfo
.achName
, pName
);
561 *This
->filterInfo
.achName
= '\0';
562 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
564 LeaveCriticalSection(&This
->csFilter
);
569 static HRESULT WINAPI
DSoundRender_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
571 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
572 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
576 static const IBaseFilterVtbl DSoundRender_Vtbl
=
578 DSoundRender_QueryInterface
,
580 DSoundRender_Release
,
581 DSoundRender_GetClassID
,
585 DSoundRender_GetState
,
586 DSoundRender_SetSyncSource
,
587 DSoundRender_GetSyncSource
,
588 DSoundRender_EnumPins
,
589 DSoundRender_FindPin
,
590 DSoundRender_QueryFilterInfo
,
591 DSoundRender_JoinFilterGraph
,
592 DSoundRender_QueryVendorInfo
595 static HRESULT WINAPI
DSoundRender_InputPin_EndOfStream(IPin
* iface
)
597 InputPin
* This
= (InputPin
*)iface
;
598 IMediaEventSink
* pEventSink
;
601 TRACE("(%p/%p)->()\n", This
, iface
);
603 hr
= IFilterGraph_QueryInterface(((DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
)->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
606 /* FIXME: We should wait that all audio data has been played */
607 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
608 IMediaEventSink_Release(pEventSink
);
614 static const IPinVtbl DSoundRender_InputPin_Vtbl
=
616 InputPin_QueryInterface
,
620 InputPin_ReceiveConnection
,
622 IPinImpl_ConnectedTo
,
623 IPinImpl_ConnectionMediaType
,
624 IPinImpl_QueryPinInfo
,
625 IPinImpl_QueryDirection
,
627 IPinImpl_QueryAccept
,
628 IPinImpl_EnumMediaTypes
,
629 IPinImpl_QueryInternalConnections
,
630 DSoundRender_InputPin_EndOfStream
,
636 static const IMemInputPinVtbl MemInputPin_Vtbl
=
638 MemInputPin_QueryInterface
,
641 MemInputPin_GetAllocator
,
642 MemInputPin_NotifyAllocator
,
643 MemInputPin_GetAllocatorRequirements
,
645 MemInputPin_ReceiveMultiple
,
646 MemInputPin_ReceiveCanBlock
649 /*** IUnknown methods ***/
650 static HRESULT WINAPI
Basicaudio_QueryInterface(IBasicAudio
*iface
,
653 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
655 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
657 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
660 static ULONG WINAPI
Basicaudio_AddRef(IBasicAudio
*iface
) {
661 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
663 TRACE("(%p/%p)->()\n", This
, iface
);
665 return DSoundRender_AddRef((IBaseFilter
*)This
);
668 static ULONG WINAPI
Basicaudio_Release(IBasicAudio
*iface
) {
669 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
671 TRACE("(%p/%p)->()\n", This
, iface
);
673 return DSoundRender_Release((IBaseFilter
*)This
);
676 /*** IDispatch methods ***/
677 static HRESULT WINAPI
Basicaudio_GetTypeInfoCount(IBasicAudio
*iface
,
679 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
681 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, pctinfo
);
686 static HRESULT WINAPI
Basicaudio_GetTypeInfo(IBasicAudio
*iface
,
689 ITypeInfo
**ppTInfo
) {
690 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
692 TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This
, iface
, iTInfo
, lcid
, ppTInfo
);
697 static HRESULT WINAPI
Basicaudio_GetIDsOfNames(IBasicAudio
*iface
,
703 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
705 TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This
, iface
, debugstr_guid(riid
), riid
, rgszNames
, cNames
, lcid
, rgDispId
);
710 static HRESULT WINAPI
Basicaudio_Invoke(IBasicAudio
*iface
,
715 DISPPARAMS
*pDispParams
,
719 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
721 TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This
, iface
, dispIdMember
, debugstr_guid(riid
), riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExepInfo
, puArgErr
);
726 /*** IBasicAudio methods ***/
727 static HRESULT WINAPI
Basicaudio_put_Volume(IBasicAudio
*iface
,
729 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
731 TRACE("(%p/%p)->(%ld): stub !!!\n", This
, iface
, lVolume
);
736 static HRESULT WINAPI
Basicaudio_get_Volume(IBasicAudio
*iface
,
738 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
740 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, plVolume
);
745 static HRESULT WINAPI
Basicaudio_put_Balance(IBasicAudio
*iface
,
747 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
749 TRACE("(%p/%p)->(%ld): stub !!!\n", This
, iface
, lBalance
);
754 static HRESULT WINAPI
Basicaudio_get_Balance(IBasicAudio
*iface
,
756 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
758 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, plBalance
);
763 static const IBasicAudioVtbl IBasicAudio_Vtbl
=
765 Basicaudio_QueryInterface
,
768 Basicaudio_GetTypeInfoCount
,
769 Basicaudio_GetTypeInfo
,
770 Basicaudio_GetIDsOfNames
,
772 Basicaudio_put_Volume
,
773 Basicaudio_get_Volume
,
774 Basicaudio_put_Balance
,
775 Basicaudio_get_Balance