2 * Generic Implementation of IBaseFilter Interface
4 * Copyright 2010 Aric Stewart, CodeWeavers
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
21 #include "strmbase_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(strmbase
);
27 IEnumPins IEnumPins_iface
;
30 unsigned int index
, count
;
32 struct strmbase_filter
*filter
;
35 static const IEnumPinsVtbl enum_pins_vtbl
;
37 static HRESULT
enum_pins_create(struct strmbase_filter
*filter
, IEnumPins
**out
)
39 struct enum_pins
*object
;
44 if (!(object
= heap_alloc_zero(sizeof(*object
))))
50 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
52 object
->filter
= filter
;
53 IBaseFilter_AddRef(&filter
->IBaseFilter_iface
);
54 object
->version
= filter
->pin_version
;
56 while (filter
->ops
->filter_get_pin(filter
, object
->count
))
59 TRACE("Created enumerator %p.\n", object
);
60 *out
= &object
->IEnumPins_iface
;
65 static inline struct enum_pins
*impl_from_IEnumPins(IEnumPins
*iface
)
67 return CONTAINING_RECORD(iface
, struct enum_pins
, IEnumPins_iface
);
70 static HRESULT WINAPI
enum_pins_QueryInterface(IEnumPins
*iface
, REFIID iid
, void **out
)
72 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
74 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumPins
))
76 IEnumPins_AddRef(iface
);
81 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
86 static ULONG WINAPI
enum_pins_AddRef(IEnumPins
*iface
)
88 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
89 ULONG refcount
= InterlockedIncrement(&enum_pins
->refcount
);
90 TRACE("%p increasing refcount to %u.\n", enum_pins
, refcount
);
94 static ULONG WINAPI
enum_pins_Release(IEnumPins
*iface
)
96 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
97 ULONG refcount
= InterlockedDecrement(&enum_pins
->refcount
);
99 TRACE("%p decreasing refcount to %u.\n", enum_pins
, refcount
);
102 IBaseFilter_Release(&enum_pins
->filter
->IBaseFilter_iface
);
103 heap_free(enum_pins
);
108 static HRESULT WINAPI
enum_pins_Next(IEnumPins
*iface
, ULONG count
, IPin
**pins
, ULONG
*ret_count
)
110 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
113 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface
, count
, pins
, ret_count
);
118 if (count
> 1 && !ret_count
)
124 if (enum_pins
->version
!= enum_pins
->filter
->pin_version
)
127 for (i
= 0; i
< count
; ++i
)
129 struct strmbase_pin
*pin
= enum_pins
->filter
->ops
->filter_get_pin(enum_pins
->filter
, enum_pins
->index
+ i
);
134 IPin_AddRef(pins
[i
] = &pin
->IPin_iface
);
139 enum_pins
->index
+= i
;
140 return i
== count
? S_OK
: S_FALSE
;
143 static HRESULT WINAPI
enum_pins_Skip(IEnumPins
*iface
, ULONG count
)
145 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
147 TRACE("iface %p, count %u.\n", iface
, count
);
149 if (enum_pins
->version
!= enum_pins
->filter
->pin_version
)
150 return VFW_E_ENUM_OUT_OF_SYNC
;
152 if (enum_pins
->index
+ count
> enum_pins
->count
)
155 enum_pins
->index
+= count
;
159 static HRESULT WINAPI
enum_pins_Reset(IEnumPins
*iface
)
161 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
163 TRACE("iface %p.\n", iface
);
165 if (enum_pins
->version
!= enum_pins
->filter
->pin_version
)
167 enum_pins
->count
= 0;
168 while (enum_pins
->filter
->ops
->filter_get_pin(enum_pins
->filter
, enum_pins
->count
))
172 enum_pins
->version
= enum_pins
->filter
->pin_version
;
173 enum_pins
->index
= 0;
178 static HRESULT WINAPI
enum_pins_Clone(IEnumPins
*iface
, IEnumPins
**out
)
180 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
183 TRACE("iface %p, out %p.\n", iface
, out
);
185 if (FAILED(hr
= enum_pins_create(enum_pins
->filter
, out
)))
187 return IEnumPins_Skip(*out
, enum_pins
->index
);
190 static const IEnumPinsVtbl enum_pins_vtbl
=
192 enum_pins_QueryInterface
,
201 static inline struct strmbase_filter
*impl_from_IUnknown(IUnknown
*iface
)
203 return CONTAINING_RECORD(iface
, struct strmbase_filter
, IUnknown_inner
);
206 static HRESULT WINAPI
filter_inner_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
208 struct strmbase_filter
*filter
= impl_from_IUnknown(iface
);
211 TRACE("filter %p %s, iid %s, out %p.\n", filter
, debugstr_w(filter
->name
), debugstr_guid(iid
), out
);
215 if (filter
->ops
->filter_query_interface
216 && SUCCEEDED(hr
= filter
->ops
->filter_query_interface(filter
, iid
, out
)))
221 if (IsEqualIID(iid
, &IID_IUnknown
))
223 else if (IsEqualIID(iid
, &IID_IPersist
)
224 || IsEqualIID(iid
, &IID_IMediaFilter
)
225 || IsEqualIID(iid
, &IID_IBaseFilter
))
227 *out
= &filter
->IBaseFilter_iface
;
231 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
232 return E_NOINTERFACE
;
235 IUnknown_AddRef((IUnknown
*)*out
);
239 static ULONG WINAPI
filter_inner_AddRef(IUnknown
*iface
)
241 struct strmbase_filter
*filter
= impl_from_IUnknown(iface
);
242 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
244 TRACE("%p increasing refcount to %u.\n", filter
, refcount
);
249 static ULONG WINAPI
filter_inner_Release(IUnknown
*iface
)
251 struct strmbase_filter
*filter
= impl_from_IUnknown(iface
);
252 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
254 TRACE("%p decreasing refcount to %u.\n", filter
, refcount
);
257 filter
->ops
->filter_destroy(filter
);
262 static const IUnknownVtbl filter_inner_vtbl
=
264 filter_inner_QueryInterface
,
266 filter_inner_Release
,
269 static inline struct strmbase_filter
*impl_from_IBaseFilter(IBaseFilter
*iface
)
271 return CONTAINING_RECORD(iface
, struct strmbase_filter
, IBaseFilter_iface
);
274 static HRESULT WINAPI
filter_QueryInterface(IBaseFilter
*iface
, REFIID iid
, void **out
)
276 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
277 return IUnknown_QueryInterface(filter
->outer_unk
, iid
, out
);
280 static ULONG WINAPI
filter_AddRef(IBaseFilter
*iface
)
282 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
283 return IUnknown_AddRef(filter
->outer_unk
);
286 static ULONG WINAPI
filter_Release(IBaseFilter
*iface
)
288 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
289 return IUnknown_Release(filter
->outer_unk
);
292 static HRESULT WINAPI
filter_GetClassID(IBaseFilter
*iface
, CLSID
*clsid
)
294 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
296 TRACE("filter %p %s, clsid %p.\n", filter
, debugstr_w(filter
->name
), clsid
);
298 *clsid
= filter
->clsid
;
303 static HRESULT WINAPI
filter_Stop(IBaseFilter
*iface
)
305 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
308 TRACE("filter %p %s.\n", filter
, debugstr_w(filter
->name
));
310 EnterCriticalSection(&filter
->filter_cs
);
312 if (filter
->state
== State_Running
&& filter
->ops
->filter_stop_stream
)
313 hr
= filter
->ops
->filter_stop_stream(filter
);
314 if (SUCCEEDED(hr
) && filter
->ops
->filter_cleanup_stream
)
315 hr
= filter
->ops
->filter_cleanup_stream(filter
);
317 filter
->state
= State_Stopped
;
319 LeaveCriticalSection(&filter
->filter_cs
);
324 static HRESULT WINAPI
filter_Pause(IBaseFilter
*iface
)
326 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
329 TRACE("filter %p %s.\n", filter
, debugstr_w(filter
->name
));
331 EnterCriticalSection(&filter
->filter_cs
);
333 if (filter
->state
== State_Stopped
&& filter
->ops
->filter_init_stream
)
334 hr
= filter
->ops
->filter_init_stream(filter
);
335 else if (filter
->state
== State_Running
&& filter
->ops
->filter_stop_stream
)
336 hr
= filter
->ops
->filter_stop_stream(filter
);
338 filter
->state
= State_Paused
;
340 LeaveCriticalSection(&filter
->filter_cs
);
345 static HRESULT WINAPI
filter_Run(IBaseFilter
*iface
, REFERENCE_TIME start
)
347 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
350 TRACE("filter %p %s, start %s.\n", filter
, debugstr_w(filter
->name
), debugstr_time(start
));
352 EnterCriticalSection(&filter
->filter_cs
);
354 if (filter
->state
== State_Stopped
&& filter
->ops
->filter_init_stream
)
355 hr
= filter
->ops
->filter_init_stream(filter
);
356 if (SUCCEEDED(hr
) && filter
->ops
->filter_start_stream
)
357 hr
= filter
->ops
->filter_start_stream(filter
, start
);
359 filter
->state
= State_Running
;
361 LeaveCriticalSection(&filter
->filter_cs
);
366 static HRESULT WINAPI
filter_GetState(IBaseFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
368 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
371 TRACE("filter %p %s, timeout %u, state %p.\n", filter
, debugstr_w(filter
->name
), timeout
, state
);
373 EnterCriticalSection(&filter
->filter_cs
);
375 if (filter
->ops
->filter_wait_state
)
376 hr
= filter
->ops
->filter_wait_state(filter
, timeout
);
377 *state
= filter
->state
;
379 LeaveCriticalSection(&filter
->filter_cs
);
384 static HRESULT WINAPI
filter_SetSyncSource(IBaseFilter
*iface
, IReferenceClock
*clock
)
386 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
388 TRACE("filter %p %s, clock %p.\n", filter
, debugstr_w(filter
->name
), clock
);
390 EnterCriticalSection(&filter
->filter_cs
);
393 IReferenceClock_Release(filter
->clock
);
394 filter
->clock
= clock
;
396 IReferenceClock_AddRef(filter
->clock
);
398 LeaveCriticalSection(&filter
->filter_cs
);
403 static HRESULT WINAPI
filter_GetSyncSource(IBaseFilter
*iface
, IReferenceClock
**clock
)
405 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
407 TRACE("filter %p %s, clock %p.\n", filter
, debugstr_w(filter
->name
), clock
);
409 EnterCriticalSection(&filter
->filter_cs
);
411 *clock
= filter
->clock
;
413 IReferenceClock_AddRef(filter
->clock
);
415 LeaveCriticalSection(&filter
->filter_cs
);
420 static HRESULT WINAPI
filter_EnumPins(IBaseFilter
*iface
, IEnumPins
**enum_pins
)
422 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
424 TRACE("filter %p %s, enum_pins %p.\n", filter
, debugstr_w(filter
->name
), enum_pins
);
426 return enum_pins_create(filter
, enum_pins
);
429 static HRESULT WINAPI
filter_FindPin(IBaseFilter
*iface
, const WCHAR
*id
, IPin
**ret
)
431 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
432 struct strmbase_pin
*pin
;
435 TRACE("filter %p %s, id %s, ret %p.\n", filter
, debugstr_w(filter
->name
), debugstr_w(id
), ret
);
437 for (i
= 0; (pin
= filter
->ops
->filter_get_pin(filter
, i
)); ++i
)
439 if (!lstrcmpW(id
, pin
->name
))
441 IPin_AddRef(*ret
= &pin
->IPin_iface
);
446 return VFW_E_NOT_FOUND
;
449 static HRESULT WINAPI
filter_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*info
)
451 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
453 TRACE("filter %p %s, info %p.\n", filter
, debugstr_w(filter
->name
), info
);
455 lstrcpyW(info
->achName
, filter
->name
);
456 info
->pGraph
= filter
->graph
;
459 IFilterGraph_AddRef(info
->pGraph
);
464 static HRESULT WINAPI
filter_JoinFilterGraph(IBaseFilter
*iface
, IFilterGraph
*graph
, const WCHAR
*name
)
466 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
468 TRACE("filter %p %s, graph %p, name %s.\n", filter
, debugstr_w(filter
->name
), graph
, debugstr_w(name
));
470 EnterCriticalSection(&filter
->filter_cs
);
473 lstrcpynW(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
476 /* The graph references us, so we cannot also reference the graph. */
477 filter
->graph
= graph
;
479 LeaveCriticalSection(&filter
->filter_cs
);
484 static HRESULT WINAPI
filter_QueryVendorInfo(IBaseFilter
*iface
, WCHAR
**info
)
486 struct strmbase_filter
*filter
= impl_from_IBaseFilter(iface
);
488 TRACE("filter %p %s, info %p.\n", filter
, debugstr_w(filter
->name
), info
);
493 static const IBaseFilterVtbl filter_vtbl
=
495 filter_QueryInterface
,
503 filter_SetSyncSource
,
504 filter_GetSyncSource
,
507 filter_QueryFilterInfo
,
508 filter_JoinFilterGraph
,
509 filter_QueryVendorInfo
,
512 VOID WINAPI
BaseFilterImpl_IncrementPinVersion(struct strmbase_filter
*filter
)
514 InterlockedIncrement(&filter
->pin_version
);
517 void strmbase_filter_init(struct strmbase_filter
*filter
, IUnknown
*outer
,
518 const CLSID
*clsid
, const struct strmbase_filter_ops
*ops
)
520 memset(filter
, 0, sizeof(*filter
));
522 filter
->IBaseFilter_iface
.lpVtbl
= &filter_vtbl
;
523 filter
->IUnknown_inner
.lpVtbl
= &filter_inner_vtbl
;
524 filter
->outer_unk
= outer
? outer
: &filter
->IUnknown_inner
;
525 filter
->refcount
= 1;
527 InitializeCriticalSection(&filter
->filter_cs
);
528 if (filter
->filter_cs
.DebugInfo
!= (RTL_CRITICAL_SECTION_DEBUG
*)-1)
529 filter
->filter_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": strmbase_filter.filter_cs");
530 InitializeCriticalSection(&filter
->stream_cs
);
531 if (filter
->stream_cs
.DebugInfo
!= (RTL_CRITICAL_SECTION_DEBUG
*)-1)
532 filter
->stream_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": strmbase_filter.stream_cs");
533 filter
->clsid
= *clsid
;
534 filter
->pin_version
= 1;
538 void strmbase_filter_cleanup(struct strmbase_filter
*filter
)
541 IReferenceClock_Release(filter
->clock
);
543 filter
->IBaseFilter_iface
.lpVtbl
= NULL
;
544 if (filter
->filter_cs
.DebugInfo
!= (RTL_CRITICAL_SECTION_DEBUG
*)-1)
545 filter
->filter_cs
.DebugInfo
->Spare
[0] = 0;
546 DeleteCriticalSection(&filter
->filter_cs
);
547 if (filter
->stream_cs
.DebugInfo
!= (RTL_CRITICAL_SECTION_DEBUG
*)-1)
548 filter
->stream_cs
.DebugInfo
->Spare
[0] = 0;
549 DeleteCriticalSection(&filter
->stream_cs
);