prepare fixing vfw.h header so it can be compile without include/wine again
[reactos.git] / reactos / lib / avifil32 / tmpfile.c
1 /*
2 * Copyright 2003 Michael Günnewig
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #define COM_NO_WINDOWS_H
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "winerror.h"
29 #include "windowsx.h"
30 #include "mmsystem.h"
31 #include "mmreg.h"
32 #include "vfw.h"
33
34 #include "avifile_private.h"
35 #include "extrachunk.h"
36
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
40
41 /***********************************************************************/
42
43 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
44 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile* iface);
45 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile* iface);
46 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
47 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
48 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
49 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
50 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
51 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile*iface);
52 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
53
54 static const struct IAVIFileVtbl itmpft = {
55 ITmpFile_fnQueryInterface,
56 ITmpFile_fnAddRef,
57 ITmpFile_fnRelease,
58 ITmpFile_fnInfo,
59 ITmpFile_fnGetStream,
60 ITmpFile_fnCreateStream,
61 ITmpFile_fnWriteData,
62 ITmpFile_fnReadData,
63 ITmpFile_fnEndRecord,
64 ITmpFile_fnDeleteStream
65 };
66
67 typedef struct _ITmpFileImpl {
68 /* IUnknown stuff */
69 const IAVIFileVtbl *lpVtbl;
70 LONG ref;
71
72 /* IAVIFile stuff */
73 AVIFILEINFOW fInfo;
74 PAVISTREAM *ppStreams;
75 } ITmpFileImpl;
76
77 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, PAVISTREAM *ppStreams) {
78 ITmpFileImpl *tmpFile;
79 int i;
80
81 tmpFile = LocalAlloc(LPTR, sizeof(ITmpFileImpl));
82 if (tmpFile == NULL)
83 return NULL;
84
85 tmpFile->lpVtbl = &itmpft;
86 tmpFile->ref = 1;
87 memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
88
89 tmpFile->fInfo.dwStreams = nStreams;
90 tmpFile->ppStreams = LocalAlloc(LPTR, nStreams * sizeof(PAVISTREAM));
91 if (tmpFile->ppStreams == NULL) {
92 LocalFree((HLOCAL)tmpFile);
93 return NULL;
94 }
95
96 for (i = 0; i < nStreams; i++) {
97 AVISTREAMINFOW sInfo;
98
99 tmpFile->ppStreams[i] = ppStreams[i];
100
101 AVIStreamAddRef(ppStreams[i]);
102 AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
103 if (i == 0) {
104 tmpFile->fInfo.dwScale = sInfo.dwScale;
105 tmpFile->fInfo.dwRate = sInfo.dwRate;
106 if (!sInfo.dwScale || !sInfo.dwRate) {
107 tmpFile->fInfo.dwScale = 1;
108 tmpFile->fInfo.dwRate = 100;
109 }
110 }
111
112 if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
113 tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
114
115 {
116 register DWORD tmp;
117
118 tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength), \
119 tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
120 if (tmpFile->fInfo.dwLength < tmp)
121 tmpFile->fInfo.dwLength = tmp;
122
123 tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
124 if (tmpFile->fInfo.dwWidth < tmp)
125 tmpFile->fInfo.dwWidth = tmp;
126 tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
127 if (tmpFile->fInfo.dwHeight < tmp)
128 tmpFile->fInfo.dwHeight = tmp;
129 }
130 }
131
132 return (PAVIFILE)tmpFile;
133 }
134
135 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
136 LPVOID *obj)
137 {
138 ITmpFileImpl *This = (ITmpFileImpl *)iface;
139
140 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
141
142 if (IsEqualGUID(&IID_IUnknown, refiid) ||
143 IsEqualGUID(&IID_IAVIFile, refiid)) {
144 *obj = iface;
145 IAVIFile_AddRef(iface);
146
147 return S_OK;
148 }
149
150 return OLE_E_ENUM_NOMORE;
151 }
152
153 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
154 {
155 ITmpFileImpl *This = (ITmpFileImpl *)iface;
156 ULONG ref = InterlockedIncrement(&This->ref);
157
158 TRACE("(%p) -> %ld\n", iface, ref);
159
160 return ref;
161 }
162
163 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface)
164 {
165 ITmpFileImpl *This = (ITmpFileImpl *)iface;
166 ULONG ref = InterlockedDecrement(&This->ref);
167
168 TRACE("(%p) -> %ld\n", iface, ref);
169
170 if (!ref) {
171 unsigned int i;
172
173 for (i = 0; i < This->fInfo.dwStreams; i++) {
174 if (This->ppStreams[i] != NULL) {
175 AVIStreamRelease(This->ppStreams[i]);
176
177 This->ppStreams[i] = NULL;
178 }
179 }
180
181 LocalFree((HLOCAL)This);
182 return 0;
183 }
184
185 return ref;
186 }
187
188 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
189 AVIFILEINFOW *afi, LONG size)
190 {
191 ITmpFileImpl *This = (ITmpFileImpl *)iface;
192
193 TRACE("(%p,%p,%ld)\n",iface,afi,size);
194
195 if (afi == NULL)
196 return AVIERR_BADPARAM;
197 if (size < 0)
198 return AVIERR_BADSIZE;
199
200 memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
201
202 if ((DWORD)size < sizeof(This->fInfo))
203 return AVIERR_BUFFERTOOSMALL;
204 return AVIERR_OK;
205 }
206
207 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
208 DWORD fccType, LONG lParam)
209 {
210 ITmpFileImpl *This = (ITmpFileImpl *)iface;
211
212 ULONG nStream = (ULONG)-1;
213
214 TRACE("(%p,%p,0x%08lX,%ld)\n", iface, avis, fccType, lParam);
215
216 if (avis == NULL || lParam < 0)
217 return AVIERR_BADPARAM;
218
219 if (fccType != streamtypeANY) {
220 /* search the number of the specified stream */
221 ULONG i;
222
223 for (i = 0; i < This->fInfo.dwStreams; i++) {
224 AVISTREAMINFOW sInfo;
225 HRESULT hr;
226
227 hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
228 if (FAILED(hr))
229 return hr;
230
231 if (sInfo.fccType == fccType) {
232 if (lParam == 0) {
233 nStream = i;
234 break;
235 } else
236 lParam--;
237 }
238 }
239 } else
240 nStream = lParam;
241
242 /* Does the requested stream exist ? */
243 if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
244 *avis = This->ppStreams[nStream];
245 AVIStreamAddRef(*avis);
246
247 return AVIERR_OK;
248 }
249
250 /* Sorry, but the specified stream doesn't exist */
251 return AVIERR_NODATA;
252 }
253
254 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
255 AVISTREAMINFOW *asi)
256 {
257 TRACE("(%p,%p,%p)\n",iface,avis,asi);
258
259 return AVIERR_UNSUPPORTED;
260 }
261
262 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
263 LPVOID lpData, LONG size)
264 {
265 TRACE("(%p,0x%08lX,%p,%ld)\n", iface, ckid, lpData, size);
266
267 return AVIERR_UNSUPPORTED;
268 }
269
270 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
271 LPVOID lpData, LONG *size)
272 {
273 TRACE("(%p,0x%08lX,%p,%p)\n", iface, ckid, lpData, size);
274
275 return AVIERR_UNSUPPORTED;
276 }
277
278 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
279 {
280 TRACE("(%p)\n",iface);
281
282 return AVIERR_OK;
283 }
284
285 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
286 LONG lParam)
287 {
288 TRACE("(%p,0x%08lX,%ld)\n", iface, fccType, lParam);
289
290 return AVIERR_UNSUPPORTED;
291 }