home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / TOOLKIT / MM / ULTIMOIO / ULREAD.C < prev    next >
C/C++ Source or Header  |  1994-11-17  |  46KB  |  804 lines

  1. /*************************START OF SPECIFICATIONS *************************/
  2. /* SOURCE FILE NAME:  ULREAD.C                                            */
  3. /*                                                                        */
  4. /* DESCRIPTIVE NAME: Ultimotion IO Proc routine for MMIOM_READ            */
  5. /*                                                                        */
  6. /* COPYRIGHT:     IBM - International Business Machines                   */
  7. /*            Copyright (c) IBM Corporation  1991, 1992, 1993             */
  8. /*                        All Rights Reserved                             */
  9. /*                                                                        */
  10. /* STATUS: OS/2 Release 2.0                                               */
  11. /*                                                                        */
  12. /* FUNCTION: This source module contains the read routine.                */
  13. /*                                                                        */
  14. /* NOTES:                                                                 */
  15. /*    DEPENDENCIES: none                                                  */
  16. /*    RESTRICTIONS: Runs in 32 bit protect mode (OS/2 2.0)                */
  17. /*                                                                        */
  18. /* ENTRY POINTS:                                                          */
  19. /*       IOProcRead                                                       */
  20. /*       IOProcReadInterLeaved                                            */
  21. /*                                                                        */
  22. /************************* END OF SPECIFICATIONS **************************/
  23.  
  24.  
  25. #include        <stdio.h>
  26. #include        <string.h>
  27. #include        <stdlib.h>
  28. #include        <memory.h>
  29.  
  30. #define         INCL_DOS                        /* #define  INCL_DOSPROCESS. */
  31. #define         INCL_ERRORS
  32. #define         INCL_WIN
  33. #define         INCL_GPI
  34. #include        <os2.h>                         /* OS/2 headers.             */
  35. #include        <pmbitmap.h>
  36.  
  37. #define         INCL_OS2MM
  38. #define         INCL_MMIO_CODEC
  39. #define         INCL_MMIO_DOSIOPROC
  40. #include        <os2me.h>                       /* Multi-Media IO extensions.*/
  41. #include        <hhpheap.h>
  42. #include        <ioi.h>
  43.  
  44.    extern HHUGEHEAP hheap;
  45.    extern HMTX hmtxGlobalHeap;
  46.  
  47.  
  48. //#define CHUNKSIZE          (pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER))
  49. // Fixes files to be parsed as true RIFF files - 0 padded if odd size chunk.
  50. #define CHUNKSIZE          ((pumchHdr->ulChunkLength % 2)                                        \
  51.                                   ? (pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER)+1)   \
  52.                                   : (pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER)))
  53.  
  54.  
  55.  
  56. /************************** START OF SPECIFICATIONS *************************/
  57. /*                                                                          */
  58. /* SUBROUTINE NAME:  IOProcRead                                             */
  59. /*                                                                          */
  60. /* DESCRIPTIVE NAME: Read data from file.                                   */
  61. /*                                                                          */
  62. /* FUNCTION: This function will read data from previously opened UltiMotion */
  63. /*           file, and return number of bytes read.                         */
  64. /*                                                                          */
  65. /* NOTES: None                                                              */
  66. /*                                                                          */
  67. /* ENTRY POINT: IOProcRead                                                  */
  68. /*   LINKAGE:   CALL FAR (00:32)                                            */
  69. /*                                                                          */
  70. /* INPUT:     PMMIOINFO pmmioinfo  - Pointer to MMIOINFO status structure.  */
  71. /*            PBYTE     pbBuffer   - Pointer to caller's buffer             */
  72. /*            LONG      lBytes     - Number of bytes to read.               */
  73. /*                                                                          */
  74. /*                                                                          */
  75. /* EXIT-NORMAL:                                                             */
  76. /*              0                                                           */
  77. /*                                                                          */
  78. /* EXIT-ERROR:                                                              */
  79. /*              MMIO_ERROR                                                  */
  80. /*                                                                          */
  81. /* SIDE EFFECTS:                                                            */
  82. /*                                                                          */
  83. /*************************** END OF SPECIFICATIONS **************************/
  84. LONG IOProcRead ( PMMIOINFO pmmioinfo,
  85.                   PBYTE pbBuffer,
  86.                   LONG  lBytes )
  87.  
  88. {
  89.   LONG  rc = MMIO_SUCCESS;
  90. //LONG  lByteCount  = 0L;
  91. //PVOID pTmpReadBuffer = XXXBuffer;
  92. //PVOID pTmpRec;
  93. //PSZ   pLocalBuffer;
  94. //PRECMAP precmap;
  95. //PINSTANCE  pinstance;
  96. //PUMCHUNKHEADER pRecord;
  97. //ULONG TrackWanted = 0L;
  98. //ULONG BufferLengthCount = 0L;
  99. //ULONG DataOffset = 0L;
  100. //
  101. //
  102. // if (rc = ioGetPtrInstance(pmmioinfo,&pinstance))
  103. //      return(rc);
  104. //
  105. //  if (XXXBuffer == (PSZ) 0L){
  106. //     pmmioinfo->ulErrorRet = MMIOERR_INVALID_PARAMETER;
  107. //     return(MMIO_ERROR);
  108. //     }
  109. // /* Test byte count requested.*/
  110. //  if (lBytes <= 0L) {
  111. //     pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  112. //     return(MMIO_ERROR);
  113. //     }
  114. //
  115. //  if (pinstance->lFileCurrentPosition >= pinstance->ulFileLen){
  116. //     pmmioinfo->ulErrorRet = MMIOERR_EOF_SEEN;
  117. //     return(0L);
  118. //     }
  119. //
  120. //  if ((pinstance->lFileCurrentPosition + lBytes) >= pinstance->ulFileLen){
  121. //      lBytes = pinstance->ulFileLen - pinstance->lFileCurrentPosition;
  122. //      }
  123. //
  124. // /***************************************************************************/
  125. // /* if a particular track is not requested to be read, do the normal read   */
  126. // /* which is to read the requested lBytes to the buffer passed, then return.*/
  127. // /***************************************************************************/
  128. //  if (pinstance->lCurrentTrack == RESETTRACKS){
  129. //      if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)){
  130. //          lBytes = mmioRead(pinstance->hmmioFileHandle,XXXBuffer,lBytes);
  131. //          if (lBytes < 0L){
  132. //             pmmioinfo->ulErrorRet = mmioGetLastError(pinstance->hmmioFileHandle);
  133. //             return(MMIO_ERROR);
  134. //             }
  135. //          pinstance->lFileCurrentPosition += lBytes;
  136. //          return(lBytes);
  137. //          }/* end if */
  138. //      else{
  139. //          pmmioinfo->ulErrorRet = MMIOERR_INVALID_ACCESS_FLAG;
  140. //          return(MMIO_ERROR);
  141. //          }
  142. //      }/* end if lCurrentTrack */
  143. //
  144. // /***************************************************************************/
  145. // /* If a particular track is requested:                                     */
  146. // /* the following process will read only data from track.                   */
  147. // /***************************************************************************/
  148. //  if (ioFindTracki(pinstance,(ULONG)pinstance->lCurrentTrack)){
  149. //      if (pinstance->pTempBuffer == NULL){
  150. // ENTERCRIT
  151. //          if ((pinstance->pTempBuffer = HhpAllocMem(hheap,DEFAULTBUFFERSIZE)) == NULL){
  152. //               pmmioinfo->ulErrorRet = MMIOERR_OUTOFMEMORY;
  153. //               return(MMIO_ERROR);
  154. //               }
  155. // EXITCRIT
  156. //          pinstance->ulTempBufferSize;
  157. //          }/* end if */
  158. //
  159. //      while (lByteCount < lBytes){
  160. //            if (pinstance->lLastTrack == pinstance->lCurrentTrack){
  161. //                if (pinstance->pLastBuffer){
  162. //                    memcpy(pTmpReadBuffer,pinstance->pLastBuffer,pinstance->ulLastBufferOffset);
  163. //                    BufferLengthCount   = pinstance->ulLastBufferOffset;
  164. //                    }
  165. //                }
  166. //            if (!pinstance->lLastTrack){
  167. //                pRecord = (PUMCHUNKHEADER)pinstance->pTempBuffer;// move to 1st stat. after while.??
  168. //                pTmpRec = pinstance->pTempBuffer;
  169. //                rc = mmioRead(pinstance->hmmioFileHandle,
  170. //                              (PSZ)pinstance->pTempBuffer,
  171. //                              pinstance->ulTempBufferSize);
  172. //                pinstance->lFileCurrentPosition += pinstance->ulTempBufferSize;
  173. //                }/* end if */
  174. //            while(lByteCount < lBytes){
  175. //                 /***********************************************************/
  176. //                 /* IF last temp buffer has copied a portion of the data of */
  177. //                 /* a record to user buffer,now we want to copy the remained*/
  178. //                 /* data of the record to user buffer. ELSE we ignore that  */
  179. //                 /* block of data and advance pRecord to next record.       */
  180. //                 /***********************************************************/
  181. //                  if (TrackWanted){
  182. //                      memcpy(pTmpReadBuffer,pinstance->pTempBuffer,BufferLengthCount);
  183. //                      pTmpRec = (PVOID)(BufferLengthCount + (ULONG)pTmpRec);
  184. //                      pRecord = (PUMCHUNKHEADER)pTmpRec;
  185. //                      TrackWanted = 0L;
  186. //                      }/* end if */
  187. //                  else{
  188. //                      pTmpRec = (PVOID)(BufferLengthCount + (ULONG)pTmpRec);
  189. //                      pRecord = (PUMCHUNKHEADER)pTmpRec;
  190. //                      }/* end else */
  191. //                 /***********************************************************/
  192. //                 /* Base on pRecord->usID, we find record map entry.        */
  193. //                 /***********************************************************/
  194. //                  precmap = ffFindRecordMap(pRecord->usID,VOIDPARM);
  195. //                  if (precmap == NULL){  /* precmap must be found. */
  196. //                      pmmioinfo->ulErrorRet = MMIOERR_MATCH_NOT_FOUND;
  197. //                      return(MMIO_ERROR);
  198. //                      }/* end if */
  199. //                 /***********************************************************/
  200. //                 /* Increments BufferLengthCount by a whole block of record.*/
  201. //                 /* Check if the pRecord spans temp buffer,then see if that */
  202. //                 /* record has a track# we're interested in, if yes, check  */
  203. //                 /* user buffer space then copy a whole block of record to  */
  204. //                 /* user buffer. If user buffer can't store the whole block */
  205. //                 /* of data, copy as much as possible and return.           */
  206. //                 /***********************************************************/
  207. //                  BufferLengthCount += RECSIZE;
  208. //                  if (BufferLengthCount <= pinstance->ulTempBufferSize){
  209. //                      if (precmap->ulTrackID == pinstance->lCurrentTrack){
  210. //                          if((lByteCount + RECSIZE) <= lBytes){
  211. //                              memcpy(pTmpReadBuffer,pinstance->pTempBuffer,RECSIZE);
  212. //                              lByteCount += RECSIZE;
  213. //                              pTmpReadBuffer = (PVOID)(RECSIZE + (ULONG)pTmpReadBuffer);
  214. //                              }/* end if */
  215. //                          else{/* copy as much as possible. */
  216. //                              memcpy(pTmpReadBuffer,pRecord,(lBytes - lByteCount));
  217. //                              pinstance->pLastBuffer        = (PVOID)((lBytes - lByteCount) + (LONG)pTmpRec);
  218. //                              pinstance->ulLastBufferOffset = (pinstance->ulTempBufferSize -
  219. //                                                            (RECSIZE - (lBytes - lByteCount)) );
  220. //                              lByteCount = lBytes;
  221. //                              break;
  222. //                              }/* end else */
  223. //                          }/* end if precmap */
  224. //                 //     if (pTmpRec = (PVOID)(RECSIZE + (ULONG)pTmpRec)){
  225. //                 //         pRecord = pTmpRec;
  226. //                 //         }
  227. //                 //     else{ break; }
  228. //                      }/* end if */
  229. //                 /***********************************************************/
  230. //                 /* A pRecord block spans the temp buffer: check if that is */
  231. //                 /* a record need to be copied to user buffer, if yes, copy */
  232. //                 /* it to user buffer though that is not a whole block, the */
  233. //                 /* rest will be copied after the temp buffer is refilled.  */
  234. //                 /***********************************************************/
  235. //                  else{
  236. //                      DataOffset = (pRecord->ulLength -
  237. //                                   (BufferLengthCount - pinstance->ulTempBufferSize) +
  238. //                                   (sizeof(UMCHUNKHEADER)) );
  239. //
  240. //                      if (precmap->ulTrackID == pinstance->lCurrentTrack){
  241. //                          if((lByteCount + DataOffset) <= lBytes){
  242. //                              memcpy(pTmpReadBuffer,pRecord,DataOffset);
  243. //                              pTmpReadBuffer = (PVOID)(DataOffset + (ULONG)pTmpReadBuffer);
  244. //                              lByteCount += DataOffset;
  245. //                              }
  246. //                          else{ /* copy as much as possible. */
  247. //                              memcpy(pTmpReadBuffer,pRecord,(lBytes - lByteCount));
  248. //                              pinstance->pLastBuffer        = (PVOID)((lBytes - lByteCount) + (LONG)pTmpRec);
  249. //                              pinstance->ulLastBufferOffset = (pinstance->ulTempBufferSize -
  250. //                                                            (DataOffset - (lBytes - lByteCount)) );
  251. //                              lByteCount = lBytes;
  252. //                              break;
  253. //                              }
  254. //                          TrackWanted = 1L;
  255. //                          }/* end if precmap */
  256. //
  257. //                      BufferLengthCount   = RECSIZE - DataOffset;
  258. //                      pinstance->lLastTrack = 0L;
  259. //                      break;
  260. //                      }/* end else */
  261. //                  }/* end while */
  262. //            }/* end while */
  263. //      pinstance->lLastTrack = pinstance->lCurrentTrack;
  264. //      precmap->ptracki->ulLastReadPos = 0L; //???????????
  265. //
  266. //      }/* end if */
  267. //  else{/* not valid track */
  268. //      pmmioinfo->ulErrorRet = MMIOERR_MATCH_NOT_FOUND;
  269. //      return(MMIO_ERROR);
  270. //      }
  271. //  return(lBytes);
  272. //
  273.    return(rc);
  274. }
  275.  
  276.  
  277. /************************** START OF SPECIFICATIONS *************************/
  278. /*                                                                          */
  279. /* SUBROUTINE NAME:  ffRoundChunkLength                                     */
  280. /*                                                                          */
  281. /* DESCRIPTIVE NAME: Round out the length of chunk to even boundary         */
  282. /*                                                                          */
  283. /* FUNCTION: This function checks for BETA content files and ignores this   */
  284. /*           rounding effect. Otherwise, round chunk length to even bounds. */
  285. /*                                                                          */
  286. /* NOTES: None                                                              */
  287. /*                                                                          */
  288. /* ENTRY POINT: ffRoundChunkLength                                          */
  289. /*   LINKAGE:   CALL FAR (00:32)                                            */
  290. /*                                                                          */
  291. /* INPUT:                                                                   */
  292. /*                                                                          */
  293. /*                                                                          */
  294. /* EXIT-NORMAL:                                                             */
  295. /*              ulChunkSize                                                 */
  296. /*                                                                          */
  297. /* EXIT-ERROR:                                                              */
  298. /*              MMIO_ERROR                                                  */
  299. /*                                                                          */
  300. /* SIDE EFFECTS:                                                            */
  301. /*                                                                          */
  302. /*************************** END OF SPECIFICATIONS **************************/
  303. ULONG ffRoundChunkLength ( PINSTANCE pinstance,
  304.                            PUMCHUNKHEADER  pumchHdr)
  305.  
  306. {
  307.    ULONG           ulChunkSize;
  308.    PUMVIDEOHEADER  pumvh;
  309.  
  310.    /*******************************************************************/
  311.    /* Parse BETA (semi-riff) files ok (BETA PROVIDED CONTENT ONLY)    */
  312.    /*******************************************************************/
  313.    pumvh = (PUMVIDEOHEADER)((ULONG)pinstance->pRawHdr + sizeof(UMCHUNKHEADER));
  314.  
  315.    if (pumvh->Reserved[0] == HEX_FOURCC_FFIO) {                               /*BETAONLY*/
  316.       ulChunkSize = pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER);   /*BETAONLY*/
  317.       }                                                                       /*BETAONLY*/
  318.    else {
  319.       if (pumchHdr->ulChunkLength % 2) {
  320.          ulChunkSize = pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER)+1;
  321.          }
  322.       else {
  323.          ulChunkSize = pumchHdr->ulChunkLength + (ULONG)sizeof(UMCHUNKHEADER);
  324.          }
  325.       }
  326.  
  327.    return(ulChunkSize);
  328. }
  329.  
  330.  
  331. /************************** START OF SPECIFICATIONS *************************/
  332. /*                                                                          */
  333. /* SUBROUTINE NAME:  ffSavePartialFrame                                     */
  334. /*                                                                          */
  335. /* DESCRIPTIVE NAME: Save the leftover of a frame to temp buffer.           */
  336. /*                                                                          */
  337. /* FUNCTION: This function saves any leftover data from this read into a    */
  338. /*           temp buffer for the next read to use.                          */
  339. /*                                                                          */
  340. /* NOTES: None                                                              */
  341. /*                                                                          */
  342. /* ENTRY POINT: ffSavePartialFrame                                          */
  343. /*   LINKAGE:   CALL FAR (00:32)                                            */
  344. /*                                                                          */
  345. /* INPUT:                                                                   */
  346. /*                                                                          */
  347. /*                                                                          */
  348. /* EXIT-NORMAL:                                                             */
  349. /*              MMIO_SUCCESS                                                */
  350. /*                                                                          */
  351. /* EXIT-ERROR:                                                              */
  352. /*              MMIO_ERROR                                                  */
  353. /*                                                                          */
  354. /* SIDE EFFECTS:                                                            */
  355. /*                                                                          */
  356. /*************************** END OF SPECIFICATIONS **************************/
  357. LONG ffSavePartialFrame(PINSTANCE pinstance,
  358.                         PMMMULTITRACKREAD pmtread,
  359.                         ULONG  ulSaveLen,
  360.                         PVOID pSaveData)
  361.  
  362. {
  363.    pinstance->ulDataInTempBuffer = ulSaveLen;
  364.  
  365.    /* if temp buffer is not big enough, enlarges the size of buffer. */
  366.    if (ulSaveLen > pinstance->ulTempBufferSize) {
  367.       ENTERCRITX;
  368.       HhpFreeMem(hheap,pinstance->pTempBuffer);
  369.  
  370.       if ((pinstance->pTempBuffer  = HhpAllocMem(hheap,ulSaveLen)) == NULL) {
  371.          EXITCRIT;
  372.          return(MMIOERR_OUTOFMEMORY);
  373.          }
  374.       EXITCRIT;
  375.       }
  376.  
  377.    pinstance->ulLastBufferOffset    = (ULONG)0L;
  378.  
  379.    if (ulSaveLen) {
  380.       memcpy(pinstance->pTempBuffer,pSaveData,ulSaveLen);
  381.       pmtread->ulFlags = (ULONG)0L;
  382.       }
  383.  
  384.    return(MMIO_SUCCESS);
  385. }
  386.  
  387.  
  388.  
  389. /************************** START OF SPECIFICATIONS *************************/
  390. /*                                                                          */
  391. /* SUBROUTINE NAME: IOProcMultiTrackRead                                    */
  392. /*                                                                          */
  393. /* DESCRIPTIVE NAME: Read and sorts data, send them to a proper track.      */
  394. /*                                                                          */
  395. /* FUNCTION: MMMULTITRACKREAD     contains a pBuffer, a track list which    */
  396. /*           has valid track numbers of the current file. Each track carries*/
  397. /*           a table, each element of the table is a pvoid pointer(pRecord).*/
  398. /*           This function reads data to the pBuffer passed, goes through   */
  399. /*           every record, maps the track number based on record ID;        */
  400. /*           If a track number of the record is found, and the table is     */
  401. /*           not full, then sets pRecord to the record.  The function       */
  402. /*           also supports two frequently happened situations:              */
  403. /*           1) The last record in pBuffer is often read incompletely, this */
  404. /*              means that record length spans pBuffer.  When this happens, */
  405. /*              we don't set a pRecord to that record, copy the data to the */
  406. /*              Temp Buffer instead.  When next IOProcReadInterLeaved is    */
  407. /*              called, that record will be returned.                       */
  408. /*           2) If one of the tables in track list is filled, the sorting   */
  409. /*              process is terminated, return whatever has been sorted to   */
  410. /*              caller, the remainded data will be sorted when next         */
  411. /*              IOProcReadInterLeaved is called.                            */
  412. /*                                                                          */
  413. /*                                                                          */
  414. /* NOTES:                                                                   */
  415. /*                                                                          */
  416. /* ENTRY POINT: IOProcMultiTrackRead                                        */
  417. /*   LINKAGE:   CALL FAR (00:32)                                            */
  418. /*                                                                          */
  419. /* INPUT:       PMMIOINFO              pmmioinfo                            */
  420. /*              PMMMULTITRACKREAD      pmtread                              */
  421. /*                                                                          */
  422. /* EXIT-NORMAL:                                                             */
  423. /*              0                                                           */
  424. /*                                                                          */
  425. /* EXIT-ERROR:                                                              */
  426. /*              MMIO_ERROR                                                  */
  427. /*                                                                          */
  428. /*                                                                          */
  429. /* SIDE EFFECTS:                                                            */
  430. /*                                                                          */
  431. /*************************** END OF SPECIFICATIONS **************************/
  432. LONG IOProcMultiTrackRead ( PMMIOINFO pmmioinfo,
  433.                              PMMMULTITRACKREAD pmtread )
  434.  
  435. {
  436.    LONG            rc;                           /* Return code */
  437.    PINSTANCE       pinstance;                    /* Ptr to movie instance structure */
  438.    PVOID           pReadBuffer;                  /* Ptr to buffer to read data from storage device into */
  439.    PVOID           pTemp;                        /* Ptr to each record.     */
  440.    ULONG           BufferLengthCounter = 0L;     /* Counter of bufferlength.*/
  441. //-BOOL            fFirstPalette = FALSE;        /* First palette flag.     */
  442.    BOOL            fReturnFrame = TRUE;          /* Return this frame data to caller */
  443.    ULONG           Counter = 0L;
  444.    LONG            lBytes;                       /* Buffer length.     */
  445.    PTRACKMAP       ptrackmap;                    /* Ptr to track map.       */
  446.    PESRCBUFTAB     pesrcbuftab;                  /* Ptr to escrbuftab array. */
  447.    PUMCHUNKHEADER  pumchHdr;                     /* Pointer to record prefix block.*/
  448.    PUSHORT         pusTrackNum;                  /* Pointer to record prefix block.*/
  449.    PTRACKI         ptracki;                      /* Pointer to internal track structure */
  450.    PTRACKI         ptrackiExtAudio;              /* Pointer to an external audio file track */ /*EXTAUDIO*/
  451.    ULONG           ulReadBufferLen = 0L;         /* Read buffer real size (minus ext audio part) */ /*EXTAUDIO*/
  452.    ULONG           ulExtAudBufLen = 0L;          /* Ext audio buffer size */                   /*EXTAUDIO*/
  453.    ULONG           ulVidDuration = 0L;           /* Duration of video frames read */           /*EXTAUDIO*/
  454.    PMMAUDIOHEADER  pmmAudioHdr;                  /* Audio header ptr        */                 /*EXTAUDIO*/
  455.  
  456.  
  457.    if (rc = ioGetPtrInstance(pmmioinfo,&pinstance))
  458.       return(rc);     // Always MMIO_ERROR
  459.  
  460. //-if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA){          /* Seek needs this flag set, so don't fail here */
  461. //    pmmioinfo->ulErrorRet = MMIOERR_INVALID_ACCESS_FLAG;
  462. //    return(MMIO_ERROR);
  463. //----}
  464.  
  465.    pReadBuffer = pmtread->pBuffer;
  466.  
  467.    if (rc = ioValidateRead(pinstance,
  468.                            pReadBuffer,
  469.                            pmtread->ulNumTracks,
  470.                            pmtread->pTrackMapList)) {
  471.       pmmioinfo->ulErrorRet = rc;
  472.       return(MMIO_ERROR);
  473.       }
  474.  
  475.  
  476.    /*******************************************************************/  /*EXTAUDIO*/
  477.    /* Determine if any of the tracks refer to an external audio file  */  /*EXTAUDIO*/
  478.    /*******************************************************************/  /*EXTAUDIO*/
  479.    if (ptrackiExtAudio = ffFindExtAudioTrack(pinstance,                   /*EXTAUDIO*/
  480.                                              pmtread->ulNumTracks,        /*EXTAUDIO*/
  481.                                              pmtread->pTrackMapList)) {  /*EXTAUDIO*/
  482.  
  483.       /**************************************************************************/
  484.       /* Compute the percentage of buffer should be reserved for external audio */
  485.       /**************************************************************************/
  486.       pmmAudioHdr = (PMMAUDIOHEADER)ptrackiExtAudio->pTrackHeader;                            /*EXTAUDIO*/
  487.       ulExtAudBufLen =  (ULONG) ((float)pmtread->ulLength / EXTAUDIOPERCENT);                 /*EXTAUDIO*/
  488.       ulExtAudBufLen += (ulExtAudBufLen % pmmAudioHdr->mmXWAVHeader.WAVEHeader.usBlockAlign); /*EXTAUDIO*/
  489.       }
  490.    ulReadBufferLen = pmtread->ulLength - ulExtAudBufLen;                                      /*EXTAUDIO*/
  491.  
  492.    /**************************************************************************/
  493.    /* check to make sure that we are still within the Data Frame List chunk  */
  494.    /**************************************************************************/
  495.    if ((pinstance->lFileCurrentPosition >= pinstance->ulMisc1) ||
  496.        (pinstance->lFileCurrentPosition < pinstance->ulMisc2)) {
  497.       if (ptrackiExtAudio) {    /* Check for external audio data left to read */     /*EXTAUDIO*/
  498.          //                                                                          /*EXTAUDIO*/
  499.          // ##BILL - add call to the code to check for audio data! - make the code   /*EXTAUDIO*/
  500.          //          at the end of this routine into a routine that is callable      /*EXTAUDIO*/
  501.          //          at this point to recover real audio data!!!!!!!                 /*EXTAUDIO*/
  502.          //                                                                          /*EXTAUDIO*/
  503. #ifdef MMDEBUG                                                                       /*EXTAUDIO*/
  504.          DosBeep(500,600);     // Let them know !                                    /*EXTAUDIO*/
  505. #endif                                                                               /*EXTAUDIO*/
  506.          // if no external audio data                                                /*EXTAUDIO*/
  507.          return(MMIOERR_CHUNKNOTFOUND);                                              /*EXTAUDIO*/
  508.          }                                                                           /*EXTAUDIO*/
  509.       else                                                                           /*EXTAUDIO*/
  510.          return(MMIOERR_CHUNKNOTFOUND);
  511.       }                                                                              /*EXTAUDIO*/
  512.  
  513.    /**************************************************************************/
  514.    /* Sets pumchHdr to a first chunk header         which is expected in the */
  515.    /* beginning of the pBuffer after read.                                   */
  516.    /**************************************************************************/
  517.    pumchHdr = (PUMCHUNKHEADER)pReadBuffer;
  518.    pTemp = pReadBuffer;
  519.    lBytes = ulReadBufferLen;
  520.  
  521.    /**************************************************************************/
  522.    /* check if there is data need to be copied from TempBuffer to pBuffer.   */
  523.    /**************************************************************************/
  524.    if (pinstance->ulDataInTempBuffer) {
  525.  
  526.       if (ulReadBufferLen <= pinstance->ulDataInTempBuffer) {
  527.          pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  528.          return(MMIO_ERROR);
  529.          }
  530.  
  531.       memcpy(pReadBuffer,pinstance->pTempBuffer,pinstance->ulDataInTempBuffer);
  532.       pTemp = (PVOID)(pinstance ->ulDataInTempBuffer + (ULONG)pReadBuffer);
  533.       lBytes  -= pinstance->ulDataInTempBuffer;
  534.       Counter  = pinstance->ulDataInTempBuffer;
  535.       pinstance->ulDataInTempBuffer = 0L;
  536.       }
  537.  
  538.    /**************************************************************************/
  539.    /* if previous sorting encountered READINTERLEAVED_NOTDONE, caller has    */
  540.    /* to pass back the previous pBuffer (if not, error returned), then sets  */
  541.    /* pumchHdr to a position where the last sorting stopped at.  This read   */
  542.    /* doesn't read data to pBuffer, and only sorts record from previous      */
  543.    /* pBuffer.                                                               */
  544.    /**************************************************************************/
  545.    if (pinstance->ulLastBufferOffset) {
  546.  
  547.       if(pinstance->pLastBuffer != pReadBuffer) {
  548.          pmmioinfo->ulErrorRet = MMIOERR_INVALID_PARAMETER;
  549.          return(MMIO_ERROR);
  550.          }
  551.  
  552.       else {
  553.          BufferLengthCounter = pinstance->ulLastBufferOffset;
  554.          pTemp = (PVOID)(pinstance->ulLastBufferOffset + (ULONG)pTemp);
  555.          pumchHdr = (PUMCHUNKHEADER)pTemp;
  556.          }
  557.       }
  558.  
  559.    /**************************************************************************/
  560.    /* else read data to buffer, and update file pos in instant structure.    */
  561.    /*   If Buffer length is greater than the data leaves in the file, read   */
  562.    /*   the rest of the data to buffer, set the END_OF_FILE flag on.         */
  563.    /**************************************************************************/
  564.    else {
  565.       if ((pinstance->ulMisc1 - (ULONG)pinstance->lFileCurrentPosition) <= lBytes) {
  566.          lBytes = (pinstance->ulMisc1 - (ULONG)pinstance->lFileCurrentPosition);
  567.          pmtread->ulFlags |= MULTITRACKREAD_EOF;
  568.          }
  569.  
  570.       lBytes = mmioRead(pinstance->hmmioFileHandle,pTemp,lBytes);
  571.       pinstance->lFileCurrentPosition += lBytes;
  572.       Counter += lBytes;
  573.       pTemp = pumchHdr;
  574.       }
  575.  
  576.    /**************************************************************************/
  577.    /* Starts sorting frames into the corresponding tracks                    */
  578.    /**************************************************************************/
  579.    while (pumchHdr != NULL) {
  580.  
  581.       /***********************************************************************/
  582.       /* Check for some bytes left at end of buffer. Not enough to form      */
  583.       /* a chunk header and ushort track number. So must save them away in   */
  584.       /* temp buffer for next time. (Boundary condition check)               */
  585.       /***********************************************************************/
  586.       if (((ULONG)pumchHdr + sizeof(UMCHUNKHEADER) + sizeof(USHORT)) >
  587.           ((ULONG)pReadBuffer + ulReadBufferLen)) {
  588.  
  589.          if (rc = ffSavePartialFrame(pinstance,
  590.                                      pmtread,
  591.                                      ((ULONG)pReadBuffer + ulReadBufferLen) - (ULONG)pumchHdr,
  592.                                      (PVOID)pumchHdr)) {
  593.             pmmioinfo->ulErrorRet = rc;
  594.             return(MMIO_ERROR);
  595.             }
  596. //-------return(MMIO_SUCCESS);
  597.          break;
  598.          }
  599.  
  600.  
  601.       /* Check for chapter list chunk headers, ignore them */
  602.       if ((pumchHdr->ulChunkID == FOURCC_LIST) &&
  603.           ((pumchHdr+1)->ulChunkID == HEX_UMFORM_CHAPTERDATALIST)) {
  604.  
  605.          pTemp   = (PVOID) (sizeof(UMCHUNKHEADER) + SIZEOF_FORM + (ULONG)pTemp);
  606.          pumchHdr = (PUMCHUNKHEADER) pTemp;
  607.          BufferLengthCounter += sizeof(UMCHUNKHEADER)+SIZEOF_FORM;   /* implement counter by the chunk size. */
  608.          }
  609.  
  610.       BufferLengthCounter += ffRoundChunkLength(pinstance,pumchHdr);   /* implement counter by the chunk size. */
  611.       pusTrackNum = (PUSHORT)(pumchHdr+1);  /* Point at first ushort after chunk hdr */
  612.  
  613.       /* Find track structure */
  614.       if (!(ptracki = ioFindTracki(pinstance,*pusTrackNum))) {
  615.          pmmioinfo->ulErrorRet = MMIOERR_MATCH_NOT_FOUND;
  616.          return(MMIO_ERROR);
  617.          }
  618.  
  619.  
  620.       /**********************************************************************/
  621.       /* If a record is not completely read and stored in the Buffer, we    */
  622.       /* don't return that record, and we want to copy the data to a        */
  623.       /* Temp Buffer.                                                       */
  624.       /**********************************************************************/
  625.       if (BufferLengthCounter > ulReadBufferLen) {
  626.          /*
  627.           * if a record's length is > than buffer length, returns error.
  628.           */
  629.          if ((pumchHdr == pReadBuffer) && (ffRoundChunkLength(pinstance,pumchHdr) > ulReadBufferLen)) {
  630.              pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  631.              return(MMIO_ERROR);
  632.              }
  633.  
  634. //-------/*
  635. //        * if first palette, returns without copying data to temp buffer.
  636. //        */
  637. //       if (IS_PALETTE_RECORD(precmap)) {
  638. //          if (pinstance->ulFlags & HAVE_PALETTE) {            //##BILL - need to be on track basis!!
  639. //             pinstance->ulFlags &= ~HAVE_PALETTE;
  640. //     #no->   return(MMIO_SUCCESS);       (break;)                //FIX-READ_BYTES
  641. //             }
  642. //----------}
  643.  
  644.          if (rc = ffSavePartialFrame(pinstance,
  645.                                      pmtread,
  646.                                      (ffRoundChunkLength(pinstance,pumchHdr) -
  647.                                       (BufferLengthCounter - ulReadBufferLen)),
  648.                                      (PVOID)pumchHdr)) {
  649.             pmmioinfo->ulErrorRet = rc;
  650.             return(MMIO_ERROR);
  651.             }
  652.          break;
  653.          }  /* end if BufferLengthCounter > */
  654.  
  655.       /**********************************************************************/
  656.       /* Before setting pesrcbuftab->pRecord to a track:                    */
  657.       /* 1/FindRecordMap matches usID, which is gotten from data, with      */
  658.       /*   the recmaptable,if found, address of an entry in table will be   */
  659.       /*   returned.                                                        */
  660.       /* 2/FindTrackMapEntry matches track# of pTrackMapList, that is in    */
  661.       /*   pmtread, with track# of precmap. If found, address               */
  662.       /*   of the entry in pTrackMapList will be returned.                  */
  663.       /* 3/The 1st and 2nd steps are successful, next we validate track,    */
  664.       /*   make sure the sorted track that the IOProc supports.             */
  665.       /**********************************************************************/
  666. //----if (IS_PALETTE_RECORD(precmap)) {
  667. //       if (pinstance->ulFlags & HAVE_PALETTE) {            //##BILL - need to be on track basis!!
  668. //          fFirstPalette = TRUE;
  669. //          fReturnFrame = FALSE;
  670. //          pinstance->ulFlags &= ~HAVE_PALETTE;
  671. //          }
  672. //-------}
  673. //----else if () {
  674.  
  675.  
  676.       /*************************************************************/
  677.       /* Check for SCAN Mode, return only Key Frames               */
  678.       /*************************************************************/
  679.       if (pinstance->ulMode == MODE_SCANREAD) {
  680.          if (((PVIDEOFRAME)(pumchHdr+1))->ulFrameFlags == UM_VIDEO_FRAME_FLAG_DELTAFRAME) {
  681.             fReturnFrame = FALSE;
  682.             }
  683.          }
  684.  
  685.       if (fReturnFrame) {
  686.          if(ptrackmap = ioFindTrackMapEntry(pmtread->pTrackMapList,
  687.                                             pmtread->ulNumTracks,
  688.                                             *pusTrackNum))      {
  689.  
  690.             /*************************************************************/
  691.             /* check paesrcbuftab did not overflow. This is the NOT DONE */
  692.             /* condition that implies that no more records entries are   */
  693.             /* available for this buffer.                                */
  694.             /*************************************************************/
  695.             if (ptrackmap->ulNumEntries < ptracki->ulNumEntries) {
  696.                pesrcbuftab = (PESRCBUFTAB)ptrackmap->pRecordTabList;
  697.                pesrcbuftab += ptrackmap->ulNumEntries;
  698.                pesrcbuftab->pBuffer = pReadBuffer;
  699.                pesrcbuftab->pRecord  = (PVOID)(pumchHdr+1);
  700.                pesrcbuftab->ulLength = pumchHdr->ulChunkLength;
  701.  
  702.                if (!IS_VIDEO_TRACK(ptracki->ulMediaType)) {  /* Skip the track # if not video frame */
  703.                   pesrcbuftab->pRecord  = (PVOID) ((ULONG)pesrcbuftab->pRecord + sizeof(USHORT));
  704.                   pesrcbuftab->ulLength -= sizeof(USHORT);
  705.                   }
  706.                else if (ptrackiExtAudio) {                                                   /*EXTAUDIO*/
  707.                   ulVidDuration += ((PVIDEOFRAME)pesrcbuftab->pRecord)->ulDuration;           /*EXTAUDIO*/
  708.                   }                                                                          /*EXTAUDIO*/
  709.  
  710.                ptrackmap->ulNumEntries++;
  711.                }
  712.  
  713.             else {
  714.                pinstance->ulLastBufferOffset = BufferLengthCounter - ffRoundChunkLength(pinstance,pumchHdr);
  715.                pmtread->ulFlags |= MULTITRACKREAD_NOTDONE;
  716.                break;
  717.                }
  718.             }
  719.          } /* end if FirstPalette. */
  720.  
  721.       else
  722.          fReturnFrame = TRUE;     /* Reset after processing this frame */
  723.  
  724.       /**********************************************************************/
  725.       /* if end of file, must set pumchHdr = NULL to exit loop.             */
  726.       /**********************************************************************/
  727.       if ((pinstance->lFileCurrentPosition >= (LONG)pinstance->ulMisc1) &&
  728.          (BufferLengthCounter >= Counter)){
  729.           pumchHdr = NULL;
  730.           } /* end if */
  731.       else{
  732.           pTemp   = (PVOID)(ffRoundChunkLength(pinstance,pumchHdr) + (ULONG)pTemp);
  733.           pumchHdr = (PUMCHUNKHEADER)pTemp;
  734.           } /* end else */
  735.       } /* End while loop */
  736.  
  737.  
  738. //   /*******************************************************************************************/
  739. //   /* Read some audio into the buffer and set the first record in this trackmap to the length */
  740. //   /*******************************************************************************************/
  741. //   if (ptrackiExtAudio) {                                                   /*EXTAUDIO*/
  742. //      ULONG       ulTemp;                                                   /*EXTAUDIO*/
  743. //
  744. //      /* Compute # bytes for each MMTIME unit */                            /*EXTAUDIO*/
  745. //      ulTemp = pmmAudioHdr->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;   /*EXTAUDIO*/
  746. //      ulTemp *= pmmAudioHdr->mmXWAVHeader.WAVEHeader.ulSamplesPerSec;      /*EXTAUDIO*/
  747. //      ulTemp /= 3000;       /* # bytes/MMTIME unit */                      /*EXTAUDIO*/
  748. //      ulTemp *= ulVidDuration;                                             /*EXTAUDIO*/
  749. //      ulTemp += (ulTemp % pmmAudioHdr->mmXWAVHeader.WAVEHeader.usBlockAlign); /*EXTAUDIO*/
  750. //
  751. //      if (ulTemp >= ulExtAudBufLen) { /* too much audio, remember leftover */ /*EXTAUDIO*/
  752. //         ptrackiExtAudio->ulMisc1 += (ulTemp - ulExtAudBufLen);            /*EXTAUDIO*/
  753. //         ulTemp = ulExtAudBufLen;                                          /*EXTAUDIO*/
  754. //         }                                                                  /*EXTAUDIO*/
  755. //      else { /* Too little audio, check for any leftover audio from previous buffers */ /*EXTAUDIO*/
  756. //         lBytes = ulExtAudBufLen - ulTemp;      /* leftover amount */      /*EXTAUDIO*/
  757. //
  758. //         if (lBytes >= ptrackiExtAudio->ulMisc1) {  /* Take what is there */ /*EXTAUDIO*/
  759. //            ulTemp += ptrackiExtAudio->ulMisc1;                            /*EXTAUDIO*/
  760. //            ptrackiExtAudio->ulMisc1 = 0L;                                  /*EXTAUDIO*/
  761. //            }
  762. //         else { /* Take what I can, leave the rest */
  763. //            ulTemp += lBytes;                                              /*EXTAUDIO*/
  764. //            ptrackiExtAudio->ulMisc1 -= lBytes;                             /*EXTAUDIO*/
  765. //            }                                                               /*EXTAUDIO*/
  766. //
  767. //         ptrackiExtAudio->ulMisc1 -= (ulExtAudBufLen - ulTemp);            /*EXTAUDIO*/
  768. //         ulTemp = ulExtAudBufLen;                                          /*EXTAUDIO*/
  769. //         }                                                                  /*EXTAUDIO*/
  770. //
  771. //      /* Read audio data into buffer */                                     /*EXTAUDIO*/
  772. //      rc = mmioRead(ptracki->hmmioTrackFileHandle,                          /*EXTAUDIO*/
  773. //                    (PVOID)((ULONG)pReadBuffer+ulReadBufferLen),            /*EXTAUDIO*/
  774. //                    ulTemp);                                               /*EXTAUDIO*/
  775. //      if (rc < ulTemp)  /* Reset EOF, if more External Audio to read */    /*EXTAUDIO*/
  776. //         pmtread->ulFlags &= ~MULTITRACKREAD_EOF;                          /*EXTAUDIO*/
  777. //
  778. //      /* Find the trackmap table for this track - We know it exists */      /*EXTAUDIO*/
  779. //      ptrackmap = ioFindTrackMapEntry(pmtread->pTrackMapList,              /*EXTAUDIO*/
  780. //                                      pmtread->ulNumTracks,                  /*EXTAUDIO*/
  781. //                                      ptrackiExtAudio->ulTrackID);            /*EXTAUDIO*/
  782. //                                                                            /*EXTAUDIO*/
  783. //      /* Fill in record information for this track */                       /*EXTAUDIO*/
  784. //      pesrcbuftab = (PESRCBUFTAB)ptrackmap->pRecordTabList;  /* always use the first entry */ /*EXTAUDIO*/
  785. //      pesrcbuftab->pBuffer = pReadBuffer;                                    /*EXTAUDIO*/
  786. //      pesrcbuftab->pRecord  = (PVOID)((ULONG)pReadBuffer+ulReadBufferLen);   /*EXTAUDIO*/
  787. //      pesrcbuftab->ulLength = ulTemp;                                       /*EXTAUDIO*/
  788. //      ptrackmap->ulNumEntries++;                                            /*EXTAUDIO*/
  789. //      }                                                                     /*EXTAUDIO*/
  790.  
  791.  
  792.    /**************************************************************************/
  793.    /* Reset READINTERLEAVED_NOTDONE condition if EOF                         */
  794.    /**************************************************************************/
  795.    lBytes = Counter;                                              //FIX-READ_BYTES
  796. //-lBytes = pinstance->ulLastBufferOffset;                        //FIX-READ_BYTES
  797.    if (pmtread->ulFlags & MULTITRACKREAD_EOF) {
  798.       pinstance->ulLastBufferOffset = (ULONG)0L;
  799.       pmtread->ulFlags &= ~MULTITRACKREAD_NOTDONE;
  800.       }
  801.  
  802.    return(MMIO_SUCCESS);
  803. }
  804.