1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
5 * Copyright 1998, 1999 Eric Kohl
9 * I will only improve this control once in a while.
10 * Eric <ekohl@abo.rhein-zeitung.de>
13 * - check for the 'rec ' list in some AVI files
14 * - concurrent access to infoPtr
22 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(animate
);
28 /* reference to input stream (file or resource) */
30 HMMIO hMMio
; /* handle to mmio stream */
32 /* information on the loaded AVI file */
35 LPBITMAPINFOHEADER inbih
;
37 /* data for the decompressor */
39 LPBITMAPINFOHEADER outbih
;
42 /* data for the background mechanism */
46 /* data for playing the file */
52 COLORREF transparentColor
;
57 #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
58 #define ANIMATE_COLOR_NONE 0xffffffff
60 static void ANIMATE_Notify(ANIMATE_INFO
* infoPtr
, UINT notif
)
62 SendMessageA(GetParent(infoPtr
->hWnd
), WM_COMMAND
,
63 MAKEWPARAM(GetDlgCtrlID(infoPtr
->hWnd
), notif
),
64 (LPARAM
)infoPtr
->hWnd
);
67 static BOOL
ANIMATE_LoadResA(ANIMATE_INFO
*infoPtr
, HINSTANCE hInst
, LPSTR lpName
)
73 hrsrc
= FindResourceA(hInst
, lpName
, "AVI");
77 infoPtr
->hRes
= LoadResource(hInst
, hrsrc
);
81 lpAvi
= LockResource(infoPtr
->hRes
);
85 memset(&mminfo
, 0, sizeof(mminfo
));
86 mminfo
.fccIOProc
= FOURCC_MEM
;
87 mminfo
.pchBuffer
= (LPSTR
)lpAvi
;
88 mminfo
.cchBuffer
= SizeofResource(hInst
, hrsrc
);
89 infoPtr
->hMMio
= mmioOpenA(NULL
, &mminfo
, MMIO_READ
);
90 if (!infoPtr
->hMMio
) {
91 GlobalFree((HGLOBAL
)lpAvi
);
99 static BOOL
ANIMATE_LoadFileA(ANIMATE_INFO
*infoPtr
, LPSTR lpName
)
101 infoPtr
->hMMio
= mmioOpenA((LPSTR
)lpName
, NULL
,
102 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
111 static LRESULT
ANIMATE_DoStop(ANIMATE_INFO
*infoPtr
)
113 EnterCriticalSection(&infoPtr
->cs
);
115 /* should stop playing */
116 if (infoPtr
->hThread
)
118 if (!TerminateThread(infoPtr
->hThread
,0))
119 WARN("could not destroy animation thread!\n");
120 infoPtr
->hThread
= 0;
122 if (infoPtr
->uTimer
) {
123 KillTimer(infoPtr
->hWnd
, infoPtr
->uTimer
);
127 LeaveCriticalSection(&infoPtr
->cs
);
129 ANIMATE_Notify(infoPtr
, ACN_STOP
);
135 static void ANIMATE_Free(ANIMATE_INFO
*infoPtr
)
137 if (infoPtr
->hMMio
) {
138 ANIMATE_DoStop(infoPtr
);
139 mmioClose(infoPtr
->hMMio
, 0);
141 FreeResource(infoPtr
->hRes
);
144 if (infoPtr
->lpIndex
) {
145 HeapFree(GetProcessHeap(), 0, infoPtr
->lpIndex
);
146 infoPtr
->lpIndex
= NULL
;
149 ICClose(infoPtr
->hic
);
152 if (infoPtr
->inbih
) {
153 HeapFree(GetProcessHeap(), 0, infoPtr
->inbih
);
154 infoPtr
->inbih
= NULL
;
156 if (infoPtr
->outbih
) {
157 HeapFree(GetProcessHeap(), 0, infoPtr
->outbih
);
158 infoPtr
->outbih
= NULL
;
160 if( infoPtr
->indata
)
162 HeapFree(GetProcessHeap(), 0, infoPtr
->indata
);
163 infoPtr
->indata
= NULL
;
165 if( infoPtr
->outdata
)
167 HeapFree(GetProcessHeap(), 0, infoPtr
->outdata
);
168 infoPtr
->outdata
= NULL
;
170 if( infoPtr
->hbmPrevFrame
)
172 DeleteObject(infoPtr
->hbmPrevFrame
);
173 infoPtr
->hbmPrevFrame
= 0;
175 infoPtr
->indata
= infoPtr
->outdata
= NULL
;
179 memset(&infoPtr
->mah
, 0, sizeof(infoPtr
->mah
));
180 memset(&infoPtr
->ash
, 0, sizeof(infoPtr
->ash
));
181 infoPtr
->nFromFrame
= infoPtr
->nToFrame
= infoPtr
->nLoop
= infoPtr
->currFrame
= 0;
183 infoPtr
->transparentColor
= ANIMATE_COLOR_NONE
;
186 static void ANIMATE_TransparentBlt(ANIMATE_INFO
* infoPtr
, HDC hdcDest
, HDC hdcSource
)
192 /* create a transparency mask */
193 hdcMask
= CreateCompatibleDC(hdcDest
);
194 hbmMask
= CreateBitmap(infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
, 1,1,NULL
);
195 hbmOld
= SelectObject(hdcMask
, hbmMask
);
197 SetBkColor(hdcSource
,infoPtr
->transparentColor
);
198 BitBlt(hdcMask
,0,0,infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,hdcSource
,0,0,SRCCOPY
);
200 /* mask the source bitmap */
201 SetBkColor(hdcSource
, RGB(0,0,0));
202 SetTextColor(hdcSource
, RGB(255,255,255));
203 BitBlt(hdcSource
, 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
, hdcMask
, 0, 0, SRCAND
);
205 /* mask the destination bitmap */
206 SetBkColor(hdcDest
, RGB(255,255,255));
207 SetTextColor(hdcDest
, RGB(0,0,0));
208 BitBlt(hdcDest
, 0, 0, infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
, hdcMask
, 0, 0, SRCAND
);
210 /* combine source and destination */
211 BitBlt(hdcDest
,0,0,infoPtr
->inbih
->biWidth
, infoPtr
->inbih
->biHeight
,hdcSource
,0,0,SRCPAINT
);
213 SelectObject(hdcMask
, hbmOld
);
214 DeleteObject(hbmMask
);
218 static LRESULT
ANIMATE_PaintFrame(ANIMATE_INFO
* infoPtr
, HDC hDC
)
220 void* pBitmapData
= NULL
;
221 LPBITMAPINFO pBitmapInfo
= NULL
;
232 if (!hDC
|| !infoPtr
->inbih
)
237 pBitmapData
= infoPtr
->outdata
;
238 pBitmapInfo
= (LPBITMAPINFO
)infoPtr
->outbih
;
240 nWidth
= infoPtr
->outbih
->biWidth
;
241 nHeight
= infoPtr
->outbih
->biHeight
;
244 pBitmapData
= infoPtr
->indata
;
245 pBitmapInfo
= (LPBITMAPINFO
)infoPtr
->inbih
;
247 nWidth
= infoPtr
->inbih
->biWidth
;
248 nHeight
= infoPtr
->inbih
->biHeight
;
251 if(!infoPtr
->hbmPrevFrame
)
253 infoPtr
->hbmPrevFrame
=CreateCompatibleBitmap(hDC
, nWidth
,nHeight
);
256 SetDIBits(hDC
, infoPtr
->hbmPrevFrame
, 0, nHeight
, pBitmapData
, (LPBITMAPINFO
)pBitmapInfo
, DIB_RGB_COLORS
);
258 hdcMem
= CreateCompatibleDC(hDC
);
259 hbmOld
= SelectObject(hdcMem
, infoPtr
->hbmPrevFrame
);
262 * we need to get the transparent color even without ACS_TRANSPARENT,
263 * because the style can be changed later on and the color should always
264 * be obtained in the first frame
266 if(infoPtr
->transparentColor
== ANIMATE_COLOR_NONE
)
268 infoPtr
->transparentColor
= GetPixel(hdcMem
,0,0);
271 if(GetWindowLongA(infoPtr
->hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
)
273 HDC hdcFinal
= CreateCompatibleDC(hDC
);
274 HBITMAP hbmFinal
= CreateCompatibleBitmap(hDC
,nWidth
, nHeight
);
275 HBITMAP hbmOld2
= SelectObject(hdcFinal
, hbmFinal
);
281 rect
.bottom
= nHeight
;
283 if(!infoPtr
->hbrushBG
)
284 infoPtr
->hbrushBG
= GetCurrentObject(hDC
, OBJ_BRUSH
);
286 FillRect(hdcFinal
, &rect
, infoPtr
->hbrushBG
);
287 ANIMATE_TransparentBlt(infoPtr
, hdcFinal
, hdcMem
);
289 SelectObject(hdcFinal
, hbmOld2
);
290 SelectObject(hdcMem
, hbmFinal
);
292 DeleteObject(infoPtr
->hbmPrevFrame
);
293 infoPtr
->hbmPrevFrame
= hbmFinal
;
296 if (GetWindowLongA(infoPtr
->hWnd
, GWL_STYLE
) & ACS_CENTER
)
300 GetWindowRect(infoPtr
->hWnd
, &rect
);
301 nOffsetX
= ((rect
.right
- rect
.left
) - nWidth
)/2;
302 nOffsetY
= ((rect
.bottom
- rect
.top
) - nHeight
)/2;
304 BitBlt(hDC
, nOffsetX
, nOffsetY
, nWidth
, nHeight
, hdcMem
, 0, 0, SRCCOPY
);
306 SelectObject(hdcMem
, hbmOld
);
311 static LRESULT
ANIMATE_DrawFrame(ANIMATE_INFO
* infoPtr
)
315 TRACE("Drawing frame %d (loop %d)\n", infoPtr
->currFrame
, infoPtr
->nLoop
);
317 EnterCriticalSection(&infoPtr
->cs
);
319 mmioSeek(infoPtr
->hMMio
, infoPtr
->lpIndex
[infoPtr
->currFrame
], SEEK_SET
);
320 mmioRead(infoPtr
->hMMio
, infoPtr
->indata
, infoPtr
->ash
.dwSuggestedBufferSize
);
323 ICDecompress(infoPtr
->hic
, 0, infoPtr
->inbih
, infoPtr
->indata
,
324 infoPtr
->outbih
, infoPtr
->outdata
) != ICERR_OK
) {
325 LeaveCriticalSection(&infoPtr
->cs
);
326 WARN("Decompression error\n");
330 if ((hDC
= GetDC(infoPtr
->hWnd
)) != 0) {
331 ANIMATE_PaintFrame(infoPtr
, hDC
);
332 ReleaseDC(infoPtr
->hWnd
, hDC
);
335 if (infoPtr
->currFrame
++ >= infoPtr
->nToFrame
) {
336 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
337 if (infoPtr
->nLoop
!= -1) {
338 if (--infoPtr
->nLoop
== 0) {
339 ANIMATE_DoStop(infoPtr
);
343 LeaveCriticalSection(&infoPtr
->cs
);
348 static DWORD CALLBACK
ANIMATE_AnimationThread(LPVOID ptr_
)
350 ANIMATE_INFO
* infoPtr
= (ANIMATE_INFO
*)ptr_
;
355 WARN("animation structure undefined!\n");
361 if(GetWindowLongA(infoPtr
->hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
)
363 hDC
= GetDC(infoPtr
->hWnd
);
364 infoPtr
->hbrushBG
= SendMessageA(GetParent(infoPtr
->hWnd
),WM_CTLCOLORSTATIC
,hDC
, infoPtr
->hWnd
);
365 ReleaseDC(infoPtr
->hWnd
,hDC
);
368 EnterCriticalSection(&infoPtr
->cs
);
369 ANIMATE_DrawFrame(infoPtr
);
370 LeaveCriticalSection(&infoPtr
->cs
);
372 /* time is in microseconds, we should convert it to milliseconds */
373 Sleep((infoPtr
->mah
.dwMicroSecPerFrame
+500)/1000);
378 static LRESULT
ANIMATE_Play(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
380 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
386 if (infoPtr
->hThread
|| infoPtr
->uTimer
) {
387 FIXME("Already playing ? what should I do ??\n");
388 ANIMATE_DoStop(infoPtr
);
391 infoPtr
->nFromFrame
= (INT
)LOWORD(lParam
);
392 infoPtr
->nToFrame
= (INT
)HIWORD(lParam
);
393 infoPtr
->nLoop
= (INT
)wParam
;
395 if (infoPtr
->nToFrame
== 0xFFFF)
396 infoPtr
->nToFrame
= infoPtr
->mah
.dwTotalFrames
- 1;
398 TRACE("(repeat=%d from=%d to=%d);\n",
399 infoPtr
->nLoop
, infoPtr
->nFromFrame
, infoPtr
->nToFrame
);
401 if (infoPtr
->nFromFrame
>= infoPtr
->nToFrame
||
402 infoPtr
->nToFrame
>= infoPtr
->mah
.dwTotalFrames
)
405 infoPtr
->currFrame
= infoPtr
->nFromFrame
;
407 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TIMER
) {
408 TRACE("Using a timer\n");
409 /* create a timer to display AVI */
410 infoPtr
->uTimer
= SetTimer(hWnd
, 1, infoPtr
->mah
.dwMicroSecPerFrame
/ 1000, NULL
);
414 TRACE("Using an animation thread\n");
415 infoPtr
->hThread
= CreateThread(0,0,ANIMATE_AnimationThread
,(LPVOID
)infoPtr
,0,0 &threadID
);
416 if(!infoPtr
->hThread
)
418 ERR("Could not create animation thread!\n");
424 ANIMATE_Notify(infoPtr
, ACN_START
);
430 static BOOL
ANIMATE_GetAviInfo(ANIMATE_INFO
*infoPtr
)
439 if (mmioDescend(infoPtr
->hMMio
, &ckMainRIFF
, NULL
, 0) != 0) {
440 WARN("Can't find 'RIFF' chunk\n");
444 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
445 (ckMainRIFF
.fccType
!= mmioFOURCC('A', 'V', 'I', ' '))) {
446 WARN("Can't find 'AVI ' chunk\n");
450 mmckHead
.fccType
= mmioFOURCC('h', 'd', 'r', 'l');
451 if (mmioDescend(infoPtr
->hMMio
, &mmckHead
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
452 WARN("Can't find 'hdrl' list\n");
456 mmckInfo
.ckid
= mmioFOURCC('a', 'v', 'i', 'h');
457 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckHead
, MMIO_FINDCHUNK
) != 0) {
458 WARN("Can't find 'avih' chunk\n");
462 mmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->mah
, sizeof(infoPtr
->mah
));
464 TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr
->mah
.dwMicroSecPerFrame
);
465 TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr
->mah
.dwMaxBytesPerSec
);
466 TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr
->mah
.dwPaddingGranularity
);
467 TRACE("mah.dwFlags=%ld\n", infoPtr
->mah
.dwFlags
);
468 TRACE("mah.dwTotalFrames=%ld\n", infoPtr
->mah
.dwTotalFrames
);
469 TRACE("mah.dwInitialFrames=%ld\n", infoPtr
->mah
.dwInitialFrames
);
470 TRACE("mah.dwStreams=%ld\n", infoPtr
->mah
.dwStreams
);
471 TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr
->mah
.dwSuggestedBufferSize
);
472 TRACE("mah.dwWidth=%ld\n", infoPtr
->mah
.dwWidth
);
473 TRACE("mah.dwHeight=%ld\n", infoPtr
->mah
.dwHeight
);
475 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
477 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
478 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) != 0) {
479 WARN("Can't find 'strl' list\n");
483 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'h');
484 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
485 WARN("Can't find 'strh' chunk\n");
489 mmioRead(infoPtr
->hMMio
, (LPSTR
)&infoPtr
->ash
, sizeof(infoPtr
->ash
));
491 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccType
)),
492 HIBYTE(LOWORD(infoPtr
->ash
.fccType
)),
493 LOBYTE(HIWORD(infoPtr
->ash
.fccType
)),
494 HIBYTE(HIWORD(infoPtr
->ash
.fccType
)));
495 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
496 HIBYTE(LOWORD(infoPtr
->ash
.fccHandler
)),
497 LOBYTE(HIWORD(infoPtr
->ash
.fccHandler
)),
498 HIBYTE(HIWORD(infoPtr
->ash
.fccHandler
)));
499 TRACE("ash.dwFlags=%ld\n", infoPtr
->ash
.dwFlags
);
500 TRACE("ash.wPriority=%d\n", infoPtr
->ash
.wPriority
);
501 TRACE("ash.wLanguage=%d\n", infoPtr
->ash
.wLanguage
);
502 TRACE("ash.dwInitialFrames=%ld\n", infoPtr
->ash
.dwInitialFrames
);
503 TRACE("ash.dwScale=%ld\n", infoPtr
->ash
.dwScale
);
504 TRACE("ash.dwRate=%ld\n", infoPtr
->ash
.dwRate
);
505 TRACE("ash.dwStart=%ld\n", infoPtr
->ash
.dwStart
);
506 TRACE("ash.dwLength=%ld\n", infoPtr
->ash
.dwLength
);
507 TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr
->ash
.dwSuggestedBufferSize
);
508 TRACE("ash.dwQuality=%ld\n", infoPtr
->ash
.dwQuality
);
509 TRACE("ash.dwSampleSize=%ld\n", infoPtr
->ash
.dwSampleSize
);
510 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr
->ash
.rcFrame
.top
, infoPtr
->ash
.rcFrame
.left
,
511 infoPtr
->ash
.rcFrame
.bottom
, infoPtr
->ash
.rcFrame
.right
);
513 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
515 mmckInfo
.ckid
= mmioFOURCC('s', 't', 'r', 'f');
516 if (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, MMIO_FINDCHUNK
) != 0) {
517 WARN("Can't find 'strh' chunk\n");
521 infoPtr
->inbih
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
522 if (!infoPtr
->inbih
) {
523 WARN("Can't alloc input BIH\n");
527 mmioRead(infoPtr
->hMMio
, (LPSTR
)infoPtr
->inbih
, mmckInfo
.cksize
);
529 TRACE("bih.biSize=%ld\n", infoPtr
->inbih
->biSize
);
530 TRACE("bih.biWidth=%ld\n", infoPtr
->inbih
->biWidth
);
531 TRACE("bih.biHeight=%ld\n", infoPtr
->inbih
->biHeight
);
532 TRACE("bih.biPlanes=%d\n", infoPtr
->inbih
->biPlanes
);
533 TRACE("bih.biBitCount=%d\n", infoPtr
->inbih
->biBitCount
);
534 TRACE("bih.biCompression=%ld\n", infoPtr
->inbih
->biCompression
);
535 TRACE("bih.biSizeImage=%ld\n", infoPtr
->inbih
->biSizeImage
);
536 TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr
->inbih
->biXPelsPerMeter
);
537 TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr
->inbih
->biYPelsPerMeter
);
538 TRACE("bih.biClrUsed=%ld\n", infoPtr
->inbih
->biClrUsed
);
539 TRACE("bih.biClrImportant=%ld\n", infoPtr
->inbih
->biClrImportant
);
541 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
543 mmioAscend(infoPtr
->hMMio
, &mmckList
, 0);
546 /* an AVI has 0 or 1 video stream, and to be animated should not contain
547 * an audio stream, so only one strl is allowed
549 mmckList
.fccType
= mmioFOURCC('s', 't', 'r', 'l');
550 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &mmckHead
, MMIO_FINDLIST
) == 0) {
551 WARN("There should be a single 'strl' list\n");
556 mmioAscend(infoPtr
->hMMio
, &mmckHead
, 0);
558 /* no need to read optional JUNK chunk */
560 mmckList
.fccType
= mmioFOURCC('m', 'o', 'v', 'i');
561 if (mmioDescend(infoPtr
->hMMio
, &mmckList
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
562 WARN("Can't find 'movi' list\n");
566 /* FIXME: should handle the 'rec ' LIST when present */
568 infoPtr
->lpIndex
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
569 infoPtr
->mah
.dwTotalFrames
* sizeof(DWORD
));
570 if (!infoPtr
->lpIndex
) {
571 WARN("Can't alloc index array\n");
575 numFrame
= insize
= 0;
576 while (mmioDescend(infoPtr
->hMMio
, &mmckInfo
, &mmckList
, 0) == 0 &&
577 numFrame
< infoPtr
->mah
.dwTotalFrames
) {
578 infoPtr
->lpIndex
[numFrame
] = mmckInfo
.dwDataOffset
;
579 if (insize
< mmckInfo
.cksize
)
580 insize
= mmckInfo
.cksize
;
582 mmioAscend(infoPtr
->hMMio
, &mmckInfo
, 0);
584 if (numFrame
!= infoPtr
->mah
.dwTotalFrames
) {
585 WARN("Found %ld frames (/%ld)\n", numFrame
, infoPtr
->mah
.dwTotalFrames
);
588 if (insize
> infoPtr
->ash
.dwSuggestedBufferSize
) {
589 WARN("insize=%ld suggestedSize=%ld\n", insize
, infoPtr
->ash
.dwSuggestedBufferSize
);
590 infoPtr
->ash
.dwSuggestedBufferSize
= insize
;
593 infoPtr
->indata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->ash
.dwSuggestedBufferSize
);
594 if (!infoPtr
->indata
) {
595 WARN("Can't alloc input buffer\n");
603 static BOOL
ANIMATE_GetAviCodec(ANIMATE_INFO
*infoPtr
)
607 /* check uncompressed AVI */
608 if ((infoPtr
->ash
.fccHandler
== mmioFOURCC('D', 'I', 'B', ' ')) ||
609 (infoPtr
->ash
.fccHandler
== mmioFOURCC('R', 'L', 'E', ' ')))
615 /* try to get a decompressor for that type */
616 infoPtr
->hic
= ICOpen(ICTYPE_VIDEO
, infoPtr
->ash
.fccHandler
, ICMODE_DECOMPRESS
);
618 WARN("Can't load codec for the file\n");
622 outSize
= ICSendMessage(infoPtr
->hic
, ICM_DECOMPRESS_GET_FORMAT
,
623 (DWORD
)infoPtr
->inbih
, 0L);
625 infoPtr
->outbih
= HeapAlloc(GetProcessHeap(), 0, outSize
);
626 if (!infoPtr
->outbih
) {
627 WARN("Can't alloc output BIH\n");
631 if (ICSendMessage(infoPtr
->hic
, ICM_DECOMPRESS_GET_FORMAT
,
632 (DWORD
)infoPtr
->inbih
, (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
633 WARN("Can't get output BIH\n");
637 infoPtr
->outdata
= HeapAlloc(GetProcessHeap(), 0, infoPtr
->outbih
->biSizeImage
);
638 if (!infoPtr
->outdata
) {
639 WARN("Can't alloc output buffer\n");
643 if (ICSendMessage(infoPtr
->hic
, ICM_DECOMPRESS_BEGIN
,
644 (DWORD
)infoPtr
->inbih
, (DWORD
)infoPtr
->outbih
) != ICERR_OK
) {
645 WARN("Can't begin decompression\n");
652 static LRESULT
ANIMATE_OpenA(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
654 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
655 HINSTANCE hInstance
= (HINSTANCE
)wParam
;
657 ANIMATE_Free(infoPtr
);
660 TRACE("Closing avi!\n");
665 hInstance
= GetWindowLongA(hWnd
, GWL_HINSTANCE
);
667 if (HIWORD(lParam
)) {
668 TRACE("(\"%s\");\n", (LPSTR
)lParam
);
670 if (!ANIMATE_LoadResA(infoPtr
, hInstance
, (LPSTR
)lParam
)) {
671 TRACE("No AVI resource found!\n");
672 if (!ANIMATE_LoadFileA(infoPtr
, (LPSTR
)lParam
)) {
673 WARN("No AVI file found!\n");
678 TRACE("(%u);\n", (WORD
)LOWORD(lParam
));
680 if (!ANIMATE_LoadResA(infoPtr
, hInstance
,
681 MAKEINTRESOURCEA((INT
)lParam
))) {
682 WARN("No AVI resource found!\n");
687 if (!ANIMATE_GetAviInfo(infoPtr
)) {
688 WARN("Can't get AVI information\n");
689 ANIMATE_Free(infoPtr
);
693 if (!ANIMATE_GetAviCodec(infoPtr
)) {
694 WARN("Can't get AVI Codec\n");
695 ANIMATE_Free(infoPtr
);
699 if (!GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
700 SetWindowPos(hWnd
, 0, 0, 0, infoPtr
->mah
.dwWidth
, infoPtr
->mah
.dwHeight
,
701 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
704 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_AUTOPLAY
) {
705 return ANIMATE_Play(hWnd
, -1, (LPARAM
)MAKELONG(0, infoPtr
->mah
.dwTotalFrames
-1));
712 /* << ANIMATE_Open32W >> */
714 static LRESULT
ANIMATE_Stop(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
716 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
722 ANIMATE_DoStop(infoPtr
);
727 static LRESULT
ANIMATE_Create(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
729 ANIMATE_INFO
* infoPtr
;
731 /* allocate memory for info structure */
732 infoPtr
= (ANIMATE_INFO
*)COMCTL32_Alloc(sizeof(ANIMATE_INFO
));
734 ERR("could not allocate info memory!\n");
738 TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd
, GWL_STYLE
), (DWORD
)GetParent(hWnd
));
740 /* store crossref hWnd <-> info structure */
741 SetWindowLongA(hWnd
, 0, (DWORD
)infoPtr
);
742 infoPtr
->hWnd
= hWnd
;
743 infoPtr
->transparentColor
= ANIMATE_COLOR_NONE
;
744 infoPtr
->hbmPrevFrame
= 0;
746 InitializeCriticalSection(&infoPtr
->cs
);
752 static LRESULT
ANIMATE_Destroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
754 ANIMATE_INFO
*infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
758 ANIMATE_Free(infoPtr
);
760 /* free animate info data */
761 COMCTL32_Free(infoPtr
);
762 SetWindowLongA(hWnd
, 0, 0);
768 static LRESULT
ANIMATE_EraseBackground(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
773 if(GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
)
775 hBrush
= SendMessageA(GetParent(hWnd
),WM_CTLCOLORSTATIC
,(HDC
)wParam
, hWnd
);
778 GetClientRect(hWnd
, &rect
);
779 FillRect((HDC
)wParam
, &rect
, hBrush
? hBrush
: GetCurrentObject((HDC
)wParam
, OBJ_BRUSH
));
784 static LRESULT WINAPI
ANIMATE_Size(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
786 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_CENTER
) {
787 InvalidateRect(hWnd
, NULL
, TRUE
);
792 static LRESULT WINAPI
ANIMATE_WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
794 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hWnd
, uMsg
, wParam
, lParam
);
795 if (!ANIMATE_GetInfoPtr(hWnd
) && (uMsg
!= WM_NCCREATE
))
796 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
800 return ANIMATE_OpenA(hWnd
, wParam
, lParam
);
802 /* case ACM_OPEN32W: FIXME!! */
803 /* return ANIMATE_Open32W(hWnd, wParam, lParam); */
806 return ANIMATE_Play(hWnd
, wParam
, lParam
);
809 return ANIMATE_Stop(hWnd
, wParam
, lParam
);
812 ANIMATE_Create(hWnd
, wParam
, lParam
);
813 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
816 return HTTRANSPARENT
;
819 ANIMATE_Destroy(hWnd
, wParam
, lParam
);
820 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
823 ANIMATE_EraseBackground(hWnd
, wParam
, lParam
);
826 /* case WM_STYLECHANGED: FIXME shall we do something ?? */
829 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
)
831 ANIMATE_INFO
* infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
832 infoPtr
->hbrushBG
= SendMessageA(GetParent(hWnd
),WM_CTLCOLORSTATIC
,(HDC
)wParam
, hWnd
);
834 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd
));
837 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd
));
842 ANIMATE_INFO
* infoPtr
= ANIMATE_GetInfoPtr(hWnd
);
844 /* the animation isn't playing, don't paint */
845 if(!infoPtr
->uTimer
&& !infoPtr
->hThread
)
846 /* default paint handling */
847 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
849 if (GetWindowLongA(hWnd
, GWL_STYLE
) & ACS_TRANSPARENT
)
850 infoPtr
->hbrushBG
= SendMessageA(GetParent(hWnd
), WM_CTLCOLORSTATIC
,
855 EnterCriticalSection(&infoPtr
->cs
);
856 ANIMATE_PaintFrame(infoPtr
, (HDC
)wParam
);
857 LeaveCriticalSection(&infoPtr
->cs
);
862 HDC hDC
= BeginPaint(hWnd
, &ps
);
864 EnterCriticalSection(&infoPtr
->cs
);
865 ANIMATE_PaintFrame(infoPtr
, hDC
);
866 LeaveCriticalSection(&infoPtr
->cs
);
874 ANIMATE_Size(hWnd
, wParam
, lParam
);
875 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
879 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
, lParam
);
881 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
887 void ANIMATE_Register(void)
891 ZeroMemory(&wndClass
, sizeof(WNDCLASSA
));
892 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
893 wndClass
.lpfnWndProc
= (WNDPROC
)ANIMATE_WindowProc
;
894 wndClass
.cbClsExtra
= 0;
895 wndClass
.cbWndExtra
= sizeof(ANIMATE_INFO
*);
896 wndClass
.hCursor
= LoadCursorA(0, IDC_ARROWA
);
897 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
898 wndClass
.lpszClassName
= ANIMATE_CLASSA
;
900 RegisterClassA(&wndClass
);
904 void ANIMATE_Unregister(void)
906 UnregisterClassA(ANIMATE_CLASSA
, (HINSTANCE
)NULL
);