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"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
42 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
44 static const IBaseFilterVtbl DSoundRender_Vtbl
;
45 static const IPinVtbl DSoundRender_InputPin_Vtbl
;
46 static const IBasicAudioVtbl IBasicAudio_Vtbl
;
47 static const IReferenceClockVtbl IReferenceClock_Vtbl
;
48 static const IMediaSeekingVtbl IMediaSeeking_Vtbl
;
49 static const IAMDirectSoundVtbl IAMDirectSound_Vtbl
;
51 typedef struct DSoundRenderImpl
53 const IBaseFilterVtbl
* lpVtbl
;
54 const IBasicAudioVtbl
*IBasicAudio_vtbl
;
55 const IReferenceClockVtbl
*IReferenceClock_vtbl
;
56 const IAMDirectSoundVtbl
*IAMDirectSound_vtbl
;
59 CRITICAL_SECTION csFilter
;
61 REFERENCE_TIME rtStreamStart
, rtLastStop
;
62 IReferenceClock
* pClock
;
63 FILTER_INFO filterInfo
;
67 IDirectSound8
*dsound
;
68 LPDIRECTSOUNDBUFFER dsbuffer
;
77 REFERENCE_TIME play_time
;
78 MediaSeekingImpl mediaSeeking
;
80 HANDLE state_change
, blocked
;
86 /* Seeking is not needed for a renderer, rely on newsegment for the appropriate changes */
87 static HRESULT
sound_mod_stop(IBaseFilter
*iface
)
89 TRACE("(%p)\n", iface
);
93 static HRESULT
sound_mod_start(IBaseFilter
*iface
)
95 TRACE("(%p)\n", iface
);
100 static HRESULT
sound_mod_rate(IBaseFilter
*iface
)
102 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
104 WAVEFORMATEX
*format
= (WAVEFORMATEX
*)This
->pInputPin
->pin
.mtCurrent
.pbFormat
;
105 DWORD freq
= format
->nSamplesPerSec
;
106 double rate
= This
->mediaSeeking
.dRate
;
108 freq
= (DWORD
)((double)freq
* rate
);
110 TRACE("(%p)\n", iface
);
112 if (freq
> DSBFREQUENCY_MAX
)
113 return VFW_E_UNSUPPORTED_AUDIO
;
115 if (freq
< DSBFREQUENCY_MIN
)
116 return VFW_E_UNSUPPORTED_AUDIO
;
121 static inline HRESULT
DSoundRender_GetPos(DSoundRenderImpl
*This
, DWORD
*pPlayPos
, REFERENCE_TIME
*pRefTime
)
125 EnterCriticalSection(&This
->csFilter
);
130 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
131 if (SUCCEEDED(hr
) && !(state
& DSBSTATUS_PLAYING
) && This
->state
== State_Running
)
133 TRACE("Not playing, kickstarting the engine\n");
135 hr
= IDirectSoundBuffer_Play(This
->dsbuffer
, 0, 0, DSBPLAY_LOOPING
);
137 ERR("Can't play sound buffer (%x)\n", hr
);
141 hr
= IDirectSoundBuffer_GetCurrentPosition(This
->dsbuffer
, pPlayPos
, &write_pos
);
144 DWORD play_pos
= *pPlayPos
;
146 if (play_pos
< This
->last_play_pos
)
148 This
->last_play_pos
= play_pos
;
150 /* If we really fell behind, start at the next possible position
151 * Also happens when just starting playback for the first time,
154 if ((This
->play_loops
*This
->buf_size
)+play_pos
>=
155 (This
->write_loops
*This
->buf_size
)+This
->write_pos
)
156 This
->write_pos
= write_pos
;
160 REFERENCE_TIME play_time
;
161 play_time
= ((REFERENCE_TIME
)This
->play_loops
*10000000) +
162 ((REFERENCE_TIME
)play_pos
*10000000/This
->buf_size
);
164 /* Don't let time run backwards */
165 if(play_time
-This
->play_time
> 0)
166 This
->play_time
= play_time
;
170 *pRefTime
= This
->play_time
;
174 LeaveCriticalSection(&This
->csFilter
);
179 static HRESULT
DSoundRender_SendSampleData(DSoundRenderImpl
* This
, const BYTE
*data
, DWORD size
)
182 LPBYTE lpbuf1
= NULL
;
183 LPBYTE lpbuf2
= NULL
;
187 DWORD play_pos
,buf_free
;
191 hr
= DSoundRender_GetPos(This
, &play_pos
, NULL
);
194 ERR("GetPos returned error: %x\n", hr
);
197 if (This
->write_pos
<= play_pos
)
198 buf_free
= play_pos
-This
->write_pos
;
200 buf_free
= This
->buf_size
- This
->write_pos
+ play_pos
;
202 /* Wait for enough of the buffer to empty before filling it */
203 if(buf_free
< This
->buf_size
/20)
207 LeaveCriticalSection(&This
->csFilter
);
208 ret
= WaitForSingleObject(This
->blocked
, 50);
209 if (ret
!= WAIT_TIMEOUT
)
211 EnterCriticalSection(&This
->csFilter
);
213 if (This
->pInputPin
->flushing
)
214 return VFW_E_WRONG_STATE
;
215 if (This
->state
== State_Stopped
)
216 return VFW_E_WRONG_STATE
;
220 size2
= min(buf_free
, size
);
221 hr
= IDirectSoundBuffer_Lock(This
->dsbuffer
, This
->write_pos
, size2
, (LPVOID
*)&lpbuf1
, &dwsize1
, (LPVOID
*)&lpbuf2
, &dwsize2
, 0);
223 ERR("Unable to lock sound buffer! (%x)\n", hr
);
226 /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */
228 memcpy(lpbuf1
, data
, dwsize1
);
230 memcpy(lpbuf2
, data
+ dwsize1
, dwsize2
);
232 hr
= IDirectSoundBuffer_Unlock(This
->dsbuffer
, lpbuf1
, dwsize1
, lpbuf2
, dwsize2
);
234 ERR("Unable to unlock sound buffer! (%x)\n", hr
);
236 size
-= dwsize1
+ dwsize2
;
237 data
+= dwsize1
+ dwsize2
;
238 This
->write_pos
+= dwsize1
+ dwsize2
;
239 if (This
->write_pos
>= This
->buf_size
)
241 This
->write_pos
-= This
->buf_size
;
244 } while (size
&& This
->state
== State_Running
);
249 static HRESULT
DSoundRender_Sample(LPVOID iface
, IMediaSample
* pSample
)
251 DSoundRenderImpl
*This
= iface
;
252 LPBYTE pbSrcStream
= NULL
;
253 LONG cbSrcStream
= 0;
254 REFERENCE_TIME tStart
, tStop
;
258 TRACE("%p %p\n", iface
, pSample
);
260 /* Slightly incorrect, Pause completes when a frame is received so we should signal
261 * pause completion here, but for sound playing a single frame doesn't make sense
264 EnterCriticalSection(&This
->csFilter
);
266 if (This
->pInputPin
->end_of_stream
|| This
->pInputPin
->flushing
)
268 LeaveCriticalSection(&This
->csFilter
);
272 if (This
->state
== State_Stopped
)
274 LeaveCriticalSection(&This
->csFilter
);
275 return VFW_E_WRONG_STATE
;
278 if (IMediaSample_GetMediaType(pSample
, &amt
) == S_OK
)
280 AM_MEDIA_TYPE
*orig
= &This
->pInputPin
->pin
.mtCurrent
;
281 WAVEFORMATEX
*origfmt
= (WAVEFORMATEX
*)orig
->pbFormat
;
282 WAVEFORMATEX
*newfmt
= (WAVEFORMATEX
*)amt
->pbFormat
;
284 if (origfmt
->wFormatTag
== newfmt
->wFormatTag
&&
285 origfmt
->nChannels
== newfmt
->nChannels
&&
286 origfmt
->nBlockAlign
== newfmt
->nBlockAlign
&&
287 origfmt
->wBitsPerSample
== newfmt
->wBitsPerSample
&&
288 origfmt
->cbSize
== newfmt
->cbSize
)
290 if (origfmt
->nSamplesPerSec
!= newfmt
->nSamplesPerSec
)
292 hr
= IDirectSoundBuffer_SetFrequency(This
->dsbuffer
,
293 newfmt
->nSamplesPerSec
);
296 LeaveCriticalSection(&This
->csFilter
);
297 return VFW_E_TYPE_NOT_ACCEPTED
;
300 CopyMediaType(orig
, amt
);
301 IMediaSample_SetMediaType(pSample
, NULL
);
306 LeaveCriticalSection(&This
->csFilter
);
307 return VFW_E_TYPE_NOT_ACCEPTED
;
311 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
314 ERR("Cannot get pointer to sample data (%x)\n", hr
);
315 LeaveCriticalSection(&This
->csFilter
);
319 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
321 ERR("Cannot get sample time (%x)\n", hr
);
323 if (This
->rtLastStop
!= tStart
&& (IMediaSample_IsDiscontinuity(pSample
) == S_FALSE
))
324 WARN("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n",
325 (DWORD
)(This
->rtLastStop
/ 10000000), (DWORD
)((This
->rtLastStop
/ 10000)%1000),
326 (DWORD
)(tStart
/ 10000000), (DWORD
)((tStart
/ 10000)%1000));
327 This
->rtLastStop
= tStop
;
329 if (IMediaSample_IsPreroll(pSample
) == S_OK
)
332 LeaveCriticalSection(&This
->csFilter
);
336 if (This
->state
== State_Paused
)
338 SetEvent(This
->state_change
);
339 LeaveCriticalSection(&This
->csFilter
);
340 WaitForSingleObject(This
->blocked
, INFINITE
);
341 EnterCriticalSection(&This
->csFilter
);
342 if (This
->state
== State_Stopped
)
344 LeaveCriticalSection(&This
->csFilter
);
345 return VFW_E_WRONG_STATE
;
348 if (This
->state
== State_Paused
)
350 /* Assuming we return because of flushing */
352 LeaveCriticalSection(&This
->csFilter
);
357 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
358 TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream
, cbSrcStream
);
360 #if 0 /* For debugging purpose */
363 for(i
= 0; i
< cbSrcStream
; i
++)
365 if ((i
!=0) && !(i
%16))
367 TRACE("%02x ", pbSrcStream
[i
]);
373 hr
= DSoundRender_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
374 SetEvent(This
->state_change
);
375 LeaveCriticalSection(&This
->csFilter
);
379 static HRESULT
DSoundRender_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
381 WAVEFORMATEX
* format
;
383 if (!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
))
386 format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
387 TRACE("Format = %p\n", format
);
388 TRACE("wFormatTag = %x %x\n", format
->wFormatTag
, WAVE_FORMAT_PCM
);
389 TRACE("nChannels = %d\n", format
->nChannels
);
390 TRACE("nSamplesPerSec = %d\n", format
->nAvgBytesPerSec
);
391 TRACE("nAvgBytesPerSec = %d\n", format
->nAvgBytesPerSec
);
392 TRACE("nBlockAlign = %d\n", format
->nBlockAlign
);
393 TRACE("wBitsPerSample = %d\n", format
->wBitsPerSample
);
395 if (!IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
401 HRESULT
DSoundRender_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
405 DSoundRenderImpl
* pDSoundRender
;
407 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
412 return CLASS_E_NOAGGREGATION
;
414 pDSoundRender
= CoTaskMemAlloc(sizeof(DSoundRenderImpl
));
416 return E_OUTOFMEMORY
;
417 ZeroMemory(pDSoundRender
, sizeof(DSoundRenderImpl
));
419 pDSoundRender
->lpVtbl
= &DSoundRender_Vtbl
;
420 pDSoundRender
->IBasicAudio_vtbl
= &IBasicAudio_Vtbl
;
421 pDSoundRender
->IReferenceClock_vtbl
= &IReferenceClock_Vtbl
;
422 pDSoundRender
->IAMDirectSound_vtbl
= &IAMDirectSound_Vtbl
;
423 pDSoundRender
->refCount
= 1;
424 InitializeCriticalSection(&pDSoundRender
->csFilter
);
425 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSoundRenderImpl.csFilter");
426 pDSoundRender
->state
= State_Stopped
;
428 /* construct input pin */
429 piInput
.dir
= PINDIR_INPUT
;
430 piInput
.pFilter
= (IBaseFilter
*)pDSoundRender
;
431 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
432 hr
= InputPin_Construct(&DSoundRender_InputPin_Vtbl
, &piInput
, DSoundRender_Sample
, pDSoundRender
, DSoundRender_QueryAccept
, NULL
, &pDSoundRender
->csFilter
, NULL
, (IPin
**)&pDSoundRender
->pInputPin
);
436 hr
= DirectSoundCreate8(NULL
, &pDSoundRender
->dsound
, NULL
);
438 ERR("Cannot create Direct Sound object (%x)\n", hr
);
440 IDirectSound_SetCooperativeLevel(pDSoundRender
->dsound
, GetDesktopWindow(), DSSCL_PRIORITY
);
445 MediaSeekingImpl_Init((IBaseFilter
*)pDSoundRender
, sound_mod_stop
, sound_mod_start
, sound_mod_rate
, &pDSoundRender
->mediaSeeking
, &pDSoundRender
->csFilter
);
446 pDSoundRender
->mediaSeeking
.lpVtbl
= &IMediaSeeking_Vtbl
;
448 pDSoundRender
->state_change
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
449 pDSoundRender
->blocked
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
451 if (!pDSoundRender
->state_change
|| !pDSoundRender
->blocked
)
453 IUnknown_Release((IUnknown
*)pDSoundRender
);
454 return HRESULT_FROM_WIN32(GetLastError());
457 *ppv
= pDSoundRender
;
461 if (pDSoundRender
->pInputPin
)
462 IPin_Release((IPin
*)pDSoundRender
->pInputPin
);
463 pDSoundRender
->csFilter
.DebugInfo
->Spare
[0] = 0;
464 DeleteCriticalSection(&pDSoundRender
->csFilter
);
465 CoTaskMemFree(pDSoundRender
);
471 static HRESULT WINAPI
DSoundRender_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
473 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
474 TRACE("(%p, %p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
478 if (IsEqualIID(riid
, &IID_IUnknown
))
480 else if (IsEqualIID(riid
, &IID_IPersist
))
482 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
484 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
486 else if (IsEqualIID(riid
, &IID_IBasicAudio
))
487 *ppv
= &This
->IBasicAudio_vtbl
;
488 else if (IsEqualIID(riid
, &IID_IReferenceClock
))
489 *ppv
= &This
->IReferenceClock_vtbl
;
490 else if (IsEqualIID(riid
, &IID_IMediaSeeking
))
491 *ppv
= &This
->mediaSeeking
.lpVtbl
;
492 else if (IsEqualIID(riid
, &IID_IAMDirectSound
))
493 *ppv
= &This
->IAMDirectSound_vtbl
;
497 IUnknown_AddRef((IUnknown
*)(*ppv
));
501 if (!IsEqualIID(riid
, &IID_IPin
) && !IsEqualIID(riid
, &IID_IVideoWindow
))
502 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
504 return E_NOINTERFACE
;
507 static ULONG WINAPI
DSoundRender_AddRef(IBaseFilter
* iface
)
509 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
510 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
512 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
517 static ULONG WINAPI
DSoundRender_Release(IBaseFilter
* iface
)
519 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
520 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
522 TRACE("(%p)->() Release from %d\n", This
, refCount
+ 1);
529 IReferenceClock_Release(This
->pClock
);
532 IDirectSoundBuffer_Release(This
->dsbuffer
);
533 This
->dsbuffer
= NULL
;
535 IDirectSound_Release(This
->dsound
);
538 if (SUCCEEDED(IPin_ConnectedTo((IPin
*)This
->pInputPin
, &pConnectedTo
)))
540 IPin_Disconnect(pConnectedTo
);
541 IPin_Release(pConnectedTo
);
543 IPin_Disconnect((IPin
*)This
->pInputPin
);
545 IPin_Release((IPin
*)This
->pInputPin
);
548 This
->IBasicAudio_vtbl
= NULL
;
550 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
551 DeleteCriticalSection(&This
->csFilter
);
553 CloseHandle(This
->state_change
);
554 CloseHandle(This
->blocked
);
556 TRACE("Destroying Audio Renderer\n");
565 /** IPersist methods **/
567 static HRESULT WINAPI
DSoundRender_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
569 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
570 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
572 *pClsid
= CLSID_DSoundRender
;
577 /** IMediaFilter methods **/
579 static HRESULT WINAPI
DSoundRender_Stop(IBaseFilter
* iface
)
582 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
584 TRACE("(%p/%p)->()\n", This
, iface
);
586 EnterCriticalSection(&This
->csFilter
);
591 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
594 if (state
& DSBSTATUS_PLAYING
)
595 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
599 This
->state
= State_Stopped
;
601 /* Complete our transition */
602 SetEvent(This
->state_change
);
603 SetEvent(This
->blocked
);
605 LeaveCriticalSection(&This
->csFilter
);
610 static HRESULT WINAPI
DSoundRender_Pause(IBaseFilter
* iface
)
613 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
615 TRACE("(%p/%p)->()\n", This
, iface
);
617 EnterCriticalSection(&This
->csFilter
);
618 if (This
->state
!= State_Paused
)
621 if (This
->state
== State_Stopped
)
623 This
->pInputPin
->end_of_stream
= 0;
628 hr
= IDirectSoundBuffer_GetStatus(This
->dsbuffer
, &state
);
631 if (state
& DSBSTATUS_PLAYING
)
632 hr
= IDirectSoundBuffer_Stop(This
->dsbuffer
);
636 This
->state
= State_Paused
;
638 ResetEvent(This
->blocked
);
639 ResetEvent(This
->state_change
);
641 LeaveCriticalSection(&This
->csFilter
);
646 static HRESULT WINAPI
DSoundRender_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
649 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
651 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
653 EnterCriticalSection(&This
->csFilter
);
655 This
->rtStreamStart
= tStart
;
656 if (This
->state
== State_Paused
)
658 /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */
659 SetEvent(This
->blocked
);
661 else if (This
->state
== State_Stopped
)
663 ResetEvent(This
->state_change
);
664 This
->pInputPin
->end_of_stream
= 0;
666 ResetEvent(This
->blocked
);
668 This
->state
= State_Running
;
670 LeaveCriticalSection(&This
->csFilter
);
675 static HRESULT WINAPI
DSoundRender_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
678 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
680 TRACE("(%p/%p)->(%d, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
682 if (WaitForSingleObject(This
->state_change
, dwMilliSecsTimeout
) == WAIT_TIMEOUT
)
683 hr
= VFW_S_STATE_INTERMEDIATE
;
687 EnterCriticalSection(&This
->csFilter
);
689 *pState
= This
->state
;
691 LeaveCriticalSection(&This
->csFilter
);
696 static HRESULT WINAPI
DSoundRender_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
698 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
700 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
702 EnterCriticalSection(&This
->csFilter
);
705 IReferenceClock_Release(This
->pClock
);
706 This
->pClock
= pClock
;
708 IReferenceClock_AddRef(This
->pClock
);
710 LeaveCriticalSection(&This
->csFilter
);
715 static HRESULT WINAPI
DSoundRender_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
717 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
719 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
721 EnterCriticalSection(&This
->csFilter
);
723 *ppClock
= This
->pClock
;
725 IReferenceClock_AddRef(This
->pClock
);
727 LeaveCriticalSection(&This
->csFilter
);
732 /** IBaseFilter implementation **/
734 static HRESULT
DSoundRender_GetPin(IBaseFilter
*iface
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
736 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
738 /* Our pins are static, not changing so setting static tick count is ok */
744 *pin
= (IPin
*)This
->pInputPin
;
749 static HRESULT WINAPI
DSoundRender_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
751 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
753 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
755 return IEnumPinsImpl_Construct(ppEnum
, DSoundRender_GetPin
, iface
);
758 static HRESULT WINAPI
DSoundRender_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
760 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
762 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
764 FIXME("DSoundRender::FindPin(...)\n");
766 /* FIXME: critical section */
771 static HRESULT WINAPI
DSoundRender_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
773 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
775 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
777 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
778 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
781 IFilterGraph_AddRef(pInfo
->pGraph
);
786 static HRESULT WINAPI
DSoundRender_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
788 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
790 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
792 EnterCriticalSection(&This
->csFilter
);
795 strcpyW(This
->filterInfo
.achName
, pName
);
797 *This
->filterInfo
.achName
= '\0';
798 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
800 LeaveCriticalSection(&This
->csFilter
);
805 static HRESULT WINAPI
DSoundRender_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
807 DSoundRenderImpl
*This
= (DSoundRenderImpl
*)iface
;
808 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
812 static const IBaseFilterVtbl DSoundRender_Vtbl
=
814 DSoundRender_QueryInterface
,
816 DSoundRender_Release
,
817 DSoundRender_GetClassID
,
821 DSoundRender_GetState
,
822 DSoundRender_SetSyncSource
,
823 DSoundRender_GetSyncSource
,
824 DSoundRender_EnumPins
,
825 DSoundRender_FindPin
,
826 DSoundRender_QueryFilterInfo
,
827 DSoundRender_JoinFilterGraph
,
828 DSoundRender_QueryVendorInfo
831 static HRESULT WINAPI
DSoundRender_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
833 InputPin
*This
= (InputPin
*)iface
;
834 PIN_DIRECTION pindirReceive
;
835 DSoundRenderImpl
*DSImpl
;
838 TRACE("(%p)->(%p, %p)\n", This
, pReceivePin
, pmt
);
839 dump_AM_MEDIA_TYPE(pmt
);
841 EnterCriticalSection(This
->pin
.pCritSec
);
843 DSImpl
= (DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
;
844 DSImpl
->rtLastStop
= -1;
846 if (This
->pin
.pConnectedTo
)
847 hr
= VFW_E_ALREADY_CONNECTED
;
849 if (SUCCEEDED(hr
) && This
->pin
.fnQueryAccept(This
->pin
.pUserData
, pmt
) != S_OK
)
850 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
854 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
856 if (pindirReceive
!= PINDIR_OUTPUT
)
858 ERR("Can't connect from non-output pin\n");
859 hr
= VFW_E_INVALID_DIRECTION
;
865 WAVEFORMATEX
*format
;
866 DSBUFFERDESC buf_desc
;
868 TRACE("MajorType %s\n", debugstr_guid(&pmt
->majortype
));
869 TRACE("SubType %s\n", debugstr_guid(&pmt
->subtype
));
870 TRACE("Format %s\n", debugstr_guid(&pmt
->formattype
));
871 TRACE("Size %d\n", pmt
->cbFormat
);
873 format
= (WAVEFORMATEX
*)pmt
->pbFormat
;
875 DSImpl
->buf_size
= format
->nAvgBytesPerSec
;
877 memset(&buf_desc
,0,sizeof(DSBUFFERDESC
));
878 buf_desc
.dwSize
= sizeof(DSBUFFERDESC
);
879 buf_desc
.dwFlags
= DSBCAPS_CTRLVOLUME
| DSBCAPS_CTRLPAN
|
880 DSBCAPS_CTRLFREQUENCY
|
881 DSBCAPS_GETCURRENTPOSITION2
;
882 buf_desc
.dwBufferBytes
= DSImpl
->buf_size
;
883 buf_desc
.lpwfxFormat
= format
;
884 hr
= IDirectSound_CreateSoundBuffer(DSImpl
->dsound
, &buf_desc
, &DSImpl
->dsbuffer
, NULL
);
886 ERR("Can't create sound buffer (%x)\n", hr
);
891 hr
= IDirectSoundBuffer_SetVolume(DSImpl
->dsbuffer
, DSImpl
->volume
);
893 ERR("Can't set volume to %d (%x)\n", DSImpl
->volume
, hr
);
895 hr
= IDirectSoundBuffer_SetPan(DSImpl
->dsbuffer
, DSImpl
->pan
);
897 ERR("Can't set pan to %d (%x)\n", DSImpl
->pan
, hr
);
899 DSImpl
->write_pos
= 0;
905 CopyMediaType(&This
->pin
.mtCurrent
, pmt
);
906 This
->pin
.pConnectedTo
= pReceivePin
;
907 IPin_AddRef(pReceivePin
);
909 else if (hr
!= VFW_E_ALREADY_CONNECTED
)
911 if (DSImpl
->dsbuffer
)
912 IDirectSoundBuffer_Release(DSImpl
->dsbuffer
);
913 DSImpl
->dsbuffer
= NULL
;
916 LeaveCriticalSection(This
->pin
.pCritSec
);
921 static HRESULT WINAPI
DSoundRender_InputPin_Disconnect(IPin
* iface
)
923 IPinImpl
*This
= (IPinImpl
*)iface
;
924 DSoundRenderImpl
*DSImpl
;
926 TRACE("(%p)->()\n", iface
);
928 DSImpl
= (DSoundRenderImpl
*)This
->pinInfo
.pFilter
;
929 if (DSImpl
->dsbuffer
)
930 IDirectSoundBuffer_Release(DSImpl
->dsbuffer
);
931 DSImpl
->dsbuffer
= NULL
;
933 return IPinImpl_Disconnect(iface
);
936 static HRESULT WINAPI
DSoundRender_InputPin_EndOfStream(IPin
* iface
)
938 InputPin
* This
= (InputPin
*)iface
;
939 DSoundRenderImpl
*me
= (DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
;
940 IMediaEventSink
* pEventSink
;
943 EnterCriticalSection(This
->pin
.pCritSec
);
945 TRACE("(%p/%p)->()\n", This
, iface
);
946 hr
= InputPin_EndOfStream(iface
);
950 LeaveCriticalSection(This
->pin
.pCritSec
);
954 hr
= IFilterGraph_QueryInterface(me
->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
959 silence
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, me
->buf_size
);
962 memset(silence
, 0, me
->buf_size
);
963 DSoundRender_SendSampleData((DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
, silence
, me
->buf_size
);
964 HeapFree(GetProcessHeap(), 0, silence
);
967 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
968 IMediaEventSink_Release(pEventSink
);
970 LeaveCriticalSection(This
->pin
.pCritSec
);
975 static HRESULT WINAPI
DSoundRender_InputPin_BeginFlush(IPin
* iface
)
977 InputPin
*This
= (InputPin
*)iface
;
978 DSoundRenderImpl
*pFilter
= (DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
;
983 EnterCriticalSection(This
->pin
.pCritSec
);
984 hr
= InputPin_BeginFlush(iface
);
985 SetEvent(pFilter
->blocked
);
986 LeaveCriticalSection(This
->pin
.pCritSec
);
991 static HRESULT WINAPI
DSoundRender_InputPin_EndFlush(IPin
* iface
)
993 InputPin
*This
= (InputPin
*)iface
;
994 DSoundRenderImpl
*pFilter
= (DSoundRenderImpl
*)This
->pin
.pinInfo
.pFilter
;
999 EnterCriticalSection(This
->pin
.pCritSec
);
1000 if (pFilter
->in_loop
) {
1001 ResetEvent(pFilter
->state_change
);
1002 LeaveCriticalSection(This
->pin
.pCritSec
);
1003 WaitForSingleObject(pFilter
->state_change
, -1);
1004 EnterCriticalSection(This
->pin
.pCritSec
);
1006 if (pFilter
->state
!= State_Stopped
)
1007 ResetEvent(pFilter
->blocked
);
1009 if (pFilter
->dsbuffer
)
1013 IDirectSoundBuffer_Stop(pFilter
->dsbuffer
);
1016 IDirectSoundBuffer_SetCurrentPosition(pFilter
->dsbuffer
, 0);
1017 pFilter
->write_pos
= pFilter
->last_play_pos
= 0;
1018 ++pFilter
->play_loops
;
1019 pFilter
->write_loops
= pFilter
->play_loops
;
1021 IDirectSoundBuffer_Lock(pFilter
->dsbuffer
, 0, 0, (LPVOID
*)&buffer
, &size
, NULL
, NULL
, DSBLOCK_ENTIREBUFFER
);
1022 memset(buffer
, 0, size
);
1023 IDirectSoundBuffer_Unlock(pFilter
->dsbuffer
, buffer
, size
, NULL
, 0);
1025 hr
= InputPin_EndFlush(iface
);
1026 LeaveCriticalSection(This
->pin
.pCritSec
);
1031 static const IPinVtbl DSoundRender_InputPin_Vtbl
=
1033 InputPin_QueryInterface
,
1037 DSoundRender_InputPin_ReceiveConnection
,
1038 DSoundRender_InputPin_Disconnect
,
1039 IPinImpl_ConnectedTo
,
1040 IPinImpl_ConnectionMediaType
,
1041 IPinImpl_QueryPinInfo
,
1042 IPinImpl_QueryDirection
,
1044 IPinImpl_QueryAccept
,
1045 IPinImpl_EnumMediaTypes
,
1046 IPinImpl_QueryInternalConnections
,
1047 DSoundRender_InputPin_EndOfStream
,
1048 DSoundRender_InputPin_BeginFlush
,
1049 DSoundRender_InputPin_EndFlush
,
1053 /*** IUnknown methods ***/
1054 static HRESULT WINAPI
Basicaudio_QueryInterface(IBasicAudio
*iface
,
1057 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1059 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
1061 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
1064 static ULONG WINAPI
Basicaudio_AddRef(IBasicAudio
*iface
) {
1065 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1067 TRACE("(%p/%p)->()\n", This
, iface
);
1069 return DSoundRender_AddRef((IBaseFilter
*)This
);
1072 static ULONG WINAPI
Basicaudio_Release(IBasicAudio
*iface
) {
1073 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1075 TRACE("(%p/%p)->()\n", This
, iface
);
1077 return DSoundRender_Release((IBaseFilter
*)This
);
1080 /*** IDispatch methods ***/
1081 static HRESULT WINAPI
Basicaudio_GetTypeInfoCount(IBasicAudio
*iface
,
1083 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1085 TRACE("(%p/%p)->(%p): stub !!!\n", This
, iface
, pctinfo
);
1090 static HRESULT WINAPI
Basicaudio_GetTypeInfo(IBasicAudio
*iface
,
1093 ITypeInfo
**ppTInfo
) {
1094 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1096 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This
, iface
, iTInfo
, lcid
, ppTInfo
);
1101 static HRESULT WINAPI
Basicaudio_GetIDsOfNames(IBasicAudio
*iface
,
1107 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1109 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This
, iface
, debugstr_guid(riid
), riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1114 static HRESULT WINAPI
Basicaudio_Invoke(IBasicAudio
*iface
,
1115 DISPID dispIdMember
,
1119 DISPPARAMS
*pDispParams
,
1121 EXCEPINFO
*pExepInfo
,
1123 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1125 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
);
1130 /*** IBasicAudio methods ***/
1131 static HRESULT WINAPI
Basicaudio_put_Volume(IBasicAudio
*iface
,
1133 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1135 TRACE("(%p/%p)->(%d)\n", This
, iface
, lVolume
);
1137 if (lVolume
> DSBVOLUME_MAX
|| lVolume
< DSBVOLUME_MIN
)
1138 return E_INVALIDARG
;
1140 if (This
->dsbuffer
) {
1141 if (FAILED(IDirectSoundBuffer_SetVolume(This
->dsbuffer
, lVolume
)))
1145 This
->volume
= lVolume
;
1149 static HRESULT WINAPI
Basicaudio_get_Volume(IBasicAudio
*iface
,
1151 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1153 TRACE("(%p/%p)->(%p)\n", This
, iface
, plVolume
);
1158 *plVolume
= This
->volume
;
1162 static HRESULT WINAPI
Basicaudio_put_Balance(IBasicAudio
*iface
,
1164 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1166 TRACE("(%p/%p)->(%d)\n", This
, iface
, lBalance
);
1168 if (lBalance
< DSBPAN_LEFT
|| lBalance
> DSBPAN_RIGHT
)
1169 return E_INVALIDARG
;
1171 if (This
->dsbuffer
) {
1172 if (FAILED(IDirectSoundBuffer_SetPan(This
->dsbuffer
, lBalance
)))
1176 This
->pan
= lBalance
;
1180 static HRESULT WINAPI
Basicaudio_get_Balance(IBasicAudio
*iface
,
1182 ICOM_THIS_MULTI(DSoundRenderImpl
, IBasicAudio_vtbl
, iface
);
1184 TRACE("(%p/%p)->(%p)\n", This
, iface
, plBalance
);
1189 *plBalance
= This
->pan
;
1193 static const IBasicAudioVtbl IBasicAudio_Vtbl
=
1195 Basicaudio_QueryInterface
,
1198 Basicaudio_GetTypeInfoCount
,
1199 Basicaudio_GetTypeInfo
,
1200 Basicaudio_GetIDsOfNames
,
1202 Basicaudio_put_Volume
,
1203 Basicaudio_get_Volume
,
1204 Basicaudio_put_Balance
,
1205 Basicaudio_get_Balance
1209 /*** IUnknown methods ***/
1210 static HRESULT WINAPI
ReferenceClock_QueryInterface(IReferenceClock
*iface
,
1214 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1216 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
1218 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
1221 static ULONG WINAPI
ReferenceClock_AddRef(IReferenceClock
*iface
)
1223 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1225 TRACE("(%p/%p)->()\n", This
, iface
);
1227 return DSoundRender_AddRef((IBaseFilter
*)This
);
1230 static ULONG WINAPI
ReferenceClock_Release(IReferenceClock
*iface
)
1232 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1234 TRACE("(%p/%p)->()\n", This
, iface
);
1236 return DSoundRender_Release((IBaseFilter
*)This
);
1239 /*** IReferenceClock methods ***/
1240 static HRESULT WINAPI
ReferenceClock_GetTime(IReferenceClock
*iface
,
1241 REFERENCE_TIME
*pTime
)
1243 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1244 HRESULT hr
= E_FAIL
;
1247 TRACE("(%p/%p)->(%p)\n", This
, iface
, pTime
);
1250 hr
= DSoundRender_GetPos(This
, &play_pos
, pTime
);
1252 ERR("Could not get reference time (%x)!\n", hr
);
1257 static HRESULT WINAPI
ReferenceClock_AdviseTime(IReferenceClock
*iface
,
1258 REFERENCE_TIME rtBaseTime
,
1259 REFERENCE_TIME rtStreamTime
,
1261 DWORD_PTR
*pdwAdviseCookie
)
1263 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1265 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This
, iface
, wine_dbgstr_longlong(rtBaseTime
), wine_dbgstr_longlong(rtStreamTime
), (void*)hEvent
, pdwAdviseCookie
);
1270 static HRESULT WINAPI
ReferenceClock_AdvisePeriodic(IReferenceClock
*iface
,
1271 REFERENCE_TIME rtBaseTime
,
1272 REFERENCE_TIME rtStreamTime
,
1273 HSEMAPHORE hSemaphore
,
1274 DWORD_PTR
*pdwAdviseCookie
)
1276 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1278 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This
, iface
, wine_dbgstr_longlong(rtBaseTime
), wine_dbgstr_longlong(rtStreamTime
), (void*)hSemaphore
, pdwAdviseCookie
);
1283 static HRESULT WINAPI
ReferenceClock_Unadvise(IReferenceClock
*iface
,
1284 DWORD_PTR dwAdviseCookie
)
1286 ICOM_THIS_MULTI(DSoundRenderImpl
, IReferenceClock_vtbl
, iface
);
1288 FIXME("(%p/%p)->(%p): stub!\n", This
, iface
, (void*)dwAdviseCookie
);
1293 static const IReferenceClockVtbl IReferenceClock_Vtbl
=
1295 ReferenceClock_QueryInterface
,
1296 ReferenceClock_AddRef
,
1297 ReferenceClock_Release
,
1298 ReferenceClock_GetTime
,
1299 ReferenceClock_AdviseTime
,
1300 ReferenceClock_AdvisePeriodic
,
1301 ReferenceClock_Unadvise
1304 static inline DSoundRenderImpl
*impl_from_IMediaSeeking( IMediaSeeking
*iface
)
1306 return (DSoundRenderImpl
*)((char*)iface
- FIELD_OFFSET(DSoundRenderImpl
, mediaSeeking
.lpVtbl
));
1309 static HRESULT WINAPI
sound_seek_QueryInterface(IMediaSeeking
* iface
, REFIID riid
, LPVOID
* ppv
)
1311 DSoundRenderImpl
*This
= impl_from_IMediaSeeking(iface
);
1313 return IUnknown_QueryInterface((IUnknown
*)This
, riid
, ppv
);
1316 static ULONG WINAPI
sound_seek_AddRef(IMediaSeeking
* iface
)
1318 DSoundRenderImpl
*This
= impl_from_IMediaSeeking(iface
);
1320 return IUnknown_AddRef((IUnknown
*)This
);
1323 static ULONG WINAPI
sound_seek_Release(IMediaSeeking
* iface
)
1325 DSoundRenderImpl
*This
= impl_from_IMediaSeeking(iface
);
1327 return IUnknown_Release((IUnknown
*)This
);
1330 static const IMediaSeekingVtbl IMediaSeeking_Vtbl
=
1332 sound_seek_QueryInterface
,
1335 MediaSeekingImpl_GetCapabilities
,
1336 MediaSeekingImpl_CheckCapabilities
,
1337 MediaSeekingImpl_IsFormatSupported
,
1338 MediaSeekingImpl_QueryPreferredFormat
,
1339 MediaSeekingImpl_GetTimeFormat
,
1340 MediaSeekingImpl_IsUsingTimeFormat
,
1341 MediaSeekingImpl_SetTimeFormat
,
1342 MediaSeekingImpl_GetDuration
,
1343 MediaSeekingImpl_GetStopPosition
,
1344 MediaSeekingImpl_GetCurrentPosition
,
1345 MediaSeekingImpl_ConvertTimeFormat
,
1346 MediaSeekingImpl_SetPositions
,
1347 MediaSeekingImpl_GetPositions
,
1348 MediaSeekingImpl_GetAvailable
,
1349 MediaSeekingImpl_SetRate
,
1350 MediaSeekingImpl_GetRate
,
1351 MediaSeekingImpl_GetPreroll
1354 /*** IUnknown methods ***/
1355 static HRESULT WINAPI
AMDirectSound_QueryInterface(IAMDirectSound
*iface
,
1359 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1361 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
1363 return DSoundRender_QueryInterface((IBaseFilter
*)This
, riid
, ppvObj
);
1366 static ULONG WINAPI
AMDirectSound_AddRef(IAMDirectSound
*iface
)
1368 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1370 TRACE("(%p/%p)->()\n", This
, iface
);
1372 return DSoundRender_AddRef((IBaseFilter
*)This
);
1375 static ULONG WINAPI
AMDirectSound_Release(IAMDirectSound
*iface
)
1377 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1379 TRACE("(%p/%p)->()\n", This
, iface
);
1381 return DSoundRender_Release((IBaseFilter
*)This
);
1384 /*** IAMDirectSound methods ***/
1385 static HRESULT WINAPI
AMDirectSound_GetDirectSoundInterface(IAMDirectSound
*iface
, IDirectSound
**ds
)
1387 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1389 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, ds
);
1394 static HRESULT WINAPI
AMDirectSound_GetPrimaryBufferInterface(IAMDirectSound
*iface
, IDirectSoundBuffer
**buf
)
1396 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1398 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, buf
);
1403 static HRESULT WINAPI
AMDirectSound_GetSecondaryBufferInterface(IAMDirectSound
*iface
, IDirectSoundBuffer
**buf
)
1405 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1407 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, buf
);
1412 static HRESULT WINAPI
AMDirectSound_ReleaseDirectSoundInterface(IAMDirectSound
*iface
, IDirectSound
*ds
)
1414 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1416 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, ds
);
1421 static HRESULT WINAPI
AMDirectSound_ReleasePrimaryBufferInterface(IAMDirectSound
*iface
, IDirectSoundBuffer
*buf
)
1423 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1425 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, buf
);
1430 static HRESULT WINAPI
AMDirectSound_ReleaseSecondaryBufferInterface(IAMDirectSound
*iface
, IDirectSoundBuffer
*buf
)
1432 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1434 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, buf
);
1439 static HRESULT WINAPI
AMDirectSound_SetFocusWindow(IAMDirectSound
*iface
, HWND hwnd
, BOOL bgsilent
)
1441 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1443 FIXME("(%p/%p)->(%p,%d): stub\n", This
, iface
, hwnd
, bgsilent
);
1448 static HRESULT WINAPI
AMDirectSound_GetFocusWindow(IAMDirectSound
*iface
, HWND hwnd
)
1450 ICOM_THIS_MULTI(DSoundRenderImpl
, IAMDirectSound_vtbl
, iface
);
1452 FIXME("(%p/%p)->(%p): stub\n", This
, iface
, hwnd
);
1457 static const IAMDirectSoundVtbl IAMDirectSound_Vtbl
=
1459 AMDirectSound_QueryInterface
,
1460 AMDirectSound_AddRef
,
1461 AMDirectSound_Release
,
1462 AMDirectSound_GetDirectSoundInterface
,
1463 AMDirectSound_GetPrimaryBufferInterface
,
1464 AMDirectSound_GetSecondaryBufferInterface
,
1465 AMDirectSound_ReleaseDirectSoundInterface
,
1466 AMDirectSound_ReleasePrimaryBufferInterface
,
1467 AMDirectSound_ReleaseSecondaryBufferInterface
,
1468 AMDirectSound_SetFocusWindow
,
1469 AMDirectSound_GetFocusWindow