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;
49 static const IReferenceClockVtbl IReferenceClock_Vtbl;
51 typedef struct DSoundRenderImpl
53 const IBaseFilterVtbl * lpVtbl;
54 const IBasicAudioVtbl *IBasicAudio_vtbl;
55 const IReferenceClockVtbl *IReferenceClock_vtbl;
58 CRITICAL_SECTION csFilter;
60 REFERENCE_TIME rtStreamStart;
61 IReferenceClock * pClock;
62 FILTER_INFO filterInfo;
68 LPDIRECTSOUNDBUFFER dsbuffer;
76 REFERENCE_TIME play_time;
82 static HRESULT DSoundRender_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
88 if (pPinInfo->dir != PINDIR_INPUT)
90 ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
94 pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
99 if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
101 pPinImpl->pin.lpVtbl = &DSoundRender_InputPin_Vtbl;
102 pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
104 *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
111 static HRESULT DSoundRender_CreateSoundBuffer(IBaseFilter * iface)
114 WAVEFORMATEX wav_fmt;
116 WAVEFORMATEX* format;
117 DSBUFFERDESC buf_desc;
118 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
120 hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
122 ERR("Unable to retrieve media type\n");
126 TRACE("MajorType %s\n", debugstr_guid(&amt.majortype));
127 TRACE("SubType %s\n", debugstr_guid(&amt.subtype));
128 TRACE("Format %s\n", debugstr_guid(&amt.formattype));
129 TRACE("Size %d\n", amt.cbFormat);
131 dump_AM_MEDIA_TYPE(&amt);
133 format = (WAVEFORMATEX*)amt.pbFormat;
134 TRACE("wFormatTag = %x %x\n", format->wFormatTag, WAVE_FORMAT_PCM);
135 TRACE("nChannels = %d\n", format->nChannels);
136 TRACE("nSamplesPerSec = %u\n", format->nSamplesPerSec);
137 TRACE("nAvgBytesPerSec = %u\n", format->nAvgBytesPerSec);
138 TRACE("nBlockAlign = %d\n", format->nBlockAlign);
139 TRACE("wBitsPerSample = %d\n", format->wBitsPerSample);
140 TRACE("cbSize = %d\n", format->cbSize);
142 /* Lock the critical section to make sure we're still marked to play while
143 setting up the playback buffer */
144 EnterCriticalSection(&This->csFilter);
146 if (This->state != State_Running) {
147 hr = VFW_E_WRONG_STATE;
151 hr = DirectSoundCreate(NULL, &This->dsound, NULL);
153 ERR("Cannot create Direct Sound object\n");
157 This->buf_size = format->nAvgBytesPerSec;
162 memset(&buf_desc,0,sizeof(DSBUFFERDESC));
163 buf_desc.dwSize = sizeof(DSBUFFERDESC);
164 buf_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN |
165 DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2;
166 buf_desc.dwBufferBytes = This->buf_size;
167 buf_desc.lpwfxFormat = &wav_fmt;
168 hr = IDirectSound_CreateSoundBuffer(This->dsound, &buf_desc, &This->dsbuffer, NULL);
170 ERR("Can't create sound buffer !\n");
171 IDirectSound_Release(This->dsound);
175 hr = IDirectSoundBuffer_SetVolume(This->dsbuffer, This->volume);
177 ERR("Can't set volume to %ld (%x)!\n", This->volume, hr);
179 hr = IDirectSoundBuffer_SetPan(This->dsbuffer, This->pan);
181 ERR("Can't set pan to %ld (%x)!\n", This->pan, hr);
183 hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
185 ERR("Can't start sound buffer (%x)!\n", hr);
186 IDirectSoundBuffer_Release(This->dsbuffer);
187 IDirectSound_Release(This->dsound);
194 LeaveCriticalSection(&This->csFilter);
198 static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPos, DWORD *pWritePos, REFERENCE_TIME *pRefTime)
202 EnterCriticalSection(&This->csFilter);
204 hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, pWritePos);
207 DWORD play_pos = *pPlayPos;
209 if (play_pos < This->last_play_pos)
211 This->last_play_pos = play_pos;
213 /* If we're really falling behind, kick the play time back */
214 if ((This->play_loops*This->buf_size)+play_pos >=
215 (This->write_loops*This->buf_size)+This->write_pos)
220 REFERENCE_TIME play_time;
221 play_time = ((REFERENCE_TIME)This->play_loops*10000000) +
222 ((REFERENCE_TIME)play_pos*10000000/This->buf_size);
224 /* Don't let time run backwards */
225 if(play_time-This->play_time > 0)
226 This->play_time = play_time;
230 *pRefTime = This->play_time;
234 LeaveCriticalSection(&This->csFilter);
239 static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, LPBYTE data, DWORD size)
242 LPBYTE lpbuf1 = NULL;
243 LPBYTE lpbuf2 = NULL;
247 DWORD play_pos,buf_free;
250 hr = DSoundRender_GetPos(This, &play_pos, NULL, NULL);
253 ERR("GetPos returned error: %x\n", hr);
256 if (This->write_pos <= play_pos)
257 buf_free = play_pos-This->write_pos;
259 buf_free = This->buf_size - This->write_pos + play_pos;
261 /* Wait for enough of the buffer to empty before filling it */
262 if(buf_free < This->buf_size/4)
268 size2 = min(buf_free, size);
269 hr = IDirectSoundBuffer_Lock(This->dsbuffer, This->write_pos, size2, (LPVOID *)&lpbuf1, &dwsize1, (LPVOID *)&lpbuf2, &dwsize2, 0);
271 ERR("Unable to lock sound buffer! (%x)\n", hr);
274 /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */
276 memcpy(lpbuf1, data, dwsize1);
278 memcpy(lpbuf2, data + dwsize1, dwsize2);
280 hr = IDirectSoundBuffer_Unlock(This->dsbuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
282 ERR("Unable to unlock sound buffer! (%x)\n", hr);
284 size -= dwsize1 + dwsize2;
285 data += dwsize1 + dwsize2;
286 This->write_pos += dwsize1 + dwsize2;
287 if (This->write_pos >= This->buf_size)
289 This->write_pos -= This->buf_size;
292 } while (size && This->state == State_Running);
297 static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
299 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
300 LPBYTE pbSrcStream = NULL;
301 long cbSrcStream = 0;
302 REFERENCE_TIME tStart, tStop;
305 TRACE("%p %p\n", iface, pSample);
307 if (This->state != State_Running)
308 return VFW_E_WRONG_STATE;
310 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
313 ERR("Cannot get pointer to sample data (%x)\n", hr);
317 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
319 ERR("Cannot get sample time (%x)\n", hr);
321 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
323 TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream);
325 #if 0 /* For debugging purpose */
328 for(i = 0; i < cbSrcStream; i++)
330 if ((i!=0) && !(i%16))
332 TRACE("%02x ", pbSrcStream[i]);
340 hr = DSoundRender_CreateSoundBuffer(iface);
345 ERR("Unable to create DSound buffer\n");
350 hr = DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream);
355 static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
357 WAVEFORMATEX* format = (WAVEFORMATEX*)pmt->pbFormat;
358 TRACE("wFormatTag = %x %x\n", format->wFormatTag, WAVE_FORMAT_PCM);
359 TRACE("nChannels = %d\n", format->nChannels);
360 TRACE("nSamplesPerSec = %d\n", format->nAvgBytesPerSec);
361 TRACE("nAvgBytesPerSec = %d\n", format->nAvgBytesPerSec);
362 TRACE("nBlockAlign = %d\n", format->nBlockAlign);
363 TRACE("wBitsPerSample = %d\n", format->wBitsPerSample);
365 if (IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_PCM))
370 HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
374 DSoundRenderImpl * pDSoundRender;
376 TRACE("(%p, %p)\n", pUnkOuter, ppv);
381 return CLASS_E_NOAGGREGATION;
383 pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl));
385 return E_OUTOFMEMORY;
386 ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl));
388 pDSoundRender->lpVtbl = &DSoundRender_Vtbl;
389 pDSoundRender->IBasicAudio_vtbl = &IBasicAudio_Vtbl;
390 pDSoundRender->IReferenceClock_vtbl = &IReferenceClock_Vtbl;
391 pDSoundRender->refCount = 1;
392 InitializeCriticalSection(&pDSoundRender->csFilter);
393 pDSoundRender->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter");
394 pDSoundRender->state = State_Stopped;
396 pDSoundRender->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
397 if (!pDSoundRender->ppPins)
399 pDSoundRender->csFilter.DebugInfo->Spare[0] = 0;
400 DeleteCriticalSection(&pDSoundRender->csFilter);
401 CoTaskMemFree(pDSoundRender);
402 return E_OUTOFMEMORY;
405 /* construct input pin */
406 piInput.dir = PINDIR_INPUT;
407 piInput.pFilter = (IBaseFilter *)pDSoundRender;
408 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
409 hr = DSoundRender_InputPin_Construct(&piInput, DSoundRender_Sample, (LPVOID)pDSoundRender, DSoundRender_QueryAccept, &pDSoundRender->csFilter, (IPin **)&pDSoundRender->pInputPin);
413 pDSoundRender->ppPins[0] = (IPin *)pDSoundRender->pInputPin;
414 *ppv = (LPVOID)pDSoundRender;
418 CoTaskMemFree(pDSoundRender->ppPins);
419 pDSoundRender->csFilter.DebugInfo->Spare[0] = 0;
420 DeleteCriticalSection(&pDSoundRender->csFilter);
421 CoTaskMemFree(pDSoundRender);
427 static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
429 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
430 TRACE("(%p, %p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
434 if (IsEqualIID(riid, &IID_IUnknown))
436 else if (IsEqualIID(riid, &IID_IPersist))
438 else if (IsEqualIID(riid, &IID_IMediaFilter))
440 else if (IsEqualIID(riid, &IID_IBaseFilter))
442 else if (IsEqualIID(riid, &IID_IBasicAudio))
443 *ppv = (LPVOID)&(This->IBasicAudio_vtbl);
444 else if (IsEqualIID(riid, &IID_IReferenceClock))
445 *ppv = (LPVOID)&(This->IReferenceClock_vtbl);
449 IUnknown_AddRef((IUnknown *)(*ppv));
453 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
455 return E_NOINTERFACE;
458 static ULONG WINAPI DSoundRender_AddRef(IBaseFilter * iface)
460 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
461 ULONG refCount = InterlockedIncrement(&This->refCount);
463 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
468 static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface)
470 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
471 ULONG refCount = InterlockedDecrement(&This->refCount);
473 TRACE("(%p)->() Release from %d\n", This, refCount + 1);
480 IReferenceClock_Release(This->pClock);
483 IDirectSoundBuffer_Release(This->dsbuffer);
484 This->dsbuffer = NULL;
486 IDirectSound_Release(This->dsound);
489 if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
491 IPin_Disconnect(pConnectedTo);
492 IPin_Release(pConnectedTo);
494 IPin_Disconnect(This->ppPins[0]);
496 IPin_Release(This->ppPins[0]);
498 CoTaskMemFree(This->ppPins);
500 This->IBasicAudio_vtbl = NULL;
502 This->csFilter.DebugInfo->Spare[0] = 0;
503 DeleteCriticalSection(&This->csFilter);
505 TRACE("Destroying Audio Renderer\n");
514 /** IPersist methods **/
516 static HRESULT WINAPI DSoundRender_GetClassID(IBaseFilter * iface, CLSID * pClsid)
518 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
519 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
521 *pClsid = CLSID_DSoundRender;
526 /** IMediaFilter methods **/
528 static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface)
531 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
533 TRACE("(%p/%p)->()\n", This, iface);
535 EnterCriticalSection(&This->csFilter);
540 hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state);
543 if (state & DSBSTATUS_PLAYING)
544 hr = IDirectSoundBuffer_Stop(This->dsbuffer);
548 This->state = State_Stopped;
550 LeaveCriticalSection(&This->csFilter);
555 static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
558 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
560 TRACE("(%p/%p)->()\n", This, iface);
562 EnterCriticalSection(&This->csFilter);
567 hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state);
570 if (state & DSBSTATUS_PLAYING)
571 hr = IDirectSoundBuffer_Stop(This->dsbuffer);
575 This->state = State_Paused;
577 LeaveCriticalSection(&This->csFilter);
582 static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
585 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
587 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
589 EnterCriticalSection(&This->csFilter);
591 /* It's okay if there's no buffer yet. It'll start when it's created */
594 hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
596 ERR("Can't start playing! (%x)\n", hr);
600 This->rtStreamStart = tStart;
601 This->state = State_Running;
604 LeaveCriticalSection(&This->csFilter);
609 static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
611 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
613 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
615 EnterCriticalSection(&This->csFilter);
617 *pState = This->state;
619 LeaveCriticalSection(&This->csFilter);
624 static HRESULT WINAPI DSoundRender_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
626 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
628 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
630 EnterCriticalSection(&This->csFilter);
633 IReferenceClock_Release(This->pClock);
634 This->pClock = pClock;
636 IReferenceClock_AddRef(This->pClock);
638 LeaveCriticalSection(&This->csFilter);
643 static HRESULT WINAPI DSoundRender_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
645 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
647 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
649 EnterCriticalSection(&This->csFilter);
651 *ppClock = This->pClock;
652 IReferenceClock_AddRef(This->pClock);
654 LeaveCriticalSection(&This->csFilter);
659 /** IBaseFilter implementation **/
661 static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
664 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
666 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
668 epd.cPins = 1; /* input pin */
669 epd.ppPins = This->ppPins;
670 return IEnumPinsImpl_Construct(&epd, ppEnum);
673 static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
675 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
677 TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin);
679 FIXME("DSoundRender::FindPin(...)\n");
681 /* FIXME: critical section */
686 static HRESULT WINAPI DSoundRender_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
688 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
690 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
692 strcpyW(pInfo->achName, This->filterInfo.achName);
693 pInfo->pGraph = This->filterInfo.pGraph;
696 IFilterGraph_AddRef(pInfo->pGraph);
701 static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
703 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
705 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
707 EnterCriticalSection(&This->csFilter);
710 strcpyW(This->filterInfo.achName, pName);
712 *This->filterInfo.achName = '\0';
713 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
715 LeaveCriticalSection(&This->csFilter);
720 static HRESULT WINAPI DSoundRender_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
722 DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
723 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
727 static const IBaseFilterVtbl DSoundRender_Vtbl =
729 DSoundRender_QueryInterface,
731 DSoundRender_Release,
732 DSoundRender_GetClassID,
736 DSoundRender_GetState,
737 DSoundRender_SetSyncSource,
738 DSoundRender_GetSyncSource,
739 DSoundRender_EnumPins,
740 DSoundRender_FindPin,
741 DSoundRender_QueryFilterInfo,
742 DSoundRender_JoinFilterGraph,
743 DSoundRender_QueryVendorInfo
746 static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
748 InputPin* This = (InputPin*)iface;
749 IMediaEventSink* pEventSink;
752 TRACE("(%p/%p)->()\n", This, iface);
754 hr = IFilterGraph_QueryInterface(((DSoundRenderImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
757 /* FIXME: We should wait that all audio data has been played */
758 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
759 IMediaEventSink_Release(pEventSink);
765 static const IPinVtbl DSoundRender_InputPin_Vtbl =
767 InputPin_QueryInterface,
771 InputPin_ReceiveConnection,
773 IPinImpl_ConnectedTo,
774 IPinImpl_ConnectionMediaType,
775 IPinImpl_QueryPinInfo,
776 IPinImpl_QueryDirection,
778 IPinImpl_QueryAccept,
779 IPinImpl_EnumMediaTypes,
780 IPinImpl_QueryInternalConnections,
781 DSoundRender_InputPin_EndOfStream,
787 static const IMemInputPinVtbl MemInputPin_Vtbl =
789 MemInputPin_QueryInterface,
792 MemInputPin_GetAllocator,
793 MemInputPin_NotifyAllocator,
794 MemInputPin_GetAllocatorRequirements,
796 MemInputPin_ReceiveMultiple,
797 MemInputPin_ReceiveCanBlock
800 /*** IUnknown methods ***/
801 static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface,
804 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
806 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
808 return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj);
811 static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
812 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
814 TRACE("(%p/%p)->()\n", This, iface);
816 return DSoundRender_AddRef((IBaseFilter*)This);
819 static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
820 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
822 TRACE("(%p/%p)->()\n", This, iface);
824 return DSoundRender_Release((IBaseFilter*)This);
827 /*** IDispatch methods ***/
828 static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface,
830 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
832 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
837 static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface,
840 ITypeInfo**ppTInfo) {
841 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
843 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
848 static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface,
854 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
856 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
861 static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface,
866 DISPPARAMS*pDispParams,
870 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
872 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);
877 /*** IBasicAudio methods ***/
878 static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface,
880 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
882 TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
884 if (lVolume > DSBVOLUME_MAX || lVolume < DSBVOLUME_MIN)
887 if (This->dsbuffer) {
888 if (FAILED(IDirectSoundBuffer_SetVolume(This->dsbuffer, lVolume)))
892 This->volume = lVolume;
896 static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface,
898 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
900 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
905 *plVolume = This->volume;
909 static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface,
911 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
913 TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
915 if (lBalance < DSBPAN_LEFT || lBalance > DSBPAN_RIGHT)
918 if (This->dsbuffer) {
919 if (FAILED(IDirectSoundBuffer_SetPan(This->dsbuffer, lBalance)))
923 This->pan = lBalance;
927 static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface,
929 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
931 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
936 *plBalance = This->pan;
940 static const IBasicAudioVtbl IBasicAudio_Vtbl =
942 Basicaudio_QueryInterface,
945 Basicaudio_GetTypeInfoCount,
946 Basicaudio_GetTypeInfo,
947 Basicaudio_GetIDsOfNames,
949 Basicaudio_put_Volume,
950 Basicaudio_get_Volume,
951 Basicaudio_put_Balance,
952 Basicaudio_get_Balance
956 /*** IUnknown methods ***/
957 static HRESULT WINAPI ReferenceClock_QueryInterface(IReferenceClock *iface,
961 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
963 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
965 return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj);
968 static ULONG WINAPI ReferenceClock_AddRef(IReferenceClock *iface)
970 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
972 TRACE("(%p/%p)->()\n", This, iface);
974 return DSoundRender_AddRef((IBaseFilter*)This);
977 static ULONG WINAPI ReferenceClock_Release(IReferenceClock *iface)
979 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
981 TRACE("(%p/%p)->()\n", This, iface);
983 return DSoundRender_Release((IBaseFilter*)This);
986 /*** IReferenceClock methods ***/
987 static HRESULT WINAPI ReferenceClock_GetTime(IReferenceClock *iface,
988 REFERENCE_TIME *pTime)
990 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
994 TRACE("(%p/%p)->(%p)\n", This, iface, pTime);
997 hr = DSoundRender_GetPos(This, &play_pos, NULL, pTime);
999 ERR("Could not get refreence time (%x)!\n", hr);
1004 static HRESULT WINAPI ReferenceClock_AdviseTime(IReferenceClock *iface,
1005 REFERENCE_TIME rtBaseTime,
1006 REFERENCE_TIME rtStreamTime,
1008 DWORD_PTR *pdwAdviseCookie)
1010 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
1012 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hEvent, pdwAdviseCookie);
1017 static HRESULT WINAPI ReferenceClock_AdvisePeriodic(IReferenceClock *iface,
1018 REFERENCE_TIME rtBaseTime,
1019 REFERENCE_TIME rtStreamTime,
1020 HSEMAPHORE hSemaphore,
1021 DWORD_PTR *pdwAdviseCookie)
1023 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
1025 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hSemaphore, pdwAdviseCookie);
1030 static HRESULT WINAPI ReferenceClock_Unadvise(IReferenceClock *iface,
1031 DWORD_PTR dwAdviseCookie)
1033 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface);
1035 FIXME("(%p/%p)->(%p): stub!\n", This, iface, (void*)dwAdviseCookie);
1040 static const IReferenceClockVtbl IReferenceClock_Vtbl =
1042 ReferenceClock_QueryInterface,
1043 ReferenceClock_AddRef,
1044 ReferenceClock_Release,
1045 ReferenceClock_GetTime,
1046 ReferenceClock_AdviseTime,
1047 ReferenceClock_AdvisePeriodic,
1048 ReferenceClock_Unadvise