Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine] / dlls / 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 "vfw.h"
32
33 #include "avifile_private.h"
34 #include "extrachunk.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
39
40 /***********************************************************************/
41
42 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
43 static ULONG   WINAPI ITmpFile_fnAddRef(IAVIFile* iface);
44 static ULONG   WINAPI ITmpFile_fnRelease(IAVIFile* iface);
45 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
46 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
47 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
48 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
49 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
50 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile*iface);
51 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
52
53 struct IAVIFileVtbl itmpft = {
54   ITmpFile_fnQueryInterface,
55   ITmpFile_fnAddRef,
56   ITmpFile_fnRelease,
57   ITmpFile_fnInfo,
58   ITmpFile_fnGetStream,
59   ITmpFile_fnCreateStream,
60   ITmpFile_fnWriteData,
61   ITmpFile_fnReadData,
62   ITmpFile_fnEndRecord,
63   ITmpFile_fnDeleteStream
64 };
65
66 typedef struct _ITmpFileImpl {
67   /* IUnknown stuff */
68   IAVIFileVtbl *lpVtbl;
69   DWORD         ref;
70
71   /* IAVIFile stuff */
72   AVIFILEINFOW  fInfo;
73   PAVISTREAM   *ppStreams;
74 } ITmpFileImpl;
75
76 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, PAVISTREAM *ppStreams) {
77   ITmpFileImpl *tmpFile;
78   int           i;
79
80   tmpFile = LocalAlloc(LPTR, sizeof(ITmpFileImpl));
81   if (tmpFile == NULL)
82     return NULL;
83
84   tmpFile->lpVtbl = &itmpft;
85   tmpFile->ref    = 1;
86   memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
87
88   tmpFile->fInfo.dwStreams = nStreams;
89   tmpFile->ppStreams = LocalAlloc(LPTR, nStreams * sizeof(PAVISTREAM));
90   if (tmpFile->ppStreams == NULL) {
91     LocalFree((HLOCAL)tmpFile);
92     return NULL;
93   }
94
95   for (i = 0; i < nStreams; i++) {
96     AVISTREAMINFOW sInfo;
97
98     tmpFile->ppStreams[i] = ppStreams[i];
99
100     AVIStreamAddRef(ppStreams[i]);
101     AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
102     if (i == 0) {
103       tmpFile->fInfo.dwScale = sInfo.dwScale;
104       tmpFile->fInfo.dwRate  = sInfo.dwRate;
105       if (!sInfo.dwScale || !sInfo.dwRate) {
106         tmpFile->fInfo.dwScale = 1;
107         tmpFile->fInfo.dwRate  = 100;
108       }
109     }
110
111     if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
112       tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
113
114     {
115       register DWORD tmp;
116
117       tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength), \
118                    tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
119       if (tmpFile->fInfo.dwLength < tmp)
120         tmpFile->fInfo.dwLength = tmp;
121
122       tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
123       if (tmpFile->fInfo.dwWidth < tmp)
124         tmpFile->fInfo.dwWidth = tmp;
125       tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
126       if (tmpFile->fInfo.dwHeight < tmp)
127         tmpFile->fInfo.dwHeight = tmp;
128     }
129   }
130
131   return (PAVIFILE)tmpFile;
132 }
133
134 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
135                                                 LPVOID *obj)
136 {
137   ICOM_THIS(ITmpFileImpl,iface);
138
139   TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
140
141   if (IsEqualGUID(&IID_IUnknown, refiid) ||
142       IsEqualGUID(&IID_IAVIFile, refiid)) {
143     *obj = iface;
144     IAVIFile_AddRef(iface);
145
146     return S_OK;
147   }
148
149   return OLE_E_ENUM_NOMORE;
150 }
151
152 static ULONG   WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
153 {
154   ICOM_THIS(ITmpFileImpl,iface);
155
156   TRACE("(%p) -> %ld\n", iface, This->ref + 1);
157   return ++(This->ref);
158 }
159
160 static ULONG   WINAPI ITmpFile_fnRelease(IAVIFile *iface)
161 {
162   ICOM_THIS(ITmpFileImpl,iface);
163
164   TRACE("(%p) -> %ld\n", iface, This->ref - 1);
165
166   if (!--(This->ref)) {
167     int i;
168
169     for (i = 0; i < This->fInfo.dwStreams; i++) {
170       if (This->ppStreams[i] != NULL) {
171         AVIStreamRelease(This->ppStreams[i]);
172
173         This->ppStreams[i] = NULL;
174       }
175     }
176
177     LocalFree((HLOCAL)This);
178     return 0;
179   }
180
181   return This->ref;
182 }
183
184 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
185                                       AVIFILEINFOW *afi, LONG size)
186 {
187   ICOM_THIS(ITmpFileImpl,iface);
188
189   TRACE("(%p,%p,%ld)\n",iface,afi,size);
190
191   if (afi == NULL)
192     return AVIERR_BADPARAM;
193   if (size < 0)
194     return AVIERR_BADSIZE;
195
196   memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
197
198   if ((DWORD)size < sizeof(This->fInfo))
199     return AVIERR_BUFFERTOOSMALL;
200   return AVIERR_OK;
201 }
202
203 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
204                                            DWORD fccType, LONG lParam)
205 {
206   ICOM_THIS(ITmpFileImpl,iface);
207
208   ULONG nStream = (ULONG)-1;
209
210   TRACE("(%p,%p,0x%08lX,%ld)\n", iface, avis, fccType, lParam);
211
212   if (avis == NULL || lParam < 0)
213     return AVIERR_BADPARAM;
214
215   if (fccType != streamtypeANY) {
216     /* search the number of the specified stream */
217     ULONG i;
218
219     for (i = 0; i < This->fInfo.dwStreams; i++) {
220       AVISTREAMINFOW sInfo;
221       HRESULT        hr;
222
223       hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
224       if (FAILED(hr))
225         return hr;
226
227       if (sInfo.fccType == fccType) {
228         if (lParam == 0) {
229           nStream = i;
230           break;
231         } else
232           lParam--;
233       }
234     }
235   } else
236     nStream = lParam;
237
238   /* Does the requested stream exist ? */
239   if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
240     *avis = This->ppStreams[nStream];
241     AVIStreamAddRef(*avis);
242
243     return AVIERR_OK;
244   }
245
246   /* Sorry, but the specified stream doesn't exist */
247   return AVIERR_NODATA;
248 }
249
250 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
251                                               AVISTREAMINFOW *asi)
252 {
253   TRACE("(%p,%p,%p)\n",iface,avis,asi);
254
255   return AVIERR_UNSUPPORTED;
256 }
257
258 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
259                                            LPVOID lpData, LONG size)
260 {
261   TRACE("(%p,0x%08lX,%p,%ld)\n", iface, ckid, lpData, size);
262
263   return AVIERR_UNSUPPORTED;
264 }
265
266 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
267                                           LPVOID lpData, LONG *size)
268 {
269   TRACE("(%p,0x%08lX,%p,%p)\n", iface, ckid, lpData, size);
270
271   return AVIERR_UNSUPPORTED;
272 }
273
274 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
275 {
276   TRACE("(%p)\n",iface);
277
278   return AVIERR_OK;
279 }
280
281 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
282                                               LONG lParam)
283 {
284   TRACE("(%p,0x%08lX,%ld)\n", iface, fccType, lParam);
285
286   return AVIERR_UNSUPPORTED;
287 }