[QUARTZ] Added video and audio renderers and AVI decompressor
Christian Costa
titan.costa at wanadoo.fr
Mon Aug 23 16:52:30 CDT 2004
Hi,
Here is the direct show filters I have in my tree.
There is still work to do but this allow me to do some basic playback yet.
I will improve this while working on a better IGraphBuilder implementation.
Changelog:
Added Video Renderer (based on Direct Draw).
Added Direct Sound Audio Renderer.
Added AVI Decompressor (VFW decompressors wrapper).
Christian Costa titan.costa at wanadoo.fr
-------------- next part --------------
Index: dlls/quartz/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/quartz/Makefile.in,v
retrieving revision 1.39
diff -u -r1.39 Makefile.in
--- dlls/quartz/Makefile.in 19 Aug 2004 19:31:20 -0000 1.39
+++ dlls/quartz/Makefile.in 23 Aug 2004 20:41:49 -0000
@@ -3,12 +3,14 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = quartz.dll
-IMPORTS = ole32 oleaut32 advapi32 kernel32 user32
+IMPORTS = ole32 oleaut32 advapi32 kernel32 user32 dsound ddraw msvfw32
EXTRALIBS = -lstrmiids -luuid $(LIBUNICODE)
C_SRCS = \
+ avidec.c \
avisplit.c \
control.c \
+ dsoundrender.c \
enumfilters.c \
enummedia.c \
enummoniker.c \
@@ -21,7 +23,8 @@
memallocator.c \
pin.c \
regsvr.c \
- systemclock.c
+ systemclock.c \
+ videorenderer.c
RC_SRCS = version.rc
Index: dlls/quartz/main.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/main.c,v
retrieving revision 1.34
diff -u -r1.34 main.c
--- dlls/quartz/main.c 12 Aug 2004 23:00:53 -0000 1.34
+++ dlls/quartz/main.c 23 Aug 2004 20:41:50 -0000
@@ -66,7 +66,9 @@
{ &CLSID_AsyncReader, AsyncReader_create },
{ &CLSID_MemoryAllocator, StdMemAllocator_create },
{ &CLSID_AviSplitter, AVISplitter_create },
-
+ { &CLSID_VideoRenderer, VideoRenderer_create },
+ { &CLSID_DSoundRender, DSoundRender_create },
+ { &CLSID_AVIDec, AVIDec_create },
{ &CLSID_SystemClock, &QUARTZ_CreateSystemClock }
};
Index: dlls/quartz/regsvr.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/regsvr.c,v
retrieving revision 1.10
diff -u -r1.10 regsvr.c
--- dlls/quartz/regsvr.c 5 May 2004 23:51:59 -0000 1.10
+++ dlls/quartz/regsvr.c 23 Aug 2004 20:41:53 -0000
@@ -527,6 +527,42 @@
"quartz.dll",
"Both"
},
+ { &CLSID_MemoryAllocator,
+ "Memory Allocator",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
+ { &CLSID_AsyncReader,
+ "File Source Filter",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
+ { &CLSID_AviSplitter,
+ "AVI Splitter",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
+ { &CLSID_AVIDec,
+ "AVI Decompressor",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
+ { &CLSID_DSoundRender,
+ "Direct Sound Audio Renderer",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
+ { &CLSID_VideoRenderer,
+ "Video Renderer",
+ NULL,
+ "quartz.dll",
+ "Both"
+ },
{ NULL } /* list terminator */
};
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/avidec.c 2004-08-23 22:38:36.000000000 +0100
@@ -0,0 +1,708 @@
+/*
+ * AVI Decompressor (VFW decompressors wrapper)
+ *
+ * Copyright 2004 Christian Costa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include "quartz_private.h"
+#include "control_private.h"
+#include "pin.h"
+
+#include "uuids.h"
+#include "aviriff.h"
+#include "mmreg.h"
+#include "vfwmsgs.h"
+#include "amvideo.h"
+#include "windef.h"
+#include "winbase.h"
+#include "dshow.h"
+#include "strmif.h"
+#include "vfwmsgs.h"
+#include "evcode.h"
+#include "vfw.h"
+//#include "fourcc.h"
+#include "avcodec.h"
+
+#include <assert.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
+static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0};
+
+static const IBaseFilterVtbl AVIDec_Vtbl;
+static const IPinVtbl AVIDec_InputPin_Vtbl;
+static const IMemInputPinVtbl MemInputPin_Vtbl;
+static const IPinVtbl AVIDec_OutputPin_Vtbl;
+
+typedef struct AVIDecImpl
+{
+ const IBaseFilterVtbl * lpVtbl;
+
+ ULONG refCount;
+ CRITICAL_SECTION csFilter;
+ FILTER_STATE state;
+ REFERENCE_TIME rtStreamStart;
+ IReferenceClock * pClock;
+ FILTER_INFO filterInfo;
+
+ IPin ** ppPins;
+
+ HIC hvid;
+ int init;
+} AVIDecImpl;
+
+static DWORD AVIDec_SendSampleData(AVIDecImpl* This, LPBYTE data, DWORD size)
+{
+ VIDEOINFOHEADER* format;
+ AM_MEDIA_TYPE amt;
+ BITMAPINFOHEADER bi;
+ HRESULT hr;
+ DWORD res;
+ IMediaSample* pSample = NULL;
+ DWORD cbDstStream;
+ LPBYTE pbDstStream;
+
+ hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
+ if (FAILED(hr)) {
+ ERR("Unable to retreive media type\n");
+ goto error;
+ }
+ format = (VIDEOINFOHEADER*)amt.pbFormat;
+
+ /* Fill a bitmap header for output */
+ bi.biSize = sizeof(bi);
+ bi.biWidth = format->bmiHeader.biWidth;
+ bi.biHeight = format->bmiHeader.biHeight;
+ bi.biPlanes = 1;
+ bi.biBitCount = format->bmiHeader.biBitCount;
+ bi.biCompression = 0;
+ bi.biSizeImage = bi.biWidth * bi.biHeight * bi.biBitCount / 8;
+
+ hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->ppPins[1], &pSample, NULL, NULL, 0);
+ if (FAILED(hr)) {
+ ERR("Unable to get delivery buffer (%lx)\n", hr);
+ goto error;
+ }
+
+ hr = IMediaSample_SetActualDataLength(pSample, 0);
+ assert(hr == S_OK);
+
+ hr = IMediaSample_GetPointer(pSample, &pbDstStream);
+ if (FAILED(hr)) {
+ ERR("Unable to get pointer to buffer (%lx)\n", hr);
+ goto error;
+ }
+ cbDstStream = IMediaSample_GetSize(pSample);
+ if (cbDstStream < bi.biSizeImage) {
+ ERR("Sample size is too small %ld < %ld\n", cbDstStream, bi.biSizeImage);
+ hr = E_FAIL;
+ goto error;
+ }
+
+ res = ICDecompress(This->hvid, 0, &format->bmiHeader, data, &bi, pbDstStream);
+ if (res != ICERR_OK)
+ ERR("Error occured during the decompression (%lx)\n", res);
+
+ hr = OutputPin_SendSample((OutputPin*)This->ppPins[1], pSample);
+ if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
+ ERR("Error sending sample (%lx)\n", hr);
+ goto error;
+ }
+
+ return S_OK;
+
+error:
+ /* If we have a sample that has not been delivered, release it */
+ if (pSample)
+ IMediaSample_Release(pSample);
+
+ return hr;
+}
+
+static HRESULT AVIDec_Sample(LPVOID iface, IMediaSample * pSample)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+ LPBYTE pbSrcStream = NULL;
+ long cbSrcStream = 0;
+ REFERENCE_TIME tStart, tStop;
+ HRESULT hr;
+
+ TRACE("%p %p\n", iface, pSample);
+
+ hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
+ if (FAILED(hr))
+ {
+ ERR("Cannot get pointer to sample data (%lx)\n", hr);
+ return hr;
+ }
+
+ hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
+ if (FAILED(hr))
+ ERR("Cannot get sample time (%lx)\n", hr);
+
+ cbSrcStream = IMediaSample_GetActualDataLength(pSample);
+
+ TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream);
+
+#if 0 /* For debugging purpose */
+ {
+ int i;
+ for(i = 0; i < cbSrcStream; i++)
+ {
+ if ((i!=0) && !(i%16))
+ DPRINTF("\n");
+ DPRINTF("%02x ", pbSrcStream[i]);
+ }
+ DPRINTF("\n");
+ }
+#endif
+
+ AVIDec_SendSampleData(This, pbSrcStream, cbSrcStream);
+
+ /* We have finished with the incoming sample, we must release it now */
+ IMediaSample_Release(pSample);
+
+ return S_OK;
+}
+
+static HRESULT AVIDec_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+{
+ AVIDecImpl* pAVIDec = (AVIDecImpl*)iface;
+ TRACE("%p\n", iface);
+ dump_AM_MEDIA_TYPE(pmt);
+
+ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
+ (!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */
+ (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)))
+ {
+ HIC drv;
+ VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat;
+ drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
+ if (drv)
+ {
+ AM_MEDIA_TYPE* outpmt = &((OutputPin*)pAVIDec->ppPins[1])->pin.mtCurrent;
+ const CLSID* outsubtype;
+ switch(format->bmiHeader.biBitCount)
+ {
+ case 32: outsubtype = &MEDIATYPE_Video; break;
+ case 24: outsubtype = &MEDIASUBTYPE_RGB24; break;
+ case 16: outsubtype = &MEDIASUBTYPE_RGB565; break;
+ case 8: outsubtype = &MEDIASUBTYPE_RGB8; break;
+ default:
+ FIXME("Depth %d not supported\n", format->bmiHeader.biBitCount);
+ ICClose(drv);
+ return S_FALSE;
+ }
+ CopyMediaType( outpmt, pmt);
+ outpmt->subtype = *outsubtype;
+ pAVIDec->hvid = drv;
+ pAVIDec->init = 1;
+ TRACE("Connection accepted\n");
+ return S_OK;
+ }
+ TRACE("Unable to find a suitable VFW decompressor\n");
+ }
+
+ TRACE("Connection refused\n");
+ return S_FALSE;
+}
+
+
+static HRESULT AVIDec_Output_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+{
+ AVIDecImpl* pAVIDec = (AVIDecImpl*)iface;
+ AM_MEDIA_TYPE* outpmt = &((OutputPin*)pAVIDec->ppPins[1])->pin.mtCurrent;
+ TRACE("%p\n", iface);
+
+ if (IsEqualIID(&pmt->majortype, &outpmt->majortype) && IsEqualIID(&pmt->subtype, &outpmt->subtype))
+ return S_OK;
+ return S_FALSE;
+}
+
+static HRESULT AVIDec_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ InputPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ if (pPinInfo->dir != PINDIR_INPUT)
+ {
+ ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
+ return E_INVALIDARG;
+ }
+
+ pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+ TRACE("QA : %p %p\n", pQueryAccept, AVIDec_Input_QueryAccept);
+ if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.lpVtbl = &AVIDec_InputPin_Vtbl;
+ pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
+
+ *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT AVIDec_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ OutputPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ if (pPinInfo->dir != PINDIR_OUTPUT)
+ {
+ ERR("Pin direction(%x) != PINDIR_OUTPUT\n", pPinInfo->dir);
+ return E_INVALIDARG;
+ }
+
+ pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+
+ if (SUCCEEDED(OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.lpVtbl = &AVIDec_OutputPin_Vtbl;
+
+ *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
+{
+ HRESULT hr;
+ PIN_INFO piInput;
+ PIN_INFO piOutput;
+ AVIDecImpl * pAVIDec;
+
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ pAVIDec = CoTaskMemAlloc(sizeof(AVIDecImpl));
+
+ pAVIDec->lpVtbl = &AVIDec_Vtbl;
+
+ pAVIDec->refCount = 1;
+ InitializeCriticalSection(&pAVIDec->csFilter);
+ pAVIDec->state = State_Stopped;
+ pAVIDec->pClock = NULL;
+ pAVIDec->init = 0;
+ ZeroMemory(&pAVIDec->filterInfo, sizeof(FILTER_INFO));
+
+ pAVIDec->ppPins = CoTaskMemAlloc(2 * sizeof(IPin *));
+
+ /* construct input pin */
+ piInput.dir = PINDIR_INPUT;
+ piInput.pFilter = (IBaseFilter *)pAVIDec;
+ strncpyW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
+ piOutput.dir = PINDIR_OUTPUT;
+ piOutput.pFilter = (IBaseFilter *)pAVIDec;
+ strncpyW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
+
+ hr = AVIDec_InputPin_Construct(&piInput, AVIDec_Sample, (LPVOID)pAVIDec, AVIDec_Input_QueryAccept, &pAVIDec->csFilter, &pAVIDec->ppPins[0]);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = AVIDec_OutputPin_Construct(&piOutput, NULL, NULL, AVIDec_Output_QueryAccept, &pAVIDec->csFilter, &pAVIDec->ppPins[1]);
+
+ if (FAILED(hr))
+ ERR("Cannot create output pin (%lx)\n", hr);
+
+ *ppv = (LPVOID)pAVIDec;
+ }
+ else
+ {
+ CoTaskMemFree(pAVIDec->ppPins);
+ DeleteCriticalSection(&pAVIDec->csFilter);
+ CoTaskMemFree(pAVIDec);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI AVIDec_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+ TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IPersist))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IMediaFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = (LPVOID)This;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI AVIDec_AddRef(IBaseFilter * iface)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+ TRACE("(%p/%p)->()\n", This, iface);
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI AVIDec_Release(IBaseFilter * iface)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+ TRACE("(%p/%p)->()\n", This, iface);
+ if (!InterlockedDecrement(&This->refCount))
+ {
+ ULONG i;
+
+ DeleteCriticalSection(&This->csFilter);
+ IReferenceClock_Release(This->pClock);
+
+ for (i = 0; i < 2; i++)
+ IPin_Release(This->ppPins[i]);
+
+ HeapFree(GetProcessHeap(), 0, This->ppPins);
+ This->lpVtbl = NULL;
+
+ if (This->hvid)
+ ICClose(This->hvid);
+
+ TRACE("Destroying AVI Decompressor\n");
+ CoTaskMemFree(This);
+
+ return 0;
+ }
+ else
+ return This->refCount;
+}
+
+/** IPersist methods **/
+
+static HRESULT WINAPI AVIDec_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
+
+ *pClsid = CLSID_AVIDec;
+
+ return S_OK;
+}
+
+/** IMediaFilter methods **/
+
+static HRESULT WINAPI AVIDec_Stop(IBaseFilter * iface)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Stopped;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_Pause(IBaseFilter * iface)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Paused;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+{
+ HRESULT hr = S_OK;
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->rtStreamStart = tStart;
+
+ This->state = State_Running;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI AVIDec_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%ld, %p)\n", This, iface, dwMilliSecsTimeout, pState);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *pState = This->state;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+ This->pClock = pClock;
+ if (This->pClock)
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *ppClock = This->pClock;
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+/** IBaseFilter implementation **/
+
+static HRESULT WINAPI AVIDec_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+ ENUMPINDETAILS epd;
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+ epd.cPins = 2; /* input and output pins */
+ epd.ppPins = This->ppPins;
+ return IEnumPinsImpl_Construct(&epd, ppEnum);
+}
+
+static HRESULT WINAPI AVIDec_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
+
+ FIXME("AVISplitter::FindPin(...)\n");
+
+ /* FIXME: critical section */
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI AVIDec_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
+
+ strcpyW(pInfo->achName, This->filterInfo.achName);
+ pInfo->pGraph = This->filterInfo.pGraph;
+
+ if (pInfo->pGraph)
+ IFilterGraph_AddRef(pInfo->pGraph);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+{
+ HRESULT hr = S_OK;
+ ICOM_THIS(AVIDecImpl, iface);
+
+ TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (pName)
+ strcpyW(This->filterInfo.achName, pName);
+ else
+ *This->filterInfo.achName = '\0';
+ This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI AVIDec_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+{
+ ICOM_THIS(AVIDecImpl, iface);
+ TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
+ return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl AVIDec_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ AVIDec_QueryInterface,
+ AVIDec_AddRef,
+ AVIDec_Release,
+ AVIDec_GetClassID,
+ AVIDec_Stop,
+ AVIDec_Pause,
+ AVIDec_Run,
+ AVIDec_GetState,
+ AVIDec_SetSyncSource,
+ AVIDec_GetSyncSource,
+ AVIDec_EnumPins,
+ AVIDec_FindPin,
+ AVIDec_QueryFilterInfo,
+ AVIDec_JoinFilterGraph,
+ AVIDec_QueryVendorInfo
+};
+
+static const IPinVtbl AVIDec_InputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ InputPin_QueryInterface,
+ IPinImpl_AddRef,
+ InputPin_Release,
+ InputPin_Connect,
+ InputPin_ReceiveConnection,
+ IPinImpl_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ IPinImpl_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ InputPin_EndOfStream,
+ InputPin_BeginFlush,
+ InputPin_EndFlush,
+ InputPin_NewSegment
+};
+
+HRESULT WINAPI AVIDec_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+{
+ ICOM_THIS(IPinImpl, iface);
+ ENUMMEDIADETAILS emd;
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+ emd.cMediaTypes = 1;
+ emd.pMediaTypes = &This->mtCurrent;
+
+ return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+}
+
+HRESULT WINAPI AVIDec_Output_Disconnect(IPin * iface)
+{
+ OutputPin* This = (OutputPin*)iface;
+ HRESULT hr;
+ AVIDecImpl* pAVIDec = (AVIDecImpl*)This->pin.pinInfo.pFilter;
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ hr = OutputPin_Disconnect(iface);
+
+ if (hr == S_OK)
+ {
+ ICClose(pAVIDec->hvid);
+ pAVIDec->hvid = 0;
+ }
+
+ return hr;
+}
+
+static const IPinVtbl AVIDec_OutputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ OutputPin_QueryInterface,
+ IPinImpl_AddRef,
+ OutputPin_Release,
+ OutputPin_Connect,
+ OutputPin_ReceiveConnection,
+ AVIDec_Output_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ AVIDec_Output_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ OutputPin_EndOfStream,
+ OutputPin_BeginFlush,
+ OutputPin_EndFlush,
+ OutputPin_NewSegment
+};
+
+static const IMemInputPinVtbl MemInputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ MemInputPin_QueryInterface,
+ MemInputPin_AddRef,
+ MemInputPin_Release,
+ MemInputPin_GetAllocator,
+ MemInputPin_NotifyAllocator,
+ MemInputPin_GetAllocatorRequirements,
+ MemInputPin_Receive,
+ MemInputPin_ReceiveMultiple,
+ MemInputPin_ReceiveCanBlock
+};
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/videorenderer.c 2004-08-23 22:15:19.000000000 +0100
@@ -0,0 +1,1561 @@
+/*
+ * Video Renderer (Fullscreen and Windowed using Direct Draw)
+ *
+ * Copyright 2004 Christian Costa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include "quartz_private.h"
+#include "control_private.h"
+#include "pin.h"
+
+#include "uuids.h"
+#include "mmreg.h"
+#include "vfwmsgs.h"
+#include "amvideo.h"
+#include "fourcc.h"
+#include "windef.h"
+#include "winbase.h"
+#include "dshow.h"
+#include "strmif.h"
+#include "ddraw.h"
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
+
+static const IBaseFilterVtbl VideoRenderer_Vtbl;
+static IBasicVideoVtbl IBasicVideo_VTable;
+static IVideoWindowVtbl IVideoWindow_VTable;
+static const IPinVtbl VideoRenderer_InputPin_Vtbl;
+
+typedef struct VideoRendererImpl
+{
+ const IBaseFilterVtbl * lpVtbl;
+ IBasicVideoVtbl * IBasicVideo_vtbl;
+ IVideoWindowVtbl * IVideoWindow_vtbl;
+
+ ULONG refCount;
+ CRITICAL_SECTION csFilter;
+ FILTER_STATE state;
+ REFERENCE_TIME rtStreamStart;
+ IReferenceClock * pClock;
+ FILTER_INFO filterInfo;
+
+ InputPin * pInputPin;
+ IPin ** ppPins;
+
+ LPDIRECTDRAW ddraw;
+ LPDIRECTDRAWSURFACE surface;
+ LPDIRECTDRAWSURFACE backbuffer;
+ int init;
+} VideoRendererImpl;
+
+static const IMemInputPinVtbl MemInputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ MemInputPin_QueryInterface,
+ MemInputPin_AddRef,
+ MemInputPin_Release,
+ MemInputPin_GetAllocator,
+ MemInputPin_NotifyAllocator,
+ MemInputPin_GetAllocatorRequirements,
+ MemInputPin_Receive,
+ MemInputPin_ReceiveMultiple,
+ MemInputPin_ReceiveCanBlock
+};
+
+static HRESULT VideoRenderer_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ InputPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ if (pPinInfo->dir != PINDIR_INPUT)
+ {
+ ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
+ return E_INVALIDARG;
+ }
+
+ pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+
+ if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.lpVtbl = &VideoRenderer_InputPin_Vtbl;
+ pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
+
+ *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+static HRESULT VideoRenderer_CreatePrimarySurface(IBaseFilter * iface)
+{
+ HRESULT hr;
+ DDSURFACEDESC sdesc;
+ DDSCAPS ddscaps;
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ hr = DirectDrawCreate(NULL, &This->ddraw, NULL);
+
+ if (FAILED(hr)) {
+ ERR("Cannot create Direct Draw object\n");
+ return hr;
+ }
+
+ hr = IDirectDraw_SetCooperativeLevel(This->ddraw, NULL, DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE);
+ if (FAILED(hr)) {
+ ERR("Cannot set fulscreen mode\n");
+ return hr;
+ }
+
+ sdesc.dwSize = sizeof(sdesc);
+ sdesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ sdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
+ sdesc.dwBackBufferCount = 1;
+
+ hr = IDirectDraw_CreateSurface(This->ddraw, &sdesc, &This->surface, NULL);
+ if (FAILED(hr)) {
+ ERR("Cannot create surface\n");
+ return hr;
+ }
+
+ hr = IDirectDrawSurface_GetSurfaceDesc(This->surface, &sdesc);
+ if (FAILED(hr)) {
+ ERR("Cannot get surface information\n");
+ return hr;
+ }
+ TRACE("Width = %ld\n", sdesc.dwWidth);
+ TRACE("Height = %ld\n", sdesc.dwHeight);
+ TRACE("Pitch = %ld\n", sdesc.lPitch);
+ TRACE("Depth = %ld\n", sdesc.ddpfPixelFormat.dwRGBBitCount);
+
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ hr = IDirectDrawSurface_GetAttachedSurface(This->surface, &ddscaps, &This->backbuffer);
+ if (FAILED(hr)) {
+ ERR("Cannot get backbuffer\n");
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
+{
+ VIDEOINFOHEADER* format;
+ AM_MEDIA_TYPE amt;
+ HRESULT hr = S_OK;
+ int i = 0;
+ int j = 0;
+ LPBYTE ptr;
+ DDSURFACEDESC sdesc;
+ sdesc.dwSize = sizeof(sdesc);
+ int width;
+ int height;
+ LPBYTE palette = NULL;
+
+ TRACE("%p %p %ld\n", This, data, size);
+
+ hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
+ if (FAILED(hr)) {
+ ERR("Unable to retreive media type\n");
+ return hr;
+ }
+ format = (VIDEOINFOHEADER*)amt.pbFormat;
+
+ TRACE("biSize = %ld\n", format->bmiHeader.biSize);
+ TRACE("biWidth = %ld\n", format->bmiHeader.biWidth);
+ TRACE("biHeigth = %ld\n", format->bmiHeader.biHeight);
+ TRACE("biPlanes = %d\n", format->bmiHeader.biPlanes);
+ TRACE("biBitCount = %d\n", format->bmiHeader.biBitCount);
+ TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(format->bmiHeader.biCompression), 4));
+ TRACE("biSizeImage = %ld\n", format->bmiHeader.biSizeImage);
+
+ width = format->bmiHeader.biWidth;
+ height = format->bmiHeader.biHeight;
+ palette = ((LPBYTE)&format->bmiHeader) + format->bmiHeader.biSize;
+
+ hr = IDirectDrawSurface_Lock(This->backbuffer, NULL, &sdesc, DDLOCK_WRITEONLY, NULL);
+ if (FAILED(hr)) {
+ ERR("Cannot lock backbuffer\n");
+ return hr;
+ }
+
+ ptr = sdesc.lpSurface;
+
+ /* FIXME: We may use Direct Draw services to do the conversion for us */
+ if ((sdesc.ddpfPixelFormat.dwRGBBitCount == 24) || (sdesc.ddpfPixelFormat.dwRGBBitCount == 32))
+ {
+ if (format->bmiHeader.biBitCount == 8)
+ {
+ int psz = sdesc.ddpfPixelFormat.dwRGBBitCount == 32 ? 4 : 3;
+ for (j = 0; j < height; j++)
+ for (i = 0; i < width; i++)
+ {
+ *(ptr + i*psz + 0 + j * sdesc.lPitch) = palette[*(data + i + 0 + (height-1-j) * width)*4 + 0];
+ *(ptr + i*psz + 1 + j * sdesc.lPitch) = palette[*(data + i + 0 + (height-1-j) * width)*4 + 1];
+ *(ptr + i*psz + 2 + j * sdesc.lPitch) = palette[*(data + i + 0 + (height-1-j) * width)*4 + 2];
+ if (psz == 4)
+ *(ptr + i*psz + 3 + j * sdesc.lPitch) = 0xFF;
+ }
+ }
+ else
+ FIXME("Source size with a depths other than paletted 8 bits are not yet supported\n");
+ }
+ else
+ FIXME("Destination depths with a depth other than 24 or 32 bits are not yet supported\n");
+
+ hr = IDirectDrawSurface_Unlock(This->backbuffer, NULL);
+ if (FAILED(hr)) {
+ ERR("Cannot unlock backbuffer\n");
+ return hr;
+ }
+
+ hr = IDirectDrawSurface_Flip(This->surface, NULL, DDFLIP_WAIT);
+ if (FAILED(hr)) {
+ ERR("Cannot unlock backbuffer\n");
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+ LPBYTE pbSrcStream = NULL;
+ long cbSrcStream = 0;
+ REFERENCE_TIME tStart, tStop;
+ HRESULT hr;
+
+ TRACE("%p %p\n", iface, pSample);
+
+ hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
+ if (FAILED(hr))
+ {
+ ERR("Cannot get pointer to sample data (%lx)\n", hr);
+ return hr;
+ }
+
+ hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
+ if (FAILED(hr))
+ ERR("Cannot get sample time (%lx)\n", hr);
+
+ cbSrcStream = IMediaSample_GetActualDataLength(pSample);
+
+ TRACE("val %p %ld\n", pbSrcStream, cbSrcStream);
+
+#if 0 /* For debugging purpose */
+ {
+ int i;
+ for(i = 0; i < cbSrcStream; i++)
+ {
+ if ((i!=0) && !(i%16))
+ DPRINTF("\n");
+ DPRINTF("%02x ", pbSrcStream[i]);
+ }
+ DPRINTF("\n");
+ }
+#endif
+
+ if (!This->init)
+ {
+ This->init = 1;
+ hr = VideoRenderer_CreatePrimarySurface(iface);
+ if (FAILED(hr))
+ {
+ ERR("Unable to create primary surface\n");
+ }
+ }
+
+ VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
+
+ /* We have finished with the incoming sample, we must release it now */
+ IMediaSample_Release(pSample);
+
+ return S_OK;
+}
+
+static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+{
+ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32)) ||
+ (IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24)) ||
+ (IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565)) ||
+ (IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8)))
+ return S_OK;
+ return S_FALSE;
+}
+
+HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
+{
+ HRESULT hr;
+ PIN_INFO piInput;
+ VideoRendererImpl * pVideoRenderer;
+
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
+
+ pVideoRenderer->lpVtbl = &VideoRenderer_Vtbl;
+ pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable;
+ pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable;
+
+ pVideoRenderer->refCount = 1;
+ InitializeCriticalSection(&pVideoRenderer->csFilter);
+ pVideoRenderer->state = State_Stopped;
+ pVideoRenderer->pClock = NULL;
+ pVideoRenderer->init = 0;
+ ZeroMemory(&pVideoRenderer->filterInfo, sizeof(FILTER_INFO));
+
+ pVideoRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
+
+ /* construct input pin */
+ piInput.dir = PINDIR_INPUT;
+ piInput.pFilter = (IBaseFilter *)pVideoRenderer;
+ strncpyW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
+
+ hr = VideoRenderer_InputPin_Construct(&piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, &pVideoRenderer->csFilter, (IPin **)&pVideoRenderer->pInputPin);
+
+ if (SUCCEEDED(hr))
+ {
+ pVideoRenderer->ppPins[0] = (IPin *)pVideoRenderer->pInputPin;
+ *ppv = (LPVOID)pVideoRenderer;
+ }
+ else
+ {
+ CoTaskMemFree(pVideoRenderer->ppPins);
+ DeleteCriticalSection(&pVideoRenderer->csFilter);
+ CoTaskMemFree(pVideoRenderer);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+ TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IPersist))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IMediaFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBasicVideo))
+ *ppv = (LPVOID)&(This->IBasicVideo_vtbl);
+ else if (IsEqualIID(riid, &IID_IVideoWindow))
+ *ppv = (LPVOID)&(This->IVideoWindow_vtbl);
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+ TRACE("(%p/%p)->() AddRef from %ld\n", This, iface, This->refCount);
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+ TRACE("(%p/%p)->() Release from %ld\n", This, iface, This->refCount);
+ if (!InterlockedDecrement(&This->refCount))
+ {
+ DeleteCriticalSection(&This->csFilter);
+ IReferenceClock_Release(This->pClock);
+
+ IPin_Release(This->ppPins[0]);
+
+ HeapFree(GetProcessHeap(), 0, This->ppPins);
+ This->lpVtbl = NULL;
+
+ TRACE("Destroying Video Renderer\n");
+ CoTaskMemFree(This);
+
+ return 0;
+ }
+ else
+ return This->refCount;
+}
+
+/** IPersist methods **/
+
+static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
+
+ *pClsid = CLSID_VideoRenderer;
+
+ return S_OK;
+}
+
+/** IMediaFilter methods **/
+
+static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Stopped;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Paused;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->rtStreamStart = tStart;
+ This->state = State_Running;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%ld, %p)\n", This, iface, dwMilliSecsTimeout, pState);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *pState = This->state;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+ This->pClock = pClock;
+ if (This->pClock)
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *ppClock = This->pClock;
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+/** IBaseFilter implementation **/
+
+static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+ ENUMPINDETAILS epd;
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+ epd.cPins = 1; /* input pin */
+ epd.ppPins = This->ppPins;
+ return IEnumPinsImpl_Construct(&epd, ppEnum);
+}
+
+static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
+
+ FIXME("VideoRenderer::FindPin(...)\n");
+
+ /* FIXME: critical section */
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI VideoRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
+
+ strcpyW(pInfo->achName, This->filterInfo.achName);
+ pInfo->pGraph = This->filterInfo.pGraph;
+
+ if (pInfo->pGraph)
+ IFilterGraph_AddRef(pInfo->pGraph);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+
+ TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (pName)
+ strcpyW(This->filterInfo.achName, pName);
+ else
+ *This->filterInfo.achName = '\0';
+ This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+{
+ ICOM_THIS(VideoRendererImpl, iface);
+ TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
+ return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl VideoRenderer_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ VideoRenderer_QueryInterface,
+ VideoRenderer_AddRef,
+ VideoRenderer_Release,
+ VideoRenderer_GetClassID,
+ VideoRenderer_Stop,
+ VideoRenderer_Pause,
+ VideoRenderer_Run,
+ VideoRenderer_GetState,
+ VideoRenderer_SetSyncSource,
+ VideoRenderer_GetSyncSource,
+ VideoRenderer_EnumPins,
+ VideoRenderer_FindPin,
+ VideoRenderer_QueryFilterInfo,
+ VideoRenderer_JoinFilterGraph,
+ VideoRenderer_QueryVendorInfo
+};
+
+static const IPinVtbl VideoRenderer_InputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ InputPin_QueryInterface,
+ IPinImpl_AddRef,
+ InputPin_Release,
+ InputPin_Connect,
+ InputPin_ReceiveConnection,
+ IPinImpl_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ IPinImpl_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ InputPin_EndOfStream,
+ InputPin_BeginFlush,
+ InputPin_EndFlush,
+ InputPin_NewSegment
+};
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
+ REFIID riid,
+ LPVOID*ppvObj) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
+
+ return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
+}
+
+static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return VideoRenderer_AddRef((IBaseFilter*)This);
+}
+
+static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return VideoRenderer_Release((IBaseFilter*)This);
+}
+
+/*** IDispatch methods ***/
+static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
+ UINT*pctinfo) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo**ppTInfo) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
+ REFIID riid,
+ LPOLESTR*rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID*rgDispId) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS*pDispParams,
+ VARIANT*pVarResult,
+ EXCEPINFO*pExepInfo,
+ UINT*puArgErr) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ 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);
+
+ return S_OK;
+}
+
+/*** IBasicVideo methods ***/
+static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
+ REFTIME *pAvgTimePerFrame) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
+ long *pBitRate) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
+ long *pBitErrorRate) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
+ long *pVideoWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
+ long *pVideoHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
+ long SourceLeft) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceLeft);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
+ long *pSourceLeft) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceLeft);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
+ long SourceWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
+ long *pSourceWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
+ long SourceTop) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceTop);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
+ long *pSourceTop) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceTop);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
+ long SourceHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
+ long *pSourceHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
+ long DestinationLeft) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationLeft);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
+ long *pDestinationLeft) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationLeft);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
+ long DestinationWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
+ long *pDestinationWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
+ long DestinationTop) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationTop);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
+ long *pDestinationTop) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationTop);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
+ long DestinationHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
+ long *pDestinationHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
+ long Left,
+ long Top,
+ long Width,
+ long Height) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
+ long *pLeft,
+ long *pTop,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
+ long Left,
+ long Top,
+ long Width,
+ long Height) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
+ long *pLeft,
+ long *pTop,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
+ long StartIndex,
+ long Entries,
+ long *pRetrieved,
+ long *pPalette) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
+ long *pBufferSize,
+ long *pDIBImage) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+
+ TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+
+ return S_OK;
+}
+
+
+static IBasicVideoVtbl IBasicVideo_VTable =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ Basicvideo_QueryInterface,
+ Basicvideo_AddRef,
+ Basicvideo_Release,
+ Basicvideo_GetTypeInfoCount,
+ Basicvideo_GetTypeInfo,
+ Basicvideo_GetIDsOfNames,
+ Basicvideo_Invoke,
+ Basicvideo_get_AvgTimePerFrame,
+ Basicvideo_get_BitRate,
+ Basicvideo_get_BitErrorRate,
+ Basicvideo_get_VideoWidth,
+ Basicvideo_get_VideoHeight,
+ Basicvideo_put_SourceLeft,
+ Basicvideo_get_SourceLeft,
+ Basicvideo_put_SourceWidth,
+ Basicvideo_get_SourceWidth,
+ Basicvideo_put_SourceTop,
+ Basicvideo_get_SourceTop,
+ Basicvideo_put_SourceHeight,
+ Basicvideo_get_SourceHeight,
+ Basicvideo_put_DestinationLeft,
+ Basicvideo_get_DestinationLeft,
+ Basicvideo_put_DestinationWidth,
+ Basicvideo_get_DestinationWidth,
+ Basicvideo_put_DestinationTop,
+ Basicvideo_get_DestinationTop,
+ Basicvideo_put_DestinationHeight,
+ Basicvideo_get_DestinationHeight,
+ Basicvideo_SetSourcePosition,
+ Basicvideo_GetSourcePosition,
+ Basicvideo_SetDefaultSourcePosition,
+ Basicvideo_SetDestinationPosition,
+ Basicvideo_GetDestinationPosition,
+ Basicvideo_SetDefaultDestinationPosition,
+ Basicvideo_GetVideoSize,
+ Basicvideo_GetVideoPaletteEntries,
+ Basicvideo_GetCurrentImage,
+ Basicvideo_IsUsingDefaultSource,
+ Basicvideo_IsUsingDefaultDestination
+};
+
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
+ REFIID riid,
+ LPVOID*ppvObj) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
+
+ return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
+}
+
+static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return VideoRenderer_AddRef((IBaseFilter*)This);
+}
+
+static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return VideoRenderer_Release((IBaseFilter*)This);
+}
+
+/*** IDispatch methods ***/
+static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
+ UINT*pctinfo) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo**ppTInfo) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
+ REFIID riid,
+ LPOLESTR*rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID*rgDispId) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS*pDispParams,
+ VARIANT*pVarResult,
+ EXCEPINFO*pExepInfo,
+ UINT*puArgErr) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ 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);
+
+ return S_OK;
+}
+
+/*** IVideoWindow methods ***/
+static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
+ BSTR strCaption) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strCaption), strCaption);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
+ BSTR *strCaption) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, strCaption);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
+ long WindowStyle) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyle);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
+ long *WindowStyle) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyle);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
+ long WindowStyleEx) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyleEx);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
+ long *WindowStyleEx) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyleEx);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
+ long AutoShow) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, AutoShow);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
+ long *AutoShow) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, AutoShow);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
+ long WindowState) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
+ long *WindowState) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
+ long BackgroundPalette) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
+ long *pBackgroundPalette) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
+ long Visible) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Visible);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
+ long *pVisible) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVisible);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
+ long Left) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Left);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
+ long *pLeft) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pLeft);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
+ long Width) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Width);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
+ long *pWidth) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pWidth);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
+ long Top) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Top);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
+ long *pTop) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pTop);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
+ long Height) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Height);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
+ OAHWND Owner) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
+ OAHWND *Owner) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
+ OAHWND Drain) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Drain);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
+ OAHWND *Drain) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Drain);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
+ long *Color) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
+ long Color) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
+ long *FullScreenMode) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
+ long FullScreenMode) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
+ long Focus) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Focus);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
+ OAHWND hwnd,
+ long uMsg,
+ LONG_PTR wParam,
+ LONG_PTR lParam) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%08lx, %ld, %08lx, %08lx): stub !!!\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
+ long Left,
+ long Top,
+ long Width,
+ long Height) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
+ long *pLeft,
+ long *pTop,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
+ long *pLeft,
+ long *pTop,
+ long *pWidth,
+ long *pHeight) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
+ long HideCursor) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
+ long *CursorHidden) {
+ ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
+
+ return S_OK;
+}
+
+static IVideoWindowVtbl IVideoWindow_VTable =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ Videowindow_QueryInterface,
+ Videowindow_AddRef,
+ Videowindow_Release,
+ Videowindow_GetTypeInfoCount,
+ Videowindow_GetTypeInfo,
+ Videowindow_GetIDsOfNames,
+ Videowindow_Invoke,
+ Videowindow_put_Caption,
+ Videowindow_get_Caption,
+ Videowindow_put_WindowStyle,
+ Videowindow_get_WindowStyle,
+ Videowindow_put_WindowStyleEx,
+ Videowindow_get_WindowStyleEx,
+ Videowindow_put_AutoShow,
+ Videowindow_get_AutoShow,
+ Videowindow_put_WindowState,
+ Videowindow_get_WindowState,
+ Videowindow_put_BackgroundPalette,
+ Videowindow_get_BackgroundPalette,
+ Videowindow_put_Visible,
+ Videowindow_get_Visible,
+ Videowindow_put_Left,
+ Videowindow_get_Left,
+ Videowindow_put_Width,
+ Videowindow_get_Width,
+ Videowindow_put_Top,
+ Videowindow_get_Top,
+ Videowindow_put_Height,
+ Videowindow_get_Height,
+ Videowindow_put_Owner,
+ Videowindow_get_Owner,
+ Videowindow_put_MessageDrain,
+ Videowindow_get_MessageDrain,
+ Videowindow_get_BorderColor,
+ Videowindow_put_BorderColor,
+ Videowindow_get_FullScreenMode,
+ Videowindow_put_FullScreenMode,
+ Videowindow_SetWindowForeground,
+ Videowindow_NotifyOwnerMessage,
+ Videowindow_SetWindowPosition,
+ Videowindow_GetWindowPosition,
+ Videowindow_GetMinIdealImageSize,
+ Videowindow_GetMaxIdealImageSize,
+ Videowindow_GetRestorePosition,
+ Videowindow_HideCursor,
+ Videowindow_IsCursorHidden
+};
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/dsoundrender.c 2004-08-23 21:58:01.000000000 +0100
@@ -0,0 +1,772 @@
+/*
+ * Direct Sound Audio Renderer
+ *
+ * Copyright 2004 Christian Costa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include "quartz_private.h"
+#include "control_private.h"
+#include "pin.h"
+
+#include "uuids.h"
+#include "mmreg.h"
+#include "vfwmsgs.h"
+#include "fourcc.h"
+#include "windef.h"
+#include "winbase.h"
+#include "dshow.h"
+#include "evcode.h"
+#include "strmif.h"
+#include "dsound.h"
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
+
+static const IBaseFilterVtbl DSoundRender_Vtbl;
+static const IPinVtbl DSoundRender_InputPin_Vtbl;
+static const IMemInputPinVtbl MemInputPin_Vtbl;
+static const IBasicAudioVtbl IBasicAudio_Vtbl;
+
+typedef struct DSoundRenderImpl
+{
+ const IBaseFilterVtbl * lpVtbl;
+ const IBasicAudioVtbl *IBasicAudio_vtbl;
+
+ ULONG refCount;
+ CRITICAL_SECTION csFilter;
+ FILTER_STATE state;
+ REFERENCE_TIME rtStreamStart;
+ IReferenceClock * pClock;
+ FILTER_INFO filterInfo;
+ IMediaEventSink * pEventSink;
+
+ InputPin * pInputPin;
+ IPin ** ppPins;
+
+ LPDIRECTSOUND dsound;
+ LPDIRECTSOUNDBUFFER dsbuffer;
+ DWORD write_pos;
+ int init;
+} DSoundRenderImpl;
+
+static HRESULT DSoundRender_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ InputPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ if (pPinInfo->dir != PINDIR_INPUT)
+ {
+ ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
+ return E_INVALIDARG;
+ }
+
+ pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+
+ if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.lpVtbl = &DSoundRender_InputPin_Vtbl;
+ pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
+
+ *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+
+#define DSBUFFERSIZE 8192
+
+static HRESULT DSoundRender_CreateSoundBuffer(IBaseFilter * iface)
+{
+ HRESULT hr;
+ WAVEFORMATEX wav_fmt;
+ AM_MEDIA_TYPE amt;
+ WAVEFORMATEX* format;
+ DSBUFFERDESC buf_desc;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
+ if (FAILED(hr)) {
+ ERR("Unable to retreive media type\n");
+ return hr;
+ }
+
+ TRACE("MajorType %s\n", debugstr_guid(&amt.majortype));
+ TRACE("SubType %s\n", debugstr_guid(&amt.subtype));
+ TRACE("Format %s\n", debugstr_guid(&amt.formattype));
+ TRACE("Size %ld\n", amt.cbFormat);
+
+ dump_AM_MEDIA_TYPE(&amt);
+
+ format = (WAVEFORMATEX*)amt.pbFormat;
+ TRACE("wFormatTag = %x %x\n", format->wFormatTag, WAVE_FORMAT_PCM);
+ TRACE("nChannels = %d\n", format->nChannels);
+ TRACE("nSamplesPerSec = %lu\n", format->nSamplesPerSec);
+ TRACE("nAvgBytesPerSec = %lu\n", format->nAvgBytesPerSec);
+ TRACE("nBlockAlign = %d\n", format->nBlockAlign);
+ TRACE("wBitsPerSample = %d\n", format->wBitsPerSample);
+ TRACE("cbSize = %d\n", format->cbSize);
+
+ hr = DirectSoundCreate(NULL, &This->dsound, NULL);
+ if (FAILED(hr)) {
+ ERR("Cannot create Direct Sound object\n");
+ return hr;
+ }
+
+ wav_fmt = *format;
+ wav_fmt.cbSize = 0;
+
+ memset(&buf_desc,0,sizeof(DSBUFFERDESC));
+ buf_desc.dwSize = sizeof(DSBUFFERDESC);
+ buf_desc.dwBufferBytes = DSBUFFERSIZE;
+ buf_desc.lpwfxFormat = &wav_fmt;
+ hr = IDirectSound_CreateSoundBuffer(This->dsound, &buf_desc, &This->dsbuffer, NULL);
+ if (FAILED(hr)) {
+ ERR("Can't create sound buffer !\n");
+ return hr;
+ }
+
+ This->write_pos = 0;
+
+ return hr;
+}
+
+static DWORD DSoundRender_SendSampleData(DSoundRenderImpl* This, LPBYTE data, DWORD size)
+{
+ HRESULT result;
+ LPBYTE lpbuf1 = NULL;
+ LPBYTE lpbuf2 = NULL;
+ DWORD dwsize1 = 0;
+ DWORD dwsize2 = 0;
+ static int init_;
+ DWORD size2;
+ DWORD play_pos,buf_free;
+
+ while (1)
+ {
+ result=IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, &play_pos, NULL);
+ if (result != DS_OK) {
+ ERR("Error GetCurrentPosition: %lx\n", result);
+ break;
+ }
+ if (This->write_pos < play_pos)
+ buf_free = play_pos-This->write_pos;
+ else
+ buf_free = DSBUFFERSIZE - This->write_pos + play_pos;
+
+ size2 = min(buf_free, size);
+ result = IDirectSoundBuffer_Lock(This->dsbuffer, This->write_pos, size2, &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
+ if (result != DS_OK) {
+ ERR("Unable to lock sound buffer !\n");
+ break;
+ }
+ TRACE("write_pos=%ld, size=%ld, sz1=%ld, sz2=%ld\n", This->write_pos, size2, dwsize1, dwsize2);
+
+ memcpy(lpbuf1, data, dwsize1);
+ if (dwsize2) {
+ memcpy(lpbuf2, data + dwsize1, dwsize2);
+ }
+
+ result = IDirectSoundBuffer_Unlock(This->dsbuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
+ if (result != DS_OK)
+ ERR("Unable to unlock sound buffer !\n");
+ if (!init_)
+ {
+ result = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
+ if (result != DS_OK) {
+ ERR("Can't start playing !\n");
+ }
+ }
+ size -= dwsize1 + dwsize2;
+ data += dwsize1 + dwsize2;
+ This->write_pos = (This->write_pos + dwsize1 + dwsize2) % DSBUFFERSIZE;
+
+ if (!size)
+ break;
+ Sleep(10);
+ }
+ return 0;
+}
+
+static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ LPBYTE pbSrcStream = NULL;
+ long cbSrcStream = 0;
+ REFERENCE_TIME tStart, tStop;
+ HRESULT hr;
+
+ TRACE("%p %p\n", iface, pSample);
+
+ hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
+ if (FAILED(hr))
+ {
+ ERR("Cannot get pointer to sample data (%lx)\n", hr);
+ return hr;
+ }
+
+ hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
+ if (FAILED(hr))
+ ERR("Cannot get sample time (%lx)\n", hr);
+
+ cbSrcStream = IMediaSample_GetActualDataLength(pSample);
+
+ TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream);
+
+#if 0 /* For debugging purpose */
+ {
+ int i;
+ for(i = 0; i < cbSrcStream; i++)
+ {
+ if ((i!=0) && !(i%16))
+ DPRINTF("\n");
+ DPRINTF("%02x ", pbSrcStream[i]);
+ }
+ DPRINTF("\n");
+ }
+#endif
+
+ if (!This->init)
+ {
+ This->init = 1;
+ hr = DSoundRender_CreateSoundBuffer(iface);
+ if (FAILED(hr))
+ {
+ ERR("Unable to create DSound buffer\n");
+ }
+ }
+ DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream);
+
+ /* We have finished with the incoming sample, we must release it now */
+ IMediaSample_Release(pSample);
+
+ return S_OK;
+}
+
+static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+{
+ WAVEFORMATEX* format = (WAVEFORMATEX*)pmt->pbFormat;
+ TRACE("wFormatTag = %x %x\n", format->wFormatTag, WAVE_FORMAT_PCM);
+ TRACE("nChannels = %d\n", format->nChannels);
+ TRACE("nSamplesPerSec = %ld\n", format->nAvgBytesPerSec);
+ TRACE("nAvgBytesPerSec = %ld\n", format->nAvgBytesPerSec);
+ TRACE("nBlockAlign = %d\n", format->nBlockAlign);
+ TRACE("wBitsPerSample = %d\n", format->wBitsPerSample);
+
+ if (IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_PCM))
+ return S_OK;
+ return S_FALSE;
+}
+
+HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
+{
+ HRESULT hr;
+ PIN_INFO piInput;
+ DSoundRenderImpl * pDSoundRender;
+
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl));
+
+ pDSoundRender->lpVtbl = &DSoundRender_Vtbl;
+ pDSoundRender->IBasicAudio_vtbl = &IBasicAudio_Vtbl;
+ pDSoundRender->refCount = 1;
+ InitializeCriticalSection(&pDSoundRender->csFilter);
+ pDSoundRender->state = State_Stopped;
+ pDSoundRender->pClock = NULL;
+ pDSoundRender->init = 0;
+ ZeroMemory(&pDSoundRender->filterInfo, sizeof(FILTER_INFO));
+
+ pDSoundRender->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
+
+ /* construct input pin */
+ piInput.dir = PINDIR_INPUT;
+ piInput.pFilter = (IBaseFilter *)pDSoundRender;
+ strncpyW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
+ hr = DSoundRender_InputPin_Construct(&piInput, DSoundRender_Sample, (LPVOID)pDSoundRender, DSoundRender_QueryAccept, &pDSoundRender->csFilter, (IPin **)&pDSoundRender->pInputPin);
+
+ if (SUCCEEDED(hr))
+ {
+ pDSoundRender->ppPins[0] = (IPin *)pDSoundRender->pInputPin;
+ *ppv = (LPVOID)pDSoundRender;
+ }
+ else
+ {
+ CoTaskMemFree(pDSoundRender->ppPins);
+ DeleteCriticalSection(&pDSoundRender->csFilter);
+ CoTaskMemFree(pDSoundRender);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ TRACE("(%p, %p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IPersist))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IMediaFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = (LPVOID)&(This->IBasicAudio_vtbl);
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DSoundRender_AddRef(IBaseFilter * iface)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ TRACE("(%p/%p)->()\n", This, iface);
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ TRACE("(%p/%p)->()\n", This, iface);
+ if (!InterlockedDecrement(&This->refCount))
+ {
+ DeleteCriticalSection(&This->csFilter);
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+
+ IPin_Release(This->ppPins[0]);
+
+ HeapFree(GetProcessHeap(), 0, This->ppPins);
+ This->lpVtbl = NULL;
+ This->IBasicAudio_vtbl = NULL;
+
+ TRACE("Destroying Audio Renderer\n");
+ CoTaskMemFree(This);
+
+ return 0;
+ }
+ else
+ return This->refCount;
+}
+
+/** IPersist methods **/
+
+static HRESULT WINAPI DSoundRender_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
+
+ *pClsid = CLSID_DSoundRender;
+
+ return S_OK;
+}
+
+/** IMediaFilter methods **/
+
+static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface)
+{
+ HRESULT hr = S_OK;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Stopped;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
+{
+ HRESULT hr = S_OK;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->state = State_Paused;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+{
+ HRESULT hr = S_OK;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->rtStreamStart = tStart;
+ This->state = State_Running;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%ld, %p)\n", This, iface, dwMilliSecsTimeout, pState);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *pState = This->state;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DSoundRender_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+ This->pClock = pClock;
+ if (This->pClock)
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DSoundRender_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *ppClock = This->pClock;
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+/** IBaseFilter implementation **/
+
+static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+ ENUMPINDETAILS epd;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+ epd.cPins = 1; /* input pin */
+ epd.ppPins = This->ppPins;
+ return IEnumPinsImpl_Construct(&epd, ppEnum);
+}
+
+static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin);
+
+ FIXME("DSoundRender::FindPin(...)\n");
+
+ /* FIXME: critical section */
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DSoundRender_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
+
+ strcpyW(pInfo->achName, This->filterInfo.achName);
+ pInfo->pGraph = This->filterInfo.pGraph;
+
+ if (pInfo->pGraph)
+ IFilterGraph_AddRef(pInfo->pGraph);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+{
+ HRESULT hr;
+ ICOM_THIS(DSoundRenderImpl, iface);
+
+ TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (pName)
+ strcpyW(This->filterInfo.achName, pName);
+ else
+ *This->filterInfo.achName = '\0';
+ This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+
+ hr = IFilterGraph_QueryInterface(pGraph, &IID_IMediaEventSink, (LPVOID*)&This->pEventSink);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI DSoundRender_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+{
+ ICOM_THIS(DSoundRenderImpl, iface);
+ TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
+ return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl DSoundRender_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DSoundRender_QueryInterface,
+ DSoundRender_AddRef,
+ DSoundRender_Release,
+ DSoundRender_GetClassID,
+ DSoundRender_Stop,
+ DSoundRender_Pause,
+ DSoundRender_Run,
+ DSoundRender_GetState,
+ DSoundRender_SetSyncSource,
+ DSoundRender_GetSyncSource,
+ DSoundRender_EnumPins,
+ DSoundRender_FindPin,
+ DSoundRender_QueryFilterInfo,
+ DSoundRender_JoinFilterGraph,
+ DSoundRender_QueryVendorInfo
+};
+
+static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
+{
+ /* FIXME: critical section */
+ InputPin* This = (InputPin*)iface;
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return IMediaEventSink_Notify(((DSoundRenderImpl*)This->pin.pinInfo.pFilter)->pEventSink, EC_COMPLETE, S_OK, 0);
+}
+
+static const IPinVtbl DSoundRender_InputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ InputPin_QueryInterface,
+ IPinImpl_AddRef,
+ InputPin_Release,
+ InputPin_Connect,
+ InputPin_ReceiveConnection,
+ IPinImpl_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ IPinImpl_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ DSoundRender_InputPin_EndOfStream,
+ InputPin_BeginFlush,
+ InputPin_EndFlush,
+ InputPin_NewSegment
+};
+
+static const IMemInputPinVtbl MemInputPin_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ MemInputPin_QueryInterface,
+ MemInputPin_AddRef,
+ MemInputPin_Release,
+ MemInputPin_GetAllocator,
+ MemInputPin_NotifyAllocator,
+ MemInputPin_GetAllocatorRequirements,
+ MemInputPin_Receive,
+ MemInputPin_ReceiveMultiple,
+ MemInputPin_ReceiveCanBlock
+};
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface,
+ REFIID riid,
+ LPVOID*ppvObj) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
+
+ return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj);
+}
+
+static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return DSoundRender_AddRef((IBaseFilter*)This);
+}
+
+static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->()\n", This, iface);
+
+ return DSoundRender_Release((IBaseFilter*)This);
+}
+
+/*** IDispatch methods ***/
+static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface,
+ UINT*pctinfo) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo**ppTInfo) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface,
+ REFIID riid,
+ LPOLESTR*rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID*rgDispId) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS*pDispParams,
+ VARIANT*pVarResult,
+ EXCEPINFO*pExepInfo,
+ UINT*puArgErr) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ 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);
+
+ return S_OK;
+}
+
+/*** IBasicAudio methods ***/
+static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface,
+ long lVolume) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lVolume);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface,
+ long *plVolume) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plVolume);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface,
+ long lBalance) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lBalance);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface,
+ long *plBalance) {
+ ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface);
+
+ TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plBalance);
+
+ return S_OK;
+}
+
+static const IBasicAudioVtbl IBasicAudio_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ Basicaudio_QueryInterface,
+ Basicaudio_AddRef,
+ Basicaudio_Release,
+ Basicaudio_GetTypeInfoCount,
+ Basicaudio_GetTypeInfo,
+ Basicaudio_GetIDsOfNames,
+ Basicaudio_Invoke,
+ Basicaudio_put_Volume,
+ Basicaudio_get_Volume,
+ Basicaudio_put_Balance,
+ Basicaudio_get_Balance
+};
More information about the wine-patches
mailing list