Each IOProc must be able to process the MMIOM_OPEN message, which requests that a file be opened. Once the application knows which IOProc is associated with the selected file, it can open the file using mmioOpen. The application references the appropriate IOProc using the FOURCC provided by the identification process.

A file format IOProc must check for the following items when the MMIO Manager issues an MMIOM_OPEN message.

If the OPEN was successful, the application can obtain information about the media in the file using the mmioGetHeaderInfo message.

The following example illustrates how to handle the MMIOM_OPEN message for a file format IOProc. The MMIOM_OPEN message handler uses the mmioOpen function to locate a media data object using an MMIO-supported storage system IOProc. Upon opening the data object, an hmmio handle (H1) is returned to the file format IOProc. This handle is saved in the aulInfo[1] field of MMIOINFO for the file format IOProc. Upon the return to the mmioOpen function issued by the application, you will notice that another handle (H2) was already generated and returned to the application. These handles allow access to the data object. The application will use H2, and the file format IOProc will use H1 with MMIO function calls to the storage system IOProc.

The following example shows an example of how the M-Motion IOProc supports the MMIOM_OPEN message.

case MMIOM_OPEN:    {
    /************************************************************
     * Declare local variables
     ************************************************************/
    PMMFILESTATUS   pVidInfo;   /* pointer to an M-Motion file    */
                                /* status structure that we will*/
                                /* use for this file instance   */
    MMIMAGEHEADER   MMImgHdr;
    ULONG           ulRequiredFileLength;
    ULONG           ulActualFileLength;
    ULONG           ulWidth;
    ULONG           ulHeight;
    PBYTE           lpYUVBuf;
    ULONG           ulRowCount;
    ULONG           ulRGBBytesPerLine;
    ULONG           ulYUVBytesPerLine;
    LONG            rc;
    HMMIO           hmmioSS;
    PBYTE           lpRGBBufPtr;
    FOURCC          fccStorageSystem;   /* SS I/O Proc FOURCC       */
    MMIOINFO        mmioinfoSS;         /* I/O info block for SS ref*/
    PSZ pszFileName = (CHAR *)lParam1;  /* get the filename from    */
                                        /* parameter                */
    /************************************************************
     * Check for valid MMIOINFO block.
     ************************************************************/
    if (!pmmioinfo)
        return (MMIO_ERROR);
    /************************************************************
     * If flags show read and write then send back an error.  We
     * only support reading or writing but not both at the same
     * time on the same file.
     ************************************************************/
    if ((pmmioinfo->ulFlags & MMIO_READWRITE) &&
        ((pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) ||
         (pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER)))
        {
        return (MMIO_ERROR);
        }
    /*********************************************************
     *   Determine the storage system/child IOProc that actually
     *   obtains the data for us.  The M-Motion data may be contained
     *   in a memory (RAM) file, as a component in a database or
     *   library (a Compound file), or as a stand-alone disk file.
     *
     *   While the application uses this M-Motion IOProc to obtain
     *   untranslated (M-Motion) or translated (bitmap) data,
     *   the IOProc must obtain it's data from something that
     *   reads and writes to a storage media.  The exact storage
     *   media is immaterial - so long as the read and write
     *   operations generate data that LOOKS like it is part
     *   of a standard file.
     *********************************************************/
    if (!pmmioinfo->fccChildIOProc)
       {
       /* Need to determine SS if create from pmmioinfo and filename. */
       if (pmmioinfo->ulFlags & MMIO_CREATE)
          {
          if (mmioDetermineSSIOProc( pszFileName,
                                     pmmioinfo,
                                     &fccStorageSystem,
                                     NULL ))
             {
             fccStorageSystem = FOURCC_DOS;
             }
          }
       else
          {
          if (mmioIdentifyStorageSystem( pszFileName,
                                         pmmioinfo,
                                         &fccStorageSystem ))
             {
             return (MMIO_ERROR);
             }

          }

       if (!fccStorageSystem)
          {
          return (MMIO_ERROR);
          }
       else
          {
          pmmioinfo->fccChildIOProc = fccStorageSystem;
          }
       } /* end storage system identification block */
    /**************************************************************
     * Direct the open to the specific storage system necessary
     **************************************************************/
    memset( &mmioinfoSS, '\0', sizeof(MMIOINFO));
    memmove( &mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
    mmioinfoSS.pIOProc = NULL;
    mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
    mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
    /************************************************************
     * Try to open the file.  Add the NO IDENTIFY flag to
     *    ENSURE THAT WE DON'T LOOP RECURSIVELY!!!
     ************************************************************/
    hmmioSS = mmioOpen (pszFileName,
                        &mmioinfoSS,
                        mmioinfoSS.ulFlags);
    /************************************************************
     * Check if a DELETE was requested - mmioOpen returns a 1,
     *    so we much check this separately
     ************************************************************/
    if (pmmioinfo->ulFlags & MMIO_DELETE)
       {
       /* was the delete successful?         */
       if (!hmmioSS)
          {
          pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
          return (MMIO_ERROR);
          }
       else
          {
          return (MMIO_SUCCESS);
          }
       }
    /************************************************************
     * Check the return code from the open call for an error.
     *    If not delete, then the open should have worked.
     ************************************************************/
    if (!hmmioSS)
        return (MMIO_ERROR);
    /************************************************************
     * Allocate memory for one M-Motion FileStatus structures
     ************************************************************/
    DosAllocMem ((PPVOID) &pVidInfo,
                          sizeof (MMFILESTATUS),
                          fALLOC);
    /************************************************************
     * Ensure the allocate was successful.  If not, then
     *   close the file and return open as unsuccessful...
     ************************************************************/
    if (!pVidInfo)
       {
       mmioClose (hmmioSS, 0);
       return (MMIO_ERROR);
    pVidInfo->hmmioSS = hmmioSS;
    /************************************************************
     * Store pointer to our MMFILESTATUS structure in
     * pExtraInfoStruct field that is provided for our use.
     ************************************************************/
    pmmioinfo->pExtraInfoStruct = (PVOID)pVidInfo;
    /************************************************************
     * Set the fields of the FileStatus structure that the
     * IOProc is responsible for.
     ************************************************************/
    InitFileStruct (pVidInfo);
    /*********************************************************
     * If this is a read, we need to check that is a M-Motion
     *    file and perhaps get the data.
     *********************************************************/
    if (pmmioinfo->ulFlags & MMIO_READ)
       {
       /*********************************************************
        * First we must get some basic information from the file
        * Read in data to fill up the MMOTIONHEADER structure.
        *
        * If the read is unsuccessful, this is not a M-Motion file
        * and we should return a failure on the open
        *********************************************************/
       if (sizeof (MMOTIONHEADER) !=
                           mmioRead (pVidInfo->hmmioSS,
                                     (PVOID) &pVidInfo->mmotHeader,
                                     (ULONG) sizeof (MMOTIONHEADER)))
           {
           mmioClose (pVidInfo->hmmioSS, 0);
           DosFreeMem ((PVOID) pVidInfo);
           return (MMIO_ERROR);
           }
       /* Ensure this IS an M-Motion file header before we continue  */
       if (strcmp (pVidInfo->mmotHeader.mmID, "YUV12C"))
           {
           mmioClose (pVidInfo->hmmioSS, 0);
           DosFreeMem ((PVOID) pVidInfo);
           return (MMIO_ERROR);
           }
       /********************************************************
        * Set up width and height of image.
        ********************************************************/
       ulWidth  = (ULONG)pVidInfo->mmotHeader.mmXlen;
       ulHeight = (ULONG)pVidInfo->mmotHeader.mmYlen;
       /* Calculate what the length of the file SHOULD be based on the */
       /*   header contents                                            */
       ulRequiredFileLength = (((ulWidth >> 2) * 6) * ulHeight) +
                                              sizeof (MMOTIONHEADER);

       /* Query what the ACTUAL length of the file is,                 */
       /*   then move back to just after the header.                   */
       ulActualFileLength = (ULONG)mmioSeek (pVidInfo->hmmioSS,
                                            0, SEEK_END);

       mmioSeek (pVidInfo->hmmioSS, sizeof (MMOTIONHEADER), SEEK_SET);
       /* If these don't match, then it isn't a VALID M-Motion file    */
       /*    - regardless of what the header says.                     */
       if (ulRequiredFileLength != ulActualFileLength)
           {
           mmioClose (pVidInfo->hmmioSS, 0);
           DosFreeMem ((PVOID) pVidInfo);
           return (MMIO_ERROR);
           }

       /************************************************************
        * If the app intends to read in translation mode, we must
        * allocate and set-up the buffer that will contain the RGB data.
        *
        * We must also read in the data to insure that the first
        * read, seek, or get-header operation will have data
        * to use.  This is ONLY NECESSARY FOR TRANSLATED MODE
        * operations, since we must process reads/writes pretending
        * the image is stored from the bottom-up.
        *
        ************************************************************
        ************************************************************
        * Fill out the MMIMAGEHEADER structure.
        ************************************************************/
       MMImgHdr.ulHeaderLength = sizeof (MMIMAGEHEADER);
       MMImgHdr.ulContentType  = MMIO_IMAGE_PHOTO;
       MMImgHdr.ulMediaType    = MMIO_MEDIATYPE_IMAGE;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbFix =
                   sizeof (BITMAPINFOHEADER2);
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cx              = ulWidth;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cy              = ulHeight;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cPlanes         = 1;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount       = 24;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulCompression   =
           BCA_UNCOMP;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbImage         =
           ulWidth * ulHeight * 3;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cxResolution    = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cyResolution    = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrUsed        = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrImportant   = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usUnits         = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usReserved      = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRecording     =
           BRA_BOTTOMUP;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRendering     =
           BRH_NOTHALFTONED;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize1          = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize2          = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulColorEncoding = 0L;
       MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulIdentifier    = 0L;
       /************************************************************
        * Copy the image header into private area for later use.
        * This will be returned on a mmioGetHeader () call
        ************************************************************/
       pVidInfo->mmImgHdr = MMImgHdr;
       /********************************************************
        * YUV Bytes/Line are = 1 1/2 times the number of pels
        ********************************************************/
       ulYUVBytesPerLine = ulWidth + (ulWidth >> 1);

       /********************************************************
        * RGB Bytes/Line are = 2* YUV bytes/line
        ********************************************************/
       ulRGBBytesPerLine = (ulYUVBytesPerLine << 1);

       /********************************************************
        * Determine total bytes in image
        ********************************************************/
       pVidInfo->ulRGBTotalBytes = ulWidth * ulHeight * 3;

       /********************************************************
        * M-Motion images are always on 4-pel boundaries, which also
        * makes them on 4-byte/LONG boundaries, which is used for
        * bitmaps.  Therefore, there are no extra pad bytes necessary.
        ********************************************************/
       pVidInfo->ulImgPaddedBytesPerLine = ulWidth * 3;
       pVidInfo->ulImgTotalBytes = pVidInfo->ulRGBTotalBytes;
       /*********************************************************
        * For translated data READ mode, we must allocate a buffer,
        * get the YUV data from the file, and load the RGB buffer.
        * Place format-specific code here to load the image into the
        * buffer.  The code below is M-Motion format specific.
        *********************************************************/
       if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)
          {
          /********************************************************
           * Get space for full image buffer.
           * This will be retained until the file is closed.
           ********************************************************/
          if (DosAllocMem ((PPVOID) &(pVidInfo->lpRGBBuf),
                            pVidInfo->ulRGBTotalBytes,
                            fALLOC))
              {
              mmioClose (pVidInfo->hmmioSS, 0);
              DosFreeMem ((PVOID) pVidInfo);
              return (MMIO_ERROR);
              }

          /********************************************************
           * Get temporary space for one line YUV buffer.
           ********************************************************/
          if (DosAllocMem ((PPVOID) &lpYUVBuf,
                           ulYUVBytesPerLine,
                           fALLOC))
              {
              mmioClose (pVidInfo->hmmioSS, 0);
              DosFreeMem ((PVOID) pVidInfo);
              return (MMIO_ERROR);
              }
          /********************************************************
           * Initialize the beginning buffer position.
           ********************************************************/
          lpRGBBufPtr = pVidInfo->lpRGBBuf;

          /********************************************************
           * Read in YUV data one line at a time, converting
           * from YUV to RGB, then placing in the image buffer.
           ********************************************************/
          for (ulRowCount = 0;
               ulRowCount < ulHeight;
               ulRowCount++)

              {
              /****************************************************
               * Read in one line.
               ****************************************************/
              rc = mmioRead (pVidInfo->hmmioSS,
                             (PVOID) lpYUVBuf,
                             (ULONG) ulYUVBytesPerLine);

              /****************************************************
               * Convert one line at a time.
               ****************************************************/
              ConvertOneLineYUVtoRGB (lpYUVBuf,
                                      lpRGBBufPtr,
                                      ulYUVBytesPerLine);

              /****************************************************
               * Make sure buffer ptr is correct for the next convert.
               ****************************************************/
              lpRGBBufPtr += (LONG)ulRGBBytesPerLine;
              }   /* end of FOR loop to read YUV data */
          DosFreeMem (lpYUVBuf);

          /********************************************************
           * This changes from M-Motion's top-down form to OS/2
           * PM's bottom-up bitmap form.
           ********************************************************/
          ImgBufferFlip (pVidInfo->lpRGBBuf,
                         pVidInfo->ulImgPaddedBytesPerLine,
                         ulHeight);
          /********************************************************
           * RGB buffer now full, set position pointers to the
           * beginning of the buffer.
           ********************************************************/
          pVidInfo->lImgBytePos =  0;
          }   /*  end IF TRANSLATED block */
       } /* end IF READ block */
    return (MMIO_SUCCESS);
    } /* end case of MMIOM_OPEN */


[Back] [Next]