Improve handling of custom dialog templates passed to
[wine/multimedia.git] / dlls / avifil32 / api.c
blob29a77498eb310614f999cc09d1c27522f674ca74
1 /*
2 * Copyright 1999 Marcus Meissner
3 * Copyright 2002-2003 Michael Günnewig
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define COM_NO_WINDOWS_H
21 #include <assert.h>
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "winuser.h"
26 #include "winreg.h"
27 #include "winerror.h"
28 #include "windowsx.h"
30 #include "ole2.h"
31 #include "shellapi.h"
32 #include "vfw.h"
33 #include "msacm.h"
35 #include "avifile_private.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
42 /***********************************************************************
43 * copied from dlls/shell32/undocshell.h
45 HRESULT WINAPI SHCoCreateInstance(LPCSTR lpszClsid,REFCLSID rClsid,
46 LPUNKNOWN pUnkOuter,REFIID riid,LPVOID *ppv);
48 /***********************************************************************
49 * for AVIBuildFilterW -- uses fixed size table
51 #define MAX_FILTERS 30 /* 30 => 7kB */
53 typedef struct _AVIFilter {
54 WCHAR szClsid[40];
55 WCHAR szExtensions[MAX_FILTERS * 7];
56 } AVIFilter;
58 /***********************************************************************
59 * for AVISaveOptions
61 static struct {
62 UINT uFlags;
63 INT nStreams;
64 PAVISTREAM *ppavis;
65 LPAVICOMPRESSOPTIONS *ppOptions;
66 INT nCurrent;
67 } SaveOpts;
69 /***********************************************************************
70 * copied from dlls/ole32/compobj.c
72 static HRESULT AVIFILE_CLSIDFromString(LPCSTR idstr, LPCLSID id)
74 BYTE const *s = (BYTE const*)idstr;
75 BYTE *p;
76 INT i;
77 BYTE table[256];
79 if (!s) {
80 memset(id, 0, sizeof(CLSID));
81 return S_OK;
82 } else { /* validate the CLSID string */
83 if (lstrlenA(s) != 38)
84 return CO_E_CLASSSTRING;
86 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') ||
87 (s[24]!='-') || (s[37]!='}'))
88 return CO_E_CLASSSTRING;
90 for (i = 1; i < 37; i++) {
91 if ((i == 9) || (i == 14) || (i == 19) || (i == 24))
92 continue;
93 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
94 ((s[i] >= 'a') && (s[i] <= 'f')) ||
95 ((s[i] >= 'A') && (s[i] <= 'F')))
97 return CO_E_CLASSSTRING;
101 TRACE("%s -> %p\n", s, id);
103 /* quick lookup table */
104 memset(table, 0, 256);
106 for (i = 0; i < 10; i++)
107 table['0' + i] = i;
109 for (i = 0; i < 6; i++) {
110 table['A' + i] = i+10;
111 table['a' + i] = i+10;
114 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
115 p = (BYTE *) id;
117 s++; /* skip leading brace */
118 for (i = 0; i < 4; i++) {
119 p[3 - i] = table[*s]<<4 | table[*(s+1)];
120 s += 2;
122 p += 4;
123 s++; /* skip - */
125 for (i = 0; i < 2; i++) {
126 p[1-i] = table[*s]<<4 | table[*(s+1)];
127 s += 2;
129 p += 2;
130 s++; /* skip - */
132 for (i = 0; i < 2; i++) {
133 p[1-i] = table[*s]<<4 | table[*(s+1)];
134 s += 2;
136 p += 2;
137 s++; /* skip - */
139 /* these are just sequential bytes */
140 for (i = 0; i < 2; i++) {
141 *p++ = table[*s]<<4 | table[*(s+1)];
142 s += 2;
144 s++; /* skip - */
146 for (i = 0; i < 6; i++) {
147 *p++ = table[*s]<<4 | table[*(s+1)];
148 s += 2;
151 return S_OK;
154 static BOOL AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile, LPCLSID lpclsid)
156 CHAR szRegKey[25];
157 CHAR szValue[100];
158 LPWSTR szExt = strrchrW(szFile, '.');
159 LONG len = sizeof(szValue) / sizeof(szValue[0]);
161 if (szExt == NULL)
162 return FALSE;
164 szExt++;
166 wsprintfA(szRegKey, "AVIFile\\Extensions\\%.3ls", szExt);
167 if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &len) != ERROR_SUCCESS)
168 return FALSE;
170 return (AVIFILE_CLSIDFromString(szValue, lpclsid) == S_OK);
173 /***********************************************************************
174 * AVIFileInit (AVIFIL32.@)
175 * AVIFileInit (AVIFILE.100)
177 void WINAPI AVIFileInit(void) {
178 /* need to load ole32.dll if not already done and get some functions */
179 FIXME("(): stub!\n");
182 /***********************************************************************
183 * AVIFileExit (AVIFIL32.@)
184 * AVIFileExit (AVIFILE.101)
186 void WINAPI AVIFileExit(void) {
187 /* need to free ole32.dll if we are the last exit call */
188 FIXME("(): stub!\n");
191 /***********************************************************************
192 * AVIFileOpenA (AVIFIL32.@)
193 * AVIFileOpen (AVIFILE.102)
195 HRESULT WINAPI AVIFileOpenA(PAVIFILE *ppfile, LPCSTR szFile, UINT uMode,
196 LPCLSID lpHandler)
198 LPWSTR wszFile = NULL;
199 HRESULT hr;
200 int len;
202 TRACE("(%p,%s,0x%08X,%s)\n", ppfile, debugstr_a(szFile), uMode,
203 debugstr_guid(lpHandler));
205 /* check parameters */
206 if (ppfile == NULL || szFile == NULL)
207 return AVIERR_BADPARAM;
209 /* convert ASCII string to Unicode and call unicode function */
210 len = lstrlenA(szFile);
211 if (len <= 0)
212 return AVIERR_BADPARAM;
214 wszFile = (LPWSTR)LocalAlloc(LPTR, (len + 1) * sizeof(WCHAR));
215 if (wszFile == NULL)
216 return AVIERR_MEMORY;
218 MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len + 1);
219 wszFile[len + 1] = 0;
221 hr = AVIFileOpenW(ppfile, wszFile, uMode, lpHandler);
223 LocalFree((HLOCAL)wszFile);
225 return hr;
228 /***********************************************************************
229 * AVIFileOpenW (AVIFIL32.@)
231 HRESULT WINAPI AVIFileOpenW(PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode,
232 LPCLSID lpHandler)
234 IPersistFile *ppersist = NULL;
235 CLSID clsidHandler;
236 HRESULT hr;
238 TRACE("(%p,%s,0x%X,%s)\n", ppfile, debugstr_w(szFile), uMode,
239 debugstr_guid(lpHandler));
241 /* check parameters */
242 if (ppfile == NULL || szFile == NULL)
243 return AVIERR_BADPARAM;
245 *ppfile = NULL;
247 /* if no handler then try guessing it by extension */
248 if (lpHandler == NULL) {
249 if (! AVIFILE_GetFileHandlerByExtension(szFile, &clsidHandler))
250 return AVIERR_UNSUPPORTED;
251 } else
252 memcpy(&clsidHandler, lpHandler, sizeof(clsidHandler));
254 /* crete instance of handler */
255 hr = SHCoCreateInstance(NULL, &clsidHandler, NULL,
256 &IID_IAVIFile, (LPVOID*)ppfile);
257 if (FAILED(hr) || *ppfile == NULL)
258 return hr;
260 /* ask for IPersistFile interface for loading/creating the file */
261 hr = IAVIFile_QueryInterface(*ppfile, &IID_IPersistFile, (LPVOID*)&ppersist);
262 if (FAILED(hr) || ppersist == NULL) {
263 IAVIFile_Release(*ppfile);
264 *ppfile = NULL;
265 return hr;
268 hr = IPersistFile_Load(ppersist, szFile, uMode);
269 IPersistFile_Release(ppersist);
270 if (FAILED(hr)) {
271 IAVIFile_Release(*ppfile);
272 *ppfile = NULL;
275 return hr;
278 /***********************************************************************
279 * AVIFileAddRef (AVIFIL32.@)
280 * AVIFileAddRef (AVIFILE.140)
282 ULONG WINAPI AVIFileAddRef(PAVIFILE pfile)
284 TRACE("(%p)\n", pfile);
286 if (pfile == NULL) {
287 ERR(": bad handle passed!\n");
288 return 0;
291 return IAVIFile_AddRef(pfile);
294 /***********************************************************************
295 * AVIFileRelease (AVIFIL32.@)
296 * AVIFileRelease (AVIFILE.141)
298 ULONG WINAPI AVIFileRelease(PAVIFILE pfile)
300 TRACE("(%p)\n", pfile);
302 if (pfile == NULL) {
303 ERR(": bad handle passed!\n");
304 return 0;
307 return IAVIFile_Release(pfile);
310 /***********************************************************************
311 * AVIFileInfo (AVIFIL32.@)
312 * AVIFileInfoA (AVIFIL32.@)
313 * AVIFileInfo (AVIFILE.142)
315 HRESULT WINAPI AVIFileInfoA(PAVIFILE pfile, LPAVIFILEINFOA afi, LONG size)
317 AVIFILEINFOW afiw;
318 HRESULT hres;
320 TRACE("(%p,%p,%ld)\n", pfile, afi, size);
322 if (pfile == NULL)
323 return AVIERR_BADHANDLE;
324 if ((DWORD)size < sizeof(AVIFILEINFOA))
325 return AVIERR_BADSIZE;
327 hres = IAVIFile_Info(pfile, &afiw, sizeof(afiw));
329 memcpy(afi, &afiw, sizeof(*afi) - sizeof(afi->szFileType));
330 WideCharToMultiByte(CP_ACP, 0, afiw.szFileType, -1, afi->szFileType,
331 sizeof(afi->szFileType), NULL, NULL);
332 afi->szFileType[sizeof(afi->szFileType) - 1] = 0;
334 return hres;
337 /***********************************************************************
338 * AVIFileInfoW (AVIFIL32.@)
340 HRESULT WINAPI AVIFileInfoW(PAVIFILE pfile, LPAVIFILEINFOW afiw, LONG size)
342 TRACE("(%p,%p,%ld)\n", pfile, afiw, size);
344 if (pfile == NULL)
345 return AVIERR_BADHANDLE;
347 return IAVIFile_Info(pfile, afiw, size);
350 /***********************************************************************
351 * AVIFileGetStream (AVIFIL32.@)
352 * AVIFileGetStream (AVIFILE.143)
354 HRESULT WINAPI AVIFileGetStream(PAVIFILE pfile, PAVISTREAM *avis,
355 DWORD fccType, LONG lParam)
357 TRACE("(%p,%p,'%4.4s',%ld)\n", pfile, avis, (char*)&fccType, lParam);
359 if (pfile == NULL)
360 return AVIERR_BADHANDLE;
362 return IAVIFile_GetStream(pfile, avis, fccType, lParam);
365 /***********************************************************************
366 * AVIFileCreateStreamA (AVIFIL32.@)
367 * AVIFileCreateStream (AVIFILE.144)
369 HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE pfile, PAVISTREAM *ppavi,
370 LPAVISTREAMINFOA psi)
372 AVISTREAMINFOW psiw;
374 TRACE("(%p,%p,%p)\n", pfile, ppavi, psi);
376 if (pfile == NULL)
377 return AVIERR_BADHANDLE;
379 /* Only the szName at the end is different */
380 memcpy(&psiw, psi, sizeof(*psi) - sizeof(psi->szName));
381 MultiByteToWideChar(CP_ACP, 0, psi->szName, -1, psiw.szName,
382 sizeof(psiw.szName) / sizeof(psiw.szName[0]));
384 return IAVIFile_CreateStream(pfile, ppavi, &psiw);
387 /***********************************************************************
388 * AVIFileCreateStreamW (AVIFIL32.@)
390 HRESULT WINAPI AVIFileCreateStreamW(PAVIFILE pfile, PAVISTREAM *avis,
391 LPAVISTREAMINFOW asi)
393 TRACE("(%p,%p,%p)\n", pfile, avis, asi);
395 return IAVIFile_CreateStream(pfile, avis, asi);
398 /***********************************************************************
399 * AVIFileWriteData (AVIFIL32.@)
400 * AVIFileWriteData (AVIFILE.146)
402 HRESULT WINAPI AVIFileWriteData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LONG size)
404 TRACE("(%p,'%4.4s',%p,%ld)\n", pfile, (char*)&fcc, lp, size);
406 if (pfile == NULL)
407 return AVIERR_BADHANDLE;
409 return IAVIFile_WriteData(pfile, fcc, lp, size);
412 /***********************************************************************
413 * AVIFileReadData (AVIFIL32.@)
414 * AVIFileReadData (AVIFILE.147)
416 HRESULT WINAPI AVIFileReadData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LPLONG size)
418 TRACE("(%p,'%4.4s',%p,%p)\n", pfile, (char*)&fcc, lp, size);
420 if (pfile == NULL)
421 return AVIERR_BADHANDLE;
423 return IAVIFile_ReadData(pfile, fcc, lp, size);
426 /***********************************************************************
427 * AVIFileEndRecord (AVIFIL32.@)
428 * AVIFileEndRecord (AVIFILE.148)
430 HRESULT WINAPI AVIFileEndRecord(PAVIFILE pfile)
432 TRACE("(%p)\n", pfile);
434 if (pfile == NULL)
435 return AVIERR_BADHANDLE;
437 return IAVIFile_EndRecord(pfile);
440 /***********************************************************************
441 * AVIStreamAddRef (AVIFIL32.@)
442 * AVIStreamAddRef (AVIFILE.160)
444 ULONG WINAPI AVIStreamAddRef(PAVISTREAM pstream)
446 TRACE("(%p)\n", pstream);
448 if (pstream == NULL) {
449 ERR(": bad handle passed!\n");
450 return 0;
453 return IAVIStream_AddRef(pstream);
456 /***********************************************************************
457 * AVIStreamRelease (AVIFIL32.@)
458 * AVIStreamRelease (AVIFILE.161)
460 ULONG WINAPI AVIStreamRelease(PAVISTREAM pstream)
462 TRACE("(%p)\n", pstream);
464 if (pstream == NULL) {
465 ERR(": bad handle passed!\n");
466 return 0;
469 return IAVIStream_Release(pstream);
472 /***********************************************************************
473 * AVIStreamCreate (AVIFIL32.@)
474 * AVIStreamCreate (AVIFILE.104)
476 HRESULT WINAPI AVIStreamCreate(PAVISTREAM *ppavi, LONG lParam1, LONG lParam2,
477 LPCLSID pclsidHandler)
479 HRESULT hr;
481 TRACE("(%p,0x%08lX,0x%08lX,%s)\n", ppavi, lParam1, lParam2,
482 debugstr_guid(pclsidHandler));
484 if (ppavi == NULL)
485 return AVIERR_BADPARAM;
487 *ppavi = NULL;
488 if (pclsidHandler == NULL)
489 return AVIERR_UNSUPPORTED;
491 hr = SHCoCreateInstance(NULL, pclsidHandler, NULL,
492 &IID_IAVIStream, (LPVOID*)ppavi);
493 if (FAILED(hr) || *ppavi == NULL)
494 return hr;
496 hr = IAVIStream_Create(*ppavi, lParam1, lParam2);
497 if (FAILED(hr)) {
498 IAVIStream_Release(*ppavi);
499 *ppavi = NULL;
502 return hr;
505 /***********************************************************************
506 * AVIStreamInfoA (AVIFIL32.@)
507 * AVIStreamInfo (AVIFILE.162)
509 HRESULT WINAPI AVIStreamInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
510 LONG size)
512 AVISTREAMINFOW asiw;
513 HRESULT hres;
515 TRACE("(%p,%p,%ld)\n", pstream, asi, size);
517 if (pstream == NULL)
518 return AVIERR_BADHANDLE;
519 if ((DWORD)size < sizeof(AVISTREAMINFOA))
520 return AVIERR_BADSIZE;
522 hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
524 memcpy(asi, &asiw, sizeof(asiw) - sizeof(asiw.szName));
525 WideCharToMultiByte(CP_ACP, 0, asiw.szName, -1, asi->szName,
526 sizeof(asi->szName), NULL, NULL);
527 asi->szName[sizeof(asi->szName) - 1] = 0;
529 return hres;
532 /***********************************************************************
533 * AVIStreamInfoW (AVIFIL32.@)
535 HRESULT WINAPI AVIStreamInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
536 LONG size)
538 TRACE("(%p,%p,%ld)\n", pstream, asi, size);
540 if (pstream == NULL)
541 return AVIERR_BADHANDLE;
543 return IAVIStream_Info(pstream, asi, size);
546 /***********************************************************************
547 * AVIStreamFindSample (AVIFIL32.@)
548 * AVIStreamFindSample (AVIFILE.163)
550 HRESULT WINAPI AVIStreamFindSample(PAVISTREAM pstream, LONG pos, DWORD flags)
552 TRACE("(%p,%ld,0x%lX)\n", pstream, pos, flags);
554 if (pstream == NULL)
555 return -1;
557 return IAVIStream_FindSample(pstream, pos, flags);
560 /***********************************************************************
561 * AVIStreamReadFormat (AVIFIL32.@)
562 * AVIStreamReadFormat (AVIFILE.164)
564 HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM pstream, LONG pos,
565 LPVOID format, LPLONG formatsize)
567 TRACE("(%p,%ld,%p,%p)\n", pstream, pos, format, formatsize);
569 if (pstream == NULL)
570 return AVIERR_BADHANDLE;
572 return IAVIStream_ReadFormat(pstream, pos, format, formatsize);
575 /***********************************************************************
576 * AVIStreamSetFormat (AVIFIL32.@)
577 * AVIStreamSetFormat (AVIFILE.169)
579 HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM pstream, LONG pos,
580 LPVOID format, LONG formatsize)
582 TRACE("(%p,%ld,%p,%ld)\n", pstream, pos, format, formatsize);
584 if (pstream == NULL)
585 return AVIERR_BADHANDLE;
587 return IAVIStream_SetFormat(pstream, pos, format, formatsize);
590 /***********************************************************************
591 * AVIStreamRead (AVIFIL32.@)
592 * AVIStreamRead (AVIFILE.167)
594 HRESULT WINAPI AVIStreamRead(PAVISTREAM pstream, LONG start, LONG samples,
595 LPVOID buffer, LONG buffersize,
596 LPLONG bytesread, LPLONG samplesread)
598 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", pstream, start, samples, buffer,
599 buffersize, bytesread, samplesread);
601 if (pstream == NULL)
602 return AVIERR_BADHANDLE;
604 return IAVIStream_Read(pstream, start, samples, buffer, buffersize,
605 bytesread, samplesread);
608 /***********************************************************************
609 * AVIStreamWrite (AVIFIL32.@)
610 * AVIStreamWrite (AVIFILE.168)
612 HRESULT WINAPI AVIStreamWrite(PAVISTREAM pstream, LONG start, LONG samples,
613 LPVOID buffer, LONG buffersize, DWORD flags,
614 LPLONG sampwritten, LPLONG byteswritten)
616 TRACE("(%p,%ld,%ld,%p,%ld,0x%lX,%p,%p)\n", pstream, start, samples, buffer,
617 buffersize, flags, sampwritten, byteswritten);
619 if (pstream == NULL)
620 return AVIERR_BADHANDLE;
622 return IAVIStream_Write(pstream, start, samples, buffer, buffersize,
623 flags, sampwritten, byteswritten);
626 /***********************************************************************
627 * AVIStreamReadData (AVIFIL32.@)
628 * AVIStreamReadData (AVIFILE.165)
630 HRESULT WINAPI AVIStreamReadData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
631 LPLONG lpread)
633 TRACE("(%p,'%4.4s',%p,%p)\n", pstream, (char*)&fcc, lp, lpread);
635 if (pstream == NULL)
636 return AVIERR_BADHANDLE;
638 return IAVIStream_ReadData(pstream, fcc, lp, lpread);
641 /***********************************************************************
642 * AVIStreamWriteData (AVIFIL32.@)
643 * AVIStreamWriteData (AVIFILE.166)
645 HRESULT WINAPI AVIStreamWriteData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
646 LONG size)
648 TRACE("(%p,'%4.4s',%p,%ld)\n", pstream, (char*)&fcc, lp, size);
650 if (pstream == NULL)
651 return AVIERR_BADHANDLE;
653 return IAVIStream_WriteData(pstream, fcc, lp, size);
656 /***********************************************************************
657 * AVIStreamGetFrameOpen (AVIFIL32.@)
658 * AVIStreamGetFrameOpen (AVIFILE.112)
660 PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pstream,
661 LPBITMAPINFOHEADER lpbiWanted)
663 PGETFRAME pg = NULL;
665 TRACE("(%p,%p)\n", pstream, lpbiWanted);
667 if (FAILED(IAVIStream_QueryInterface(pstream, &IID_IGetFrame, (LPVOID*)&pg)) ||
668 pg == NULL) {
669 pg = AVIFILE_CreateGetFrame(pstream);
670 if (pg == NULL)
671 return NULL;
674 if (FAILED(IGetFrame_SetFormat(pg, lpbiWanted, NULL, 0, 0, -1, -1))) {
675 IGetFrame_Release(pg);
676 return NULL;
679 return pg;
682 /***********************************************************************
683 * AVIStreamGetFrame (AVIFIL32.@)
684 * AVIStreamGetFrame (AVIFILE.110)
686 LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg, LONG pos)
688 TRACE("(%p,%ld)\n", pg, pos);
690 if (pg == NULL)
691 return NULL;
693 return IGetFrame_GetFrame(pg, pos);
696 /***********************************************************************
697 * AVIStreamGetFrameClose (AVIFIL32.@)
698 * AVIStreamGetFrameClose (AVIFILE.111)
700 HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg)
702 TRACE("(%p)\n", pg);
704 if (pg != NULL)
705 return IGetFrame_Release(pg);
706 return 0;
709 /***********************************************************************
710 * AVIMakeCompressedStream (AVIFIL32.@)
712 HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,
713 PAVISTREAM psSource,
714 LPAVICOMPRESSOPTIONS aco,
715 LPCLSID pclsidHandler)
717 AVISTREAMINFOW asiw;
718 CHAR szRegKey[25];
719 CHAR szValue[100];
720 CLSID clsidHandler;
721 HRESULT hr;
722 LONG size = sizeof(szValue);
724 TRACE("(%p,%p,%p,%s)\n", ppsCompressed, psSource, aco,
725 debugstr_guid(pclsidHandler));
727 if (ppsCompressed == NULL)
728 return AVIERR_BADPARAM;
729 if (psSource == NULL)
730 return AVIERR_BADHANDLE;
732 *ppsCompressed = NULL;
734 /* if no handler given get default ones based on streamtype */
735 if (pclsidHandler == NULL) {
736 hr = IAVIStream_Info(psSource, &asiw, sizeof(asiw));
737 if (FAILED(hr))
738 return hr;
740 wsprintfA(szRegKey, "AVIFile\\Compressors\\%4.4s", (char*)&asiw.fccType);
741 if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &size) != ERROR_SUCCESS)
742 return AVIERR_UNSUPPORTED;
743 if (AVIFILE_CLSIDFromString(szValue, &clsidHandler) != S_OK)
744 return AVIERR_UNSUPPORTED;
745 } else
746 memcpy(&clsidHandler, pclsidHandler, sizeof(clsidHandler));
748 hr = SHCoCreateInstance(NULL, &clsidHandler, NULL,
749 &IID_IAVIStream, (LPVOID*)ppsCompressed);
750 if (FAILED(hr) || *ppsCompressed == NULL)
751 return hr;
753 hr = IAVIStream_Create(*ppsCompressed, (LPARAM)psSource, (LPARAM)aco);
754 if (FAILED(hr)) {
755 IAVIStream_Release(*ppsCompressed);
756 *ppsCompressed = NULL;
759 return hr;
762 /***********************************************************************
763 * AVIMakeFileFromStreams (AVIFIL32.@)
765 HRESULT WINAPI AVIMakeFileFromStreams(PAVIFILE *ppfile, int nStreams,
766 PAVISTREAM *ppStreams)
768 TRACE("(%p,%d,%p)\n", ppfile, nStreams, ppStreams);
770 if (nStreams < 0 || ppfile == NULL || ppStreams == NULL)
771 return AVIERR_BADPARAM;
773 *ppfile = AVIFILE_CreateAVITempFile(nStreams, ppStreams);
774 if (*ppfile == NULL)
775 return AVIERR_MEMORY;
777 return AVIERR_OK;
780 /***********************************************************************
781 * AVIStreamOpenFromFile (AVIFILE.103)
782 * AVIStreamOpenFromFileA (AVIFIL32.@)
784 HRESULT WINAPI AVIStreamOpenFromFileA(PAVISTREAM *ppavi, LPCSTR szFile,
785 DWORD fccType, LONG lParam,
786 UINT mode, LPCLSID pclsidHandler)
788 PAVIFILE pfile = NULL;
789 HRESULT hr;
791 TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi, debugstr_a(szFile),
792 (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
794 if (ppavi == NULL || szFile == NULL)
795 return AVIERR_BADPARAM;
797 *ppavi = NULL;
799 hr = AVIFileOpenA(&pfile, szFile, mode, pclsidHandler);
800 if (FAILED(hr) || pfile == NULL)
801 return hr;
803 hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
804 IAVIFile_Release(pfile);
806 return hr;
809 /***********************************************************************
810 * AVIStreamOpenFromFileW (AVIFIL32.@)
812 HRESULT WINAPI AVIStreamOpenFromFileW(PAVISTREAM *ppavi, LPCWSTR szFile,
813 DWORD fccType, LONG lParam,
814 UINT mode, LPCLSID pclsidHandler)
816 PAVIFILE pfile = NULL;
817 HRESULT hr;
819 TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi, debugstr_w(szFile),
820 (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
822 if (ppavi == NULL || szFile == NULL)
823 return AVIERR_BADPARAM;
825 *ppavi = NULL;
827 hr = AVIFileOpenW(&pfile, szFile, mode, pclsidHandler);
828 if (FAILED(hr) || pfile == NULL)
829 return hr;
831 hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
832 IAVIFile_Release(pfile);
834 return hr;
837 /***********************************************************************
838 * AVIStreamBeginStreaming (AVIFIL32.@)
840 LONG WINAPI AVIStreamBeginStreaming(PAVISTREAM pavi, LONG lStart, LONG lEnd, LONG lRate)
842 FIXME("(%p)->(%ld,%ld,%ld)\n", pavi, lStart, lEnd, lRate);
844 return AVIERR_OK;
847 /***********************************************************************
848 * AVIStreamEndStreaming (AVIFIL32.@)
850 LONG WINAPI AVIStreamEndStreaming(PAVISTREAM pavi)
852 FIXME("(%p)\n", pavi);
854 return AVIERR_OK;
857 /***********************************************************************
858 * AVIStreamStart (AVIFILE.130)
859 * AVIStreamStart (AVIFIL32.@)
861 LONG WINAPI AVIStreamStart(PAVISTREAM pstream)
863 AVISTREAMINFOW asiw;
865 TRACE("(%p)\n", pstream);
867 if (pstream == NULL)
868 return 0;
870 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
871 return 0;
873 return asiw.dwStart;
876 /***********************************************************************
877 * AVIStreamLength (AVIFILE.131)
878 * AVIStreamLength (AVIFIL32.@)
880 LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
882 AVISTREAMINFOW asiw;
884 TRACE("(%p)\n", pstream);
886 if (pstream == NULL)
887 return 0;
889 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
890 return 0;
892 return asiw.dwLength;
895 /***********************************************************************
896 * AVIStreamSampleToTime (AVIFILE.133)
897 * AVIStreamSampleToTime (AVIFIL32.@)
899 LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
901 AVISTREAMINFOW asiw;
902 LONG time;
904 TRACE("(%p,%ld)\n", pstream, lSample);
906 if (pstream == NULL)
907 return -1;
909 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
910 return -1;
911 if (asiw.dwRate == 0)
912 return -1;
914 /* limit to stream bounds */
915 if (lSample < asiw.dwStart)
916 lSample = asiw.dwStart;
917 if (lSample > asiw.dwStart + asiw.dwLength)
918 lSample = asiw.dwStart + asiw.dwLength;
920 if (asiw.dwRate / asiw.dwScale < 1000)
921 time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
922 else
923 time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);
925 TRACE(" -> %ld\n",time);
926 return time;
929 /***********************************************************************
930 * AVIStreamTimeToSample (AVIFILE.132)
931 * AVIStreamTimeToSample (AVIFIL32.@)
933 LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
935 AVISTREAMINFOW asiw;
936 LONG sample;
938 TRACE("(%p,%ld)\n", pstream, lTime);
940 if (pstream == NULL || lTime < 0)
941 return -1;
943 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
944 return -1;
945 if (asiw.dwScale == 0)
946 return -1;
948 if (asiw.dwRate / asiw.dwScale < 1000)
949 sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
950 else
951 sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));
953 /* limit to stream bounds */
954 if (sample < asiw.dwStart)
955 sample = asiw.dwStart;
956 if (sample > asiw.dwStart + asiw.dwLength)
957 sample = asiw.dwStart + asiw.dwLength;
959 TRACE(" -> %ld\n", sample);
960 return sample;
963 /***********************************************************************
964 * AVIBuildFilterA (AVIFIL32.@)
965 * AVIBuildFilter (AVIFILE.123)
967 HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
969 LPWSTR wszFilter;
970 HRESULT hr;
972 TRACE("(%p,%ld,%d)\n", szFilter, cbFilter, fSaving);
974 /* check parameters */
975 if (szFilter == NULL)
976 return AVIERR_BADPARAM;
977 if (cbFilter < 2)
978 return AVIERR_BADSIZE;
980 szFilter[0] = 0;
981 szFilter[1] = 0;
983 wszFilter = (LPWSTR)GlobalAllocPtr(GHND, cbFilter);
984 if (wszFilter == NULL)
985 return AVIERR_MEMORY;
987 hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
988 if (SUCCEEDED(hr)) {
989 WideCharToMultiByte(CP_ACP, 0, wszFilter, cbFilter,
990 szFilter, cbFilter, NULL, NULL);
993 GlobalFreePtr(wszFilter);
995 return hr;
998 /***********************************************************************
999 * AVIBuildFilterW (AVIFIL32.@)
1001 HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving)
1003 static const WCHAR szClsid[] = {'C','L','S','I','D',0};
1004 static const WCHAR szExtensionFmt[] = {';','*','.','%','s',0};
1005 static const WCHAR szAVIFileExtensions[] =
1006 {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1008 AVIFilter *lp;
1009 WCHAR szAllFiles[40];
1010 WCHAR szFileExt[10];
1011 WCHAR szValue[128];
1012 HKEY hKey;
1013 DWORD n, i;
1014 LONG size;
1015 DWORD count = 0;
1017 TRACE("(%p,%ld,%d)\n", szFilter, cbFilter, fSaving);
1019 /* check parameters */
1020 if (szFilter == NULL)
1021 return AVIERR_BADPARAM;
1022 if (cbFilter < 2)
1023 return AVIERR_BADSIZE;
1025 lp = (AVIFilter*)GlobalAllocPtr(GHND, MAX_FILTERS * sizeof(AVIFilter));
1026 if (lp == NULL)
1027 return AVIERR_MEMORY;
1030 * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
1031 * extensions and CLSID's
1032 * 2. iterate over collected CLSID's and copy it's description and it's
1033 * extensions to szFilter if it fits
1035 * First filter is named "All multimedia files" and it's filter is a
1036 * collection of all possible extensions except "*.*".
1038 if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != S_OK) {
1039 GlobalFreePtr(lp);
1040 return AVIERR_ERROR;
1042 for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)) == S_OK;n++) {
1043 /* get CLSID to extension */
1044 size = sizeof(szValue)/sizeof(szValue[0]);
1045 if (RegQueryValueW(hKey, szFileExt, szValue, &size) != S_OK)
1046 break;
1048 /* search if the CLSID is already known */
1049 for (i = 1; i <= count; i++) {
1050 if (lstrcmpW(lp[i].szClsid, szValue) == 0)
1051 break; /* a new one */
1054 if (count - i == -1U) {
1055 /* it's a new CLSID */
1057 /* FIXME: How do we get info's about read/write capabilities? */
1059 if (count >= MAX_FILTERS) {
1060 /* try to inform user of our full fixed size table */
1061 ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS);
1062 break;
1065 lstrcpyW(lp[i].szClsid, szValue);
1067 count++;
1070 /* append extension to the filter */
1071 wsprintfW(szValue, szExtensionFmt, szFileExt);
1072 if (lp[i].szExtensions[0] == 0)
1073 lstrcatW(lp[i].szExtensions, szValue + 1);
1074 else
1075 lstrcatW(lp[i].szExtensions, szValue);
1077 /* also append to the "all multimedia"-filter */
1078 if (lp[0].szExtensions[0] == 0)
1079 lstrcatW(lp[0].szExtensions, szValue + 1);
1080 else
1081 lstrcatW(lp[0].szExtensions, szValue);
1083 RegCloseKey(hKey);
1085 /* 2. get descriptions for the CLSIDs and fill out szFilter */
1086 if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != S_OK) {
1087 GlobalFreePtr(lp);
1088 return AVIERR_ERROR;
1090 for (n = 0; n <= count; n++) {
1091 /* first the description */
1092 if (n != 0) {
1093 size = sizeof(szValue)/sizeof(szValue[0]);
1094 if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == S_OK) {
1095 size = lstrlenW(szValue);
1096 lstrcpynW(szFilter, szValue, cbFilter);
1098 } else
1099 size = LoadStringW(AVIFILE_hModule,IDS_ALLMULTIMEDIA,szFilter,cbFilter);
1101 /* check for enough space */
1102 size++;
1103 if (cbFilter < size + lstrlenW(lp[n].szExtensions) + 2) {
1104 szFilter[0] = 0;
1105 szFilter[1] = 0;
1106 GlobalFreePtr(lp);
1107 RegCloseKey(hKey);
1108 return AVIERR_BUFFERTOOSMALL;
1110 cbFilter -= size;
1111 szFilter += size;
1113 /* and then the filter */
1114 lstrcpynW(szFilter, lp[n].szExtensions, cbFilter);
1115 size = lstrlenW(lp[n].szExtensions) + 1;
1116 cbFilter -= size;
1117 szFilter += size;
1120 RegCloseKey(hKey);
1121 GlobalFreePtr(lp);
1123 /* add "All files" "*.*" filter if enough space left */
1124 size = LoadStringW(AVIFILE_hModule, IDS_ALLFILES,
1125 szAllFiles, sizeof(szAllFiles)) + 1;
1126 if (cbFilter > size) {
1127 int i;
1129 /* replace '@' with \000 to separate description of filter */
1130 for (i = 0; i < size && szAllFiles[i] != 0; i++) {
1131 if (szAllFiles[i] == '@') {
1132 szAllFiles[i] = 0;
1133 break;
1137 memcpy(szFilter, szAllFiles, size * sizeof(szAllFiles[0]));
1138 szFilter += size;
1139 szFilter[0] = 0;
1141 return AVIERR_OK;
1142 } else {
1143 szFilter[0] = 0;
1144 return AVIERR_BUFFERTOOSMALL;
1148 static BOOL AVISaveOptionsFmtChoose(HWND hWnd)
1150 LPAVICOMPRESSOPTIONS pOptions = SaveOpts.ppOptions[SaveOpts.nCurrent];
1151 AVISTREAMINFOW sInfo;
1153 TRACE("(%p)\n", hWnd);
1155 if (pOptions == NULL || SaveOpts.ppavis[SaveOpts.nCurrent] == NULL) {
1156 ERR(": bad state!\n");
1157 return FALSE;
1160 if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent],
1161 &sInfo, sizeof(sInfo)))) {
1162 ERR(": AVIStreamInfoW failed!\n");
1163 return FALSE;
1166 if (sInfo.fccType == streamtypeVIDEO) {
1167 COMPVARS cv;
1168 BOOL ret;
1170 memset(&cv, 0, sizeof(cv));
1172 if ((pOptions->dwFlags & AVICOMPRESSF_VALID) == 0) {
1173 memset(pOptions, 0, sizeof(AVICOMPRESSOPTIONS));
1174 pOptions->fccType = streamtypeVIDEO;
1175 pOptions->fccHandler = comptypeDIB;
1176 pOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
1179 cv.cbSize = sizeof(cv);
1180 cv.dwFlags = ICMF_COMPVARS_VALID;
1181 /*cv.fccType = pOptions->fccType; */
1182 cv.fccHandler = pOptions->fccHandler;
1183 cv.lQ = pOptions->dwQuality;
1184 cv.lpState = pOptions->lpParms;
1185 cv.cbState = pOptions->cbParms;
1186 if (pOptions->dwFlags & AVICOMPRESSF_KEYFRAMES)
1187 cv.lKey = pOptions->dwKeyFrameEvery;
1188 else
1189 cv.lKey = 0;
1190 if (pOptions->dwFlags & AVICOMPRESSF_DATARATE)
1191 cv.lDataRate = pOptions->dwBytesPerSecond / 1024; /* need kBytes */
1192 else
1193 cv.lDataRate = 0;
1195 ret = ICCompressorChoose(hWnd, SaveOpts.uFlags, NULL,
1196 SaveOpts.ppavis[SaveOpts.nCurrent], &cv, NULL);
1198 if (ret) {
1199 pOptions->fccHandler = cv.fccHandler;
1200 pOptions->lpParms = cv.lpState;
1201 pOptions->cbParms = cv.cbState;
1202 pOptions->dwQuality = cv.lQ;
1203 if (cv.lKey != 0) {
1204 pOptions->dwKeyFrameEvery = cv.lKey;
1205 pOptions->dwFlags |= AVICOMPRESSF_KEYFRAMES;
1206 } else
1207 pOptions->dwFlags &= ~AVICOMPRESSF_KEYFRAMES;
1208 if (cv.lDataRate != 0) {
1209 pOptions->dwBytesPerSecond = cv.lDataRate * 1024; /* need bytes */
1210 pOptions->dwFlags |= AVICOMPRESSF_DATARATE;
1211 } else
1212 pOptions->dwFlags &= ~AVICOMPRESSF_DATARATE;
1213 pOptions->dwFlags |= AVICOMPRESSF_VALID;
1215 ICCompressorFree(&cv);
1217 return ret;
1218 } else if (sInfo.fccType == streamtypeAUDIO) {
1219 ACMFORMATCHOOSEW afmtc;
1220 MMRESULT ret;
1221 LONG size;
1223 /* FIXME: check ACM version -- Which version is needed? */
1225 memset(&afmtc, 0, sizeof(afmtc));
1226 afmtc.cbStruct = sizeof(afmtc);
1227 afmtc.fdwStyle = 0;
1228 afmtc.hwndOwner = hWnd;
1230 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &size);
1231 if ((pOptions->cbFormat == 0 || pOptions->lpFormat == NULL) && size != 0) {
1232 pOptions->lpFormat = GlobalAllocPtr(GMEM_MOVEABLE, size);
1233 pOptions->cbFormat = size;
1234 } else if (pOptions->cbFormat < (DWORD)size) {
1235 pOptions->lpFormat = GlobalReAllocPtr(pOptions->lpFormat, size, GMEM_MOVEABLE);
1236 pOptions->cbFormat = size;
1238 if (pOptions->lpFormat == NULL)
1239 return FALSE;
1240 afmtc.pwfx = pOptions->lpFormat;
1241 afmtc.cbwfx = pOptions->cbFormat;
1243 size = 0;
1244 AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],
1245 sInfo.dwStart, &size);
1246 if (size < (LONG)sizeof(PCMWAVEFORMAT))
1247 size = sizeof(PCMWAVEFORMAT);
1248 afmtc.pwfxEnum = GlobalAllocPtr(GHND, size);
1249 if (afmtc.pwfxEnum != NULL) {
1250 AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],
1251 sInfo.dwStart, afmtc.pwfxEnum, &size);
1252 afmtc.fdwEnum = ACM_FORMATENUMF_CONVERT;
1255 ret = acmFormatChooseW(&afmtc);
1256 if (ret == S_OK)
1257 pOptions->dwFlags |= AVICOMPRESSF_VALID;
1259 if (afmtc.pwfxEnum != NULL)
1260 GlobalFreePtr(afmtc.pwfxEnum);
1262 return (ret == S_OK ? TRUE : FALSE);
1263 } else {
1264 ERR(": unknown streamtype 0x%08lX\n", sInfo.fccType);
1265 return FALSE;
1269 static void AVISaveOptionsUpdate(HWND hWnd)
1271 static const WCHAR szVideoFmt[]={'%','l','d','x','%','l','d','x','%','d',0};
1272 static const WCHAR szAudioFmt[]={'%','s',' ','%','s',0};
1274 WCHAR szFormat[128];
1275 AVISTREAMINFOW sInfo;
1276 LPVOID lpFormat;
1277 LONG size;
1279 TRACE("(%p)\n", hWnd);
1281 SaveOpts.nCurrent = SendDlgItemMessageW(hWnd,IDC_STREAM,CB_GETCURSEL,0,0);
1282 if (SaveOpts.nCurrent < 0)
1283 return;
1285 if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent], &sInfo, sizeof(sInfo))))
1286 return;
1288 AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,&size);
1289 if (size > 0) {
1290 szFormat[0] = 0;
1292 /* read format to build format descriotion string */
1293 lpFormat = GlobalAllocPtr(GHND, size);
1294 if (lpFormat != NULL) {
1295 if (SUCCEEDED(AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,lpFormat, &size))) {
1296 if (sInfo.fccType == streamtypeVIDEO) {
1297 LPBITMAPINFOHEADER lpbi = lpFormat;
1298 ICINFO icinfo;
1300 wsprintfW(szFormat, szVideoFmt, lpbi->biWidth,
1301 lpbi->biHeight, lpbi->biBitCount);
1303 if (lpbi->biCompression != BI_RGB) {
1304 HIC hic;
1306 hic = ICLocate(ICTYPE_VIDEO, sInfo.fccHandler, lpFormat,
1307 NULL, ICMODE_DECOMPRESS);
1308 if (hic != NULL) {
1309 if (ICGetInfo(hic, &icinfo, sizeof(icinfo)) == S_OK)
1310 lstrcatW(szFormat, icinfo.szDescription);
1311 ICClose(hic);
1313 } else {
1314 LoadStringW(AVIFILE_hModule, IDS_UNCOMPRESSED,
1315 icinfo.szDescription, sizeof(icinfo.szDescription));
1316 lstrcatW(szFormat, icinfo.szDescription);
1318 } else if (sInfo.fccType == streamtypeAUDIO) {
1319 ACMFORMATTAGDETAILSW aftd;
1320 ACMFORMATDETAILSW afd;
1322 memset(&aftd, 0, sizeof(aftd));
1323 memset(&afd, 0, sizeof(afd));
1325 aftd.cbStruct = sizeof(aftd);
1326 aftd.dwFormatTag = afd.dwFormatTag =
1327 ((PWAVEFORMATEX)lpFormat)->wFormatTag;
1328 aftd.cbFormatSize = afd.cbwfx = size;
1330 afd.cbStruct = sizeof(afd);
1331 afd.pwfx = lpFormat;
1333 if (acmFormatTagDetailsW(NULL, &aftd,
1334 ACM_FORMATTAGDETAILSF_FORMATTAG) == S_OK) {
1335 if (acmFormatDetailsW(NULL,&afd,ACM_FORMATDETAILSF_FORMAT) == S_OK)
1336 wsprintfW(szFormat, szAudioFmt, afd.szFormat, aftd.szFormatTag);
1340 GlobalFreePtr(lpFormat);
1343 /* set text for format description */
1344 SetDlgItemTextW(hWnd, IDC_FORMATTEXT, szFormat);
1346 /* Disable option button for unsupported streamtypes */
1347 if (sInfo.fccType == streamtypeVIDEO ||
1348 sInfo.fccType == streamtypeAUDIO)
1349 EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), TRUE);
1350 else
1351 EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), FALSE);
1356 INT_PTR CALLBACK AVISaveOptionsDlgProc(HWND hWnd, UINT uMsg,
1357 WPARAM wParam, LPARAM lParam)
1359 DWORD dwInterleave;
1360 BOOL bIsInterleaved;
1361 INT n;
1363 /*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
1365 switch (uMsg) {
1366 case WM_INITDIALOG:
1367 SaveOpts.nCurrent = 0;
1368 if (SaveOpts.nStreams == 1) {
1369 EndDialog(hWnd, AVISaveOptionsFmtChoose(hWnd));
1370 return TRUE;
1373 /* add streams */
1374 for (n = 0; n < SaveOpts.nStreams; n++) {
1375 AVISTREAMINFOW sInfo;
1377 AVIStreamInfoW(SaveOpts.ppavis[n], &sInfo, sizeof(sInfo));
1378 SendDlgItemMessageW(hWnd, IDC_STREAM, CB_ADDSTRING,
1379 0L, (LPARAM)sInfo.szName);
1382 /* select first stream */
1383 SendDlgItemMessageW(hWnd, IDC_STREAM, CB_SETCURSEL, 0, 0);
1384 SendMessageW(hWnd, WM_COMMAND,
1385 GET_WM_COMMAND_MPS(IDC_STREAM, hWnd, CBN_SELCHANGE));
1387 /* initialize interleave */
1388 if (SaveOpts.ppOptions[0] != NULL &&
1389 (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_VALID)) {
1390 bIsInterleaved = (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_INTERLEAVE);
1391 dwInterleave = SaveOpts.ppOptions[0]->dwInterleaveEvery;
1392 } else {
1393 bIsInterleaved = TRUE;
1394 dwInterleave = 0;
1396 CheckDlgButton(hWnd, IDC_INTERLEAVE, bIsInterleaved);
1397 SetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, dwInterleave, FALSE);
1398 EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY), bIsInterleaved);
1399 break;
1400 case WM_COMMAND:
1401 switch (GET_WM_COMMAND_ID(wParam, lParam)) {
1402 case IDOK:
1403 /* get data from controls and save them */
1404 dwInterleave = GetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, NULL, 0);
1405 bIsInterleaved = IsDlgButtonChecked(hWnd, IDC_INTERLEAVE);
1406 for (n = 0; n < SaveOpts.nStreams; n++) {
1407 if (SaveOpts.ppOptions[n] != NULL) {
1408 if (bIsInterleaved) {
1409 SaveOpts.ppOptions[n]->dwFlags |= AVICOMPRESSF_INTERLEAVE;
1410 SaveOpts.ppOptions[n]->dwInterleaveEvery = dwInterleave;
1411 } else
1412 SaveOpts.ppOptions[n]->dwFlags &= ~AVICOMPRESSF_INTERLEAVE;
1415 /* fall through */
1416 case IDCANCEL:
1417 EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
1418 break;
1419 case IDC_INTERLEAVE:
1420 EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY),
1421 IsDlgButtonChecked(hWnd, IDC_INTERLEAVE));
1422 break;
1423 case IDC_STREAM:
1424 if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) {
1425 /* update control elements */
1426 AVISaveOptionsUpdate(hWnd);
1428 break;
1429 case IDC_OPTIONS:
1430 AVISaveOptionsFmtChoose(hWnd);
1431 break;
1433 return TRUE;
1436 return FALSE;
1439 /***********************************************************************
1440 * AVISaveOptions (AVIFIL32.@)
1442 BOOL WINAPI AVISaveOptions(HWND hWnd, UINT uFlags, INT nStreams,
1443 PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *ppOptions)
1445 LPAVICOMPRESSOPTIONS pSavedOptions = NULL;
1446 INT ret, n;
1448 TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd, uFlags, nStreams,
1449 ppavi, ppOptions);
1451 /* check parameters */
1452 if (nStreams <= 0 || ppavi == NULL || ppOptions == NULL)
1453 return AVIERR_BADPARAM;
1455 /* save options for case user press cancel */
1456 if (ppOptions != NULL && nStreams > 1) {
1457 pSavedOptions = GlobalAllocPtr(GHND,nStreams * sizeof(AVICOMPRESSOPTIONS));
1458 if (pSavedOptions == NULL)
1459 return FALSE;
1461 for (n = 0; n < nStreams; n++) {
1462 if (ppOptions[n] != NULL)
1463 memcpy(pSavedOptions + n, ppOptions[n], sizeof(AVICOMPRESSOPTIONS));
1467 SaveOpts.uFlags = uFlags;
1468 SaveOpts.nStreams = nStreams;
1469 SaveOpts.ppavis = ppavi;
1470 SaveOpts.ppOptions = ppOptions;
1472 ret = DialogBoxW(AVIFILE_hModule, MAKEINTRESOURCEW(IDD_SAVEOPTIONS),
1473 hWnd, AVISaveOptionsDlgProc);
1475 if (ret == -1)
1476 ret = FALSE;
1478 /* restore options when user pressed cancel */
1479 if (pSavedOptions != NULL) {
1480 if (ret == FALSE) {
1481 for (n = 0; n < nStreams; n++) {
1482 if (ppOptions[n] != NULL)
1483 memcpy(ppOptions[n], pSavedOptions + n, sizeof(AVICOMPRESSOPTIONS));
1486 GlobalFreePtr(pSavedOptions);
1489 return (BOOL)ret;
1492 /***********************************************************************
1493 * AVISaveOptionsFree (AVIFIL32.@)
1494 * AVISaveOptionsFree (AVIFILE.124)
1496 HRESULT WINAPI AVISaveOptionsFree(INT nStreams,LPAVICOMPRESSOPTIONS*ppOptions)
1498 TRACE("(%d,%p)\n", nStreams, ppOptions);
1500 if (nStreams < 0 || ppOptions == NULL)
1501 return AVIERR_BADPARAM;
1503 for (; nStreams > 0; nStreams--) {
1504 if (ppOptions[nStreams] != NULL) {
1505 ppOptions[nStreams]->dwFlags &= ~AVICOMPRESSF_VALID;
1507 if (ppOptions[nStreams]->lpParms != NULL) {
1508 GlobalFreePtr(ppOptions[nStreams]->lpParms);
1509 ppOptions[nStreams]->lpParms = NULL;
1510 ppOptions[nStreams]->cbParms = 0;
1512 if (ppOptions[nStreams]->lpFormat != NULL) {
1513 GlobalFreePtr(ppOptions[nStreams]->lpFormat);
1514 ppOptions[nStreams]->lpFormat = NULL;
1515 ppOptions[nStreams]->cbFormat = 0;
1520 return AVIERR_OK;
1523 /***********************************************************************
1524 * AVISaveVA (AVIFIL32.@)
1526 HRESULT WINAPI AVISaveVA(LPCSTR szFile, CLSID *pclsidHandler,
1527 AVISAVECALLBACK lpfnCallback, int nStream,
1528 PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
1530 LPWSTR wszFile = NULL;
1531 HRESULT hr;
1532 int len;
1534 TRACE("%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile), pclsidHandler,
1535 lpfnCallback, nStream, ppavi, plpOptions);
1537 if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
1538 return AVIERR_BADPARAM;
1540 /* convert ASCII string to Unicode and call Unicode function */
1541 len = lstrlenA(szFile);
1542 if (len <= 0)
1543 return AVIERR_BADPARAM;
1545 wszFile = (LPWSTR)LocalAlloc(LPTR, (len + 1) * sizeof(WCHAR));
1546 if (wszFile == NULL)
1547 return AVIERR_MEMORY;
1549 MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len + 1);
1550 wszFile[len + 1] = 0;
1552 hr = AVISaveVW(wszFile, pclsidHandler, lpfnCallback,
1553 nStream, ppavi, plpOptions);
1555 LocalFree((HLOCAL)wszFile);
1557 return hr;
1560 /***********************************************************************
1561 * AVIFILE_AVISaveDefaultCallback (internal)
1563 static BOOL WINAPI AVIFILE_AVISaveDefaultCallback(INT progress)
1565 TRACE("(%d)\n", progress);
1567 return FALSE;
1570 /***********************************************************************
1571 * AVISaveVW (AVIFIL32.@)
1573 HRESULT WINAPI AVISaveVW(LPCWSTR szFile, CLSID *pclsidHandler,
1574 AVISAVECALLBACK lpfnCallback, int nStreams,
1575 PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
1577 LONG lStart[MAX_AVISTREAMS];
1578 PAVISTREAM pOutStreams[MAX_AVISTREAMS];
1579 PAVISTREAM pInStreams[MAX_AVISTREAMS];
1580 AVIFILEINFOW fInfo;
1581 AVISTREAMINFOW sInfo;
1583 PAVIFILE pfile = NULL; /* the output AVI file */
1584 LONG lFirstVideo = -1;
1585 int curStream;
1587 /* for interleaving ... */
1588 DWORD dwInterleave = 0; /* interleave rate */
1589 DWORD dwFileInitialFrames;
1590 LONG lFileLength;
1591 LONG lSampleInc;
1593 /* for reading/writing the data ... */
1594 LPVOID lpBuffer = NULL;
1595 LONG cbBuffer; /* real size of lpBuffer */
1596 LONG lBufferSize; /* needed bytes for format(s), etc. */
1597 LONG lReadBytes;
1598 LONG lReadSamples;
1599 HRESULT hres;
1601 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile), pclsidHandler,
1602 lpfnCallback, nStreams, ppavi, plpOptions);
1604 if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
1605 return AVIERR_BADPARAM;
1606 if (nStreams >= MAX_AVISTREAMS) {
1607 WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams, MAX_AVISTREAMS);
1608 return AVIERR_INTERNAL;
1611 if (lpfnCallback == NULL)
1612 lpfnCallback = AVIFILE_AVISaveDefaultCallback;
1614 /* clear local variable(s) */
1615 for (curStream = 0; curStream < nStreams; curStream++) {
1616 pInStreams[curStream] = NULL;
1617 pOutStreams[curStream] = NULL;
1620 /* open output AVI file (create it if it doesn't exist) */
1621 hres = AVIFileOpenW(&pfile, szFile, OF_CREATE|OF_SHARE_EXCLUSIVE|OF_WRITE,
1622 pclsidHandler);
1623 if (FAILED(hres))
1624 return hres;
1625 AVIFileInfoW(pfile, &fInfo, sizeof(fInfo)); /* for dwCaps */
1627 /* initialize our data structures part 1 */
1628 for (curStream = 0; curStream < nStreams; curStream++) {
1629 PAVISTREAM pCurStream = ppavi[curStream];
1631 hres = AVIStreamInfoW(pCurStream, &sInfo, sizeof(sInfo));
1632 if (FAILED(hres))
1633 goto error;
1635 /* search first video stream and check for interleaving */
1636 if (sInfo.fccType == streamtypeVIDEO) {
1637 /* remember first video stream -- needed for interleaving */
1638 if (lFirstVideo < 0)
1639 lFirstVideo = curStream;
1640 } else if (!dwInterleave && plpOptions != NULL) {
1641 /* check if any non-video stream wants to be interleaved */
1642 WARN("options.flags=0x%lX options.dwInterleave=%lu\n",plpOptions[curStream]->dwFlags,plpOptions[curStream]->dwInterleaveEvery);
1643 if (plpOptions[curStream] != NULL &&
1644 plpOptions[curStream]->dwFlags & AVICOMPRESSF_INTERLEAVE)
1645 dwInterleave = plpOptions[curStream]->dwInterleaveEvery;
1648 /* create de-/compressed stream interface if needed */
1649 pInStreams[curStream] = NULL;
1650 if (plpOptions != NULL && plpOptions[curStream] != NULL) {
1651 if (plpOptions[curStream]->fccHandler ||
1652 plpOptions[curStream]->lpFormat != NULL) {
1653 DWORD dwKeySave = plpOptions[curStream]->dwKeyFrameEvery;
1655 if (fInfo.dwCaps & AVIFILECAPS_ALLKEYFRAMES)
1656 plpOptions[curStream]->dwKeyFrameEvery = 1;
1658 hres = AVIMakeCompressedStream(&pInStreams[curStream], pCurStream,
1659 plpOptions[curStream], NULL);
1660 plpOptions[curStream]->dwKeyFrameEvery = dwKeySave;
1661 if (FAILED(hres) || pInStreams[curStream] == NULL) {
1662 pInStreams[curStream] = NULL;
1663 goto error;
1666 /* test stream interface and update stream-info */
1667 hres = AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1668 if (FAILED(hres))
1669 goto error;
1673 /* now handle streams which will only be copied */
1674 if (pInStreams[curStream] == NULL) {
1675 pCurStream = pInStreams[curStream] = ppavi[curStream];
1676 AVIStreamAddRef(pCurStream);
1677 } else
1678 pCurStream = pInStreams[curStream];
1680 lStart[curStream] = sInfo.dwStart;
1681 } /* for all streams */
1683 /* check that first video stream is the first stream */
1684 if (lFirstVideo > 0) {
1685 PAVISTREAM pTmp = pInStreams[lFirstVideo];
1686 LONG lTmp = lStart[lFirstVideo];
1688 pInStreams[lFirstVideo] = pInStreams[0];
1689 pInStreams[0] = pTmp;
1690 lStart[lFirstVideo] = lStart[0];
1691 lStart[0] = lTmp;
1692 lFirstVideo = 0;
1695 /* allocate buffer for formats, data, etc. of an initiale size of 64 kByte */
1696 lpBuffer = GlobalAllocPtr(GPTR, cbBuffer = 0x00010000);
1697 if (lpBuffer == NULL) {
1698 hres = AVIERR_MEMORY;
1699 goto error;
1702 AVIStreamInfoW(pInStreams[0], &sInfo, sizeof(sInfo));
1703 lFileLength = sInfo.dwLength;
1704 dwFileInitialFrames = 0;
1705 if (lFirstVideo >= 0) {
1706 /* check for correct version of the format
1707 * -- need atleast BITMAPINFOHEADER or newer
1709 lSampleInc = 1;
1710 lBufferSize = cbBuffer;
1711 hres = AVIStreamReadFormat(pInStreams[lFirstVideo], AVIStreamStart(pInStreams[lFirstVideo]), lpBuffer, &lBufferSize);
1712 if (lBufferSize < (LONG)sizeof(BITMAPINFOHEADER))
1713 hres = AVIERR_INTERNAL;
1714 if (FAILED(hres))
1715 goto error;
1716 } else /* use one second blocks for interleaving if no video present */
1717 lSampleInc = AVIStreamTimeToSample(pInStreams[0], 1000000);
1719 /* create output streams */
1720 for (curStream = 0; curStream < nStreams; curStream++) {
1721 AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1723 sInfo.dwInitialFrames = 0;
1724 if (dwInterleave != 0 && curStream > 0 && sInfo.fccType != streamtypeVIDEO) {
1725 /* 750 ms initial frames for non-video streams */
1726 sInfo.dwInitialFrames = AVIStreamTimeToSample(pInStreams[0], 750);
1729 hres = AVIFileCreateStreamW(pfile, &pOutStreams[curStream], &sInfo);
1730 if (pOutStreams[curStream] != NULL && SUCCEEDED(hres)) {
1731 /* copy initial format for this stream */
1732 lBufferSize = cbBuffer;
1733 hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1734 lpBuffer, &lBufferSize);
1735 if (FAILED(hres))
1736 goto error;
1737 hres = AVIStreamSetFormat(pOutStreams[curStream], 0, lpBuffer, lBufferSize);
1738 if (FAILED(hres))
1739 goto error;
1741 /* try to copy stream handler data */
1742 lBufferSize = cbBuffer;
1743 hres = AVIStreamReadData(pInStreams[curStream], ckidSTREAMHANDLERDATA,
1744 lpBuffer, &lBufferSize);
1745 if (SUCCEEDED(hres) && lBufferSize > 0) {
1746 hres = AVIStreamWriteData(pOutStreams[curStream],ckidSTREAMHANDLERDATA,
1747 lpBuffer, lBufferSize);
1748 if (FAILED(hres))
1749 goto error;
1752 if (dwFileInitialFrames < sInfo.dwInitialFrames)
1753 dwFileInitialFrames = sInfo.dwInitialFrames;
1754 lReadBytes =
1755 AVIStreamSampleToSample(pOutStreams[0], pInStreams[curStream],
1756 sInfo.dwLength);
1757 if (lFileLength < lReadBytes)
1758 lFileLength = lReadBytes;
1759 } else {
1760 /* creation of de-/compression stream interface failed */
1761 WARN("creation of (de-)compression stream failed for stream %d\n",curStream);
1762 AVIStreamRelease(pInStreams[curStream]);
1763 if (curStream + 1 >= nStreams) {
1764 /* move the others one up */
1765 PAVISTREAM *ppas = &pInStreams[curStream];
1766 int n = nStreams - (curStream + 1);
1768 do {
1769 *ppas = pInStreams[curStream + 1];
1770 } while (--n);
1772 nStreams--;
1773 curStream--;
1775 } /* create output streams for all input streams */
1777 /* have we still something to write, or lost everything? */
1778 if (nStreams <= 0)
1779 goto error;
1781 if (dwInterleave) {
1782 LONG lCurFrame = -dwFileInitialFrames;
1784 /* interleaved file */
1785 if (dwInterleave == 1)
1786 AVIFileEndRecord(pfile);
1788 for (; lCurFrame < lFileLength; lCurFrame += lSampleInc) {
1789 for (curStream = 0; curStream < nStreams; curStream++) {
1790 LONG lLastSample;
1792 hres = AVIStreamInfoW(pOutStreams[curStream], &sInfo, sizeof(sInfo));
1793 if (FAILED(hres))
1794 goto error;
1796 /* initial frames phase at the end for this stream? */
1797 if (-(LONG)sInfo.dwInitialFrames > lCurFrame)
1798 continue;
1800 if ((lFileLength - lSampleInc) <= lCurFrame) {
1801 lLastSample = AVIStreamLength(pInStreams[curStream]);
1802 lFirstVideo = lLastSample + AVIStreamStart(pInStreams[curStream]);
1803 } else {
1804 if (curStream != 0) {
1805 lFirstVideo =
1806 AVIStreamSampleToSample(pInStreams[curStream], pInStreams[0],
1807 (sInfo.fccType == streamtypeVIDEO ?
1808 (LONG)dwInterleave : lSampleInc) +
1809 sInfo.dwInitialFrames + lCurFrame);
1810 } else
1811 lFirstVideo = lSampleInc + (sInfo.dwInitialFrames + lCurFrame);
1813 lLastSample = AVIStreamEnd(pInStreams[curStream]);
1814 if (lLastSample <= lFirstVideo)
1815 lFirstVideo = lLastSample;
1818 /* copy needed samples now */
1819 WARN("copy from stream %d samples %ld to %ld...\n",curStream,
1820 lStart[curStream],lFirstVideo);
1821 while (lFirstVideo > lStart[curStream]) {
1822 DWORD flags = 0;
1824 /* copy format for case it can change */
1825 lBufferSize = cbBuffer;
1826 hres = AVIStreamReadFormat(pInStreams[curStream], lStart[curStream],
1827 lpBuffer, &lBufferSize);
1828 if (FAILED(hres))
1829 goto error;
1830 AVIStreamSetFormat(pOutStreams[curStream], lStart[curStream],
1831 lpBuffer, lBufferSize);
1833 /* try to read data until we got it, or error */
1834 do {
1835 hres = AVIStreamRead(pInStreams[curStream], lStart[curStream],
1836 lFirstVideo - lStart[curStream], lpBuffer,
1837 cbBuffer, &lReadBytes, &lReadSamples);
1838 } while ((hres == AVIERR_BUFFERTOOSMALL) &&
1839 (lpBuffer = GlobalReAllocPtr(lpBuffer, cbBuffer *= 2, GPTR)) != NULL);
1840 if (lpBuffer == NULL)
1841 hres = AVIERR_MEMORY;
1842 if (FAILED(hres))
1843 goto error;
1845 if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
1846 flags = AVIIF_KEYFRAME;
1847 hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1848 lpBuffer, lReadBytes, flags, NULL, NULL);
1849 if (FAILED(hres))
1850 goto error;
1852 lStart[curStream] += lReadSamples;
1854 lStart[curStream] = lFirstVideo;
1855 } /* stream by stream */
1857 /* need to close this block? */
1858 if (dwInterleave == 1) {
1859 hres = AVIFileEndRecord(pfile);
1860 if (FAILED(hres))
1861 break;
1864 /* show progress */
1865 if (lpfnCallback(MulDiv(dwFileInitialFrames + lCurFrame, 100,
1866 dwFileInitialFrames + lFileLength))) {
1867 hres = AVIERR_USERABORT;
1868 break;
1870 } /* copy frame by frame */
1871 } else {
1872 /* non-interleaved file */
1874 for (curStream = 0; curStream < nStreams; curStream++) {
1875 /* show progress */
1876 if (lpfnCallback(MulDiv(curStream, 100, nStreams))) {
1877 hres = AVIERR_USERABORT;
1878 goto error;
1881 AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1883 if (sInfo.dwSampleSize != 0) {
1884 /* sample-based data like audio */
1885 while (sInfo.dwStart < sInfo.dwLength) {
1886 LONG lSamples = cbBuffer / sInfo.dwSampleSize;
1888 /* copy format for case it can change */
1889 lBufferSize = cbBuffer;
1890 hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1891 lpBuffer, &lBufferSize);
1892 if (FAILED(hres))
1893 return hres;
1894 AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
1895 lpBuffer, lBufferSize);
1897 /* limit to stream boundaries */
1898 if (lSamples != (LONG)(sInfo.dwLength - sInfo.dwStart))
1899 lSamples = sInfo.dwLength - sInfo.dwStart;
1901 /* now try to read until we got it, or error occures */
1902 do {
1903 lReadBytes = cbBuffer;
1904 lReadSamples = 0;
1905 hres = AVIStreamRead(pInStreams[curStream],sInfo.dwStart,lSamples,
1906 lpBuffer,cbBuffer,&lReadBytes,&lReadSamples);
1907 } while ((hres == AVIERR_BUFFERTOOSMALL) &&
1908 (lpBuffer = GlobalReAllocPtr(lpBuffer, cbBuffer *= 2, GPTR)) != NULL);
1909 if (lpBuffer == NULL)
1910 hres = AVIERR_MEMORY;
1911 if (FAILED(hres))
1912 goto error;
1913 if (lReadSamples != 0) {
1914 sInfo.dwStart += lReadSamples;
1915 hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1916 lpBuffer, lReadBytes, 0, NULL , NULL);
1917 if (FAILED(hres))
1918 goto error;
1920 /* show progress */
1921 if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
1922 MulDiv(curStream, 100, nStreams))) {
1923 hres = AVIERR_USERABORT;
1924 goto error;
1926 } else {
1927 if ((sInfo.dwLength - sInfo.dwStart) != 1) {
1928 hres = AVIERR_FILEREAD;
1929 goto error;
1933 } else {
1934 /* block-based data like video */
1935 for (; sInfo.dwStart < sInfo.dwLength; sInfo.dwStart++) {
1936 DWORD flags = 0;
1938 /* copy format for case it can change */
1939 lBufferSize = cbBuffer;
1940 hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1941 lpBuffer, &lBufferSize);
1942 if (FAILED(hres))
1943 goto error;
1944 AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
1945 lpBuffer, lBufferSize);
1947 /* try to read block and resize buffer if necessary */
1948 do {
1949 lReadSamples = 0;
1950 lReadBytes = cbBuffer;
1951 hres = AVIStreamRead(pInStreams[curStream], sInfo.dwStart, 1,
1952 lpBuffer, cbBuffer,&lReadBytes,&lReadSamples);
1953 } while ((hres == AVIERR_BUFFERTOOSMALL) &&
1954 (lpBuffer = GlobalReAllocPtr(lpBuffer, cbBuffer *= 2, GPTR)) != NULL);
1955 if (lpBuffer == NULL)
1956 hres = AVIERR_MEMORY;
1957 if (FAILED(hres))
1958 goto error;
1959 if (lReadSamples != 1) {
1960 hres = AVIERR_FILEREAD;
1961 goto error;
1964 if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
1965 flags = AVIIF_KEYFRAME;
1966 hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1967 lpBuffer, lReadBytes, flags, NULL, NULL);
1968 if (FAILED(hres))
1969 goto error;
1971 /* show progress */
1972 if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
1973 MulDiv(curStream, 100, nStreams))) {
1974 hres = AVIERR_USERABORT;
1975 goto error;
1977 } /* copy all blocks */
1979 } /* copy data stream by stream */
1982 error:
1983 if (lpBuffer != NULL)
1984 GlobalFreePtr(lpBuffer);
1985 if (pfile != NULL) {
1986 for (curStream = 0; curStream < nStreams; curStream++) {
1987 if (pOutStreams[curStream] != NULL)
1988 AVIStreamRelease(pOutStreams[curStream]);
1989 if (pInStreams[curStream] != NULL)
1990 AVIStreamRelease(pInStreams[curStream]);
1993 AVIFileRelease(pfile);
1996 return hres;
1999 /***********************************************************************
2000 * CreateEditableStream (AVIFIL32.@)
2002 HRESULT WINAPI CreateEditableStream(PAVISTREAM *ppEditable, PAVISTREAM pSource)
2004 IAVIEditStream *pEdit = NULL;
2005 HRESULT hr;
2007 FIXME("(%p,%p), semi stub!\n", ppEditable, pSource);
2009 if (ppEditable == NULL)
2010 return AVIERR_BADPARAM;
2012 *ppEditable = NULL;
2014 if (pSource != NULL) {
2015 hr = IAVIStream_QueryInterface(pSource, &IID_IAVIEditStream,
2016 (LPVOID*)&pEdit);
2017 if (FAILED(hr) || pEdit == NULL) {
2018 /* need own implementation of IAVIEditStream */
2020 return AVIERR_UNSUPPORTED;
2024 hr = IAVIEditStream_Clone(pEdit, ppEditable);
2025 IAVIEditStream_Release(pEdit);
2027 return hr;
2030 /***********************************************************************
2031 * EditStreamClone (AVIFIL32.@)
2033 HRESULT WINAPI EditStreamClone(PAVISTREAM pStream, PAVISTREAM *ppResult)
2035 PAVIEDITSTREAM pEdit = NULL;
2036 HRESULT hr;
2038 TRACE("(%p,%p)\n", pStream, ppResult);
2040 if (pStream == NULL)
2041 return AVIERR_BADHANDLE;
2042 if (ppResult == NULL)
2043 return AVIERR_BADPARAM;
2045 *ppResult = NULL;
2047 hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2048 if (SUCCEEDED(hr) && pEdit != NULL) {
2049 hr = IAVIEditStream_Clone(pEdit, ppResult);
2051 IAVIEditStream_Release(pEdit);
2052 } else
2053 hr = AVIERR_UNSUPPORTED;
2055 return hr;
2058 /***********************************************************************
2059 * EditStreamCopy (AVIFIL32.@)
2061 HRESULT WINAPI EditStreamCopy(PAVISTREAM pStream, LONG *plStart,
2062 LONG *plLength, PAVISTREAM *ppResult)
2064 PAVIEDITSTREAM pEdit = NULL;
2065 HRESULT hr;
2067 TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
2069 if (pStream == NULL)
2070 return AVIERR_BADHANDLE;
2071 if (plStart == NULL || plLength == NULL || ppResult == NULL)
2072 return AVIERR_BADPARAM;
2074 *ppResult = NULL;
2076 hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2077 if (SUCCEEDED(hr) && pEdit != NULL) {
2078 hr = IAVIEditStream_Copy(pEdit, plStart, plLength, ppResult);
2080 IAVIEditStream_Release(pEdit);
2081 } else
2082 hr = AVIERR_UNSUPPORTED;
2084 return hr;
2087 /***********************************************************************
2088 * EditStreamCut (AVIFIL32.@)
2090 HRESULT WINAPI EditStreamCut(PAVISTREAM pStream, LONG *plStart,
2091 LONG *plLength, PAVISTREAM *ppResult)
2093 PAVIEDITSTREAM pEdit = NULL;
2094 HRESULT hr;
2096 TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
2098 if (pStream == NULL)
2099 return AVIERR_BADHANDLE;
2100 if (plStart == NULL || plLength == NULL || ppResult == NULL)
2101 return AVIERR_BADPARAM;
2103 *ppResult = NULL;
2105 hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2106 if (SUCCEEDED(hr) && pEdit != NULL) {
2107 hr = IAVIEditStream_Cut(pEdit, plStart, plLength, ppResult);
2109 IAVIEditStream_Release(pEdit);
2110 } else
2111 hr = AVIERR_UNSUPPORTED;
2113 return hr;
2116 /***********************************************************************
2117 * EditStreamPaste (AVIFIL32.@)
2119 HRESULT WINAPI EditStreamPaste(PAVISTREAM pDest, LONG *plStart, LONG *plLength,
2120 PAVISTREAM pSource, LONG lStart, LONG lEnd)
2122 PAVIEDITSTREAM pEdit = NULL;
2123 HRESULT hr;
2125 TRACE("(%p,%p,%p,%p,%ld,%ld)\n", pDest, plStart, plLength,
2126 pSource, lStart, lEnd);
2128 if (pDest == NULL || pSource == NULL)
2129 return AVIERR_BADHANDLE;
2130 if (plStart == NULL || plLength == NULL || lStart < 0)
2131 return AVIERR_BADPARAM;
2133 hr = IAVIStream_QueryInterface(pDest, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2134 if (SUCCEEDED(hr) && pEdit != NULL) {
2135 hr = IAVIEditStream_Paste(pEdit, plStart, plLength, pSource, lStart, lEnd);
2137 IAVIEditStream_Release(pEdit);
2138 } else
2139 hr = AVIERR_UNSUPPORTED;
2141 return hr;
2144 /***********************************************************************
2145 * EditStreamSetInfoA (AVIFIL32.@)
2147 HRESULT WINAPI EditStreamSetInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
2148 LONG size)
2150 AVISTREAMINFOW asiw;
2152 TRACE("(%p,%p,%ld)\n", pstream, asi, size);
2154 if (pstream == NULL)
2155 return AVIERR_BADHANDLE;
2156 if ((DWORD)size < sizeof(AVISTREAMINFOA))
2157 return AVIERR_BADSIZE;
2159 memcpy(&asiw, asi, sizeof(asi) - sizeof(asi->szName));
2160 MultiByteToWideChar(CP_ACP, 0, asi->szName, -1,
2161 asiw.szName, sizeof(asiw.szName));
2163 return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
2166 /***********************************************************************
2167 * EditStreamSetInfoW (AVIFIL32.@)
2169 HRESULT WINAPI EditStreamSetInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
2170 LONG size)
2172 PAVIEDITSTREAM pEdit = NULL;
2173 HRESULT hr;
2175 TRACE("(%p,%p,%ld)\n", pstream, asi, size);
2177 hr = IAVIStream_QueryInterface(pstream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2178 if (SUCCEEDED(hr) && pEdit != NULL) {
2179 hr = IAVIEditStream_SetInfo(pEdit, asi, size);
2181 IAVIEditStream_Release(pEdit);
2182 } else
2183 hr = AVIERR_UNSUPPORTED;
2185 return hr;
2188 /***********************************************************************
2189 * EditStreamSetNameA (AVIFIL32.@)
2191 HRESULT WINAPI EditStreamSetNameA(PAVISTREAM pstream, LPCSTR szName)
2193 AVISTREAMINFOA asia;
2194 HRESULT hres;
2196 TRACE("(%p,%s)\n", pstream, debugstr_a(szName));
2198 if (pstream == NULL)
2199 return AVIERR_BADHANDLE;
2200 if (szName == NULL)
2201 return AVIERR_BADPARAM;
2203 hres = AVIStreamInfoA(pstream, &asia, sizeof(asia));
2204 if (FAILED(hres))
2205 return hres;
2207 memset(asia.szName, 0, sizeof(asia.szName));
2208 lstrcpynA(asia.szName, szName, sizeof(asia.szName)/sizeof(asia.szName[0]));
2210 return EditStreamSetInfoA(pstream, &asia, sizeof(asia));
2213 /***********************************************************************
2214 * EditStreamSetNameW (AVIFIL32.@)
2216 HRESULT WINAPI EditStreamSetNameW(PAVISTREAM pstream, LPCWSTR szName)
2218 AVISTREAMINFOW asiw;
2219 HRESULT hres;
2221 TRACE("(%p,%s)\n", pstream, debugstr_w(szName));
2223 if (pstream == NULL)
2224 return AVIERR_BADHANDLE;
2225 if (szName == NULL)
2226 return AVIERR_BADPARAM;
2228 hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
2229 if (FAILED(hres))
2230 return hres;
2232 memset(asiw.szName, 0, sizeof(asiw.szName));
2233 lstrcpynW(asiw.szName, szName, sizeof(asiw.szName)/sizeof(asiw.szName[0]));
2235 return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
2238 /***********************************************************************
2239 * AVIClearClipboard (AVIFIL32.@)
2241 HRESULT WINAPI AVIClearClipboard(void)
2243 TRACE("()\n");
2245 return AVIERR_UNSUPPORTED; /* OleSetClipboard(NULL); */
2248 /***********************************************************************
2249 * AVIGetFromClipboard (AVIFIL32.@)
2251 HRESULT WINAPI AVIGetFromClipboard(PAVIFILE *ppfile)
2253 FIXME("(%p), stub!\n", ppfile);
2255 *ppfile = NULL;
2257 return AVIERR_UNSUPPORTED;
2260 /***********************************************************************
2261 * AVIPutFileOnClipboard (AVIFIL32.@)
2263 HRESULT WINAPI AVIPutFileOnClipboard(PAVIFILE pfile)
2265 FIXME("(%p), stub!\n", pfile);
2267 if (pfile == NULL)
2268 return AVIERR_BADHANDLE;
2270 return AVIERR_UNSUPPORTED;