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

Last change on this file since 5280 was 4627, checked in by sandervl, 25 years ago

Resynched with Christoph's changes for unicode handling

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