home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / clock / clock.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  100KB  |  2,517 lines

  1. /*******************************************************************************
  2.  * File Name   : CLOCK.C
  3.  *
  4.  * Description : This file contains the C source code required for the clock
  5.  *               sample program.  This sample draws a clock in a dialog
  6.  *               window and chimes for the user at every hour, quarter hour,
  7.  *               half hour, and three-quarter hour.  The user can also play
  8.  *               the next hour's chime by pushing a button.
  9.  *
  10.  * Concepts    : This program illustrates how to create and use a Memory
  11.  *               Playlist.  The sample also shows how to use MMIO API's
  12.  *               used in opening, reading, and closing files.
  13.  *
  14.  * MMPM/2 API's: List of all MMPM/2 API's that are used in this module.
  15.  *
  16.  *               mciQuerySysValue
  17.  *               mciSendCommand
  18.  *               mciGetErrorString
  19.  *               mmioOpen
  20.  *               mmioGetHeader
  21.  *               mmioRead
  22.  *               mmioClose
  23.  *
  24.  * Required
  25.  *    Files    : clock.c         Source Code.
  26.  *               clockdrw.c      Source Code.
  27.  *               clock.h         Include file.
  28.  *               clock.dlg       Dialog definition.
  29.  *               clock.rc        Resources.
  30.  *               clock.ipf       Help text.
  31.  *               makefile        Make file.
  32.  *               clock.def       Linker definition file.
  33.  *               clock.ico       Clock icon.
  34.  *               bellc.bmp       Center bell bitmap.
  35.  *               belllt.bmp      Left bell bitmap.
  36.  *               bellfrlt.bmp    Far left bell bitmap.
  37.  *               bellrt.bmp      Right bell bitmap.
  38.  *               bellfrrt.bmp    Far right bell bitmap.
  39.  *               clock1.wav      Quarter hour chime file.
  40.  *               clock2.wav      Half hour chime file.
  41.  *               clock3.wav      Hour chime file.
  42.  *
  43.  * Copyright (C) IBM  1991, 1992, 1993
  44.  ******************************************************************************/
  45.  
  46. #define  INCL_OS2MM                      /* Required for MCI & MMIO headers   */
  47. #define  INCL_WIN                        /* Required to use Win APIs.         */
  48. #define  INCL_PM                         /* Required to use PM APIs.          */
  49. #define  INCL_GPIPRIMATIVES              /* Required to use GPI OS/2 APIs.    */
  50. #define  INCL_DOSSEMAPHORES              /* Required to use Semaphores.       */
  51. #define  INCL_DOSDATETIME                /* Required for get date time info.  */
  52. #define  INCL_DOSPROCESS                 /* Required for OS/2 process APIs.   */
  53. #define  INCL_WINHELP                    /* Required to use IPF.              */
  54. #define  INCL_DOSMEMMGR                  /* Required to use memory API's.     */
  55. #define  INCL_SECONDARYWINDOW            /* required for secondary window     */
  56.  
  57. #include <os2.h>
  58. #include <os2me.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <math.h>
  63. #include <bsememf.h>
  64.  
  65. #include <sw.h>
  66.  
  67. #include "clock.h"
  68.  
  69. /************************* Procedure/Function Prototypes **********************/
  70. /*
  71.  * This definition is required to use the sample program with the IBM
  72.  * C compiler.
  73.  */
  74. #pragma linkage( MainDialogProc, system )
  75. #pragma linkage( IncludeDialogProc, system )
  76. #pragma linkage( DisplayDialogProc, system )
  77. #pragma linkage( DisplayListBoxProc, system )
  78. #pragma linkage( SwingTheBell, Optlink )
  79.  
  80. MRESULT EXPENTRY MainDialogProc( HWND hwnd,
  81.                                  ULONG msg,
  82.                                  MPARAM mp1,
  83.                                  MPARAM mp2 );
  84. USHORT           ShowAMessage( CHAR   *pcMessageTitle,
  85.                                USHORT usMessageId,
  86.                                ULONG  ulMessageBoxStyle );
  87. ULONG            HowBigIsTheChimeFile( USHORT usChimeFileId );
  88. VOID             InitializeDialog( VOID );
  89. VOID             TerminateDialog( VOID );
  90. VOID             CopyWaveformIntoMemory( LONG   *pulBaseAddress,
  91.                                          ULONG  ulSizeOfBuffer,
  92.                                          USHORT usChimeFile );
  93. VOID             FindAndPlayTheCorrectChime( CHIME_TIME_VALUE_T ctvChimeTime,
  94.                                              USHORT usHour );
  95. VOID             FindTheNearestChimeTimeAndPlayIt( VOID );
  96. VOID             SetupChimeFileInformation( VOID );
  97. VOID             InitializeHelp( VOID );
  98. VOID             LoadBellBitmaps( VOID );
  99. VOID             SetupPlayList( VOID );
  100. VOID             DealWithChiming( VOID );
  101. VOID             SwingTheBell( PVOID pvData);
  102. VOID             OpenPlaylistChimeDevice( ULONG  ulOpenFlags,
  103.                                          USHORT usChimeFileToPlay );
  104. BOOL             IsItChimeTime( CHIME_TIME_VALUE_T *ctvChimeTime,
  105.                                 USHORT             *pusNowHour );
  106. MRESULT EXPENTRY DrawTheHourHand( HPS     hps,
  107.                                   PPOINTL pptlCircleCenter,
  108.                                   USHORT  usHour,
  109.                                   USHORT  usMinute);
  110. VOID             DrawTheClockFace( HPS     hps,
  111.                                    PPOINTL pptlCircleCenter );
  112. MRESULT EXPENTRY DrawTheMinuteHand( HPS     hps,
  113.                                     PPOINTL pptlCircleCenter,
  114.                                     USHORT  usMinute);
  115. VOID             DrawClockCircles( HPS     hps,
  116.                                    PPOINTL pptlMarkerPosition,
  117.                                    LONG    lCircleColor,
  118.                                    USHORT  usCircleSize );
  119. VOID             UpdateTheClock( VOID);
  120. /*************** End of Procedure/Function Prototypes *************************/
  121.  
  122.  
  123. /****************************** Global Variables. *****************************/
  124.  
  125. /*
  126.  * This double array holds the playlists that will be used to play the chimes
  127.  * for the clock.  Each array has four fields within the structure, one for
  128.  * the playlist command( 32 bit value ) and three operands( 32 bit values ).
  129.  * The DATA_OPERATION's first operand will contain the address to the
  130.  * respective waveform buffers.  Once the playlist has been played, the
  131.  * CHIME_PLAYING_HAS_STOPPED message will be sent so that the application
  132.  * knows that the audio is finished.
  133.  *
  134.  * The clock will have a unique chime for each quarter hour.
  135.  * There are three chime files that are used in different combinations to
  136.  * create all of the chimes used for the clock.  These three files are
  137.  * clock1.wav, clock2.wav, and clock3.wav.
  138.  *
  139.  * The first playlist will play quarter hour chime.  This is simply
  140.  * clock1.wav.
  141.  *
  142.  * The second playlist will play the half hour chime.  This
  143.  * consists of clock1.wav + clock2.wav.
  144.  *
  145.  * The third playlist will play the three quarter hour chime.  This consists
  146.  * of clock1.wav + clock2.wav + clock1.wav.
  147.  *
  148.  * The fouth playlist plays the hour chime.  This consists of clock1.wav +
  149.  * clock2.wav + clock1.wav + clock2.wav + (HOUR * clock3.wav)
  150.  * The Number of loops to perform for the hour value
  151.  * is kept in the high order 16 bits of the first operand.  This will be set
  152.  * in a later procedure when the hour of the chime time is known.
  153.  */
  154. PLAY_LIST_STRUCTURE_T apltPlayList[ NUMBER_OF_PLAYLISTS ]
  155.                                   [ NUMBER_OF_COMMANDS ] =
  156. {
  157.    /*
  158.     * Quarter Hour Chime.
  159.     */
  160.    {
  161.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.                       */
  162.       MESSAGE_OPERATION, 0, CHIME_PLAYING_HAS_STOPPED, 0,
  163.       EXIT_OPERATION,    0, 0, 0
  164.    },
  165.  
  166.    /*
  167.     * Half Hour Chime.
  168.     */
  169.    {
  170.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.                       */
  171.       DATA_OPERATION,    0, 0, 0,      /* Chime file 2.                       */
  172.       MESSAGE_OPERATION, 0, CHIME_PLAYING_HAS_STOPPED, 0,
  173.       EXIT_OPERATION,    0, 0, 0
  174.    },
  175.  
  176.    /*
  177.     * Three Quarter Hour Chime.
  178.     */
  179.    {
  180.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.                       */
  181.       DATA_OPERATION,    0, 0, 0,      /* Chime file 2.                       */
  182.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.                       */
  183.       MESSAGE_OPERATION, 0, CHIME_PLAYING_HAS_STOPPED, 0,
  184.       EXIT_OPERATION,    0, 0, 0
  185.    },
  186.  
  187.    /*
  188.     * Hour Chime.
  189.     */
  190.    {
  191.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.             < Line 0 >*/
  192.       DATA_OPERATION,    0, 0, 0,      /* Chime file 2.             < Line 1 >*/
  193.       DATA_OPERATION,    0, 0, 0,      /* Chime file 1.             < Line 2 >*/
  194.       DATA_OPERATION,    0, 0, 0,      /* Chime file 2.             < Line 3 >*/
  195.       LOOP_OPERATION,    0, 7, 0,      /* Which line to end on      < Line 4 >*/
  196.       DATA_OPERATION,    0, 0, 0,      /* Chime file 3.             < Line 5 >*/
  197.       BRANCH_OPERATION,  0, 4, 0,      /* Branch back to Loop       < Line 6 >*/
  198.       MESSAGE_OPERATION, 0, CHIME_PLAYING_HAS_STOPPED, 0,
  199.       EXIT_OPERATION,    0, 0, 0
  200.    }
  201. };
  202.  
  203. /*
  204.  * This array holds the ID's that are used to retrieve the strings from
  205.  * the string table and placed into the global double array acStringBuffer.
  206.  * The defines that are used for the string table is used to create the
  207.  * index into the global buffer.  Since the string table starts at 1 and
  208.  * the global buffer starts at 0, the index is decremented by 1 when used.
  209.  * This means when the acStringBuffer is accessed after the strings have
  210.  * been loaded into the buffer, all indexes will be n-1, i.e.,
  211.  * IDS_HELP_WINDOW_TITLE - 1, to get the proper string.  This is done
  212.  * simply to keep down the number of #defines.
  213.  */
  214. USHORT ausMessageId[] = { IDS_MAIN_WINDOW_TITLE,
  215.                           IDS_HELP_CREATION_ERROR,
  216.                           IDS_HELP_LIBRARY_FILE,
  217.                           IDS_HELP_WINDOW_TITLE,
  218.                           IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT,
  219.                           IDS_SWING_THREAD_NOT_STARTED,
  220.                           IDS_CHIME_FILE_A,
  221.                           IDS_CHIME_FILE_B,
  222.                           IDS_CHIME_FILE_C };
  223.  
  224. /*
  225.  * This shows the order in which the bell bitmaps will be drawn so that the
  226.  * visible 'ringing' of the bell can be seen.  The bell will start at the
  227.  * center position, move to the right, move back to center, as it moves to the
  228.  * left, and finally back to the center position where it started.
  229.  */
  230. USHORT ausBellSwingOrder[ NUMBER_OF_BELLS_IN_A_SWING ] =
  231.      {
  232.         IX_CENTER_BELL,
  233.         IX_RIGHT_BELL,
  234.         IX_FAR_RIGHT_BELL,
  235.         IX_RIGHT_BELL,
  236.         IX_CENTER_BELL,
  237.         IX_LEFT_BELL,
  238.         IX_FAR_LEFT_BELL,
  239.         IX_LEFT_BELL,
  240.      };
  241.  
  242. /*
  243.  * This array holds program required text that is pulled from the string
  244.  * table.
  245.  */
  246. CHAR  acStringBuffer[ NUMBER_OF_PROGRAM_STRINGS ][ STRING_SIZE ];
  247.  
  248. HWND  hwndHelpInstance;                              /* Handle to Help window.*/
  249. HAB   hab;                                           /* Handle to anchor blk. */
  250. HPS   hps;                                           /* Handle to pres space. */
  251. HPS   hpsMemory;                                     /* Handle to pres space. */
  252. HPS   hpsScreen;                                     /* Handle to pres space. */
  253. QMSG  qmsg;                                          /* Message queue.        */
  254. HMQ   hmq;                                           /* Handle to the msg q.  */
  255. HWND  hwndMainDialogBox;                             /* Handle to the dlg win.*/
  256. HWND  hwndPlayChimePB;                               /* Handle to the Play PB */
  257. HWND  hwndFrame;                                     /* Handle to Frame win.  */
  258. RECTL rctClockFaceRectangle;                         /* Area of the clk face. */
  259. HEV                hevContinueToSwingTheBell;        /* When to swing bell.   */
  260. STOP_GO_READY_T    yngContinueToSwingTheBell = STOP, /* When to swing bell.   */
  261.                    yngAreChimeFilesLoaded    = READY;/* Have files been loaded*/
  262. MCI_OPEN_PARMS     mciOpenParameters;                /* Open structure.       */
  263. HELPINIT           hmiHelpStructure;                 /* Help init. structure. */
  264. HBITMAP ahbmBellBitMaps[ NUMBER_OF_BELL_BITMAPS ],   /* Holds the handles to  */
  265.         hbmBitmapToShow;                             /* the bell bitmaps.     */
  266. BOOL    fThreadIsAlive              = FALSE,         /* Has thread started.   */
  267.         fPassed                     = FALSE;         /* device  ownership     */
  268. MMAUDIOHEADER mmAudioHeader;                         /* Contains info for SET */
  269. BOOL    fInitHeader = TRUE;                          /* Should we init header?*/
  270. USHORT  usLastHour   = 99, /* The last hour when in the Draw Hands proc.      */
  271.         usLastMinute = 0,  /* The last minute when in the Draw Minute proc.   */
  272.         usHour       = 25, /* Contains current hour given by UpdateTheClock.  */
  273.         usMinute     = 61; /* Contains current minute given by UpdateTheClock.*/
  274.                            /* The 3 in the usHour is required so that the     */
  275.                            /* hands do not start in the same overlapping      */
  276.                            /* position.                                       */
  277. POINTL   aptl[4];                /* for bit blt                            */
  278. BITMAPINFOHEADER    bmpInfo;     /* bitmap info                            */
  279.  
  280. /************************** End of Globle Variables ***************************/
  281.  
  282.  
  283. /*******************************************************************************
  284.  * Name         : main
  285.  *
  286.  * Description  : This function calls the InitializeDialog and TerminateDialog
  287.  *                procedures.  The message loop is also in this routine.
  288.  *
  289.  * Concepts     : None.
  290.  *
  291.  * MMPM/2 API's : None.
  292.  *
  293.  * Parameters   : None.
  294.  *
  295.  * Return       : TRUE is returned to the operating system.
  296.  *
  297.  ******************************************************************************/
  298. INT main( VOID )
  299. {
  300.  
  301.    InitializeDialog();
  302.  
  303.    while ( WinGetMsg( hab, (PQMSG) &qmsg, (HWND) NULL, 0, 0) )
  304.       WinDispatchMsg( hab, (PQMSG) &qmsg );
  305.  
  306.    TerminateDialog();
  307.  
  308.    return( TRUE );
  309.  
  310. } /* End of main */
  311.  
  312.  
  313. /*******************************************************************************
  314.  * Name         : InitializeDialog
  315.  *
  316.  * Description  : This function performs the necessary initializations and
  317.  *                setups that are required to show/run a dialog box as a
  318.  *                main window.  The message queue will be created, as well as
  319.  *                the dialog box.  Finally the message passing loop will be
  320.  *                started to give messages to the dialog box.
  321.  *
  322.  * Concepts     : None.
  323.  *
  324.  * MMPM/2 API's : None.
  325.  *
  326.  * Parameters   : None.
  327.  *
  328.  * Return       : None.
  329.  *
  330.  ******************************************************************************/
  331. VOID InitializeDialog( VOID )
  332. {
  333.  
  334.    USHORT   usCounter  = 0;              /* Generic counter.                  */
  335.    BYTE  bThreadStackSize[ THREAD_STACK_SIZE ];         /* Thread stack size.    */
  336.  
  337.    DosCreateEventSem(
  338.       (PSZ) NULL,                         /* No semaphore Name. Do not share. */
  339.       &hevContinueToSwingTheBell,         /* Semaphore Handle.                */
  340.       (ULONG) NULL,                       /* Creation attributes.             */
  341.       (BOOL32) FALSE );                   /* State of semaphore.              */
  342.  
  343.    /*
  344.     * Create the thread that will animate the bell bitmaps.
  345.     */
  346.    if ( _beginthread(
  347.            SwingTheBell,                  /* Routine to run in the thread.    */
  348.            NULL,                          /* What parameters to pass. Ignore  */
  349.            (ULONG)(bThreadStackSize +
  350.                        sizeof( bThreadStackSize )),   /* Thread stack size.   */
  351.            NULL) == -1 )
  352.    {                                      /* What parameters to pass. Ignore  */
  353.       fThreadIsAlive = FALSE;
  354.    }
  355.    else
  356.    {
  357.       fThreadIsAlive = TRUE;
  358.    }
  359.  
  360.    /*
  361.     * Load the various strings that are required by the program.
  362.     */
  363.    for( usCounter=0; usCounter<NUMBER_OF_PROGRAM_STRINGS; usCounter++)
  364.    {
  365.       WinLoadString(
  366.          hab,                                  /* HAB for this dialog box.    */
  367.          (HMODULE) NULL,                       /* Get string from .exe file.  */
  368.          ausMessageId[ usCounter ],            /* Which string to get.        */
  369.          (SHORT) STRING_SIZE,                  /* The size of the buffer.     */
  370.          (PSZ) &acStringBuffer[ usCounter ] ); /* Buffer to place string.     */
  371.    }
  372.  
  373.    /*
  374.     * Setup and initialize the dialog window.
  375.     */
  376.    hab = WinInitialize( (USHORT) 0 );
  377.  
  378.    hmq = WinCreateMsgQueue( hab, 0 );
  379.  
  380.    hwndFrame =                  /* Returns the handle to the frame.           */
  381.       WinLoadSecondaryWindow(
  382.          HWND_DESKTOP,          /* Parent of the dialog box.                  */
  383.          HWND_DESKTOP,          /* Owner of the dialog box.                   */
  384.          (PFNWP) MainDialogProc,/* 'Window' procedure for the dialog box.     */
  385.          (HMODULE) NULL,        /* Where is the dialog.  Null is EXE file..   */
  386.          ID_CLOCK_DIALOG_BOX,   /* Dialog ID.                                 */
  387.          (PVOID) NULL );        /* Creation Parameters for the dialog.        */
  388.  
  389.    /*
  390.     * Retrieve the handle to the dialog box by specifying the QS_DIALOG flag.
  391.     */
  392.    hwndMainDialogBox = WinQuerySecondaryHWND(hwndFrame, QS_DIALOG);
  393.  
  394.    /*
  395.     * Set the name of the sample program in the title bar of the dialog
  396.     * window.  This is done so that the program name will show up in
  397.     * the Task List window, via the FCF_TASKLIST flag AND will NOT
  398.     * show the .exe file name of the program.  If the FCF_TASKLIST flag
  399.     * is used the .exe file name AND the dialog title will show up
  400.     * in the title bar.  This is not wanted.
  401.     */
  402.    WinSetWindowText(hwndFrame, acStringBuffer[IDS_MAIN_WINDOW_TITLE-1]);
  403.  
  404.    /*
  405.     * Initialize the help structure and associate the help instance to this
  406.     * dialog via it's handle to anchor block.
  407.     */
  408.    InitializeHelp();
  409.  
  410. } /* End of InitializeDialog */
  411.  
  412.  
  413. /*******************************************************************************
  414.  * Name         : TerminateDialog
  415.  *
  416.  * Description  : This routine is called after the message dispatch loop has
  417.  *                ended because of a WM_QUIT message.  The code will destroy
  418.  *                the help instance, messages queue, window, and bitmaps.
  419.  *
  420.  * Concepts     : None.
  421.  *
  422.  * MMPM/2 API's : None.
  423.  *
  424.  * Parameters   : None.
  425.  *
  426.  * Return       : None.
  427.  *
  428.  ******************************************************************************/
  429. VOID TerminateDialog( VOID )
  430. {
  431.    USHORT usCounter = 0;                        /* Generic counter.           */
  432.  
  433.    /*
  434.     * Destroy the Help Instance for this dialog window.
  435.     */
  436.    if ( hwndHelpInstance != (HWND) NULL )
  437.    {
  438.       WinDestroyHelpInstance( hwndHelpInstance );
  439.    }
  440.  
  441.    WinDestroySecondaryWindow( hwndFrame);
  442.    WinDestroyMsgQueue( hmq );
  443.    WinTerminate( hab );
  444.  
  445.    /*
  446.     * Get rid of the clock bitmaps.
  447.     */
  448.    for( usCounter=0; usCounter<NUMBER_OF_BELL_BITMAPS; usCounter++)
  449.    {
  450.       GpiDeleteBitmap( ahbmBellBitMaps[ usCounter ] );
  451.    }
  452.  
  453.    /*
  454.     * Get rid of the space that was malloc to hold the clock waveform
  455.     * files.
  456.     */
  457.    for( usCounter=0; usCounter<NUMBER_OF_AUDIO_CHIMES; usCounter++ )
  458.    {
  459.       free( (VOID *) apltPlayList[ usCounter ][ 0 ].ulOperandOne );
  460.    }
  461.  
  462. }  /* End of TerminateDialog */
  463.  
  464.  
  465. /*******************************************************************************
  466.  * Name        : MainDialogProc
  467.  *
  468.  * Description : This function controls the main dialog box.  It will handle
  469.  *               received messages such as pushbutton notifications, timing
  470.  *               events, etc.
  471.  *
  472.  *               The following messages are handled specifically by this
  473.  *               routine.
  474.  *
  475.  *                  WM_INITDLG
  476.  *                  WM_CLOSE
  477.  *                  WM_PAINT
  478.  *                  WM_TIMER
  479.  *                  WM_HELP
  480.  *                  WM_COMMAND
  481.  *                  WM_MINMAXFRAME
  482.  *                  MM_MCINOTIFY
  483.  *
  484.  * Concepts    : The MM_MCINOTIFY message is used to indicate when to turn
  485.  *               off the swinging of the Bells when the playlist is finished
  486.  *               processing.
  487.  *
  488.  *               In order to update the clock hands when the time has changed,
  489.  *               an OS/2 timer is used to call this window procedure when a
  490.  *               period of time has passed.  When the WM_TIMER message is
  491.  *               received the current time will be compared with the last time
  492.  *               that the clock hands were updated.  If the time is different
  493.  *               then the clock hands will be drawn in positions reflecting
  494.  *               the new time.
  495.  *
  496.  *               The WM_TIMER message will cause the UpdateTheClock routine to
  497.  *               be called which will check the time values and if necessary
  498.  *               invalidate the clock face.  This will cause the clock hands
  499.  *               to be drawn via the WM_PAINT message.
  500.  *
  501.  *               Another routine DealWithChiming is also called to see if it
  502.  *               is time to chime and if the Closed Caption flag is set in
  503.  *               the system.  If it is a Chime Time then the audio chime for
  504.  *               the particular time will be played and if the Closed Caption
  505.  *               flag is set the Bell bitmap will be swung back and forth to
  506.  *               indicate that a chime time has been reached.
  507.  *
  508.  *               Below is a diagram of the the routines called by
  509.  *               DealWithChiming.
  510.  *
  511.  *                                      DealWithChiming()
  512.  *                                              │
  513.  *                                              │
  514.  *                               FindAndPlayTheCorrectChime(...)
  515.  *                                              │
  516.  *                             ┌────────────────┴────────┐
  517.  *                     IsItChimeTime(...)                │
  518.  *                                                       │
  519.  *                                            OpenPlaylistChimeDevice(...)
  520.  *
  521.  *
  522.  * MMPM/2 API's : mciSendCommand
  523.  *
  524.  *
  525.  * Parameters   : hwnd - Handle for the Main dialog box.
  526.  *                msg  - Message received by the dialog box.
  527.  *                mp1  - Parameter 1 for the just recieved message.
  528.  *                mp2  - Parameter 2 for the just recieved message.
  529.  *
  530.  * Return       :
  531.  *
  532.  *
  533.  ******************************************************************************/
  534. MRESULT EXPENTRY MainDialogProc( HWND   hwnd,
  535.                                  ULONG  msg,
  536.                                  MPARAM mp1,
  537.                                  MPARAM mp2 )
  538. {
  539.    static PSWP pswpWindowActionMP    = (PSWP) NULL; /* State of window.       */
  540.    static BOOL fIsTheWindowMinimized = FALSE;   /* Flag for the window state. */
  541.    MCI_GENERIC_PARMS mciGenericParms;/* generic parms for MCI_ACQUIRE         */
  542.    HDC      hdcScreen;
  543.    HDC      hdcMemory;
  544.    HPOINTER hpProgramIcon;          /* Pointer to the program icon.           */
  545.    POINTL   ptlCircleCenter;        /* Point of the center of the circle.     */
  546.    USHORT   usReceivedMessage,      /* MCI message that was received.         */
  547.             usNotifyCode,           /* Notify code from the MCI Notify msg.   */
  548.             usMCIUserParameter;     /* User parameter.                        */
  549.    ULONG    ulPostCount;            /* Count of number of Posts for the Sem.  */
  550.    RECTL    rctWindowRectangle;     /* The area rectangle of the window.      */
  551.    ULONG    ulError;                /* RC for acquire device.                 */
  552.    SIZEL    sizel;                  /* for GpiCreatePS.                       */
  553.  
  554.    switch( msg )
  555.    {
  556.  
  557.       /*
  558.        * The WM_INITDLG is called when the dialog is first being created
  559.        * by the system.
  560.        */
  561.       case WM_INITDLG :
  562.          /*
  563.           * Since the startup of this program can take more than a second,
  564.           * the hourglass icon will be shown to the user.  The main reason
  565.           * for the delay in startup is the chime files that are read in
  566.           * when the program is started.
  567.           */
  568.          WinSetPointer(
  569.             HWND_DESKTOP,        /* Desktop window handle.                    */
  570.             WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  571.                HWND_DESKTOP,     /* Desktop window handle.                    */
  572.                SPTR_WAIT,        /* The Hourglass icon.                       */
  573.                FALSE ) );        /* Return the system pointer's handle.       */
  574.  
  575.          /*
  576.           * Get the sample programs minimize icon.
  577.           */
  578.          hpProgramIcon =
  579.             WinLoadPointer(
  580.                HWND_DESKTOP,
  581.                (HMODULE) NULL, /* Where the resource is kept. (Exe file)      */
  582.                ID_ICON );      /* Which icon to use.                          */
  583.  
  584.          WinDefSecondaryWindowProc(
  585.             hwnd,              /* Dialog window handle.                       */
  586.             WM_SETICON,        /* Message to the dialog.  Set it's icon.      */
  587.             (MPARAM) hpProgramIcon,
  588.             (MPARAM) 0 );      /* mp2 no value.                               */
  589.  
  590.          /*
  591.           * Open screen device context (DC) and create presentation space (PS)
  592.           * associated with it. This DC is a real output device.
  593.           */
  594.          hdcScreen = WinOpenWindowDC ( hwnd );
  595.  
  596.          sizel.cx = 0L;
  597.          sizel.cy = 0L;
  598.          hpsScreen =
  599.             GpiCreatePS (
  600.                hab,                               /* anchor block             */
  601.                hdcScreen,                         /* memory device context    */
  602.                &sizel,                            /* page size data structure */
  603.                GPIT_NORMAL | PU_LOENGLISH |       /* flags                    */
  604.                GPIA_ASSOC );
  605.  
  606.          /*
  607.           * Open memory device context (DC) and create presentation space (PS)
  608.           * associated with it. This DC is not a output device and exists only
  609.           * in the memory.
  610.           */
  611.          hdcMemory =
  612.             DevOpenDC(
  613.                hab,                               /* anchor block             */
  614.                OD_MEMORY,                         /* DC type                  */
  615.                "*",                               /* token not used           */
  616.                0L,                                /* no data struct count     */
  617.                NULL,                              /* no data strct            */
  618.                (ULONG) NULL );                    /* compatible DC            */
  619.  
  620.          sizel.cx = 0;
  621.          sizel.cy = 0;
  622.          hpsMemory =
  623.             GpiCreatePS(
  624.                hab,                               /* anchor block             */
  625.                hdcMemory,                         /* memory device context    */
  626.                &sizel,                            /* page size data structure */
  627.                PU_PELS | GPIT_MICRO | GPIA_ASSOC);/* flags                    */
  628.  
  629.          /*
  630.           * Load the center bell bitmap into memory PS.
  631.           */
  632.          hbmBitmapToShow =
  633.             GpiLoadBitmap(
  634.                hpsMemory,
  635.                (HMODULE) NULL,
  636.                ID_CENTER_BELL,
  637.                (LONG) BELL_BITMAP_X_SIZE,
  638.                (LONG) BELL_BITMAP_Y_SIZE );
  639.  
  640.          /*
  641.           * Display the center bell bitmap and query the bitmap parameters.
  642.           */
  643.          GpiSetBitmap( hpsMemory, hbmBitmapToShow );
  644.          GpiQueryBitmapParameters( hbmBitmapToShow, &bmpInfo );
  645.  
  646.          /*
  647.           * Load the bitmaps into the hpsMemory.
  648.           */
  649.          LoadBellBitmaps();
  650.  
  651.          /*
  652.           * Load the playlist waveform files into memory and set the
  653.           * DATA_OPERATION's first operand to the address of the buffer
  654.           * containing the files.
  655.           */
  656.          SetupPlayList();
  657.  
  658.          /*
  659.           * Place the clock hands in position based on the time.
  660.           */
  661.          UpdateTheClock();
  662.  
  663.          /*
  664.           * Start the timer so that we know to check to see when the time
  665.           * has changed so that we can move the clock hands.
  666.           */
  667.          WinStartTimer(
  668.             hab,                    /* Anchor Block for the window.           */
  669.             hwnd,                   /* Handle for the window.                 */
  670.             CLOCK_TIMER_ID,         /* Id for this particular Timer.          */
  671.             CLOCK_TIMER_TIMEOUT );  /* Number of seconds that the timer waits.*/
  672.  
  673.          /*
  674.           * Now that the startup processing is over, remove the Hourglass
  675.           * icon and replace it with the normal arrow icon.
  676.           */
  677.          WinSetPointer(
  678.             HWND_DESKTOP,        /* Desktop window handle.                    */
  679.             WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  680.                HWND_DESKTOP,     /* Desktop window handle.                    */
  681.                SPTR_ARROW,       /* The Arrow icon.                           */
  682.                FALSE ) );        /* Return the system pointer's handle.       */
  683.  
  684.          hwndPlayChimePB =
  685.             WinWindowFromID(
  686.                hwnd,                /* Handle to the window.                  */
  687.                ID_PLAY_CHIME_PB );  /* Id of the control.                     */
  688.  
  689.          return( 0 );
  690.  
  691.       case WM_CLOSE :
  692.          if ( mciOpenParameters.usDeviceID > 0 )
  693.          {
  694.             mciSendCommand(
  695.                mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  696.                MCI_CLOSE,                    /* MCI message.                  */
  697.                MCI_WAIT,                     /* Flags for the MCI message.    */
  698.                (ULONG) NULL,                 /* Parameters for the message.   */
  699.                (ULONG) NULL );               /* Parameter for notify message. */
  700.          }
  701.  
  702.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  703.  
  704.       case WM_TIMER :
  705.          /*
  706.           * A period of time has passed so check the time and see if the
  707.           * clock hands need to be repositioned.  Also see if Chiming should
  708.           * take place.
  709.           */
  710.          UpdateTheClock();
  711.          DealWithChiming();
  712.          return( 0 );
  713.  
  714.       case WM_HELP :
  715.          /*
  716.           * The dialog window has recieved a request for help from the user,
  717.           * i.e., the Help pushbutton was pressed.  Send the HM_DISPLAY_HELP
  718.           * message to the Help Instance with the IPF resource identifier
  719.           * for the correct HM panel.  This will show the help panel for this
  720.           * sample program.
  721.           */
  722.          WinSendMsg(
  723.             hwndHelpInstance,
  724.             HM_DISPLAY_HELP,
  725.             MPFROMSHORT( 1 ),
  726.             MPFROMSHORT( HM_RESOURCEID ) );
  727.          return( 0 );
  728.  
  729.       case MM_MCINOTIFY :
  730.          /*
  731.           * A MCI Notify message has been recieved as a result of an MCI_PLAY.
  732.           * Process as required.
  733.           */
  734.          usNotifyCode       = SHORT1FROMMP( mp1 );
  735.          usReceivedMessage  = SHORT2FROMMP( mp2 );
  736.          usMCIUserParameter = SHORT2FROMMP( mp1 );
  737.  
  738.          /*
  739.           * If for some reason the Notify code is not successful then the
  740.           * file will be closed OR if the User parameter indicates that the
  741.           * Playlist sent a message indicating that the file has been played.
  742.           */
  743.          if ( ( usNotifyCode != MCI_NOTIFY_SUPERSEDED &&
  744.                 usNotifyCode != MCI_NOTIFY_ABORTED &&
  745.                 usNotifyCode != MCI_NOTIFY_SUCCESSFUL ) ||
  746.               usNotifyCode == MCI_NOTIFY_SUPERSEDED ||
  747.               usNotifyCode == MCI_NOTIFY_ABORTED ||
  748.               (usNotifyCode == MCI_NOTIFY_SUCCESSFUL &&
  749.                  usReceivedMessage == MCI_PLAY ) ||
  750.               usMCIUserParameter == CHIME_PLAYING_HAS_STOPPED )
  751.          {
  752.             /*
  753.              * Turn off the swinging of the visual bells and clean up the
  754.              * audio device.
  755.              */
  756.             yngContinueToSwingTheBell = STOP;
  757.             DosResetEventSem(
  758.                hevContinueToSwingTheBell,    /* Semaphore Handle.             */
  759.                &ulPostCount );               /* How many times Posted.        */
  760.  
  761.             mciSendCommand(
  762.                mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  763.                MCI_CLOSE,                    /* MCI message.                  */
  764.                MCI_WAIT,                     /* Flags for the MCI message.    */
  765.                (ULONG) NULL,                 /* Parameters for the message.   */
  766.                (ULONG) NULL );               /* Parameter for notify message. */
  767.  
  768.             WinEnableWindow(
  769.                hwndPlayChimePB,     /* Handle to the Play Chime push button.  */
  770.                TRUE );              /* Enable the push button.                */
  771.  
  772.          }
  773.  
  774.          return( 0 );
  775.  
  776.       case WM_COMMAND :
  777.          /*
  778.           * To get which pushbutton was pressed the SHORT1FROMMP macro
  779.           * is used.
  780.           */
  781.          switch( SHORT1FROMMP( mp1 ) )
  782.          {
  783.             case ID_PLAY_CHIME_PB :
  784.                /*
  785.                 * Since the user want to play the next hour chime, the next
  786.                 * procedure call will get the current hour and increase it
  787.                 * to the next hour.  However this will only occur if all of
  788.                 * the chime files have been loaded correctly.
  789.                 */
  790.                if ( yngAreChimeFilesLoaded == STOP )
  791.                {
  792.                   ShowAMessage(
  793.                      acStringBuffer[
  794.                         IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  795.                      IDS_CHIME_FILE_ERROR,
  796.                      MB_CANCEL | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  797.                         MB_MOVEABLE );
  798.                }
  799.                else
  800.                {
  801.                   FindTheNearestChimeTimeAndPlayIt();
  802.                }
  803.  
  804.                return( 0 );
  805.  
  806.             case DID_CANCEL:                      /* Handle ESC key */
  807.             case ID_CANCEL_PB :
  808.                WinSendMsg(
  809.                   hwnd,
  810.                   WM_CLOSE,
  811.                   (MPARAM) NULL,
  812.                   (MPARAM) NULL );
  813.  
  814.                return( 0 );
  815.  
  816.          }  /* End of Command Switch */
  817.  
  818.          return( 0 );
  819.  
  820.       case WM_MINMAXFRAME :
  821.  
  822.          hwndPlayChimePB =
  823.             WinWindowFromID(
  824.                hwnd,                /* Handle of this dialog window.          */
  825.                ID_PLAY_CHIME_PB );  /* ID of the left most PM control.        */
  826.  
  827.          pswpWindowActionMP = (PSWP) LONGFROMMP( mp1 );
  828.  
  829.          if ( pswpWindowActionMP->fl & SWP_MINIMIZE )
  830.          {
  831.             fIsTheWindowMinimized = TRUE;
  832.             WinSetWindowPos(
  833.                hwndPlayChimePB,        /* Handle to the control.              */
  834.                HWND_BOTTOM,            /* Place the control behind siblings.  */
  835.                X_PLAY_CHIME_POSITION,  /* X position of the control.          */
  836.                Y_PLAY_CHIME_POSITION,  /* Y position of the control.          */
  837.                X_SIZE_OF_THE_BUTTONS,  /* X size of the control.              */
  838.                Y_SIZE_OF_THE_BUTTONS,  /* Y size of the control.              */
  839.                SWP_HIDE | SWP_ACTIVATE ); /* Positioning options.             */
  840.          }
  841.          else
  842.          {
  843.             fIsTheWindowMinimized = FALSE;
  844.             WinSetWindowPos(
  845.                hwndPlayChimePB,        /* Handle to the control.              */
  846.                HWND_BOTTOM,            /* Place the control behind siblings.  */
  847.                X_PLAY_CHIME_POSITION,  /* X position of the control.          */
  848.                Y_PLAY_CHIME_POSITION,  /* Y position of the control.          */
  849.                X_SIZE_OF_THE_BUTTONS,  /* X size of the control.              */
  850.                Y_SIZE_OF_THE_BUTTONS,  /* Y size of the control.              */
  851.                SWP_SHOW | SWP_ACTIVATE ); /* Positioning options.             */
  852.          }
  853.  
  854.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  855.  
  856.       case WM_PAINT :
  857.       {
  858.          if ( fIsTheWindowMinimized == FALSE )
  859.          {
  860.             hps =
  861.                WinBeginPaint(
  862.                   hwnd,             /* Window that wants PS.                  */
  863.                   (HPS) NULL,       /* Get a Cache Pres. Space.               */
  864.                   (PRECTL) NULL );
  865.  
  866.             GpiSetLineWidth(
  867.                hps,
  868.                LINEWIDTH_NORMAL * 3 );
  869.  
  870.             /*
  871.              * Get the size of the window.
  872.              */
  873.             WinQueryWindowRect(
  874.                hwnd,                            /* Handle to the window.      */
  875.                (PRECTL) &rctWindowRectangle );  /* Size of the window.        */
  876.  
  877.             /*
  878.              * Fill the presentation space.
  879.              */
  880.             WinFillRect(
  881.                hps,                             /* Presentation Space.        */
  882.                (PRECTL) &rctWindowRectangle,    /* Size of the window.        */
  883.                SYSCLR_FIELDBACKGROUND);         /* The background color.      */
  884.  
  885.             /*
  886.              * Calculate the center of the window.
  887.              */
  888.             ptlCircleCenter.x =
  889.                ( ( rctWindowRectangle.xRight - rctWindowRectangle.xLeft ) / 2 );
  890.             ptlCircleCenter.y =
  891.                ( ( rctWindowRectangle.yTop - Y_ADJUSTMENT_SIZE_OF_BUTTONS -
  892.                   rctWindowRectangle.yBottom ) / 2 );
  893.  
  894.             /*
  895.              * Calculate the rectangular area of the clock face by using the
  896.              * center point of the window and the macros that discribe its
  897.              * size.  The values calculated below are used to invalidate the
  898.              * portions of the window so that the clock hands can be re-drawn
  899.              * when the time changes.  The area that is invalidated is a
  900.              * square that is the two minute hand lengths from side to side.
  901.              */
  902.             rctClockFaceRectangle.xLeft   =
  903.                ptlCircleCenter.x - (LONG)
  904.                   (MARKER_POSITION_FROM_CENTER - 25 );
  905.             rctClockFaceRectangle.yBottom =
  906.                ptlCircleCenter.y - (LONG)
  907.                   (MARKER_POSITION_FROM_CENTER - 25 );
  908.  
  909.             rctClockFaceRectangle.xRight  =
  910.                ptlCircleCenter.x + (LONG)
  911.                   (MARKER_POSITION_FROM_CENTER - 25 );
  912.             rctClockFaceRectangle.yTop    =
  913.                ptlCircleCenter.y + (LONG)
  914.                   (MARKER_POSITION_FROM_CENTER - 25 );
  915.  
  916.             /*
  917.              * Draw the clock face, the hour, minute hands, and center circle.
  918.              *   Order is important when drawing the hour and minute hands.
  919.              *   Since the minute hand is longer than the hour, the minute
  920.              *   hand should be drawn first followed by the hour hand.
  921.              */
  922.             DrawTheClockFace(
  923.                hps,                 /* Presentation Space.                    */
  924.                &ptlCircleCenter );  /* Point to the center of the clock face. */
  925.  
  926.             DrawTheMinuteHand(
  927.                hps,                 /* Presentation Space.                    */
  928.                &ptlCircleCenter,    /* Point to the center of the clock face. */
  929.                usMinute);           /* Minute value for the clock hand.       */
  930.  
  931.             DrawTheHourHand(
  932.                hps,                 /* Presentation Space.                    */
  933.                &ptlCircleCenter,    /* Point to the center of the clock face. */
  934.                usHour,              /* Hour value for the clock hand.         */
  935.                usMinute);           /* Minute value for the clock hand.       */
  936.  
  937.             DrawClockCircles(
  938.                hps,                 /* Handle to the Presentation space.      */
  939.                &ptlCircleCenter,    /* Position to place the Marker.          */
  940.                CLOCK_HAND_COLOR,    /* Color to make the end dot.             */
  941.                (USHORT) 5 );        /* Size of the time marker circle.        */
  942.  
  943.             /*
  944.              * Set up target rectangle.
  945.              */
  946.             aptl[0].x = rctWindowRectangle.xRight - BELL_BITMAP_X_SIZE - 25;
  947.             aptl[0].y = rctWindowRectangle.yBottom + Y_BITMAP_POSITION;
  948.             aptl[1].x = aptl[0].x + BELL_BITMAP_X_SIZE;
  949.             aptl[1].y = aptl[0].y + BELL_BITMAP_Y_SIZE + 10;
  950.             aptl[2].x = 0;
  951.             aptl[2].y = 0;
  952.             aptl[3].x = bmpInfo.cx-1;
  953.             aptl[3].y = bmpInfo.cy-1;
  954.  
  955.             /*
  956.              * Draw the bitmap.
  957.              */
  958.             GpiBitBlt(
  959.                hpsScreen,                     /* target presentation space.   */
  960.                hpsMemory,                     /* source presentation space.   */
  961.                4L,                            /* # of points.                 */
  962.                aptl,                          /* array of points.             */
  963.                ROP_SRCCOPY,                   /* copy source over destination.*/
  964.                BBO_IGNORE );                  /* ignore eiminated data.       */
  965.  
  966.             WinEndPaint( hps );
  967.  
  968.          }   /* End of Minimize IF */
  969.  
  970.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  971.  
  972.       }  /* End of WM_PAINT. */
  973.  
  974.       /*
  975.        * The next two messages are handled so that the Clock application can
  976.        * participate in device sharing.  Since it opens the devices as
  977.        * shareable devices, other applications can gain control of the devices.
  978.        * When this happens, we will receive a pass device message.  We keep
  979.        * track of this device passing in the fPassed boolean variable.
  980.        *
  981.        * If we do not have access to the device when we receive an activate
  982.        * message, then we will issue an acquire device command to gain
  983.        * access to the device.
  984.        */
  985.  
  986.       case MM_MCIPASSDEVICE:
  987.          if (SHORT1FROMMP(mp2) == MCI_GAINING_USE)
  988.          {
  989.             fPassed = FALSE;                    /* Gaining control of device */
  990.          } else
  991.          {
  992.             fPassed = TRUE;                     /* Losing control of device  */
  993.          }
  994.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  995.  
  996.       case WM_ACTIVATE:
  997.  
  998.          /* We use the WM_ACTIVATE message to participate in device sharing.
  999.           * We first check to see if this is an activate or a deactivate
  1000.           * message (indicated by mp1). Then, we check to see if we've passed
  1001.           * control of the device that we use.  If these conditions are true,
  1002.           * then we issue an acquire device command to regain control of the
  1003.           * device, since we're now the active window on the screen.
  1004.           *
  1005.           * This is one possible method that can be used to implement
  1006.           * device sharing. For applications that are more complex
  1007.           * than this sample program, developers may wish to take
  1008.           * advantage of a more robust method of device sharing.
  1009.           * This can be done by using the MCI_ACQUIRE_QUEUE flag on
  1010.           * the MCI_ACQUIREDEVICE command.  Please refer to the MMPM/2
  1011.           * documentation for more information on this flag.
  1012.           */
  1013.  
  1014.          /*
  1015.           * First we check to see if we've passed control of the device
  1016.           */
  1017.  
  1018.          if ((BOOL)mp1 && fPassed == TRUE) {
  1019.  
  1020.             mciGenericParms.hwndCallback =  hwnd;
  1021.  
  1022.             ulError = mciSendCommand( mciOpenParameters.usDeviceID,
  1023.                                       MCI_ACQUIREDEVICE,
  1024.                                       (ULONG)MCI_NOTIFY,
  1025.                                       (PVOID) &mciGenericParms,
  1026.                                       (USHORT)NULL);
  1027.             if (ulError)
  1028.             {
  1029.                ShowAMessage(acStringBuffer[IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT-1],
  1030.                             IDS_CHIME_FILE_ERROR,       /* ID of message      */
  1031.                             MB_OK | MB_INFORMATION |
  1032.                             MB_HELP | MB_APPLMODAL |
  1033.                             MB_MOVEABLE );              /* Style of msg box.  */
  1034.             }
  1035.          }
  1036.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  1037.  
  1038.  
  1039.       default:
  1040.          return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  1041.  
  1042.    }  /* End of Switch */
  1043.  
  1044.    return( FALSE );
  1045.  
  1046. } /* End of MainDialogProc */
  1047.  
  1048.  
  1049. /*******************************************************************************
  1050.  * Name         : UpdateTheClock
  1051.  *
  1052.  * Description  : This procedure checks to see if the time has changed since
  1053.  *                the last time the clock hands where drawn.  If they have
  1054.  *                and the dialog window is not minimized then the clock hands
  1055.  *                will be redrawn.  If the dialog window is minimized then
  1056.  *                the usLastHour, usLastMinute, usHour, and usMinute global
  1057.  *                variables will be updated to pretend that the clock hands
  1058.  *                have been redrawn.  Whenever the dialog window receives a
  1059.  *                WM_PAINT message the clock hands will be placed into the
  1060.  *                correct position.
  1061.  *
  1062.  * Concepts     : None.
  1063.  *
  1064.  * MMPM/2 API's : None.
  1065.  *
  1066.  * Parameters   : None.
  1067.  *
  1068.  * Return       : None.
  1069.  *
  1070.  ******************************************************************************/
  1071. VOID UpdateTheClock(VOID)
  1072. {
  1073.    DATETIME dtDateTime;          /* Structure to get the date and time.       */
  1074.    USHORT   usNowHour,           /* Hour converted from the above structure.  */
  1075.             usNowMinute;         /* Minute converted from the above structure.*/
  1076.  
  1077.    extern USHORT usLastHour;
  1078.    extern USHORT usLastMinute;
  1079.  
  1080.  
  1081.    DosGetDateTime( &dtDateTime );
  1082.  
  1083.    usNowHour   = (USHORT) dtDateTime.hours;
  1084.    usNowMinute = (USHORT) dtDateTime.minutes;
  1085.  
  1086.    /*
  1087.     * See if the current time differs from the last updated time.  If this is
  1088.     * the case then the clock hands need to be redrawn in the new positions.
  1089.     */
  1090.    if ( usNowHour != usLastHour ||
  1091.         usNowMinute != usLastMinute )
  1092.    {
  1093.       /*
  1094.        * Update the global variables to the new time so that the WM_PAINT
  1095.        * code can set the new hand positions.
  1096.        */
  1097.       usHour   = usNowHour;
  1098.       usMinute = usNowMinute;
  1099.  
  1100.       /*
  1101.        * Since the Time has changed, invalidate the window so that the
  1102.        * clock hands can be redrawn.
  1103.        */
  1104.  
  1105.       WinInvalidateRect(
  1106.          hwndMainDialogBox,
  1107.          &rctClockFaceRectangle,
  1108.          FALSE );
  1109.    }
  1110. } /* End of UpdateTheClock */
  1111.  
  1112. /*****************************************************************************
  1113.  * Name         : DealWithChiming
  1114.  *
  1115.  * Description  : This procedure will handle all of the processing that is
  1116.  *                required to play a chime.  The first thing the procedure
  1117.  *                does is to check to see if it is time to chime. If it is
  1118.  *                then the chiming process will be started otherwise the
  1119.  *                procedure will return to the calling routine.
  1120.  *
  1121.  * Concepts     : None.
  1122.  *
  1123.  * MMPM/2 API's : mciQuerySysValue
  1124.  *
  1125.  * Parameters   : None.
  1126.  *
  1127.  * Return       : None.
  1128.  *
  1129.  ******************************************************************************/
  1130. VOID DealWithChiming( VOID )
  1131. {
  1132.    CHIME_TIME_VALUE_T ctvChimeTime; /* Chime time structure.                  */
  1133.    USHORT usHour;                   /* Hour time.                             */
  1134.    ULONG  fClosedCaptionIsSet;      /* Is closed caption set.                 */
  1135.  
  1136.    if ( IsItChimeTime( &ctvChimeTime, &usHour ) == TRUE &&
  1137.            fThreadIsAlive == TRUE )
  1138.    {
  1139.  
  1140.       /*
  1141.        * If the Close Caption Flag indicates that the bell should be
  1142.        * animated( swung ) then the region of the Presentation space
  1143.        * that contains the Bell bitmap is to be invalidated so that a
  1144.        * WM_PAINT will be sent to draw the Bells.
  1145.        */
  1146.       mciQuerySysValue( MSV_CLOSEDCAPTION, (PVOID)&fClosedCaptionIsSet );
  1147.  
  1148.       if ( (BOOL)fClosedCaptionIsSet == TRUE)
  1149.       {
  1150.           /*
  1151.            * The bell is ready to be swung if needed and the thread that will
  1152.            * swing the bell is running so allow the bell to go.
  1153.            */
  1154.            yngContinueToSwingTheBell = GO;
  1155.            DosPostEventSem(
  1156.               hevContinueToSwingTheBell );  /* Semaphore Handle.          */
  1157.  
  1158.       }  /* End of test for closed caption. */
  1159.  
  1160.       FindAndPlayTheCorrectChime(
  1161.          ctvChimeTime,  /* Current Chime Time value.                          */
  1162.          usHour );      /* The current hour.                                  */
  1163.  
  1164.    }  /* End of Chiming */
  1165.    else
  1166.    if ( fThreadIsAlive == FALSE )
  1167.    {
  1168.       ShowAMessage(
  1169.           acStringBuffer[
  1170.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT -  1 ],
  1171.             IDS_SWING_THREAD_NOT_STARTED,   /* ID of the message.       */
  1172.             MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  1173.                MB_MOVEABLE );                /* Message box style.      */
  1174.    }
  1175.  
  1176. } /* End of DealWithChiming */
  1177.  
  1178.  
  1179. /******************************************************************************
  1180.  * Name         : FindTheNearestChimeTimeAndPlayIt
  1181.  *
  1182.  * Description  : This procedure is called when the Play Chime pushbutton is
  1183.  *                pressed.  The code will calculate the next Hour chime time,
  1184.  *                check to see if the CLosed Caption flag is set so that the
  1185.  *                bell can be swung back and forth, and finally will call a
  1186.  *                procedure to start the process to play the next Hour chime.
  1187.  *
  1188.  * Concepts     : None.
  1189.  *
  1190.  * MMPM/2 API's : None.
  1191.  *
  1192.  * Parameters   : None.
  1193.  *
  1194.  * Return       : None.
  1195.  *
  1196.  ******************************************************************************/
  1197. VOID FindTheNearestChimeTimeAndPlayIt( VOID )
  1198. {
  1199.  
  1200.    DATETIME dtDateTime;          /* Date time structure.                      */
  1201.    USHORT   usNextHour;          /* The hour to play.                         */
  1202.    ULONG    fClosedCaptionIsSet; /* Is closed caption set.                    */
  1203.  
  1204.    /*
  1205.     * Since the startup to play the chime can take more than a second, the
  1206.     * hourglass icon will be shown to the user.
  1207.     */
  1208.    WinSetPointer(
  1209.       HWND_DESKTOP,        /* Desktop window handle.                    */
  1210.       WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  1211.          HWND_DESKTOP,     /* Desktop window handle.                    */
  1212.          SPTR_WAIT,        /* The Hourglass icon.                       */
  1213.          FALSE ) );        /* Return the system pointer's handle.       */
  1214.  
  1215.    DosGetDateTime( &dtDateTime );
  1216.  
  1217.    usNextHour = (USHORT) dtDateTime.hours;
  1218.  
  1219.    /*
  1220.     * If it is 24:00, i.e., Midnight the system will return 0.  We want 12.
  1221.     */
  1222.    if ( usNextHour == 0 )
  1223.    {
  1224.       usNextHour = 12;
  1225.    }
  1226.  
  1227.    /*
  1228.     * Go to the next hour.
  1229.     */
  1230.    usNextHour++;
  1231.  
  1232.    /*
  1233.     * Make sure that the next hour does not go past 12 o' clock.  The time
  1234.     * is kept by the system in "military" time, i.e., 4:42 is 16:42 thus
  1235.     * we need to play the Hour chime 4 times not 16.  Therefore subtract
  1236.     * 12 from the next hour value.
  1237.     */
  1238.    if ( usNextHour > 12 )
  1239.    {
  1240.       usNextHour-= 12;
  1241.    }
  1242.  
  1243.     /*
  1244.     * If the Close Caption Flag indicates that the bell should be animate
  1245.     * ( swung ) then the region of the Presentation space that contains
  1246.     * the Bell bitmap is to be invalidated so that a WM_PAINT will be sent
  1247.     * to draw the Bells.
  1248.     */
  1249.    mciQuerySysValue( MSV_CLOSEDCAPTION, (PVOID)&fClosedCaptionIsSet );
  1250.  
  1251.    if ( (BOOL)fClosedCaptionIsSet == TRUE &&
  1252.               fThreadIsAlive == TRUE )
  1253.    {
  1254.         /*
  1255.          * The bell is ready to be swung if needed and the thread that will
  1256.          * swing the bell is running so allow the bell to go.
  1257.          */
  1258.         yngContinueToSwingTheBell = GO;
  1259.         DosPostEventSem(
  1260.            hevContinueToSwingTheBell );  /* Semaphore Handle.          */
  1261.  
  1262.    }  /* End of test for closed caption. */
  1263.    else
  1264.    if ( fThreadIsAlive == FALSE )
  1265.    {
  1266.       ShowAMessage(
  1267.           acStringBuffer[
  1268.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT -  1 ],
  1269.             IDS_SWING_THREAD_NOT_STARTED,   /* ID of the message.       */
  1270.             MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  1271.                MB_MOVEABLE );                /* Message box style.      */
  1272.    }
  1273.  
  1274.    /*
  1275.     * Now that we know what the hour is start playing the chime.
  1276.     */
  1277.    FindAndPlayTheCorrectChime(
  1278.       HOUR,               /* Current Chime Time value.                        */
  1279.       usNextHour );       /* The next hour to chime.                          */
  1280.  
  1281.    /*
  1282.     * Now that the startup processing is over, remove the Hourglass
  1283.     * icon and replace it with the normal arrow icon.
  1284.     */
  1285.    WinSetPointer(
  1286.       HWND_DESKTOP,        /* Desktop window handle.                    */
  1287.       WinQuerySysPointer(  /* This API will give the handle of the PTR. */
  1288.          HWND_DESKTOP,     /* Desktop window handle.                    */
  1289.          SPTR_ARROW,       /* The Hourglass icon.                       */
  1290.          FALSE ) );        /* Return the system pointer's handle.       */
  1291. }  /* End of FindTheNearestChimeTimeAndPlayIt. */
  1292.  
  1293. /*****************************************************************************
  1294.  * Name         : FindAndPlayTheCorrectChime
  1295.  *
  1296.  * Description  : This procedure will take the passed in values, open and
  1297.  *                eventually play the correct chime file based on the given
  1298.  *                information.
  1299.  *
  1300.  * Concepts     : Sending MCI commands to the MCD.
  1301.  *
  1302.  * MMPM/2 API's : mciSendCommand
  1303.  *                MCI_PLAY
  1304.  *
  1305.  * Parameters   : ctvChimeTime           : The time that is to be chimed.
  1306.  *                usHour                 : The Hour to play.
  1307.  *
  1308.  * Return       : None.
  1309.  *
  1310.  ******************************************************************************/
  1311. VOID FindAndPlayTheCorrectChime( CHIME_TIME_VALUE_T ctvChimeTime,
  1312.                                  USHORT             usHour )
  1313. {
  1314.    /*
  1315.     * Flags used to open the playlist.
  1316.     */
  1317.    ULONG    ulPostCount;            /* Count of number of Posts for the Sem.  */
  1318.    ULONG ulError;
  1319.    ULONG ulOpenFlags = MCI_WAIT | MCI_OPEN_PLAYLIST | MCI_OPEN_TYPE_ID |
  1320.                        MCI_OPEN_SHAREABLE;
  1321.  
  1322.    switch( ctvChimeTime )
  1323.    {
  1324.       case HOUR :
  1325.       {
  1326.  
  1327.          OpenPlaylistChimeDevice(
  1328.             ulOpenFlags,                  /* The flags to use when Opening.*/
  1329.             HOUR_PLAYLIST );              /* Which chime file to open.     */
  1330.  
  1331.          /*
  1332.           * Set the playlist to loop for the number of hours that is to
  1333.           * be played.  The hour value will be placed into the high order
  1334.           * of the 32 bit value in operand one of the playlist structure.
  1335.           */
  1336.          apltPlayList[ HOUR_PLAYLIST ][ LOOP_LINE ].ulOperandOne =
  1337.             ((ULONG) (usHour));
  1338.  
  1339.          SetupChimeFileInformation();
  1340.  
  1341.          /*
  1342.           * fill in handle of main window proc for callback processing
  1343.           * after play completes.
  1344.           */
  1345.          mciOpenParameters.hwndCallback = hwndMainDialogBox;
  1346.  
  1347.  
  1348.          ulError =
  1349.          mciSendCommand(
  1350.             mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  1351.             MCI_PLAY,                     /* MCI message.                  */
  1352.             MCI_NOTIFY,                   /* Flags for the MCI message.    */
  1353.             (PVOID) &mciOpenParameters,   /* Parameters for the message.   */
  1354.             HOUR_PLAYLIST );              /* Parameter for notify message. */
  1355.  
  1356.          if (ulError)
  1357.          {
  1358.             /*
  1359.              * Turn off the swinging of the visual bells
  1360.              */
  1361.             yngContinueToSwingTheBell = STOP;
  1362.             DosResetEventSem(
  1363.                hevContinueToSwingTheBell,    /* Semaphore Handle.             */
  1364.                &ulPostCount );               /* How many times Posted.        */
  1365.  
  1366.             ShowAMessage(acStringBuffer[IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT-1],
  1367.                          IDS_CANNOT_PLAY_CHIME,       /* ID of message      */
  1368.                          MB_OK | MB_INFORMATION |
  1369.                          MB_HELP | MB_APPLMODAL |
  1370.                          MB_MOVEABLE );              /* Style of msg box.  */
  1371.             break;
  1372.          }
  1373.          /* Disable the Play Chime pushbutton while the chime is playing. */
  1374.  
  1375.          WinEnableWindow(
  1376.             hwndPlayChimePB,     /* Handle to the Play Chime push button.   */
  1377.             FALSE);              /* Disable the push button.                */
  1378.  
  1379.          break;
  1380.       }  /* End of Hour Chime. */
  1381.  
  1382.       case HALF_HOUR :
  1383.       {
  1384.          OpenPlaylistChimeDevice(
  1385.             ulOpenFlags,               /* The flags to use when Opening.   */
  1386.             HALF_HOUR_PLAYLIST );      /* Which chime file to open.        */
  1387.  
  1388.          SetupChimeFileInformation();
  1389.  
  1390.          /*
  1391.           * fill in handle of main window proc for callback processing
  1392.           * after play completes.
  1393.           */
  1394.          mciOpenParameters.hwndCallback = hwndMainDialogBox;
  1395.  
  1396.          ulError =
  1397.          mciSendCommand(
  1398.             mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  1399.             MCI_PLAY,                     /* MCI message.                  */
  1400.             MCI_NOTIFY,                   /* Flags for the MCI message.    */
  1401.             (PVOID) &mciOpenParameters,   /* Parameters for the message.   */
  1402.             HALF_HOUR_PLAYLIST );         /* Parameter for notify message. */
  1403.  
  1404.          if (ulError)
  1405.          {
  1406.             /*
  1407.              * Turn off the swinging of the visual bells
  1408.              */
  1409.             yngContinueToSwingTheBell = STOP;
  1410.             DosResetEventSem(
  1411.                hevContinueToSwingTheBell,    /* Semaphore Handle.             */
  1412.                &ulPostCount );               /* How many times Posted.        */
  1413.  
  1414.             ShowAMessage(acStringBuffer[IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT-1],
  1415.                          IDS_CANNOT_PLAY_CHIME,       /* ID of message      */
  1416.                          MB_OK | MB_INFORMATION |
  1417.                          MB_HELP | MB_APPLMODAL |
  1418.                          MB_MOVEABLE );              /* Style of msg box.  */
  1419.          }
  1420.  
  1421.          break;
  1422.       }  /* End of Half Hour Chime. */
  1423.  
  1424.       case QUARTER_HOUR :
  1425.       {
  1426.          OpenPlaylistChimeDevice(
  1427.             ulOpenFlags,               /* The flags to use when Opening.   */
  1428.             QUARTERS_PLAYLIST );       /* Which chime file to open.        */
  1429.  
  1430.          SetupChimeFileInformation();
  1431.  
  1432.          /*
  1433.           * fill in handle of main window proc for callback processing
  1434.           * after play completes.
  1435.           */
  1436.          mciOpenParameters.hwndCallback = hwndMainDialogBox;
  1437.  
  1438.          ulError =
  1439.          mciSendCommand(
  1440.             mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  1441.             MCI_PLAY,                     /* MCI message.                  */
  1442.             MCI_NOTIFY,                   /* Flags for the MCI message.    */
  1443.             (PVOID) &mciOpenParameters,   /* Parameters for the message.   */
  1444.             QUARTERS_PLAYLIST );          /* Parameter for notify message. */
  1445.  
  1446.          if (ulError)
  1447.          {
  1448.             /*
  1449.              * Turn off the swinging of the visual bells
  1450.              */
  1451.             yngContinueToSwingTheBell = STOP;
  1452.             DosResetEventSem(
  1453.                hevContinueToSwingTheBell,    /* Semaphore Handle.             */
  1454.                &ulPostCount );               /* How many times Posted.        */
  1455.  
  1456.             ShowAMessage(acStringBuffer[IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT-1],
  1457.                          IDS_CANNOT_PLAY_CHIME,       /* ID of message      */
  1458.                          MB_OK | MB_INFORMATION |
  1459.                          MB_HELP | MB_APPLMODAL |
  1460.                          MB_MOVEABLE );              /* Style of msg box.  */
  1461.          }
  1462.  
  1463.          break;
  1464.       }  /* End of Quarter Hour chime. */
  1465.  
  1466.       case THREE_QUARTER_HOUR :
  1467.       {
  1468.          OpenPlaylistChimeDevice(
  1469.             ulOpenFlags,               /* The flags to use when Opening.   */
  1470.             THREE_QUARTERS_PLAYLIST ); /* Which chime file to open.        */
  1471.  
  1472.          SetupChimeFileInformation();
  1473.  
  1474.          /*
  1475.           * fill in handle of main window proc for callback processing
  1476.           * after play completes.
  1477.           */
  1478.          mciOpenParameters.hwndCallback = hwndMainDialogBox;
  1479.  
  1480.          ulError =
  1481.          mciSendCommand(
  1482.             mciOpenParameters.usDeviceID, /* Device to play the chimes.    */
  1483.             MCI_PLAY,                     /* MCI message.                  */
  1484.             MCI_NOTIFY,                   /* Flags for the MCI message.    */
  1485.             (PVOID) &mciOpenParameters,   /* Parameters for the message.   */
  1486.             THREE_QUARTERS_PLAYLIST );    /* Notify Parameter.           */
  1487.  
  1488.          if (ulError)
  1489.          {
  1490.             /*
  1491.              * Turn off the swinging of the visual bells
  1492.              */
  1493.             yngContinueToSwingTheBell = STOP;
  1494.             DosResetEventSem(
  1495.                hevContinueToSwingTheBell,    /* Semaphore Handle.             */
  1496.                &ulPostCount );               /* How many times Posted.        */
  1497.  
  1498.             ShowAMessage(acStringBuffer[IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT-1],
  1499.                          IDS_CANNOT_PLAY_CHIME,       /* ID of message      */
  1500.                          MB_OK | MB_INFORMATION |
  1501.                          MB_HELP | MB_APPLMODAL |
  1502.                          MB_MOVEABLE );              /* Style of msg box.  */
  1503.          }
  1504.  
  1505.          break;
  1506.       }  /* End of Three Quarter Hour Chime. */
  1507.    }  /* End of Switch. */
  1508.  
  1509. }  /* End of FindAndPlayTheCorrectChime */
  1510.  
  1511.  
  1512. /******************************************************************************
  1513.  * Name        : SetupChimeFileInformation
  1514.  *
  1515.  * Description : This procedure tells the MCD information about the file
  1516.  *               that is about to be played.  The Samples Per Second,
  1517.  *               Bits Per Sample, and the number of channels with which
  1518.  *               the waveform file was created has to be told to the MCD.
  1519.  *
  1520.  * Concepts    : How to set information on waveform files so that they may
  1521.  *               be played.  This info was obtained by querying the header
  1522.  *               of the waveform file in the routine CopyWaveformIntoMemory.
  1523.  *               This information is stored in the global variable,
  1524.  *               mmAudioHeader.
  1525.  *               In this routine, the info is set by issuing an mciSendCommand
  1526.  *               with the MCI_SET message.
  1527.  *
  1528.  * MMPM/2 API's: mciSendCommand
  1529.  *               MCI_SET
  1530.  *
  1531.  * Parameters  : None.
  1532.  *
  1533.  * Return      : None.
  1534.  *
  1535.  ******************************************************************************/
  1536. VOID SetupChimeFileInformation( VOID )
  1537. {
  1538.    MCI_WAVE_SET_PARMS mwspWaveFormParameters;   /* Waveform parameters.       */
  1539.    ULONG              ulRC;                     /* Return code.               */
  1540.  
  1541.    /*
  1542.     * Fill the structure with zeros.
  1543.     */
  1544.    memset( &mwspWaveFormParameters,            /* Object to fill with zeros.  */
  1545.            0,                                  /* Value to place in object.   */
  1546.            sizeof( mwspWaveFormParameters ) ); /* How many zeros's to use.    */
  1547.  
  1548.    /*
  1549.     * Set structure values for the MCI_SET.
  1550.     */
  1551.    mwspWaveFormParameters.ulSamplesPerSec =
  1552.       mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  1553.    mwspWaveFormParameters.usBitsPerSample =
  1554.       mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
  1555.    mwspWaveFormParameters.usChannels     =
  1556.       mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
  1557.    mwspWaveFormParameters.ulAudio        =
  1558.       MCI_SET_AUDIO_ALL;
  1559.  
  1560.    /*
  1561.     * Set the number of channels.
  1562.     */
  1563.    ulRC =
  1564.       mciSendCommand(
  1565.          mciOpenParameters.usDeviceID,
  1566.          MCI_SET,
  1567.          MCI_WAIT | MCI_WAVE_SET_CHANNELS,
  1568.          (PVOID) &mwspWaveFormParameters,
  1569.          0 );
  1570.  
  1571.    /*
  1572.     * Set the samples per second for the waveform file.
  1573.     */
  1574.    ulRC =
  1575.       mciSendCommand(
  1576.          mciOpenParameters.usDeviceID,
  1577.          MCI_SET,
  1578.          MCI_WAIT | MCI_WAVE_SET_SAMPLESPERSEC,
  1579.          (PVOID) &mwspWaveFormParameters,
  1580.          0 );
  1581.  
  1582.    /*
  1583.     * Set the bits per second for the waveform file.
  1584.     */
  1585.    ulRC =
  1586.       mciSendCommand(
  1587.          mciOpenParameters.usDeviceID,
  1588.          MCI_SET,
  1589.          MCI_WAIT | MCI_WAVE_SET_BITSPERSAMPLE,
  1590.          (PVOID) &mwspWaveFormParameters,
  1591.          0 );
  1592.  
  1593. }  /* End of SetupChimeFileInformation. */
  1594.  
  1595.  
  1596. /******************************************************************************
  1597.  * Name        : OpenPlaylistChimeDevice
  1598.  *
  1599.  * Description : This procedure opens a device based on the variable
  1600.  *               usChimeFileToPlay with the open flags given in the
  1601.  *               ulOpenFlags parameter.  The code uses the given parameters
  1602.  *               to set up the open parameters structure and then simply
  1603.  *               opens the playlist.
  1604.  *
  1605.  * Concepts    : How to open playlists and how to retrieve error information
  1606.  *               from failed MMPM/2 APIs.
  1607.  *
  1608.  * MMPM/2 API's: mciSendCommand
  1609.  *               mciGetErrorString
  1610.  *               MCI_OPEN
  1611.  *
  1612.  * Parameters  : ulOpenFlags       : The flags to use when opending the file.
  1613.  *               usChimePlaylistToPlay : Which chime to play.
  1614.  *
  1615.  * Return      : None.
  1616.  *
  1617.  ******************************************************************************/
  1618. VOID OpenPlaylistChimeDevice( ULONG  ulOpenFlags,
  1619.                               USHORT usChimePlaylistToPlay )
  1620.  
  1621. {
  1622.    ULONG mciRC;                 /* MCI generic return code variable.          */
  1623.  
  1624.    /*
  1625.     * Holds error text discription.
  1626.     */
  1627.    CHAR  acErrorStringBuffer[ MCI_ERROR_STRING_LENGTH ];
  1628.  
  1629.    /*
  1630.     * Open the correct waveform device for the chimes with the MCI_OPEN
  1631.     * message to MCI.
  1632.     */
  1633.    mciOpenParameters.pszDeviceType    = (PSZ)
  1634.       MAKEULONG ( MCI_DEVTYPE_WAVEFORM_AUDIO, 1 );
  1635.  
  1636.    /*
  1637.     * The address of the buffer containing the chime waveform file.
  1638.     */
  1639.    mciOpenParameters.pszElementName =
  1640.                (PSZ)&apltPlayList[ usChimePlaylistToPlay ][ 0 ];
  1641.  
  1642.    /*
  1643.     * Initialize the MCI_OPEN_PARMS data structure with hwndMainDialogBox
  1644.     * as callback handle for MM_MCIPASSDEVICE, then issue the MCI_OPEN
  1645.     * command with the mciSendCommand function.  No alias is used.
  1646.     */
  1647.    mciOpenParameters.hwndCallback  = hwndMainDialogBox;
  1648.    mciOpenParameters.pszAlias      = (CHAR) NULL;
  1649.  
  1650.    /*
  1651.     * Open the waveform file in the playlist mode.
  1652.     */
  1653.    mciRC =
  1654.       mciSendCommand(
  1655.          0,                           /* We don't know the device yet.        */
  1656.          MCI_OPEN,                    /* MCI message.                         */
  1657.          ulOpenFlags,                 /* Flags for the MCI message.           */
  1658.          (PVOID) &mciOpenParameters,  /* Parameters for the message.          */
  1659.          0 );                         /* Parameter for notify message.        */
  1660.  
  1661.    if ( mciRC != 0 )
  1662.    {
  1663.       mciRC =
  1664.          mciGetErrorString(
  1665.             mciRC,
  1666.             (PSZ)&acErrorStringBuffer[ 0 ],
  1667.             (USHORT) MCI_ERROR_STRING_LENGTH );
  1668.  
  1669.       /*
  1670.        * Make sure that the retrieving of the error string was successfull.
  1671.        */
  1672.       if ( mciRC != MCIERR_SUCCESS )
  1673.       {
  1674.          ShowAMessage(
  1675.             acStringBuffer[
  1676.                IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  1677.             IDS_CHIME_FILE_ERROR,
  1678.             MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP | MB_APPLMODAL  );
  1679.  
  1680.          return;
  1681.  
  1682.       }  /* End of IF testing for failed Get Error String API. */
  1683.  
  1684.       /*
  1685.        * Show the error string that was retrieved by the mciGetErrorString
  1686.        * MMPM/2 API.
  1687.        */
  1688.       WinMessageBox(
  1689.          HWND_DESKTOP,                  /* Parent handle.                     */
  1690.          hwndMainDialogBox,             /* Owner handle of the message box.   */
  1691.          acErrorStringBuffer,           /* String to show in the message box. */
  1692.          acStringBuffer[
  1693.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],  /* Title.               */
  1694.          ID_MESSAGE_BOX,                /* Message Box Id.                    */
  1695.          MB_OK | MB_INFORMATION );      /* The style of the message box.      */
  1696.  
  1697.    }  /* End of IF testing for failed MCI Send Command API. */
  1698.  
  1699. }  /* End of OpenPlaylistChimeDevice. */
  1700.  
  1701.  
  1702. /******************************************************************************
  1703.  * Name        : IsItChimeTime
  1704.  *
  1705.  * Description : This procedure will start the processing that is required
  1706.  *               to play a chime.  The first thing the procedure does is
  1707.  *               to check to see if it is time to chime.  If it is, then the
  1708.  *               chime file that is used will be determined and the function
  1709.  *               will return TRUE to the calling routine.  The calling code
  1710.  *               will continue with the processing requied to play a chime
  1711.  *               file.
  1712.  *
  1713.  * Concepts    : None.
  1714.  *
  1715.  * MMPM/2 API's: None.
  1716.  *
  1717.  * Parameters  : ctvChimeTime - What time is it, hour, quarter hour, etc.
  1718.  *               pusNowHour   - Holds the actual hour value.
  1719.  *
  1720.  * Return      : TRUE         - if it is time to chime.
  1721.  *               FALSE        - if it is NOT time to chime.
  1722.  *               ctvChimeTime - This will be returned to the calling
  1723.  *                              routine.
  1724.  *
  1725.  ******************************************************************************/
  1726. BOOL IsItChimeTime( CHIME_TIME_VALUE_T *ctvChimeTime,
  1727.                     USHORT             *pusNowHour )
  1728. {
  1729.    /*
  1730.     * The last valid chime time structure in HOUR, QUARTER....
  1731.     */
  1732.    static CHIME_TIME_VALUE_T ctvLastValidChimeTime = NONE;
  1733.  
  1734.    DATETIME dtDateTime;       /* Date time structure.                         */
  1735.    USHORT   usNowHour,        /* The current hour from the above structure.   */
  1736.             usNowMinute;      /* The current minute from the above structure. */
  1737.  
  1738.    DosGetDateTime( &dtDateTime );
  1739.  
  1740.    usNowHour   = (USHORT) dtDateTime.hours;
  1741.    usNowMinute = (USHORT) dtDateTime.minutes;
  1742.  
  1743.    /*
  1744.     * See if it is greater the 12 o' clock.  If it is then subtract 12 to get
  1745.     * the correct hour.  If the time is 0 then it is midnight which is 12.
  1746.     */
  1747.    if ( usNowHour > 12 )
  1748.    {
  1749.       usNowHour -= 12;
  1750.    }
  1751.    else
  1752.    if ( usNowHour == 0 )
  1753.    {
  1754.       usNowHour = 12;
  1755.    }
  1756.  
  1757.    *pusNowHour = usNowHour;
  1758.  
  1759.    /*
  1760.     * See if the time is one of the chime times.  If so and we have not ever
  1761.     * been in this function since the time changed to a chime time, then
  1762.     * the function will return TRUE and the correct chime time indicator.
  1763.     * Otherwise the function will return FALSE and NONE.
  1764.     */
  1765.    if ( (usNowMinute == 0 || usNowMinute == 60) &&
  1766.          ctvLastValidChimeTime != HOUR)
  1767.    {
  1768.       *ctvChimeTime         = HOUR;
  1769.       ctvLastValidChimeTime = HOUR;
  1770.       return( TRUE );
  1771.    }
  1772.    else
  1773.    if ( usNowMinute == 15 && ctvLastValidChimeTime != QUARTER_HOUR )
  1774.    {
  1775.       *ctvChimeTime         = QUARTER_HOUR;
  1776.       ctvLastValidChimeTime = QUARTER_HOUR;
  1777.       return( TRUE );
  1778.    }
  1779.    else
  1780.    if ( usNowMinute == 30 && ctvLastValidChimeTime != HALF_HOUR )
  1781.    {
  1782.       *ctvChimeTime         = HALF_HOUR;
  1783.       ctvLastValidChimeTime = HALF_HOUR;
  1784.       return( TRUE );
  1785.    }
  1786.    else
  1787.    if ( usNowMinute == 45 && ctvLastValidChimeTime != THREE_QUARTER_HOUR )
  1788.    {
  1789.       *ctvChimeTime         = THREE_QUARTER_HOUR;
  1790.       ctvLastValidChimeTime = THREE_QUARTER_HOUR;
  1791.       return( TRUE );
  1792.    }
  1793.    else
  1794.    {
  1795.       *ctvChimeTime         = NONE;
  1796.       return( FALSE );
  1797.    }
  1798.  
  1799. } /* End of IsItChimeTime */
  1800.  
  1801.  
  1802. /******************************************************************************
  1803.  * Name        : InitializeHelp
  1804.  *
  1805.  * Description : This procedure will set up the initial values in the global
  1806.  *               help structure.  This help structure will then be passed on
  1807.  *               to the Help Manager when the Help Instance is created.  The
  1808.  *               handle to the Help Instance will be kept for later use.
  1809.  *
  1810.  * Concepts    : None.
  1811.  *
  1812.  * MMPM/2 API's: None.
  1813.  *
  1814.  * Parameters  : None.
  1815.  *
  1816.  * Return      : None.
  1817.  *
  1818.  ******************************************************************************/
  1819. VOID InitializeHelp( VOID )
  1820. {
  1821.  
  1822.    /*
  1823.     * Get the size of the initialization structure.
  1824.     */
  1825.    hmiHelpStructure.cb              = sizeof( HELPINIT );
  1826.  
  1827.    hmiHelpStructure.ulReturnCode    = (ULONG) NULL; /* RC from initialization.*/
  1828.    hmiHelpStructure.pszTutorialName = (CHAR) NULL;  /* No tutorial program.   */
  1829.  
  1830.    hmiHelpStructure.phtHelpTable    = (PVOID)(0xffff0000 | ID_CLOCK_HELPTABLE);
  1831.  
  1832.    /*
  1833.     * The action bar is not used, so set the following to NULL.
  1834.     */
  1835.    hmiHelpStructure.hmodAccelActionBarModule = (HMODULE) NULL;
  1836.    hmiHelpStructure.idAccelTable             = (USHORT) NULL;
  1837.    hmiHelpStructure.idActionBar              = (USHORT) NULL;
  1838.  
  1839.    /*
  1840.     * The Help window title.
  1841.     */
  1842.    hmiHelpStructure.pszHelpWindowTitle  =
  1843.       acStringBuffer[ IDS_HELP_WINDOW_TITLE - 1 ];
  1844.  
  1845.    /*
  1846.     * The Help table is in the executable file.
  1847.     */
  1848.    hmiHelpStructure.hmodHelpTableModule = (HMODULE) NULL;
  1849.  
  1850.    /*
  1851.     * The help panel ID is not displayed.
  1852.     */
  1853.    hmiHelpStructure.fShowPanelId       = (ULONG) NULL;
  1854.  
  1855.    /*
  1856.     * The library that contains the clock help panels.
  1857.     */
  1858.    hmiHelpStructure.pszHelpLibraryName  =
  1859.       acStringBuffer[ IDS_HELP_LIBRARY_FILE - 1 ];
  1860.  
  1861.    /*
  1862.     * Create the Help Instance for IPF.
  1863.     * Give IPF the Anchor Block handle and address of the IPF initialization
  1864.     * structure, and check that creation of Help was a success.
  1865.     */
  1866.    hwndHelpInstance = WinCreateHelpInstance(
  1867.                          hab,                   /* Anchor Block Handle.       */
  1868.                          &hmiHelpStructure );   /* Help Structure.            */
  1869.  
  1870.    if ( hwndHelpInstance == (HWND) NULL )
  1871.    {
  1872.       ShowAMessage(
  1873.          acStringBuffer[
  1874.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],   /* Message Box title.  */
  1875.          IDS_HELP_CREATION_ERROR,                      /* ID of the message.  */
  1876.          MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_APPLMODAL );
  1877.    }
  1878.    else
  1879.    {
  1880.       if ( hmiHelpStructure.ulReturnCode )
  1881.       {
  1882.          ShowAMessage(
  1883.             acStringBuffer[
  1884.                IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  1885.             IDS_HELP_CREATION_ERROR,           /* ID of the message.          */
  1886.             MB_OK | MB_INFORMATION | MB_APPLMODAL |
  1887.                MB_MOVEABLE );                  /* Message box style.          */
  1888.  
  1889.          WinDestroyHelpInstance( hwndHelpInstance );
  1890.       }
  1891.    }  /* End of IF checking the creation of the Help Instance. */
  1892.  
  1893.    /*
  1894.     * Associate the Help Instance of the IPF to this dialog window.
  1895.     */
  1896.    if ( hwndHelpInstance != (HWND) NULL )
  1897.    {
  1898.      WinAssociateHelpInstance(
  1899.         hwndHelpInstance,     /* The handle of the Help Instance.             */
  1900.         hwndFrame );          /* Associate to this dialog window.             */
  1901.    }
  1902.  
  1903. }  /* End of InitializeHelp */
  1904.  
  1905. /******************************************************************************
  1906.  * Name        : ShowAMessage
  1907.  *
  1908.  * Description : This function will show text in a message box.  The text
  1909.  *               is pulled from the string table that is originally kept
  1910.  *               in the resource file.  The text is retrieved by the
  1911.  *               message id that is passed into this function.  This id is
  1912.  *               used in the WinLoadString OS/2 API to get the correct
  1913.  *               string from the table.
  1914.  *
  1915.  * Concepts    : None.
  1916.  *
  1917.  * MMPM/2 API's: None.
  1918.  *
  1919.  * Parameters  : pcMessageTitle    - The tile to be placed in the message
  1920.  *                                   box.
  1921.  *               usMessageId       - The message id that identifies which
  1922.  *                                   string to retreived from the string
  1923.  *                                   table.
  1924.  *               ulMessageBoxStyle - The style of the message box.  Which
  1925.  *                                   icons, buttons, etc., to show.
  1926.  *
  1927.  * Return      : The result from the message box.
  1928.  *
  1929.  ******************************************************************************/
  1930. USHORT ShowAMessage( CHAR   *pcMessageTitle,
  1931.                      USHORT usMessageId,
  1932.                      ULONG  ulMessageBoxStyle )
  1933. {
  1934.  
  1935.    CHAR   acStringBuffer[ STRING_SIZE ];        /* String Buffer.             */
  1936.    USHORT usMessageBoxResult;                   /* RC from WinMessageBox.     */
  1937.  
  1938.    /*
  1939.     * Get the string from the Resource defined string table and show it
  1940.     * in the message box.
  1941.     */
  1942.    WinLoadString(
  1943.       hab,                             /* HAB for this dialog box.            */
  1944.       (HMODULE) NULL,                  /* Get the string from the .exe file.  */
  1945.       usMessageId,                     /* Which string to get.                */
  1946.       (SHORT) STRING_SIZE,             /* The size of the buffer.             */
  1947.       acStringBuffer );                /* The buffer to place the string.     */
  1948.  
  1949.    usMessageBoxResult =
  1950.       WinMessageBox(
  1951.          HWND_DESKTOP,                 /* Parent handle of the message box.   */
  1952.          hwndMainDialogBox,            /* Owner handle of the message box.    */
  1953.          acStringBuffer,               /* String to show in the message box.  */
  1954.          pcMessageTitle,               /* Title to shown in the message box.  */
  1955.          ID_MESSAGE_BOX,               /* Message Box Id.                     */
  1956.          ulMessageBoxStyle );          /* The style of the message box.       */
  1957.  
  1958.    return( usMessageBoxResult );
  1959.  
  1960. }  /* End of ShowAMessage */
  1961.  
  1962.  
  1963. /******************************************************************************
  1964.  * Name        : SetupPlayList
  1965.  *
  1966.  * Description : This procedure will load the chimes waveform files into
  1967.  *               buffers as well as setting up the required playlists.
  1968.  *
  1969.  *               - Create memory buffers for the waveform( Chimes ) files.
  1970.  *               - Load the chime files into the buffers( mmioRead ).
  1971.  *               - Create the Playlist
  1972.  *
  1973.  * Concepts    : How to create and use the MMPM/2 Playlist functionality.
  1974.  *
  1975.  * MMPM/2 API's: None.
  1976.  *
  1977.  * Parameters  : None.
  1978.  *
  1979.  * Return      : None.
  1980.  *
  1981.  *************************************************************************/
  1982. VOID SetupPlayList( VOID )
  1983. {
  1984.    /*
  1985.     * This array keeps the address of each audio chime file.
  1986.     */
  1987.    static LONG *pulBaseAddress[ NUMBER_OF_CHIME_FILES ];
  1988.  
  1989.    USHORT usChimeFileId;            /* Chime audio file id.                   */
  1990.    ULONG  ulSizeOfFile,             /* Size of audio file.                    */
  1991.  
  1992.    ulMemoryAllocationFlags = PAG_COMMIT | PAG_READ | PAG_WRITE;
  1993.  
  1994.    for(usChimeFileId=0; usChimeFileId<NUMBER_OF_CHIME_FILES; usChimeFileId++)
  1995.    {
  1996.  
  1997.       ulSizeOfFile = HowBigIsTheChimeFile( usChimeFileId );
  1998.  
  1999.       /*
  2000.        * If the returned file size is zero, there is a problem with the chime
  2001.        * files.  A message will already have been shown to the user by the
  2002.        * HowBigIsTheChimeFile function so get out of this routine.
  2003.        */
  2004.       if ( ulSizeOfFile == 0 )
  2005.       {
  2006.          return;
  2007.       }
  2008.  
  2009.       if ( (pulBaseAddress[ usChimeFileId ] = (LONG *)
  2010.               malloc( ulSizeOfFile )) == (LONG *) NULL )
  2011.       {
  2012.          /*
  2013.           * The memory for the waveform files cannot be allocated.
  2014.           * Notify the user and return from this routine.  No playlist can
  2015.           * be created/played until memory is available.
  2016.           */
  2017.          ShowAMessage(
  2018.             acStringBuffer[
  2019.                IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2020.             IDS_CANNOT_GET_MEMORY,              /* ID of the message to show. */
  2021.             MB_OK | MB_INFORMATION | MB_HELP |  MB_APPLMODAL |
  2022.                MB_MOVEABLE );                   /* Style of the message box.  */
  2023.  
  2024.          return;
  2025.  
  2026.       }  /* End of IF allocation fails. */
  2027.  
  2028.       /*
  2029.        * Place the waveform files into the memory buffer that was just
  2030.        * created.
  2031.        */
  2032.       CopyWaveformIntoMemory(
  2033.          pulBaseAddress[ usChimeFileId ],
  2034.          ulSizeOfFile,
  2035.          usChimeFileId );
  2036.  
  2037.       /*
  2038.        * Now that we've loaded the waveform into memory, we need to put
  2039.        * it's address and size into the playlist data statements that
  2040.        * use this particular file.
  2041.        *
  2042.        * It's address must be placed into the Data statement's first operand
  2043.        * and its size must be placed in the Data statement's second operand.
  2044.        *
  2045.        * For the four different playlist, one for each chime time, 1/4, 1/2,
  2046.        * 3/4 and 1 hour increments, the address of the chime file and it's
  2047.        * size will be loaded into each Data statement of the Playlist.
  2048.        */
  2049.       if ( usChimeFileId == 0 )
  2050.       /* If we just loaded clock1.wav */
  2051.       {
  2052.  
  2053.          /*
  2054.           * Put the address of this chime into the first operand of
  2055.           * every data operation that uses this particular chime.
  2056.           */
  2057.          apltPlayList[ 0 ][ 0 ].ulOperandOne =        /* 1/4 hour 1st data op */
  2058.          apltPlayList[ 1 ][ 0 ].ulOperandOne =        /* 1/2 hour 1st data op */
  2059.          apltPlayList[ 2 ][ 0 ].ulOperandOne =        /* 3/4 hour 1st data op */
  2060.          apltPlayList[ 2 ][ 2 ].ulOperandOne =        /* 3/4 hour 3rd data op */
  2061.          apltPlayList[ 3 ][ 0 ].ulOperandOne =        /* 1   hour 1st data op */
  2062.          apltPlayList[ 3 ][ 2 ].ulOperandOne =        /* 1   hour 3rd data op */
  2063.             (ULONG) pulBaseAddress[ usChimeFileId ];  /* address              */
  2064.  
  2065.          /*
  2066.           * Now put the size of the file into the second operand of every
  2067.           * data operation that uses this particular chime.
  2068.           */
  2069.          apltPlayList[ 0 ][ 0 ].ulOperandTwo =        /* 1/4 hour 1st data op */
  2070.          apltPlayList[ 1 ][ 0 ].ulOperandTwo =        /* 1/2 hour 1st data op */
  2071.          apltPlayList[ 2 ][ 0 ].ulOperandTwo =        /* 3/4 hour 1st data op */
  2072.          apltPlayList[ 2 ][ 2 ].ulOperandTwo =        /* 3/4 hour 3rd data op */
  2073.          apltPlayList[ 3 ][ 0 ].ulOperandTwo =        /* 1   hour 1st data op */
  2074.          apltPlayList[ 3 ][ 2 ].ulOperandTwo =        /* 1   hour 3rd data op */
  2075.             ulSizeOfFile;                             /* size                 */
  2076.  
  2077.       }
  2078.       else
  2079.       if ( usChimeFileId == 1 )
  2080.       /* If we just loaded clock2.wav */
  2081.       {
  2082.          /*
  2083.           * Put the address of this chime into the first operand of
  2084.           * every data operation that uses this particular chime.
  2085.           */
  2086.          apltPlayList[ 1 ][ 1 ].ulOperandOne =        /* 1/2 hour 2nd data op */
  2087.          apltPlayList[ 2 ][ 1 ].ulOperandOne =        /* 3/4 hour 2nd data op */
  2088.          apltPlayList[ 3 ][ 1 ].ulOperandOne =        /* 1   hour 2nd data op */
  2089.          apltPlayList[ 3 ][ 3 ].ulOperandOne =        /* 1   hour 4th data op */
  2090.             (ULONG) pulBaseAddress[ usChimeFileId ];  /* address              */
  2091.  
  2092.          /*
  2093.           * Now put the size of the file into the second operand of every
  2094.           * data operation that uses this particular chime.
  2095.           */
  2096.          apltPlayList[ 1 ][ 1 ].ulOperandTwo =        /* 1/2 hour 2nd data op */
  2097.          apltPlayList[ 2 ][ 1 ].ulOperandTwo =        /* 3/4 hour 2nd data op */
  2098.          apltPlayList[ 3 ][ 1 ].ulOperandTwo =        /* 1   hour 2nd data op */
  2099.          apltPlayList[ 3 ][ 3 ].ulOperandTwo =        /* 1   hour 4th data op */
  2100.             ulSizeOfFile;                             /* size                 */
  2101.       }
  2102.       else
  2103.       if ( usChimeFileId == 2 )
  2104.       /* If we just loaded clock3.wav (this is the gong part of the chime) */
  2105.       {
  2106.          /*
  2107.           * Put the address of this chime into the first operand of
  2108.           * every data operation that uses this particular chime.
  2109.           */
  2110.          apltPlayList[ 3 ][ 5 ].ulOperandOne =        /* 1 hour 5th data op */
  2111.             (ULONG) pulBaseAddress[ usChimeFileId ];
  2112.  
  2113.          /*
  2114.           * Now put the size of the file into the second operand of every
  2115.           * data operation that uses this particular chime.
  2116.           */
  2117.          apltPlayList[ 3 ][ 5 ].ulOperandTwo =        /* 1 hour 5th data op */
  2118.             ulSizeOfFile;
  2119.       }
  2120.  
  2121.    }  /* End of For loop of chime files. */
  2122.  
  2123. }  /* End of SetupPlayList */
  2124.  
  2125.  
  2126. /******************************************************************************
  2127.  * Name        : HowBigIsTheChimeFile
  2128.  *
  2129.  * Description : This function will retrieve the size of a chime file.
  2130.  *               The chime file is identified by the passed in parameter.
  2131.  *
  2132.  * Concepts    : None.
  2133.  *
  2134.  * MMPM/2 API's: mmioOpen  - MMIO_READ
  2135.  *               mmioGetHeader
  2136.  *               mmioClose
  2137.  *
  2138.  * Parameters  : usChimeFileId - Chime file id.
  2139.  *
  2140.  * Return      : Size of the file.
  2141.  *
  2142.  ******************************************************************************/
  2143. ULONG HowBigIsTheChimeFile( USHORT usChimeFileId )
  2144. {
  2145.    MMAUDIOHEADER mmAudHeader;          /* Get size of audio data from this.   */
  2146.    HMMIO hmmioFileHandle;              /* Handle to the audio file handle.    */
  2147.    ULONG ulRC;                         /* Return code from mmioGetHeader.     */
  2148.    ULONG ulBytesRead;                  /* Returned from mmioGetHeader.        */
  2149.    LONG  lMMIOResults;                 /* Results from the MMIO calls.        */
  2150.    CHAR  acFileName[ FILE_NAME_SIZE ]; /* Name of the file.                   */
  2151.  
  2152.    switch( usChimeFileId )
  2153.    {
  2154.       case 0 :
  2155.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_A - 1] );
  2156.          break;
  2157.  
  2158.       case 1 :
  2159.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_B - 1 ] );
  2160.          break;
  2161.  
  2162.       case 2 :
  2163.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_C - 1 ] );
  2164.          break;
  2165.  
  2166.       default:
  2167.          ShowAMessage(
  2168.             acStringBuffer[
  2169.                IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2170.             IDS_CHIME_FILE_ERROR,               /* ID of the message to show. */
  2171.             MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2172.                MB_MOVEABLE );                   /* Style of the message box.  */
  2173.  
  2174.          return( 0 );
  2175.  
  2176.    }  /* End of switch statment. */
  2177.  
  2178.    /*
  2179.     * Open the chime file.
  2180.     */
  2181.    hmmioFileHandle =
  2182.       mmioOpen(
  2183.          acFileName,
  2184.          (PMMIOINFO) NULL,
  2185.          MMIO_READ );
  2186.  
  2187.    /*
  2188.     * See if the file open was successful.  If it was not then show an
  2189.     * error message, set a flag so that NO chimes will be played and
  2190.     * return a size 0.
  2191.     */
  2192.    if ( hmmioFileHandle == (HMMIO) NULL )
  2193.    {
  2194.       yngAreChimeFilesLoaded = STOP;
  2195.       ShowAMessage(
  2196.          acStringBuffer[
  2197.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2198.          IDS_CHIME_FILE_ERROR,                  /* ID of the message to show. */
  2199.          MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2200.             MB_MOVEABLE );                      /* Style of the message box.  */
  2201.       return (0);
  2202.    }
  2203.  
  2204.    /*
  2205.     * Get the header information from the waveform file. From this
  2206.     * information, we can get the size of the waveform data in the file.
  2207.     *
  2208.     * We only want to copy the waveform data into memory, we do not
  2209.     * want to copy the header as well.  So, we use the usAudioLengthInBytes
  2210.     * field of the XWAV_HEADERINFO structure, which indicates the size of
  2211.     * the audio data in the file.
  2212.     */
  2213.    ulRC = mmioGetHeader ( hmmioFileHandle,
  2214.                           (PVOID)&mmAudHeader,
  2215.                           sizeof (MMAUDIOHEADER),
  2216.                           (PLONG) &ulBytesRead,
  2217.                           (ULONG) NULL,
  2218.                           (ULONG) NULL);
  2219.  
  2220.  
  2221.    if (ulRC != MMIO_SUCCESS) {
  2222.       yngAreChimeFilesLoaded = STOP;
  2223.       ShowAMessage(
  2224.          acStringBuffer[
  2225.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2226.          IDS_CHIME_FILE_ERROR,                  /* ID of the message to show. */
  2227.          MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2228.             MB_MOVEABLE );                      /* Style of the message box.  */
  2229.       return (0);
  2230.    }
  2231.  
  2232.    /*
  2233.     * If the global flag is not stop then assign the GO value.  This will allow
  2234.     * a chime file to be played.
  2235.     */
  2236.    if ( yngAreChimeFilesLoaded != STOP )
  2237.    {
  2238.       yngAreChimeFilesLoaded = GO;
  2239.    }
  2240.  
  2241.    /*
  2242.     * Close the file.
  2243.     */
  2244.    lMMIOResults =
  2245.       mmioClose(
  2246.          hmmioFileHandle,             /* Handle of the file to close.         */
  2247.          0 );                         /* No flags are used.                   */
  2248.  
  2249.  
  2250.    /* Return the size of the audio data in bytes.
  2251.     */
  2252.  
  2253.    return( mmAudHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes );
  2254.  
  2255. }  /* End of HowBigIsTheChimeFile */
  2256.  
  2257.  
  2258. /******************************************************************************
  2259.  * Name        : CopyWaveformIntoMemory
  2260.  *
  2261.  * Description : This procedure loads the chime waveform files from DASD into
  2262.  *               the memory buffer that was created by the routine that called
  2263.  *               CopyWaveformIntoMemory.  It also querys information in the
  2264.  *               header of the waveform file for use in a later routine,
  2265.  *               SetupChimeFileInformation.
  2266.  *
  2267.  * Concepts    : How to open and read files with the MMIO APIs.
  2268.  *
  2269.  * MMPM/2 API's: mmioOpen
  2270.  *               mmioRead
  2271.  *               mmioClose
  2272.  *               mmioGetHeader
  2273.  *
  2274.  * Parameters  : pulBaseAddress - The address of the buffer that will hold
  2275.  *                                one of the chime waveform files.
  2276.  *               ulSizeOfBuffer - The size the file buffer.
  2277.  *               usChimeFile    - The identifier for the chime file.
  2278.  *
  2279.  * Return      : None.
  2280.  *
  2281.  ******************************************************************************/
  2282. VOID CopyWaveformIntoMemory( LONG   *pulBaseAddress,
  2283.                              ULONG  ulSizeOfBuffer,
  2284.                              USHORT usChimeFile )
  2285. {
  2286.  
  2287.    HMMIO hmmioFileHandle;              /* Handle to the audio file handle.    */
  2288.    CHAR  acFileName[ FILE_NAME_SIZE ]; /* Name of the file.                   */
  2289.    LONG  lMMIOResults;                 /* Results from the MMIO calls.        */
  2290.    ULONG ulRC;                         /* Return code from mmioGetHeader.     */
  2291.    ULONG ulBytesRead;                  /* Returned from mmioGetHeader.        */
  2292.  
  2293.    switch( usChimeFile )
  2294.    {
  2295.       case 0 :
  2296.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_A - 1] );
  2297.          break;
  2298.  
  2299.       case 1 :
  2300.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_B - 1 ] );
  2301.          break;
  2302.  
  2303.       case 2 :
  2304.          strcpy( acFileName, acStringBuffer[ IDS_CHIME_FILE_C - 1 ] );
  2305.          break;
  2306.  
  2307.       default:
  2308.          ShowAMessage(
  2309.             acStringBuffer[
  2310.                IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2311.             IDS_CHIME_FILE_ERROR,               /* ID of the message to show. */
  2312.             MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2313.                MB_MOVEABLE );                   /* Style of the message box.  */
  2314.          return;
  2315.  
  2316.    }  /* End of switch statment. */
  2317.  
  2318.    /*
  2319.     * Open the chime file.
  2320.     */
  2321.    hmmioFileHandle =
  2322.       mmioOpen(
  2323.          acFileName,
  2324.          (PMMIOINFO) NULL,
  2325.          MMIO_READ );
  2326.  
  2327.    if ( hmmioFileHandle == (HMMIO) NULL )
  2328.    {
  2329.       ShowAMessage(
  2330.          acStringBuffer[
  2331.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2332.          IDS_CHIME_FILE_ERROR,                  /* ID of the message to show. */
  2333.          MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2334.             MB_MOVEABLE );                      /* Style of the message box.  */
  2335.       return;
  2336.    }
  2337.  
  2338.    /*
  2339.     * Get the header information from the waveform file.  This information
  2340.     * will be used later in the routine SetupChimeFileInformation in order
  2341.     * to setup the device to play the playlist.  We only need to do this
  2342.     * for the first file, since all of the chime files were recorded in the
  2343.     * same way. The fInitHeader boolean indicates if we've already performed
  2344.     * this query or not.
  2345.     */
  2346.  
  2347.    if (fInitHeader) {
  2348.       ulRC = mmioGetHeader ( hmmioFileHandle,
  2349.                              (PVOID)&mmAudioHeader,
  2350.                              sizeof (MMAUDIOHEADER),
  2351.                              (PLONG) &ulBytesRead,
  2352.                              (ULONG) NULL,
  2353.                              (ULONG) NULL);
  2354.       fInitHeader = FALSE;
  2355.    }
  2356.  
  2357.  
  2358.    /*
  2359.     * Move the data from the chime file into the buffer.
  2360.     */
  2361.    lMMIOResults =
  2362.       mmioRead(
  2363.          hmmioFileHandle,
  2364.          (PSZ)pulBaseAddress,
  2365.          ulSizeOfBuffer );
  2366.  
  2367.    if ( lMMIOResults == MMIO_ERROR )
  2368.    {
  2369.       ShowAMessage(
  2370.          acStringBuffer[
  2371.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2372.          IDS_CHIME_FILE_ERROR,                  /* ID of the message to show. */
  2373.          MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2374.             MB_MOVEABLE );                      /* Style of the message box.  */
  2375.    }
  2376.  
  2377.    /*
  2378.     * Close the file.
  2379.     */
  2380.    lMMIOResults =
  2381.       mmioClose(
  2382.          hmmioFileHandle,             /* Handle of the file to close.         */
  2383.          0 );                         /* No flags are used.                   */
  2384.  
  2385.    if ( lMMIOResults != MMIO_SUCCESS )
  2386.    {
  2387.       ShowAMessage(
  2388.          acStringBuffer[
  2389.             IDS_NORMAL_ERROR_MESSAGE_BOX_TEXT - 1 ],
  2390.          IDS_FAILED_MMIO_CLOSE,                 /* ID of the message to show. */
  2391.          MB_OK | MB_INFORMATION | MB_HELP | MB_APPLMODAL |
  2392.             MB_MOVEABLE );                      /* Style of the message box.  */
  2393.    }
  2394.  
  2395. }  /* End of CopyWaveformIntoMemory */
  2396.  
  2397.  
  2398. /******************************************************************************
  2399.  * Name        : LoadBellBitmaps
  2400.  *
  2401.  * Description : This procedure will load the bitmaps that are required to
  2402.  *               animate the bell.  The handle for each bitmap is stored in
  2403.  *               a global array for later use.
  2404.  *
  2405.  * Concepts    : None.
  2406.  *
  2407.  * MMPM/2 API's: None.
  2408.  *
  2409.  * Parameters  : None.
  2410.  *
  2411.  * Return      : None.
  2412.  *
  2413.  ******************************************************************************/
  2414. VOID LoadBellBitmaps( VOID )
  2415. {
  2416.    USHORT usBitmapIdCounter,     /* Bitmap id counter.                        */
  2417.           usCount;               /* Generic counter.                          */
  2418.  
  2419.    usBitmapIdCounter            = ID_CENTER_BELL;
  2420.  
  2421.    for( usCount=0; usCount<NUMBER_OF_BELL_BITMAPS; usCount++)
  2422.    {
  2423.       /*
  2424.        * Believe It or Not if the following sleep is not performed some of
  2425.        * the bitmaps will not be loaded and therefore the 'ringing' swing
  2426.        * of the bell will not work correctly.  Without the sleep some of
  2427.        * the bitmaps will not be loaded, i.e., every other one.
  2428.        */
  2429.       DosSleep( 300 );
  2430.  
  2431.       ahbmBellBitMaps[ usCount ] =
  2432.          GpiLoadBitmap(
  2433.             hpsMemory,
  2434.             (HMODULE) NULL,
  2435.             usBitmapIdCounter,
  2436.             (LONG) BELL_BITMAP_X_SIZE,
  2437.             (LONG) BELL_BITMAP_Y_SIZE );
  2438.  
  2439.       usBitmapIdCounter++;
  2440.  
  2441.    }  /* End of For loop to load the bitmaps. */
  2442.  
  2443. }  /* End of LoadBellBitmaps */
  2444.  
  2445.  
  2446. /******************************************************************************
  2447.  * Name        : SwingTheBell
  2448.  *
  2449.  * Description : This procedure will handle all of the processing that is
  2450.  *               required animate the bell bitmaps.  The bitmaps will be
  2451.  *               moved if the Closed Caption Flag is set to show a non-audio
  2452.  *               method of indicating sound.  The bells will be moved until
  2453.  *               the MCI Notify message is received by the message loop at
  2454.  *               which point a semaphore, hevContinueToSwingTheBell will
  2455.  *               be set so that the animation will stop.
  2456.  *
  2457.  *               This routine will be set up in a seperate thread to allow
  2458.  *               the main window procedure to continue processing message.
  2459.  *
  2460.  * Concepts    : None.
  2461.  *
  2462.  * MMPM/2 API's: None.
  2463.  *
  2464.  * Parameters  : None.
  2465.  *
  2466.  * Return      : None.
  2467.  *
  2468.  ******************************************************************************/
  2469. VOID  SwingTheBell( PVOID pvData)
  2470. {
  2471.    USHORT usCount;            /* Generic counter.                             */
  2472.    BOOL   fStopSwinging;                 /* Flag to stop the bell swinging.    */
  2473.  
  2474.    while( DosWaitEventSem(
  2475.              hevContinueToSwingTheBell,
  2476.              SEM_INDEFINITE_WAIT ) ==  NO_ERROR )
  2477.    {
  2478.       for( usCount=0; usCount<NUMBER_OF_BELLS_IN_A_SWING; usCount++ )
  2479.       {
  2480.          /*
  2481.           * The important element in the next function call is how the
  2482.           * correct bitmap handle is picked.  This is done by using the
  2483.           * usCount value to index into the ausBellSwingOrder array. This
  2484.           * array has the order that the bitmaps are to be shown.  The
  2485.           * ausBellSwingOrder returns a value that indexes into the array
  2486.           * that contains the handle to the bitmaps.  This will indicate
  2487.           * which bitmap is to be drawn.
  2488.           */
  2489.          if (yngContinueToSwingTheBell == GO)
  2490.          {
  2491.             GpiSetBitmap(
  2492.                hpsMemory,
  2493.                ahbmBellBitMaps[ ausBellSwingOrder[ usCount ] ] );
  2494.             fStopSwinging = FALSE;          /* swinging, set the flag.        */
  2495.          }
  2496.          else if ( fStopSwinging == FALSE )
  2497.          {
  2498.             GpiSetBitmap( hpsMemory, ahbmBellBitMaps[ IX_CENTER_BELL ] );
  2499.             fStopSwinging = TRUE;           /* No more swinging, set the flag.*/
  2500.          }
  2501.          DosSleep( 230 );
  2502.          GpiBitBlt(
  2503.             hpsScreen,                        /* target presentation space.   */
  2504.             hpsMemory,                        /* source presentation space.   */
  2505.             4L,                               /* # of points.                 */
  2506.             aptl,                             /* array of points.             */
  2507.             ROP_SRCCOPY,                      /* copy source over destination.*/
  2508.             BBO_IGNORE );                     /* ignore eiminated data.       */
  2509.  
  2510.       }  /* End of for loop. */
  2511.    }  /* End of while loop */
  2512.   DosExit(
  2513.      0,        /* Exit only from this thread leave other threads alone.       */
  2514.      0 );      /* Return value from the thread.                               */
  2515.  
  2516. } /* End of SwingTheBell */
  2517.