source: trunk/src/comctl32/animate.c@ 6666

Last change on this file since 6666 was 6644, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 28.3 KB
Line 
1/* -*- tab-width: 8; c-basic-offset: 4 -*- */
2/* $Id: animate.c,v 1.14 2001-09-05 12:04:56 bird Exp $ */
3/*
4 * Animation control
5 *
6 * Copyright 1998, 1999 Eric Kohl
7 * 1999 Eric Pouech
8 *
9 * NOTES
10 * I will only improve this control once in a while.
11 * Eric <ekohl@abo.rhein-zeitung.de>
12 *
13 * TODO:
14 * - check for the 'rec ' list in some AVI files
15 * - concurrent access to infoPtr
16 */
17
18#include <string.h>
19#include "winbase.h"
20#include "commctrl.h"
21#include "vfw.h"
22#include "mmsystem.h"
23#include "debugtools.h"
24#ifdef __WIN32OS2__
25#include "ccbase.h"
26#endif
27
28DEFAULT_DEBUG_CHANNEL(animate);
29
30typedef struct
31{
32#ifdef __WIN32OS2__
33 COMCTL32_HEADER header;
34#endif
35 /* reference to input stream (file or resource) */
36 HGLOBAL hRes;
37 HMMIO hMMio; /* handle to mmio stream */
38 HWND hWnd;
39 /* information on the loaded AVI file */
40 MainAVIHeader mah;
41 AVIStreamHeader ash;
42 LPBITMAPINFOHEADER inbih;
43 LPDWORD lpIndex;
44 /* data for the decompressor */
45 HIC hic;
46 LPBITMAPINFOHEADER outbih;
47 LPVOID indata;
48 LPVOID outdata;
49 /* data for the background mechanism */
50 CRITICAL_SECTION cs;
51 HANDLE hThread;
52 UINT uTimer;
53 /* data for playing the file */
54 int nFromFrame;
55 int nToFrame;
56 int nLoop;
57 int currFrame;
58 /* tranparency info*/
59 COLORREF transparentColor;
60 HBRUSH hbrushBG;
61 HBITMAP hbmPrevFrame;
62} ANIMATE_INFO;
63
64#define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
65#define ANIMATE_COLOR_NONE 0xffffffff
66
67static void ANIMATE_Notify(ANIMATE_INFO* infoPtr, UINT notif)
68{
69 SendMessageA(GetParent(infoPtr->hWnd), WM_COMMAND,
70 MAKEWPARAM(GetDlgCtrlID(infoPtr->hWnd), notif),
71 (LPARAM)infoPtr->hWnd);
72}
73
74#ifdef __WIN32OS2__
75static BOOL ANIMATE_LoadRes(ANIMATE_INFO *infoPtr,HINSTANCE hInst,LPWSTR lpName,BOOL unicode)
76#else
77static BOOL ANIMATE_LoadResA(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPSTR lpName)
78#endif
79{
80 HRSRC hrsrc;
81 MMIOINFO mminfo;
82 LPVOID lpAvi;
83
84#ifdef __WIN32OS2__
85 if (unicode)
86 hrsrc = FindResourceW(hInst,lpName,(LPWSTR)L"AVI");
87 else
88 hrsrc = FindResourceA(hInst,(LPCSTR)lpName,"AVI");
89#else
90 hrsrc = FindResourceA(hInst, lpName, "AVI");
91#endif
92 if (!hrsrc)
93 return FALSE;
94
95 infoPtr->hRes = LoadResource(hInst, hrsrc);
96 if (!infoPtr->hRes)
97 return FALSE;
98
99 lpAvi = LockResource(infoPtr->hRes);
100 if (!lpAvi)
101 return FALSE;
102
103 memset(&mminfo, 0, sizeof(mminfo));
104 mminfo.fccIOProc = FOURCC_MEM;
105 mminfo.pchBuffer = (LPSTR)lpAvi;
106 mminfo.cchBuffer = SizeofResource(hInst, hrsrc);
107 infoPtr->hMMio = mmioOpenA(NULL, &mminfo, MMIO_READ);
108 if (!infoPtr->hMMio) {
109 GlobalFree((HGLOBAL)lpAvi);
110 return FALSE;
111 }
112
113 return TRUE;
114}
115
116
117#ifdef __WIN32OS2__
118static BOOL ANIMATE_LoadFile(ANIMATE_INFO *infoPtr,LPWSTR lpName,BOOL unicode)
119#else
120static BOOL ANIMATE_LoadFileA(ANIMATE_INFO *infoPtr, LPSTR lpName)
121#endif
122{
123#ifdef __WIN32OS2__
124 if (unicode)
125 infoPtr->hMMio = mmioOpenW(lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
126 else
127 infoPtr->hMMio = mmioOpenA((LPSTR)lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
128#else
129 infoPtr->hMMio = mmioOpenA((LPSTR)lpName, NULL,
130 MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
131#endif
132 if (!infoPtr->hMMio)
133 return FALSE;
134
135 return TRUE;
136}
137
138
139static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr)
140{
141 EnterCriticalSection(&infoPtr->cs);
142
143 /* should stop playing */
144 if (infoPtr->hThread)
145 {
146 if (!TerminateThread(infoPtr->hThread,0))
147 WARN("could not destroy animation thread!\n");
148 infoPtr->hThread = 0;
149 }
150 if (infoPtr->uTimer) {
151 KillTimer(infoPtr->hWnd, infoPtr->uTimer);
152 infoPtr->uTimer = 0;
153 }
154
155 LeaveCriticalSection(&infoPtr->cs);
156
157 ANIMATE_Notify(infoPtr, ACN_STOP);
158
159 return TRUE;
160}
161
162
163static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
164{
165 if (infoPtr->hMMio) {
166 ANIMATE_DoStop(infoPtr);
167 mmioClose(infoPtr->hMMio, 0);
168 if (infoPtr->hRes) {
169 FreeResource(infoPtr->hRes);
170 infoPtr->hRes = 0;
171 }
172 if (infoPtr->lpIndex) {
173 HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex);
174 infoPtr->lpIndex = NULL;
175 }
176 if (infoPtr->hic) {
177 ICClose(infoPtr->hic);
178 infoPtr->hic = 0;
179 }
180 if (infoPtr->inbih) {
181 HeapFree(GetProcessHeap(), 0, infoPtr->inbih);
182 infoPtr->inbih = NULL;
183 }
184 if (infoPtr->outbih) {
185 HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
186 infoPtr->outbih = NULL;
187 }
188 if( infoPtr->indata )
189 {
190 HeapFree(GetProcessHeap(), 0, infoPtr->indata);
191 infoPtr->indata = NULL;
192 }
193 if( infoPtr->outdata )
194 {
195 HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
196 infoPtr->outdata = NULL;
197 }
198 if( infoPtr->hbmPrevFrame )
199 {
200 DeleteObject(infoPtr->hbmPrevFrame);
201 infoPtr->hbmPrevFrame = 0;
202 }
203 infoPtr->indata = infoPtr->outdata = NULL;
204 infoPtr->hWnd = 0;
205 infoPtr->hMMio = 0;
206
207 memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
208 memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
209 infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
210 }
211 infoPtr->transparentColor = ANIMATE_COLOR_NONE;
212}
213
214static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource)
215{
216 HDC hdcMask;
217 HBITMAP hbmMask;
218 HBITMAP hbmOld;
219
220 /* create a transparency mask */
221 hdcMask = CreateCompatibleDC(hdcDest);
222 hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL);
223 hbmOld = SelectObject(hdcMask, hbmMask);
224
225 SetBkColor(hdcSource,infoPtr->transparentColor);
226 BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY);
227
228 /* mask the source bitmap */
229 SetBkColor(hdcSource, RGB(0,0,0));
230 SetTextColor(hdcSource, RGB(255,255,255));
231 BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
232
233 /* mask the destination bitmap */
234 SetBkColor(hdcDest, RGB(255,255,255));
235 SetTextColor(hdcDest, RGB(0,0,0));
236 BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
237
238 /* combine source and destination */
239 BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT);
240
241 SelectObject(hdcMask, hbmOld);
242 DeleteObject(hbmMask);
243 DeleteDC(hdcMask);
244}
245
246static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC)
247{
248 void* pBitmapData = NULL;
249 LPBITMAPINFO pBitmapInfo = NULL;
250
251 HDC hdcMem;
252 HBITMAP hbmOld;
253
254 int nOffsetX = 0;
255 int nOffsetY = 0;
256
257 int nWidth;
258 int nHeight;
259
260 if (!hDC || !infoPtr->inbih)
261 return TRUE;
262
263 if (infoPtr->hic )
264 {
265 pBitmapData = infoPtr->outdata;
266 pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih;
267
268 nWidth = infoPtr->outbih->biWidth;
269 nHeight = infoPtr->outbih->biHeight;
270 } else
271 {
272 pBitmapData = infoPtr->indata;
273 pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih;
274
275 nWidth = infoPtr->inbih->biWidth;
276 nHeight = infoPtr->inbih->biHeight;
277 }
278
279 if(!infoPtr->hbmPrevFrame)
280 {
281 infoPtr->hbmPrevFrame=CreateCompatibleBitmap(hDC, nWidth,nHeight );
282 }
283
284 SetDIBits(hDC, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS);
285
286 hdcMem = CreateCompatibleDC(hDC);
287 hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame);
288
289 /*
290 * we need to get the transparent color even without ACS_TRANSPARENT,
291 * because the style can be changed later on and the color should always
292 * be obtained in the first frame
293 */
294 if(infoPtr->transparentColor == ANIMATE_COLOR_NONE)
295 {
296 infoPtr->transparentColor = GetPixel(hdcMem,0,0);
297 }
298
299 if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
300 {
301 HDC hdcFinal = CreateCompatibleDC(hDC);
302 HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight);
303 HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal);
304 RECT rect;
305
306 rect.left = 0;
307 rect.top = 0;
308 rect.right = nWidth;
309 rect.bottom = nHeight;
310
311 if(!infoPtr->hbrushBG)
312 infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH);
313
314 FillRect(hdcFinal, &rect, infoPtr->hbrushBG);
315 ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem);
316
317 SelectObject(hdcFinal, hbmOld2);
318 SelectObject(hdcMem, hbmFinal);
319 DeleteDC(hdcFinal);
320 DeleteObject(infoPtr->hbmPrevFrame);
321 infoPtr->hbmPrevFrame = hbmFinal;
322 }
323
324 if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_CENTER)
325 {
326 RECT rect;
327
328 GetWindowRect(infoPtr->hWnd, &rect);
329 nOffsetX = ((rect.right - rect.left) - nWidth)/2;
330 nOffsetY = ((rect.bottom - rect.top) - nHeight)/2;
331 }
332 BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
333
334 SelectObject(hdcMem, hbmOld);
335 DeleteDC(hdcMem);
336 return TRUE;
337}
338
339static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr)
340{
341 HDC hDC;
342
343 TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop);
344
345 EnterCriticalSection(&infoPtr->cs);
346
347 mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
348 mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
349
350 if (infoPtr->hic &&
351 ICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
352 infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
353 LeaveCriticalSection(&infoPtr->cs);
354 WARN("Decompression error\n");
355 return FALSE;
356 }
357
358 if ((hDC = GetDC(infoPtr->hWnd)) != 0) {
359 ANIMATE_PaintFrame(infoPtr, hDC);
360 ReleaseDC(infoPtr->hWnd, hDC);
361 }
362
363 if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
364 infoPtr->currFrame = infoPtr->nFromFrame;
365 if (infoPtr->nLoop != -1) {
366 if (--infoPtr->nLoop == 0) {
367 ANIMATE_DoStop(infoPtr);
368 }
369 }
370 }
371 LeaveCriticalSection(&infoPtr->cs);
372
373 return TRUE;
374}
375
376static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_)
377{
378 ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_;
379 HDC hDC;
380
381 if(!infoPtr)
382 {
383 WARN("animation structure undefined!\n");
384 return FALSE;
385 }
386
387 while(1)
388 {
389 if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
390 {
391 hDC = GetDC(infoPtr->hWnd);
392 /* sometimes the animation window will be destroyed in between
393 * by the main program, so a ReleaseDC() error msg is possible */
394 infoPtr->hbrushBG = SendMessageA(GetParent(infoPtr->hWnd),WM_CTLCOLORSTATIC,hDC, infoPtr->hWnd);
395 ReleaseDC(infoPtr->hWnd,hDC);
396 }
397
398 EnterCriticalSection(&infoPtr->cs);
399 ANIMATE_DrawFrame(infoPtr);
400 LeaveCriticalSection(&infoPtr->cs);
401
402 /* time is in microseconds, we should convert it to milliseconds */
403 Sleep((infoPtr->mah.dwMicroSecPerFrame+500)/1000);
404 }
405 return TRUE;
406}
407
408static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
409{
410 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
411
412 /* nothing opened */
413 if (!infoPtr->hMMio)
414 return FALSE;
415
416 if (infoPtr->hThread || infoPtr->uTimer) {
417 FIXME("Already playing ? what should I do ??\n");
418 ANIMATE_DoStop(infoPtr);
419 }
420
421 infoPtr->nFromFrame = (INT)LOWORD(lParam);
422 infoPtr->nToFrame = (INT)HIWORD(lParam);
423 infoPtr->nLoop = (INT)wParam;
424
425 if (infoPtr->nToFrame == 0xFFFF)
426 infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
427
428 TRACE("(repeat=%d from=%d to=%d);\n",
429 infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
430
431 if (infoPtr->nFromFrame >= infoPtr->nToFrame ||
432 infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
433 return FALSE;
434
435 infoPtr->currFrame = infoPtr->nFromFrame;
436
437 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) {
438 TRACE("Using a timer\n");
439 /* create a timer to display AVI */
440 infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
441 } else {
442 DWORD threadID;
443
444 TRACE("Using an animation thread\n");
445 infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr,0,0 &threadID);
446 if(!infoPtr->hThread)
447 {
448 ERR("Could not create animation thread!\n");
449 return FALSE;
450 }
451
452 }
453
454 ANIMATE_Notify(infoPtr, ACN_START);
455
456 return TRUE;
457}
458
459
460static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr)
461{
462 MMCKINFO ckMainRIFF;
463 MMCKINFO mmckHead;
464 MMCKINFO mmckList;
465 MMCKINFO mmckInfo;
466 DWORD numFrame;
467 DWORD insize;
468
469 if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
470 WARN("Can't find 'RIFF' chunk\n");
471 return FALSE;
472 }
473
474 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
475 (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
476 WARN("Can't find 'AVI ' chunk\n");
477 return FALSE;
478 }
479
480 mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l');
481 if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
482 WARN("Can't find 'hdrl' list\n");
483 return FALSE;
484 }
485
486 mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
487 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
488 WARN("Can't find 'avih' chunk\n");
489 return FALSE;
490 }
491
492 mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
493
494 TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr->mah.dwMicroSecPerFrame);
495 TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr->mah.dwMaxBytesPerSec);
496 TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr->mah.dwPaddingGranularity);
497 TRACE("mah.dwFlags=%ld\n", infoPtr->mah.dwFlags);
498 TRACE("mah.dwTotalFrames=%ld\n", infoPtr->mah.dwTotalFrames);
499 TRACE("mah.dwInitialFrames=%ld\n", infoPtr->mah.dwInitialFrames);
500 TRACE("mah.dwStreams=%ld\n", infoPtr->mah.dwStreams);
501 TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr->mah.dwSuggestedBufferSize);
502 TRACE("mah.dwWidth=%ld\n", infoPtr->mah.dwWidth);
503 TRACE("mah.dwHeight=%ld\n", infoPtr->mah.dwHeight);
504
505 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
506
507 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
508 if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
509 WARN("Can't find 'strl' list\n");
510 return FALSE;
511 }
512
513 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
514 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
515 WARN("Can't find 'strh' chunk\n");
516 return FALSE;
517 }
518
519 mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
520
521 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)),
522 HIBYTE(LOWORD(infoPtr->ash.fccType)),
523 LOBYTE(HIWORD(infoPtr->ash.fccType)),
524 HIBYTE(HIWORD(infoPtr->ash.fccType)));
525 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
526 HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
527 LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
528 HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
529 TRACE("ash.dwFlags=%ld\n", infoPtr->ash.dwFlags);
530 TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority);
531 TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage);
532 TRACE("ash.dwInitialFrames=%ld\n", infoPtr->ash.dwInitialFrames);
533 TRACE("ash.dwScale=%ld\n", infoPtr->ash.dwScale);
534 TRACE("ash.dwRate=%ld\n", infoPtr->ash.dwRate);
535 TRACE("ash.dwStart=%ld\n", infoPtr->ash.dwStart);
536 TRACE("ash.dwLength=%ld\n", infoPtr->ash.dwLength);
537 TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr->ash.dwSuggestedBufferSize);
538 TRACE("ash.dwQuality=%ld\n", infoPtr->ash.dwQuality);
539 TRACE("ash.dwSampleSize=%ld\n", infoPtr->ash.dwSampleSize);
540 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
541 infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
542
543 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
544
545 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
546 if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
547 WARN("Can't find 'strh' chunk\n");
548 return FALSE;
549 }
550
551 infoPtr->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
552 if (!infoPtr->inbih) {
553 WARN("Can't alloc input BIH\n");
554 return FALSE;
555 }
556
557 mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
558
559 TRACE("bih.biSize=%ld\n", infoPtr->inbih->biSize);
560 TRACE("bih.biWidth=%ld\n", infoPtr->inbih->biWidth);
561 TRACE("bih.biHeight=%ld\n", infoPtr->inbih->biHeight);
562 TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes);
563 TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount);
564 TRACE("bih.biCompression=%ld\n", infoPtr->inbih->biCompression);
565 TRACE("bih.biSizeImage=%ld\n", infoPtr->inbih->biSizeImage);
566 TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr->inbih->biXPelsPerMeter);
567 TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr->inbih->biYPelsPerMeter);
568 TRACE("bih.biClrUsed=%ld\n", infoPtr->inbih->biClrUsed);
569 TRACE("bih.biClrImportant=%ld\n", infoPtr->inbih->biClrImportant);
570
571 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
572
573 mmioAscend(infoPtr->hMMio, &mmckList, 0);
574
575#if 0
576 /* an AVI has 0 or 1 video stream, and to be animated should not contain
577 * an audio stream, so only one strl is allowed
578 */
579 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
580 if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
581 WARN("There should be a single 'strl' list\n");
582 return FALSE;
583 }
584#endif
585
586 mmioAscend(infoPtr->hMMio, &mmckHead, 0);
587
588 /* no need to read optional JUNK chunk */
589
590 mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
591 if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
592 WARN("Can't find 'movi' list\n");
593 return FALSE;
594 }
595
596 /* FIXME: should handle the 'rec ' LIST when present */
597
598 infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
599 infoPtr->mah.dwTotalFrames * sizeof(DWORD));
600 if (!infoPtr->lpIndex) {
601 WARN("Can't alloc index array\n");
602 return FALSE;
603 }
604
605 numFrame = insize = 0;
606 while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
607 numFrame < infoPtr->mah.dwTotalFrames) {
608 infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
609 if (insize < mmckInfo.cksize)
610 insize = mmckInfo.cksize;
611 numFrame++;
612 mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
613 }
614 if (numFrame != infoPtr->mah.dwTotalFrames) {
615 WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames);
616 return FALSE;
617 }
618 if (insize > infoPtr->ash.dwSuggestedBufferSize) {
619 WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize);
620 infoPtr->ash.dwSuggestedBufferSize = insize;
621 }
622
623 infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize);
624 if (!infoPtr->indata) {
625 WARN("Can't alloc input buffer\n");
626 return FALSE;
627 }
628
629 return TRUE;
630}
631
632
633static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
634{
635 DWORD outSize;
636
637 /* check uncompressed AVI */
638 if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) ||
639 (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')))
640 {
641 infoPtr->hic = 0;
642 return TRUE;
643 }
644
645 /* try to get a decompressor for that type */
646 infoPtr->hic = ICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS);
647 if (!infoPtr->hic) {
648 WARN("Can't load codec for the file\n");
649 return FALSE;
650 }
651
652 outSize = ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
653 (DWORD)infoPtr->inbih, 0L);
654
655 infoPtr->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
656 if (!infoPtr->outbih) {
657 WARN("Can't alloc output BIH\n");
658 return FALSE;
659 }
660
661 if (ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
662 (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) {
663 WARN("Can't get output BIH\n");
664 return FALSE;
665 }
666
667 infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage);
668 if (!infoPtr->outdata) {
669 WARN("Can't alloc output buffer\n");
670 return FALSE;
671 }
672
673 if (ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
674 (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) {
675 WARN("Can't begin decompression\n");
676 return FALSE;
677 }
678
679 return TRUE;
680}
681
682#ifdef __WIN32OS2__
683static LRESULT ANIMATE_Open(HWND hWnd, WPARAM wParam, LPARAM lParam,BOOL unicode)
684#else
685static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam)
686#endif
687{
688 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
689 HINSTANCE hInstance = (HINSTANCE)wParam;
690
691 ANIMATE_Free(infoPtr);
692
693 if (!lParam) {
694 TRACE("Closing avi!\n");
695 return TRUE;
696 }
697
698 if (!hInstance)
699 hInstance = GetWindowLongA(hWnd, GWL_HINSTANCE);
700
701#ifdef __WIN32OS2__
702 if (HIWORD(lParam)) {
703 //TRACE("(\"%s\");\n", (LPSTR)lParam);
704
705 if (!ANIMATE_LoadRes(infoPtr, hInstance, (LPWSTR)lParam,unicode)) {
706 TRACE("No AVI resource found!\n");
707 if (!ANIMATE_LoadFile(infoPtr, (LPWSTR)lParam,unicode)) {
708 WARN("No AVI file found!\n");
709 return FALSE;
710 }
711 }
712 } else {
713 //TRACE("(%u);\n", (WORD)LOWORD(lParam));
714
715 if (!ANIMATE_LoadRes(infoPtr,hInstance,unicode ? MAKEINTRESOURCEW((INT)lParam):(LPWSTR)MAKEINTRESOURCEA((INT)lParam),unicode)) {
716 WARN("No AVI resource found!\n");
717 return FALSE;
718 }
719 }
720#else
721 if (HIWORD(lParam)) {
722 TRACE("(\"%s\");\n", (LPSTR)lParam);
723
724 if (!ANIMATE_LoadResA(infoPtr, hInstance, (LPSTR)lParam)) {
725 TRACE("No AVI resource found!\n");
726 if (!ANIMATE_LoadFileA(infoPtr, (LPSTR)lParam)) {
727 WARN("No AVI file found!\n");
728 return FALSE;
729 }
730 }
731 } else {
732 TRACE("(%u);\n", (WORD)LOWORD(lParam));
733
734 if (!ANIMATE_LoadResA(infoPtr, hInstance,
735 MAKEINTRESOURCEA((INT)lParam))) {
736 WARN("No AVI resource found!\n");
737 return FALSE;
738 }
739 }
740#endif
741 if (!ANIMATE_GetAviInfo(infoPtr)) {
742 WARN("Can't get AVI information\n");
743 ANIMATE_Free(infoPtr);
744 return FALSE;
745 }
746
747 if (!ANIMATE_GetAviCodec(infoPtr)) {
748 WARN("Can't get AVI Codec\n");
749 ANIMATE_Free(infoPtr);
750 return FALSE;
751 }
752
753 if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
754 SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
755 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
756 }
757
758 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) {
759 return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
760 }
761
762 return TRUE;
763}
764
765
766/* << ANIMATE_Open32W >> */
767
768static LRESULT ANIMATE_Stop(HWND hWnd, WPARAM wParam, LPARAM lParam)
769{
770 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
771
772 /* nothing opened */
773 if (!infoPtr->hMMio)
774 return FALSE;
775
776 ANIMATE_DoStop(infoPtr);
777 return TRUE;
778}
779
780
781static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam)
782{
783 ANIMATE_INFO* infoPtr;
784
785 /* allocate memory for info structure */
786#ifdef __WIN32OS2__
787 infoPtr = (ANIMATE_INFO*)initControl(hWnd,sizeof(ANIMATE_INFO));
788#else
789 infoPtr = (ANIMATE_INFO *)COMCTL32_Alloc(sizeof(ANIMATE_INFO));
790#endif
791 if (!infoPtr) {
792 ERR("could not allocate info memory!\n");
793 return 0;
794 }
795
796 TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd, GWL_STYLE), (DWORD)GetParent(hWnd));
797
798 /* store crossref hWnd <-> info structure */
799 SetWindowLongA(hWnd, 0, (DWORD)infoPtr);
800 infoPtr->hWnd = hWnd;
801 infoPtr->transparentColor = ANIMATE_COLOR_NONE;
802 infoPtr->hbmPrevFrame = 0;
803
804 InitializeCriticalSection(&infoPtr->cs);
805
806 return 0;
807}
808
809
810static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
811{
812 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
813
814
815 /* free avi data */
816 ANIMATE_Free(infoPtr);
817
818 /* free animate info data */
819 COMCTL32_Free(infoPtr);
820 SetWindowLongA(hWnd, 0, 0);
821
822 return 0;
823}
824
825
826static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam)
827{
828 RECT rect;
829 HBRUSH hBrush = 0;
830
831 if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
832 {
833 hBrush = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
834 }
835
836 GetClientRect(hWnd, &rect);
837 FillRect((HDC)wParam, &rect, hBrush ? hBrush : GetCurrentObject((HDC)wParam, OBJ_BRUSH));
838
839 return TRUE;
840}
841
842static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam)
843{
844 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
845 InvalidateRect(hWnd, NULL, TRUE);
846 }
847 return TRUE;
848}
849
850static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
851{
852 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam);
853 if (!ANIMATE_GetInfoPtr(hWnd) && (uMsg != WM_NCCREATE))
854 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
855 switch (uMsg)
856 {
857#ifdef __WIN32OS2__
858 case ACM_OPENA:
859 return ANIMATE_Open(hWnd,wParam,lParam,FALSE);
860
861 case ACM_OPENW:
862 return ANIMATE_Open(hWnd,wParam,lParam,TRUE);
863#else
864 case ACM_OPENA:
865 return ANIMATE_OpenA(hWnd, wParam, lParam);
866
867 /* case ACM_OPEN32W: FIXME!! */
868 /* return ANIMATE_Open32W(hWnd, wParam, lParam); */
869#endif
870
871 case ACM_PLAY:
872 return ANIMATE_Play(hWnd, wParam, lParam);
873
874 case ACM_STOP:
875 return ANIMATE_Stop(hWnd, wParam, lParam);
876
877 case WM_NCCREATE:
878 ANIMATE_Create(hWnd, wParam, lParam);
879 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
880
881 case WM_NCHITTEST:
882 return HTTRANSPARENT;
883
884 case WM_DESTROY:
885 ANIMATE_Destroy(hWnd, wParam, lParam);
886 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
887
888 case WM_ERASEBKGND:
889 ANIMATE_EraseBackground(hWnd, wParam, lParam);
890 break;
891
892 /* case WM_STYLECHANGED: FIXME shall we do something ?? */
893
894 case WM_TIMER:
895 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
896 {
897 ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
898 infoPtr->hbrushBG = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
899 }
900 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
901
902 case WM_CLOSE:
903 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd));
904 return TRUE;
905
906 case WM_PAINT:
907 {
908 ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
909
910 /* the animation isn't playing, don't paint */
911 if(!infoPtr->uTimer && !infoPtr->hThread)
912 /* default paint handling */
913 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
914
915 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
916 infoPtr->hbrushBG = SendMessageA(GetParent(hWnd), WM_CTLCOLORSTATIC,
917 (HDC)wParam, hWnd);
918
919 if (wParam)
920 {
921 EnterCriticalSection(&infoPtr->cs);
922 ANIMATE_PaintFrame(infoPtr, (HDC)wParam);
923 LeaveCriticalSection(&infoPtr->cs);
924 }
925 else
926 {
927 PAINTSTRUCT ps;
928 HDC hDC = BeginPaint(hWnd, &ps);
929
930 EnterCriticalSection(&infoPtr->cs);
931 ANIMATE_PaintFrame(infoPtr, hDC);
932 LeaveCriticalSection(&infoPtr->cs);
933
934 EndPaint(hWnd, &ps);
935 }
936 }
937 break;
938
939 case WM_SIZE:
940 ANIMATE_Size(hWnd, wParam, lParam);
941 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
942
943 default:
944 if (uMsg >= WM_USER)
945 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
946
947#ifdef __WIN32OS2__
948 return defComCtl32ProcA (hWnd, uMsg, wParam, lParam);
949#else
950 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
951#endif
952 }
953 return 0;
954}
955
956
957void ANIMATE_Register(void)
958{
959 WNDCLASSA wndClass;
960
961 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
962 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
963 wndClass.lpfnWndProc = (WNDPROC)ANIMATE_WindowProc;
964 wndClass.cbClsExtra = 0;
965 wndClass.cbWndExtra = sizeof(ANIMATE_INFO *);
966 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
967 wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
968 wndClass.lpszClassName = ANIMATE_CLASSA;
969
970 RegisterClassA(&wndClass);
971}
972
973
974void ANIMATE_Unregister(void)
975{
976 UnregisterClassA(ANIMATE_CLASSA, (HINSTANCE)NULL);
977}
978
Note: See TracBrowser for help on using the repository browser.