amstream: Remove duplicate GraphBuilder member.
[wine] / dlls / amstream / amstream.c
1 /*
2  * Implementation of IAMMultiMediaStream Interface
3  *
4  * Copyright 2004 Christian Costa
5  * Copyright 2006 Ivan Leo Puoti
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "wine/debug.h"
23
24 #define COBJMACROS
25
26 #include "winbase.h"
27 #include "wingdi.h"
28
29 #include "amstream_private.h"
30 #include "amstream.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
33
34 typedef struct {
35     IAMMultiMediaStream IAMMultiMediaStream_iface;
36     LONG ref;
37     IGraphBuilder* pFilterGraph;
38     IPin* ipin;
39     ULONG nbStreams;
40     IMediaStream** pStreams;
41     STREAM_TYPE StreamType;
42 } IAMMultiMediaStreamImpl;
43
44 static inline IAMMultiMediaStreamImpl *impl_from_IAMMultiMediaStream(IAMMultiMediaStream *iface)
45 {
46     return CONTAINING_RECORD(iface, IAMMultiMediaStreamImpl, IAMMultiMediaStream_iface);
47 }
48
49 static const struct IAMMultiMediaStreamVtbl AM_Vtbl;
50
51 HRESULT AM_create(IUnknown *pUnkOuter, LPVOID *ppObj)
52 {
53     IAMMultiMediaStreamImpl* object; 
54
55     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
56
57     if( pUnkOuter )
58         return CLASS_E_NOAGGREGATION;
59
60     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAMMultiMediaStreamImpl));
61     if (!object)
62     {
63         ERR("Out of memory\n");
64         return E_OUTOFMEMORY;
65     }
66
67     object->IAMMultiMediaStream_iface.lpVtbl = &AM_Vtbl;
68     object->ref = 1;
69
70     *ppObj = object;
71
72     return S_OK;
73 }
74
75 /*** IUnknown methods ***/
76 static HRESULT WINAPI IAMMultiMediaStreamImpl_QueryInterface(IAMMultiMediaStream* iface, REFIID riid, void** ppvObject)
77 {
78     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
79
80     TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
81
82     if (IsEqualGUID(riid, &IID_IUnknown) ||
83         IsEqualGUID(riid, &IID_IMultiMediaStream) ||
84         IsEqualGUID(riid, &IID_IAMMultiMediaStream))
85     {
86         IUnknown_AddRef(iface);
87         *ppvObject = This;
88         return S_OK;
89     }
90
91     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
92
93     return E_NOINTERFACE;
94 }
95
96 static ULONG WINAPI IAMMultiMediaStreamImpl_AddRef(IAMMultiMediaStream* iface)
97 {
98     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
99
100     TRACE("(%p/%p)\n", iface, This);
101
102     return InterlockedIncrement(&This->ref);
103 }
104
105 static ULONG WINAPI IAMMultiMediaStreamImpl_Release(IAMMultiMediaStream* iface)
106 {
107     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
108     ULONG ref = InterlockedDecrement(&This->ref);
109
110     TRACE("(%p/%p)\n", iface, This);
111
112     if (!ref)
113         HeapFree(GetProcessHeap(), 0, This);
114
115     return ref;
116 }
117
118 /*** IMultiMediaStream methods ***/
119 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetInformation(IAMMultiMediaStream* iface, DWORD* pdwFlags, STREAM_TYPE* pStreamType)
120 {
121     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
122
123     FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pdwFlags, pStreamType);
124
125     return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetMediaStream(IAMMultiMediaStream* iface, REFMSPID idPurpose, IMediaStream** ppMediaStream)
129 {
130     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
131     MSPID PurposeId;
132     unsigned int i;
133
134     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(idPurpose), ppMediaStream);
135
136     for (i = 0; i < This->nbStreams; i++)
137     {
138         IMediaStream_GetInformation(This->pStreams[i], &PurposeId, NULL);
139         if (IsEqualIID(&PurposeId, idPurpose))
140         {
141             *ppMediaStream = This->pStreams[i];
142             IMediaStream_AddRef(*ppMediaStream);
143             return S_OK;
144         }
145     }
146
147     return MS_E_NOSTREAM;
148 }
149
150 static HRESULT WINAPI IAMMultiMediaStreamImpl_EnumMediaStreams(IAMMultiMediaStream* iface, LONG Index, IMediaStream** ppMediaStream)
151 {
152     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
153
154     FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, Index, ppMediaStream);
155
156     return E_NOTIMPL;
157 }
158
159 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetState(IAMMultiMediaStream* iface, STREAM_STATE* pCurrentState)
160 {
161     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
162
163     FIXME("(%p/%p)->(%p) stub!\n", This, iface, pCurrentState);
164
165     return E_NOTIMPL;
166 }
167
168 static HRESULT WINAPI IAMMultiMediaStreamImpl_SetState(IAMMultiMediaStream* iface, STREAM_STATE NewState)
169 {
170     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
171
172     FIXME("(%p/%p)->() stub!\n", This, iface);
173
174     return E_NOTIMPL;
175 }
176
177 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetTime(IAMMultiMediaStream* iface, STREAM_TIME* pCurrentTime)
178 {
179     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
180
181     FIXME("(%p/%p)->(%p) stub!\n", This, iface, pCurrentTime);
182
183     return E_NOTIMPL;
184 }
185
186 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetDuration(IAMMultiMediaStream* iface, STREAM_TIME* pDuration)
187 {
188     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
189
190     FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDuration);
191
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI IAMMultiMediaStreamImpl_Seek(IAMMultiMediaStream* iface, STREAM_TIME SeekTime)
196 {
197     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
198
199     FIXME("(%p/%p)->() stub!\n", This, iface);
200
201     return E_NOTIMPL;
202 }
203
204 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetEndOfStream(IAMMultiMediaStream* iface, HANDLE* phEOS)
205 {
206     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
207
208     FIXME("(%p/%p)->(%p) stub!\n", This, iface, phEOS);
209
210     return E_NOTIMPL;
211 }
212
213 /*** IAMMultiMediaStream methods ***/
214 static HRESULT WINAPI IAMMultiMediaStreamImpl_Initialize(IAMMultiMediaStream* iface, STREAM_TYPE StreamType, DWORD dwFlags, IGraphBuilder* pFilterGraph)
215 {
216     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
217     HRESULT hr = S_OK;
218
219     TRACE("(%p/%p)->(%x,%x,%p)\n", This, iface, (DWORD)StreamType, dwFlags, pFilterGraph);
220
221     if (pFilterGraph)
222     {
223         This->pFilterGraph = pFilterGraph;
224         IGraphBuilder_AddRef(This->pFilterGraph);
225     }
226     else
227     {
228         hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&This->pFilterGraph);
229     }
230
231     if (SUCCEEDED(hr))
232     {
233         This->StreamType = StreamType;
234     }
235
236     return hr;
237 }
238
239 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetFilterGraph(IAMMultiMediaStream* iface, IGraphBuilder** ppGraphBuilder)
240 {
241     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
242
243     TRACE("(%p/%p)->(%p)\n", This, iface, ppGraphBuilder);
244
245     if (!ppGraphBuilder)
246         return E_POINTER;
247
248     if (This->pFilterGraph)
249         return IFilterGraph_QueryInterface(This->pFilterGraph, &IID_IGraphBuilder, (void**)ppGraphBuilder);
250     else
251         *ppGraphBuilder = NULL;
252
253     return S_OK;
254 }
255
256 static HRESULT WINAPI IAMMultiMediaStreamImpl_GetFilter(IAMMultiMediaStream* iface, IMediaStreamFilter** ppFilter)
257 {
258     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
259
260     FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppFilter); 
261
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI IAMMultiMediaStreamImpl_AddMediaStream(IAMMultiMediaStream* iface, IUnknown* pStreamObject, const MSPID* PurposeId,
266                                           DWORD dwFlags, IMediaStream** ppNewStream)
267 {
268     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
269     HRESULT hr;
270     IMediaStream* pStream;
271     IMediaStream** pNewStreams;
272
273     FIXME("(%p/%p)->(%p,%s,%x,%p) partial stub!\n", This, iface, pStreamObject, debugstr_guid(PurposeId), dwFlags, ppNewStream);
274
275     hr = mediastream_create((IMultiMediaStream*)iface, PurposeId, This->StreamType, &pStream);
276     if (SUCCEEDED(hr))
277     {
278         pNewStreams = CoTaskMemRealloc(This->pStreams, (This->nbStreams+1) * sizeof(IMediaStream*));
279         if (!pNewStreams)
280         {
281             IMediaStream_Release(pStream);
282             return E_OUTOFMEMORY;
283         }
284         This->pStreams = pNewStreams;
285         This->pStreams[This->nbStreams] = pStream;
286         This->nbStreams++;
287
288         if (ppNewStream)
289             *ppNewStream = pStream;
290     }
291
292     return hr;
293 }
294
295 static HRESULT WINAPI IAMMultiMediaStreamImpl_OpenFile(IAMMultiMediaStream* iface, LPCWSTR pszFileName, DWORD dwFlags)
296 {
297     HRESULT ret;
298     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
299     IFileSourceFilter *SourceFilter;
300     IBaseFilter *BaseFilter;
301     IEnumPins *EnumPins;
302     IPin *ipin;
303     PIN_DIRECTION pin_direction;
304
305     TRACE("(%p/%p)->(%s,%x)\n", This, iface, debugstr_w(pszFileName), dwFlags);
306
307     /* If Initialize was not called before, we do it here */
308     if (!This->pFilterGraph)
309     {
310         ret = IAMMultiMediaStream_Initialize(iface, STREAMTYPE_READ, 0, NULL);
311         if (FAILED(ret))
312             return ret;
313     }
314
315     ret = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IFileSourceFilter, (void**)&SourceFilter);
316     if(ret != S_OK)
317         return ret;
318
319     ret = IFileSourceFilter_Load(SourceFilter, pszFileName, NULL);
320     if(ret != S_OK)
321     {
322         IFileSourceFilter_Release(SourceFilter);
323         return ret;
324     }
325
326     ret = IFileSourceFilter_QueryInterface(SourceFilter, &IID_IBaseFilter, (void**)&BaseFilter);
327     if(ret != S_OK)
328     {
329         IFileSourceFilter_Release(SourceFilter);
330         return ret;
331     }
332
333     ret = IBaseFilter_EnumPins(BaseFilter, &EnumPins);
334     if(ret != S_OK)
335     {
336         goto end;
337     }
338
339     ret = IEnumPins_Next(EnumPins, 1, &ipin, NULL);
340     if(ret == S_OK)
341     {
342         ret = IPin_QueryDirection(ipin, &pin_direction);
343         IEnumPins_Release(EnumPins);
344         if(ret == S_OK && pin_direction == PINDIR_OUTPUT)
345             This->ipin = ipin;
346         else
347             goto end;
348     }
349     else
350     {
351         IEnumPins_Release(EnumPins);
352         goto end;
353     }
354
355     ret = IGraphBuilder_AddSourceFilter(This->pFilterGraph, pszFileName, pszFileName, &BaseFilter);
356
357 end:
358     IBaseFilter_Release(BaseFilter);
359     IFileSourceFilter_Release(SourceFilter);
360     return ret;
361 }
362
363 static HRESULT WINAPI IAMMultiMediaStreamImpl_OpenMoniker(IAMMultiMediaStream* iface, IBindCtx* pCtx, IMoniker* pMoniker, DWORD dwFlags)
364 {
365     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
366
367     FIXME("(%p/%p)->(%p,%p,%x) stub!\n", This, iface, pCtx, pMoniker, dwFlags);
368
369     return E_NOTIMPL;
370 }
371
372 static HRESULT WINAPI IAMMultiMediaStreamImpl_Render(IAMMultiMediaStream* iface, DWORD dwFlags)
373 {
374     IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface);
375
376     FIXME("(%p/%p)->(%x) partial stub!\n", This, iface, dwFlags);
377
378     if(dwFlags != AMMSF_NOCLOCK)
379         return E_INVALIDARG;
380
381     return IGraphBuilder_Render(This->pFilterGraph, This->ipin);
382 }
383
384 static const IAMMultiMediaStreamVtbl AM_Vtbl =
385 {
386     IAMMultiMediaStreamImpl_QueryInterface,
387     IAMMultiMediaStreamImpl_AddRef,
388     IAMMultiMediaStreamImpl_Release,
389     IAMMultiMediaStreamImpl_GetInformation,
390     IAMMultiMediaStreamImpl_GetMediaStream,
391     IAMMultiMediaStreamImpl_EnumMediaStreams,
392     IAMMultiMediaStreamImpl_GetState,
393     IAMMultiMediaStreamImpl_SetState,
394     IAMMultiMediaStreamImpl_GetTime,
395     IAMMultiMediaStreamImpl_GetDuration,
396     IAMMultiMediaStreamImpl_Seek,
397     IAMMultiMediaStreamImpl_GetEndOfStream,
398     IAMMultiMediaStreamImpl_Initialize,
399     IAMMultiMediaStreamImpl_GetFilterGraph,
400     IAMMultiMediaStreamImpl_GetFilter,
401     IAMMultiMediaStreamImpl_AddMediaStream,
402     IAMMultiMediaStreamImpl_OpenFile,
403     IAMMultiMediaStreamImpl_OpenMoniker,
404     IAMMultiMediaStreamImpl_Render
405 };