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