home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / rleapp / rlefile.c < prev   
C/C++ Source or Header  |  1992-09-12  |  24KB  |  923 lines

  1. /*----------------------------------------------------------------------------*\
  2.     rlefile.c - file handling for RLEAPP
  3.     
  4. \*----------------------------------------------------------------------------*/
  5. /*
  6.      (C) Copyright Microsoft Corp. 1991, 1992.  All rights reserved.
  7.  
  8.      You have a royalty-free right to use, modify, reproduce and 
  9.      distribute the Sample Files (and/or any modified version) in 
  10.      any way you find useful, provided that you agree that 
  11.      Microsoft has no warranty obligations or liability for any 
  12.      Sample Application Files which are modified. 
  13.      
  14.      If you did not get this from Microsoft Sources, then it may not be the
  15.      most current version.  This sample code in particular will be updated
  16.      and include more documentation.  
  17.  
  18.      Sources are:
  19.          The MM Sys BBS: The phone number is 206 936-4082.
  20.     CompuServe: WINSDK forum, MDK section.
  21.  
  22. */
  23.  
  24.  
  25. #include <windows.h>
  26. #include <mmsystem.h>
  27.  
  28. #include "rleapp.h"
  29. #include "gmem.h"
  30. #include "dib.h"
  31. #include "rle.h"
  32.  
  33. /*----------------------------------------------------------------------------*\
  34. \*----------------------------------------------------------------------------*/
  35.  
  36. #define FOURCC( ch0, ch1, ch2, ch3 )                         \
  37.         ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) |    \
  38.                 ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
  39.  
  40. #define RIFF_RIFF       FOURCC('R','I','F','F')
  41. #define RIFF_LIST       FOURCC('L','I','S','T')
  42. #define RIFF_RLE0       FOURCC('R','L','E','0')
  43. #define RIFF_RLEh       FOURCC('R','L','E','h')
  44. #define RIFF_DIBh       FOURCC('D','I','B','h')
  45. #define RIFF_WAVh       FOURCC('W','A','V','h')
  46. #define RIFF_RGBq       FOURCC('r','g','b','q')
  47. #define RIFF_DIBb       FOURCC('D','I','B','b')
  48.  
  49. #define RIFF_WAVb       FOURCC('W','A','V','b')
  50. #define RIFF_PALb       FOURCC('P','A','L','b')
  51. #define RIFF_PAD        FOURCC('p','a','d','d')
  52.  
  53. #define RIFF_WAVE       FOURCC('W','A','V','E')
  54. #define RIFF_DATA       FOURCC('d','a','t','a')
  55. #define RIFF_FMT        FOURCC('f','m','t',' ')
  56.  
  57.  
  58. typedef struct {
  59.     DWORD       dwType;
  60.     DWORD       dwSize;
  61. } RIFF, *PRIFF, FAR *LPRIFF;
  62.  
  63. typedef struct {
  64.     DWORD       dwRiff;
  65.     DWORD       dwSize;
  66.     DWORD       dwType;
  67. } RIFFHDR;
  68.  
  69. typedef struct {
  70.     DWORD       dwFlags;
  71.     DWORD       dwNumFrames;
  72.     DWORD       dwMaxBuffer;
  73.     DWORD       dwFrameRate;
  74. } RLEHDR;
  75.                 /* stats about RLE frames */
  76. /* flags for _lseek */
  77. #define  SEEK_CUR 1
  78. #define  SEEK_END 2
  79. #define  SEEK_SET 0
  80.  
  81. DWORD FAR PASCAL lread(int fh, LPVOID p, DWORD len);
  82. DWORD FAR PASCAL lwrite(int fh, LPVOID p, DWORD len);
  83. DWORD FAR PASCAL lseek(int fh, DWORD off, WORD w);
  84. int   FAR PASCAL lopen(LPSTR sz, WORD acc);
  85. int   FAR PASCAL lclose(int fh);
  86.  
  87. #define LWRITE(fh, p, len)         {if (lwrite(fh,p,len) != (len)) goto error;}
  88. #define LREAD(fh, p, len)          {if (lread(fh,p,len) != (len)) goto error;}
  89. #define WRITERIFF(fh,dwType,p,len) {if (WriteRiff(fh,dwType,p,len) != (len)) goto error;}
  90.  
  91. /*----------------------------------------------------------------------------*\
  92. \*----------------------------------------------------------------------------*/
  93. DWORD WriteRiff(int fh, DWORD dwType, LPVOID p, DWORD dwSize)
  94. {
  95.     RIFF    riff;
  96.  
  97.     riff.dwType = dwType;
  98.     riff.dwSize = dwSize;
  99.  
  100.     LWRITE(fh, &riff, sizeof(riff));
  101.  
  102.     if (p != NULL)
  103.         LWRITE(fh, p, (dwSize+1)&~1);
  104.  
  105.     return dwSize;
  106. error:
  107.     return -1L;
  108. }
  109.  
  110. /*----------------------------------------------------------------------------*\
  111. \*----------------------------------------------------------------------------*/
  112. DWORD WriteList(int fh, DWORD dwList, DWORD dwType)
  113. {
  114.     DWORD   off;
  115.     RIFFHDR riff;
  116.  
  117.     if (!(dwList == RIFF_RIFF || dwList == RIFF_LIST))
  118.         return -1;
  119.  
  120.     off = lseek(fh, 0L, SEEK_CUR);
  121.  
  122.     riff.dwRiff = dwList;
  123.     riff.dwSize = 0L;
  124.     riff.dwType = dwType;
  125.  
  126.     LWRITE(fh, &riff, sizeof(riff));
  127.  
  128.     return off;
  129. error:
  130.     return -1L;
  131. }
  132.  
  133. /*----------------------------------------------------------------------------*\
  134. \*----------------------------------------------------------------------------*/
  135. BOOL EndList(int fh, DWORD offList)
  136. {
  137.     DWORD off;
  138.     DWORD dwLen;
  139.  
  140.     off = lseek(fh, 0L, SEEK_CUR);
  141.     dwLen = off - offList - sizeof(RIFF);
  142.  
  143.     lseek(fh, offList+sizeof(DWORD), SEEK_SET);
  144.     LWRITE(fh, &dwLen, sizeof(DWORD));
  145.     lseek(fh, off, SEEK_SET);
  146.  
  147.     return TRUE;
  148. error:
  149.     return FALSE;
  150. }
  151.  
  152. /*----------------------------------------------------------------------------*\
  153. \*----------------------------------------------------------------------------*/
  154. BOOL OpenRiffFile(LPSTR szFile, int iFrame, DWORD dwType)
  155. {
  156.     unsigned    fh;
  157.     HANDLE      hdib;
  158.     BITMAPINFOHEADER bi;
  159.     RGBQUAD     argbq[256];
  160.     LPBITMAPINFOHEADER lpbi;
  161.     DWORD       off;
  162.     RIFF        riff;
  163.     RIFFHDR     riffhdr;
  164.     LPSTR       pbits;
  165.     LPSTR       prgb;
  166.     int         wWaveRead = 0;
  167.     DWORD    dwWaveSize = 0L;    // Total size of all wave data
  168.     int         i;
  169.     LPWAVEHDR    pwh;
  170.     RLEHDR      rlehdr;
  171.  
  172.     totFrames = 0;        // length of movie; displayed on status bar
  173.     fh = lopen(szFile, OF_READ);
  174.  
  175.     if (fh == -1) 
  176.     return FALSE;
  177.  
  178.     LREAD(fh,(LPVOID)&riffhdr,sizeof(riffhdr));
  179.  
  180.     if (riffhdr.dwRiff != RIFF_RIFF || riffhdr.dwType != dwType)
  181.         goto exit;
  182.  
  183.     rlehdr.dwFlags      = 0L;
  184.     rlehdr.dwNumFrames  = 0L;
  185.     rlehdr.dwMaxBuffer  = 0L;
  186.     rlehdr.dwFrameRate  = 0L;
  187.  
  188.     if (pWaveFormat)            // Free the movie's wave header
  189.     GFreePtr(pWaveFormat);
  190.     if (pwhMovie)                       // Free the movie's wave data
  191.         GFreePtr(pwhMovie);
  192.  
  193.     pWaveFormat = NULL;
  194.     pwhMovie = NULL;
  195.  
  196.     for (;;)
  197.     {
  198.         if (lread(fh,(LPVOID)&riff,sizeof(riff)) != sizeof(riff))
  199.         break;
  200.  
  201.         off = lseek(fh, 0L, SEEK_CUR);
  202.  
  203.         switch (riff.dwType)
  204.         {
  205.         case RIFF_RLEh:
  206.             LREAD(fh,(LPVOID)&rlehdr,sizeof(RLEHDR));
  207.             totFrames = (WORD)rlehdr.dwNumFrames;
  208.             break;
  209.  
  210.         case RIFF_DIBh:
  211.             LREAD(fh,(LPVOID)&bi,sizeof(bi));
  212.  
  213.             if (bi.biClrUsed == 0)
  214.                 bi.biClrUsed = 1 << bi.biBitCount;
  215.  
  216.         bi.biSizeImage = (DWORD)DIBWIDTHBYTES(bi) * bi.biHeight;
  217.  
  218.         if (riff.dwSize > sizeof(bi))
  219.                 LREAD(fh,(LPVOID)argbq,bi.biClrUsed*sizeof(RGBQUAD));
  220.  
  221.             break;
  222.  
  223.         case RIFF_RGBq:
  224.             LREAD(fh,(LPVOID)argbq,bi.biClrUsed*sizeof(RGBQUAD));
  225.             break;
  226.  
  227.         case RIFF_DIBb:
  228.         hdib = GAlloc(bi.biSize+bi.biClrUsed*sizeof(RGBQUAD)+riff.dwSize);
  229.  
  230.         if (!hdib)
  231.                 goto errormem;
  232.  
  233.         lpbi = GLock(hdib);
  234.  
  235.         prgb  = (LPSTR)lpbi + bi.biSize;
  236.         pbits = (LPSTR)prgb + bi.biClrUsed * sizeof(RGBQUAD);
  237.  
  238.         bi.biSizeImage = riff.dwSize;
  239.             MemCopy((LPVOID)lpbi,(LPVOID)&bi,sizeof(bi));
  240.             MemCopy((LPVOID)prgb,(LPVOID)argbq,(int)bi.biClrUsed*sizeof(RGBQUAD));
  241.  
  242.             LREAD(fh,pbits,riff.dwSize);
  243.  
  244.         InsertFrame(hdib,iFrame,TRUE);
  245.  
  246.         if (iFrame == -1)            // What frame was that?
  247.         i = numFrames - 1;
  248.         else
  249.         i = iFrame;
  250.  
  251.         if (iFrame >= 0)
  252.         iFrame++;
  253.             break;
  254.  
  255.         case RIFF_WAVh:
  256.         pWaveFormat = GAllocPtr(riff.dwSize);
  257.  
  258.         if (pWaveFormat == NULL)
  259.                 goto errormem;
  260.  
  261.             LREAD(fh,(LPVOID)pWaveFormat,(WORD)riff.dwSize);
  262.         gSamplesPerSec = pWaveFormat->nSamplesPerSec;
  263.             gChannels = pWaveFormat->nChannels;
  264.             break;
  265.  
  266.         case RIFF_WAVb:
  267.             if (pwhMovie)
  268.             {
  269.                 pwh = GReAllocPtr(pwhMovie,
  270.                     sizeof(WAVEHDR)+pwhMovie->dwBufferLength+riff.dwSize);
  271.  
  272.                 if (!pwh)
  273.                 {
  274.                     pwh = GAllocPtr(sizeof(WAVEHDR)+pwhMovie->dwBufferLength+riff.dwSize);
  275.  
  276.                     if (!pwh)
  277.                         goto errormem;
  278.  
  279.                     MemCopy(pwh,pwhMovie,pwhMovie->dwBufferLength);
  280.  
  281.                     GFreePtr(pwhMovie);
  282.                 }
  283.  
  284.                 pwhMovie = pwh;
  285.         pwhMovie->lpData = (LPVOID)(pwhMovie+1);
  286.             }
  287.             else
  288.             {
  289.                 pwh = GAllocPtr(riff.dwSize + sizeof(WAVEHDR));
  290.  
  291.                 if (!pwh)
  292.                     goto errormem;
  293.  
  294.         pwh->lpData          = (LPVOID)(pwh+1);
  295.         pwh->dwBufferLength  = 0;
  296.         pwh->dwBytesRecorded = 0;
  297.         pwh->dwUser          = 0;
  298.         pwh->dwFlags         = WHDR_DONE;
  299.                 pwh->dwLoops         = 0;
  300.  
  301.                 pwhMovie = pwh;
  302.         }
  303.  
  304.             LREAD(fh, (BYTE huge *)(pwh->lpData) + pwh->dwBufferLength, riff.dwSize);
  305.         dwWaveSize += riff.dwSize;
  306.             pwh->dwBufferLength += riff.dwSize;
  307.             break;
  308.  
  309.         case RIFF_LIST:
  310.             //
  311.             //  we want to desend into all list chunks, so treat
  312.             //  the list chunk as a small bogus chunk.
  313.             //
  314.             riff.dwSize = sizeof(DWORD);        // LIST form type.
  315.             break;
  316.  
  317.         default:
  318.         case RIFF_PALb:
  319.         case RIFF_PAD:
  320.             // ignore
  321.             break;
  322.     }
  323.  
  324.         lseek(fh, off + (riff.dwSize+1)&~1L, SEEK_SET);
  325.  
  326.     if (WinYield())
  327.         break;
  328.     }
  329.  
  330. exit1:
  331.     if ((rlehdr.dwFrameRate > 1*FramesSecScale) && (rlehdr.dwFrameRate < 32*FramesSecScale))
  332.     FramesSec = rlehdr.dwFrameRate;
  333.     else if (dwWaveSize && numFrames)
  334.         FramesSec = muldiv32(numFrames,(long)gChannels*gSamplesPerSec*FramesSecScale,dwWaveSize);
  335.     else
  336.         FramesSec = 15 * FramesSecScale;
  337.  
  338. /* HACK!!  Remember the start and size of the wave data */
  339.  
  340.     if (pwhMovie)
  341.     {
  342.         glpData         = pwhMovie->lpData;
  343.         gdwBufferLength = pwhMovie->dwBufferLength;
  344.     }
  345.  
  346.     lclose(fh);
  347.     return TRUE;
  348.  
  349. errormem:
  350.     ErrMsg("Out of Memory Error");
  351.     goto exit1;
  352.  
  353. error:
  354.     ErrMsg("Read Error");
  355.     goto exit1;
  356.  
  357. exit:
  358.     lclose(fh);
  359.     return FALSE;
  360. }
  361.  
  362. /*----------------------------------------------------------------------------*\
  363. \*----------------------------------------------------------------------------*/
  364. BOOL OpenRl0File(LPSTR szFile, int iFrame)
  365. {
  366.     return OpenRiffFile(szFile, iFrame, RIFF_RLE0);
  367. }
  368.  
  369.  
  370. /*----------------------------------------------------------------------------*\
  371. \*----------------------------------------------------------------------------*/
  372. void SaveRl0File(LPSTR szFile,int startFrame,int nFrames)
  373. {
  374.     unsigned    fh;
  375.     int         i;
  376.     HANDLE      hdib;
  377.     HPALETTE    hpal;
  378.     int         curSave = curFrame;
  379.     LPBITMAPINFOHEADER lpbi;
  380.     BITMAPINFOHEADER bi;
  381. #if 0    
  382.     RIFF        riff;
  383. #endif
  384.     RIFFHDR     riffhdr;
  385.     RLEHDR    rlehdr;
  386.  
  387.     fh = lopen(szFile, OF_READWRITE|OF_CREATE);
  388.  
  389.     if (fh == -1) {
  390.     ErrMsg("Error Creating File");
  391.     return;
  392.     }
  393.  
  394.     StartWait();
  395.  
  396.     //
  397.     // write the RIFF header.
  398.     //
  399.     riffhdr.dwRiff = RIFF_RIFF;
  400.     riffhdr.dwType = RIFF_RLE0;
  401.     riffhdr.dwSize = 0;             // patch later
  402.     LWRITE(fh, (LPVOID)&riffhdr, sizeof(RIFFHDR));
  403.  
  404.     //
  405.     // write the RLE header.
  406.     //
  407.     rlehdr.dwFlags      = 0L;
  408.     rlehdr.dwNumFrames  = (DWORD)numFrames;
  409.     rlehdr.dwMaxBuffer  = 0L;
  410.     rlehdr.dwFrameRate  = FramesSec;
  411.  
  412.     for (i=startFrame; i<startFrame+nFrames; i++)
  413.     {
  414.     lpbi = GLock(FrameRle(i));
  415.     rlehdr.dwMaxBuffer = max(rlehdr.dwMaxBuffer,lpbi->biSizeImage);
  416.     }
  417.  
  418.     WriteRiff(fh, RIFF_RLEh, (LPVOID)&rlehdr, sizeof(RLEHDR));
  419. #if 0    
  420.     riff.dwType = RIFF_RLEh;
  421.     riff.dwSize = sizeof(RLEHDR);
  422.     LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  423.     LWRITE(fh, (LPVOID)&rlehdr, sizeof(RLEHDR));
  424. #endif
  425.  
  426.     //
  427.     // write the WAV header.
  428.     //
  429.     if (pWaveFormat)
  430.     {
  431.     WriteRiff( fh, RIFF_WAVh, (LPVOID)pWaveFormat, GSize(HIWORD(pWaveFormat)));
  432. #if 0    
  433.     riff.dwType = RIFF_WAVh;
  434.     riff.dwSize = GSize(HIWORD(pWaveFormat));  //!!!
  435.         LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  436.         LWRITE(fh, (LPVOID)pWaveFormat, (WORD)riff.dwSize);
  437. #endif    
  438.     }
  439.  
  440.     //
  441.     //  write the WAV bits?
  442.     //
  443.     if (pwhMovie)
  444.     {
  445.         pwhMovie->dwBufferLength = gdwBufferLength;
  446.         pwhMovie->lpData = glpData;
  447.  
  448.     WriteRiff(fh, RIFF_WAVb, pwhMovie->lpData, ALIGNULONG(pwhMovie->dwBufferLength));
  449. #if 0    
  450.     riff.dwType = RIFF_WAVb;
  451.         riff.dwSize = pwhMovie->dwBufferLength;
  452.     riff.dwSize = ALIGNULONG(riff.dwSize);
  453.         LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  454.         LWRITE(fh, pwhMovie->lpData, riff.dwSize);
  455. #endif    
  456.     }
  457.  
  458.     //
  459.     // write all the frames.
  460.     //
  461.     for (i=startFrame; i<startFrame+nFrames; i++)
  462.     {
  463.     hdib = FrameRle(i);
  464.     hpal = FramePalette(i);
  465.     lpbi = GLock(hdib);
  466.  
  467.     //
  468.     // write a DIB header. (if needed)
  469.     //
  470.     if (i==startFrame ||
  471.         bi.biWidth != lpbi->biWidth ||
  472.         bi.biHeight != lpbi->biHeight ||
  473.         bi.biCompression != lpbi->biCompression)
  474.     {
  475.         bi = *lpbi;
  476.         WriteRiff(fh, RIFF_DIBh, (LPVOID)lpbi, lpbi->biSize);
  477. #if 0        
  478.         riff.dwType = RIFF_DIBh;
  479.         riff.dwSize = lpbi->biSize;
  480.             LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  481.             LWRITE(fh, (LPVOID)lpbi, (WORD)riff.dwSize);
  482. #endif        
  483.     }
  484.  
  485.     //
  486.     // write a palette if needed
  487.     //
  488.     if (!(FrameFlags(i) & F_PALSHARED))
  489.     {
  490.         SetDibUsage(hdib,hpal,DIB_RGB_COLORS);
  491.         WriteRiff(fh, RIFF_RGBq, (LPSTR)lpbi+lpbi->biSize, lpbi->biClrUsed * sizeof(RGBQUAD));
  492. #if 0        
  493.         riff.dwType = RIFF_RGBq;
  494.         riff.dwSize = lpbi->biClrUsed * sizeof(RGBQUAD);
  495.             LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  496.             LWRITE(fh, (LPSTR)lpbi+lpbi->biSize, (WORD)riff.dwSize);
  497. #endif        
  498.         SetDibUsage(hdib,hpal,DIB_PAL_COLORS);
  499.     }
  500.     //
  501.     //  write the DIB bits
  502.     //
  503.     WriteRiff(fh, RIFF_DIBb, DibXY(lpbi,0,0), lpbi->biSizeImage);
  504. #if 0    
  505.     riff.dwType = RIFF_DIBb;
  506.     riff.dwSize = lpbi->biSizeImage;
  507.         LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  508.         LWRITE(fh, DibXY(lpbi,0,0), riff.dwSize);
  509. #endif
  510.     ShowFrame(i);
  511.  
  512.     if (WinYield())
  513.         break;
  514.     }
  515.  
  516.     //
  517.     // patch the RIFFHDR
  518.     //
  519.     riffhdr.dwRiff = RIFF_RIFF;
  520.     riffhdr.dwType = RIFF_RLE0;
  521.     riffhdr.dwSize = lseek(fh, 0L, SEEK_CUR) - sizeof(RIFF);
  522.  
  523.     lseek(fh, 0L, SEEK_SET);
  524.     LWRITE(fh, (LPVOID)&riffhdr, sizeof(RIFFHDR));
  525.  
  526.     lclose(fh);
  527.  
  528.     ShowFrame(curSave);
  529.     EndWait();
  530.  
  531.     return;
  532.  
  533. error:
  534.     lclose(fh);
  535.  
  536.     ShowFrame(curSave);
  537.     EndWait();
  538.  
  539.     ErrMsg("Error Writing file");
  540.     return;
  541. }
  542.  
  543. /*----------------------------------------------------------------------------*\
  544. \*----------------------------------------------------------------------------*/
  545. BOOL SaveWavFile(LPSTR szFile,int startFrame,int nFrames)
  546. {
  547.     unsigned    fh;
  548. #if 0    
  549.     DWORD       dwSize;
  550.     RIFF        riff;
  551. #endif    
  552.     RIFFHDR     riffhdr;
  553.  
  554.     if (!pWaveFormat || !pwhMovie)
  555.     return FALSE;
  556.  
  557.     fh = lopen(szFile, OF_READWRITE|OF_CREATE);
  558.  
  559.     if (fh == -1) {
  560.     ErrMsg("Error Creating File");
  561.     return FALSE;
  562.     }
  563.  
  564.     StartWait();
  565.  
  566.     //
  567.     // write the RIFF header.
  568.     //
  569.     riffhdr.dwRiff = RIFF_RIFF;
  570.     riffhdr.dwType = RIFF_WAVE;
  571.     riffhdr.dwSize = 0;            // patch it later
  572.     LWRITE(fh, (LPVOID)&riffhdr, sizeof(RIFFHDR));
  573.  
  574.     //
  575.     // write the WAV header.
  576.     //
  577.     WriteRiff(fh, RIFF_FMT, (LPVOID)pWaveFormat, GSize(HIWORD(pWaveFormat)));
  578. #if 0
  579.     riff.dwType = RIFF_FMT;
  580.     riff.dwSize = GSize(HIWORD(pWaveFormat));  //!!!
  581.     LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  582.     LWRITE(fh, (LPVOID)pWaveFormat, (WORD)riff.dwSize);
  583. #endif
  584.  
  585.     //
  586.     //  write the WAV bits?
  587.     //
  588.     pwhMovie->dwBufferLength = gdwBufferLength;
  589.     pwhMovie->lpData = glpData;
  590.  
  591.     WriteRiff(fh, RIFF_DATA, pwhMovie->lpData, pwhMovie->dwBufferLength);
  592. #if 0    
  593.     riff.dwSize = pwhMovie->dwBufferLength;
  594.     riff.dwType = RIFF_DATA;
  595.  
  596.     LWRITE(fh, (LPVOID)&riff, sizeof(RIFF));
  597.     LWRITE(fh, pwhMovie->lpData, dwSize);
  598.  
  599.  
  600.     //
  601.     // word align
  602.     //
  603.     if (riff.dwSize & 1)
  604.         LWRITE(fh, (LPVOID)&riff, 1);
  605.  
  606. #endif
  607.  
  608.     //
  609.     // patch the RIFFHDR
  610.     //
  611.     riffhdr.dwRiff = RIFF_RIFF;
  612.     riffhdr.dwType = RIFF_WAVE;
  613.     riffhdr.dwSize = lseek(fh, 0L, SEEK_CUR) - sizeof(RIFF);
  614.     lseek(fh, 0L, SEEK_SET);
  615.     LWRITE(fh, (LPVOID)&riffhdr, sizeof(RIFFHDR));
  616.  
  617.     lclose(fh);
  618.     EndWait();
  619.     return TRUE;
  620.  
  621. error:
  622.     ErrMsg("Error writing file");
  623.     lclose(fh);
  624.     EndWait();
  625.     return FALSE;
  626. }
  627.  
  628. /*----------------------------------------------------------------------------*\
  629. \*----------------------------------------------------------------------------*/
  630.  
  631. #define BUFSIZE         2048
  632. #define BUFALIGN(ul)    (((ul)+BUFSIZE-1) & ~(BUFSIZE-1))
  633.  
  634.  
  635. /*----------------------------------------------------------------------------*\
  636.   
  637. // *********************************************************************    
  638. //  BAD CODE WARNING:    
  639. // *********************************************************************    
  640. //
  641. // This code requires that the header be the first thing
  642. // followed by data.  THIS IS NOT CORRECT!!!!!!
  643. // This code will be fixed in a next version.
  644. //
  645. // Do not use this code!!!!!
  646. //
  647.  
  648. \*----------------------------------------------------------------------------*/
  649. BOOL OpenWavFile(LPSTR szFile)
  650. {
  651.     unsigned    fh;
  652.     RIFF        riff;
  653.     RIFFHDR     riffhdr;
  654.     LPWAVEHDR    pwh;
  655.     DWORD    dwWaveSize;
  656.  
  657.     fh = lopen(szFile, OF_READ);
  658.     if (fh == -1)
  659.     return FALSE;
  660.  
  661.     //
  662.     // read the RIFF header.
  663.     //
  664.     LREAD(fh, (LPVOID)&riffhdr, sizeof(RIFFHDR));
  665.     if (riffhdr.dwRiff != RIFF_RIFF || riffhdr.dwType != RIFF_WAVE) 
  666.     {
  667.         lclose(fh);
  668.     return FALSE;
  669.     }
  670.  
  671.     if (numFrames == 0) 
  672.     {
  673.     ErrMsg("Can't Open Wave File onto Empty Movie");
  674.         lclose(fh);
  675.     return FALSE;
  676.     }
  677.  
  678.     StartWait();
  679.  
  680.     //
  681.     // read the WAVE header
  682.     //
  683.     LREAD(fh, (LPVOID)&riff, sizeof(RIFF));
  684.  
  685.     if (riff.dwType != RIFF_FMT) 
  686.     {
  687.     ErrMsg("File Corrupted");
  688.     goto openwave_barf;
  689.     }
  690.  
  691. /* Destroy the current waves of this movie */
  692.  
  693.     if (pWaveFormat)
  694.     GFreePtr(pWaveFormat);
  695.     if (pwhMovie)
  696.         GFreePtr(pwhMovie);
  697.     pWaveFormat = NULL;
  698.     pwhMovie = NULL;
  699.  
  700. /* Load the wave header in */
  701.  
  702.     pWaveFormat = GAllocPtr(riff.dwSize);
  703.     if (pWaveFormat == NULL) 
  704.     {
  705.     ErrMsg("Out of Memory Error");
  706.     goto openwave_barf;
  707.     }
  708.  
  709.     LREAD(fh,(LPVOID)pWaveFormat,(WORD)riff.dwSize);
  710.     gSamplesPerSec = pWaveFormat->nSamplesPerSec;
  711.     gChannels = pWaveFormat->nChannels;
  712.  
  713.     //
  714.     // read the DATA header
  715.     //
  716.     LREAD(fh, (LPVOID)&riff, sizeof(RIFF));
  717.     if (riff.dwType != RIFF_DATA) 
  718.     {
  719.     ErrMsg("File Corrupted");
  720.     goto openwave_barf;
  721.     }
  722.  
  723.     //
  724.     // read the actual wave data
  725.     //
  726.     pwh = GAllocPtr(riff.dwSize + sizeof(WAVEHDR));
  727.     if (!pwh) 
  728.     {
  729.     ErrMsg("Out of Memory Error");
  730.     goto openwave_barf;
  731.     }
  732.     pwh->lpData          = (LPVOID)(pwh+1);
  733.     pwh->dwBufferLength  = riff.dwSize;
  734.     pwh->dwBytesRecorded = 0;
  735.     pwh->dwUser          = 0;
  736.     pwh->dwFlags         = WHDR_DONE;
  737.     pwh->dwLoops         = 0;
  738.  
  739.     LREAD(fh,pwh->lpData,riff.dwSize);
  740.     dwWaveSize = pwh->dwBufferLength;
  741.  
  742.     if (dwWaveSize && numFrames)
  743.         FramesSec = muldiv32(numFrames,(long)gChannels*gSamplesPerSec*FramesSecScale,dwWaveSize);
  744.     else
  745.         FramesSec = 15 * FramesSecScale;
  746.  
  747.     pwhMovie = pwh;
  748.  
  749.     glpData         = pwh->lpData;
  750.     gdwBufferLength = pwh->dwBufferLength;
  751.  
  752.     lclose(fh);
  753.     EndWait();
  754.     return TRUE;
  755.  
  756. error:
  757. openwave_barf:
  758.     lclose(fh);
  759.     EndWait();
  760.     return FALSE;
  761. }
  762.  
  763. /*----------------------------------------------------------------------------*\
  764. \*----------------------------------------------------------------------------*/
  765. BOOL NEAR OpenRleFile(LPSTR szFile, int iFrame)
  766. {
  767.     unsigned    fh;
  768.     HANDLE      hdib;
  769.     BOOL    fValidDibRead = FALSE;
  770.  
  771.     totFrames = 0;
  772.     fh = lopen(szFile, OF_READ);
  773.  
  774.     if (fh == -1)
  775.     return FALSE;
  776.  
  777.     while (hdib = OpenDIB((LPSTR)MAKEINTATOM(fh)))
  778.     {
  779.     fValidDibRead = TRUE;
  780.     InsertFrame(hdib, iFrame, TRUE);
  781.  
  782.     if (iFrame >= 0)
  783.         iFrame++;
  784.  
  785.     if (WinYield())
  786.         break;
  787.     }
  788.  
  789.     lclose(fh);
  790.     FramesSec = 15 * FramesSecScale;
  791.  
  792.     return fValidDibRead;
  793. }
  794.  
  795. /*----------------------------------------------------------------------------*\
  796.    Load in a whole slew of frames one at a time if they are called
  797.    foo000.dib
  798.    foo001.dib
  799.    foo002.dib  ...etc....  in this case you would use a filename of
  800.                            foo%03d.dib to load in this sequence.
  801.    The sequence can start with 0 or 1, and go arbitrarily high as long as
  802.    every filename can be generated with some printf statement.
  803. \*----------------------------------------------------------------------------*/
  804.  
  805. BOOL OpenFrames(LPSTR szFrame, int iFrame)
  806. {
  807.     char buf[80];
  808.     int i;
  809.     BOOL fFileFound = FALSE;
  810.  
  811.     totFrames = 0;        // length of movie; displayed on status bar
  812.     // or wsprintf in the "load a slew of frames" won't work
  813.     AnsiLower(szFrame);
  814.  
  815.     for (i=0; (wsprintf(buf,szFrame,i) &&
  816.         (fFileFound = OpenRleFile(buf,iFrame)) && !WinYield()) || i==0; i++)
  817.         ;
  818.  
  819.     return fFileFound;
  820. }
  821.  
  822. /*----------------------------------------------------------------------------*\
  823. \*----------------------------------------------------------------------------*/
  824. BOOL OpenMovieFile(LPSTR szFrame, int iFrame)
  825. {
  826.     BOOL f;
  827.  
  828.     StartWait();
  829.     fLoading++;
  830.  
  831.     f = OpenWavFile(szFrame) ||
  832.         OpenRl0File(szFrame, iFrame) ||
  833.         OpenRleFile(szFrame, iFrame) ||
  834.         OpenFrames (szFrame, iFrame);
  835.  
  836.     fLoading--;
  837.     EndWait();
  838.  
  839.     if (!f)  // We never did load a valid file!
  840.     ErrMsg("File Open Error");
  841.  
  842.     return f;
  843. }
  844.  
  845. /*----------------------------------------------------------------------------*\
  846. \*----------------------------------------------------------------------------*/
  847. void SaveRleFile(LPSTR szFile,int startFrame,int nFrames)
  848. {
  849.     unsigned    fh;
  850.     int         i;
  851.     HANDLE      hdib;
  852.     HPALETTE    hpal;
  853.     int         curSave = curFrame;
  854.  
  855.     fh = lopen(szFile, OF_READWRITE|OF_CREATE);
  856.  
  857.     if (fh == -1)
  858.     return;
  859.  
  860.     if (startFrame > 0)            // Validate the first frame of movie
  861.     RenderFrame(startFrame);
  862.  
  863.     StartWait();
  864.     for (i=startFrame; i<startFrame+nFrames; i++)
  865.     {
  866.     hdib = FrameDib(i);
  867.     hpal = FramePalette(i);
  868.  
  869.     SetDibUsage(hdib,hpal,DIB_RGB_COLORS);
  870.         WriteDIB((LPSTR)MAKEINTATOM(fh),hdib);
  871.     SetDibUsage(hdib,hpal,DIB_PAL_COLORS);
  872.  
  873.     ShowFrame(i);
  874.     if (WinYield())
  875.         break;
  876.     } 
  877.     PurgeFrames();
  878.     ShowFrame(curSave);
  879.     EndWait();
  880.  
  881.     lclose(fh);
  882.  
  883.     return;
  884. }
  885.  
  886. /***************************************************************************\
  887. *
  888. *   routines for file I/O
  889. *
  890. \***************************************************************************/
  891.  
  892. DWORD FAR PASCAL lread(int fh, LPVOID p, DWORD len)
  893. {
  894.     return mmioRead((HMMIO)fh, p, len);
  895. }
  896.  
  897. DWORD FAR PASCAL lwrite(int fh, LPVOID p, DWORD len)
  898. {
  899.     return mmioWrite((HMMIO)fh, p, len);
  900. }
  901.  
  902. DWORD FAR PASCAL lseek(int fh, DWORD off, WORD w)
  903. {
  904.     return mmioSeek((HMMIO)fh,off,w);
  905. }
  906.  
  907. int FAR PASCAL lopen(LPSTR sz, WORD acc)
  908. {
  909.     HMMIO hmmio;
  910.  
  911.     hmmio = mmioOpen(sz, NULL, acc | MMIO_ALLOCBUF);
  912.  
  913.     if (hmmio == NULL)
  914.         return -1;
  915.  
  916.     return (int)hmmio;
  917. }
  918.  
  919. int FAR PASCAL lclose(int fh)
  920. {
  921.     return mmioClose((HMMIO)fh, 0);
  922. }
  923.