[QUARTZ][STRMBASE]
[reactos.git] / reactos / lib / 3rdparty / strmbase / filter.c
1 /*
2 * Generic Implementation of IBaseFilter Interface
3 *
4 * Copyright 2010 Aric Stewart, CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "strmbase_private.h"
22
23 static inline BaseFilter *impl_from_IBaseFilter(IBaseFilter *iface)
24 {
25 return CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface);
26 }
27
28 HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
29 {
30 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
31
32 *ppv = NULL;
33
34 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPersist) ||
35 IsEqualIID(riid, &IID_IMediaFilter) || IsEqualIID(riid, &IID_IBaseFilter))
36 {
37 *ppv = iface;
38 IBaseFilter_AddRef(iface);
39 return S_OK;
40 }
41
42 return E_NOINTERFACE;
43 }
44
45 ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface)
46 {
47 BaseFilter *This = impl_from_IBaseFilter(iface);
48 ULONG refCount = InterlockedIncrement(&This->refCount);
49
50 TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
51
52 return refCount;
53 }
54
55 ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface)
56 {
57 BaseFilter *This = impl_from_IBaseFilter(iface);
58 ULONG refCount = InterlockedDecrement(&This->refCount);
59
60 TRACE("(%p)->() Release from %d\n", This, refCount + 1);
61
62 if (!refCount)
63 BaseFilter_Destroy(This);
64
65 return refCount;
66 }
67
68 HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid)
69 {
70 BaseFilter *This = impl_from_IBaseFilter(iface);
71 TRACE("(%p)->(%p)\n", This, pClsid);
72
73 *pClsid = This->clsid;
74
75 return S_OK;
76 }
77
78 HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState )
79 {
80 BaseFilter *This = impl_from_IBaseFilter(iface);
81 TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState);
82
83 EnterCriticalSection(&This->csFilter);
84 {
85 *pState = This->state;
86 }
87 LeaveCriticalSection(&This->csFilter);
88
89 return S_OK;
90 }
91
92 HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
93 {
94 BaseFilter *This = impl_from_IBaseFilter(iface);
95 TRACE("(%p)->(%p)\n", This, pClock);
96
97 EnterCriticalSection(&This->csFilter);
98 {
99 if (This->pClock)
100 IReferenceClock_Release(This->pClock);
101 This->pClock = pClock;
102 if (This->pClock)
103 IReferenceClock_AddRef(This->pClock);
104 }
105 LeaveCriticalSection(&This->csFilter);
106
107 return S_OK;
108 }
109
110 HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
111 {
112 BaseFilter *This = impl_from_IBaseFilter(iface);
113 TRACE("(%p)->(%p)\n", This, ppClock);
114
115 EnterCriticalSection(&This->csFilter);
116 {
117 *ppClock = This->pClock;
118 if (This->pClock)
119 IReferenceClock_AddRef(This->pClock);
120 }
121 LeaveCriticalSection(&This->csFilter);
122
123 return S_OK;
124 }
125
126 HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
127 {
128 BaseFilter *This = impl_from_IBaseFilter(iface);
129
130 TRACE("(%p)->(%p)\n", iface, ppEnum);
131
132 return EnumPins_Construct(This, This->pFuncsTable->pfnGetPin, This->pFuncsTable->pfnGetPinCount, BaseFilterImpl_GetPinVersion, ppEnum);
133 }
134
135
136 HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
137 {
138 BaseFilter *This = impl_from_IBaseFilter(iface);
139 TRACE("(%p)->(%p)\n", This, pInfo);
140
141 strcpyW(pInfo->achName, This->filterInfo.achName);
142 pInfo->pGraph = This->filterInfo.pGraph;
143
144 if (pInfo->pGraph)
145 IFilterGraph_AddRef(pInfo->pGraph);
146
147 return S_OK;
148 }
149
150 HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName )
151 {
152 HRESULT hr = S_OK;
153 BaseFilter *This = impl_from_IBaseFilter(iface);
154
155 TRACE("(%p)->(%p, %s)\n", This, pGraph, debugstr_w(pName));
156
157 EnterCriticalSection(&This->csFilter);
158 {
159 if (pName)
160 strcpyW(This->filterInfo.achName, pName);
161 else
162 *This->filterInfo.achName = '\0';
163 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
164 }
165 LeaveCriticalSection(&This->csFilter);
166
167 return hr;
168 }
169
170 HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
171 {
172 TRACE("(%p)->(%p)\n", iface, pVendorInfo);
173 return E_NOTIMPL;
174 }
175
176 LONG WINAPI BaseFilterImpl_GetPinVersion(BaseFilter * This)
177 {
178 TRACE("(%p)\n", This);
179 return This->pinVersion;
180 }
181
182 VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter * This)
183 {
184 InterlockedIncrement(&This->pinVersion);
185 TRACE("(%p) -> New pinVersion %i\n", This,This->pinVersion);
186 }
187
188 HRESULT WINAPI BaseFilter_Init(BaseFilter * This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseFilterFuncTable* pBaseFuncsTable)
189 {
190 This->IBaseFilter_iface.lpVtbl = Vtbl;
191 This->refCount = 1;
192 InitializeCriticalSection(&This->csFilter);
193 This->state = State_Stopped;
194 This->rtStreamStart = 0;
195 This->pClock = NULL;
196 ZeroMemory(&This->filterInfo, sizeof(FILTER_INFO));
197 This->clsid = *pClsid;
198 This->csFilter.DebugInfo->Spare[0] = DebugInfo;
199 This->pinVersion = 1;
200
201 This->pFuncsTable = pBaseFuncsTable;
202
203 return S_OK;
204 }
205
206 HRESULT WINAPI BaseFilter_Destroy(BaseFilter * This)
207 {
208 if (This->pClock)
209 IReferenceClock_Release(This->pClock);
210
211 This->IBaseFilter_iface.lpVtbl = NULL;
212 This->csFilter.DebugInfo->Spare[0] = 0;
213 DeleteCriticalSection(&This->csFilter);
214
215 return S_OK;
216 }