dmusic: Support creating default ports with GUID_NULL.
[wine.git] / dlls / avifil32 / tmpfile.c
blob3bdd50a3ea0377ead352c2a9f8be14f1196cdd43
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 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wingdi.h"
24 #include "winuser.h"
25 #include "winerror.h"
26 #include "vfw.h"
28 #include "avifile_private.h"
29 #include "extrachunk.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
35 /***********************************************************************/
37 typedef struct _ITmpFileImpl {
38 IAVIFile IAVIFile_iface;
39 LONG ref;
41 AVIFILEINFOW fInfo;
42 PAVISTREAM *ppStreams;
43 } ITmpFileImpl;
45 static inline ITmpFileImpl *impl_from_IAVIFile(IAVIFile *iface)
47 return CONTAINING_RECORD(iface, ITmpFileImpl, IAVIFile_iface);
50 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
51 LPVOID *obj)
53 ITmpFileImpl *This = impl_from_IAVIFile(iface);
55 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
57 if (IsEqualGUID(&IID_IUnknown, refiid) ||
58 IsEqualGUID(&IID_IAVIFile, refiid)) {
59 *obj = iface;
60 IAVIFile_AddRef(iface);
62 return S_OK;
65 return OLE_E_ENUM_NOMORE;
68 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
70 ITmpFileImpl *This = impl_from_IAVIFile(iface);
71 ULONG ref = InterlockedIncrement(&This->ref);
73 TRACE("(%p) -> %d\n", iface, ref);
75 return ref;
78 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface)
80 ITmpFileImpl *This = impl_from_IAVIFile(iface);
81 ULONG ref = InterlockedDecrement(&This->ref);
83 TRACE("(%p) -> %d\n", iface, ref);
85 if (!ref) {
86 unsigned int i;
88 for (i = 0; i < This->fInfo.dwStreams; i++) {
89 if (This->ppStreams[i] != NULL) {
90 AVIStreamRelease(This->ppStreams[i]);
92 This->ppStreams[i] = NULL;
96 HeapFree(GetProcessHeap(), 0, This);
97 return 0;
100 return ref;
103 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
104 AVIFILEINFOW *afi, LONG size)
106 ITmpFileImpl *This = impl_from_IAVIFile(iface);
108 TRACE("(%p,%p,%d)\n",iface,afi,size);
110 if (afi == NULL)
111 return AVIERR_BADPARAM;
112 if (size < 0)
113 return AVIERR_BADSIZE;
115 memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
117 if ((DWORD)size < sizeof(This->fInfo))
118 return AVIERR_BUFFERTOOSMALL;
119 return AVIERR_OK;
122 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
123 DWORD fccType, LONG lParam)
125 ITmpFileImpl *This = impl_from_IAVIFile(iface);
127 ULONG nStream = (ULONG)-1;
129 TRACE("(%p,%p,0x%08X,%d)\n", iface, avis, fccType, lParam);
131 if (avis == NULL || lParam < 0)
132 return AVIERR_BADPARAM;
134 if (fccType != streamtypeANY) {
135 /* search the number of the specified stream */
136 ULONG i;
138 for (i = 0; i < This->fInfo.dwStreams; i++) {
139 AVISTREAMINFOW sInfo;
140 HRESULT hr;
142 hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
143 if (FAILED(hr))
144 return hr;
146 if (sInfo.fccType == fccType) {
147 if (lParam == 0) {
148 nStream = i;
149 break;
150 } else
151 lParam--;
154 } else
155 nStream = lParam;
157 /* Does the requested stream exist ? */
158 if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
159 *avis = This->ppStreams[nStream];
160 AVIStreamAddRef(*avis);
162 return AVIERR_OK;
165 /* Sorry, but the specified stream doesn't exist */
166 return AVIERR_NODATA;
169 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
170 AVISTREAMINFOW *asi)
172 TRACE("(%p,%p,%p)\n",iface,avis,asi);
174 return AVIERR_UNSUPPORTED;
177 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
178 LPVOID lpData, LONG size)
180 TRACE("(%p,0x%08X,%p,%d)\n", iface, ckid, lpData, size);
182 return AVIERR_UNSUPPORTED;
185 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
186 LPVOID lpData, LONG *size)
188 TRACE("(%p,0x%08X,%p,%p)\n", iface, ckid, lpData, size);
190 return AVIERR_UNSUPPORTED;
193 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
195 TRACE("(%p)\n",iface);
197 return AVIERR_OK;
200 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
201 LONG lParam)
203 TRACE("(%p,0x%08X,%d)\n", iface, fccType, lParam);
205 return AVIERR_UNSUPPORTED;
208 static const struct IAVIFileVtbl itmpft = {
209 ITmpFile_fnQueryInterface,
210 ITmpFile_fnAddRef,
211 ITmpFile_fnRelease,
212 ITmpFile_fnInfo,
213 ITmpFile_fnGetStream,
214 ITmpFile_fnCreateStream,
215 ITmpFile_fnWriteData,
216 ITmpFile_fnReadData,
217 ITmpFile_fnEndRecord,
218 ITmpFile_fnDeleteStream
221 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, const PAVISTREAM *ppStreams)
223 ITmpFileImpl *tmpFile;
224 int i;
226 tmpFile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITmpFileImpl));
227 if (tmpFile == NULL)
228 return NULL;
230 tmpFile->IAVIFile_iface.lpVtbl = &itmpft;
231 tmpFile->ref = 1;
232 memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
234 tmpFile->fInfo.dwStreams = nStreams;
235 tmpFile->ppStreams = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(PAVISTREAM));
236 if (tmpFile->ppStreams == NULL) {
237 HeapFree(GetProcessHeap(), 0, tmpFile);
238 return NULL;
241 for (i = 0; i < nStreams; i++) {
242 AVISTREAMINFOW sInfo;
244 tmpFile->ppStreams[i] = ppStreams[i];
246 AVIStreamAddRef(ppStreams[i]);
247 AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
248 if (i == 0) {
249 tmpFile->fInfo.dwScale = sInfo.dwScale;
250 tmpFile->fInfo.dwRate = sInfo.dwRate;
251 if (!sInfo.dwScale || !sInfo.dwRate) {
252 tmpFile->fInfo.dwScale = 1;
253 tmpFile->fInfo.dwRate = 100;
257 if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
258 tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
261 register DWORD tmp;
263 tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength),
264 tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
265 if (tmpFile->fInfo.dwLength < tmp)
266 tmpFile->fInfo.dwLength = tmp;
268 tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
269 if (tmpFile->fInfo.dwWidth < tmp)
270 tmpFile->fInfo.dwWidth = tmp;
271 tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
272 if (tmpFile->fInfo.dwHeight < tmp)
273 tmpFile->fInfo.dwHeight = tmp;
277 return (PAVIFILE)tmpFile;