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