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"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
41 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
43 static const IBaseFilterVtbl DSoundRender_Vtbl
;
44 static const IPinVtbl DSoundRender_InputPin_Vtbl
;
45 static const IMemInputPinVtbl MemInputPin_Vtbl
;
46 static const IBasicAudioVtbl IBasicAudio_Vtbl
;
47 static const IReferenceClockVtbl IReferenceClock_Vtbl
;
49 typedef struct DSoundRenderImpl
51 const IBaseFilterVtbl
* lpVtbl
;
52 const IBasicAudioVtbl
*IBasicAudio_vtbl
;
53 const IReferenceClockVtbl
*IReferenceClock_vtbl
;
56 CRITICAL_SECTION csFilter
;
58 REFERENCE_TIME rtStreamStart
;
59 IReferenceClock
* pClock
;
60 FILTER_INFO filterInfo
;
66 LPDIRECTSOUNDBUFFER dsbuffer
;
73 REFERENCE_TIME play_time
;
79 static HRESULT
DSoundRender_InputPin_Construct(const PIN_INFO
* pPinInfo
, SAMPLEPROC pSampleProc
, LPVOID pUserData
, QUERYACCEPTPROC pQueryAccept
, LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
85 if (pPinInfo
->dir
!= PINDIR_INPUT
)
87 ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo
->dir
);
91 pPinImpl
= CoTaskMemAlloc(sizeof(*pPinImpl
));
96 if (SUCCEEDED(InputPin_Init(pPinInfo
, pSampleProc
, pUserData
, pQueryAccept
, pCritSec
, pPinImpl
)))
98 pPinImpl
->pin
.lpVtbl
= &DSoundRender_InputPin_Vtbl
;
99 pPinImpl
->lpVtblMemInput
= &MemInputPin_Vtbl
;
101 *ppPin
= (IPin
*)(&pPinImpl
->pin
.lpVtbl
);
105 CoTaskMemFree(pPinImpl
);
110 static inline HRESULT
DSoundRender_GetPos(DSoundRenderImpl
*This
, DWORD
*pPlayPos
, DWORD
*pWritePos
, REFERENCE_TIME
*pRefTime
)
114 EnterCriticalSection(&This
->csFilter
);
116 hr
= IDirectSoundBuffer_GetCurrentPosition(This
->dsbuffer
, pPlayPos
, pWritePos
);
119 DWORD play_pos
= *pPlayPos
;
121 if (play_pos
< This
->last_play_pos
)
123 This
->last_play_pos
= play_pos
;
125 /* If we're really falling behind, kick the play time back */
126 if ((This
->play_loops
*This
->buf_size
)+play_pos
>=
127 (This
->write_loops
*This
->buf_size
)+This
->write_pos
)
132 REFERENCE_TIME play_time
;
133 play_time
= ((REFERENCE_TIME
)This
->play_loops
*10000000) +
134 ((REFERENCE_TIME
)play_pos
*10000000/This
->buf_size
);
136 /* Don't let time run backwards */
137 if(play_time
-This
->play_time
> 0)
138 This
->play_time
= play_time
;
142 *pRefTime
= This
->play_time
;
146 LeaveCriticalSection(&This
->csFilter
);
151 static HRESULT
DSoundRender_SendSampleData(DSoundRenderImpl
* This
, const BYTE
*data
, DWORD size
)
154 LPBYTE lpbuf1
= NULL
;
155 LPBYTE lpbuf2
= NULL
;
159 DWORD play_pos
,buf_free
;
162 hr
= DSoundRender_GetPos(This
, &play_pos
, NULL
, NULL
);
165 ERR("GetPos returned error: %x\n", hr
);
168 if (This
->write_pos
<= play_pos
)
169 buf_free
= play_pos
-This
->write_pos
;
171 buf_free
= This
->buf_size
- This
->write_pos
+ play_pos
;
173 /* Wait for enough of the buffer to empty before filling it */
174 if(buf_free
< This
->buf_size
/4)
180 size2
= min(buf_free
, size
);
181 hr
= IDirectSoundBuffer_Lock(This
->dsbuffer
, This
->write_pos
, size2
, (LPVOID
*)&lpbuf1
, &dwsize1
, (LPVOID
*)&lpbuf2
, &dwsize2
, 0);
183 ERR("Unable to lock sound buffer! (%x)\n", hr
);
186 /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */
188 memcpy(lpbuf1
, data
, dwsize1
);
190 memcpy(lpbuf2
, data
+ dwsize1
, dwsize2
);
192 hr
= IDirectSoundBuffer_Unlock(This
->dsbuffer
, lpbuf1
, dwsize1
, lpbuf2
, dwsize2
);
194 ERR("Unable to unlock sound buffer! (%x)\n", hr
);
196 size
-= dwsize1
+ dwsize2
;
197 data
+= dwsize1
+ dwsize2
;
198 This
->write_pos
+= dwsize1
+ dwsize2
;
199 if (This
->write_pos
>= This
->buf_size
)
201 This
->write_pos
-= This
->buf_size
;
204 } while (size
&& This
->state
== State_Running
);
209 static HRESULT
DSoundRender_Sample(LPVOID iface
, IMediaSample
* pSample
)
211 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
212 LPBYTE pbSrcStream
= NULL
;
213 long cbSrcStream
= 0;
214 REFERENCE_TIME tStart
, tStop
;
217 TRACE("%p %p\n", iface
, pSample
);
219 if (This
->state
!= State_Running
)
220 return VFW_E_WRONG_STATE
;
222 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
225 ERR("Cannot get pointer to sample data (%x)\n", hr
);
229 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
231 ERR("Cannot get sample time (%x)\n", hr
);
233 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
235 TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream
, cbSrcStream
);
237 #if 0 /* For debugging purpose */
240 for(i
= 0; i
< cbSrcStream
; i
++)
242 if ((i
!=0) && !(i
%16))
244 TRACE("%02x ", pbSrcStream
[i
]);
250 return DSoundRender_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
253 static HRESULT
DSoundRender_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
255 WAVEFORMATEX
* format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
256 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
257 TRACE("nChannels = %d\n", format
->nChannels
);
258 TRACE("nSamplesPerSec = %d\n", format
->nAvgBytesPerSec
);
259 TRACE("nAvgBytesPerSec = %d\n", format
->nAvgBytesPerSec
);
260 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
261 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
263 if (IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) && IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
268 HRESULT
DSoundRender_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
272 DSoundRenderImpl
* pDSoundRender
;
274 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
279 return CLASS_E_NOAGGREGATION
;
281 pDSoundRender
= CoTaskMemAlloc(sizeof(DSoundRenderImpl
));
283 return E_OUTOFMEMORY
;
284 ZeroMemory(pDSoundRender
, sizeof(DSoundRenderImpl
));
286 pDSoundRender
->lpVtbl
= &DSoundRender_Vtbl
;
287 pDSoundRender
->IBasicAudio_vtbl
= &IBasicAudio_Vtbl
;
288 pDSoundRender
->IReferenceClock_vtbl
= &IReferenceClock_Vtbl
;
289 pDSoundRender
->refCount
= 1;
290 InitializeCriticalSection(&pDSoundRender
->csFilter
);
291 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSoundRenderImpl.csFilter");
292 pDSoundRender
->state
= State_Stopped
;
294 pDSoundRender
->ppPins
= CoTaskMemAlloc(1 * sizeof(IPin
*));
295 if (!pDSoundRender
->ppPins
)
297 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = 0;
298 DeleteCriticalSection(&pDSoundRender
->csFilter
);
299 CoTaskMemFree(pDSoundRender
);
300 return E_OUTOFMEMORY
;
303 /* construct input pin */
304 piInput
.dir
= PINDIR_INPUT
;
305 piInput
.pFilter
= (IBaseFilter
*)pDSoundRender
;
306 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
307 hr
= DSoundRender_InputPin_Construct(&piInput
, DSoundRender_Sample
, (LPVOID
)pDSoundRender
, DSoundRender_QueryAccept
, &pDSoundRender
->csFilter
, (IPin
**)&pDSoundRender
->pInputPin
);
311 hr
= DirectSoundCreate(NULL
, &pDSoundRender
->dsound
, NULL
);
313 ERR("Cannot create Direct Sound object (%x)\n", hr
);
318 pDSoundRender
->ppPins
[0] = (IPin
*)pDSoundRender
->pInputPin
;
319 *ppv
= (LPVOID
)pDSoundRender
;
323 if (pDSoundRender
->pInputPin
)
324 IPin_Release((IPin
*)pDSoundRender
->pInputPin
);
325 CoTaskMemFree(pDSoundRender
->ppPins
);
326 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = 0;
327 DeleteCriticalSection(&pDSoundRender
->csFilter
);
328 CoTaskMemFree(pDSoundRender
);
334 static HRESULT WINAPI
DSoundRender_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
336 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
337 TRACE("(%p, %p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
341 if (IsEqualIID(riid
, &IID_IUnknown
))
343 else if (IsEqualIID(riid
, &IID_IPersist
))
345 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
347 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
349 else if (IsEqualIID(riid
, &IID_IBasicAudio
))
350 *ppv
= (LPVOID
)&(This
->IBasicAudio_vtbl
);
351 else if (IsEqualIID(riid
, &IID_IReferenceClock
))
352 *ppv
= (LPVOID
)&(This
->IReferenceClock_vtbl
);
356 IUnknown_AddRef((IUnknown
*)(*ppv
));
360 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
362 return E_NOINTERFACE
;
365 static ULONG WINAPI
DSoundRender_AddRef(IBaseFilter
* iface
)
367 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
368 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
370 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
375 static ULONG WINAPI
DSoundRender_Release(IBaseFilter
* iface
)
377 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
378 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
380 TRACE("(%p)->() Release from %d\n", This
, refCount
+ 1);
387 IReferenceClock_Release(This
->pClock
);
390 IDirectSoundBuffer_Release(This
->dsbuffer
);
391 This
->dsbuffer
= NULL
;
393 IDirectSound_Release(This
->dsound
);
396 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[0], &pConnectedTo
)))
398 IPin_Disconnect(pConnectedTo
);
399 IPin_Release(pConnectedTo
);
401 IPin_Disconnect(This
->ppPins
[0]);
403 IPin_Release(This
->ppPins
[0]);
405 CoTaskMemFree(This
->ppPins
);
407 This
->IBasicAudio_vtbl
= NULL
;
409 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
410 DeleteCriticalSection(&This
->csFilter
);
412 TRACE("Destroying Audio Renderer\n");
421 /** IPersist methods **/
423 static HRESULT WINAPI
DSoundRender_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
425 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
426 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
428 *pClsid
= CLSID_DSoundRender
;
433 /** IMediaFilter methods **/
435 static HRESULT WINAPI
DSoundRender_Stop(IBaseFilter
* iface
)
438 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
440 TRACE("(%p/%p)->()\n", This
, iface
);
442 EnterCriticalSection(&This
->csFilter
);
447 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
450 if (state
& DSBSTATUS_PLAYING
)
451 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
455 This
->state
= State_Stopped
;
457 LeaveCriticalSection(&This
->csFilter
);
462 static HRESULT WINAPI
DSoundRender_Pause(IBaseFilter
* iface
)
465 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
467 TRACE("(%p/%p)->()\n", This
, iface
);
469 EnterCriticalSection(&This
->csFilter
);
474 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
477 if (state
& DSBSTATUS_PLAYING
)
478 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
482 This
->state
= State_Paused
;
484 LeaveCriticalSection(&This
->csFilter
);
489 static HRESULT WINAPI
DSoundRender_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
492 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
494 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
496 EnterCriticalSection(&This
->csFilter
);
498 /* It's okay if there's no buffer yet. It'll start when it's created */
501 hr
= IDirectSoundBuffer_Play(This
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
503 ERR("Can't start playing! (%x)\n", hr
);
507 This
->rtStreamStart
= tStart
;
508 This
->state
= State_Running
;
511 LeaveCriticalSection(&This
->csFilter
);
516 static HRESULT WINAPI
DSoundRender_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
518 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
520 TRACE("(%p/%p)->(%d, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
522 EnterCriticalSection(&This
->csFilter
);
524 *pState
= This
->state
;
526 LeaveCriticalSection(&This
->csFilter
);
531 static HRESULT WINAPI
DSoundRender_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
533 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
535 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
537 EnterCriticalSection(&This
->csFilter
);
540 IReferenceClock_Release(This
->pClock
);
541 This
->pClock
= pClock
;
543 IReferenceClock_AddRef(This
->pClock
);
545 LeaveCriticalSection(&This
->csFilter
);
550 static HRESULT WINAPI
DSoundRender_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
552 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
554 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
556 EnterCriticalSection(&This
->csFilter
);
558 *ppClock
= This
->pClock
;
559 IReferenceClock_AddRef(This
->pClock
);
561 LeaveCriticalSection(&This
->csFilter
);
566 /** IBaseFilter implementation **/
568 static HRESULT WINAPI
DSoundRender_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
571 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
573 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
575 epd
.cPins
= 1; /* input pin */
576 epd
.ppPins
= This
->ppPins
;
577 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
580 static HRESULT WINAPI
DSoundRender_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
582 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
584 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
586 FIXME("DSoundRender::FindPin(...)\n");
588 /* FIXME: critical section */
593 static HRESULT WINAPI
DSoundRender_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
595 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
597 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
599 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
600 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
603 IFilterGraph_AddRef(pInfo
->pGraph
);
608 static HRESULT WINAPI
DSoundRender_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
610 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
612 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
614 EnterCriticalSection(&This
->csFilter
);
617 strcpyW(This
->filterInfo
.achName
, pName
);
619 *This
->filterInfo
.achName
= '\0';
620 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
622 LeaveCriticalSection(&This
->csFilter
);
627 static HRESULT WINAPI
DSoundRender_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
629 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
630 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
634 static const IBaseFilterVtbl DSoundRender_Vtbl
=
636 DSoundRender_QueryInterface
,
638 DSoundRender_Release
,
639 DSoundRender_GetClassID
,
643 DSoundRender_GetState
,
644 DSoundRender_SetSyncSource
,
645 DSoundRender_GetSyncSource
,
646 DSoundRender_EnumPins
,
647 DSoundRender_FindPin
,
648 DSoundRender_QueryFilterInfo
,
649 DSoundRender_JoinFilterGraph
,
650 DSoundRender_QueryVendorInfo
653 static HRESULT WINAPI
DSoundRender_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
655 InputPin
*This
= (InputPin
*)iface
;
656 PIN_DIRECTION pindirReceive
;
657 DSoundRenderImpl
*DSImpl
;
660 TRACE("(%p)->(%p, %p)\n", This
, pReceivePin
, pmt
);
661 dump_AM_MEDIA_TYPE(pmt
);
663 EnterCriticalSection(This
->pin
.pCritSec
);
665 DSImpl
= (DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
;
667 if (This
->pin
.pConnectedTo
)
668 hr
= VFW_E_ALREADY_CONNECTED
;
670 if (SUCCEEDED(hr
) && This
->pin
.fnQueryAccept(This
->pin
.pUserData
, pmt
) != S_OK
)
671 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
675 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
677 if (pindirReceive
!= PINDIR_OUTPUT
)
679 ERR("Can't connect from non-output pin\n");
680 hr
= VFW_E_INVALID_DIRECTION
;
686 WAVEFORMATEX
*format
;
687 DSBUFFERDESC buf_desc
;
689 TRACE("MajorType %s\n", debugstr_guid(&pmt
->majortype
));
690 TRACE("SubType %s\n", debugstr_guid(&pmt
->subtype
));
691 TRACE("Format %s\n", debugstr_guid(&pmt
->formattype
));
692 TRACE("Size %d\n", pmt
->cbFormat
);
694 format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
696 DSImpl
->buf_size
= format
->nAvgBytesPerSec
;
698 memset(&buf_desc
,0,sizeof(DSBUFFERDESC
));
699 buf_desc
.dwSize
= sizeof(DSBUFFERDESC
);
700 buf_desc
.dwFlags
= DSBCAPS_CTRLVOLUME
| DSBCAPS_CTRLPAN
|
701 DSBCAPS_CTRLFREQUENCY
|
702 DSBCAPS_GETCURRENTPOSITION2
;
703 buf_desc
.dwBufferBytes
= DSImpl
->buf_size
;
704 buf_desc
.lpwfxFormat
= format
;
705 hr
= IDirectSound_CreateSoundBuffer(DSImpl
->dsound
, &buf_desc
, &DSImpl
->dsbuffer
, NULL
);
707 ERR("Can't create sound buffer (%x)\n", hr
);
712 hr
= IDirectSoundBuffer_SetVolume(DSImpl
->dsbuffer
, DSImpl
->volume
);
714 ERR("Can't set volume to %ld (%x)\n", DSImpl
->volume
, hr
);
716 hr
= IDirectSoundBuffer_SetPan(DSImpl
->dsbuffer
, DSImpl
->pan
);
718 ERR("Can't set pan to %ld (%x)\n", DSImpl
->pan
, hr
);
720 DSImpl
->write_pos
= 0;
722 if (DSImpl
->state
== State_Running
)
723 hr
= IDirectSoundBuffer_Play(DSImpl
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
725 ERR("Can't play sound buffer (%x)\n", hr
);
730 CopyMediaType(&This
->pin
.mtCurrent
, pmt
);
731 This
->pin
.pConnectedTo
= pReceivePin
;
732 IPin_AddRef(pReceivePin
);
736 if (DSImpl
->dsbuffer
)
737 IDirectSoundBuffer_Release(DSImpl
->dsbuffer
);
738 DSImpl
->dsbuffer
= NULL
;
741 LeaveCriticalSection(This
->pin
.pCritSec
);
746 static HRESULT WINAPI
DSoundRender_InputPin_Disconnect(IPin
* iface
)
748 IPinImpl
*This
= (IPinImpl
*)iface
;
749 DSoundRenderImpl
*DSImpl
;
751 TRACE("(%p)->()\n", iface
);
753 DSImpl
= (DSoundRenderImpl
*)This
->pinInfo
.pFilter
;
754 if (DSImpl
->dsbuffer
)
755 IDirectSoundBuffer_Release(DSImpl
->dsbuffer
);
756 DSImpl
->dsbuffer
= NULL
;
758 return IPinImpl_Disconnect(iface
);
761 static HRESULT WINAPI
DSoundRender_InputPin_EndOfStream(IPin
* iface
)
763 InputPin
* This
= (InputPin
*)iface
;
764 IMediaEventSink
* pEventSink
;
767 TRACE("(%p/%p)->()\n", This
, iface
);
769 hr
= IFilterGraph_QueryInterface(((DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
)->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
772 /* FIXME: We should wait that all audio data has been played */
773 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
774 IMediaEventSink_Release(pEventSink
);
780 static const IPinVtbl DSoundRender_InputPin_Vtbl
=
782 InputPin_QueryInterface
,
786 DSoundRender_InputPin_ReceiveConnection
,
787 DSoundRender_InputPin_Disconnect
,
788 IPinImpl_ConnectedTo
,
789 IPinImpl_ConnectionMediaType
,
790 IPinImpl_QueryPinInfo
,
791 IPinImpl_QueryDirection
,
793 IPinImpl_QueryAccept
,
794 IPinImpl_EnumMediaTypes
,
795 IPinImpl_QueryInternalConnections
,
796 DSoundRender_InputPin_EndOfStream
,
802 static const IMemInputPinVtbl MemInputPin_Vtbl
=
804 MemInputPin_QueryInterface
,
807 MemInputPin_GetAllocator
,
808 MemInputPin_NotifyAllocator
,
809 MemInputPin_GetAllocatorRequirements
,
811 MemInputPin_ReceiveMultiple
,
812 MemInputPin_ReceiveCanBlock
815 /*** IUnknown methods ***/
816 static HRESULT WINAPI
Basicaudio_QueryInterface(IBasicAudio
*iface
,
819 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
821 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
823 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
826 static ULONG WINAPI
Basicaudio_AddRef(IBasicAudio
*iface
) {
827 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
829 TRACE("(%p/%p)->()\n", This
, iface
);
831 return DSoundRender_AddRef((IBaseFilter
*)This
);
834 static ULONG WINAPI
Basicaudio_Release(IBasicAudio
*iface
) {
835 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
837 TRACE("(%p/%p)->()\n", This
, iface
);
839 return DSoundRender_Release((IBaseFilter
*)This
);
842 /*** IDispatch methods ***/
843 static HRESULT WINAPI
Basicaudio_GetTypeInfoCount(IBasicAudio
*iface
,
845 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
847 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, pctinfo
);
852 static HRESULT WINAPI
Basicaudio_GetTypeInfo(IBasicAudio
*iface
,
855 ITypeInfo
**ppTInfo
) {
856 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
858 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This
, iface
, iTInfo
, lcid
, ppTInfo
);
863 static HRESULT WINAPI
Basicaudio_GetIDsOfNames(IBasicAudio
*iface
,
869 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
871 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This
, iface
, debugstr_guid(riid
), riid
, rgszNames
, cNames
, lcid
, rgDispId
);
876 static HRESULT WINAPI
Basicaudio_Invoke(IBasicAudio
*iface
,
881 DISPPARAMS
*pDispParams
,
885 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
887 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
);
892 /*** IBasicAudio methods ***/
893 static HRESULT WINAPI
Basicaudio_put_Volume(IBasicAudio
*iface
,
895 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
897 TRACE("(%p/%p)->(%ld)\n", This
, iface
, lVolume
);
899 if (lVolume
> DSBVOLUME_MAX
|| lVolume
< DSBVOLUME_MIN
)
902 if (This
->dsbuffer
) {
903 if (FAILED(IDirectSoundBuffer_SetVolume(This
->dsbuffer
, lVolume
)))
907 This
->volume
= lVolume
;
911 static HRESULT WINAPI
Basicaudio_get_Volume(IBasicAudio
*iface
,
913 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
915 TRACE("(%p/%p)->(%p)\n", This
, iface
, plVolume
);
920 *plVolume
= This
->volume
;
924 static HRESULT WINAPI
Basicaudio_put_Balance(IBasicAudio
*iface
,
926 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
928 TRACE("(%p/%p)->(%ld)\n", This
, iface
, lBalance
);
930 if (lBalance
< DSBPAN_LEFT
|| lBalance
> DSBPAN_RIGHT
)
933 if (This
->dsbuffer
) {
934 if (FAILED(IDirectSoundBuffer_SetPan(This
->dsbuffer
, lBalance
)))
938 This
->pan
= lBalance
;
942 static HRESULT WINAPI
Basicaudio_get_Balance(IBasicAudio
*iface
,
944 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
946 TRACE("(%p/%p)->(%p)\n", This
, iface
, plBalance
);
951 *plBalance
= This
->pan
;
955 static const IBasicAudioVtbl IBasicAudio_Vtbl
=
957 Basicaudio_QueryInterface
,
960 Basicaudio_GetTypeInfoCount
,
961 Basicaudio_GetTypeInfo
,
962 Basicaudio_GetIDsOfNames
,
964 Basicaudio_put_Volume
,
965 Basicaudio_get_Volume
,
966 Basicaudio_put_Balance
,
967 Basicaudio_get_Balance
971 /*** IUnknown methods ***/
972 static HRESULT WINAPI
ReferenceClock_QueryInterface(IReferenceClock
*iface
,
976 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
978 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
980 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
983 static ULONG WINAPI
ReferenceClock_AddRef(IReferenceClock
*iface
)
985 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
987 TRACE("(%p/%p)->()\n", This
, iface
);
989 return DSoundRender_AddRef((IBaseFilter
*)This
);
992 static ULONG WINAPI
ReferenceClock_Release(IReferenceClock
*iface
)
994 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
996 TRACE("(%p/%p)->()\n", This
, iface
);
998 return DSoundRender_Release((IBaseFilter
*)This
);
1001 /*** IReferenceClock methods ***/
1002 static HRESULT WINAPI
ReferenceClock_GetTime(IReferenceClock
*iface
,
1003 REFERENCE_TIME
*pTime
)
1005 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1006 HRESULT hr
= E_FAIL
;
1009 TRACE("(%p/%p)->(%p)\n", This
, iface
, pTime
);
1012 hr
= DSoundRender_GetPos(This
, &play_pos
, NULL
, pTime
);
1014 ERR("Could not get refreence time (%x)!\n", hr
);
1019 static HRESULT WINAPI
ReferenceClock_AdviseTime(IReferenceClock
*iface
,
1020 REFERENCE_TIME rtBaseTime
,
1021 REFERENCE_TIME rtStreamTime
,
1023 DWORD_PTR
*pdwAdviseCookie
)
1025 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1027 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This
, iface
, wine_dbgstr_longlong(rtBaseTime
), wine_dbgstr_longlong(rtStreamTime
), (void*)hEvent
, pdwAdviseCookie
);
1032 static HRESULT WINAPI
ReferenceClock_AdvisePeriodic(IReferenceClock
*iface
,
1033 REFERENCE_TIME rtBaseTime
,
1034 REFERENCE_TIME rtStreamTime
,
1035 HSEMAPHORE hSemaphore
,
1036 DWORD_PTR
*pdwAdviseCookie
)
1038 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1040 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This
, iface
, wine_dbgstr_longlong(rtBaseTime
), wine_dbgstr_longlong(rtStreamTime
), (void*)hSemaphore
, pdwAdviseCookie
);
1045 static HRESULT WINAPI
ReferenceClock_Unadvise(IReferenceClock
*iface
,
1046 DWORD_PTR dwAdviseCookie
)
1048 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1050 FIXME("(%p/%p)->(%p): stub!\n", This
, iface
, (void*)dwAdviseCookie
);
1055 static const IReferenceClockVtbl IReferenceClock_Vtbl
=
1057 ReferenceClock_QueryInterface
,
1058 ReferenceClock_AddRef
,
1059 ReferenceClock_Release
,
1060 ReferenceClock_GetTime
,
1061 ReferenceClock_AdviseTime
,
1062 ReferenceClock_AdvisePeriodic
,
1063 ReferenceClock_Unadvise