ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

animate.c
Go to the documentation of this file.
00001 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
00002 /*
00003  * Animation control
00004  *
00005  * Copyright 1998, 1999 Eric Kohl
00006  * Copyright 1999 Eric Pouech
00007  * Copyright 2005 Dimitrie O. Paun
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  *
00023  * NOTES
00024  *
00025  * This code was audited for completeness against the documented features
00026  * of Comctl32.dll version 6.0 on Mar. 15, 2005, by Dimitrie O. Paun.
00027  * 
00028  * Unless otherwise noted, we believe this code to be complete, as per
00029  * the specification mentioned above.
00030  * If you discover missing features, or bugs, please note them below.
00031  * 
00032  * TODO:
00033  *   - check for the 'rec ' list in some AVI files
00034  */
00035 
00036 #include <stdarg.h>
00037 #include <string.h>
00038 #include "windef.h"
00039 #include "winbase.h"
00040 #include "wingdi.h"
00041 #include "winuser.h"
00042 #include "winnls.h"
00043 #include "commctrl.h"
00044 #include "vfw.h"
00045 #include "mmsystem.h"
00046 #include "comctl32.h"
00047 #include "wine/debug.h"
00048 
00049 WINE_DEFAULT_DEBUG_CHANNEL(animate);
00050 
00051 static struct {
00052     HMODULE hModule;
00053     HIC         (WINAPI *fnICOpen)(DWORD, DWORD, UINT);
00054     LRESULT     (WINAPI *fnICClose)(HIC);
00055     LRESULT     (WINAPI *fnICSendMessage)(HIC, UINT, DWORD_PTR, DWORD_PTR);
00056     DWORD       (WINAPIV *fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER,LPVOID);
00057 } fnIC;
00058 
00059 typedef struct
00060 {
00061    /* reference to input stream (file or resource) */
00062    HGLOBAL      hRes;
00063    HMMIO        hMMio;  /* handle to mmio stream */
00064    HWND         hwndSelf;
00065    HWND         hwndNotify;
00066    DWORD        dwStyle;
00067    /* information on the loaded AVI file */
00068    MainAVIHeader    mah;
00069    AVIStreamHeader  ash;
00070    LPBITMAPINFOHEADER   inbih;
00071    LPDWORD      lpIndex;
00072    /* data for the decompressor */
00073    HIC          hic;
00074    LPBITMAPINFOHEADER   outbih;
00075    LPVOID       indata;
00076    LPVOID       outdata;
00077    /* data for the background mechanism */
00078    CRITICAL_SECTION cs;
00079    HANDLE       hStopEvent;
00080    HANDLE       hThread;
00081    DWORD        threadId;
00082    UINT         uTimer;
00083    /* data for playing the file */
00084    int          nFromFrame;
00085    int          nToFrame;
00086    int          nLoop;
00087    int          currFrame;
00088    /* transparency info*/
00089    COLORREF             transparentColor;
00090    HBRUSH               hbrushBG;
00091    HBITMAP              hbmPrevFrame;
00092 } ANIMATE_INFO;
00093 
00094 #define ANIMATE_COLOR_NONE      0xffffffff
00095 
00096 static void ANIMATE_Notify(const ANIMATE_INFO *infoPtr, UINT notif)
00097 {
00098     PostMessageW(infoPtr->hwndNotify, WM_COMMAND,
00099          MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), notif),
00100          (LPARAM)infoPtr->hwndSelf);
00101 }
00102 
00103 static BOOL ANIMATE_LoadResW(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPCWSTR lpName)
00104 {
00105     static const WCHAR aviW[] = { 'A', 'V', 'I', 0 };
00106     HRSRC   hrsrc;
00107     MMIOINFO    mminfo;
00108     LPVOID  lpAvi;
00109 
00110     hrsrc = FindResourceW(hInst, lpName, aviW);
00111     if (!hrsrc)
00112     return FALSE;
00113 
00114     infoPtr->hRes = LoadResource(hInst, hrsrc);
00115     if (!infoPtr->hRes)
00116     return FALSE;
00117 
00118     lpAvi = LockResource(infoPtr->hRes);
00119     if (!lpAvi)
00120     return FALSE;
00121 
00122     memset(&mminfo, 0, sizeof(mminfo));
00123     mminfo.fccIOProc = FOURCC_MEM;
00124     mminfo.pchBuffer = lpAvi;
00125     mminfo.cchBuffer = SizeofResource(hInst, hrsrc);
00126     infoPtr->hMMio = mmioOpenW(NULL, &mminfo, MMIO_READ);
00127     if (!infoPtr->hMMio) 
00128     {
00129     FreeResource(infoPtr->hRes);
00130     return FALSE;
00131     }
00132 
00133     return TRUE;
00134 }
00135 
00136 
00137 static BOOL ANIMATE_LoadFileW(ANIMATE_INFO *infoPtr, LPWSTR lpName)
00138 {
00139     infoPtr->hMMio = mmioOpenW(lpName, 0, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
00140 
00141     if(!infoPtr->hMMio) return FALSE;
00142     return TRUE;
00143 }
00144 
00145 
00146 static BOOL ANIMATE_DoStop(ANIMATE_INFO *infoPtr)
00147 {
00148     BOOL stopped = FALSE;
00149 
00150     EnterCriticalSection(&infoPtr->cs);
00151 
00152     /* should stop playing */
00153     if (infoPtr->hThread)
00154     {
00155         HANDLE handle = infoPtr->hThread;
00156 
00157         TRACE("stopping animation thread\n");
00158         infoPtr->hThread = 0;
00159         SetEvent( infoPtr->hStopEvent );
00160 
00161         if (infoPtr->threadId != GetCurrentThreadId())
00162         {
00163             LeaveCriticalSection(&infoPtr->cs);  /* leave it a chance to run */
00164             WaitForSingleObject( handle, INFINITE );
00165             TRACE("animation thread stopped\n");
00166             EnterCriticalSection(&infoPtr->cs);
00167         }
00168 
00169         CloseHandle( handle );
00170         CloseHandle( infoPtr->hStopEvent );
00171         infoPtr->hStopEvent = 0;
00172         stopped = TRUE;
00173     }
00174     if (infoPtr->uTimer) {
00175     KillTimer(infoPtr->hwndSelf, infoPtr->uTimer);
00176     infoPtr->uTimer = 0;
00177     stopped = TRUE;
00178     }
00179 
00180     LeaveCriticalSection(&infoPtr->cs);
00181 
00182     if (stopped)
00183         ANIMATE_Notify(infoPtr, ACN_STOP);
00184 
00185     return TRUE;
00186 }
00187 
00188 
00189 static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
00190 {
00191     if (infoPtr->hMMio) {
00192     ANIMATE_DoStop(infoPtr);
00193     mmioClose(infoPtr->hMMio, 0);
00194     if (infoPtr->hRes) {
00195         FreeResource(infoPtr->hRes);
00196         infoPtr->hRes = 0;
00197     }
00198         Free (infoPtr->lpIndex);
00199         infoPtr->lpIndex = NULL;
00200     if (infoPtr->hic) {
00201         fnIC.fnICClose(infoPtr->hic);
00202         infoPtr->hic = 0;
00203     }
00204         Free (infoPtr->inbih);
00205         infoPtr->inbih = NULL;
00206         Free (infoPtr->outbih);
00207         infoPtr->outbih = NULL;
00208     Free (infoPtr->indata);
00209         infoPtr->indata = NULL;
00210     Free (infoPtr->outdata);
00211         infoPtr->outdata = NULL;
00212         if( infoPtr->hbmPrevFrame )
00213         {
00214         DeleteObject(infoPtr->hbmPrevFrame);
00215             infoPtr->hbmPrevFrame = 0;
00216         }
00217 
00218     memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
00219     memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
00220     infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
00221     }
00222     infoPtr->transparentColor = ANIMATE_COLOR_NONE;
00223 }
00224 
00225 static void ANIMATE_TransparentBlt(ANIMATE_INFO const *infoPtr, HDC hdcDest, HDC hdcSource)
00226 {
00227     HDC hdcMask;
00228     HBITMAP hbmMask;
00229     HBITMAP hbmOld;
00230 
00231     /* create a transparency mask */
00232     hdcMask = CreateCompatibleDC(hdcDest);
00233     hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL);
00234     hbmOld = SelectObject(hdcMask, hbmMask);
00235 
00236     SetBkColor(hdcSource,infoPtr->transparentColor);
00237     BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY);
00238 
00239     /* mask the source bitmap */
00240     SetBkColor(hdcSource, RGB(0,0,0));
00241     SetTextColor(hdcSource, RGB(255,255,255));
00242     BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
00243 
00244     /* mask the destination bitmap */
00245     SetBkColor(hdcDest, RGB(255,255,255));
00246     SetTextColor(hdcDest, RGB(0,0,0));
00247     BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
00248 
00249     /* combine source and destination */
00250     BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT);
00251 
00252     SelectObject(hdcMask, hbmOld);
00253     DeleteObject(hbmMask);
00254     DeleteDC(hdcMask);
00255 }
00256 
00257 static BOOL ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC)
00258 {
00259     void const *pBitmapData;
00260     BITMAPINFO const *pBitmapInfo;
00261     HDC hdcMem;
00262     HBITMAP hbmOld;
00263     int nOffsetX = 0;
00264     int nOffsetY = 0;
00265     int nWidth;
00266     int nHeight;
00267 
00268     if (!hDC || !infoPtr->inbih)
00269     return TRUE;
00270 
00271     if (infoPtr->hic )
00272     {
00273         pBitmapData = infoPtr->outdata;
00274         pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih;
00275 
00276         nWidth = infoPtr->outbih->biWidth;
00277         nHeight = infoPtr->outbih->biHeight;
00278     } 
00279     else
00280     {
00281         pBitmapData = infoPtr->indata;
00282         pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih;
00283 
00284         nWidth = infoPtr->inbih->biWidth;
00285         nHeight = infoPtr->inbih->biHeight;
00286     }
00287 
00288     if(!infoPtr->hbmPrevFrame)
00289     {
00290         infoPtr->hbmPrevFrame=CreateCompatibleBitmap(hDC, nWidth,nHeight );
00291     }
00292 
00293     hdcMem = CreateCompatibleDC(hDC);
00294     hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame);
00295 
00296     SetDIBits(hdcMem, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS);
00297 
00298     /*
00299      * we need to get the transparent color even without ACS_TRANSPARENT,
00300      * because the style can be changed later on and the color should always
00301      * be obtained in the first frame
00302      */
00303     if(infoPtr->transparentColor == ANIMATE_COLOR_NONE)
00304     {
00305         infoPtr->transparentColor = GetPixel(hdcMem,0,0);
00306     }
00307 
00308     if(infoPtr->dwStyle & ACS_TRANSPARENT)
00309     {
00310         HDC hdcFinal = CreateCompatibleDC(hDC);
00311         HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight);
00312         HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal);
00313         RECT rect;
00314 
00315         rect.left = 0;
00316         rect.top = 0;
00317         rect.right = nWidth;
00318         rect.bottom = nHeight;
00319 
00320         if(!infoPtr->hbrushBG)
00321             infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH);
00322 
00323         FillRect(hdcFinal, &rect, infoPtr->hbrushBG);
00324         ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem);
00325 
00326         SelectObject(hdcFinal, hbmOld2);
00327         SelectObject(hdcMem, hbmFinal);
00328         DeleteDC(hdcFinal);
00329         DeleteObject(infoPtr->hbmPrevFrame);
00330         infoPtr->hbmPrevFrame = hbmFinal;
00331     }
00332 
00333     if (infoPtr->dwStyle & ACS_CENTER)
00334     {
00335         RECT rect;
00336 
00337         GetWindowRect(infoPtr->hwndSelf, &rect);
00338         nOffsetX = ((rect.right - rect.left) - nWidth)/2;
00339         nOffsetY = ((rect.bottom - rect.top) - nHeight)/2;
00340     }
00341     BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
00342 
00343     SelectObject(hdcMem, hbmOld);
00344     DeleteDC(hdcMem);
00345     return TRUE;
00346 }
00347 
00348 static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr, HDC hDC)
00349 {
00350     TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop);
00351 
00352     mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
00353     mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
00354 
00355     if (infoPtr->hic &&
00356     fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
00357              infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
00358     WARN("Decompression error\n");
00359     return FALSE;
00360     }
00361 
00362     ANIMATE_PaintFrame(infoPtr, hDC);
00363 
00364     if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
00365     infoPtr->currFrame = infoPtr->nFromFrame;
00366     if (infoPtr->nLoop != -1) {
00367         if (--infoPtr->nLoop == 0) {
00368         ANIMATE_DoStop(infoPtr);
00369         }
00370     }
00371     }
00372 
00373     return TRUE;
00374 }
00375 
00376 static LRESULT ANIMATE_Timer(ANIMATE_INFO *infoPtr)
00377 {
00378     HDC hDC;
00379 
00380     if ((hDC = GetDC(infoPtr->hwndSelf)) != 0)
00381     {
00382         EnterCriticalSection(&infoPtr->cs);
00383         ANIMATE_DrawFrame(infoPtr, hDC);
00384         LeaveCriticalSection(&infoPtr->cs);
00385 
00386     ReleaseDC(infoPtr->hwndSelf, hDC);
00387     }
00388 
00389     return 0;
00390 }
00391 
00392 static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_)
00393 {
00394     ANIMATE_INFO *infoPtr = ptr_;
00395     HANDLE event;
00396     DWORD timeout;
00397 
00398     while(1)
00399     {
00400         HDC hDC = GetDC(infoPtr->hwndSelf);
00401 
00402         EnterCriticalSection(&infoPtr->cs);
00403         ANIMATE_DrawFrame(infoPtr, hDC);
00404         timeout = infoPtr->mah.dwMicroSecPerFrame;
00405         event = infoPtr->hStopEvent;
00406         LeaveCriticalSection(&infoPtr->cs);
00407 
00408         ReleaseDC(infoPtr->hwndSelf, hDC);
00409 
00410         /* time is in microseconds, we should convert it to milliseconds */
00411         if ((event == 0) || WaitForSingleObject( event, (timeout+500)/1000) == WAIT_OBJECT_0)
00412             break;
00413     }
00414     return TRUE;
00415 }
00416 
00417 static LRESULT ANIMATE_Play(ANIMATE_INFO *infoPtr, UINT cRepeat, WORD wFrom, WORD wTo)
00418 {
00419     /* nothing opened */
00420     if (!infoPtr->hMMio)
00421     return FALSE;
00422 
00423     if (infoPtr->hThread || infoPtr->uTimer) {
00424     TRACE("Already playing\n");
00425     return TRUE;
00426     }
00427 
00428     infoPtr->nFromFrame = wFrom;
00429     infoPtr->nToFrame   = wTo;
00430     infoPtr->nLoop      = cRepeat;
00431 
00432     if (infoPtr->nToFrame == 0xFFFF)
00433     infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
00434 
00435     TRACE("(repeat=%d from=%d to=%d);\n",
00436       infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
00437 
00438     if (infoPtr->nFromFrame >= infoPtr->mah.dwTotalFrames &&
00439         (SHORT)infoPtr->nFromFrame < 0)
00440         infoPtr->nFromFrame = 0;
00441 
00442     if (infoPtr->nFromFrame > infoPtr->nToFrame ||
00443     infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
00444     return FALSE;
00445 
00446     infoPtr->currFrame = infoPtr->nFromFrame;
00447 
00448     /* seek - doesn't need to start a thread or set a timer and neither
00449      * does it send a notification */
00450     if (infoPtr->nFromFrame == infoPtr->nToFrame)
00451     {
00452         HDC hDC;
00453 
00454         if ((hDC = GetDC(infoPtr->hwndSelf)) != 0)
00455         {
00456             ANIMATE_DrawFrame(infoPtr, hDC);
00457 
00458         ReleaseDC(infoPtr->hwndSelf, hDC);
00459         }
00460         return TRUE;
00461     }
00462 
00463     if (infoPtr->dwStyle & ACS_TIMER) 
00464     {
00465     TRACE("Using a timer\n");
00466     /* create a timer to display AVI */
00467     infoPtr->uTimer = SetTimer(infoPtr->hwndSelf, 1, 
00468                                    infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
00469     } 
00470     else 
00471     {
00472     TRACE("Using an animation thread\n");
00473         infoPtr->hStopEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
00474         infoPtr->hThread = CreateThread(0, 0, ANIMATE_AnimationThread,
00475                                         infoPtr, 0, &infoPtr->threadId);
00476         if(!infoPtr->hThread) return FALSE;
00477 
00478     }
00479 
00480     ANIMATE_Notify(infoPtr, ACN_START);
00481 
00482     return TRUE;
00483 }
00484 
00485 
00486 static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr)
00487 {
00488     MMCKINFO        ckMainRIFF;
00489     MMCKINFO        mmckHead;
00490     MMCKINFO        mmckList;
00491     MMCKINFO        mmckInfo;
00492     DWORD       numFrame;
00493     DWORD       insize;
00494 
00495     if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
00496     WARN("Can't find 'RIFF' chunk\n");
00497     return FALSE;
00498     }
00499 
00500     if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
00501     (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
00502     WARN("Can't find 'AVI ' chunk\n");
00503     return FALSE;
00504     }
00505 
00506     mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l');
00507     if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
00508     WARN("Can't find 'hdrl' list\n");
00509     return FALSE;
00510     }
00511 
00512     mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
00513     if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
00514     WARN("Can't find 'avih' chunk\n");
00515     return FALSE;
00516     }
00517 
00518     mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
00519 
00520     TRACE("mah.dwMicroSecPerFrame=%d\n",    infoPtr->mah.dwMicroSecPerFrame);
00521     TRACE("mah.dwMaxBytesPerSec=%d\n",      infoPtr->mah.dwMaxBytesPerSec);
00522     TRACE("mah.dwPaddingGranularity=%d\n",  infoPtr->mah.dwPaddingGranularity);
00523     TRACE("mah.dwFlags=%d\n",           infoPtr->mah.dwFlags);
00524     TRACE("mah.dwTotalFrames=%d\n",     infoPtr->mah.dwTotalFrames);
00525     TRACE("mah.dwInitialFrames=%d\n",       infoPtr->mah.dwInitialFrames);
00526     TRACE("mah.dwStreams=%d\n",         infoPtr->mah.dwStreams);
00527     TRACE("mah.dwSuggestedBufferSize=%d\n", infoPtr->mah.dwSuggestedBufferSize);
00528     TRACE("mah.dwWidth=%d\n",           infoPtr->mah.dwWidth);
00529     TRACE("mah.dwHeight=%d\n",          infoPtr->mah.dwHeight);
00530 
00531     mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
00532 
00533     mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
00534     if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
00535     WARN("Can't find 'strl' list\n");
00536     return FALSE;
00537     }
00538 
00539     mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
00540     if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
00541     WARN("Can't find 'strh' chunk\n");
00542     return FALSE;
00543     }
00544 
00545     mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
00546 
00547     TRACE("ash.fccType='%c%c%c%c'\n",       LOBYTE(LOWORD(infoPtr->ash.fccType)),
00548                                             HIBYTE(LOWORD(infoPtr->ash.fccType)),
00549                                             LOBYTE(HIWORD(infoPtr->ash.fccType)),
00550                                             HIBYTE(HIWORD(infoPtr->ash.fccType)));
00551     TRACE("ash.fccHandler='%c%c%c%c'\n",    LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
00552                                             HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
00553                                             LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
00554                                             HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
00555     TRACE("ash.dwFlags=%d\n",           infoPtr->ash.dwFlags);
00556     TRACE("ash.wPriority=%d\n",         infoPtr->ash.wPriority);
00557     TRACE("ash.wLanguage=%d\n",         infoPtr->ash.wLanguage);
00558     TRACE("ash.dwInitialFrames=%d\n",       infoPtr->ash.dwInitialFrames);
00559     TRACE("ash.dwScale=%d\n",           infoPtr->ash.dwScale);
00560     TRACE("ash.dwRate=%d\n",            infoPtr->ash.dwRate);
00561     TRACE("ash.dwStart=%d\n",           infoPtr->ash.dwStart);
00562     TRACE("ash.dwLength=%d\n",          infoPtr->ash.dwLength);
00563     TRACE("ash.dwSuggestedBufferSize=%d\n",     infoPtr->ash.dwSuggestedBufferSize);
00564     TRACE("ash.dwQuality=%d\n",         infoPtr->ash.dwQuality);
00565     TRACE("ash.dwSampleSize=%d\n",      infoPtr->ash.dwSampleSize);
00566     TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",    infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
00567       infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
00568 
00569     mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
00570 
00571     mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
00572     if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
00573     WARN("Can't find 'strh' chunk\n");
00574     return FALSE;
00575     }
00576 
00577     infoPtr->inbih = Alloc(mmckInfo.cksize);
00578     if (!infoPtr->inbih) {
00579     WARN("Can't alloc input BIH\n");
00580     return FALSE;
00581     }
00582 
00583     mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
00584 
00585     TRACE("bih.biSize=%d\n",        infoPtr->inbih->biSize);
00586     TRACE("bih.biWidth=%d\n",       infoPtr->inbih->biWidth);
00587     TRACE("bih.biHeight=%d\n",      infoPtr->inbih->biHeight);
00588     TRACE("bih.biPlanes=%d\n",      infoPtr->inbih->biPlanes);
00589     TRACE("bih.biBitCount=%d\n",    infoPtr->inbih->biBitCount);
00590     TRACE("bih.biCompression=%d\n",     infoPtr->inbih->biCompression);
00591     TRACE("bih.biSizeImage=%d\n",   infoPtr->inbih->biSizeImage);
00592     TRACE("bih.biXPelsPerMeter=%d\n",   infoPtr->inbih->biXPelsPerMeter);
00593     TRACE("bih.biYPelsPerMeter=%d\n",   infoPtr->inbih->biYPelsPerMeter);
00594     TRACE("bih.biClrUsed=%d\n",     infoPtr->inbih->biClrUsed);
00595     TRACE("bih.biClrImportant=%d\n",    infoPtr->inbih->biClrImportant);
00596 
00597     mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
00598 
00599     mmioAscend(infoPtr->hMMio, &mmckList, 0);
00600 
00601 #if 0
00602     /* an AVI has 0 or 1 video stream, and to be animated should not contain
00603      * an audio stream, so only one strl is allowed
00604      */
00605     mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
00606     if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
00607     WARN("There should be a single 'strl' list\n");
00608     return FALSE;
00609     }
00610 #endif
00611 
00612     mmioAscend(infoPtr->hMMio, &mmckHead, 0);
00613 
00614     /* no need to read optional JUNK chunk */
00615 
00616     mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
00617     if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
00618     WARN("Can't find 'movi' list\n");
00619     return FALSE;
00620     }
00621 
00622     /* FIXME: should handle the 'rec ' LIST when present */
00623 
00624     infoPtr->lpIndex = Alloc(infoPtr->mah.dwTotalFrames * sizeof(DWORD));
00625     if (!infoPtr->lpIndex) 
00626     return FALSE;
00627 
00628     numFrame = insize = 0;
00629     while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
00630        numFrame < infoPtr->mah.dwTotalFrames) {
00631     infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
00632     if (insize < mmckInfo.cksize)
00633         insize = mmckInfo.cksize;
00634     numFrame++;
00635     mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
00636     }
00637     if (numFrame != infoPtr->mah.dwTotalFrames) {
00638     WARN("Found %d frames (/%d)\n", numFrame, infoPtr->mah.dwTotalFrames);
00639     return FALSE;
00640     }
00641     if (insize > infoPtr->ash.dwSuggestedBufferSize) {
00642     WARN("insize=%d suggestedSize=%d\n", insize, infoPtr->ash.dwSuggestedBufferSize);
00643     infoPtr->ash.dwSuggestedBufferSize = insize;
00644     }
00645 
00646     infoPtr->indata = Alloc(infoPtr->ash.dwSuggestedBufferSize);
00647     if (!infoPtr->indata) 
00648     return FALSE;
00649 
00650     return TRUE;
00651 }
00652 
00653 
00654 static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
00655 {
00656     DWORD   outSize;
00657 
00658     /* check uncompressed AVI */
00659     if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) ||
00660        (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) ||
00661        (infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0)))
00662     {
00663         infoPtr->hic = 0;
00664     return TRUE;
00665     }
00666 
00667     /* try to get a decompressor for that type */
00668     infoPtr->hic = fnIC.fnICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS);
00669     if (!infoPtr->hic) {
00670     WARN("Can't load codec for the file\n");
00671     return FALSE;
00672     }
00673 
00674     outSize = fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
00675                 (DWORD_PTR)infoPtr->inbih, 0L);
00676 
00677     infoPtr->outbih = Alloc(outSize);
00678     if (!infoPtr->outbih)
00679     return FALSE;
00680 
00681     if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
00682               (DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK) 
00683     {
00684     WARN("Can't get output BIH\n");
00685     return FALSE;
00686     }
00687 
00688     infoPtr->outdata = Alloc(infoPtr->outbih->biSizeImage);
00689     if (!infoPtr->outdata) 
00690     return FALSE;
00691 
00692     if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
00693               (DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK) {
00694     WARN("Can't begin decompression\n");
00695     return FALSE;
00696     }
00697 
00698     return TRUE;
00699 }
00700 
00701 
00702 static BOOL ANIMATE_OpenW(ANIMATE_INFO *infoPtr, HINSTANCE hInstance, LPWSTR lpszName)
00703 {
00704     HDC hdc;
00705 
00706     ANIMATE_Free(infoPtr);
00707 
00708     if (!lpszName) 
00709     {
00710     TRACE("Closing avi!\n");
00711         /* installer of thebat! v1.62 requires FALSE here */
00712     return (infoPtr->hMMio != 0);
00713     }
00714 
00715     if (!hInstance)
00716         hInstance = (HINSTANCE)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_HINSTANCE);
00717 
00718     TRACE("(%s)\n", debugstr_w(lpszName));
00719 
00720     if (!IS_INTRESOURCE(lpszName))
00721     {
00722     if (!ANIMATE_LoadResW(infoPtr, hInstance, lpszName)) 
00723         {
00724         TRACE("No AVI resource found!\n");
00725         if (!ANIMATE_LoadFileW(infoPtr, lpszName)) 
00726             {
00727         WARN("No AVI file found!\n");
00728         return FALSE;
00729         }
00730     }
00731     } 
00732     else 
00733     {
00734     if (!ANIMATE_LoadResW(infoPtr, hInstance, lpszName))
00735         {
00736         WARN("No AVI resource found!\n");
00737         return FALSE;
00738     }
00739     }
00740 
00741     if (!ANIMATE_GetAviInfo(infoPtr)) 
00742     {
00743     WARN("Can't get AVI information\n");
00744     ANIMATE_Free(infoPtr);
00745     return FALSE;
00746     }
00747 
00748     if (!ANIMATE_GetAviCodec(infoPtr)) 
00749     {
00750     WARN("Can't get AVI Codec\n");
00751     ANIMATE_Free(infoPtr);
00752     return FALSE;
00753     }
00754 
00755     hdc = GetDC(infoPtr->hwndSelf);
00756     /* native looks at the top left pixel of the first frame here too. */
00757     infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLORSTATIC,
00758                                              (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
00759     ReleaseDC(infoPtr->hwndSelf, hdc);
00760 
00761     if (!(infoPtr->dwStyle & ACS_CENTER))
00762     SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
00763              SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
00764 
00765     if (infoPtr->dwStyle & ACS_AUTOPLAY) 
00766     return ANIMATE_Play(infoPtr, -1, 0, infoPtr->mah.dwTotalFrames - 1);
00767 
00768     return TRUE;
00769 }
00770 
00771 
00772 static BOOL ANIMATE_OpenA(ANIMATE_INFO *infoPtr, HINSTANCE hInstance, LPSTR lpszName)
00773 {
00774     LPWSTR lpwszName;
00775     LRESULT result;
00776     INT len;
00777 
00778     if (IS_INTRESOURCE(lpszName))
00779         return ANIMATE_OpenW(infoPtr, hInstance, (LPWSTR)lpszName);
00780 
00781     len = MultiByteToWideChar(CP_ACP, 0, lpszName, -1, NULL, 0);
00782     lpwszName = Alloc(len * sizeof(WCHAR));
00783     if (!lpwszName) return FALSE;
00784     MultiByteToWideChar(CP_ACP, 0, lpszName, -1, lpwszName, len);
00785 
00786     result = ANIMATE_OpenW(infoPtr, hInstance, lpwszName);
00787     Free (lpwszName);
00788     return result;
00789 }
00790 
00791 
00792 static BOOL ANIMATE_Stop(ANIMATE_INFO *infoPtr)
00793 {
00794     /* nothing opened */
00795     if (!infoPtr->hMMio)
00796     return FALSE;
00797 
00798     ANIMATE_DoStop(infoPtr);
00799     return TRUE;
00800 }
00801 
00802 
00803 static BOOL ANIMATE_Create(HWND hWnd, const CREATESTRUCTW *lpcs)
00804 {
00805     static const WCHAR msvfw32W[] = { 'm', 's', 'v', 'f', 'w', '3', '2', '.', 'd', 'l', 'l', 0 };
00806     ANIMATE_INFO *infoPtr;
00807 
00808     if (!fnIC.hModule)
00809     {
00810     fnIC.hModule = LoadLibraryW(msvfw32W);
00811     if (!fnIC.hModule) return FALSE;
00812 
00813     fnIC.fnICOpen        = (void*)GetProcAddress(fnIC.hModule, "ICOpen");
00814     fnIC.fnICClose       = (void*)GetProcAddress(fnIC.hModule, "ICClose");
00815     fnIC.fnICSendMessage = (void*)GetProcAddress(fnIC.hModule, "ICSendMessage");
00816     fnIC.fnICDecompress  = (void*)GetProcAddress(fnIC.hModule, "ICDecompress");
00817     }
00818 
00819     /* allocate memory for info structure */
00820     infoPtr = Alloc(sizeof(ANIMATE_INFO));
00821     if (!infoPtr) return FALSE;
00822 
00823     /* store crossref hWnd <-> info structure */
00824     SetWindowLongPtrW(hWnd, 0, (DWORD_PTR)infoPtr);
00825     infoPtr->hwndSelf = hWnd;
00826     infoPtr->hwndNotify = lpcs->hwndParent;
00827     infoPtr->transparentColor = ANIMATE_COLOR_NONE;
00828     infoPtr->hbmPrevFrame = 0;
00829     infoPtr->dwStyle = lpcs->style;
00830 
00831     TRACE("Animate style=0x%08x, parent=%p\n", infoPtr->dwStyle, infoPtr->hwndNotify);
00832 
00833     InitializeCriticalSection(&infoPtr->cs);
00834     infoPtr->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ANIMATE_INFO*->cs");
00835 
00836     return TRUE;
00837 }
00838 
00839 
00840 static LRESULT ANIMATE_Destroy(ANIMATE_INFO *infoPtr)
00841 {
00842     /* free avi data */
00843     ANIMATE_Free(infoPtr);
00844 
00845     /* free animate info data */
00846     SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
00847 
00848     infoPtr->cs.DebugInfo->Spare[0] = 0;
00849     DeleteCriticalSection(&infoPtr->cs);
00850     Free(infoPtr);
00851 
00852     return 0;
00853 }
00854 
00855 
00856 static BOOL ANIMATE_EraseBackground(ANIMATE_INFO const *infoPtr, HDC hdc)
00857 {
00858     RECT rect;
00859     HBRUSH hBrush;
00860 
00861     hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLORSTATIC,
00862                                   (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
00863     GetClientRect(infoPtr->hwndSelf, &rect);
00864     FillRect(hdc, &rect, hBrush ? hBrush : GetCurrentObject(hdc, OBJ_BRUSH));
00865 
00866     return TRUE;
00867 }
00868 
00869 
00870 static LRESULT ANIMATE_StyleChanged(ANIMATE_INFO *infoPtr, WPARAM wStyleType, const STYLESTRUCT *lpss)
00871 {
00872     TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
00873           wStyleType, lpss->styleOld, lpss->styleNew);
00874 
00875     if (wStyleType != GWL_STYLE) return 0;
00876   
00877     infoPtr->dwStyle = lpss->styleNew;
00878 
00879     InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
00880     return 0;
00881 }
00882 
00883 
00884 static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00885 {
00886     ANIMATE_INFO *infoPtr = (ANIMATE_INFO *)GetWindowLongPtrW(hWnd, 0);
00887 
00888     TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hWnd, uMsg, wParam, lParam);
00889     if (!infoPtr && (uMsg != WM_NCCREATE))
00890     return DefWindowProcW(hWnd, uMsg, wParam, lParam);
00891     switch (uMsg)
00892     {
00893     case ACM_OPENA:
00894     return ANIMATE_OpenA(infoPtr, (HINSTANCE)wParam, (LPSTR)lParam);
00895 
00896     case ACM_OPENW:
00897     return ANIMATE_OpenW(infoPtr, (HINSTANCE)wParam, (LPWSTR)lParam);
00898 
00899     case ACM_PLAY:
00900     return ANIMATE_Play(infoPtr, (INT)wParam, LOWORD(lParam), HIWORD(lParam));
00901 
00902     case ACM_STOP:
00903     return ANIMATE_Stop(infoPtr);
00904 
00905     case WM_CLOSE:
00906     ANIMATE_Free(infoPtr);
00907     return 0;
00908 
00909     case WM_NCCREATE:
00910     return ANIMATE_Create(hWnd, (LPCREATESTRUCTW)lParam);
00911 
00912     case WM_NCHITTEST:
00913     return HTTRANSPARENT;
00914 
00915     case WM_DESTROY:
00916     return ANIMATE_Destroy(infoPtr);
00917 
00918     case WM_ERASEBKGND:
00919     return ANIMATE_EraseBackground(infoPtr, (HDC)wParam);
00920 
00921     case WM_STYLECHANGED:
00922         return ANIMATE_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
00923 
00924     case WM_TIMER:
00925         return ANIMATE_Timer(infoPtr);
00926 
00927     case WM_PRINTCLIENT:
00928     case WM_PAINT:
00929         {
00930             /* the animation has not decompressed
00931              * (and displayed) the first frame yet, don't paint
00932              */
00933             if (!infoPtr->hbmPrevFrame)
00934             {
00935                 /* default paint handling */
00936                 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
00937             }
00938 
00939             if (wParam)
00940             {
00941                 EnterCriticalSection(&infoPtr->cs);
00942                 ANIMATE_PaintFrame(infoPtr, (HDC)wParam);
00943                 LeaveCriticalSection(&infoPtr->cs);
00944             }
00945             else
00946             {
00947                 PAINTSTRUCT ps;
00948                 HDC hDC = BeginPaint(infoPtr->hwndSelf, &ps);
00949 
00950                 EnterCriticalSection(&infoPtr->cs);
00951                 ANIMATE_PaintFrame(infoPtr, hDC);
00952                 LeaveCriticalSection(&infoPtr->cs);
00953 
00954                 EndPaint(infoPtr->hwndSelf, &ps);
00955             }
00956         }
00957         break;
00958 
00959     case WM_SIZE:
00960         if (infoPtr->dwStyle & ACS_CENTER) 
00961         InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
00962     return DefWindowProcW(hWnd, uMsg, wParam, lParam);
00963 
00964     default:
00965     if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
00966         ERR("unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
00967 
00968     return DefWindowProcW(hWnd, uMsg, wParam, lParam);
00969     }
00970     return 0;
00971 }
00972 
00973 void ANIMATE_Register(void)
00974 {
00975     WNDCLASSW wndClass;
00976 
00977     ZeroMemory(&wndClass, sizeof(WNDCLASSW));
00978     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
00979     wndClass.lpfnWndProc   = ANIMATE_WindowProc;
00980     wndClass.cbClsExtra    = 0;
00981     wndClass.cbWndExtra    = sizeof(ANIMATE_INFO *);
00982     wndClass.hCursor       = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
00983     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
00984     wndClass.lpszClassName = ANIMATE_CLASSW;
00985 
00986     RegisterClassW(&wndClass);
00987 }
00988 
00989 
00990 void ANIMATE_Unregister(void)
00991 {
00992     UnregisterClassW(ANIMATE_CLASSW, NULL);
00993 }

Generated on Fri May 25 2012 04:20:55 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.