Release 0.9.14.
[wine/multimedia.git] / dlls / avifil32 / tmpfile.c
blob1bac19e2fc52e4a1be261212c58a07fcb4a493ec
1 /*
2 * Copyright 2003 Michael Günnewig
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COM_NO_WINDOWS_H
20 #include <assert.h>
21 #include <stdarg.h>
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 "mmsystem.h"
30 #include "vfw.h"
32 #include "avifile_private.h"
33 #include "extrachunk.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
39 /***********************************************************************/
41 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
42 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile* iface);
43 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile* iface);
44 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
45 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
46 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
47 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
48 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
49 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile*iface);
50 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
52 static const struct IAVIFileVtbl itmpft = {
53 ITmpFile_fnQueryInterface,
54 ITmpFile_fnAddRef,
55 ITmpFile_fnRelease,
56 ITmpFile_fnInfo,
57 ITmpFile_fnGetStream,
58 ITmpFile_fnCreateStream,
59 ITmpFile_fnWriteData,
60 ITmpFile_fnReadData,
61 ITmpFile_fnEndRecord,
62 ITmpFile_fnDeleteStream
65 typedef struct _ITmpFileImpl {
66 /* IUnknown stuff */
67 const IAVIFileVtbl *lpVtbl;
68 LONG ref;
70 /* IAVIFile stuff */
71 AVIFILEINFOW fInfo;
72 PAVISTREAM *ppStreams;
73 } ITmpFileImpl;
75 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, PAVISTREAM *ppStreams) {
76 ITmpFileImpl *tmpFile;
77 int i;
79 tmpFile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITmpFileImpl));
80 if (tmpFile == NULL)
81 return NULL;
83 tmpFile->lpVtbl = &itmpft;
84 tmpFile->ref = 1;
85 memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
87 tmpFile->fInfo.dwStreams = nStreams;
88 tmpFile->ppStreams = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(PAVISTREAM));
89 if (tmpFile->ppStreams == NULL) {
90 HeapFree(GetProcessHeap(), 0, tmpFile);
91 return NULL;
94 for (i = 0; i < nStreams; i++) {
95 AVISTREAMINFOW sInfo;
97 tmpFile->ppStreams[i] = ppStreams[i];
99 AVIStreamAddRef(ppStreams[i]);
100 AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
101 if (i == 0) {
102 tmpFile->fInfo.dwScale = sInfo.dwScale;
103 tmpFile->fInfo.dwRate = sInfo.dwRate;
104 if (!sInfo.dwScale || !sInfo.dwRate) {
105 tmpFile->fInfo.dwScale = 1;
106 tmpFile->fInfo.dwRate = 100;
110 if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
111 tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
114 register DWORD tmp;
116 tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength), \
117 tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
118 if (tmpFile->fInfo.dwLength < tmp)
119 tmpFile->fInfo.dwLength = tmp;
121 tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
122 if (tmpFile->fInfo.dwWidth < tmp)
123 tmpFile->fInfo.dwWidth = tmp;
124 tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
125 if (tmpFile->fInfo.dwHeight < tmp)
126 tmpFile->fInfo.dwHeight = tmp;
130 return (PAVIFILE)tmpFile;
133 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
134 LPVOID *obj)
136 ITmpFileImpl *This = (ITmpFileImpl *)iface;
138 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
140 if (IsEqualGUID(&IID_IUnknown, refiid) ||
141 IsEqualGUID(&IID_IAVIFile, refiid)) {
142 *obj = iface;
143 IAVIFile_AddRef(iface);
145 return S_OK;
148 return OLE_E_ENUM_NOMORE;
151 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
153 ITmpFileImpl *This = (ITmpFileImpl *)iface;
154 ULONG ref = InterlockedIncrement(&This->ref);
156 TRACE("(%p) -> %ld\n", iface, ref);
158 return ref;
161 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface)
163 ITmpFileImpl *This = (ITmpFileImpl *)iface;
164 ULONG ref = InterlockedDecrement(&This->ref);
166 TRACE("(%p) -> %ld\n", iface, ref);
168 if (!ref) {
169 unsigned int i;
171 for (i = 0; i < This->fInfo.dwStreams; i++) {
172 if (This->ppStreams[i] != NULL) {
173 AVIStreamRelease(This->ppStreams[i]);
175 This->ppStreams[i] = NULL;
179 HeapFree(GetProcessHeap(), 0, This);
180 return 0;
183 return ref;
186 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
187 AVIFILEINFOW *afi, LONG size)
189 ITmpFileImpl *This = (ITmpFileImpl *)iface;
191 TRACE("(%p,%p,%ld)\n",iface,afi,size);
193 if (afi == NULL)
194 return AVIERR_BADPARAM;
195 if (size < 0)
196 return AVIERR_BADSIZE;
198 memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
200 if ((DWORD)size < sizeof(This->fInfo))
201 return AVIERR_BUFFERTOOSMALL;
202 return AVIERR_OK;
205 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
206 DWORD fccType, LONG lParam)
208 ITmpFileImpl *This = (ITmpFileImpl *)iface;
210 ULONG nStream = (ULONG)-1;
212 TRACE("(%p,%p,0x%08lX,%ld)\n", iface, avis, fccType, lParam);
214 if (avis == NULL || lParam < 0)
215 return AVIERR_BADPARAM;
217 if (fccType != streamtypeANY) {
218 /* search the number of the specified stream */
219 ULONG i;
221 for (i = 0; i < This->fInfo.dwStreams; i++) {
222 AVISTREAMINFOW sInfo;
223 HRESULT hr;
225 hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
226 if (FAILED(hr))
227 return hr;
229 if (sInfo.fccType == fccType) {
230 if (lParam == 0) {
231 nStream = i;
232 break;
233 } else
234 lParam--;
237 } else
238 nStream = lParam;
240 /* Does the requested stream exist ? */
241 if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
242 *avis = This->ppStreams[nStream];
243 AVIStreamAddRef(*avis);
245 return AVIERR_OK;
248 /* Sorry, but the specified stream doesn't exist */
249 return AVIERR_NODATA;
252 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
253 AVISTREAMINFOW *asi)
255 TRACE("(%p,%p,%p)\n",iface,avis,asi);
257 return AVIERR_UNSUPPORTED;
260 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
261 LPVOID lpData, LONG size)
263 TRACE("(%p,0x%08lX,%p,%ld)\n", iface, ckid, lpData, size);
265 return AVIERR_UNSUPPORTED;
268 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
269 LPVOID lpData, LONG *size)
271 TRACE("(%p,0x%08lX,%p,%p)\n", iface, ckid, lpData, size);
273 return AVIERR_UNSUPPORTED;
276 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
278 TRACE("(%p)\n",iface);
280 return AVIERR_OK;
283 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
284 LONG lParam)
286 TRACE("(%p,0x%08lX,%ld)\n", iface, fccType, lParam);
288 return AVIERR_UNSUPPORTED;