source: trunk/src/comctl32/animate.cpp@ 3203

Last change on this file since 3203 was 3203, checked in by cbratschi, 25 years ago

dynamic WINMM linking

File size: 25.0 KB
Line 
1/* $Id: animate.cpp,v 1.2 2000-03-23 17:14:33 cbratschi Exp $ */
2/*
3 * Animation control
4 *
5 * Copyright 1998, 1999 Eric Kohl
6 * 1999 Eric Pouech
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 *
10 * Status: complete
11 * Version: 5.00
12 */
13
14#include "winbase.h"
15#include "commctrl.h"
16#include "comctl32.h"
17#include "driver.h"
18#include "mmsystem.h"
19#include "ccbase.h"
20#include "animate.h"
21
22HINSTANCE hMSVFW32 = 0;
23
24HINSTANCE hWINMM = 0;
25static LONG (*WINAPI WINMM_mmioRead)(HMMIO,HPSTR,LONG) = 0;
26static LONG (*WINAPI WINMM_mmioSeek)(HMMIO,LONG,INT) = 0;
27static MMRESULT (*WINAPI WINMM_mmioClose)(HMMIO,UINT) = 0;
28static HMMIO (*WINAPI WINMM_mmioOpenA)(LPSTR ,MMIOINFO*,DWORD) = 0;
29static HMMIO (*WINAPI WINMM_mmioOpenW)(LPWSTR,MMIOINFO*,DWORD) = 0;
30static UINT (*WINAPI WINMM_mmioDescend)(HMMIO,MMCKINFO*,const MMCKINFO*,UINT) = 0;
31static UINT (*WINAPI WINMM_mmioAscend)(HMMIO,MMCKINFO*,UINT) = 0;
32
33#define ANIMATE_GetInfoPtr(hwnd) ((ANIMATE_INFO*)getInfoPtr(hwnd))
34
35static BOOL ANIMATE_LoadMSVFW32(VOID)
36{
37 if (hMSVFW32) return TRUE;
38
39 hMSVFW32 = LoadLibraryA("msvfw32.dll");
40
41 return hMSVFW32;
42}
43
44static VOID ANIMATE_UnloadMSVFW32(VOID)
45{
46 if (hMSVFW32)
47 {
48 FreeLibrary(hMSVFW32);
49 hMSVFW32 = 0;
50 }
51}
52
53static BOOL ANIMATE_LoadWINMM(VOID)
54{
55 if (hWINMM) return TRUE;
56
57 hWINMM = LoadLibraryA("WINMM");
58 if (!hWINMM) return FALSE;
59
60 *(VOID**)&WINMM_mmioRead = (VOID*)GetProcAddress(hWINMM,"mmioRead");
61 *(VOID**)&WINMM_mmioSeek = (VOID*)GetProcAddress(hWINMM,"mmioSeek");
62 *(VOID**)&WINMM_mmioClose = (VOID*)GetProcAddress(hWINMM,"mmioClose");
63 *(VOID**)&WINMM_mmioOpenA = (VOID*)GetProcAddress(hWINMM,"mmioOpenA");
64 *(VOID**)&WINMM_mmioOpenW = (VOID*)GetProcAddress(hWINMM,"mmioOpenW");
65 *(VOID**)&WINMM_mmioDescend = (VOID*)GetProcAddress(hWINMM,"mmioDescend");
66 *(VOID**)&WINMM_mmioAscend = (VOID*)GetProcAddress(hWINMM,"mmioAscend");
67
68 return TRUE;
69}
70
71static VOID ANIMATE_UnloadWINMM(VOID)
72{
73 if (hWINMM)
74 {
75 FreeLibrary(hWINMM);
76 hWINMM = 0;
77 *(VOID**)&WINMM_mmioRead = NULL;
78 *(VOID**)&WINMM_mmioSeek = NULL;
79 *(VOID**)&WINMM_mmioClose = NULL;
80 *(VOID**)&WINMM_mmioOpenA = NULL;
81 *(VOID**)&WINMM_mmioOpenW = NULL;
82 *(VOID**)&WINMM_mmioDescend = NULL;
83 *(VOID**)&WINMM_mmioAscend = NULL;
84 }
85}
86
87static BOOL ANIMATE_LoadRes(ANIMATE_INFO *infoPtr,HINSTANCE hInst,LPWSTR lpName,BOOL unicode)
88{
89 HRSRC hrsrc;
90 MMIOINFO mminfo;
91 LPVOID lpAvi;
92
93 if (unicode)
94 hrsrc = FindResourceW(hInst,lpName,(LPWSTR)L"AVI");
95 else
96 hrsrc = FindResourceA(hInst,(LPCSTR)lpName,"AVI");
97 if (!hrsrc) return FALSE;
98
99 infoPtr->hRes = LoadResource(hInst, hrsrc);
100 if (!infoPtr->hRes)
101 return FALSE;
102
103 lpAvi = LockResource (infoPtr->hRes);
104 if (!lpAvi) return FALSE;
105
106 memset(&mminfo, 0, sizeof(mminfo));
107 mminfo.fccIOProc = FOURCC_MEM;
108 mminfo.pchBuffer = (LPSTR)lpAvi;
109 mminfo.cchBuffer = SizeofResource(hInst, hrsrc);
110 infoPtr->hMMio = WINMM_mmioOpenA(NULL, &mminfo, MMIO_READ);
111
112 if (!infoPtr->hMMio) {
113 GlobalFree((HGLOBAL)lpAvi);
114 return FALSE;
115 }
116
117 return TRUE;
118}
119
120static BOOL ANIMATE_LoadFile(ANIMATE_INFO *infoPtr,LPWSTR lpName,BOOL unicode)
121{
122 if (unicode)
123 infoPtr->hMMio = WINMM_mmioOpenW(lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
124 else
125 infoPtr->hMMio = WINMM_mmioOpenA((LPSTR)lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
126
127 if (!infoPtr->hMMio)
128 return FALSE;
129
130 return TRUE;
131}
132
133static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr)
134{
135 EnterCriticalSection(&infoPtr->cs);
136
137 /* should stop playing */
138 if (infoPtr->hThread)
139 {
140 infoPtr->stopThread = TRUE;
141 infoPtr->hThread = 0;
142 }
143 if (infoPtr->uTimer) {
144 KillTimer(infoPtr->hWnd, infoPtr->uTimer);
145 infoPtr->uTimer = 0;
146 }
147
148 LeaveCriticalSection(&infoPtr->cs);
149
150 sendCommand(infoPtr->hWnd,ACN_STOP);
151
152 return TRUE;
153}
154
155
156static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
157{
158 if (infoPtr->hMMio) {
159 ANIMATE_DoStop(infoPtr);
160 WINMM_mmioClose(infoPtr->hMMio, 0);
161 if (infoPtr->hRes) {
162 FreeResource(infoPtr->hRes);
163 infoPtr->hRes = 0;
164 }
165 if (infoPtr->lpIndex) {
166 HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex);
167 infoPtr->lpIndex = NULL;
168 }
169 if (infoPtr->hic) {
170 (infoPtr->fnICClose)(infoPtr->hic);
171 infoPtr->hic = 0;
172 }
173 if (infoPtr->inbih) {
174 HeapFree(GetProcessHeap(), 0, infoPtr->inbih);
175 infoPtr->inbih = NULL;
176 }
177 if (infoPtr->outbih) {
178 HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
179 infoPtr->outbih = NULL;
180 }
181 HeapFree(GetProcessHeap(), 0, infoPtr->indata);
182 HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
183 infoPtr->indata = infoPtr->outdata = NULL;
184 infoPtr->hWnd = 0;
185 infoPtr->hMMio = 0;
186 memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
187 memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
188 infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
189 }
190}
191
192
193static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC)
194{
195 if (!hDC || !infoPtr->inbih)
196 return TRUE;
197 if (infoPtr->hic)
198 StretchDIBits(hDC, 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
199 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
200 infoPtr->outdata, (LPBITMAPINFO)infoPtr->outbih, DIB_RGB_COLORS,
201 SRCCOPY);
202 else
203 StretchDIBits(hDC, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
204 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
205 infoPtr->indata, (LPBITMAPINFO)infoPtr->inbih, DIB_RGB_COLORS,
206 SRCCOPY);
207
208 return TRUE;
209}
210
211static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr)
212{
213 HDC hDC;
214
215 //TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop);
216
217 EnterCriticalSection(&infoPtr->cs);
218
219 WINMM_mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
220 WINMM_mmioRead(infoPtr->hMMio, (HPSTR)infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
221
222 if (infoPtr->hic &&
223 (infoPtr->fnICDecompress)(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
224 infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
225 LeaveCriticalSection(&infoPtr->cs);
226 //WARN("Decompression error\n");
227 return FALSE;
228 }
229
230 if ((hDC = GetDC(infoPtr->hWnd)) != 0) {
231 ANIMATE_PaintFrame(infoPtr, hDC);
232 ReleaseDC(infoPtr->hWnd, hDC);
233 }
234
235 if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
236 infoPtr->currFrame = infoPtr->nFromFrame;
237 if (infoPtr->nLoop != -1) {
238 if (--infoPtr->nLoop == 0) {
239 ANIMATE_DoStop(infoPtr);
240 }
241 }
242 }
243 LeaveCriticalSection(&infoPtr->cs);
244
245 return TRUE;
246}
247
248static DWORD ANIMATE_ThreadFunc(LPDWORD lpdwParam)
249{
250 HWND hwnd = (HWND)lpdwParam;
251 ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hwnd);
252
253 while (IsWindow(hwnd) && !infoPtr->stopThread)
254 {
255 EnterCriticalSection(&infoPtr->cs);
256 ANIMATE_DrawFrame(infoPtr);
257 LeaveCriticalSection(&infoPtr->cs);
258 Sleep(infoPtr->delay);
259 }
260
261 return 0;
262}
263
264static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
265{
266 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
267
268 /* nothing opened */
269 if (!infoPtr->hMMio)
270 return FALSE;
271
272 if (infoPtr->hThread || infoPtr->uTimer) {
273 //FIXME("Already playing ? what should I do ??\n");
274 ANIMATE_DoStop(infoPtr);
275 }
276
277 infoPtr->nFromFrame = (INT)LOWORD(lParam);
278 infoPtr->nToFrame = (INT)HIWORD(lParam);
279 infoPtr->nLoop = (INT)wParam;
280
281 if (infoPtr->nToFrame == 0xFFFF)
282 infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
283
284 //TRACE("(repeat=%d from=%d to=%d);\n",
285 // infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
286
287 if (infoPtr->nFromFrame >= infoPtr->nToFrame ||
288 infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
289 return FALSE;
290
291 infoPtr->currFrame = infoPtr->nFromFrame;
292
293 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) {
294 //TRACE("Using a timer\n");
295 /* create a timer to display AVI */
296 infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
297 } else
298 {
299 DWORD id;
300
301 //TRACE("Using the service thread\n");
302 infoPtr->stopThread = FALSE;
303 infoPtr->delay = infoPtr->mah.dwMicroSecPerFrame+500;
304 infoPtr->hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ANIMATE_ThreadFunc,(LPVOID)hWnd,0,&id);
305 }
306
307 sendCommand(infoPtr->hWnd,ACN_START);
308
309 return TRUE;
310}
311
312
313static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr)
314{
315 MMCKINFO ckMainRIFF;
316 MMCKINFO mmckHead;
317 MMCKINFO mmckList;
318 MMCKINFO mmckInfo;
319 DWORD numFrame;
320 DWORD insize;
321
322 if (WINMM_mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
323 //WARN("Can't find 'RIFF' chunk\n");
324 return FALSE;
325 }
326
327 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
328 (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
329 //WARN("Can't find 'AVI ' chunk\n");
330 return FALSE;
331 }
332
333 mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l');
334 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
335 //WARN("Can't find 'hdrl' list\n");
336 return FALSE;
337 }
338
339 mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
340 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
341 //WARN("Can't find 'avih' chunk\n");
342 return FALSE;
343 }
344
345 WINMM_mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
346 //TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr->mah.dwMicroSecPerFrame);
347 //TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr->mah.dwMaxBytesPerSec);
348 //TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr->mah.dwPaddingGranularity);
349 //TRACE("mah.dwFlags=%ld\n", infoPtr->mah.dwFlags);
350 //TRACE("mah.dwTotalFrames=%ld\n", infoPtr->mah.dwTotalFrames);
351 //TRACE("mah.dwInitialFrames=%ld\n", infoPtr->mah.dwInitialFrames);
352 //TRACE("mah.dwStreams=%ld\n", infoPtr->mah.dwStreams);
353 //TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr->mah.dwSuggestedBufferSize);
354 //TRACE("mah.dwWidth=%ld\n", infoPtr->mah.dwWidth);
355 //TRACE("mah.dwHeight=%ld\n", infoPtr->mah.dwHeight);
356 WINMM_mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
357
358 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
359 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
360 //WARN("Can't find 'strl' list\n");
361 return FALSE;
362 }
363
364 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
365 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
366 //WARN("Can't find 'strh' chunk\n");
367 return FALSE;
368 }
369
370 WINMM_mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
371 //TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)),
372 // HIBYTE(LOWORD(infoPtr->ash.fccType)),
373 // LOBYTE(HIWORD(infoPtr->ash.fccType)),
374 // HIBYTE(HIWORD(infoPtr->ash.fccType)));
375 //TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
376 // HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
377 // LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
378 // HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
379 //TRACE("ash.dwFlags=%ld\n", infoPtr->ash.dwFlags);
380 //TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority);
381 //TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage);
382 //TRACE("ash.dwInitialFrames=%ld\n", infoPtr->ash.dwInitialFrames);
383 //TRACE("ash.dwScale=%ld\n", infoPtr->ash.dwScale);
384 //TRACE("ash.dwRate=%ld\n", infoPtr->ash.dwRate);
385 //TRACE("ash.dwStart=%ld\n", infoPtr->ash.dwStart);
386 //TRACE("ash.dwLength=%ld\n", infoPtr->ash.dwLength);
387 //TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr->ash.dwSuggestedBufferSize);
388 //TRACE("ash.dwQuality=%ld\n", infoPtr->ash.dwQuality);
389 //TRACE("ash.dwSampleSize=%ld\n", infoPtr->ash.dwSampleSize);
390 //TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
391 // infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
392 WINMM_mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
393
394 mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
395 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
396 //WARN("Can't find 'strh' chunk\n");
397 return FALSE;
398 }
399
400 infoPtr->inbih = (BITMAPINFOHEADER*)HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
401 if (!infoPtr->inbih) {
402 //WARN("Can't alloc input BIH\n");
403 return FALSE;
404 }
405
406 WINMM_mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
407 //TRACE("bih.biSize=%ld\n", infoPtr->inbih->biSize);
408 //TRACE("bih.biWidth=%ld\n", infoPtr->inbih->biWidth);
409 //TRACE("bih.biHeight=%ld\n", infoPtr->inbih->biHeight);
410 //TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes);
411 //TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount);
412 //TRACE("bih.biCompression=%ld\n", infoPtr->inbih->biCompression);
413 //TRACE("bih.biSizeImage=%ld\n", infoPtr->inbih->biSizeImage);
414 //TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr->inbih->biXPelsPerMeter);
415 //TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr->inbih->biYPelsPerMeter);
416 //TRACE("bih.biClrUsed=%ld\n", infoPtr->inbih->biClrUsed);
417 //TRACE("bih.biClrImportant=%ld\n", infoPtr->inbih->biClrImportant);
418 WINMM_mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
419
420 WINMM_mmioAscend(infoPtr->hMMio, &mmckList, 0);
421
422#if 0
423 /* an AVI has 0 or 1 video stream, and to be animated should not contain
424 * an audio stream, so only one strl is allowed
425 */
426 mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
427 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
428 //WARN("There should be a single 'strl' list\n");
429 return FALSE;
430 }
431#endif
432
433 WINMM_mmioAscend(infoPtr->hMMio, &mmckHead, 0);
434
435 /* no need to read optional JUNK chunk */
436
437 mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
438 if (WINMM_mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
439 //WARN("Can't find 'movi' list\n");
440 return FALSE;
441 }
442
443 /* FIXME: should handle the 'rec ' LIST when present */
444
445 infoPtr->lpIndex = (DWORD*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
446 infoPtr->mah.dwTotalFrames * sizeof(DWORD));
447 if (!infoPtr->lpIndex) {
448 //WARN("Can't alloc index array\n");
449 return FALSE;
450 }
451
452 numFrame = insize = 0;
453 while (WINMM_mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
454 numFrame < infoPtr->mah.dwTotalFrames) {
455 infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
456 if (insize < mmckInfo.cksize)
457 insize = mmckInfo.cksize;
458 numFrame++;
459 WINMM_mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
460 }
461 if (numFrame != infoPtr->mah.dwTotalFrames) {
462 //WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames);
463 return FALSE;
464 }
465 if (insize > infoPtr->ash.dwSuggestedBufferSize) {
466 //WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize);
467 infoPtr->ash.dwSuggestedBufferSize = insize;
468 }
469
470 infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize);
471 if (!infoPtr->indata) {
472 //WARN("Can't alloc input buffer\n");
473 return FALSE;
474 }
475
476 return TRUE;
477}
478
479
480static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
481{
482 DWORD outSize;
483
484 /* check uncompressed AVI */
485 if (infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) {
486 infoPtr->hic = 0;
487 return TRUE;
488 }
489
490 /* try to get a decompressor for that type */
491 infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO,
492 infoPtr->ash.fccHandler,
493 ICMODE_DECOMPRESS);
494 if (!infoPtr->hic) {
495 //WARN("Can't load codec for the file\n");
496 return FALSE;
497 }
498
499 outSize = (infoPtr->fnICSendMessage)(infoPtr->hic,
500 ICM_DECOMPRESS_GET_FORMAT,
501 (DWORD)infoPtr->inbih, 0L);
502 infoPtr->outbih = (BITMAPINFOHEADER*)HeapAlloc(GetProcessHeap(), 0, outSize);
503 if (!infoPtr->outbih) {
504 //WARN("Can't alloc output BIH\n");
505 return FALSE;
506 }
507
508 if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
509 (DWORD)infoPtr->inbih,
510 (DWORD)infoPtr->outbih) != ICERR_OK) {
511 //WARN("Can't get output BIH\n");
512 return FALSE;
513 }
514
515 infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage);
516 if (!infoPtr->outdata) {
517 //WARN("Can't alloc output buffer\n");
518 return FALSE;
519 }
520
521 if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
522 (DWORD)infoPtr->inbih,
523 (DWORD)infoPtr->outbih) != ICERR_OK) {
524 //WARN("Can't begin decompression\n");
525 return FALSE;
526 }
527
528 return TRUE;
529}
530
531static LRESULT ANIMATE_Open(HWND hWnd, WPARAM wParam, LPARAM lParam,BOOL unicode)
532{
533 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
534 HINSTANCE hInstance = (HINSTANCE)wParam;
535
536 ANIMATE_Free(infoPtr);
537
538 if (!lParam) {
539 //TRACE("Closing avi!\n");
540 return TRUE;
541 }
542
543 if (!hInstance)
544 hInstance = GetWindowLongA(hWnd, GWL_HINSTANCE);
545
546 if (HIWORD(lParam)) {
547 //TRACE("(\"%s\");\n", (LPSTR)lParam);
548
549 if (!ANIMATE_LoadRes(infoPtr, hInstance, (LPWSTR)lParam,unicode)) {
550 //TRACE("No AVI resource found!\n");
551 if (!ANIMATE_LoadFile(infoPtr, (LPWSTR)lParam,unicode)) {
552 //WARN("No AVI file found!\n");
553 return FALSE;
554 }
555 }
556 } else {
557 //TRACE("(%u);\n", (WORD)LOWORD(lParam));
558
559 if (!ANIMATE_LoadRes(infoPtr,hInstance,unicode ? MAKEINTRESOURCEW((INT)lParam):(LPWSTR)MAKEINTRESOURCEA((INT)lParam),unicode)) {
560 //WARN("No AVI resource found!\n");
561 return FALSE;
562 }
563 }
564
565 if (!ANIMATE_GetAviInfo(infoPtr)) {
566 //WARN("Can't get AVI information\n");
567 ANIMATE_Free(infoPtr);
568 return FALSE;
569 }
570
571 if (!ANIMATE_GetAviCodec(infoPtr)) {
572 //WARN("Can't get AVI Codec\n");
573 ANIMATE_Free(infoPtr);
574 return FALSE;
575 }
576
577 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
578 //FIXME("ACS_CENTER: NIY\n");
579 } else {
580 /* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/
581 SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
582 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
583 }
584
585 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) {
586 //FIXME("ACS_TRANSPARENT: NIY\n");
587 }
588
589 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) {
590 return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
591 }
592
593 return TRUE;
594}
595
596static LRESULT ANIMATE_Stop(HWND hWnd, WPARAM wParam, LPARAM lParam)
597{
598 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
599
600 /* nothing opened */
601 if (!infoPtr->hMMio)
602 return FALSE;
603
604 ANIMATE_DoStop(infoPtr);
605 return TRUE;
606}
607
608
609static LRESULT ANIMATE_NCCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
610{
611 ANIMATE_INFO* infoPtr;
612
613 if (!ANIMATE_LoadWINMM()) return FALSE;
614 if (!ANIMATE_LoadMSVFW32()) return FALSE;
615
616 /* allocate memory for info structure */
617 infoPtr = (ANIMATE_INFO*)initControl(hWnd,sizeof(ANIMATE_INFO));
618 if (!infoPtr) {
619 //ERR("could not allocate info memory!\n");
620 return 0;
621 }
622
623 /* Temporary hack until we get dllglue up and running */
624 *(VOID**)&infoPtr->fnICOpen = (VOID*)GetProcAddress(hMSVFW32,"ICOpen");
625 *(VOID**)&infoPtr->fnICClose = (VOID*)GetProcAddress(hMSVFW32,"ICClose");
626 *(VOID**)&infoPtr->fnICSendMessage = (VOID*)GetProcAddress(hMSVFW32,"ICSendMessage");
627 *(VOID**)&infoPtr->fnICDecompress = (VOID*)GetProcAddress(hMSVFW32,"ICDecompress");
628
629 //TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd, GWL_STYLE), (DWORD)GetParent(hWnd));
630
631 /* store crossref hWnd <-> info structure */
632 infoPtr->hWnd = hWnd;
633
634 InitializeCriticalSection(&infoPtr->cs);
635 //RegisterDebugptr(&infoPtr->cs, "Animate infoPtr->cs");
636
637 return DefWindowProcA(hWnd,WM_NCCREATE,wParam,lParam);
638}
639
640static LRESULT ANIMATE_NCHitTest(HWND hwnd,WPARAM wParam,LPARAM lParam)
641{
642 return HTTRANSPARENT;
643}
644
645static LRESULT ANIMATE_Timer(HWND hWnd,WPARAM wParam,LPARAM lParam)
646{
647 return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
648}
649
650static LRESULT ANIMATE_Paint(HWND hWnd,WPARAM wParam,LPARAM lParam)
651{
652 if (wParam)
653 {
654 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), (HDC)wParam);
655 } else
656 {
657 PAINTSTRUCT ps;
658 HDC hDC = BeginPaint(hWnd, &ps);
659
660 ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), hDC);
661 EndPaint(hWnd, &ps);
662 }
663
664 return 0;
665}
666
667static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
668{
669 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
670
671
672 /* free avi data */
673 ANIMATE_Free(infoPtr);
674
675 /* free animate info data */
676 doneControl(hWnd);
677
678 return DefWindowProcA(hWnd,WM_DESTROY,wParam,lParam);
679}
680
681
682static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam)
683{
684 RECT rect;
685
686 GetClientRect(hWnd, &rect);
687#if 0
688 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
689
690 FillRect((HDC)wParam, &rect, hBrush);
691 DeleteObject(hBrush);
692#else
693 FillRect((HDC)wParam, &rect, GetSysColorBrush(COLOR_WINDOW));
694#endif
695 return TRUE;
696}
697
698static LRESULT WINAPI ANIMATE_Close(HWND hWnd, WPARAM wParam, LPARAM lParam)
699{
700 ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd));
701 return TRUE;
702}
703
704static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam)
705{
706 ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
707
708 if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
709 //FIXME("NIY\n");
710 if (infoPtr->hMMio) {
711 /* centers the animation in the control, invalidates the control
712 */
713 }
714 InvalidateRect(hWnd, NULL, TRUE);
715 }
716 return DefWindowProcA(hWnd,WM_SIZE,wParam,lParam);
717}
718
719static LRESULT ANIMATE_StyleChanged(HWND hwnd,WPARAM wParam,LPARAM lParam)
720{
721 //CB: todo
722
723 return 0;
724}
725
726static LRESULT WINAPI ANIMATE_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
727{
728 switch (uMsg)
729 {
730 case ACM_OPENA:
731 return ANIMATE_Open(hwnd,wParam,lParam,FALSE);
732
733 case ACM_OPENW:
734 return ANIMATE_Open(hwnd,wParam,lParam,TRUE);
735
736 case ACM_PLAY:
737 return ANIMATE_Play (hwnd, wParam, lParam);
738
739 case ACM_STOP:
740 return ANIMATE_Stop (hwnd, wParam, lParam);
741
742 case WM_CLOSE:
743 return ANIMATE_Close(hwnd,wParam,lParam);
744
745 case WM_NCCREATE:
746 return ANIMATE_NCCreate(hwnd,wParam,lParam);
747
748 case WM_DESTROY:
749 return ANIMATE_Destroy (hwnd, wParam, lParam);
750
751 case WM_ERASEBKGND:
752 return ANIMATE_EraseBackground (hwnd, wParam, lParam);
753
754 case WM_NCHITTEST:
755 return ANIMATE_NCHitTest(hwnd,wParam,lParam);
756
757 case WM_PAINT:
758 return ANIMATE_Paint(hwnd,wParam,lParam);
759
760 case WM_SIZE:
761 return ANIMATE_Size(hwnd,wParam,lParam);
762
763 case WM_STYLECHANGED:
764 return ANIMATE_StyleChanged(hwnd,wParam,lParam);
765
766 case WM_TIMER:
767 return ANIMATE_Timer(hwnd,wParam,lParam);
768
769 default:
770// if (uMsg >= WM_USER)
771// ERR (animate, "unknown msg %04x wp=%08x lp=%08lx\n",
772// uMsg, wParam, lParam);
773 return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
774 }
775
776 return 0;
777}
778
779
780VOID
781ANIMATE_Register (VOID)
782{
783 WNDCLASSA wndClass;
784
785 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
786 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
787 wndClass.lpfnWndProc = (WNDPROC)ANIMATE_WindowProc;
788 wndClass.cbClsExtra = 0;
789 wndClass.cbWndExtra = sizeof(ANIMATE_INFO *);
790 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
791 wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
792 wndClass.lpszClassName = ANIMATE_CLASSA;
793
794 RegisterClassA (&wndClass);
795}
796
797
798VOID
799ANIMATE_Unregister (VOID)
800{
801 UnregisterClassA (ANIMATE_CLASSA, (HINSTANCE)NULL);
802}
803
Note: See TracBrowser for help on using the repository browser.