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

Last change on this file since 6502 was 5630, checked in by sandervl, 24 years ago

wine resync

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