amstream: Implement MediaStreamFilter::GetState.
[wine.git] / dlls / amstream / filter.c
blob1cb2ca71bacf67a0c0a547ba783631459fa8d7c3
1 /*
2 * Implementation of MediaStream Filter
4 * Copyright 2008, 2012 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #include "amstream_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
27 struct enum_pins
29 IEnumPins IEnumPins_iface;
30 LONG refcount;
32 IPin **pins;
33 unsigned int count, index;
36 static const IEnumPinsVtbl enum_pins_vtbl;
38 static struct enum_pins *impl_from_IEnumPins(IEnumPins *iface)
40 return CONTAINING_RECORD(iface, struct enum_pins, IEnumPins_iface);
43 static HRESULT WINAPI enum_pins_QueryInterface(IEnumPins *iface, REFIID iid, void **out)
45 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
47 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumPins))
49 IEnumPins_AddRef(iface);
50 *out = iface;
51 return S_OK;
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
55 *out = NULL;
56 return E_NOINTERFACE;
59 static ULONG WINAPI enum_pins_AddRef(IEnumPins *iface)
61 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
62 ULONG refcount = InterlockedIncrement(&enum_pins->refcount);
63 TRACE("%p increasing refcount to %u.\n", enum_pins, refcount);
64 return refcount;
67 static ULONG WINAPI enum_pins_Release(IEnumPins *iface)
69 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
70 ULONG refcount = InterlockedDecrement(&enum_pins->refcount);
71 unsigned int i;
73 TRACE("%p decreasing refcount to %u.\n", enum_pins, refcount);
74 if (!refcount)
76 for (i = 0; i < enum_pins->count; ++i)
77 IPin_Release(enum_pins->pins[i]);
78 heap_free(enum_pins->pins);
79 heap_free(enum_pins);
81 return refcount;
84 static HRESULT WINAPI enum_pins_Next(IEnumPins *iface, ULONG count, IPin **pins, ULONG *ret_count)
86 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
87 unsigned int i;
89 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface, count, pins, ret_count);
91 if (!pins || (count > 1 && !ret_count))
92 return E_POINTER;
94 for (i = 0; i < count && enum_pins->index < enum_pins->count; ++i)
96 IPin_AddRef(pins[i] = enum_pins->pins[i]);
97 enum_pins->index++;
100 if (ret_count) *ret_count = i;
101 return i == count ? S_OK : S_FALSE;
104 static HRESULT WINAPI enum_pins_Skip(IEnumPins *iface, ULONG count)
106 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
108 TRACE("iface %p, count %u.\n", iface, count);
110 enum_pins->index += count;
112 return enum_pins->index >= enum_pins->count ? S_FALSE : S_OK;
115 static HRESULT WINAPI enum_pins_Reset(IEnumPins *iface)
117 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
119 TRACE("iface %p.\n", iface);
121 enum_pins->index = 0;
122 return S_OK;
125 static HRESULT WINAPI enum_pins_Clone(IEnumPins *iface, IEnumPins **out)
127 struct enum_pins *enum_pins = impl_from_IEnumPins(iface);
128 struct enum_pins *object;
129 unsigned int i;
131 TRACE("iface %p, out %p.\n", iface, out);
133 if (!(object = heap_alloc(sizeof(*object))))
134 return E_OUTOFMEMORY;
136 object->IEnumPins_iface.lpVtbl = &enum_pins_vtbl;
137 object->refcount = 1;
138 object->count = enum_pins->count;
139 object->index = enum_pins->index;
140 if (!(object->pins = heap_alloc(enum_pins->count * sizeof(*object->pins))))
142 heap_free(object);
143 return E_OUTOFMEMORY;
145 for (i = 0; i < enum_pins->count; ++i)
146 IPin_AddRef(object->pins[i] = enum_pins->pins[i]);
148 *out = &object->IEnumPins_iface;
149 return S_OK;
152 static const IEnumPinsVtbl enum_pins_vtbl =
154 enum_pins_QueryInterface,
155 enum_pins_AddRef,
156 enum_pins_Release,
157 enum_pins_Next,
158 enum_pins_Skip,
159 enum_pins_Reset,
160 enum_pins_Clone,
163 struct filter
165 IMediaStreamFilter IMediaStreamFilter_iface;
166 LONG refcount;
167 CRITICAL_SECTION cs;
169 IReferenceClock *clock;
170 WCHAR name[128];
171 IFilterGraph *graph;
172 ULONG nb_streams;
173 IAMMediaStream **streams;
174 FILTER_STATE state;
177 static inline struct filter *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface)
179 return CONTAINING_RECORD(iface, struct filter, IMediaStreamFilter_iface);
182 static HRESULT WINAPI filter_QueryInterface(IMediaStreamFilter *iface, REFIID riid, void **ret_iface)
184 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
186 *ret_iface = NULL;
188 if (IsEqualIID(riid, &IID_IUnknown) ||
189 IsEqualIID(riid, &IID_IPersist) ||
190 IsEqualIID(riid, &IID_IMediaFilter) ||
191 IsEqualIID(riid, &IID_IBaseFilter) ||
192 IsEqualIID(riid, &IID_IMediaStreamFilter))
193 *ret_iface = iface;
195 if (*ret_iface)
197 IMediaStreamFilter_AddRef(*ret_iface);
198 return S_OK;
201 return E_NOINTERFACE;
204 static ULONG WINAPI filter_AddRef(IMediaStreamFilter *iface)
206 struct filter *filter = impl_from_IMediaStreamFilter(iface);
207 ULONG refcount = InterlockedIncrement(&filter->refcount);
209 TRACE("%p increasing refcount to %u.\n", iface, refcount);
211 return refcount;
214 static ULONG WINAPI filter_Release(IMediaStreamFilter *iface)
216 struct filter *filter = impl_from_IMediaStreamFilter(iface);
217 ULONG refcount = InterlockedDecrement(&filter->refcount);
218 unsigned int i;
220 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
222 if (!refcount)
224 for (i = 0; i < filter->nb_streams; ++i)
226 IAMMediaStream_JoinFilter(filter->streams[i], NULL);
227 IAMMediaStream_Release(filter->streams[i]);
229 heap_free(filter->streams);
230 if (filter->clock)
231 IReferenceClock_Release(filter->clock);
232 DeleteCriticalSection(&filter->cs);
233 heap_free(filter);
236 return refcount;
239 static HRESULT WINAPI filter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
241 *clsid = CLSID_MediaStreamFilter;
242 return S_OK;
245 static HRESULT WINAPI filter_Stop(IMediaStreamFilter *iface)
247 FIXME("(%p)->(): Stub!\n", iface);
249 return E_NOTIMPL;
252 static HRESULT WINAPI filter_Pause(IMediaStreamFilter *iface)
254 FIXME("(%p)->(): Stub!\n", iface);
256 return E_NOTIMPL;
259 static HRESULT WINAPI filter_Run(IMediaStreamFilter *iface, REFERENCE_TIME start)
261 FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(start));
263 return E_NOTIMPL;
266 static HRESULT WINAPI filter_GetState(IMediaStreamFilter *iface, DWORD timeout, FILTER_STATE *state)
268 struct filter *filter = impl_from_IMediaStreamFilter(iface);
270 TRACE("iface %p, timeout %u, state %p.\n", iface, timeout, state);
272 if (!state)
273 return E_POINTER;
275 EnterCriticalSection(&filter->cs);
277 *state = filter->state;
279 LeaveCriticalSection(&filter->cs);
281 return S_OK;
284 static HRESULT WINAPI filter_SetSyncSource(IMediaStreamFilter *iface, IReferenceClock *clock)
286 struct filter *filter = impl_from_IMediaStreamFilter(iface);
288 TRACE("iface %p, clock %p.\n", iface, clock);
290 EnterCriticalSection(&filter->cs);
292 if (clock)
293 IReferenceClock_AddRef(clock);
294 if (filter->clock)
295 IReferenceClock_Release(filter->clock);
296 filter->clock = clock;
298 LeaveCriticalSection(&filter->cs);
300 return S_OK;
303 static HRESULT WINAPI filter_GetSyncSource(IMediaStreamFilter *iface, IReferenceClock **clock)
305 struct filter *filter = impl_from_IMediaStreamFilter(iface);
307 TRACE("iface %p, clock %p.\n", iface, clock);
309 EnterCriticalSection(&filter->cs);
311 if (filter->clock)
312 IReferenceClock_AddRef(filter->clock);
313 *clock = filter->clock;
315 LeaveCriticalSection(&filter->cs);
317 return S_OK;
320 static HRESULT WINAPI filter_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
322 struct filter *filter = impl_from_IMediaStreamFilter(iface);
323 struct enum_pins *object;
324 unsigned int i;
326 TRACE("iface %p, enum_pins %p.\n", iface, enum_pins);
328 EnterCriticalSection(&filter->cs);
330 if (!enum_pins)
331 return E_POINTER;
333 if (!(object = heap_alloc(sizeof(*object))))
334 return E_OUTOFMEMORY;
336 object->IEnumPins_iface.lpVtbl = &enum_pins_vtbl;
337 object->refcount = 1;
338 object->count = filter->nb_streams;
339 object->index = 0;
340 if (!(object->pins = heap_alloc(filter->nb_streams * sizeof(*object->pins))))
342 heap_free(object);
343 return E_OUTOFMEMORY;
345 for (i = 0; i < filter->nb_streams; ++i)
347 if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&object->pins[i])))
348 WARN("Stream %p does not support IPin.\n", filter->streams[i]);
351 LeaveCriticalSection(&filter->cs);
353 *enum_pins = &object->IEnumPins_iface;
354 return S_OK;
357 static HRESULT WINAPI filter_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **out)
359 struct filter *filter = impl_from_IMediaStreamFilter(iface);
360 unsigned int i;
361 WCHAR *ret_id;
362 IPin *pin;
364 TRACE("iface %p, id %s, out %p.\n", iface, debugstr_w(id), out);
366 EnterCriticalSection(&filter->cs);
368 for (i = 0; i < filter->nb_streams; ++i)
370 if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&pin)))
372 WARN("Stream %p does not support IPin.\n", filter->streams[i]);
373 continue;
376 if (SUCCEEDED(IPin_QueryId(pin, &ret_id)))
378 if (!wcscmp(id, ret_id))
380 CoTaskMemFree(ret_id);
381 *out = pin;
382 LeaveCriticalSection(&filter->cs);
383 return S_OK;
385 CoTaskMemFree(ret_id);
387 IPin_Release(pin);
390 LeaveCriticalSection(&filter->cs);
392 return VFW_E_NOT_FOUND;
395 static HRESULT WINAPI filter_QueryFilterInfo(IMediaStreamFilter *iface, FILTER_INFO *info)
397 struct filter *filter = impl_from_IMediaStreamFilter(iface);
399 TRACE("iface %p, info %p.\n", iface, info);
401 EnterCriticalSection(&filter->cs);
403 wcscpy(info->achName, filter->name);
404 if (filter->graph)
405 IFilterGraph_AddRef(filter->graph);
406 info->pGraph = filter->graph;
408 LeaveCriticalSection(&filter->cs);
410 return S_OK;
413 static HRESULT WINAPI filter_JoinFilterGraph(IMediaStreamFilter *iface,
414 IFilterGraph *graph, const WCHAR *name)
416 struct filter *filter = impl_from_IMediaStreamFilter(iface);
418 TRACE("iface %p, graph %p, name.%s.\n", iface, graph, debugstr_w(name));
420 EnterCriticalSection(&filter->cs);
422 if (name)
423 wcsncpy(filter->name, name, ARRAY_SIZE(filter->name));
424 else
425 filter->name[0] = 0;
426 filter->graph = graph;
428 LeaveCriticalSection(&filter->cs);
430 return S_OK;
433 static HRESULT WINAPI filter_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
435 WARN("iface %p, vendor_info %p, stub!\n", iface, vendor_info);
436 return E_NOTIMPL;
439 /*** IMediaStreamFilter methods ***/
441 static HRESULT WINAPI filter_AddMediaStream(IMediaStreamFilter *iface, IAMMediaStream *pAMMediaStream)
443 struct filter *This = impl_from_IMediaStreamFilter(iface);
444 IAMMediaStream** streams;
445 HRESULT hr;
447 TRACE("(%p)->(%p)\n", iface, pAMMediaStream);
449 streams = CoTaskMemRealloc(This->streams, (This->nb_streams + 1) * sizeof(IAMMediaStream*));
450 if (!streams)
451 return E_OUTOFMEMORY;
452 This->streams = streams;
454 hr = IAMMediaStream_JoinFilter(pAMMediaStream, iface);
455 if (FAILED(hr))
456 return hr;
458 This->streams[This->nb_streams] = pAMMediaStream;
459 This->nb_streams++;
461 IAMMediaStream_AddRef(pAMMediaStream);
463 return S_OK;
466 static HRESULT WINAPI filter_GetMediaStream(IMediaStreamFilter *iface, REFMSPID idPurpose, IMediaStream **ppMediaStream)
468 struct filter *This = impl_from_IMediaStreamFilter(iface);
469 MSPID purpose_id;
470 unsigned int i;
472 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(idPurpose), ppMediaStream);
474 for (i = 0; i < This->nb_streams; i++)
476 IAMMediaStream_GetInformation(This->streams[i], &purpose_id, NULL);
477 if (IsEqualIID(&purpose_id, idPurpose))
479 *ppMediaStream = (IMediaStream *)This->streams[i];
480 IMediaStream_AddRef(*ppMediaStream);
481 return S_OK;
485 return MS_E_NOSTREAM;
488 static HRESULT WINAPI filter_EnumMediaStreams(IMediaStreamFilter *iface, LONG index, IMediaStream **stream)
490 struct filter *filter = impl_from_IMediaStreamFilter(iface);
492 TRACE("filter %p, index %d, stream %p.\n", filter, index, stream);
494 if (index >= filter->nb_streams)
495 return S_FALSE;
497 if (!stream)
498 return E_POINTER;
500 IMediaStream_AddRef(*stream = (IMediaStream *)filter->streams[index]);
501 return S_OK;
504 static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface, BOOL bRenderer)
506 FIXME("(%p)->(%d): Stub!\n", iface, bRenderer);
508 return E_NOTIMPL;
511 static HRESULT WINAPI filter_ReferenceTimeToStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *pTime)
513 FIXME("(%p)->(%p): Stub!\n", iface, pTime);
515 return E_NOTIMPL;
518 static HRESULT WINAPI filter_GetCurrentStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *pCurrentStreamTime)
520 FIXME("(%p)->(%p): Stub!\n", iface, pCurrentStreamTime);
522 return E_NOTIMPL;
525 static HRESULT WINAPI filter_WaitUntil(IMediaStreamFilter *iface, REFERENCE_TIME WaitStreamTime)
527 FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(WaitStreamTime));
529 return E_NOTIMPL;
532 static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL bCancelEOS)
534 FIXME("(%p)->(%d): Stub!\n", iface, bCancelEOS);
536 return E_NOTIMPL;
539 static HRESULT WINAPI filter_EndOfStream(IMediaStreamFilter *iface)
541 FIXME("(%p)->(): Stub!\n", iface);
543 return E_NOTIMPL;
546 static const IMediaStreamFilterVtbl filter_vtbl =
548 filter_QueryInterface,
549 filter_AddRef,
550 filter_Release,
551 filter_GetClassID,
552 filter_Stop,
553 filter_Pause,
554 filter_Run,
555 filter_GetState,
556 filter_SetSyncSource,
557 filter_GetSyncSource,
558 filter_EnumPins,
559 filter_FindPin,
560 filter_QueryFilterInfo,
561 filter_JoinFilterGraph,
562 filter_QueryVendorInfo,
563 filter_AddMediaStream,
564 filter_GetMediaStream,
565 filter_EnumMediaStreams,
566 filter_SupportSeeking,
567 filter_ReferenceTimeToStreamTime,
568 filter_GetCurrentStreamTime,
569 filter_WaitUntil,
570 filter_Flush,
571 filter_EndOfStream
574 HRESULT filter_create(IUnknown *outer, void **out)
576 struct filter *object;
578 TRACE("outer %p, out %p.\n", outer, out);
580 if (outer)
581 return CLASS_E_NOAGGREGATION;
583 if (!(object = heap_alloc_zero(sizeof(*object))))
584 return E_OUTOFMEMORY;
586 object->IMediaStreamFilter_iface.lpVtbl = &filter_vtbl;
587 object->refcount = 1;
588 InitializeCriticalSection(&object->cs);
589 object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MediaStreamFilter.cs");
591 TRACE("Created media stream filter %p.\n", object);
592 *out = &object->IMediaStreamFilter_iface;
593 return S_OK;