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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
38 #include "avifile_private.h"
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
46 /***********************************************************************
47 * for AVIBuildFilterW -- uses fixed size table
49 #define MAX_FILTERS 30 /* 30 => 7kB */
51 typedef struct _AVIFilter
{
53 WCHAR szExtensions
[MAX_FILTERS
* 7];
56 /***********************************************************************
63 LPAVICOMPRESSOPTIONS
*ppOptions
;
67 /***********************************************************************
68 * copied from dlls/ole32/compobj.c
70 static HRESULT
AVIFILE_CLSIDFromString(LPCSTR idstr
, LPCLSID id
)
78 memset(id
, 0, sizeof(CLSID
));
82 /* validate the CLSID string */
83 if (lstrlenA(idstr
) != 38)
84 return CO_E_CLASSSTRING
;
86 s
= (BYTE
const*)idstr
;
87 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') ||
88 (s
[24]!='-') || (s
[37]!='}'))
89 return CO_E_CLASSSTRING
;
91 for (i
= 1; i
< 37; i
++) {
92 if ((i
== 9) || (i
== 14) || (i
== 19) || (i
== 24))
94 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
95 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
96 ((s
[i
] >= 'A') && (s
[i
] <= 'F')))
98 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
++)
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} */
117 s
++; /* skip leading brace */
118 for (i
= 0; i
< 4; i
++) {
119 p
[3 - i
] = table
[*s
]<<4 | table
[*(s
+1)];
125 for (i
= 0; i
< 2; i
++) {
126 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
132 for (i
= 0; i
< 2; i
++) {
133 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
139 /* these are just sequential bytes */
140 for (i
= 0; i
< 2; i
++) {
141 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
146 for (i
= 0; i
< 6; i
++) {
147 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
154 static BOOL
AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile
, LPCLSID lpclsid
)
158 LPWSTR szExt
= strrchrW(szFile
, '.');
159 LONG len
= sizeof(szValue
) / sizeof(szValue
[0]);
166 wsprintfA(szRegKey
, "AVIFile\\Extensions\\%.3ls", szExt
);
167 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &len
) != ERROR_SUCCESS
)
170 return (AVIFILE_CLSIDFromString(szValue
, lpclsid
) == S_OK
);
173 /***********************************************************************
174 * AVIFileInit (AVIFIL32.@)
176 void WINAPI
AVIFileInit(void) {
180 /***********************************************************************
181 * AVIFileExit (AVIFIL32.@)
183 void WINAPI
AVIFileExit(void) {
184 /* need to free ole32.dll if we are the last exit call */
185 /* OleUninitialize() */
186 FIXME("(): stub!\n");
189 /***********************************************************************
190 * AVIFileOpen (AVIFIL32.@)
191 * AVIFileOpenA (AVIFIL32.@)
193 HRESULT WINAPI
AVIFileOpenA(PAVIFILE
*ppfile
, LPCSTR szFile
, UINT uMode
,
196 LPWSTR wszFile
= NULL
;
200 TRACE("(%p,%s,0x%08X,%s)\n", ppfile
, debugstr_a(szFile
), uMode
,
201 debugstr_guid(lpHandler
));
203 /* check parameters */
204 if (ppfile
== NULL
|| szFile
== NULL
)
205 return AVIERR_BADPARAM
;
207 /* convert ASCII string to Unicode and call unicode function */
208 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
210 return AVIERR_BADPARAM
;
212 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
214 return AVIERR_MEMORY
;
216 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
218 hr
= AVIFileOpenW(ppfile
, wszFile
, uMode
, lpHandler
);
220 HeapFree(GetProcessHeap(), 0, wszFile
);
225 /***********************************************************************
226 * AVIFileOpenW (AVIFIL32.@)
228 HRESULT WINAPI
AVIFileOpenW(PAVIFILE
*ppfile
, LPCWSTR szFile
, UINT uMode
,
231 IPersistFile
*ppersist
= NULL
;
235 TRACE("(%p,%s,0x%X,%s)\n", ppfile
, debugstr_w(szFile
), uMode
,
236 debugstr_guid(lpHandler
));
238 /* check parameters */
239 if (ppfile
== NULL
|| szFile
== NULL
)
240 return AVIERR_BADPARAM
;
244 /* if no handler then try guessing it by extension */
245 if (lpHandler
== NULL
) {
246 if (! AVIFILE_GetFileHandlerByExtension(szFile
, &clsidHandler
))
247 clsidHandler
= CLSID_AVIFile
;
249 clsidHandler
= *lpHandler
;
251 /* create instance of handler */
252 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIFile
, (LPVOID
*)ppfile
);
253 if (FAILED(hr
) || *ppfile
== NULL
)
256 /* ask for IPersistFile interface for loading/creating the file */
257 hr
= IAVIFile_QueryInterface(*ppfile
, &IID_IPersistFile
, (LPVOID
*)&ppersist
);
258 if (FAILED(hr
) || ppersist
== NULL
) {
259 IAVIFile_Release(*ppfile
);
264 hr
= IPersistFile_Load(ppersist
, szFile
, uMode
);
265 IPersistFile_Release(ppersist
);
267 IAVIFile_Release(*ppfile
);
274 /***********************************************************************
275 * AVIFileAddRef (AVIFIL32.@)
277 ULONG WINAPI
AVIFileAddRef(PAVIFILE pfile
)
279 TRACE("(%p)\n", pfile
);
282 ERR(": bad handle passed!\n");
286 return IAVIFile_AddRef(pfile
);
289 /***********************************************************************
290 * AVIFileRelease (AVIFIL32.@)
292 ULONG WINAPI
AVIFileRelease(PAVIFILE pfile
)
294 TRACE("(%p)\n", pfile
);
297 ERR(": bad handle passed!\n");
301 return IAVIFile_Release(pfile
);
304 /***********************************************************************
305 * AVIFileInfo (AVIFIL32.@)
306 * AVIFileInfoA (AVIFIL32.@)
308 HRESULT WINAPI
AVIFileInfoA(PAVIFILE pfile
, LPAVIFILEINFOA afi
, LONG size
)
313 TRACE("(%p,%p,%d)\n", pfile
, afi
, size
);
316 return AVIERR_BADHANDLE
;
317 if ((DWORD
)size
< sizeof(AVIFILEINFOA
))
318 return AVIERR_BADSIZE
;
320 hres
= IAVIFile_Info(pfile
, &afiw
, sizeof(afiw
));
322 memcpy(afi
, &afiw
, sizeof(*afi
) - sizeof(afi
->szFileType
));
323 WideCharToMultiByte(CP_ACP
, 0, afiw
.szFileType
, -1, afi
->szFileType
,
324 sizeof(afi
->szFileType
), NULL
, NULL
);
325 afi
->szFileType
[sizeof(afi
->szFileType
) - 1] = 0;
330 /***********************************************************************
331 * AVIFileInfoW (AVIFIL32.@)
333 HRESULT WINAPI
AVIFileInfoW(PAVIFILE pfile
, LPAVIFILEINFOW afiw
, LONG size
)
335 TRACE("(%p,%p,%d)\n", pfile
, afiw
, size
);
338 return AVIERR_BADHANDLE
;
340 return IAVIFile_Info(pfile
, afiw
, size
);
343 /***********************************************************************
344 * AVIFileGetStream (AVIFIL32.@)
346 HRESULT WINAPI
AVIFileGetStream(PAVIFILE pfile
, PAVISTREAM
*avis
,
347 DWORD fccType
, LONG lParam
)
349 TRACE("(%p,%p,'%4.4s',%d)\n", pfile
, avis
, (char*)&fccType
, lParam
);
352 return AVIERR_BADHANDLE
;
354 return IAVIFile_GetStream(pfile
, avis
, fccType
, lParam
);
357 /***********************************************************************
358 * AVIFileCreateStream (AVIFIL32.@)
359 * AVIFileCreateStreamA (AVIFIL32.@)
361 HRESULT WINAPI
AVIFileCreateStreamA(PAVIFILE pfile
, PAVISTREAM
*ppavi
,
362 LPAVISTREAMINFOA psi
)
366 TRACE("(%p,%p,%p)\n", pfile
, ppavi
, psi
);
369 return AVIERR_BADHANDLE
;
371 /* Only the szName at the end is different */
372 memcpy(&psiw
, psi
, sizeof(*psi
) - sizeof(psi
->szName
));
373 MultiByteToWideChar(CP_ACP
, 0, psi
->szName
, -1, psiw
.szName
,
374 sizeof(psiw
.szName
) / sizeof(psiw
.szName
[0]));
376 return IAVIFile_CreateStream(pfile
, ppavi
, &psiw
);
379 /***********************************************************************
380 * AVIFileCreateStreamW (AVIFIL32.@)
382 HRESULT WINAPI
AVIFileCreateStreamW(PAVIFILE pfile
, PAVISTREAM
*avis
,
383 LPAVISTREAMINFOW asi
)
385 TRACE("(%p,%p,%p)\n", pfile
, avis
, asi
);
388 return AVIERR_BADHANDLE
;
390 return IAVIFile_CreateStream(pfile
, avis
, asi
);
393 /***********************************************************************
394 * AVIFileWriteData (AVIFIL32.@)
396 HRESULT WINAPI
AVIFileWriteData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LONG size
)
398 TRACE("(%p,'%4.4s',%p,%d)\n", pfile
, (char*)&fcc
, lp
, size
);
401 return AVIERR_BADHANDLE
;
403 return IAVIFile_WriteData(pfile
, fcc
, lp
, size
);
406 /***********************************************************************
407 * AVIFileReadData (AVIFIL32.@)
409 HRESULT WINAPI
AVIFileReadData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LPLONG size
)
411 TRACE("(%p,'%4.4s',%p,%p)\n", pfile
, (char*)&fcc
, lp
, size
);
414 return AVIERR_BADHANDLE
;
416 return IAVIFile_ReadData(pfile
, fcc
, lp
, size
);
419 /***********************************************************************
420 * AVIFileEndRecord (AVIFIL32.@)
422 HRESULT WINAPI
AVIFileEndRecord(PAVIFILE pfile
)
424 TRACE("(%p)\n", pfile
);
427 return AVIERR_BADHANDLE
;
429 return IAVIFile_EndRecord(pfile
);
432 /***********************************************************************
433 * AVIStreamAddRef (AVIFIL32.@)
435 ULONG WINAPI
AVIStreamAddRef(PAVISTREAM pstream
)
437 TRACE("(%p)\n", pstream
);
439 if (pstream
== NULL
) {
440 ERR(": bad handle passed!\n");
444 return IAVIStream_AddRef(pstream
);
447 /***********************************************************************
448 * AVIStreamRelease (AVIFIL32.@)
450 ULONG WINAPI
AVIStreamRelease(PAVISTREAM pstream
)
452 TRACE("(%p)\n", pstream
);
454 if (pstream
== NULL
) {
455 ERR(": bad handle passed!\n");
459 return IAVIStream_Release(pstream
);
462 /***********************************************************************
463 * AVIStreamCreate (AVIFIL32.@)
465 HRESULT WINAPI
AVIStreamCreate(PAVISTREAM
*ppavi
, LONG lParam1
, LONG lParam2
,
466 LPCLSID pclsidHandler
)
470 TRACE("(%p,0x%08X,0x%08X,%s)\n", ppavi
, lParam1
, lParam2
,
471 debugstr_guid(pclsidHandler
));
474 return AVIERR_BADPARAM
;
477 if (pclsidHandler
== NULL
)
478 return AVIERR_UNSUPPORTED
;
480 hr
= CoCreateInstance(pclsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppavi
);
481 if (FAILED(hr
) || *ppavi
== NULL
)
484 hr
= IAVIStream_Create(*ppavi
, lParam1
, lParam2
);
486 IAVIStream_Release(*ppavi
);
493 /***********************************************************************
494 * AVIStreamInfo (AVIFIL32.@)
495 * AVIStreamInfoA (AVIFIL32.@)
497 HRESULT WINAPI
AVIStreamInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
503 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
506 return AVIERR_BADHANDLE
;
507 if ((DWORD
)size
< sizeof(AVISTREAMINFOA
))
508 return AVIERR_BADSIZE
;
510 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
512 memcpy(asi
, &asiw
, sizeof(asiw
) - sizeof(asiw
.szName
));
513 WideCharToMultiByte(CP_ACP
, 0, asiw
.szName
, -1, asi
->szName
,
514 sizeof(asi
->szName
), NULL
, NULL
);
515 asi
->szName
[sizeof(asi
->szName
) - 1] = 0;
520 /***********************************************************************
521 * AVIStreamInfoW (AVIFIL32.@)
523 HRESULT WINAPI
AVIStreamInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
526 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
529 return AVIERR_BADHANDLE
;
531 return IAVIStream_Info(pstream
, asi
, size
);
534 /***********************************************************************
535 * AVIStreamFindSample (AVIFIL32.@)
537 LONG WINAPI
AVIStreamFindSample(PAVISTREAM pstream
, LONG pos
, LONG flags
)
539 TRACE("(%p,%d,0x%X)\n", pstream
, pos
, flags
);
544 return IAVIStream_FindSample(pstream
, pos
, flags
);
547 /***********************************************************************
548 * AVIStreamReadFormat (AVIFIL32.@)
550 HRESULT WINAPI
AVIStreamReadFormat(PAVISTREAM pstream
, LONG pos
,
551 LPVOID format
, LPLONG formatsize
)
553 TRACE("(%p,%d,%p,%p)\n", pstream
, pos
, format
, formatsize
);
556 return AVIERR_BADHANDLE
;
558 return IAVIStream_ReadFormat(pstream
, pos
, format
, formatsize
);
561 /***********************************************************************
562 * AVIStreamSetFormat (AVIFIL32.@)
564 HRESULT WINAPI
AVIStreamSetFormat(PAVISTREAM pstream
, LONG pos
,
565 LPVOID format
, LONG formatsize
)
567 TRACE("(%p,%d,%p,%d)\n", pstream
, pos
, format
, formatsize
);
570 return AVIERR_BADHANDLE
;
572 return IAVIStream_SetFormat(pstream
, pos
, format
, formatsize
);
575 /***********************************************************************
576 * AVIStreamRead (AVIFIL32.@)
578 HRESULT WINAPI
AVIStreamRead(PAVISTREAM pstream
, LONG start
, LONG samples
,
579 LPVOID buffer
, LONG buffersize
,
580 LPLONG bytesread
, LPLONG samplesread
)
582 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", pstream
, start
, samples
, buffer
,
583 buffersize
, bytesread
, samplesread
);
586 return AVIERR_BADHANDLE
;
588 return IAVIStream_Read(pstream
, start
, samples
, buffer
, buffersize
,
589 bytesread
, samplesread
);
592 /***********************************************************************
593 * AVIStreamWrite (AVIFIL32.@)
595 HRESULT WINAPI
AVIStreamWrite(PAVISTREAM pstream
, LONG start
, LONG samples
,
596 LPVOID buffer
, LONG buffersize
, DWORD flags
,
597 LPLONG sampwritten
, LPLONG byteswritten
)
599 TRACE("(%p,%d,%d,%p,%d,0x%X,%p,%p)\n", pstream
, start
, samples
, buffer
,
600 buffersize
, flags
, sampwritten
, byteswritten
);
603 return AVIERR_BADHANDLE
;
605 return IAVIStream_Write(pstream
, start
, samples
, buffer
, buffersize
,
606 flags
, sampwritten
, byteswritten
);
609 /***********************************************************************
610 * AVIStreamReadData (AVIFIL32.@)
612 HRESULT WINAPI
AVIStreamReadData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
615 TRACE("(%p,'%4.4s',%p,%p)\n", pstream
, (char*)&fcc
, lp
, lpread
);
618 return AVIERR_BADHANDLE
;
620 return IAVIStream_ReadData(pstream
, fcc
, lp
, lpread
);
623 /***********************************************************************
624 * AVIStreamWriteData (AVIFIL32.@)
626 HRESULT WINAPI
AVIStreamWriteData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
629 TRACE("(%p,'%4.4s',%p,%d)\n", pstream
, (char*)&fcc
, lp
, size
);
632 return AVIERR_BADHANDLE
;
634 return IAVIStream_WriteData(pstream
, fcc
, lp
, size
);
637 /***********************************************************************
638 * AVIStreamGetFrameOpen (AVIFIL32.@)
640 PGETFRAME WINAPI
AVIStreamGetFrameOpen(PAVISTREAM pstream
,
641 LPBITMAPINFOHEADER lpbiWanted
)
645 TRACE("(%p,%p)\n", pstream
, lpbiWanted
);
647 if (FAILED(IAVIStream_QueryInterface(pstream
, &IID_IGetFrame
, (LPVOID
*)&pg
)) ||
649 pg
= AVIFILE_CreateGetFrame(pstream
);
654 if (FAILED(IGetFrame_SetFormat(pg
, lpbiWanted
, NULL
, 0, 0, -1, -1))) {
655 IGetFrame_Release(pg
);
662 /***********************************************************************
663 * AVIStreamGetFrame (AVIFIL32.@)
665 LPVOID WINAPI
AVIStreamGetFrame(PGETFRAME pg
, LONG pos
)
667 TRACE("(%p,%d)\n", pg
, pos
);
672 return IGetFrame_GetFrame(pg
, pos
);
675 /***********************************************************************
676 * AVIStreamGetFrameClose (AVIFIL32.@)
678 HRESULT WINAPI
AVIStreamGetFrameClose(PGETFRAME pg
)
683 return IGetFrame_Release(pg
);
687 /***********************************************************************
688 * AVIMakeCompressedStream (AVIFIL32.@)
690 HRESULT WINAPI
AVIMakeCompressedStream(PAVISTREAM
*ppsCompressed
,
692 LPAVICOMPRESSOPTIONS aco
,
693 LPCLSID pclsidHandler
)
700 LONG size
= sizeof(szValue
);
702 TRACE("(%p,%p,%p,%s)\n", ppsCompressed
, psSource
, aco
,
703 debugstr_guid(pclsidHandler
));
705 if (ppsCompressed
== NULL
)
706 return AVIERR_BADPARAM
;
707 if (psSource
== NULL
)
708 return AVIERR_BADHANDLE
;
710 *ppsCompressed
= NULL
;
712 /* if no handler given get default ones based on streamtype */
713 if (pclsidHandler
== NULL
) {
714 hr
= IAVIStream_Info(psSource
, &asiw
, sizeof(asiw
));
718 wsprintfA(szRegKey
, "AVIFile\\Compressors\\%4.4s", (char*)&asiw
.fccType
);
719 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &size
) != ERROR_SUCCESS
)
720 return AVIERR_UNSUPPORTED
;
721 if (AVIFILE_CLSIDFromString(szValue
, &clsidHandler
) != S_OK
)
722 return AVIERR_UNSUPPORTED
;
724 clsidHandler
= *pclsidHandler
;
726 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppsCompressed
);
727 if (FAILED(hr
) || *ppsCompressed
== NULL
)
730 hr
= IAVIStream_Create(*ppsCompressed
, (LPARAM
)psSource
, (LPARAM
)aco
);
732 IAVIStream_Release(*ppsCompressed
);
733 *ppsCompressed
= NULL
;
739 /***********************************************************************
740 * AVIMakeFileFromStreams (AVIFIL32.@)
742 HRESULT WINAPI
AVIMakeFileFromStreams(PAVIFILE
*ppfile
, int nStreams
,
743 PAVISTREAM
*ppStreams
)
745 TRACE("(%p,%d,%p)\n", ppfile
, nStreams
, ppStreams
);
747 if (nStreams
< 0 || ppfile
== NULL
|| ppStreams
== NULL
)
748 return AVIERR_BADPARAM
;
750 *ppfile
= AVIFILE_CreateAVITempFile(nStreams
, ppStreams
);
752 return AVIERR_MEMORY
;
757 /***********************************************************************
758 * AVIStreamOpenFromFile (AVIFIL32.@)
759 * AVIStreamOpenFromFileA (AVIFIL32.@)
761 HRESULT WINAPI
AVIStreamOpenFromFileA(PAVISTREAM
*ppavi
, LPCSTR szFile
,
762 DWORD fccType
, LONG lParam
,
763 UINT mode
, LPCLSID pclsidHandler
)
765 PAVIFILE pfile
= NULL
;
768 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi
, debugstr_a(szFile
),
769 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
771 if (ppavi
== NULL
|| szFile
== NULL
)
772 return AVIERR_BADPARAM
;
776 hr
= AVIFileOpenA(&pfile
, szFile
, mode
, pclsidHandler
);
777 if (FAILED(hr
) || pfile
== NULL
)
780 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
781 IAVIFile_Release(pfile
);
786 /***********************************************************************
787 * AVIStreamOpenFromFileW (AVIFIL32.@)
789 HRESULT WINAPI
AVIStreamOpenFromFileW(PAVISTREAM
*ppavi
, LPCWSTR szFile
,
790 DWORD fccType
, LONG lParam
,
791 UINT mode
, LPCLSID pclsidHandler
)
793 PAVIFILE pfile
= NULL
;
796 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi
, debugstr_w(szFile
),
797 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
799 if (ppavi
== NULL
|| szFile
== NULL
)
800 return AVIERR_BADPARAM
;
804 hr
= AVIFileOpenW(&pfile
, szFile
, mode
, pclsidHandler
);
805 if (FAILED(hr
) || pfile
== NULL
)
808 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
809 IAVIFile_Release(pfile
);
814 /***********************************************************************
815 * AVIStreamBeginStreaming (AVIFIL32.@)
817 LONG WINAPI
AVIStreamBeginStreaming(PAVISTREAM pavi
, LONG lStart
, LONG lEnd
, LONG lRate
)
819 IAVIStreaming
* pstream
= NULL
;
822 TRACE("(%p,%d,%d,%d)\n", pavi
, lStart
, lEnd
, lRate
);
825 return AVIERR_BADHANDLE
;
827 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
828 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
829 hr
= IAVIStreaming_Begin(pstream
, lStart
, lEnd
, lRate
);
830 IAVIStreaming_Release(pstream
);
837 /***********************************************************************
838 * AVIStreamEndStreaming (AVIFIL32.@)
840 LONG WINAPI
AVIStreamEndStreaming(PAVISTREAM pavi
)
842 IAVIStreaming
* pstream
= NULL
;
845 TRACE("(%p)\n", pavi
);
847 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
848 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
849 IAVIStreaming_End(pstream
);
850 IAVIStreaming_Release(pstream
);
856 /***********************************************************************
857 * AVIStreamStart (AVIFIL32.@)
859 LONG WINAPI
AVIStreamStart(PAVISTREAM pstream
)
863 TRACE("(%p)\n", pstream
);
868 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
874 /***********************************************************************
875 * AVIStreamLength (AVIFIL32.@)
877 LONG WINAPI
AVIStreamLength(PAVISTREAM pstream
)
881 TRACE("(%p)\n", pstream
);
886 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
889 return asiw
.dwLength
;
892 /***********************************************************************
893 * AVIStreamSampleToTime (AVIFIL32.@)
895 LONG WINAPI
AVIStreamSampleToTime(PAVISTREAM pstream
, LONG lSample
)
900 TRACE("(%p,%d)\n", pstream
, lSample
);
905 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
907 if (asiw
.dwRate
== 0)
910 /* limit to stream bounds */
911 if (lSample
< asiw
.dwStart
)
912 lSample
= asiw
.dwStart
;
913 if (lSample
> asiw
.dwStart
+ asiw
.dwLength
)
914 lSample
= asiw
.dwStart
+ asiw
.dwLength
;
916 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
917 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000) / asiw
.dwRate
);
919 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000 + (asiw
.dwRate
- 1)) / asiw
.dwRate
);
921 TRACE(" -> %d\n",time
);
925 /***********************************************************************
926 * AVIStreamTimeToSample (AVIFIL32.@)
928 LONG WINAPI
AVIStreamTimeToSample(PAVISTREAM pstream
, LONG lTime
)
933 TRACE("(%p,%d)\n", pstream
, lTime
);
935 if (pstream
== NULL
|| lTime
< 0)
938 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
940 if (asiw
.dwScale
== 0)
943 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
944 sample
= (LONG
)((((float)asiw
.dwRate
* lTime
) / (asiw
.dwScale
* 1000)));
946 sample
= (LONG
)(((float)asiw
.dwRate
* lTime
+ (asiw
.dwScale
* 1000 - 1)) / (asiw
.dwScale
* 1000));
948 /* limit to stream bounds */
949 if (sample
< asiw
.dwStart
)
950 sample
= asiw
.dwStart
;
951 if (sample
> asiw
.dwStart
+ asiw
.dwLength
)
952 sample
= asiw
.dwStart
+ asiw
.dwLength
;
954 TRACE(" -> %d\n", sample
);
958 /***********************************************************************
959 * AVIBuildFilter (AVIFIL32.@)
960 * AVIBuildFilterA (AVIFIL32.@)
962 HRESULT WINAPI
AVIBuildFilterA(LPSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
967 TRACE("(%p,%d,%d)\n", szFilter
, cbFilter
, fSaving
);
969 /* check parameters */
970 if (szFilter
== NULL
)
971 return AVIERR_BADPARAM
;
973 return AVIERR_BADSIZE
;
978 wszFilter
= HeapAlloc(GetProcessHeap(), 0, cbFilter
* sizeof(WCHAR
));
979 if (wszFilter
== NULL
)
980 return AVIERR_MEMORY
;
982 hr
= AVIBuildFilterW(wszFilter
, cbFilter
, fSaving
);
984 WideCharToMultiByte(CP_ACP
, 0, wszFilter
, cbFilter
,
985 szFilter
, cbFilter
, NULL
, NULL
);
988 HeapFree(GetProcessHeap(), 0, wszFilter
);
993 /***********************************************************************
994 * AVIBuildFilterW (AVIFIL32.@)
996 HRESULT WINAPI
AVIBuildFilterW(LPWSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
998 static const WCHAR all_files
[] = { '*','.','*',0,0 };
999 static const WCHAR szClsid
[] = {'C','L','S','I','D',0};
1000 static const WCHAR szExtensionFmt
[] = {';','*','.','%','s',0};
1001 static const WCHAR szAVIFileExtensions
[] =
1002 {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1005 WCHAR szAllFiles
[40];
1006 WCHAR szFileExt
[10];
1013 TRACE("(%p,%d,%d)\n", szFilter
, cbFilter
, fSaving
);
1015 /* check parameters */
1016 if (szFilter
== NULL
)
1017 return AVIERR_BADPARAM
;
1019 return AVIERR_BADSIZE
;
1021 lp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MAX_FILTERS
* sizeof(AVIFilter
));
1023 return AVIERR_MEMORY
;
1026 * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
1027 * extensions and CLSIDs
1028 * 2. iterate over collected CLSIDs and copy its description and its
1029 * extensions to szFilter if it fits
1031 * First filter is named "All multimedia files" and its filter is a
1032 * collection of all possible extensions except "*.*".
1034 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szAVIFileExtensions
, &hKey
) != ERROR_SUCCESS
) {
1035 HeapFree(GetProcessHeap(), 0, lp
);
1036 return AVIERR_ERROR
;
1038 for (n
= 0;RegEnumKeyW(hKey
, n
, szFileExt
, sizeof(szFileExt
)/sizeof(szFileExt
[0])) == ERROR_SUCCESS
;n
++) {
1039 /* get CLSID to extension */
1040 size
= sizeof(szValue
);
1041 if (RegQueryValueW(hKey
, szFileExt
, szValue
, &size
) != ERROR_SUCCESS
)
1044 /* search if the CLSID is already known */
1045 for (i
= 1; i
<= count
; i
++) {
1046 if (lstrcmpW(lp
[i
].szClsid
, szValue
) == 0)
1047 break; /* a new one */
1050 if (i
== count
+ 1) {
1051 /* it's a new CLSID */
1053 /* FIXME: How do we get info's about read/write capabilities? */
1055 if (count
>= MAX_FILTERS
) {
1056 /* try to inform user of our full fixed size table */
1057 ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS
);
1061 lstrcpyW(lp
[i
].szClsid
, szValue
);
1066 /* append extension to the filter */
1067 wsprintfW(szValue
, szExtensionFmt
, szFileExt
);
1068 if (lp
[i
].szExtensions
[0] == 0)
1069 lstrcatW(lp
[i
].szExtensions
, szValue
+ 1);
1071 lstrcatW(lp
[i
].szExtensions
, szValue
);
1073 /* also append to the "all multimedia"-filter */
1074 if (lp
[0].szExtensions
[0] == 0)
1075 lstrcatW(lp
[0].szExtensions
, szValue
+ 1);
1077 lstrcatW(lp
[0].szExtensions
, szValue
);
1081 /* 2. get descriptions for the CLSIDs and fill out szFilter */
1082 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szClsid
, &hKey
) != ERROR_SUCCESS
) {
1083 HeapFree(GetProcessHeap(), 0, lp
);
1084 return AVIERR_ERROR
;
1086 for (n
= 0; n
<= count
; n
++) {
1087 /* first the description */
1089 size
= sizeof(szValue
);
1090 if (RegQueryValueW(hKey
, lp
[n
].szClsid
, szValue
, &size
) == ERROR_SUCCESS
) {
1091 size
= lstrlenW(szValue
);
1092 lstrcpynW(szFilter
, szValue
, cbFilter
);
1095 size
= LoadStringW(AVIFILE_hModule
,IDS_ALLMULTIMEDIA
,szFilter
,cbFilter
);
1097 /* check for enough space */
1099 if (cbFilter
< size
+ lstrlenW(lp
[n
].szExtensions
) + 2) {
1102 HeapFree(GetProcessHeap(), 0, lp
);
1104 return AVIERR_BUFFERTOOSMALL
;
1109 /* and then the filter */
1110 lstrcpynW(szFilter
, lp
[n
].szExtensions
, cbFilter
);
1111 size
= lstrlenW(lp
[n
].szExtensions
) + 1;
1117 HeapFree(GetProcessHeap(), 0, lp
);
1119 /* add "All files" "*.*" filter if enough space left */
1120 size
= LoadStringW(AVIFILE_hModule
, IDS_ALLFILES
,
1121 szAllFiles
, (sizeof(szAllFiles
) - sizeof(all_files
))/sizeof(WCHAR
)) + 1;
1122 memcpy( szAllFiles
+ size
, all_files
, sizeof(all_files
) );
1123 size
+= sizeof(all_files
) / sizeof(WCHAR
);
1125 if (cbFilter
> size
) {
1126 memcpy(szFilter
, szAllFiles
, size
* sizeof(szAllFiles
[0]));
1130 return AVIERR_BUFFERTOOSMALL
;
1134 static BOOL
AVISaveOptionsFmtChoose(HWND hWnd
)
1136 LPAVICOMPRESSOPTIONS pOptions
= SaveOpts
.ppOptions
[SaveOpts
.nCurrent
];
1137 AVISTREAMINFOW sInfo
;
1139 TRACE("(%p)\n", hWnd
);
1141 if (pOptions
== NULL
|| SaveOpts
.ppavis
[SaveOpts
.nCurrent
] == NULL
) {
1142 ERR(": bad state!\n");
1146 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1147 &sInfo
, sizeof(sInfo
)))) {
1148 ERR(": AVIStreamInfoW failed!\n");
1152 if (sInfo
.fccType
== streamtypeVIDEO
) {
1156 memset(&cv
, 0, sizeof(cv
));
1158 if ((pOptions
->dwFlags
& AVICOMPRESSF_VALID
) == 0) {
1159 memset(pOptions
, 0, sizeof(AVICOMPRESSOPTIONS
));
1160 pOptions
->fccType
= streamtypeVIDEO
;
1161 pOptions
->fccHandler
= comptypeDIB
;
1162 pOptions
->dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
1165 cv
.cbSize
= sizeof(cv
);
1166 cv
.dwFlags
= ICMF_COMPVARS_VALID
;
1167 /*cv.fccType = pOptions->fccType; */
1168 cv
.fccHandler
= pOptions
->fccHandler
;
1169 cv
.lQ
= pOptions
->dwQuality
;
1170 cv
.lpState
= pOptions
->lpParms
;
1171 cv
.cbState
= pOptions
->cbParms
;
1172 if (pOptions
->dwFlags
& AVICOMPRESSF_KEYFRAMES
)
1173 cv
.lKey
= pOptions
->dwKeyFrameEvery
;
1176 if (pOptions
->dwFlags
& AVICOMPRESSF_DATARATE
)
1177 cv
.lDataRate
= pOptions
->dwBytesPerSecond
/ 1024; /* need kBytes */
1181 ret
= ICCompressorChoose(hWnd
, SaveOpts
.uFlags
, NULL
,
1182 SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &cv
, NULL
);
1185 pOptions
->fccHandler
= cv
.fccHandler
;
1186 pOptions
->lpParms
= cv
.lpState
;
1187 pOptions
->cbParms
= cv
.cbState
;
1188 pOptions
->dwQuality
= cv
.lQ
;
1190 pOptions
->dwKeyFrameEvery
= cv
.lKey
;
1191 pOptions
->dwFlags
|= AVICOMPRESSF_KEYFRAMES
;
1193 pOptions
->dwFlags
&= ~AVICOMPRESSF_KEYFRAMES
;
1194 if (cv
.lDataRate
!= 0) {
1195 pOptions
->dwBytesPerSecond
= cv
.lDataRate
* 1024; /* need bytes */
1196 pOptions
->dwFlags
|= AVICOMPRESSF_DATARATE
;
1198 pOptions
->dwFlags
&= ~AVICOMPRESSF_DATARATE
;
1199 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1201 ICCompressorFree(&cv
);
1204 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1205 ACMFORMATCHOOSEW afmtc
;
1209 /* FIXME: check ACM version -- Which version is needed? */
1211 memset(&afmtc
, 0, sizeof(afmtc
));
1212 afmtc
.cbStruct
= sizeof(afmtc
);
1214 afmtc
.hwndOwner
= hWnd
;
1216 acmMetrics(NULL
, ACM_METRIC_MAX_SIZE_FORMAT
, &size
);
1217 if ((pOptions
->cbFormat
== 0 || pOptions
->lpFormat
== NULL
) && size
!= 0) {
1218 pOptions
->lpFormat
= HeapAlloc(GetProcessHeap(), 0, size
);
1219 if (!pOptions
->lpFormat
) return FALSE
;
1220 pOptions
->cbFormat
= size
;
1221 } else if (pOptions
->cbFormat
< (DWORD
)size
) {
1222 void *new_buffer
= HeapReAlloc(GetProcessHeap(), 0, pOptions
->lpFormat
, size
);
1223 if (!new_buffer
) return FALSE
;
1224 pOptions
->lpFormat
= new_buffer
;
1225 pOptions
->cbFormat
= size
;
1227 afmtc
.pwfx
= pOptions
->lpFormat
;
1228 afmtc
.cbwfx
= pOptions
->cbFormat
;
1231 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1232 sInfo
.dwStart
, &size
);
1233 if (size
< (LONG
)sizeof(PCMWAVEFORMAT
))
1234 size
= sizeof(PCMWAVEFORMAT
);
1235 afmtc
.pwfxEnum
= HeapAlloc(GetProcessHeap(), 0, size
);
1236 if (afmtc
.pwfxEnum
!= NULL
) {
1237 AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1238 sInfo
.dwStart
, afmtc
.pwfxEnum
, &size
);
1239 afmtc
.fdwEnum
= ACM_FORMATENUMF_CONVERT
;
1242 ret
= acmFormatChooseW(&afmtc
);
1244 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1246 HeapFree(GetProcessHeap(), 0, afmtc
.pwfxEnum
);
1249 ERR(": unknown streamtype 0x%08X\n", sInfo
.fccType
);
1254 static void AVISaveOptionsUpdate(HWND hWnd
)
1256 static const WCHAR szVideoFmt
[]={'%','l','d','x','%','l','d','x','%','d',0};
1257 static const WCHAR szAudioFmt
[]={'%','s',' ','%','s',0};
1259 WCHAR szFormat
[128];
1260 AVISTREAMINFOW sInfo
;
1264 TRACE("(%p)\n", hWnd
);
1266 SaveOpts
.nCurrent
= SendDlgItemMessageW(hWnd
,IDC_STREAM
,CB_GETCURSEL
,0,0);
1267 if (SaveOpts
.nCurrent
< 0)
1270 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &sInfo
, sizeof(sInfo
))))
1273 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,&size
);
1277 /* read format to build format description string */
1278 lpFormat
= HeapAlloc(GetProcessHeap(), 0, size
);
1279 if (lpFormat
!= NULL
) {
1280 if (SUCCEEDED(AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,lpFormat
, &size
))) {
1281 if (sInfo
.fccType
== streamtypeVIDEO
) {
1282 LPBITMAPINFOHEADER lpbi
= lpFormat
;
1285 wsprintfW(szFormat
, szVideoFmt
, lpbi
->biWidth
,
1286 lpbi
->biHeight
, lpbi
->biBitCount
);
1288 if (lpbi
->biCompression
!= BI_RGB
) {
1291 hic
= ICLocate(ICTYPE_VIDEO
, sInfo
.fccHandler
, lpFormat
,
1292 NULL
, ICMODE_DECOMPRESS
);
1294 if (ICGetInfo(hic
, &icinfo
, sizeof(icinfo
)) == S_OK
)
1295 lstrcatW(szFormat
, icinfo
.szDescription
);
1299 LoadStringW(AVIFILE_hModule
, IDS_UNCOMPRESSED
,
1300 icinfo
.szDescription
,
1301 sizeof(icinfo
.szDescription
)/sizeof(icinfo
.szDescription
[0]));
1302 lstrcatW(szFormat
, icinfo
.szDescription
);
1304 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1305 ACMFORMATTAGDETAILSW aftd
;
1306 ACMFORMATDETAILSW afd
;
1308 memset(&aftd
, 0, sizeof(aftd
));
1309 memset(&afd
, 0, sizeof(afd
));
1311 aftd
.cbStruct
= sizeof(aftd
);
1312 aftd
.dwFormatTag
= afd
.dwFormatTag
=
1313 ((PWAVEFORMATEX
)lpFormat
)->wFormatTag
;
1314 aftd
.cbFormatSize
= afd
.cbwfx
= size
;
1316 afd
.cbStruct
= sizeof(afd
);
1317 afd
.pwfx
= lpFormat
;
1319 if (acmFormatTagDetailsW(NULL
, &aftd
,
1320 ACM_FORMATTAGDETAILSF_FORMATTAG
) == S_OK
) {
1321 if (acmFormatDetailsW(NULL
,&afd
,ACM_FORMATDETAILSF_FORMAT
) == S_OK
)
1322 wsprintfW(szFormat
, szAudioFmt
, afd
.szFormat
, aftd
.szFormatTag
);
1326 HeapFree(GetProcessHeap(), 0, lpFormat
);
1329 /* set text for format description */
1330 SetDlgItemTextW(hWnd
, IDC_FORMATTEXT
, szFormat
);
1332 /* Disable option button for unsupported streamtypes */
1333 if (sInfo
.fccType
== streamtypeVIDEO
||
1334 sInfo
.fccType
== streamtypeAUDIO
)
1335 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), TRUE
);
1337 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), FALSE
);
1342 static INT_PTR CALLBACK
AVISaveOptionsDlgProc(HWND hWnd
, UINT uMsg
,
1343 WPARAM wParam
, LPARAM lParam
)
1346 BOOL bIsInterleaved
;
1349 /*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
1353 SaveOpts
.nCurrent
= 0;
1354 if (SaveOpts
.nStreams
== 1) {
1355 EndDialog(hWnd
, AVISaveOptionsFmtChoose(hWnd
));
1360 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1361 AVISTREAMINFOW sInfo
;
1363 AVIStreamInfoW(SaveOpts
.ppavis
[n
], &sInfo
, sizeof(sInfo
));
1364 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_ADDSTRING
,
1365 0L, (LPARAM
)sInfo
.szName
);
1368 /* select first stream */
1369 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_SETCURSEL
, 0, 0);
1370 SendMessageW(hWnd
, WM_COMMAND
, MAKELONG(IDC_STREAM
, CBN_SELCHANGE
), (LPARAM
)hWnd
);
1372 /* initialize interleave */
1373 if (SaveOpts
.ppOptions
[0] != NULL
&&
1374 (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_VALID
)) {
1375 bIsInterleaved
= (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_INTERLEAVE
);
1376 dwInterleave
= SaveOpts
.ppOptions
[0]->dwInterleaveEvery
;
1378 bIsInterleaved
= TRUE
;
1381 CheckDlgButton(hWnd
, IDC_INTERLEAVE
, bIsInterleaved
);
1382 SetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, dwInterleave
, FALSE
);
1383 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
), bIsInterleaved
);
1386 switch (LOWORD(wParam
)) {
1388 /* get data from controls and save them */
1389 dwInterleave
= GetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, NULL
, 0);
1390 bIsInterleaved
= IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
);
1391 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1392 if (SaveOpts
.ppOptions
[n
] != NULL
) {
1393 if (bIsInterleaved
) {
1394 SaveOpts
.ppOptions
[n
]->dwFlags
|= AVICOMPRESSF_INTERLEAVE
;
1395 SaveOpts
.ppOptions
[n
]->dwInterleaveEvery
= dwInterleave
;
1397 SaveOpts
.ppOptions
[n
]->dwFlags
&= ~AVICOMPRESSF_INTERLEAVE
;
1402 EndDialog(hWnd
, LOWORD(wParam
) == IDOK
);
1404 case IDC_INTERLEAVE
:
1405 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
),
1406 IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
));
1409 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
1410 /* update control elements */
1411 AVISaveOptionsUpdate(hWnd
);
1415 AVISaveOptionsFmtChoose(hWnd
);
1424 /***********************************************************************
1425 * AVISaveOptions (AVIFIL32.@)
1427 BOOL WINAPI
AVISaveOptions(HWND hWnd
, UINT uFlags
, INT nStreams
,
1428 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*ppOptions
)
1430 LPAVICOMPRESSOPTIONS pSavedOptions
= NULL
;
1433 TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd
, uFlags
, nStreams
,
1436 /* check parameters */
1437 if (nStreams
<= 0 || ppavi
== NULL
|| ppOptions
== NULL
)
1438 return AVIERR_BADPARAM
;
1440 /* save options in case the user presses cancel */
1442 pSavedOptions
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(AVICOMPRESSOPTIONS
));
1443 if (pSavedOptions
== NULL
)
1446 for (n
= 0; n
< nStreams
; n
++) {
1447 if (ppOptions
[n
] != NULL
)
1448 memcpy(pSavedOptions
+ n
, ppOptions
[n
], sizeof(AVICOMPRESSOPTIONS
));
1452 SaveOpts
.uFlags
= uFlags
;
1453 SaveOpts
.nStreams
= nStreams
;
1454 SaveOpts
.ppavis
= ppavi
;
1455 SaveOpts
.ppOptions
= ppOptions
;
1457 ret
= DialogBoxW(AVIFILE_hModule
, MAKEINTRESOURCEW(IDD_SAVEOPTIONS
),
1458 hWnd
, AVISaveOptionsDlgProc
);
1463 /* restore options when user pressed cancel */
1464 if (pSavedOptions
!= NULL
) {
1466 for (n
= 0; n
< nStreams
; n
++) {
1467 if (ppOptions
[n
] != NULL
)
1468 memcpy(ppOptions
[n
], pSavedOptions
+ n
, sizeof(AVICOMPRESSOPTIONS
));
1471 HeapFree(GetProcessHeap(), 0, pSavedOptions
);
1477 /***********************************************************************
1478 * AVISaveOptionsFree (AVIFIL32.@)
1480 HRESULT WINAPI
AVISaveOptionsFree(INT nStreams
,LPAVICOMPRESSOPTIONS
*ppOptions
)
1482 TRACE("(%d,%p)\n", nStreams
, ppOptions
);
1484 if (nStreams
< 0 || ppOptions
== NULL
)
1485 return AVIERR_BADPARAM
;
1487 for (nStreams
--; nStreams
>= 0; nStreams
--) {
1488 if (ppOptions
[nStreams
] != NULL
) {
1489 ppOptions
[nStreams
]->dwFlags
&= ~AVICOMPRESSF_VALID
;
1491 if (ppOptions
[nStreams
]->lpParms
!= NULL
) {
1492 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpParms
);
1493 ppOptions
[nStreams
]->lpParms
= NULL
;
1494 ppOptions
[nStreams
]->cbParms
= 0;
1496 if (ppOptions
[nStreams
]->lpFormat
!= NULL
) {
1497 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpFormat
);
1498 ppOptions
[nStreams
]->lpFormat
= NULL
;
1499 ppOptions
[nStreams
]->cbFormat
= 0;
1507 /***********************************************************************
1508 * AVISaveVA (AVIFIL32.@)
1510 HRESULT WINAPI
AVISaveVA(LPCSTR szFile
, CLSID
*pclsidHandler
,
1511 AVISAVECALLBACK lpfnCallback
, int nStream
,
1512 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1514 LPWSTR wszFile
= NULL
;
1518 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile
), pclsidHandler
,
1519 lpfnCallback
, nStream
, ppavi
, plpOptions
);
1521 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1522 return AVIERR_BADPARAM
;
1524 /* convert ASCII string to Unicode and call Unicode function */
1525 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
1527 return AVIERR_BADPARAM
;
1529 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1530 if (wszFile
== NULL
)
1531 return AVIERR_MEMORY
;
1533 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
1535 hr
= AVISaveVW(wszFile
, pclsidHandler
, lpfnCallback
,
1536 nStream
, ppavi
, plpOptions
);
1538 HeapFree(GetProcessHeap(), 0, wszFile
);
1543 /***********************************************************************
1544 * AVIFILE_AVISaveDefaultCallback (internal)
1546 static BOOL WINAPI
AVIFILE_AVISaveDefaultCallback(INT progress
)
1548 TRACE("(%d)\n", progress
);
1553 /***********************************************************************
1554 * AVISaveVW (AVIFIL32.@)
1556 HRESULT WINAPI
AVISaveVW(LPCWSTR szFile
, CLSID
*pclsidHandler
,
1557 AVISAVECALLBACK lpfnCallback
, int nStreams
,
1558 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1560 LONG lStart
[MAX_AVISTREAMS
];
1561 PAVISTREAM pOutStreams
[MAX_AVISTREAMS
];
1562 PAVISTREAM pInStreams
[MAX_AVISTREAMS
];
1564 AVISTREAMINFOW sInfo
;
1566 PAVIFILE pfile
= NULL
; /* the output AVI file */
1567 LONG lFirstVideo
= -1;
1570 /* for interleaving ... */
1571 DWORD dwInterleave
= 0; /* interleave rate */
1572 DWORD dwFileInitialFrames
;
1576 /* for reading/writing the data ... */
1577 LPVOID lpBuffer
= NULL
;
1578 LONG cbBuffer
; /* real size of lpBuffer */
1579 LONG lBufferSize
; /* needed bytes for format(s), etc. */
1584 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile
), pclsidHandler
,
1585 lpfnCallback
, nStreams
, ppavi
, plpOptions
);
1587 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1588 return AVIERR_BADPARAM
;
1589 if (nStreams
>= MAX_AVISTREAMS
) {
1590 WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams
, MAX_AVISTREAMS
);
1591 return AVIERR_INTERNAL
;
1594 if (lpfnCallback
== NULL
)
1595 lpfnCallback
= AVIFILE_AVISaveDefaultCallback
;
1597 /* clear local variable(s) */
1598 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1599 pInStreams
[curStream
] = NULL
;
1600 pOutStreams
[curStream
] = NULL
;
1603 /* open output AVI file (create it if it doesn't exist) */
1604 hres
= AVIFileOpenW(&pfile
, szFile
, OF_CREATE
|OF_SHARE_EXCLUSIVE
|OF_WRITE
,
1608 AVIFileInfoW(pfile
, &fInfo
, sizeof(fInfo
)); /* for dwCaps */
1610 /* initialize our data structures part 1 */
1611 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1612 PAVISTREAM pCurStream
= ppavi
[curStream
];
1614 hres
= AVIStreamInfoW(pCurStream
, &sInfo
, sizeof(sInfo
));
1618 /* search first video stream and check for interleaving */
1619 if (sInfo
.fccType
== streamtypeVIDEO
) {
1620 /* remember first video stream -- needed for interleaving */
1621 if (lFirstVideo
< 0)
1622 lFirstVideo
= curStream
;
1623 } else if (!dwInterleave
) {
1624 /* check if any non-video stream wants to be interleaved */
1625 WARN("options.flags=0x%X options.dwInterleave=%u\n",plpOptions
[curStream
]->dwFlags
,plpOptions
[curStream
]->dwInterleaveEvery
);
1626 if (plpOptions
[curStream
] != NULL
&&
1627 plpOptions
[curStream
]->dwFlags
& AVICOMPRESSF_INTERLEAVE
)
1628 dwInterleave
= plpOptions
[curStream
]->dwInterleaveEvery
;
1631 /* create de-/compressed stream interface if needed */
1632 pInStreams
[curStream
] = NULL
;
1633 if (plpOptions
[curStream
] != NULL
) {
1634 if (plpOptions
[curStream
]->fccHandler
||
1635 plpOptions
[curStream
]->lpFormat
!= NULL
) {
1636 DWORD dwKeySave
= plpOptions
[curStream
]->dwKeyFrameEvery
;
1638 if (fInfo
.dwCaps
& AVIFILECAPS_ALLKEYFRAMES
)
1639 plpOptions
[curStream
]->dwKeyFrameEvery
= 1;
1641 hres
= AVIMakeCompressedStream(&pInStreams
[curStream
], pCurStream
,
1642 plpOptions
[curStream
], NULL
);
1643 plpOptions
[curStream
]->dwKeyFrameEvery
= dwKeySave
;
1644 if (FAILED(hres
) || pInStreams
[curStream
] == NULL
) {
1645 pInStreams
[curStream
] = NULL
;
1649 /* test stream interface and update stream-info */
1650 hres
= AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1656 /* now handle streams which will only be copied */
1657 if (pInStreams
[curStream
] == NULL
) {
1658 pCurStream
= pInStreams
[curStream
] = ppavi
[curStream
];
1659 AVIStreamAddRef(pCurStream
);
1661 pCurStream
= pInStreams
[curStream
];
1663 lStart
[curStream
] = sInfo
.dwStart
;
1664 } /* for all streams */
1666 /* check that first video stream is the first stream */
1667 if (lFirstVideo
> 0) {
1668 PAVISTREAM pTmp
= pInStreams
[lFirstVideo
];
1669 LONG lTmp
= lStart
[lFirstVideo
];
1671 pInStreams
[lFirstVideo
] = pInStreams
[0];
1672 pInStreams
[0] = pTmp
;
1673 lStart
[lFirstVideo
] = lStart
[0];
1678 /* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
1679 cbBuffer
= 0x00010000;
1680 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, cbBuffer
);
1681 if (lpBuffer
== NULL
) {
1682 hres
= AVIERR_MEMORY
;
1686 AVIStreamInfoW(pInStreams
[0], &sInfo
, sizeof(sInfo
));
1687 lFileLength
= sInfo
.dwLength
;
1688 dwFileInitialFrames
= 0;
1689 if (lFirstVideo
>= 0) {
1690 /* check for correct version of the format
1691 * -- need at least BITMAPINFOHEADER or newer
1694 lBufferSize
= cbBuffer
;
1695 hres
= AVIStreamReadFormat(pInStreams
[lFirstVideo
], AVIStreamStart(pInStreams
[lFirstVideo
]), lpBuffer
, &lBufferSize
);
1696 if (lBufferSize
< (LONG
)sizeof(BITMAPINFOHEADER
))
1697 hres
= AVIERR_INTERNAL
;
1700 } else /* use one second blocks for interleaving if no video present */
1701 lSampleInc
= AVIStreamTimeToSample(pInStreams
[0], 1000000);
1703 /* create output streams */
1704 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1705 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1707 sInfo
.dwInitialFrames
= 0;
1708 if (dwInterleave
!= 0 && curStream
> 0 && sInfo
.fccType
!= streamtypeVIDEO
) {
1709 /* 750 ms initial frames for non-video streams */
1710 sInfo
.dwInitialFrames
= AVIStreamTimeToSample(pInStreams
[0], 750);
1713 hres
= AVIFileCreateStreamW(pfile
, &pOutStreams
[curStream
], &sInfo
);
1714 if (pOutStreams
[curStream
] != NULL
&& SUCCEEDED(hres
)) {
1715 /* copy initial format for this stream */
1716 lBufferSize
= cbBuffer
;
1717 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1718 lpBuffer
, &lBufferSize
);
1721 hres
= AVIStreamSetFormat(pOutStreams
[curStream
], 0, lpBuffer
, lBufferSize
);
1725 /* try to copy stream handler data */
1726 lBufferSize
= cbBuffer
;
1727 hres
= AVIStreamReadData(pInStreams
[curStream
], ckidSTREAMHANDLERDATA
,
1728 lpBuffer
, &lBufferSize
);
1729 if (SUCCEEDED(hres
) && lBufferSize
> 0) {
1730 hres
= AVIStreamWriteData(pOutStreams
[curStream
],ckidSTREAMHANDLERDATA
,
1731 lpBuffer
, lBufferSize
);
1736 if (dwFileInitialFrames
< sInfo
.dwInitialFrames
)
1737 dwFileInitialFrames
= sInfo
.dwInitialFrames
;
1739 AVIStreamSampleToSample(pOutStreams
[0], pInStreams
[curStream
],
1741 if (lFileLength
< lReadBytes
)
1742 lFileLength
= lReadBytes
;
1744 /* creation of de-/compression stream interface failed */
1745 WARN("creation of (de-)compression stream failed for stream %d\n",curStream
);
1746 AVIStreamRelease(pInStreams
[curStream
]);
1747 if (curStream
+ 1 >= nStreams
) {
1748 /* move the others one up */
1749 PAVISTREAM
*ppas
= &pInStreams
[curStream
];
1750 int n
= nStreams
- (curStream
+ 1);
1753 *ppas
= pInStreams
[curStream
+ 1];
1759 } /* create output streams for all input streams */
1761 /* have we still something to write, or lost everything? */
1766 LONG lCurFrame
= -dwFileInitialFrames
;
1768 /* interleaved file */
1769 if (dwInterleave
== 1)
1770 AVIFileEndRecord(pfile
);
1772 for (; lCurFrame
< lFileLength
; lCurFrame
+= lSampleInc
) {
1773 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1776 hres
= AVIStreamInfoW(pOutStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1780 /* initial frames phase at the end for this stream? */
1781 if (-(LONG
)sInfo
.dwInitialFrames
> lCurFrame
)
1784 if ((lFileLength
- lSampleInc
) <= lCurFrame
) {
1785 lLastSample
= AVIStreamLength(pInStreams
[curStream
]);
1786 lFirstVideo
= lLastSample
+ AVIStreamStart(pInStreams
[curStream
]);
1788 if (curStream
!= 0) {
1790 AVIStreamSampleToSample(pInStreams
[curStream
], pInStreams
[0],
1791 (sInfo
.fccType
== streamtypeVIDEO
?
1792 (LONG
)dwInterleave
: lSampleInc
) +
1793 sInfo
.dwInitialFrames
+ lCurFrame
);
1795 lFirstVideo
= lSampleInc
+ (sInfo
.dwInitialFrames
+ lCurFrame
);
1797 lLastSample
= AVIStreamEnd(pInStreams
[curStream
]);
1798 if (lLastSample
<= lFirstVideo
)
1799 lFirstVideo
= lLastSample
;
1802 /* copy needed samples now */
1803 WARN("copy from stream %d samples %d to %d...\n",curStream
,
1804 lStart
[curStream
],lFirstVideo
);
1805 while (lFirstVideo
> lStart
[curStream
]) {
1808 /* copy format in case it can change */
1809 lBufferSize
= cbBuffer
;
1810 hres
= AVIStreamReadFormat(pInStreams
[curStream
], lStart
[curStream
],
1811 lpBuffer
, &lBufferSize
);
1814 AVIStreamSetFormat(pOutStreams
[curStream
], lStart
[curStream
],
1815 lpBuffer
, lBufferSize
);
1817 /* try to read data until we got it, or error */
1819 hres
= AVIStreamRead(pInStreams
[curStream
], lStart
[curStream
],
1820 lFirstVideo
- lStart
[curStream
], lpBuffer
,
1821 cbBuffer
, &lReadBytes
, &lReadSamples
);
1822 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1823 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1824 if (lpBuffer
== NULL
)
1825 hres
= AVIERR_MEMORY
;
1829 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1830 flags
= AVIIF_KEYFRAME
;
1831 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1832 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1836 lStart
[curStream
] += lReadSamples
;
1838 lStart
[curStream
] = lFirstVideo
;
1839 } /* stream by stream */
1841 /* need to close this block? */
1842 if (dwInterleave
== 1) {
1843 hres
= AVIFileEndRecord(pfile
);
1849 if (lpfnCallback(MulDiv(dwFileInitialFrames
+ lCurFrame
, 100,
1850 dwFileInitialFrames
+ lFileLength
))) {
1851 hres
= AVIERR_USERABORT
;
1854 } /* copy frame by frame */
1856 /* non-interleaved file */
1858 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1860 if (lpfnCallback(MulDiv(curStream
, 100, nStreams
))) {
1861 hres
= AVIERR_USERABORT
;
1865 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1867 if (sInfo
.dwSampleSize
!= 0) {
1868 /* sample-based data like audio */
1869 while (sInfo
.dwStart
< sInfo
.dwLength
) {
1870 LONG lSamples
= cbBuffer
/ sInfo
.dwSampleSize
;
1872 /* copy format in case it can change */
1873 lBufferSize
= cbBuffer
;
1874 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1875 lpBuffer
, &lBufferSize
);
1878 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1879 lpBuffer
, lBufferSize
);
1881 /* limit to stream boundaries */
1882 if (lSamples
!= (LONG
)(sInfo
.dwLength
- sInfo
.dwStart
))
1883 lSamples
= sInfo
.dwLength
- sInfo
.dwStart
;
1885 /* now try to read until we get it, or an error occurs */
1887 lReadBytes
= cbBuffer
;
1889 hres
= AVIStreamRead(pInStreams
[curStream
],sInfo
.dwStart
,lSamples
,
1890 lpBuffer
,cbBuffer
,&lReadBytes
,&lReadSamples
);
1891 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1892 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1893 if (lpBuffer
== NULL
)
1894 hres
= AVIERR_MEMORY
;
1897 if (lReadSamples
!= 0) {
1898 sInfo
.dwStart
+= lReadSamples
;
1899 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1900 lpBuffer
, lReadBytes
, 0, NULL
, NULL
);
1905 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1906 MulDiv(curStream
, 100, nStreams
))) {
1907 hres
= AVIERR_USERABORT
;
1911 if ((sInfo
.dwLength
- sInfo
.dwStart
) != 1) {
1912 hres
= AVIERR_FILEREAD
;
1918 /* block-based data like video */
1919 for (; sInfo
.dwStart
< sInfo
.dwLength
; sInfo
.dwStart
++) {
1922 /* copy format in case it can change */
1923 lBufferSize
= cbBuffer
;
1924 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1925 lpBuffer
, &lBufferSize
);
1928 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1929 lpBuffer
, lBufferSize
);
1931 /* try to read block and resize buffer if necessary */
1934 lReadBytes
= cbBuffer
;
1935 hres
= AVIStreamRead(pInStreams
[curStream
], sInfo
.dwStart
, 1,
1936 lpBuffer
, cbBuffer
,&lReadBytes
,&lReadSamples
);
1937 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1938 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1939 if (lpBuffer
== NULL
)
1940 hres
= AVIERR_MEMORY
;
1943 if (lReadSamples
!= 1) {
1944 hres
= AVIERR_FILEREAD
;
1948 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1949 flags
= AVIIF_KEYFRAME
;
1950 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1951 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1956 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1957 MulDiv(curStream
, 100, nStreams
))) {
1958 hres
= AVIERR_USERABORT
;
1961 } /* copy all blocks */
1963 } /* copy data stream by stream */
1967 HeapFree(GetProcessHeap(), 0, lpBuffer
);
1968 if (pfile
!= NULL
) {
1969 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1970 if (pOutStreams
[curStream
] != NULL
)
1971 AVIStreamRelease(pOutStreams
[curStream
]);
1972 if (pInStreams
[curStream
] != NULL
)
1973 AVIStreamRelease(pInStreams
[curStream
]);
1976 AVIFileRelease(pfile
);
1982 /***********************************************************************
1983 * CreateEditableStream (AVIFIL32.@)
1985 HRESULT WINAPI
CreateEditableStream(PAVISTREAM
*ppEditable
, PAVISTREAM pSource
)
1987 IAVIEditStream
*pEdit
= NULL
;
1990 TRACE("(%p,%p)\n", ppEditable
, pSource
);
1992 if (ppEditable
== NULL
)
1993 return AVIERR_BADPARAM
;
1997 if (pSource
!= NULL
) {
1998 hr
= IAVIStream_QueryInterface(pSource
, &IID_IAVIEditStream
,
2000 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2001 hr
= IAVIEditStream_Clone(pEdit
, ppEditable
);
2002 IAVIEditStream_Release(pEdit
);
2008 /* need own implementation of IAVIEditStream */
2009 pEdit
= AVIFILE_CreateEditStream(pSource
);
2011 return AVIERR_MEMORY
;
2013 hr
= IAVIEditStream_QueryInterface(pEdit
, &IID_IAVIStream
,
2014 (LPVOID
*)ppEditable
);
2015 IAVIEditStream_Release(pEdit
);
2020 /***********************************************************************
2021 * EditStreamClone (AVIFIL32.@)
2023 HRESULT WINAPI
EditStreamClone(PAVISTREAM pStream
, PAVISTREAM
*ppResult
)
2025 PAVIEDITSTREAM pEdit
= NULL
;
2028 TRACE("(%p,%p)\n", pStream
, ppResult
);
2030 if (pStream
== NULL
)
2031 return AVIERR_BADHANDLE
;
2032 if (ppResult
== NULL
)
2033 return AVIERR_BADPARAM
;
2037 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2038 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2039 hr
= IAVIEditStream_Clone(pEdit
, ppResult
);
2041 IAVIEditStream_Release(pEdit
);
2043 hr
= AVIERR_UNSUPPORTED
;
2048 /***********************************************************************
2049 * EditStreamCopy (AVIFIL32.@)
2051 HRESULT WINAPI
EditStreamCopy(PAVISTREAM pStream
, LONG
*plStart
,
2052 LONG
*plLength
, PAVISTREAM
*ppResult
)
2054 PAVIEDITSTREAM pEdit
= NULL
;
2057 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2059 if (pStream
== NULL
)
2060 return AVIERR_BADHANDLE
;
2061 if (plStart
== NULL
|| plLength
== NULL
|| ppResult
== NULL
)
2062 return AVIERR_BADPARAM
;
2066 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2067 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2068 hr
= IAVIEditStream_Copy(pEdit
, plStart
, plLength
, ppResult
);
2070 IAVIEditStream_Release(pEdit
);
2072 hr
= AVIERR_UNSUPPORTED
;
2077 /***********************************************************************
2078 * EditStreamCut (AVIFIL32.@)
2080 HRESULT WINAPI
EditStreamCut(PAVISTREAM pStream
, LONG
*plStart
,
2081 LONG
*plLength
, PAVISTREAM
*ppResult
)
2083 PAVIEDITSTREAM pEdit
= NULL
;
2086 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2088 if (ppResult
!= NULL
)
2090 if (pStream
== NULL
)
2091 return AVIERR_BADHANDLE
;
2092 if (plStart
== NULL
|| plLength
== NULL
)
2093 return AVIERR_BADPARAM
;
2095 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2096 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2097 hr
= IAVIEditStream_Cut(pEdit
, plStart
, plLength
, ppResult
);
2099 IAVIEditStream_Release(pEdit
);
2101 hr
= AVIERR_UNSUPPORTED
;
2106 /***********************************************************************
2107 * EditStreamPaste (AVIFIL32.@)
2109 HRESULT WINAPI
EditStreamPaste(PAVISTREAM pDest
, LONG
*plStart
, LONG
*plLength
,
2110 PAVISTREAM pSource
, LONG lStart
, LONG lEnd
)
2112 PAVIEDITSTREAM pEdit
= NULL
;
2115 TRACE("(%p,%p,%p,%p,%d,%d)\n", pDest
, plStart
, plLength
,
2116 pSource
, lStart
, lEnd
);
2118 if (pDest
== NULL
|| pSource
== NULL
)
2119 return AVIERR_BADHANDLE
;
2120 if (plStart
== NULL
|| plLength
== NULL
|| lStart
< 0)
2121 return AVIERR_BADPARAM
;
2123 hr
= IAVIStream_QueryInterface(pDest
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2124 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2125 hr
= IAVIEditStream_Paste(pEdit
, plStart
, plLength
, pSource
, lStart
, lEnd
);
2127 IAVIEditStream_Release(pEdit
);
2129 hr
= AVIERR_UNSUPPORTED
;
2134 /***********************************************************************
2135 * EditStreamSetInfoA (AVIFIL32.@)
2137 HRESULT WINAPI
EditStreamSetInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
2140 AVISTREAMINFOW asiw
;
2142 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
2144 if (size
>= 0 && size
< sizeof(AVISTREAMINFOA
))
2145 return AVIERR_BADSIZE
;
2147 memcpy(&asiw
, asi
, sizeof(asiw
) - sizeof(asiw
.szName
));
2148 MultiByteToWideChar(CP_ACP
, 0, asi
->szName
, -1,
2149 asiw
.szName
, sizeof(asiw
.szName
)/sizeof(WCHAR
));
2151 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2154 /***********************************************************************
2155 * EditStreamSetInfoW (AVIFIL32.@)
2157 HRESULT WINAPI
EditStreamSetInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
2160 PAVIEDITSTREAM pEdit
= NULL
;
2163 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
2165 if (size
>= 0 && size
< sizeof(AVISTREAMINFOA
))
2166 return AVIERR_BADSIZE
;
2168 hr
= IAVIStream_QueryInterface(pstream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2169 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2170 hr
= IAVIEditStream_SetInfo(pEdit
, asi
, size
);
2172 IAVIEditStream_Release(pEdit
);
2174 hr
= AVIERR_UNSUPPORTED
;
2179 /***********************************************************************
2180 * EditStreamSetNameA (AVIFIL32.@)
2182 HRESULT WINAPI
EditStreamSetNameA(PAVISTREAM pstream
, LPCSTR szName
)
2184 AVISTREAMINFOA asia
;
2187 TRACE("(%p,%s)\n", pstream
, debugstr_a(szName
));
2189 if (pstream
== NULL
)
2190 return AVIERR_BADHANDLE
;
2192 return AVIERR_BADPARAM
;
2194 hres
= AVIStreamInfoA(pstream
, &asia
, sizeof(asia
));
2198 memset(asia
.szName
, 0, sizeof(asia
.szName
));
2199 lstrcpynA(asia
.szName
, szName
, sizeof(asia
.szName
)/sizeof(asia
.szName
[0]));
2201 return EditStreamSetInfoA(pstream
, &asia
, sizeof(asia
));
2204 /***********************************************************************
2205 * EditStreamSetNameW (AVIFIL32.@)
2207 HRESULT WINAPI
EditStreamSetNameW(PAVISTREAM pstream
, LPCWSTR szName
)
2209 AVISTREAMINFOW asiw
;
2212 TRACE("(%p,%s)\n", pstream
, debugstr_w(szName
));
2214 if (pstream
== NULL
)
2215 return AVIERR_BADHANDLE
;
2217 return AVIERR_BADPARAM
;
2219 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
2223 memset(asiw
.szName
, 0, sizeof(asiw
.szName
));
2224 lstrcpynW(asiw
.szName
, szName
, sizeof(asiw
.szName
)/sizeof(asiw
.szName
[0]));
2226 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2229 /***********************************************************************
2230 * AVIClearClipboard (AVIFIL32.@)
2232 HRESULT WINAPI
AVIClearClipboard(void)
2236 return AVIERR_UNSUPPORTED
; /* OleSetClipboard(NULL); */
2239 /***********************************************************************
2240 * AVIGetFromClipboard (AVIFIL32.@)
2242 HRESULT WINAPI
AVIGetFromClipboard(PAVIFILE
*ppfile
)
2244 FIXME("(%p), stub!\n", ppfile
);
2248 return AVIERR_UNSUPPORTED
;
2251 /***********************************************************************
2252 * AVIMakeStreamFromClipboard (AVIFIL32.@)
2254 HRESULT WINAPI
AVIMakeStreamFromClipboard(UINT cfFormat
, HANDLE hGlobal
,
2255 PAVISTREAM
* ppstream
)
2257 FIXME("(0x%08x,%p,%p), stub!\n", cfFormat
, hGlobal
, ppstream
);
2259 if (ppstream
== NULL
)
2260 return AVIERR_BADHANDLE
;
2262 return AVIERR_UNSUPPORTED
;
2265 /***********************************************************************
2266 * AVIPutFileOnClipboard (AVIFIL32.@)
2268 HRESULT WINAPI
AVIPutFileOnClipboard(PAVIFILE pfile
)
2270 FIXME("(%p), stub!\n", pfile
);
2273 return AVIERR_BADHANDLE
;
2275 return AVIERR_UNSUPPORTED
;
2278 HRESULT WINAPIV
AVISaveA(LPCSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2279 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2284 PAVISTREAM
*streams
;
2285 LPAVICOMPRESSOPTIONS
*options
;
2287 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile
), pclsidHandler
, lpfnCallback
,
2288 nStreams
, pavi
, lpOptions
);
2290 if (nStreams
<= 0) return AVIERR_BADPARAM
;
2292 streams
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(void *));
2293 options
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(void *));
2294 if (!streams
|| !options
)
2296 ret
= AVIERR_MEMORY
;
2301 options
[0] = lpOptions
;
2303 __ms_va_start(vl
, lpOptions
);
2304 for (i
= 1; i
< nStreams
; i
++)
2306 streams
[i
] = va_arg(vl
, void *);
2307 options
[i
] = va_arg(vl
, void *);
2311 for (i
= 0; i
< nStreams
; i
++)
2312 TRACE("Pair[%d] - Stream = %p, Options = %p\n", i
, streams
[i
], options
[i
]);
2314 ret
= AVISaveVA(szFile
, pclsidHandler
, lpfnCallback
, nStreams
, streams
, options
);
2316 HeapFree(GetProcessHeap(), 0, streams
);
2317 HeapFree(GetProcessHeap(), 0, options
);
2321 HRESULT WINAPIV
AVISaveW(LPCWSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2322 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2327 PAVISTREAM
*streams
;
2328 LPAVICOMPRESSOPTIONS
*options
;
2330 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile
), pclsidHandler
, lpfnCallback
,
2331 nStreams
, pavi
, lpOptions
);
2333 if (nStreams
<= 0) return AVIERR_BADPARAM
;
2335 streams
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(void *));
2336 options
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(void *));
2337 if (!streams
|| !options
)
2339 ret
= AVIERR_MEMORY
;
2344 options
[0] = lpOptions
;
2346 __ms_va_start(vl
, lpOptions
);
2347 for (i
= 1; i
< nStreams
; i
++)
2349 streams
[i
] = va_arg(vl
, void *);
2350 options
[i
] = va_arg(vl
, void *);
2354 for (i
= 0; i
< nStreams
; i
++)
2355 TRACE("Pair[%d] - Stream = %p, Options = %p\n", i
, streams
[i
], options
[i
]);
2357 ret
= AVISaveVW(szFile
, pclsidHandler
, lpfnCallback
, nStreams
, streams
, options
);
2359 HeapFree(GetProcessHeap(), 0, streams
);
2360 HeapFree(GetProcessHeap(), 0, options
);