home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / source / mmpm2src / riffsamp / riffsamp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-18  |  74.3 KB  |  2,038 lines

  1.  
  2. /*******************************************************************************
  3.  * File Name   : RIFFSAMP.C
  4.  *
  5.  * Description : This file contains the C source code required for the RIFF
  6.  *               compound file sample program.  This sample allows the user
  7.  *               to Add a wave file to a RIFF compound file.  The user can
  8.  *               delete the wave element from the RIFF compound file, play
  9.  *               the wave element from the RIFF compound file and compact
  10.  *               the RIFF compound file by deleting the data for all deleted
  11.  *               entries in Compound File Resource group of a compound file.
  12.  *               There are two list boxes, one list box contains the names of
  13.  *               wave files which can be added to the RIFF compound file.
  14.  *               The other list box has the names of the elements in RIFF
  15.  *               compound file.  The following abbreviations are used
  16.  *               throughout the sample:
  17.  *               CGRP - Compound File Resource Group
  18.  *               CTOC - Compound File Table of Contents
  19.  *
  20.  *
  21.  * Concepts    : This program illustrates how to create a RIFF compound file,
  22.  *               how to Add a Wave file to RIFF compound file, how to play and
  23.  *               delete elements from a Compound file and how to compact a
  24.  *               RIFF file.  This program also illustrates how to use
  25.  *               variable length structures.
  26.  *
  27.  * MMPM/2 API's: List of all MMPM/2 API's that are used in this module.
  28.  *
  29.  *               mciSendCommand
  30.  *                  MCI_ACQUIREDEVICE
  31.  *                  MCI_OPEN
  32.  *                  MCI_PLAY
  33.  *                  MCI_CLOSE
  34.  *               mciGetErrorString
  35.  *               mmioOpen
  36.  *               mmioRead
  37.  *               mmioClose
  38.  *               mmioCFGetInfo
  39.  *               mmioCFOpen
  40.  *               mmioCFAddElement
  41.  *               mmioCFDeleteEntry
  42.  *               mmioCFCompact
  43.  *
  44.  *
  45.  * Required
  46.  *    Files    : riffsamp.c         Source Code.
  47.  *               riffsamp.h         Include file.
  48.  *               riffsamp.dlg       Dialog definition.
  49.  *               riffsamp.rc        Resources.
  50.  *               riffsamp.ipf       Help text.
  51.  *               makefile           Make file.
  52.  *               riffsamp.def       Linker definition file.
  53.  *               riffsamp.ico       RiffSamp icon.
  54.  *               riff1.wav          1st Wave File Played.
  55.  *               riff2.wav          2nd Wave File Played.
  56.  *               riff3.wav          3rd Wave File Played.
  57.  *
  58.  * Copyright (C) IBM  1993
  59.  ******************************************************************************/
  60.  
  61. #define  INCL_DOS                   /* required to use Dos APIs.           */
  62. #define  INCL_WIN                   /* required to use Win APIs.           */
  63. #define  INCL_PM                    /* required to use PM APIs.            */
  64. #define  INCL_OS2MM                 /* required for MCI and MMIO headers   */
  65. #define  INCL_WINHELP               /* required to use IPF.                */
  66. #define  INCL_SECONDARYWINDOW       /* required for secondary window       */
  67.  
  68. #include <os2.h>
  69. #include <stdio.h>
  70. #include <os2me.h>
  71. #include <stdlib.h>
  72.  
  73. #define INCL_HEAP
  74. #define INCL_DBCSCRT
  75. #include <sw.h>
  76. #include <swp.h>
  77.  
  78. #include "riffsamp.h"               /* Dialog Ids, Resource Ids etc        */
  79.  
  80. #define RIFF_COMPOUND_FILE "RIFFSAMP.BND"
  81. #define HELP_FILE "riffsamp.HLP"
  82. #define STRING_SIZE 356
  83. /*******************************************************************/
  84.  
  85. /* Procedure / Function prototypes */
  86.  
  87. #pragma linkage( MainDialogProc, system)
  88. MRESULT EXPENTRY MainDialogProc(HWND, ULONG, MPARAM, MPARAM);
  89. void main(int i,char *p[]);
  90. void InitializeDialog(void);
  91. void Finalize(void);
  92. VOID InitializeHelp( VOID );
  93. USHORT ShowAMessage( USHORT usTitleId,
  94.                      USHORT usTextId,
  95.                      ULONG  ulMessageBoxStyle,
  96.                      BOOL   fMCIError);
  97. BOOL FillListBoxWithWaves(HWND hwnd);
  98. void OpenRIFFCompoundFile(ULONG ulFlags);
  99. BOOL AddElementToRIFF(PSZ achFileName,SHORT sFileNum,HWND hwnd);
  100. BOOL DeleteEntryFromRIFF(PSZ pszElementName, SHORT sFile,HWND hwnd);
  101. PMMCTOCENTRY GetCTOCEntryInfo(PSZ pszElementName);
  102. BOOL CompactTheRIFFCompoundFile();
  103. void  EnableButtons(HWND hwnd);
  104. void PlayElement(HWND hwnd,PSZ pszElementName);
  105. void CloseRiffCompoundFile(HWND hwnd);
  106. /*******************************************************************/
  107.  
  108. /* Global Variables */
  109.  
  110. HAB      hab;                           /* anchor block handle           */
  111. QMSG     qmsg;                          /* Message Que                   */
  112. HMQ      hmq;
  113. HWND     hwndDiag;                      /* Application Dialog handle     */
  114. HWND     hwndFrame;                     /* Application Frame handle      */
  115. BOOL     fPassedDevice = FALSE;         /* Do we own the Audio device    */
  116. CHAR     achHelpTitle[STRING_SIZE];     /* Title for the Help            */
  117. HWND     hwndHelpInstance;              /* Handle to Help window         */
  118. HELPINIT hmiHelpStructure;              /* Help init. structure          */
  119. BOOL     fPlayDisable  = FALSE;         /* Is Play pushbutton disabled   */
  120. BOOL     fDelDisable   = FALSE;         /* Is Delete pushbutton disabled */
  121. BOOL     fCompactDisable = FALSE;       /* Is Compact pushbutton disabled*/
  122. BOOL     fAddDisable   = FALSE;         /* Is Add pushbutton disabled    */
  123. USHORT   usWaveDeviceId;                /* Device Id to play             */
  124. HMMIO    hmmioCF = (HMMIO)0;            /* Handle to RIFF compound file  */
  125. BOOL     fRIFFExists  = FALSE;          /* If RIFF file is open          */
  126.  
  127.  
  128.  
  129. /******************************************************************************
  130.  * Name         : main
  131.  *
  132.  * Description  : This function calls the Intialize procedure to prepare
  133.  *                everything for the program's operation, enters the
  134.  *                message loop, then call Finalize to shut everything down
  135.  *                when the program is terminated.
  136.  *
  137.  * Concepts     : None.
  138.  *
  139.  * MMPM/2 API's : None.
  140.  *
  141.  * Parameters   : argc - Number of parameters passed into the program.
  142.  *                argv - Command line parameters.
  143.  *
  144.  * Return       : None.
  145.  *
  146.  *************************************************************************/
  147. void main(int argc, char *argv[])
  148. {
  149. InitializeDialog();
  150.  
  151. /* Handle the messages: */
  152. while(WinGetMsg(hab,&qmsg,0,0,0))
  153.         WinDispatchMsg(hab,&qmsg);
  154.  
  155. Finalize();
  156.  
  157. }
  158.  
  159. /*************************************************************************
  160.  * Name         : InitializeDialog
  161.  *
  162.  * Description  : This function performs the necessary initializations and
  163.  *                setups that are required to show/run a dialog box as a
  164.  *                main window.  The message queue will be created, as will
  165.  *                the dialog box.
  166.  *
  167.  * Concepts     : Secondary Windows is used to create and show a dialog box.
  168.  *                A system clock is displayed till the application is loaded.
  169.  *
  170.  * MMPM/2 API's : WinLoadSecondaryWindow
  171.  *                WinQuerySecondaryHWND
  172.  *
  173.  * Parameters   : None.
  174.  *
  175.  * Return       : None.
  176.  *
  177.  *************************************************************************/
  178. void InitializeDialog()
  179. {
  180. CHAR achTitle[STRING_SIZE] = "";
  181. CHAR achDefaultSize[STRING_SIZE] = "";
  182.  
  183.  
  184.    /*
  185.     * Setup and initialize the dialog window.
  186.     * Change pointer to a waiting pointer first, since this might take a
  187.     * couple of seconds.
  188.     */
  189.  
  190.  
  191.    WinSetPointer(
  192.       HWND_DESKTOP,        /* Desktop window handle.                    */
  193.       WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  194.          HWND_DESKTOP,     /* Desktop window handle.                    */
  195.          SPTR_WAIT,        /* The waiting icon.                         */
  196.          FALSE ) );        /* Return the system pointer's handle.       */
  197.  
  198.    /* Initialize the Dialog window */
  199.    hab = WinInitialize(0);
  200.  
  201.    /* create a message queue for the window */
  202.    hmq = WinCreateMsgQueue(hab,0);
  203.  
  204.  
  205.  
  206.    /* Load the Dialog - This will return the Handle to the Frame */
  207.    hwndFrame =
  208.        WinLoadSecondaryWindow(HWND_DESKTOP
  209.                             ,HWND_DESKTOP
  210.                             ,(PFNWP)MainDialogProc
  211.                             ,(HMODULE)NULL
  212.                             ,ID_DLG_MAIN
  213.                             ,(PVOID)NULL);
  214.  
  215.  
  216.    /*
  217.     * By specifying the QS_DIALOG flag we will get the handle to the Dialog of
  218.     * the frame
  219.     */
  220.    hwndDiag = WinQuerySecondaryHWND(hwndFrame,QS_DIALOG);
  221.  
  222.    /* Get the string for default size */
  223.    WinLoadString(
  224.       hab,
  225.       (HMODULE) NULL,
  226.       IDS_DEFAULT_SIZE,
  227.       (SHORT) sizeof( achDefaultSize),
  228.       achDefaultSize);
  229.    /* Add Default Size menu item to system menu of the secondary window. */
  230.    WinInsertDefaultSize(hwndFrame, achDefaultSize);
  231.  
  232.    /*
  233.     * Get the window title string from the Resource string table
  234.     * and set it as the window text for the dialog window.
  235.     */
  236.    WinLoadString(
  237.       hab,
  238.       (HMODULE) NULL,
  239.       IDS_MAIN_WINDOW_TITLE,
  240.       (SHORT) sizeof( achTitle),
  241.       achTitle);
  242.  
  243.    /* Set the Title of the Dialog */
  244.    WinSetWindowText( hwndFrame, achTitle);
  245.  
  246.  
  247.    /*
  248.     * Now that we're done with initialization, so we don't the need the waiting
  249.     * icon, so we are going to change the pointer back to the arrow.
  250.     */
  251.  
  252.    WinSetPointer(
  253.       HWND_DESKTOP,        /* Desktop window handle.                    */
  254.       WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  255.          HWND_DESKTOP,     /* Desktop window handle.                    */
  256.          SPTR_ARROW,       /* The Arrow icon.                           */
  257.          FALSE ) );        /* Return the system pointer's handle.       */
  258.  
  259.    /*
  260.     * Initialize the help structure and associate the help instance to this
  261.     * dialog via it's handle to anchor block.
  262.     */
  263.  
  264.    InitializeHelp( );
  265.  
  266. }
  267.  
  268. /******************************************************************************
  269.  * Name        : InitializeHelp
  270.  *
  271.  * Description : This procedure will set up the initial values in the global
  272.  *               help structure.  This help structure will then be passed on
  273.  *               to the Help Manager when the Help Instance is created.  The
  274.  *               handle to the Help Instance will be kept for later use.
  275.  *
  276.  * Concepts    : None.
  277.  *
  278.  * MMPM/2 API's: None.
  279.  *
  280.  * Parameters  : None.
  281.  *
  282.  * Return      : None.
  283.  *
  284.  ******************************************************************************/
  285. VOID InitializeHelp( VOID )
  286. {
  287.    /*  Get the size of the initialization structure. */
  288.    hmiHelpStructure.cb              = sizeof( HELPINIT );
  289.  
  290.    hmiHelpStructure.ulReturnCode    = (ULONG) NULL; /* RC from initialization.*/
  291.    hmiHelpStructure.pszTutorialName = (CHAR) NULL;  /* No tutorial program.   */
  292.  
  293.    hmiHelpStructure.phtHelpTable    = (PVOID)(0xffff0000 | ID_RIFFSAMP_HELPTABLE);
  294.  
  295.    /* The action bar is not used, so set the following to NULL. */
  296.    hmiHelpStructure.hmodAccelActionBarModule = (HMODULE) NULL;
  297.    hmiHelpStructure.idAccelTable             = (USHORT) NULL;
  298.    hmiHelpStructure.idActionBar              = (USHORT) NULL;
  299.  
  300.    /* The Help window title. */
  301.    WinLoadString(
  302.       hab,                             /* HAB for this dialog box.            */
  303.       (HMODULE) NULL,                  /* Get the string from the .exe file.  */
  304.       IDS_HELP_WINDOW_TITLE,           /* Which string to get.                */
  305.       (SHORT) STRING_SIZE,             /* The size of the buffer.             */
  306.       achHelpTitle );                  /* The buffer to place the string.     */
  307.  
  308.    hmiHelpStructure.pszHelpWindowTitle  =
  309.       achHelpTitle;
  310.  
  311.    /* The Help table is in the executable file. */
  312.    hmiHelpStructure.hmodHelpTableModule = (HMODULE) NULL;
  313.  
  314.    /* The help panel ID is not displayed. */
  315.    hmiHelpStructure.fShowPanelId       = (ULONG) NULL;
  316.  
  317.    /* The library that contains the RIFF Sample help panels. */
  318.    hmiHelpStructure.pszHelpLibraryName  = HELP_FILE;
  319.  
  320.    /*
  321.     * Create the Help Instance for IPF.
  322.     * Give IPF the Anchor Block handle and address of the IPF initialization
  323.     * structure, and check that creation of Help was a success.
  324.     */
  325.    hwndHelpInstance = WinCreateHelpInstance(
  326.                          hab,                   /* Anchor Block Handle.       */
  327.                          &hmiHelpStructure );   /* Help Structure.            */
  328.  
  329.    if ( hwndHelpInstance == (HWND) NULL )
  330.    {
  331.      ShowAMessage(
  332.            IDS_ERROR_TITLE,
  333.            IDS_HELP_CREATION_ERROR,
  334.            MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL ,
  335.            FALSE);
  336.    }
  337.    else
  338.    {
  339.       if ( hmiHelpStructure.ulReturnCode )
  340.       {
  341.        ShowAMessage(
  342.            IDS_ERROR_TITLE,
  343.            IDS_HELP_CREATION_ERROR,
  344.            MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL ,
  345.            FALSE);
  346.  
  347.       WinDestroyHelpInstance( hwndHelpInstance );
  348.       }
  349.    }  /* End of IF checking the creation of the Help Instance. */
  350.  
  351.    /* Associate the Help Instance of the IPF to this dialog window. */
  352.    if ( hwndHelpInstance != (HWND) NULL )
  353.    {
  354.      WinAssociateHelpInstance(
  355.         hwndHelpInstance,     /* The handle of the Help Instance.             */
  356.         hwndFrame );          /* Associate to this dialog window.             */
  357.    }
  358.  
  359. }  /* End of InitializeHelp */
  360.  
  361. /*************************************************************************
  362.  * Name         : Finalize
  363.  *
  364.  * Description  : This routine is called after the message dispatch loop
  365.  *                has ended because of a WM_QUIT message.  The code will
  366.  *                destroy the help instance, messages queue, and window.
  367.  *
  368.  * Concepts     : None.
  369.  *
  370.  * MMPM/2 API's : None.
  371.  *
  372.  * Parameters   : None.
  373.  *
  374.  * Return       : None.
  375.  *
  376.  *************************************************************************/
  377. VOID Finalize( VOID )
  378. {
  379.    /* Destroy the Help Instance for this dialog window. */
  380.    if ( hwndHelpInstance != (HWND) NULL)
  381.    {
  382.       WinDestroyHelpInstance( hwndHelpInstance );
  383.    }
  384.  
  385.    WinDestroySecondaryWindow( hwndFrame );
  386.    WinDestroyMsgQueue( hmq );
  387.    WinTerminate( hab );
  388.  
  389. }  /* End of Finalize */
  390. /*******************************************************************************
  391.  * Name        : MainDialogProc
  392.  *
  393.  * Description : This function controls the main dialog box.  It will handle
  394.  *               received messages such as pushbutton notifications, Device
  395.  *               sharing messages, etc
  396.  *
  397.  *               The following messages are handled specifically by this
  398.  *               routine.
  399.  *
  400.  *                  WM_INITDLG
  401.  *                  WM_CLOSE
  402.  *                  WM_HELP
  403.  *                  WM_COMMAND
  404.  *                  MM_MCIPASSDEVICE
  405.  *                  WM_ACTIVATE
  406.  *
  407.  *
  408.  * Concepts    : This function illustrates the concept how the messages are
  409.  *               handled to play, add, delete and Compact elements from a
  410.  *               RIFF compound file.  A RIFF compound file is created when
  411.  *               the application recieves the WM_INITDLG message.  Then
  412.  *               appropriate functions are called when user presses
  413.  *               ADD, DELETE, COMPACT and PLAY push buttons.  The concept
  414.  *               of device sharing is also illustrated by this.
  415.  *
  416.  *
  417.  *
  418.  * MMPM/2 API's : mciSendCommand
  419.  *                   MCI_ACQUIREDEVICE
  420.  *
  421.  * Parameters   : hwnd - Handle for the Main dialog box.
  422.  *                msg  - Message received by the dialog box.
  423.  *                mp1  - Parameter 1 for the just recieved message.
  424.  *                mp2  - Parameter 2 for the just recieved message.
  425.  *
  426.  * Return       :
  427.  *
  428.  *
  429.  ******************************************************************************/
  430. MRESULT EXPENTRY MainDialogProc(
  431.                 HWND hwnd,
  432.                  ULONG msg,
  433.                  MPARAM mp1,
  434.                  MPARAM mp2)
  435. {
  436. HPOINTER  hpProgramIcon;                /* handle to program's icon        */
  437. ULONG     ulReturn;                     /* Ret Code for Dos and MCI calls  */
  438. USHORT    usCommandMessage;             /* high-word                       */
  439. SHORT     sFile;                        /* File Index Number to be added   */
  440. CHAR      achFileName[CCHMAXPATH] = ""; /* File which user selected        */
  441. static MCI_GENERIC_PARMS  lpWaveGeneric;/* Used for MCI_ACQUIREDEVICE      */
  442.  
  443.  
  444.  
  445. switch (msg)
  446.   {
  447.  
  448.  
  449.  
  450.     case WM_CLOSE:
  451.        WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
  452.        return ((MRESULT) NULL);
  453.  
  454.     case WM_HELP :
  455.        /*
  456.         * The dialog window has recieved a request for help from the user,
  457.         * i.e., the Help pushbutton was pressed.  Send the HM_DISPLAY_HELP
  458.         * message to the Help Instance with the IPF resource identifier
  459.         * for the correct HM panel.  This will show the help panel for this
  460.         * sample program.
  461.         */
  462.        WinSendMsg(
  463.           hwndHelpInstance,
  464.           HM_DISPLAY_HELP,
  465.           MPFROMSHORT( 1 ),
  466.           MPFROMSHORT( HM_RESOURCEID ) );
  467.        return( 0 );
  468.  
  469.     case WM_INITDLG:
  470.        /*
  471.         * Initialize the dialog window.
  472.         * Change pointer to a waiting pointer first, since this might take a
  473.         * couple of seconds.
  474.         */
  475.  
  476.        WinSetPointer(
  477.           HWND_DESKTOP,        /* Desktop window handle.                    */
  478.           WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  479.              HWND_DESKTOP,     /* Desktop window handle.                    */
  480.              SPTR_WAIT,        /* The waiting icon.                         */
  481.              FALSE ) );        /* Return the system pointer's handle.       */
  482.  
  483.        hpProgramIcon =
  484.           WinLoadPointer(
  485.              HWND_DESKTOP,
  486.              (HMODULE) NULL, /* Where the resource is kept. (Exe file)      */
  487.              ID_ICON );      /* Which icon to use.                          */
  488.  
  489.        WinDefSecondaryWindowProc(
  490.           hwnd,              /* Dialog window handle.                       */
  491.           WM_SETICON,        /* Message to the dialog.  Set it's icon.      */
  492.           (MPARAM) hpProgramIcon,
  493.           (MPARAM) 0 );      /* mp2 no value.                               */
  494.  
  495.        /*
  496.         * Find all files with .wav extensions and fill the list box with
  497.         * them.
  498.         */
  499.        FillListBoxWithWaves(hwnd);
  500.  
  501.        /* Disable Delete push button because there is no element to delete */
  502.        WinEnableWindow(WinWindowFromID(hwnd,ID_PB_DEL),
  503.                        FALSE);
  504.        fDelDisable = TRUE;
  505.  
  506.        /* Disable Compact push button because there is no deleted elements */
  507.        WinEnableWindow(WinWindowFromID(hwnd,ID_PB_COMPACT),
  508.                        FALSE);
  509.        fCompactDisable = TRUE;
  510.  
  511.        /* Disable play push button because there is no element to play */
  512.        WinEnableWindow(WinWindowFromID(hwnd,ID_PB_PLAY),
  513.                        FALSE);
  514.        fPlayDisable = TRUE;
  515.  
  516.        /*
  517.         * Create the RIFF compound file for reading and writing.  The Riff
  518.         * compound file is only created once during initialization, but is
  519.         * closed and opened whenever we compact the RIFF file.
  520.         */
  521.        OpenRIFFCompoundFile(MMIO_CREATE | MMIO_READWRITE);
  522.        if (!fRIFFExists)
  523.           {
  524.           /* Disable Add push button because RIFF could not be created */
  525.           WinEnableWindow(WinWindowFromID(hwnd,ID_PB_ADD),
  526.                           FALSE);
  527.           fAddDisable = TRUE;
  528.           }
  529.  
  530.        return((MRESULT)NULL);
  531.  
  532.     /*  Service all of the button pushes */
  533.     case WM_COMMAND:
  534.        switch (SHORT1FROMMP(mp1)) {
  535.          case ID_PB_ADD:
  536.             if (fRIFFExists)
  537.                {
  538.                /*
  539.                 * Riff File Exists so Query what wave file the user has
  540.                 * selected to ADD to the RIFF compound file.  This call
  541.                 * will return back the Index of the List Box item selected.
  542.                 */
  543.                sFile = (SHORT) WinSendMsg( WinWindowFromID( hwnd,
  544.                                                 ID_LB_ADD_FILE),
  545.                                            LM_QUERYSELECTION,
  546.                                            (MPARAM) LIT_FIRST,
  547.                                            (MPARAM) NULL);
  548.  
  549.                /* No item was selected, so display an error and break */
  550.                if (sFile == LIT_NONE)
  551.                   {
  552.                   ShowAMessage(
  553.                               IDS_ERROR_TITLE,
  554.                               IDS_NO_FILES_SELECTED,
  555.                               MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  556.                               FALSE);
  557.  
  558.                   break;
  559.                   }
  560.  
  561.                /* Query for the Actual text of the wave file */
  562.                WinQueryLboxItemText(WinWindowFromID(hwnd,ID_LB_ADD_FILE),
  563.                                     (LONG) sFile,
  564.                                     achFileName,
  565.                                     CCHMAXPATH);
  566.  
  567.                /*
  568.                 * Add the wave file which the user selected to the RIFF
  569.                 * compound file.  mmioCFAddElement is used to add an element.
  570.                 */
  571.                if (AddElementToRIFF(
  572.                              achFileName,
  573.                              sFile,
  574.                              hwnd))
  575.                   {
  576.                   /* Delete the wave file name from the Add file list box */
  577.                   WinSendMsg( WinWindowFromID( hwnd, ID_LB_ADD_FILE),
  578.                               LM_DELETEITEM,
  579.                               (MPARAM) sFile,
  580.                               (MPARAM) 0);
  581.  
  582.                   /* Select the first item in the Add file list box */
  583.                   WinSendMsg( WinWindowFromID (hwnd, ID_LB_ADD_FILE),
  584.                               LM_SELECTITEM,
  585.                               (MPARAM) 0,
  586.                               (MPARAM) TRUE);
  587.                   /*
  588.                    * Check if Add, Delete, Play or Compact buttons need to be
  589.                    * enabled or disabled.
  590.                    * Compact push button is enabled if the RIFF compound file
  591.                    * contains at least one non-deleted entry and at least one
  592.                    * deleted entry.  Otherwise it is disabled.
  593.                    * Play push button is enabled if the RIFF compound file
  594.                    * contains at least one non-deleted entry.  Otherwise it
  595.                    * is disabled.
  596.                    * Delete push button is enabled if the RIFF compound file
  597.                    * contains at least one non-deleted entry.  Otherwise it is
  598.                    * disabled
  599.                    * Add push button is enabled if the Add list box contains
  600.                    * at least one wave file.  Otherwise it is disabled
  601.                    * The current status of these push buttons is maintained
  602.                    * in their respective global variables e.g. fCompactDisable
  603.                    *
  604.                    */
  605.                   EnableButtons(hwnd);
  606.                   }
  607.                }
  608.             else
  609.                {
  610.                /* Riff was not created, so display an error */
  611.                ShowAMessage(
  612.                            IDS_ERROR_TITLE,
  613.                            IDS_CANT_PROCESS_MESSAGE,
  614.                            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  615.                            FALSE);
  616.                }
  617.  
  618.          break;
  619.  
  620.          case ID_PB_DEL:
  621.             if (fRIFFExists)
  622.                {
  623.                /*
  624.                 * Riff File Exists so Query what wave entry the user has
  625.                 * selected to be deleted from RIFF compound file.  This call
  626.                 * will return back the Index of the List Box item selected.
  627.                 */
  628.                sFile = (SHORT) WinSendMsg( WinWindowFromID( hwnd, ID_LB_FILE_TOC),
  629.                                            LM_QUERYSELECTION,
  630.                                            (MPARAM) LIT_FIRST,
  631.                                            (MPARAM) NULL);
  632.  
  633.                /* No item was selected, so display an error and break */
  634.                if (sFile == LIT_NONE)
  635.                   {
  636.                   ShowAMessage(
  637.                               IDS_ERROR_TITLE,
  638.                               IDS_NO_CTOC_ENTRIES_SELECTED,
  639.                               MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  640.                               FALSE);
  641.  
  642.                   break;
  643.                   }
  644.  
  645.                /* Query for the actual text of the entry selected */
  646.                WinQueryLboxItemText(WinWindowFromID(hwnd,ID_LB_FILE_TOC),
  647.                                    (LONG) sFile,
  648.                                    achFileName,
  649.                                    CCHMAXPATH);
  650.  
  651.                /*
  652.                 * Delete the entry which the user selected from the RIFF
  653.                 * compound file.  When the entry is deleted from a RIFF file
  654.                 * the function deletes a compound file table of contents (CTOC)
  655.                 * entry from an open RIFF compound file.  The data is still
  656.                 * present in the CGRP of RIFF file.  In order to delete the
  657.                 * data a mmioCFCompact or mmioCFCopy API should be used.
  658.                 */
  659.                if (DeleteEntryFromRIFF(achFileName,
  660.                                        sFile,
  661.                                        hwnd))
  662.                   {
  663.                   /*
  664.                    * Entry was deleted succesfull from CTOC of RIFF, so
  665.                    * Delete the entry name from the TOC list box.
  666.                    */
  667.                   WinSendMsg( WinWindowFromID( hwnd, ID_LB_FILE_TOC),
  668.                               LM_DELETEITEM,
  669.                               (MPARAM) sFile,
  670.                               (MPARAM) 0);
  671.  
  672.                   /* Select the first item in the CTOC list box */
  673.                   WinSendMsg( WinWindowFromID (hwnd, ID_LB_FILE_TOC),
  674.                               LM_SELECTITEM,
  675.                               (MPARAM) 0,
  676.                               (MPARAM) TRUE);
  677.                   /*
  678.                    * Check to see which  buttons need to be enabled and which
  679.                    * buttons need to be disabled
  680.                    */
  681.  
  682.                   EnableButtons(hwnd);
  683.                   }
  684.                }
  685.             else
  686.                {
  687.                /* Riff was not created, so display an error */
  688.                ShowAMessage(
  689.                            IDS_ERROR_TITLE,
  690.                            IDS_CANT_PROCESS_MESSAGE,
  691.                            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  692.                            FALSE);
  693.                }
  694.          break;
  695.  
  696.          case ID_PB_PLAY:
  697.             if (fRIFFExists)
  698.                {
  699.                /*
  700.                 * Riff File Exists so Query what wave entry the user has
  701.                 * selected to be played from RIFF compound file.  This call
  702.                 * will return back the Index of the List Box item selected.
  703.                 */
  704.                 sFile =
  705.                     (SHORT) WinSendMsg( WinWindowFromID( hwnd,
  706.                                                  ID_LB_FILE_TOC),
  707.                                         LM_QUERYSELECTION,
  708.                                         (MPARAM) LIT_FIRST,
  709.                                         (MPARAM) NULL);
  710.  
  711.                /* No item was selected, so display an error and break */
  712.                if (sFile == LIT_NONE)
  713.                   {
  714.                   ShowAMessage(
  715.                               IDS_ERROR_TITLE,
  716.                               IDS_NO_CTOC_ENTRIES_SELECTED,
  717.                               MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  718.                               FALSE);
  719.  
  720.                   break;
  721.                   }
  722.                 /* Query for the name of the element from the list box */
  723.                 WinQueryLboxItemText(WinWindowFromID(hwnd,ID_LB_FILE_TOC),
  724.                                      (LONG) sFile,
  725.                                      achFileName,
  726.                                      CCHMAXPATH);
  727.  
  728.                 /*
  729.                  * Play the element from the RIFF file which the user just
  730.                  * selected.  In order to play the element the element name
  731.                  * is concatanated with the RIFF file name and passed in
  732.                  * ElementName for MCI_OPEN message.
  733.                  */
  734.                 PlayElement(hwnd,achFileName);
  735.                 }
  736.             else
  737.                {
  738.                /* Riff was not created, so display an error */
  739.                ShowAMessage(
  740.                            IDS_ERROR_TITLE,
  741.                            IDS_CANT_PROCESS_MESSAGE,
  742.                            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  743.                            FALSE);
  744.                }
  745.          break;
  746.  
  747.          case ID_PB_COMPACT:
  748.  
  749.             if (fRIFFExists)
  750.                {
  751.                 /*
  752.                  * Riff File already exists so we want to compact it.
  753.                  * Close the Riff Compound file because in order to compact a
  754.                  * RIFF compound file it should be Closed.
  755.                  */
  756.                CloseRiffCompoundFile(hwnd);
  757.                /*
  758.                 * Compact the RIFF compound file.  Compacting basically
  759.                 * deletes the CGRP (Compound file resource group)
  760.                 * entries for all entries marked deleted in
  761.                 * CTOC (Compound File Table of Contents).
  762.                 * When an entry is deleted it is only marked deleted
  763.                 * in CTOC (table of contents) but the actual data still
  764.                 * resides in CGRP.  In order to compact it mmioCFCompact is
  765.                 * used.  mmioCFCopy can also be used to accomplist this.
  766.                 * However, mmioCFCopy generates another copy of the file.
  767.                 * This function returns TRUE if the compacting is successful.
  768.                 */
  769.                if (CompactTheRIFFCompoundFile())
  770.                   {
  771.                   /*
  772.                    * The file was successfully compacted so Open the RIFF file
  773.                    * to be used later.  More advanced applications should
  774.                    * open the RIFF compound file only when needed.
  775.                    */
  776.  
  777.                   OpenRIFFCompoundFile(MMIO_READWRITE);
  778.                   /*
  779.                    * After compacting the file disable or enable push buttons as
  780.                    * needed
  781.                    */
  782.                   EnableButtons(hwnd);
  783.                   }
  784.                }
  785.             else
  786.                {
  787.                /* Riff was not created, so display an error */
  788.                ShowAMessage(
  789.                            IDS_ERROR_TITLE,
  790.                            IDS_CANT_PROCESS_MESSAGE,
  791.                            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  792.                            FALSE);
  793.                }
  794.           break;
  795.        }
  796.       return( (MRESULT) 0);
  797.  
  798.  
  799.     case MM_MCIPASSDEVICE:
  800.        if (SHORT1FROMMP(mp2) == MCI_GAINING_USE)
  801.           {
  802.           /* Have gained use of the Audio Device so update the flag */
  803.           fPassedDevice = FALSE;
  804.  
  805.            }
  806.        else
  807.           {
  808.           /* Have lost use of the Audio Device so update the flag */
  809.           fPassedDevice = TRUE;
  810.  
  811.           }
  812.        break;
  813.  
  814.  
  815.     /*
  816.      * We use the WM_ACTIVATE message to participate in device sharing.
  817.      * We first check to see if this is an activate or a deactivate
  818.      * message (indicated by mp1). Then, we check to see if we've passed
  819.      * control of the device that we use.  If these conditions are true,
  820.      * then we issue an acquire device command to regain control of the
  821.      * device, since we're now the active window on the screen.
  822.      *
  823.      * This is one possible method that can be used to implement
  824.      * device sharing. For applications that are more complex
  825.      * than this sample program, developers may wish to take
  826.      * advantage of a more robust method of device sharing.
  827.      * This can be done by using the MCI_ACQUIRE_QUEUE flag on
  828.      * the MCI_ACQUIREDEVICE command.  Please refer to the MMPM/2
  829.      * documentation for more information on this flag.
  830.      */
  831.     case WM_ACTIVATE:
  832.        /* First we check to see if we've passed control of the device */
  833.        if ((BOOL)mp1 && fPassedDevice == TRUE)
  834.           {
  835.           lpWaveGeneric.hwndCallback =  (ULONG) hwnd;
  836.           ulReturn = mciSendCommand( usWaveDeviceId,
  837.                                      MCI_ACQUIREDEVICE,
  838.                                      (ULONG)MCI_WAIT,
  839.                                      (PVOID)&lpWaveGeneric,
  840.                                      (USHORT)NULL );
  841.           if (ulReturn != 0)
  842.              {
  843.              /* This is an MCI Error so show the message by passing TRUE */
  844.              ShowAMessage(
  845.                      IDS_ERROR_TITLE,
  846.                      ulReturn,
  847.                      MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL,
  848.                      TRUE);
  849.              }
  850.  
  851.           }
  852.        return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  853.        default:
  854.           return ( WinDefDlgProc( hwnd, msg, mp1, mp2 ) );
  855.     }
  856. }
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863. /******************************************************************************
  864.  * Name        : ShowAMessage
  865.  *
  866.  * Description : This function will show text in a message box.
  867.  *               If the Message is an MCI Error then the text is pulled
  868.  *               by issuing a mciGetErrorString.  The text is retrieved by the
  869.  *               Return code of the mci call which failed.
  870.  *               If the Message is not an MCI Error then the text
  871.  *               is pulled from the string table that is originally kept
  872.  *               in the resource file .  The text is retrieved by the
  873.  *               message id that is passed into this function.  This id is
  874.  *               used in the WinLoadString OS/2 API to get the correct
  875.  *               string from the table.
  876.  *
  877.  * Concepts    : None.
  878.  *
  879.  * MMPM/2 API's: mciGetErrorString
  880.  *
  881.  * Parameters  : usTitleId         - The tile id that identifies which string
  882.  *                                   to retrieve from the string table.
  883.  *               usTextId          - The message text to be placed in the
  884.  *                                   message box.  This value is the Return
  885.  *                                   value for the failed MCI call if fMCIError
  886.  *                                   is true and is the Message id (application
  887.  *                                   owned) if fMCIError is False.
  888.  *               ulMessageBoxStyle - The style of the message box.  Which
  889.  *                                   icons, buttons, etc., to show.
  890.  *               fMCIError         - If the Error is an MCIError (TRUE) or
  891.  *                                   if it is an application message id (FALSE).
  892.  *
  893.  * Return      : The result from the message box.
  894.  *
  895.  ******************************************************************************/
  896. USHORT ShowAMessage( USHORT usTitleId,
  897.                      USHORT usTextId,
  898.                      ULONG  ulMessageBoxStyle,
  899.                      BOOL   fMCIError)
  900. {
  901.  
  902.    CHAR   achStringBuffer[ STRING_SIZE ];       /* Title String Buffer.      */
  903.    USHORT usMessageBoxResult;                   /* RC from WinMessageBox.    */
  904.    CHAR   achMessageText[STRING_SIZE];          /* Message String Buffer     */
  905.    ULONG  ulReturn;                             /* Return from MCI ERROR     */
  906.  
  907.    /*
  908.     * Load the Title for the message box from the string table defined in
  909.     * the resources.
  910.     */
  911.  
  912.    WinLoadString(
  913.       hab,                           /* HAB for this dialog box.            */
  914.       (HMODULE) NULL,                /* Get the string from the .exe file.  */
  915.       usTitleId,                     /* Which string to get.                */
  916.       (SHORT) STRING_SIZE,           /* The size of the buffer.             */
  917.       achStringBuffer );             /* The buffer to place the string.     */
  918.  
  919.    /* If we are to show a MCIERROR, then load it by mciGetErrorString API */
  920.    if (fMCIError)
  921.      {
  922.         ulReturn =
  923.             mciGetErrorString(
  924.                             usTextId,
  925.                             (PSZ)achMessageText,
  926.                             (USHORT) STRING_SIZE );
  927.  
  928.  
  929.            /*
  930.             * Make sure that the retrieving of the error string was successfull.
  931.             */
  932.            if ( ulReturn != MCIERR_SUCCESS )
  933.              {
  934.               WinLoadString(
  935.                     hab,                       /* HAB for this dialog box.   */
  936.                     (HMODULE) NULL,            /* Get string from .exe file. */
  937.                     IDS_CANT_PROCESS_MESSAGE,  /* Which string to get.       */
  938.                     (SHORT) STRING_SIZE,       /* The size of the buffer.    */
  939.                     achMessageText);           /* Buffer to place the string.*/
  940.  
  941.               ulMessageBoxStyle = MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
  942.                                   MB_APPLMODAL;
  943.              }  /* End of IF testing for failed Get Error String API. */
  944.  
  945.      }
  946.    else
  947.      {
  948.      /*
  949.       This is not an MCIError so load the Text for Message Box from
  950.       the string table defined in the resources.
  951.       */
  952.        WinLoadString(
  953.            hab,                     /* HAB for this dialog box.   */
  954.            (HMODULE) NULL,          /* Get string from .exe file. */
  955.            usTextId,                /* Which string to get.       */
  956.            (SHORT) STRING_SIZE,     /* The size of the buffer.    */
  957.            achMessageText );        /* Buffer to place the string.*/
  958.      }
  959.    usMessageBoxResult =
  960.       WinMessageBox(
  961.          HWND_DESKTOP,              /* Parent handle of the message box.   */
  962.          hwndDiag,                  /* Owner handle of the message box.    */
  963.          achMessageText,            /* String to show in the message box.  */
  964.          achStringBuffer,           /* Title to shown in the message box.  */
  965.          ID_MESSAGE_BOX,            /* Message Box Id.                     */
  966.          ulMessageBoxStyle );       /* The style of the message box.       */
  967.  
  968.    return( usMessageBoxResult );
  969.  
  970. }  /* End of ShowAMessage */
  971.  
  972. /******************************************************************************
  973.  * Name        : FillListBoxWithWaves
  974.  *
  975.  * Description : This function will fill the Add File List Box with all the
  976.  *               wave files which are found in the current directory.
  977.  *               All the files with .wav extension are going to be added to
  978.  *               this list and the focus is going to be on the first wave
  979.  *               file.  These wave files can be later added on to the compound
  980.  *               RIFF file by selecting them from the Add File list box.
  981.  *               This function is called during initialization.
  982.  *
  983.  * Concepts    : None.
  984.  *
  985.  * MMPM/2 API's:
  986.  *
  987.  * Parameters  : hwnd              - Handle to the dialog of the application
  988.  *
  989.  * Return      : None.
  990.  *
  991.  ******************************************************************************/
  992.  
  993. BOOL FillListBoxWithWaves(HWND hwnd)
  994. {
  995.    CHAR          achPath[256] = "";
  996.    FILEFINDBUF3  ffb;
  997.    ULONG         ulCount = 1;
  998.    APIRET        rc;
  999.    HDIR          hdir = HDIR_CREATE;
  1000.    BOOL          fFound = FALSE;
  1001.  
  1002.    /* Search for all files with .wav extension */
  1003.    strcpy(achPath,"*.wav");
  1004.  
  1005.    /* Find the first file matching this .wav pattern */
  1006.    if (!(rc = DosFindFirst(achPath,       /* file name pattern        */
  1007.                    &hdir,                 /* dir handle               */
  1008.                    0,                     /* normal files             */
  1009.                    (PVOID)&ffb,           /* result buffer            */
  1010.                    sizeof(ffb),           /* size of buffer           */
  1011.                    &ulCount,              /* number to find = 1       */
  1012.                    FIL_STANDARD)))        /* return level 1 file info */
  1013.       {
  1014.       /* Found at least on file */
  1015.       fFound = TRUE;
  1016.       /* Insert the found file into the ADD file list box */
  1017.       WinSendMsg( WinWindowFromID( hwnd, ID_LB_ADD_FILE),
  1018.                   LM_INSERTITEM,
  1019.                  (MPARAM) LIT_END,
  1020.                  ffb.achName);
  1021.  
  1022.       ulCount = 1;
  1023.       /* Keep on searching for more files till no more exist */
  1024.  
  1025.       while (!DosFindNext(hdir,           /* dir handle            */
  1026.                           &ffb,           /* result buffer         */
  1027.                           sizeof(ffb),    /* size of result buffer */
  1028.                           &ulCount))      /* number to find        */
  1029.            {
  1030.  
  1031.            WinSendMsg( WinWindowFromID( hwnd, ID_LB_ADD_FILE),
  1032.                        LM_INSERTITEM,
  1033.                       (MPARAM) LIT_END,
  1034.                       ffb.achName);
  1035.            ulCount = 1;
  1036.            }
  1037.  
  1038.       /* select the first wave in the listbox by default */
  1039.  
  1040.       WinSendMsg( WinWindowFromID (hwnd, ID_LB_ADD_FILE),
  1041.                   LM_SELECTITEM,
  1042.                   (MPARAM) 0,
  1043.                   (MPARAM) TRUE);
  1044.       }
  1045.    else
  1046.      {
  1047.      /* No Wave files found, so display a message */
  1048.      ShowAMessage(
  1049.            IDS_ERROR_TITLE,
  1050.            IDS_NO_WAVE_FILES,
  1051.            MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL ,
  1052.            FALSE);
  1053.  
  1054.      }
  1055.  
  1056.   return fFound;
  1057.  
  1058. }
  1059.  
  1060. /******************************************************************************
  1061.  * Name        : OpenRIFFCompoundFile
  1062.  *
  1063.  * Description : This function will either Open the RIFF compound file
  1064.  *               or  Create the Riff Compound file depending upon the ulFlags
  1065.  *               passed in.  This function is first called to create the RIFF
  1066.  *               file and then later it is called to open it.  This sample
  1067.  *               program keeps the RIFFSAMP.BND compound file open at all
  1068.  *               time and only closes the file to compact it.
  1069.  *               After performing these actions the RIFF file is opened again.
  1070.  *               A global variable fRIFFExists is set to TRUE or FALSE
  1071.  *               depending upon if the opening of the RIFF file was successful.
  1072.  *
  1073.  * Concepts    : How to open and create a compound RIFF file.
  1074.  *
  1075.  * MMPM/2 API's: mmioCFOpen
  1076.  *
  1077.  * Parameters  : ulFlags              - Flags for opening the file.
  1078.  *                                      MMIO_CREATE creates the file
  1079.  *                                      MMIO_READWRITE opens it for reading and
  1080.  *                                      writing
  1081.  *
  1082.  * Return      : None.
  1083.  *
  1084.  ******************************************************************************/
  1085. void OpenRIFFCompoundFile(ULONG ulFlags)
  1086. {
  1087.  
  1088.  /*
  1089.   * Either Opens the  RIFF file  for reading and writing or creates it
  1090.   * depeneding on the ulFlags.  If ulFlags = MMIO_CREATE | MMIO_READWRITE
  1091.   * then the RIFF file is created for reading and writing.  This creation is
  1092.   * only done once during the initialization of the dialog.
  1093.   * If ulFlags = MMIO_READWRITE then the RIFF file is opened for reading and
  1094.   * writing.
  1095.  */
  1096.  hmmioCF = mmioCFOpen( (PSZ)RIFF_COMPOUND_FILE,
  1097.                         NULL,
  1098.                         NULL,
  1099.                         ulFlags);
  1100.  
  1101.  /* Call the error routine if RIFF compound file could not be created */
  1102.  if (!hmmioCF)
  1103.     {
  1104.      ShowAMessage(
  1105.            IDS_ERROR_TITLE,
  1106.            IDS_RIFF_CREATION_ERROR,
  1107.            MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL ,
  1108.            FALSE);
  1109.      fRIFFExists = FALSE;
  1110.     }
  1111.  else
  1112.     {
  1113.     fRIFFExists = TRUE;
  1114.     }
  1115.  
  1116. }
  1117.  
  1118. /******************************************************************************
  1119.  * Name        : AddElementToRIFF
  1120.  *
  1121.  * Description : This function will first call another function to get the
  1122.  *               pmmctocentry structure.  Then a mmio call is made to try to
  1123.  *               find the pszElementName in CTOC.  If the
  1124.  *               the entry does not exist, then the wave file is opened
  1125.  *               and read into a buffer and then added to the Compound RIFF
  1126.  *               file.  mmioCFAddElement is used to add the Wave file into
  1127.  *               compound file.  This mmio call takes care of adding the entry
  1128.  *               name to the CTOC and adding the element data to CGRP.  CTOC
  1129.  *               list box is updated with the new element being added.
  1130.  *               e.g. if the user selects RIFF1.WAV to be added to the
  1131.  *               compound file, an element called "RIFF1" is added if
  1132.  *               it already does not exist.
  1133.  *
  1134.  *
  1135.  * Concepts    : How to Add an element and an entry to a compound RIFF file.
  1136.  *
  1137.  * MMPM/2 API's: mmioOpen
  1138.  *               mmioStringToFOURCC
  1139.  *               mmioRead
  1140.  *               mmioCFAddElement
  1141.  *               mmioCFFindEntry
  1142.  *
  1143.  * Parameters  : pszEntryName         - Name of the Entry (or the wave file)
  1144.  *                                      to be added to the compound RIFF file
  1145.  *               sFileNum             - Index of the wave file in the Add File
  1146.  *                                      list box.
  1147.  *               hwnd                 - Handle to the Dialog.
  1148.  *
  1149.  * Return      : TRUE                 - If RIFF added successfully
  1150.  *               FALSE                - If RIFF could not be added.
  1151.  *
  1152.  ******************************************************************************/
  1153. BOOL AddElementToRIFF(PSZ pszEntryName,
  1154.                       SHORT sFileNum,
  1155.                       HWND hwnd)
  1156. {
  1157.  
  1158.   ULONG        dwReturn;
  1159.   FOURCC       fccType;
  1160.   MMIOINFO     mmioinfo;
  1161.   HMMIO        hmmioSource;
  1162.   FILESTATUS3  FileInfoBuf;
  1163.   CHAR         *pchAppBuffer;
  1164.   CHAR         achElementName[CCHMAXPATH] = "";
  1165.   PSZ          psz;
  1166.   ULONG        ulRC;
  1167.   ULONG        ulFlags;
  1168.   LONG         lBytesRead;
  1169.   PMMCTOCENTRY pmmctocentry;
  1170.   BOOL         fSuccess = FALSE;
  1171.  
  1172.   /*
  1173.    * Convert the entry name to the element name.  Element name is the
  1174.    * identifier for the entry name which is kept in CTOC.
  1175.    * Entry name may be the full file name e.g. sound.wav while the
  1176.    * element name is sound.  Element name is used to find an element, add an element.
  1177.    * Entry name is only used  to open the wave file and read it
  1178.    * Look for the period of the .WAV extension and then copy into the
  1179.    * element name everything except .WAV extension.
  1180.    */
  1181.   if (psz = strstr(pszEntryName,"."))
  1182.     {
  1183.      strncpy(achElementName,pszEntryName,psz - pszEntryName);
  1184.     }
  1185.   else
  1186.     {
  1187.      /* If no period found then display a message and return */
  1188.      ShowAMessage(
  1189.            IDS_ERROR_TITLE,
  1190.            IDS_CANT_PROCESS_MESSAGE,
  1191.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1192.            FALSE);
  1193.      return FALSE ;
  1194.     }
  1195.  
  1196.   /*
  1197.    * Get the pointer to pmmctocentry from GetCTOCEntryInfo function.
  1198.    * This function adds the pszElementName to the end of the variable
  1199.    * length structure MMCTOCENTRY.  If a NULL is returned then there was
  1200.    * was an error.  This structure is used to find if an entry already
  1201.    * exists in the CTOC.
  1202.    */
  1203.   if (!(pmmctocentry = GetCTOCEntryInfo(achElementName)))
  1204.     {
  1205.     /* a Null was returned becaus of an error so returned back */
  1206.     return FALSE;
  1207.     }
  1208.  
  1209.   /* Try to find the pszElementName in the CTOC by this API */
  1210.   ulRC =
  1211.       mmioCFFindEntry (hmmioCF,
  1212.                        pmmctocentry,
  1213.                        (ULONG) 0);
  1214.  
  1215.   if (ulRC == MMIOERR_CF_ENTRY_NOT_FOUND)
  1216.      {
  1217.      /*
  1218.       * Entry for the selected wave not found in CTOC, so add the entry and
  1219.       * element data to CTOC and CGRP.
  1220.       * First make sure the selected wave file exists in the current directory
  1221.       * and if it does then find the size of the wave file to be used later.
  1222.       */
  1223.      if (ulRC =
  1224.              (ULONG) DosQueryPathInfo(pszEntryName,
  1225.                                       FIL_STANDARD,
  1226.                                       &FileInfoBuf,
  1227.                                       sizeof(FileInfoBuf)))
  1228.         {
  1229.         /*
  1230.          * Either the wave does not exist in the current directory or some other
  1231.          * occured so display an error and return
  1232.          */
  1233.         ShowAMessage(
  1234.                     IDS_ERROR_TITLE,
  1235.                     IDS_FILE_NOT_FOUND,
  1236.                     MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1237.                     FALSE);
  1238.         return FALSE;
  1239.         }  /* endif */
  1240.      }
  1241.   else
  1242.     if (ulRC )
  1243.        {
  1244.        /*
  1245.         * If any other error occured while searching using mmioCFFindEntry
  1246.         * then display a message and return FALSE
  1247.         */
  1248.        ShowAMessage(
  1249.                    IDS_ERROR_TITLE,
  1250.                    IDS_CANT_PROCESS_MESSAGE,
  1251.                    MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1252.                    FALSE);
  1253.        return FALSE;
  1254.        }
  1255.     else
  1256.        if (ulRC == MMIO_CF_SUCCESS)
  1257.           {
  1258.           /*
  1259.            * CTOC entry was found so we don't want to add it again, so
  1260.            * display a message and return back.
  1261.            */
  1262.  
  1263.           ShowAMessage(
  1264.                    IDS_ERROR_TITLE,
  1265.                    IDS_ENTRY_ALREADY_EXISTS,
  1266.                    MB_OK | MB_INFORMATION | MB_MOVEABLE |  MB_APPLMODAL ,
  1267.                    FALSE);
  1268.  
  1269.           return FALSE;
  1270.           }
  1271.  
  1272.   /* Initialize the mmioinfo structure for opening the wave file */
  1273.   memset (&mmioinfo,'\0',sizeof(mmioinfo));
  1274.  
  1275.   /* Initialize the IOProc to use on the wave file */
  1276.   mmioinfo.fccIOProc = FOURCC_DOS;
  1277.  
  1278.   /* Open the Wave File for Reading */
  1279.   hmmioSource = mmioOpen( (PSZ)pszEntryName,
  1280.                                &mmioinfo,
  1281.                                MMIO_READ );
  1282.  
  1283.   /* if could not open wave file then display an error and return back */
  1284.   if (!hmmioSource)
  1285.      {
  1286.      ShowAMessage(
  1287.            IDS_ERROR_TITLE,
  1288.            IDS_COULD_NOT_OPEN_WAVE,
  1289.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1290.            FALSE);
  1291.      return FALSE;
  1292.      }
  1293.  
  1294.   /*
  1295.    * Wave file openened successfully, so allocate memory into a buffer
  1296.    * where the data for the wave file can be read into.
  1297.    */
  1298.  
  1299.   if ((pchAppBuffer = (PCHAR)calloc( FileInfoBuf.cbFile,sizeof(CHAR) ))
  1300.        == NULL)
  1301.      {
  1302.      /* Could not allocate memory so display an error and return */
  1303.      ShowAMessage(
  1304.            IDS_ERROR_TITLE,
  1305.            IDS_CANNOT_GET_MEMORY,
  1306.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1307.            FALSE);
  1308.      return FALSE;
  1309.      }
  1310.  
  1311.   /* Read the wave file into the Application Buffer */
  1312.  
  1313.   lBytesRead = mmioRead( hmmioSource,
  1314.                          pchAppBuffer,
  1315.                          FileInfoBuf.cbFile );
  1316.  
  1317.   if (lBytesRead != (LONG)FileInfoBuf.cbFile)
  1318.      {
  1319.  
  1320.      /*
  1321.       * If All bytes could not be read then there was an error, so diplay
  1322.       * an error and quit.
  1323.       */
  1324.      ShowAMessage(
  1325.            IDS_ERROR_TITLE,
  1326.            IDS_CANT_PROCESS_MESSAGE,
  1327.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1328.            FALSE);
  1329.  
  1330.      return FALSE;
  1331.      }
  1332.  
  1333.   /* Convert the string WAVE to FOURCC which is used for adding an element */
  1334.   fccType  =  mmioStringToFOURCC( "WAVE", MMIO_TOUPPER );
  1335.  
  1336.   ulFlags = (ULONG) 0;
  1337.   /*
  1338.    * Use the mmio API to add the entry to CTOC and element data to CGRP
  1339.    * mmioCFAddEntry could also be used, but it will only add the entry of
  1340.    * the element to the CTOC and inorder to add the element data to CGRP
  1341.    * mmioCFAddElement API has to be used.  If the entry does not exist
  1342.    * in CTOC when this API is called then it is added to CTOC.
  1343.    */
  1344.   ulRC = mmioCFAddElement(hmmioCF,           /* handle to compound RIFF file */
  1345.                           achElementName,    /* Element name to be added     */
  1346.                           fccType,           /* FOURCC type                  */
  1347.                           pchAppBuffer,      /* Pointer to element data      */
  1348.                           FileInfoBuf.cbFile,/* Size of element data         */
  1349.                           ulFlags);          /* Flags used                   */
  1350.  
  1351.  
  1352.   if (ulRC)
  1353.     {
  1354.      /* Element could not be added so display a message and return */
  1355.      ShowAMessage(
  1356.            IDS_ERROR_TITLE,
  1357.            IDS_CANT_PROCESS_MESSAGE,
  1358.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1359.            FALSE);
  1360.      return FALSE;
  1361.     }
  1362.   /* Add the element name to the CTOC list box */
  1363.   WinSendMsg( WinWindowFromID( hwnd, ID_LB_FILE_TOC),
  1364.               LM_INSERTITEM,
  1365.               (MPARAM) LIT_END,
  1366.               achElementName);
  1367.  
  1368.   /* Select the first item in the CTOC list box */
  1369.   WinSendMsg( WinWindowFromID (hwnd, ID_LB_FILE_TOC),
  1370.               LM_SELECTITEM,
  1371.               (MPARAM) 0,
  1372.               (MPARAM) TRUE);
  1373.  
  1374.  
  1375.   return TRUE;
  1376.  
  1377. }
  1378.  
  1379.  
  1380. /******************************************************************************
  1381.  * Name        : DeleteEntryFromRIFF
  1382.  *
  1383.  * Description : This function will Delete the requested element name
  1384.  *               from the RIFF compound file.  The Element entry is deleted
  1385.  *               from CTOC but the element data is still present in CGRP.  In
  1386.  *               order to delete element data from CGRP mmioCFCompact should
  1387.  *               be used.
  1388.  *
  1389.  * Concepts    : How to Delete an element entry in a CTOC RIFF compound file.
  1390.  *
  1391.  * MMPM/2 API's: mmioCFDeleteEntry
  1392.  *
  1393.  * Parameters  : pszElementName       - Name of the Element for which we
  1394.  *                                      want to delete from the CTOC.  The user
  1395.  *                                      had selected this entry.
  1396.  *               sFileNum             - Index for the Element Name in List Box
  1397.  *               hwnd                 - Handle to Dialog.
  1398.  *
  1399.  * Return      : NONE.
  1400.  *
  1401.  ******************************************************************************/
  1402. BOOL DeleteEntryFromRIFF(PSZ   pszElementName,
  1403.                          SHORT sFileNum,
  1404.                          HWND  hwnd)
  1405. {
  1406.   PMMCTOCENTRY pmmctocentry;
  1407.   ULONG        ulRC;
  1408.   CHAR         achEntryName[CCHMAXPATH] = "";
  1409.                                /* Full Name of the Entry                    */
  1410.   /*
  1411.    * Get the pointer to pmmctocentry from GetCTOCEntryInfo function.
  1412.    * This function adds the pszElementName to the end of the variable
  1413.    * length structure MMCTOCENTRY.  If a NULL is returned then there was
  1414.    * was an error.
  1415.    */
  1416.   if (!(pmmctocentry = GetCTOCEntryInfo(pszElementName)))
  1417.     {
  1418.     /* a Null was returned because of an error so returned back */
  1419.     return FALSE;
  1420.     }
  1421.  
  1422.   /*
  1423.    * The Element name has been added to the end of the variable length
  1424.    * structure pmmctocentry.  Try to find the pszElementName in the CTOC
  1425.    * by this API
  1426.    */
  1427.   ulRC =
  1428.       mmioCFDeleteEntry (hmmioCF,
  1429.                          pmmctocentry,
  1430.                          (ULONG) 0);
  1431.  
  1432.   if (ulRC)
  1433.        {
  1434.        /* If any other error occured, display a message and return FALSE */
  1435.        ShowAMessage(
  1436.              IDS_ERROR_TITLE,
  1437.              IDS_CANT_PROCESS_MESSAGE,
  1438.              MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1439.              FALSE);
  1440.        return FALSE;
  1441.        }
  1442.  
  1443.   strcpy(achEntryName,pszElementName);
  1444.   strcat(achEntryName,".WAV");
  1445.  
  1446.   /* Add the element name to the ADD File list box */
  1447.   WinSendMsg( WinWindowFromID( hwnd, ID_LB_ADD_FILE),
  1448.               LM_INSERTITEM,
  1449.               (MPARAM) LIT_END,
  1450.               achEntryName);
  1451.  
  1452.   /* Select the first item in the Add File list box */
  1453.   WinSendMsg( WinWindowFromID (hwnd, ID_LB_ADD_FILE),
  1454.               LM_SELECTITEM,
  1455.               (MPARAM) 0,
  1456.               (MPARAM) TRUE);
  1457.  
  1458.  
  1459.   return TRUE;
  1460.  
  1461. }
  1462.  
  1463. /******************************************************************************
  1464.  * Name        : GetCTOCEntryInfo
  1465.  *
  1466.  * Description : This function will allocate memory for PMMCTOCENTRY structure
  1467.  *               by using the mmioCFGetInfo call.  Since this structure is of
  1468.  *               variable length, and is used to either delete an entry or
  1469.  *               find an entry we need to add the element name to the end
  1470.  *               of this structure.  A pointer to the PMMCTOCENTRY is returned.
  1471.  *               This function is called either when trying to add an entry
  1472.  *               of either when trying to delete an entry.  The element name
  1473.  *               to be added or deleted is placed at the end of the structure.
  1474.  *
  1475.  *
  1476.  * Concepts    : How to determine the size of the MMCTOCENTRY structure and
  1477.  *               copy the pszElementName at the end of this variable length
  1478.  *               structure.  The concept of retreving MMCFINFO structure is
  1479.  *               also illustrated.
  1480.  *
  1481.  * MMPM/2 API's: mmioCFGetInfo
  1482.  *               mmioStringToFOURCC
  1483.  *
  1484.  * Parameters  : pszElementName       - Name of the Element for which we
  1485.  *                                      are looking in the CTOC.  This
  1486.  *                                      element name needs to added at the
  1487.  *                                      end of the MMCTOCENTRY variable
  1488.  *                                      length structure.
  1489.  *
  1490.  * Return      : PMMCTOCENTRY         - Pointer to MMCTOCENTRY structure with
  1491.  *                                      the pszElementName at the end.
  1492.  *               NULL                 - If an error occurs.
  1493.  *
  1494.  ******************************************************************************/
  1495. PMMCTOCENTRY GetCTOCEntryInfo(PSZ pszElementName)
  1496. {
  1497.   ULONG        ulRC;           /* Return codes                              */
  1498.   ULONG        ulCBytes;       /* Number of Bytes to read                   */
  1499.   MMCFINFO     mmcfinfo;       /* Variable length structure                 */
  1500.   USHORT       usEntrySize;    /* Size for the Entry for Element in CTOC    */
  1501.   USHORT       usNameSize;     /* Size for the Name of the Element in CTOC  */
  1502.   USHORT       usExEntFields;  /* Number of extra entry fields for mmcfinfo */
  1503.   PMMCTOCENTRY pmmctocentry;   /* Variable length structure                 */
  1504.   CHAR         *pTemp;         /* The Element Name is copied in mmctocentry */
  1505.  
  1506.   /*
  1507.    * Since there can be variable length arrays after MMCFINFO structure, call
  1508.    * mmioCFGetInfo with ulCBytes equal to the size of the ULONG.  This will
  1509.    * return the first field of the CTOC header, which happens to the size
  1510.    * of the header.  This value can be used in another call to get the full
  1511.    * structure.
  1512.    */
  1513.   ulCBytes = (ULONG) sizeof(ULONG);
  1514.  
  1515.   /*
  1516.    * Get the first field of the CTOC header which will tell us the size
  1517.    * of the MMCFINFO structure (variable size).
  1518.   */
  1519.   ulRC =
  1520.        mmioCFGetInfo(hmmioCF,
  1521.                      &mmcfinfo,
  1522.                      ulCBytes);
  1523.  
  1524.   if (ulRC != ulCBytes)
  1525.     {
  1526.     /*
  1527.      * The mmioCFGetInfo call was not successful and the first field of the
  1528.      * CTOC header could not be retrieved, so display an error and return FALSE
  1529.      */
  1530.     ShowAMessage(
  1531.            IDS_ERROR_TITLE,
  1532.            IDS_CANT_PROCESS_MESSAGE,
  1533.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1534.            FALSE);
  1535.     return NULL;
  1536.     }
  1537.  
  1538.   /*
  1539.    * The call was successfull so retrieve the size of the variable length
  1540.    * structure so we can retrieve the full structure.
  1541.    */
  1542.   ulCBytes = mmcfinfo.ulHeaderSize;
  1543.  
  1544.   /*
  1545.    * Retrieve the full mmcfinfo structure.  This call will give us back the
  1546.    * size for each entry or the size of MMCTOCENTRY structure,
  1547.    * and the size for the name of the entry which is at the end of the
  1548.    * structure, so we can input into the MMCTOCENTRY structure
  1549.    * (variable length) the name of  element we are searching for.
  1550.    */
  1551.   ulRC =
  1552.        mmioCFGetInfo(hmmioCF,
  1553.                      &mmcfinfo,
  1554.                      ulCBytes);
  1555.  
  1556.   if (ulRC != ulCBytes)
  1557.     {
  1558.     /*
  1559.      * The mmioCFGetInfo call was not successful and mmcfinfo structure
  1560.      * could not be retrieved, so display an error and return FALSE
  1561.      */
  1562.      ShowAMessage(
  1563.            IDS_ERROR_TITLE,
  1564.            IDS_CANT_PROCESS_MESSAGE,
  1565.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1566.            FALSE);
  1567.      return NULL;
  1568.     }
  1569.  
  1570.   /* Contains the size for variable length MMCTOCENTRY structure */
  1571.   usEntrySize   = (USHORT) mmcfinfo.usEntrySize;
  1572.  
  1573.   /* Contains the size for the Name of the element for each entry */
  1574.   usNameSize    = (USHORT) mmcfinfo.usNameSize;
  1575.   usExEntFields = (USHORT) mmcfinfo.usExEntFields;
  1576.  
  1577.   /*
  1578.    * Allocate memory for pmmctocentry based on the size of each entry in CTOC
  1579.    * header structure.
  1580.    */
  1581.   if ((pmmctocentry =
  1582.             (PMMCTOCENTRY) calloc(1,
  1583.                                   (ULONG)(usEntrySize)))
  1584.                                                   == NULL)
  1585.      {
  1586.      /* Could not allocate memory, so display an error and return FALSE */
  1587.      ShowAMessage(
  1588.            IDS_ERROR_TITLE,
  1589.            IDS_CANNOT_GET_MEMORY,
  1590.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1591.            FALSE);
  1592.      return NULL;
  1593.  
  1594.      }
  1595.  
  1596.   /* Align the pointer pTemp to point to the MMCTOCENTRY structure */
  1597.   pTemp = (CHAR *)(pmmctocentry);
  1598.   /*
  1599.    * Since the MMCTOCENTRY can be followed by the element name (which is going)
  1600.    * we need to input the element name at the end of the
  1601.    * variable length structure.  So go to end of the structure where the
  1602.    * space for Element Name starts.
  1603.    */
  1604.   pTemp += usEntrySize - usNameSize;
  1605.  
  1606.   /* Copy the element name (MAX of usNameSize bytes) into the structure */
  1607.   strncpy( pTemp,
  1608.           pszElementName,
  1609.           min( strlen(pszElementName), usNameSize ) );
  1610.  
  1611.   /* Input the FOURCCC of the Element type */
  1612.   pmmctocentry->ulMedType =
  1613.                    (ULONG) mmioStringToFOURCC( (PSZ)"WAVE",
  1614.                                                MMIO_TOUPPER );
  1615.   return pmmctocentry;
  1616.  
  1617. }
  1618.  
  1619. /******************************************************************************
  1620.  * Name        : CompactTheRIFFCompoundFile
  1621.  *
  1622.  * Description : This function will compact the RIFF compound file.  When
  1623.  *               any entries are deleted from a compound file their entries
  1624.  *               are only deleted from CTOC on a RIFF file.  Their data
  1625.  *               still exists in the CGRP of the RIFF file.  In order to
  1626.  *               delete the data mmioCFCompact is used.  mmioCFCompact
  1627.  *               deletes all deleted entries into the same file.  mmioCFCopy
  1628.  *               can also be used and it copies the non-deleted entries of
  1629.  *               a compound file into another file.
  1630.  *
  1631.  *
  1632.  *
  1633.  * Concepts    : How to compact a file with deleted entries.
  1634.  *
  1635.  * MMPM/2 API's: mmioCFCompact
  1636.  *
  1637.  * Parameters  :
  1638.  *
  1639.  *
  1640.  * Return      : TRUE                 - If Compacting is successfull
  1641.  *               FALSE                - If an error occurs.
  1642.  *
  1643.  ******************************************************************************/
  1644. BOOL CompactTheRIFFCompoundFile()
  1645. {
  1646.   ULONG  ulRC;
  1647.  
  1648.  
  1649.   /* Compact the RIFF_COMPOUND_FILE.  The file is already closed */
  1650.   ulRC =
  1651.       mmioCFCompact(RIFF_COMPOUND_FILE,
  1652.                     0L);
  1653.  
  1654.   if (ulRC)
  1655.      {
  1656.      /* An error occured compacting the file so display an error */
  1657.      ShowAMessage(
  1658.            IDS_ERROR_TITLE,
  1659.            IDS_CANT_PROCESS_MESSAGE,
  1660.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1661.            FALSE);
  1662.       return FALSE;
  1663.      }
  1664.  
  1665.  return TRUE;
  1666.  
  1667. }
  1668.  
  1669. /******************************************************************************
  1670.  * Name        : EnableButtons
  1671.  *
  1672.  * Description : This function either enables or Disable push buttons depending
  1673.  *               on mmcfinfo structure.
  1674.  *               Play pushbutton - If there is at least one non-deleted element
  1675.  *               in compound file then enable the pushbutton else disable it.
  1676.  *
  1677.  *               Compact pushbutton - If there is at least one deleted element
  1678.  *               and one non-deleted element in the compound file then enable
  1679.  *               it otherwise disable it.
  1680.  *
  1681.  *               Add pushbutton - If there is at least one wave file to be
  1682.  *               added in the add list box then enable it else disable it.
  1683.  *
  1684.  *               Delete pushbutton - If there is at least one non-deleted
  1685.  *               element in compound file then enable it else disable it.
  1686.  *
  1687.  *
  1688.  *
  1689.  * Concepts    : How to use MMCFINFO structure to find out how many
  1690.  *               elements are deleted, how many are used and how many are
  1691.  *               total.
  1692.  *
  1693.  * MMPM/2 API's: mmioCFGetInfo
  1694.  *
  1695.  * Parameters  : HWND                 - hwnd to the application
  1696.  *
  1697.  *
  1698.  * Return      :
  1699.  *
  1700.  ******************************************************************************/
  1701. void  EnableButtons(HWND hwnd)
  1702. {
  1703.   ULONG    ulCBytes;
  1704.   MMCFINFO mmcfinfo;
  1705.   ULONG    ulRC;
  1706.   SHORT    sItemCount;
  1707.   /*
  1708.    * Since there can be variable length arrays after MMCFINFO structure, call
  1709.    * mmioCFGetInfo with ulCBytes equal to the size of the ULONG.  This will
  1710.    * return the first field of the CTOC header, which happens to the size
  1711.    * of the header.  This value can be used in another call to get the full
  1712.    * structure.
  1713.    */
  1714.   ulCBytes = (ULONG) sizeof(ULONG);
  1715.  
  1716.   /* Get the first field of the CTOC header */
  1717.   ulRC =
  1718.        mmioCFGetInfo(hmmioCF,
  1719.                      &mmcfinfo,
  1720.                      ulCBytes);
  1721.  
  1722.   if (ulRC != ulCBytes)
  1723.     {
  1724.     /*
  1725.      * The mmioCFGetInfo call was not successful and the first field of the
  1726.      * CTOC header could not be retrieved, so display an error and return FALSE
  1727.      */
  1728.     ShowAMessage(
  1729.            IDS_ERROR_TITLE,
  1730.            IDS_CANT_PROCESS_MESSAGE,
  1731.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1732.            FALSE);
  1733.     return ;
  1734.     }
  1735.  
  1736.   /*
  1737.    * The call was successfull so retrieve the size of the variable length
  1738.    * structure so we can retrieve the full structure
  1739.    */
  1740.   ulCBytes = mmcfinfo.ulHeaderSize;
  1741.  
  1742.   /*
  1743.    * Retrieve the full mmcfinfo structure.  This call will give us back the
  1744.    * size for each entry, and the size for the name of the entry, so we
  1745.    * can input into the MMCTOCENTRY structure (variable length) the name of
  1746.    * element we are searching for.
  1747.    */
  1748.   ulRC =
  1749.        mmioCFGetInfo(hmmioCF,
  1750.                      &mmcfinfo,
  1751.                      ulCBytes);
  1752.  
  1753.   if (ulRC != ulCBytes)
  1754.     {
  1755.     /*
  1756.      * The mmioCFGetInfo call was not successful and mmcfinfo structure
  1757.      * could not be retrieved, so display an error and return FALSE
  1758.      */
  1759.      ShowAMessage(
  1760.            IDS_ERROR_TITLE,
  1761.            IDS_CANT_PROCESS_MESSAGE,
  1762.            MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1763.            FALSE);
  1764.      return ;
  1765.     }
  1766.  
  1767.   if (mmcfinfo.ulEntriesDeleted &&
  1768.      (mmcfinfo.ulEntriesTotal - mmcfinfo.ulEntriesUnused != mmcfinfo.ulEntriesDeleted))
  1769.      {
  1770.       /*
  1771.        * If there is at least on Deleted entry and one non-deleted entry in
  1772.        * the RIFF file then try to enable it, else disable it
  1773.        */
  1774.       if (fCompactDisable)
  1775.          {
  1776.          /* The push button was disabled, so enable it */
  1777.          WinEnableWindow( WinWindowFromID(hwnd, ID_PB_COMPACT),
  1778.                           TRUE);
  1779.          fCompactDisable = FALSE;
  1780.          }
  1781.      }
  1782.   else
  1783.     {
  1784.       /* Either there is no deleted entry or there is no non-deleted entry */
  1785.  
  1786.       if (!fCompactDisable)
  1787.          {
  1788.          /* push button was enabled, so disable it */
  1789.          WinEnableWindow( WinWindowFromID(hwnd, ID_PB_COMPACT),
  1790.                           FALSE);
  1791.          fCompactDisable = TRUE;
  1792.          }
  1793.     }
  1794.  
  1795.   /*  Check if there are any entries which are being used by elements */
  1796.   if ((mmcfinfo.ulEntriesTotal - mmcfinfo.ulEntriesUnused)
  1797.                !=  mmcfinfo.ulEntriesDeleted)
  1798.      {
  1799.       /* Entries found which are being used */
  1800.       if (fPlayDisable)
  1801.          {
  1802.          /*
  1803.           * Play button was disabled, so enable it since there is at least
  1804.           * one non-deleted entry
  1805.           */
  1806.  
  1807.          WinEnableWindow( WinWindowFromID(hwnd, ID_PB_PLAY),
  1808.                           TRUE);
  1809.          fPlayDisable = FALSE;
  1810.          }
  1811.  
  1812.  
  1813.       if (fDelDisable)
  1814.          {
  1815.          /*
  1816.           * Delete button was disabled, so enable it since there is at least
  1817.           * one non-deleted entry
  1818.           */
  1819.          WinEnableWindow( WinWindowFromID(hwnd, ID_PB_DEL),
  1820.                           TRUE);
  1821.          fDelDisable = FALSE;
  1822.          }
  1823.      }
  1824.   else
  1825.     {
  1826.      /* All entries are either deleted or there are no entries in RIFF file */
  1827.      if (!fPlayDisable)
  1828.         {
  1829.         /* Play button is enabled, so disable it */
  1830.          WinEnableWindow( WinWindowFromID(hwnd, ID_PB_PLAY),
  1831.                           FALSE);
  1832.          fPlayDisable = TRUE;
  1833.          }
  1834.  
  1835.  
  1836.      if (!fDelDisable)
  1837.         {
  1838.         /* Delete button is enabled, so disable it */
  1839.         WinEnableWindow( WinWindowFromID(hwnd, ID_PB_DEL),
  1840.                          FALSE);
  1841.         fDelDisable = TRUE;
  1842.         }
  1843.     }
  1844.  
  1845.   /* Query for if there are any entries in the ADD file list box */
  1846.   sItemCount =
  1847.      (SHORT)   WinSendMsg( WinWindowFromID(hwnd,ID_LB_ADD_FILE),
  1848.                            LM_QUERYITEMCOUNT,
  1849.                            (MPARAM) 0,
  1850.                            (MPARAM) 0);
  1851.   if (sItemCount == 0)
  1852.      {
  1853.      /* No entries exist in ADD file list box so disable it */
  1854.      if (!fAddDisable)
  1855.         {
  1856.         WinEnableWindow( WinWindowFromID(hwnd,ID_PB_ADD),
  1857.                          FALSE);
  1858.         fAddDisable = TRUE;
  1859.         }
  1860.      }
  1861.   else
  1862.     {
  1863.     /* Entries exist in ADD file list box so enable it */
  1864.     if (fAddDisable)
  1865.        {
  1866.         WinEnableWindow( WinWindowFromID(hwnd,ID_PB_ADD),
  1867.                          TRUE);
  1868.         fAddDisable = FALSE;
  1869.        }
  1870.     }
  1871. }
  1872.  
  1873. /******************************************************************************
  1874.  * Name        : PlayElement
  1875.  *
  1876.  * Description : This procedure will open the wave audio device to play
  1877.  *               the element which the user selected the CTOC list box.
  1878.  *               Then the element will be played.
  1879.  *
  1880.  *
  1881.  * Concepts    : How to Open a Device to play a wave file from a RIFF
  1882.  *               compound file and then how to play the file.
  1883.  *
  1884.  * MMPM/2 API's:  mciSendCommand         MCI_OPEN
  1885.  *                                       MCI_PLAY
  1886.  *                                       MCI_CLOSE
  1887.  *
  1888.  * Parameters  : hwnd                 - Handle to the applciation
  1889.  *               pszElementName       - Name of the element to play.
  1890.  *
  1891.  * Return      : None.
  1892.  *
  1893.  *************************************************************************/
  1894. void PlayElement(HWND hwnd,
  1895.                  PSZ pszElementName)
  1896. {
  1897. MCI_PLAY_PARMS  mciPlayParameters;              /* Used for MCI_PLAY messages */
  1898. MCI_OPEN_PARMS  lpWaveOpen;                     /* Used for MCI_OPEN messages */
  1899. ULONG           ulReturn;                       /* Used for ret code for API  */
  1900. CHAR            achElementName[CCHMAXPATH] = "";/* Name of the wave to play   */
  1901. MCI_GENERIC_PARMS mciGenericParms;
  1902.  
  1903.  
  1904.    /*
  1905.     * Initialize the MCI_OPEN_PARMS data structure with hwndMainDialogBox
  1906.     * as callback handle for MM_MCIPASSDEVICE, then issue the MCI_OPEN
  1907.     * command with the mciSendCommand function.  No alias is used.
  1908.     */
  1909.  
  1910.    lpWaveOpen.hwndCallback       =  hwnd;
  1911.    lpWaveOpen.pszAlias       = (PSZ) NULL;
  1912.  
  1913.  
  1914.    /* Open the correct waveform device with the MCI_OPEN message to MCI. */
  1915.    lpWaveOpen.pszDeviceType  =
  1916.          (PSZ) (MAKEULONG(MCI_DEVTYPE_WAVEFORM_AUDIO,1));
  1917.    /*
  1918.     * Concatanate the RIFF file name and the Element name to be played.
  1919.     * In order to play an element from a compound file, we need to
  1920.     * concatanate the two
  1921.     */
  1922.    strcpy(achElementName,RIFF_COMPOUND_FILE);
  1923.    strcat(achElementName,"+");
  1924.    strcat(achElementName,pszElementName);
  1925.  
  1926.    /*  The name of the element to play the wave. */
  1927.    lpWaveOpen.pszElementName = (PSZ)achElementName;
  1928.  
  1929.  
  1930.    /*  Open the waveform file in the ELEMENT mode. */
  1931.    ulReturn =
  1932.        mciSendCommand(0,
  1933.                       MCI_OPEN,
  1934.                       MCI_WAIT | MCI_OPEN_ELEMENT | MCI_READONLY |
  1935.                       MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
  1936.                       (PVOID) &lpWaveOpen,
  1937.                       (USHORT) NULL);
  1938.  
  1939.    if (ulReturn != 0)
  1940.       {
  1941.       /* MCI Open was not successfull so show a message by passing a TRUE */
  1942.        ShowAMessage(
  1943.              IDS_ERROR_TITLE,
  1944.              ulReturn,
  1945.              MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1946.              TRUE);
  1947.       }
  1948.  
  1949.    /* Save the Device Id in the global variable to be used later */
  1950.    usWaveDeviceId = lpWaveOpen.usDeviceID;
  1951.  
  1952.    /* Initialize the mciPlayParameters structure */
  1953.    memset(&mciPlayParameters,'\0',sizeof(mciPlayParameters));
  1954.    mciPlayParameters.hwndCallback =  hwnd;
  1955.  
  1956.    /* Send the Play Command to begin the playing of the RIFF element. */
  1957.    ulReturn
  1958.             = mciSendCommand(usWaveDeviceId,
  1959.                              MCI_PLAY,
  1960.                              MCI_WAIT,
  1961.                              (PVOID) &mciPlayParameters,
  1962.                              0);
  1963.    if (ulReturn)
  1964.       {
  1965.       /*
  1966.        * The MCI_PLAY was not successfull so display an error by passing
  1967.        * TRUE.
  1968.        */
  1969.       ShowAMessage(
  1970.              IDS_ERROR_TITLE,
  1971.              ulReturn,
  1972.              MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1973.              TRUE);
  1974.       return ;
  1975.       }
  1976.  
  1977.    /* Done Playing so want to close the device */
  1978.    memset(&mciGenericParms,'\0',sizeof(mciGenericParms));
  1979.    ulReturn = mciSendCommand(usWaveDeviceId,
  1980.                              MCI_CLOSE,
  1981.                              MCI_WAIT,
  1982.                              (PVOID) &mciGenericParms,
  1983.                              0);
  1984.  
  1985.    if (ulReturn)
  1986.       {
  1987.       /*
  1988.        * The MCI_CLOSE was not successfull so display an error by passing
  1989.        * TRUE.
  1990.        */
  1991.       ShowAMessage(
  1992.             IDS_ERROR_TITLE,
  1993.             ulReturn,
  1994.             MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  1995.             TRUE);
  1996.       return ;
  1997.       }
  1998. }
  1999.  
  2000. /******************************************************************************
  2001.  * Name        : CloseRiffCompoundFile
  2002.  *
  2003.  * Description : This procedure will close the RIFF compound file.
  2004.  *               The file is only closed when trying to compact the file.
  2005.  *
  2006.  *
  2007.  * Concepts    : How to Close  a RIFF file.
  2008.  *
  2009.  * MMPM/2 API's: mmioCFClose
  2010.  *
  2011.  *
  2012.  * Parameters  : None.
  2013.  *
  2014.  *
  2015.  * Return      : None.
  2016.  *
  2017.  *************************************************************************/
  2018.  
  2019. void CloseRiffCompoundFile(HWND hwndDiag)
  2020. {
  2021.  
  2022.  ULONG ulRC;
  2023.  
  2024.  /* Close the RIFF compound file, by passing the handle of the RIFF file */
  2025.  ulRC = mmioCFClose(hmmioCF,(ULONG) 0);
  2026.  
  2027.  if (ulRC)
  2028.     {
  2029.     /* An error occured so display a message */
  2030.     ShowAMessage(
  2031.           IDS_ERROR_TITLE,
  2032.           IDS_CANT_PROCESS_MESSAGE,
  2033.           MB_CANCEL | MB_ERROR | MB_MOVEABLE |  MB_HELP ,
  2034.           FALSE);
  2035.     }
  2036.  
  2037. }
  2038.