Forgot to limit capture sample rates.
[wine] / dlls / quartz / 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 "quartz_private.h"
22
23 #include "wine/debug.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
26
27 HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
28 {
29     memcpy(pDest, pSrc, sizeof(AM_MEDIA_TYPE));
30     if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
31         return E_OUTOFMEMORY;
32     memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
33     return S_OK;
34 }
35
36 void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
37 {
38     if (pMediaType->pbFormat)
39     {
40         CoTaskMemFree(pMediaType->pbFormat);
41         pMediaType->pbFormat = NULL;
42     }
43     if (pMediaType->pUnk)
44     {
45         IUnknown_Release(pMediaType->pUnk);
46         pMediaType->pUnk = NULL;
47     }
48 }
49
50 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
51 {
52     TRACE("pmt1: ");
53     dump_AM_MEDIA_TYPE(pmt1);
54     TRACE("pmt2: ");
55     dump_AM_MEDIA_TYPE(pmt2);
56     return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
57             ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL)   || IsEqualGUID(&pmt2->subtype, &GUID_NULL)))   || IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
58 }
59
60 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt)
61 {
62     if (!pmt)
63         return;
64     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", qzdebugstr_guid(&pmt->majortype), qzdebugstr_guid(&pmt->subtype), qzdebugstr_guid(&pmt->formattype));
65 }
66
67 typedef struct IEnumMediaTypesImpl
68 {
69     const IEnumMediaTypesVtbl * lpVtbl;
70     ULONG refCount;
71     ENUMMEDIADETAILS enumMediaDetails;
72     ULONG uIndex;
73 } IEnumMediaTypesImpl;
74
75 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
76
77 HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum)
78 {
79     ULONG i;
80     IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
81
82     if (!pEnumMediaTypes)
83     {
84         *ppEnum = NULL;
85         return E_OUTOFMEMORY;
86     }
87     pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
88     pEnumMediaTypes->refCount = 1;
89     pEnumMediaTypes->uIndex = 0;
90     pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
91     pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
92     for (i = 0; i < pDetails->cMediaTypes; i++)
93         pEnumMediaTypes->enumMediaDetails.pMediaTypes[i] = pDetails->pMediaTypes[i];
94     *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
95     return S_OK;
96 }
97
98 static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
99 {
100     TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
101
102     *ppv = NULL;
103
104     if (IsEqualIID(riid, &IID_IUnknown))
105         *ppv = (LPVOID)iface;
106     else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
107         *ppv = (LPVOID)iface;
108
109     if (*ppv)
110     {
111         IUnknown_AddRef((IUnknown *)(*ppv));
112         return S_OK;
113     }
114
115     FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
116
117     return E_NOINTERFACE;
118 }
119
120 static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
121 {
122     ICOM_THIS(IEnumMediaTypesImpl, iface);
123     TRACE("()\n");
124     return ++This->refCount;
125 }
126
127 static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
128 {
129     ICOM_THIS(IEnumMediaTypesImpl, iface);
130     TRACE("()\n");
131     if (!--This->refCount)
132     {
133         CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
134         CoTaskMemFree(This);
135         return 0;
136     }
137     else
138         return This->refCount;
139 }
140
141 static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
142 {
143     ULONG cFetched; 
144     ICOM_THIS(IEnumMediaTypesImpl, iface);
145
146     cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
147
148     TRACE("(%lu, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
149     TRACE("Next uIndex: %lu, cFetched: %lu\n", This->uIndex, cFetched);
150
151     if (cFetched > 0)
152     {
153         ULONG i;
154         *ppMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cFetched);
155         for (i = 0; i < cFetched; i++)
156             (*ppMediaTypes)[i] = This->enumMediaDetails.pMediaTypes[This->uIndex + i];
157     }
158
159     if ((cMediaTypes != 1) || pcFetched)
160         *pcFetched = cFetched;
161
162     This->uIndex += cFetched;
163
164     if (cFetched != cMediaTypes)
165         return S_FALSE;
166     return S_OK;
167 }
168
169 static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
170 {
171     ICOM_THIS(IEnumMediaTypesImpl, iface);
172
173     TRACE("(%lu)\n", cMediaTypes);
174
175     if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
176     {
177         This->uIndex += cMediaTypes;
178         return S_OK;
179     }
180     return S_FALSE;
181 }
182
183 static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
184 {
185     ICOM_THIS(IEnumMediaTypesImpl, iface);
186
187     TRACE("()\n");
188
189     This->uIndex = 0;
190     return S_OK;
191 }
192
193 static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
194 {
195     HRESULT hr;
196     ICOM_THIS(IEnumMediaTypesImpl, iface);
197
198     TRACE("(%p)\n", ppEnum);
199
200     hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
201     if (FAILED(hr))
202         return hr;
203     return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
204 }
205
206 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
207 {
208     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
209     IEnumMediaTypesImpl_QueryInterface,
210     IEnumMediaTypesImpl_AddRef,
211     IEnumMediaTypesImpl_Release,
212     IEnumMediaTypesImpl_Next,
213     IEnumMediaTypesImpl_Skip,
214     IEnumMediaTypesImpl_Reset,
215     IEnumMediaTypesImpl_Clone
216 };