Add IEnumMediaType object for use by other class objects. This is
[wine] / dlls / qcap / enummedia.c
1 /*
2  * Implementation of IEnumMediaTypes Interface
3  *
4  * Copyright 2003 Robert Shearman
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wtypes.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "dshow.h"
31
32 #include "qcap_main.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
37
38 HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
39 {
40     memcpy(pDest, pSrc, sizeof(AM_MEDIA_TYPE));
41     if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
42         return E_OUTOFMEMORY;
43     memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
44     return S_OK;
45 }
46
47 void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
48 {
49     if (pMediaType->pbFormat)
50     {
51         CoTaskMemFree(pMediaType->pbFormat);
52         pMediaType->pbFormat = NULL;
53     }
54     if (pMediaType->pUnk)
55     {
56         IUnknown_Release(pMediaType->pUnk);
57         pMediaType->pUnk = NULL;
58     }
59 }
60
61 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2,
62                        BOOL bWildcards)
63 {
64     TRACE("pmt1: ");
65     dump_AM_MEDIA_TYPE(pmt1);
66     TRACE("pmt2: ");
67     dump_AM_MEDIA_TYPE(pmt2);
68     return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) ||
69               IsEqualGUID(&pmt2->majortype, &GUID_NULL))) ||
70               IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
71               ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) ||
72               IsEqualGUID(&pmt2->subtype, &GUID_NULL))) ||
73               IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
74 }
75
76 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt)
77 {
78     if (!pmt)
79         return;
80     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", debugstr_guid(&pmt->majortype),
81           debugstr_guid(&pmt->subtype), debugstr_guid(&pmt->formattype));
82 }
83
84 typedef struct IEnumMediaTypesImpl
85 {
86     const IEnumMediaTypesVtbl * lpVtbl;
87     ULONG refCount;
88     ENUMMEDIADETAILS enumMediaDetails;
89     ULONG uIndex;
90 } IEnumMediaTypesImpl;
91
92 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
93
94 HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails,
95                                       IEnumMediaTypes ** ppEnum)
96 {
97     ULONG i;
98     IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
99
100     if (!pEnumMediaTypes)
101     {
102         *ppEnum = NULL;
103         return E_OUTOFMEMORY;
104     }
105     ObjectRefCount(TRUE);
106     pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
107     pEnumMediaTypes->refCount = 1;
108     pEnumMediaTypes->uIndex = 0;
109     pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
110     pEnumMediaTypes->enumMediaDetails.pMediaTypes =
111                       CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
112     for (i = 0; i < pDetails->cMediaTypes; i++)
113         pEnumMediaTypes->enumMediaDetails.pMediaTypes[i] = pDetails->pMediaTypes[i];
114     *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
115     return S_OK;
116 }
117
118 static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface,
119                                                          REFIID riid,
120                                                          LPVOID * ppv)
121 {
122     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
123
124     *ppv = NULL;
125
126     if (IsEqualIID(riid, &IID_IUnknown))
127         *ppv = (LPVOID)iface;
128     else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
129         *ppv = (LPVOID)iface;
130
131     if (*ppv)
132     {
133         IUnknown_AddRef((IUnknown *)(*ppv));
134         return S_OK;
135     }
136
137     FIXME("No interface for %s!\n", debugstr_guid(riid));
138
139     return E_NOINTERFACE;
140 }
141
142 static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
143 {
144     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
145     ULONG refCount = InterlockedIncrement(&This->refCount);
146
147     TRACE("()\n");
148
149     return refCount;
150 }
151
152 static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
153 {
154     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
155     ULONG refCount = InterlockedDecrement(&This->refCount);
156
157     TRACE("()\n");
158
159     if (!refCount)
160     {
161         CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
162         CoTaskMemFree(This);
163         ObjectRefCount(FALSE);
164         return 0;
165     }
166     else
167         return refCount;
168 }
169
170 static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface,
171                                                ULONG cMediaTypes,
172                                                AM_MEDIA_TYPE ** ppMediaTypes,
173                                                ULONG * pcFetched)
174 {
175     ULONG cFetched;
176     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
177
178     cFetched = min(This->enumMediaDetails.cMediaTypes,
179                    This->uIndex + cMediaTypes) - This->uIndex;
180
181     TRACE("(%lu, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
182     TRACE("Next uIndex: %lu, cFetched: %lu\n", This->uIndex, cFetched);
183
184     if (cFetched > 0)
185     {
186         ULONG i;
187         *ppMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cFetched);
188         for (i = 0; i < cFetched; i++)
189             (*ppMediaTypes)[i] = This->enumMediaDetails.pMediaTypes[This->uIndex + i];
190     }
191
192     if ((cMediaTypes != 1) || pcFetched)
193         *pcFetched = cFetched;
194
195     This->uIndex += cFetched;
196
197     if (cFetched != cMediaTypes)
198         return S_FALSE;
199     return S_OK;
200 }
201
202 static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface,
203                                                ULONG cMediaTypes)
204 {
205     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
206
207     TRACE("(%lu)\n", cMediaTypes);
208
209     if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
210     {
211         This->uIndex += cMediaTypes;
212         return S_OK;
213     }
214     return S_FALSE;
215 }
216
217 static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
218 {
219     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
220
221     TRACE("()\n");
222
223     This->uIndex = 0;
224     return S_OK;
225 }
226
227 static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface,
228                                                 IEnumMediaTypes ** ppEnum)
229 {
230     HRESULT hr;
231     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
232
233     TRACE("(%p)\n", ppEnum);
234
235     hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
236     if (FAILED(hr))
237         return hr;
238     return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
239 }
240
241 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
242 {
243     IEnumMediaTypesImpl_QueryInterface,
244     IEnumMediaTypesImpl_AddRef,
245     IEnumMediaTypesImpl_Release,
246     IEnumMediaTypesImpl_Next,
247     IEnumMediaTypesImpl_Skip,
248     IEnumMediaTypesImpl_Reset,
249     IEnumMediaTypesImpl_Clone
250 };