home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- * File Name : DOUPLAY.C
- *
- * Description : This file contains the C source code required for the Double
- * Buffering Playlist sample program. This sample allows
- * the user to play a wave file continuously by pushing the
- * play button. The user can stop playing the wave file by
- * pushing the stop button. Both of these push buttons are
- * animated.
- *
- * Concepts : This program illustrates how to use a Memory
- * Playlist in a double buffering manner for reading and playing
- * a wave file at the same time.
- * This concept can be used in a lot of real time recording
- * applications such as:
- * 1. Real Time recording and playing of the wave file
- * 2. Censoring a Speech being transmitted.
- * The sample also shows how to use MMIO API's used in opening,
- * reading, seeking, and closing files.
- *
- * MMPM/2 API's: List of all MMPM/2 API's that are used in this module.
- *
- * mciSendCommand
- * MCI_ACQUIREDEVICE
- * MCI_OPEN
- * MCI_PLAY
- * MCI_SET
- * mciGetErrorString
- * mmioOpen
- * mmioGetHeader
- * mmioRead
- * mmioSeek
- * mmioClose
- *
- * Required
- * Files : doubplay.c Source Code.
- * doubapp.c Source Code.
- * doubplay.h Include file.
- * doubapp.h Include file.
- * doubplay.dlg Dialog definition.
- * doubplay.rc Resources.
- * doubplay.ipf Help text.
- * makefile Make file.
- * doubplay.def Linker definition file.
- * doubplay.ico Doubplay icon.
- * mywave.wav Wave File Played.
- * play0.bmp Play PushButton Bitmap 0
- * play1.bmp Play PushButton Bitmap 1
- * play2.bmp Play PushButton Bitmap 2
- * play3.bmp Play PushButton Bitmap 3
- * play4.bmp Play PushButton Bitmap 4
- * stop.bmp Stop PushButton Bitmap
- *
- * Copyright (C) IBM 1993
- ******************************************************************************/
-
- #define INCL_DOS /* required to use Dos APIs. */
- #define INCL_WIN /* required to use Win APIs. */
- #define INCL_PM /* required to use PM APIs. */
- #define INCL_OS2MM /* required for MCI and MMIO headers */
- #define INCL_WINHELP /* required to use IPF. */
- #define INCL_WINSTDSLIDER /* required for using slider control */
- #define INCL_SECONDARYWINDOW /* required for secondary window */
- #define INCL_GRAPHICBUTTON /* required for graphic button control */
-
- #include <os2.h>
- #include <stdio.h>
- #include <os2me.h>
- #include <stdlib.h>
-
- #include <sw.h>
-
- #include "doubplay.h" /* Dialog Ids, Resource Ids etc */
- #include "doubapp.h" /* application defined values */
-
-
- #define HELP_FILE "DOUBPLAY.HLP"
- /*******************************************************************/
-
- /* Procedure / Function prototypes */
-
- #pragma linkage( MainDialogProc, system)
- MRESULT EXPENTRY MainDialogProc(HWND, ULONG, MPARAM, MPARAM);
- void main(int i,char *p[]);
- void InitializeDialog(void);
- void Finalize(void);
- void InitializePlayList();
- void OpenAudioDevice(HWND hwnd);
- VOID InitializeHelp( VOID );
- void CloseAll();
-
- /*******************************************************************/
-
- /* Global Variables */
-
- HAB hab; /* anchor block handle */
- QMSG qmsg; /* Message Que */
- HMQ hmq;
- HWND hwndDiag; /* Application Dialog handle */
- HWND hwndFrame; /* Application Frame handle */
- BOOL fPassedDevice = FALSE; /* Do we own the Audio device */
- TID PlayThreadId; /* Id for the PlayWave Thread */
- USHORT usWaveDeviceId; /* Id for the Wave Device */
- CHAR achDataBuffer[MAXBUFF][MAXSIZE]; /* Data Buffer which will hold */
- /* wave for Memory Playlist */
- CHAR achHelpTitle[STRING_SIZE]; /* Title for the Help */
- HMMIO hmmioFileHandle; /* Handle to the Wave File */
- LONG lState = STATE_IS_STOP; /* state of the application */
- /* Can be STOP or PLAYING */
- HWND hwndHelpInstance; /* Handle to Help window */
- HELPINIT hmiHelpStructure; /* Help init. structure */
- /*
- * The Play List structure is an array of 2*MAXBUFF+2 number of items.
- * This is because during initialization every even number i.e. 0, 2, 4
- * etc is going to have the DATA instruction while every odd number i.e. 1,3,5
- * is going to have the MESSAGE instruction. The 2*MAXBUFF is going to contain
- * the BRANCH instruction which will be dynamically modified to loop back to
- * the first data instruction when the Play pushbutton is used.
- * When Stop push button is pressed this will be dynamically modifed to
- * go to the EXIT instruction.
- * The 2*MAXBUFF+1 is going to be contain the EXIT instruction. When the
- * BRANCH instruction is modified to loop to the EXIT instruction, the playing
- * of the wave file will stop.
- */
- PLAY_LIST_STRUCTURE_T aplayList[2*MAXBUFF+2]; /* Play List memory Structure */
-
- /******************************************************************************
- * Name : main
- *
- * Description : This function calls the Intialize procedure to prepare
- * everything for the program's operation, enters the
- * message loop, then call Finalize to shut everything down
- * when the program is terminated.
- *
- * Concepts : None.
- *
- * MMPM/2 API's : None.
- *
- * Parameters : argc - Number of parameters passed into the program.
- * argv - Command line parameters.
- *
- * Return : None.
- *
- *************************************************************************/
- void main(int argc, char *argv[])
- {
- InitializeDialog();
-
- /* Handle the messages: */
- while(WinGetMsg(hab,&qmsg,0,0,0))
- WinDispatchMsg(hab,&qmsg);
-
- Finalize();
-
- }
-
- /*************************************************************************
- * Name : InitializeDialog
- *
- * Description : This function performs the necessary initializations and
- * setups that are required to show/run a dialog box as a
- * main window. The message queue will be created, as will
- * the dialog box.
- *
- * Concepts : Secondary Windows is used to create and show a dialog box.
- * A system clock is displayed till the application is loaded.
- *
- * MMPM/2 API's : WinLoadSecondaryWindow
- * WinQuerySecondaryHWND
- *
- * Parameters : None.
- *
- * Return : None.
- *
- *************************************************************************/
- void InitializeDialog()
- {
- CHAR achTitle[STRING_SIZE] = "";
- CHAR achDefaultSize[STRING_SIZE] = "";
-
-
- /*
- * Setup and initialize the dialog window.
- * Change pointer to a waiting pointer first, since this might take a
- * couple of seconds.
- */
-
-
- WinSetPointer(
- HWND_DESKTOP, /* Desktop window handle. */
- WinQuerySysPointer( /* This API will give the handle of the PTR. */
- HWND_DESKTOP, /* Desktop window handle. */
- SPTR_WAIT, /* The waiting icon. */
- FALSE ) ); /* Return the system pointer's handle. */
-
- /* Initialize the Dialog window */
- hab = WinInitialize(0);
-
- /* create a message queue for the window */
- hmq = WinCreateMsgQueue(hab,0);
-
-
-
- /* Load the Dialog - This will return the Handle to the Frame */
- hwndFrame =
- WinLoadSecondaryWindow(HWND_DESKTOP
- ,HWND_DESKTOP
- ,(PFNWP)MainDialogProc
- ,(HMODULE)NULL
- ,ID_SAMPLE
- ,(PVOID)NULL);
-
-
- /*
- * By specifying the QS_DIALOG flag we will get the handle to the Dialog of
- * the frame
- */
- hwndDiag = WinQuerySecondaryHWND(hwndFrame,QS_DIALOG);
-
- /* Get the string for default size */
- WinLoadString(
- hab,
- (HMODULE) NULL,
- IDS_DEFAULT_SIZE,
- (SHORT) sizeof( achDefaultSize),
- achDefaultSize);
- /* Add Default Size menu item to system menu of the secondary window. */
- WinInsertDefaultSize(hwndFrame, achDefaultSize);
-
- /*
- * Get the window title string from the Resource string table
- * and set it as the window text for the dialog window.
- */
- WinLoadString(
- hab,
- (HMODULE) NULL,
- IDS_MAIN_WINDOW_TITLE,
- (SHORT) sizeof( achTitle),
- achTitle);
-
- /* Set the Title of the Dialog */
- WinSetWindowText( hwndFrame, achTitle);
-
-
- /*
- * Now that we're done with initialization, so we don't the need the waiting
- * icon, so we are going to change the pointer back to the arrow.
- */
-
- WinSetPointer(
- HWND_DESKTOP, /* Desktop window handle. */
- WinQuerySysPointer( /* This API will give the handle of the PTR. */
- HWND_DESKTOP, /* Desktop window handle. */
- SPTR_ARROW, /* The Arrow icon. */
- FALSE ) ); /* Return the system pointer's handle. */
-
- /*
- * Initialize the help structure and associate the help instance to this
- * dialog via it's handle to anchor block.
- */
-
- InitializeHelp( );
-
- }
-
- /******************************************************************************
- * Name : CloseAll
- *
- * Description : This function is called when the current Thread finishes
- * execution and is placed in DosExitList during the WM_INITDLG
- * message. This function allows to terminate itself and all
- * of its children processes.
- *
- * Concepts : None.
- *
- * MMPM/2 API's : None.
- *
- * Parameters : None
- *
- * Return : None.
- *
- *************************************************************************/
- void CloseAll()
- {
- DosExit(EXIT_PROCESS, 0);
- DosExitList(EXLST_EXIT, NULL);
- }
- /******************************************************************************
- * Name : InitializeHelp
- *
- * Description : This procedure will set up the initial values in the global
- * help structure. This help structure will then be passed on
- * to the Help Manager when the Help Instance is created. The
- * handle to the Help Instance will be kept for later use.
- *
- * Concepts : None.
- *
- * MMPM/2 API's: None.
- *
- * Parameters : None.
- *
- * Return : None.
- *
- ******************************************************************************/
- VOID InitializeHelp( VOID )
- {
- /* Get the size of the initialization structure. */
- hmiHelpStructure.cb = sizeof( HELPINIT );
-
- hmiHelpStructure.ulReturnCode = (ULONG) NULL; /* RC from initialization.*/
- hmiHelpStructure.pszTutorialName = (CHAR) NULL; /* No tutorial program. */
-
- hmiHelpStructure.phtHelpTable = (PVOID)(0xffff0000 | ID_DOUBPLAY_HELPTABLE);
-
- /* The action bar is not used, so set the following to NULL. */
- hmiHelpStructure.hmodAccelActionBarModule = (HMODULE) NULL;
- hmiHelpStructure.idAccelTable = (USHORT) NULL;
- hmiHelpStructure.idActionBar = (USHORT) NULL;
-
- /* The Help window title. */
- WinLoadString(
- hab, /* HAB for this dialog box. */
- (HMODULE) NULL, /* Get the string from the .exe file. */
- IDS_HELP_WINDOW_TITLE, /* Which string to get. */
- (SHORT) STRING_SIZE, /* The size of the buffer. */
- achHelpTitle ); /* The buffer to place the string. */
-
- hmiHelpStructure.pszHelpWindowTitle =
- achHelpTitle;
-
- /* The Help table is in the executable file. */
- hmiHelpStructure.hmodHelpTableModule = (HMODULE) NULL;
-
- /* The help panel ID is not displayed. */
- hmiHelpStructure.fShowPanelId = (ULONG) NULL;
-
- /* The library that contains the Double Buffering help panels. */
- hmiHelpStructure.pszHelpLibraryName = HELP_FILE;
-
- /*
- * Create the Help Instance for IPF.
- * Give IPF the Anchor Block handle and address of the IPF initialization
- * structure, and check that creation of Help was a success.
- */
- hwndHelpInstance = WinCreateHelpInstance(
- hab, /* Anchor Block Handle. */
- &hmiHelpStructure ); /* Help Structure. */
-
- if ( hwndHelpInstance == (HWND) NULL )
- {
- ShowAMessage(
- IDS_ERROR_TITLE,
- IDS_HELP_CREATION_ERROR,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_APPLMODAL ,
- FALSE);
- }
- else
- {
- if ( hmiHelpStructure.ulReturnCode )
- {
- ShowAMessage(
- IDS_ERROR_TITLE,
- IDS_HELP_CREATION_ERROR,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_APPLMODAL ,
- FALSE);
-
- WinDestroyHelpInstance( hwndHelpInstance );
- }
- } /* End of IF checking the creation of the Help Instance. */
-
- /* Associate the Help Instance of the IPF to this dialog window. */
- if ( hwndHelpInstance != (HWND) NULL )
- {
- WinAssociateHelpInstance(
- hwndHelpInstance, /* The handle of the Help Instance. */
- hwndFrame ); /* Associate to this dialog window. */
- }
-
- } /* End of InitializeHelp */
-
- /*************************************************************************
- * Name : Finalize
- *
- * Description : This routine is called after the message dispatch loop
- * has ended because of a WM_QUIT message. The code will
- * destroy the help instance, messages queue, and window.
- *
- * Concepts : None.
- *
- * MMPM/2 API's : None.
- *
- * Parameters : None.
- *
- * Return : None.
- *
- *************************************************************************/
- VOID Finalize( VOID )
- {
- /* Destroy the Help Instance for this dialog window. */
- if ( hwndHelpInstance != (HWND) NULL)
- {
- WinDestroyHelpInstance( hwndHelpInstance );
- }
-
- WinDestroySecondaryWindow( hwndFrame );
- WinDestroyMsgQueue( hmq );
- WinTerminate( hab );
-
- } /* End of Finalize */
- /*******************************************************************************
- * Name : MainDialogProc
- *
- * Description : This function controls the main dialog box. It will handle
- * received messages such as pushbutton notifications, playlist
- * messages, etc
- *
- * The following messages are handled specifically by this
- * routine.
- *
- * WM_INITDLG
- * WM_CLOSE
- * WM_HELP
- * WM_COMMAND
- * MM_MCIPLAYLISTMESSAGE
- * MM_MCIPASSDEVICE
- * WM_ACTIVATE
- *
- *
- * Concepts : The MM_MCIPLAYLISTMESSAGE message is used to indicate when
- * a data buffer of the playlist is finished processing. At this
- * time the wave file is read into the buffer number passed in.
- * Wave is being constantly read into the data buffer of the play
- * list (when the playlist message is received) while the wave is
- * constantly being played by the other thread thus illustrating
- * the double buffering concept of the playlist. This concept
- * can be used in a lot of real time recording applications as:
- * 1. Real Time recording and playing of the wave file
- * 2. Censoring a Speech being transmitted.
- * A separate thread is created to play the wave file. This
- * thread sends messages to the MainDialogProc after it has
- * finished playing every DATA instruction for reading more of
- * the wave file into the buffer.
- * Also, the dynamic modification of a memory playlist's branch
- * instruction is illustrated when the STOP and PLAY pushbuttons
- * are pressed.
- *
- *
- *
- *
- * MMPM/2 API's : mciSendCommand
- * MCI_ACQUIREDEVICE
- * mmioClose
- * mmioRead
- * mmioSeek
- *
- * Parameters : hwnd - Handle for the Main dialog box.
- * msg - Message received by the dialog box.
- * mp1 - Parameter 1 for the just recieved message.
- * mp2 - Parameter 2 for the just recieved message.
- *
- * Return :
- *
- *
- ******************************************************************************/
- MRESULT EXPENTRY MainDialogProc(
- HWND hwnd,
- ULONG msg,
- MPARAM mp1,
- MPARAM mp2)
- {
- static MCI_GENERIC_PARMS lpWaveGeneric; /* Used for MCI_ACQUIREDEVICE */
- ULONG ulReturn; /* Ret Code for Dos and MCI calls */
- ULONG ulBufferNum; /* index to read the wave into */
- ULONG ulBytesRead; /* Number of bytes read from wave */
- USHORT usNotifyCode;
- USHORT usUserParm;
- USHORT usCommandMessage; /* high-word */
-
-
-
- switch (msg)
- {
-
- /*
- * This message is recieved when the DataBuffer index number ulBufferNum
- * is just finished playing. Now, the next MAXSIZE of the wave file is
- * going to be recorded into this buffer number. This new part of the wave
- * file which is read will be played during the next BRANCH iteration.
- * MM_MCIPLAYLISTMESSAGE indicates that the bufferno ulBufferNum is finished
- * playing, so read the next part of the wave file into the buffer.
- */
-
- case MM_MCIPLAYLISTMESSAGE:
- /*
- * The Buffer Number has just finished playing, so refill the buffer
- * for next loop. Remeber only the buffer which has finished playing
- * should be filled compared to the next buffer or so on because some
- * data may be lost otherwise.
- */
-
- /* Extract the Buffer Number which was just played */
- ulBufferNum = (ULONG) mp2;
-
- /* Read the Next MAXSIZE bytes of the wave file */
- ulBytesRead =
- mmioRead(hmmioFileHandle,
- (HPSTR) achDataBuffer[ulBufferNum],
- MAXSIZE);
-
- /*
- * If we have reached the end of the wave file then set the file marker
- * to the begining of the file and start reading into the bufferno.
- * This causes the continuous filling and playing of the data buffer
- * again and again as long as the END push button is not pressed.
- * The wave file is going to keep on playing without any interruptions
- * as long as the BRANCH instruction is not modified.
- */
- if (ulBytesRead == 0)
- {
- /* Seek to the starting of the wave file */
- mmioSeek(hmmioFileHandle, 0, SEEK_SET);
-
- /* Read the Next MAXSIZE bytes of the wave file */
- ulBytesRead =
- mmioRead(hmmioFileHandle,
- (HPSTR) achDataBuffer[ulBufferNum],
- MAXSIZE);
- }
- return ((MRESULT) NULL);
-
-
- case WM_CLOSE:
- WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
- return ((MRESULT) NULL);
-
- case WM_HELP :
- /*
- * The dialog window has recieved a request for help from the user,
- * i.e., the Help pushbutton was pressed. Send the HM_DISPLAY_HELP
- * message to the Help Instance with the IPF resource identifier
- * for the correct HM panel. This will show the help panel for this
- * sample program.
- */
- WinSendMsg(
- hwndHelpInstance,
- HM_DISPLAY_HELP,
- MPFROMSHORT( 1 ),
- MPFROMSHORT( HM_RESOURCEID ) );
- return( 0 );
-
- case WM_INITDLG:
- /*
- * Put the Playlist Instructions into the Playlist structure.
- * Every even subscipt (0,2,4 etc) gets the DATA_OPERATION instruction
- * and every odd subscript (1,3,5 etc) gets the MESSAGE_OPERATION
- * instruction. After every DATA_OPERATION instruction is executed
- * a message is given to the application and the wave file is read again
- * into the data buffer
- */
- InitializePlayList();
-
- /* Opens the Audio device for playlist */
- OpenAudioDevice(hwnd);
- /*
- * Since the play button is an animated button, we need to initialize it
- */
- WinSendMsg (
- WinWindowFromID(
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_SETANIMATIONRATE, /* Animation rate control */
- MPFROMLONG(100L), /* Update play bitmap every .1 sec */
- NULL); /* Ignore return data */
-
- /*
- * Place function CloseAll in exit list because in order to play
- * we have to create another thread and when we terminate we want
- * to stop all child processes.
- */
-
- DosExitList(EXLST_ADD,(PFNEXITLIST) CloseAll);
-
- return((MRESULT)NULL);
-
- /* Service all of the button pushes */
- case WM_COMMAND:
- switch (SHORT1FROMMP(mp1)) {
- case ID_END:
- /* If we are playing the playlist only then stop it */
- if (lState == STATE_IS_PLAYING)
- {
- /*
- * When the stop button is pushed, then we are going to modify
- * BRANCH_INSTRUCTION and make it branch to the EXIT_INSTRUCTION
- * When the BRANCH instruction is going to be encountered instead
- * of looping back to the DATA instruction, we are going to go to
- * EXIT instruction which will cause the wave to stop playing.
- * Till the BRANCH instruction is encountered the buffer will keep
- * on filling and the wave will keep on playing.
- * This is the reason why there may be a delay between pushing the
- * STOP button and time it takes for the wave to stop playing.
- * So here we dynamically modify operand of BRANCH instruction
- * (2*MAXBUFF index) to go to EXIT instruction (2*MAXBUFF+1)
- * instead of looping back to the first DATA instruction.
- * For a more detailed description on playlist instructions
- * refer to the MMPM/2 programming guide.
- */
-
- aplayList[2*MAXBUFF].ulOperandTwo = 2*MAXBUFF+1;
-
- /* Wait for the PlayThreadId to end */
- DosWaitThread(&PlayThreadId, DCWW_WAIT);
-
- }
- break;
-
-
- case ID_PLAY:
- /* If we are not playing the playlist only then Play it */
- if (lState == STATE_IS_STOP)
- {
- if (fPassedDevice)
- {
- /*
- * If we don't have the device then display a message.
- * FALSE is passed because this is not a MCI error.
- */
-
- ShowAMessage(
- IDS_ERROR_TITLE,
- IDS_CANT_PROCESS_MESSAGE,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL ,
- FALSE);
- }
- else
- {
- /*
- * We have the device so no problem.
- * Modify the operand of the LOOP instruction to loop back
- * to the first DATA instruction so the wave file can be
- * played continuously without any interruptions. When we
- * want the wave to stop playing then we will modify this
- * instruction again
- */
- aplayList[2*MAXBUFF].ulOperandTwo = 0;
-
- /*
- * Create a thread called PlayTheWave which will start
- * playing the wave file and send messages to this Dialog
- * procedure
- */
-
- PlayThreadId =
- _beginthread(
- PlayTheWave,
- NULL,
- 16384,
- NULL);
-
-
-
- }
- }
- break;
-
- }
- return((MRESULT)NULL);
- break;
-
- /*
- * The next two messages are handled so that the Double Buffering
- * application can participate in device sharing. Since it opens
- * the devices as shareable devices, other applications can gain
- * control of the devices. When this happens, we will receive a
- * pass device message. We keep track of this device passing in
- * the fPassedDevice boolean variable.
- *
- * fPassedDevice will be TRUE if we don't have the device and will
- * be FALSE
- *
- * If we do not have access to the device when we receive an activate
- * message, then we will issue an acquire device command to gain
- * access to the device.
- */
-
- case MM_MCIPASSDEVICE:
- if (SHORT1FROMMP(mp2) == MCI_GAINING_USE)
- {
- /* Have gained use of the Audio Device so update the flag */
- fPassedDevice = FALSE;
-
- if (lState == STATE_IS_PLAYING) { /* If the duet was playing */
- WinSendMsg( /* Start Play button animation */
- WinWindowFromID (
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_ANIMATE, /* Animation control */
- MPFROMSHORT(TRUE), /* Animation flag */
- NULL); /* Ignore return data */
- }
- }
- else
- {
- /* Have lost use of the Audio Device so update the flag */
- fPassedDevice = TRUE;
-
- if (lState == STATE_IS_PLAYING) { /* If the duet was playing */
- WinSendMsg( /* Stop Play button animation */
- WinWindowFromID (
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_ANIMATE, /* Animation control */
- MPFROMSHORT(FALSE), /* Animation flag */
- NULL); /* Ignore return data */
- }
- }
- break;
-
-
- case MM_MCINOTIFY:
- usNotifyCode = (USHORT) SHORT1FROMMP( mp1);
- usUserParm = (USHORT) SHORT2FROMMP( mp1);
-
- usCommandMessage = (USHORT) SHORT2FROMMP( mp2); /* high-word */
-
- switch (usCommandMessage)
- {
- case MCI_PLAY:
- switch (usNotifyCode)
- {
- case MCI_NOTIFY_SUCCESSFUL:
- if (lState != STATE_IS_STOP)
- {
- /*
- * We will receive the MCI_NOTIFY_SUCCESSFUL message
- * so we need to be sure to only take this action if
- * the state is not stopped. That's why we are
- * checking the lState and then immediately setting it
- * to STATE_IS_STOP.
- */
- lState = STATE_IS_STOP;
- /* Disables the animation of the Play button */
- WinSendMsg (
- WinWindowFromID(
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_ANIMATE, /* Animation control */
- MPFROMSHORT(FALSE),/* Animation flag */
- NULL); /* Ignore return data */
-
- /* Close the Wave file */
- ulReturn =
- mmioClose(hmmioFileHandle, (USHORT) NULL);
- if (ulReturn != 0)
- {
- /*
- * This is an MCI Error so show the message by
- * passing TRUE
- */
- ShowAMessage(
- IDS_ERROR_TITLE,
- ulReturn,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL,
- TRUE);
- }
-
- }
- break;
-
- case MCI_NOTIFY_SUPERSEDED:
- case MCI_NOTIFY_ABORTED:
- /* we don't need to handle these messages. */
- break;
-
- default:
- /*
- * If the message is none of the above, then it must be
- * a notification error message.
- */
- ShowAMessage(
- IDS_ERROR_TITLE,
- usNotifyCode,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL,
- TRUE);
-
- lState = STATE_IS_STOP;
- /* Disables the animation of the Play button */
- WinSendMsg (
- WinWindowFromID(
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_ANIMATE, /* Animation control */
- MPFROMSHORT(FALSE),/* Animation flag */
- NULL); /* Ignore return data */
-
- break;
-
- }
- break;
- }
- return( (MRESULT) 0);
-
- /*
- * We use the WM_ACTIVATE message to participate in device sharing.
- * We first check to see if this is an activate or a deactivate
- * message (indicated by mp1). Then, we check to see if we've passed
- * control of the device that we use. If these conditions are true,
- * then we issue an acquire device command to regain control of the
- * device, since we're now the active window on the screen.
- *
- * This is one possible method that can be used to implement
- * device sharing. For applications that are more complex
- * than this sample program, developers may wish to take
- * advantage of a more robust method of device sharing.
- * This can be done by using the MCI_ACQUIRE_QUEUE flag on
- * the MCI_ACQUIREDEVICE command. Please refer to the MMPM/2
- * documentation for more information on this flag.
- */
- case WM_ACTIVATE:
- /* First we check to see if we've passed control of the device */
- if ((BOOL)mp1 && fPassedDevice == TRUE)
- {
- lpWaveGeneric.hwndCallback = hwnd;
- ulReturn = mciSendCommand( usWaveDeviceId,
- MCI_ACQUIREDEVICE,
- (ULONG)MCI_WAIT,
- (PVOID)&lpWaveGeneric,
- (USHORT)NULL );
- if (ulReturn != 0)
- {
- /* This is an MCI Error so show the message by passing TRUE */
- ShowAMessage(
- IDS_ERROR_TITLE,
- ulReturn,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL,
- TRUE);
- }
-
- }
- return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
-
- /*
- * This is an application defined message. This message is received
- * from the PlayTheWave thread when the mmioOpen, MCI_SET or MCI_PLAY is
- * not successfull
- */
- case WM_PLAYFAILED:
-
- ShowAMessage(
- IDS_ERROR_TITLE,
- LONGFROMMP(mp1),
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL,
- (BOOL) LONGFROMMP(mp2));
- break;
- /*
- * If MCI_PLAY is successful then PlayTheWave thread sends us a message
- * indicating that the playing of the wave file has started, so that we
- * can start the animation of the play button and update the state of the
- * application
- */
- case WM_PLAYSTARTED:
- /*
- * The MCI_PLAY was successful and the thread send us a message
- * that the Playing of the wave file has started, so enable the
- * animation of the button
- */
- WinSendMsg (
- WinWindowFromID(
- hwnd, /* Dialog window handle */
- ID_PLAY), /* Id - Play graphic button */
- GBM_ANIMATE, /* Animation control */
- MPFROMSHORT(TRUE), /* Animation flag */
- NULL); /* Ignore return data */
-
- /* Update the State of the application */
- lState = STATE_IS_PLAYING;
-
- break;
-
- default:
- return ( WinDefDlgProc( hwnd, msg, mp1, mp2 ) );
- }
- }
-
-
-
- /******************************************************************************
- * Name : InitializePlayList
- *
- * Description : This procedure will initialize the playlist structure with
- * playlist instructions.
- * Every even number of the playlist structure subscript contains
- * a DATA_INSTRUCTION. Operand One of the data instruction
- * is pointing to the pre-allocated buffer where the wave file
- * will be copied into. Operand two of the data instruction
- * contains the maximum size of the buffer.
- * Every odd number of the playlist structure subscript contains
- * a MESSAGE_INSTRUCTION. Operand two of the message
- * instruction contains the Number to return to the application.
- * Operand one and Operand three for message instruction are
- * ignored.
- * After every DATA_OPERATION instruction is executed a message
- * is sent to the application about the bufferno (subscript) it
- * just finished playing. At this time the wave file is read
- * into the Data buffer. The playing of the wave file thus
- * continues without any interruption.
- * Second to Last instruction in the playlist structure
- * (2*MAXBUFF) is the BRANCH_OPERATION which is initialized
- * to go to the next instruction (2*MAXBUFF+1) which is the
- * EXIT_OPERATION.
- * When the play pushbutton is pressed, the BRANCH instruction
- * is dynamically modified to go to the first DATA instruction
- * so the wave can play continuously in loops.
- * In order to stop playing the play list the operand of the
- * BRANCH_OPERATION is simply changed to the EXIT_OPERATION in
- * the routine.
- *
- *
- * Concepts : Initialize the memory playlist data structure.
- *
- * MMPM/2 API's: None.
- *
- * Parameters : None.
- *
- * Return : None.
- *
- *************************************************************************/
- void InitializePlayList()
- {
- ULONG ulNumber;
-
- for (ulNumber=0; ulNumber<MAXBUFF; ulNumber++)
- {
- /*
- * every 0, 2, 4, 6 etc index of the playlist contains the
- * DATA instruction. Operand one contains the buffer of the data
- * Operand two contains the maxmimum size for the data buffer.
- * Operand three is ignored.
- */
- aplayList[2*ulNumber].ulCommand = DATA_OPERATION;
- aplayList[2*ulNumber].ulOperandOne = (ULONG) achDataBuffer[ulNumber];
- aplayList[2*ulNumber].ulOperandTwo = (ULONG) MAXSIZE;
- aplayList[2*ulNumber].ulOperandThree = (ULONG) 0;
-
- /*
- * every 1, 3, 5, 7 etc index of the playlist contains the
- * MESSAGE instruction. Operand two contains the buffer number
- * which will be returned to the application.
- * Operand one and three are ignored.
- */
- aplayList[2*ulNumber+1].ulCommand = (ULONG) MESSAGE_OPERATION;
- aplayList[2*ulNumber+1].ulOperandTwo = (ULONG) ulNumber;
- aplayList[2*ulNumber+1].ulOperandOne = (ULONG) 0;
- aplayList[2*ulNumber+1].ulOperandThree = (ULONG) 0;
- } /* endfor */
-
- /*
- * Initialize the BRANCH_OPEATION to loop to the last EXIT Operation
- * Instruction. This will be dynamically modified when the play
- * push button is pressed.
- */
- aplayList[2*MAXBUFF].ulCommand = BRANCH_OPERATION;
- aplayList[2*MAXBUFF].ulOperandOne = (ULONG) 2*MAXBUFF+1;
- aplayList[2*MAXBUFF].ulOperandThree = (ULONG) 2*MAXBUFF+1;
- aplayList[2*MAXBUFF].ulOperandTwo = 0;
-
- aplayList[2*MAXBUFF+1].ulCommand = EXIT_OPERATION;
- aplayList[2*MAXBUFF+1].ulOperandOne = (ULONG) 0;
- aplayList[2*MAXBUFF+1].ulOperandTwo = (ULONG) 0;
- aplayList[2*MAXBUFF+1].ulOperandThree = (ULONG) 0;
-
- }
-
- /******************************************************************************
- * Name : OpenAudioDevice
- *
- * Description : This procedure will open the device for Playlist.
- *
- *
- * Concepts : How to Open a Device to play a wave file from Playlist.
- *
- * MMPM/2 API's: mciSendCommand MCI_OPEN
- *
- * Parameters : None.
- *
- * Return : None.
- *
- *************************************************************************/
-
- void OpenAudioDevice(HWND hwnd)
- {
-
- MCI_OPEN_PARMS lpWaveOpen; /* Used for MCI_OPEN messages */
- ULONG ulReturn; /* Used for ret code for API */
-
-
- /*
- * Initialize the MCI_OPEN_PARMS data structure with hwndMainDialogBox
- * as callback handle for MM_MCIPASSDEVICE, then issue the MCI_OPEN
- * command with the mciSendCommand function. No alias is used.
- */
-
- lpWaveOpen.hwndCallback = hwnd;
- lpWaveOpen.pszAlias = (PSZ) NULL;
-
-
- /*
- * Open the correct waveform device with the MCI_OPEN message to MCI.
- * Use 0 instead of 1 because this will then use the default audio device.
- */
- lpWaveOpen.pszDeviceType =
- (PSZ) (MAKEULONG(MCI_DEVTYPE_WAVEFORM_AUDIO,0));
-
- /*
- * The address of the buffer which will record and play the wave.
- */
- lpWaveOpen.pszElementName = (PSZ) &aplayList[0];
-
-
- /*
- * Open the waveform file in the playlist mode.
- */
- ulReturn =
- mciSendCommand(0,
- MCI_OPEN,
- MCI_WAIT | MCI_OPEN_PLAYLIST |
- MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
- (PVOID) &lpWaveOpen,
- (USHORT) NULL);
-
- if (ulReturn != 0)
- {
- /* MCI Open was not successfull so show a message by passing a TRUE */
- ShowAMessage(
- IDS_ERROR_TITLE,
- ulReturn,
- MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP | MB_APPLMODAL,
- TRUE);
- }
-
- /* Save the Device Id in the global variable to be used later */
- usWaveDeviceId = lpWaveOpen.usDeviceID;
- }
-
-
- /******************************************************************************
- * Name : ShowAMessage
- *
- * Description : This function will show text in a message box.
- * If the Message is an MCI Error then the text is pulled
- * by issuing a mciGetErrorString. The text is retrieved by the
- * Return code of the mci call which failed.
- * If the Message is not an MCI Error then the text
- * is pulled from the string table that is originally kept
- * in the resource file . The text is retrieved by the
- * message id that is passed into this function. This id is
- * used in the WinLoadString OS/2 API to get the correct
- * string from the table.
- *
- * Concepts : None.
- *
- * MMPM/2 API's: mciGetErrorString
- *
- * Parameters : usTitleId - The tile id that identifies which string
- * to retrieve from the string table.
- * usTextId - The message text to be placed in the
- * message box. This value is the Return
- * value for the failed MCI call if fMCIError
- * is true and is the Message id (application
- * owned) if fMCIError is False.
- * ulMessageBoxStyle - The style of the message box. Which
- * icons, buttons, etc., to show.
- * fMCIError - If the Error is an MCIError (TRUE) or
- * if it is an application message id (FALSE).
- *
- * Return : The result from the message box.
- *
- ******************************************************************************/
- USHORT ShowAMessage( USHORT usTitleId,
- USHORT usTextId,
- ULONG ulMessageBoxStyle,
- BOOL fMCIError)
- {
-
- CHAR achStringBuffer[ STRING_SIZE ]; /* Title String Buffer. */
- USHORT usMessageBoxResult; /* RC from WinMessageBox. */
- CHAR achMessageText[STRING_SIZE]; /* Message String Buffer */
- ULONG ulReturn; /* Return from MCI ERROR */
-
- /*
- * Load the Title for the message box from the string table defined in
- * the resources.
- */
-
- WinLoadString(
- hab, /* HAB for this dialog box. */
- (HMODULE) NULL, /* Get the string from the .exe file. */
- usTitleId, /* Which string to get. */
- (SHORT) STRING_SIZE, /* The size of the buffer. */
- achStringBuffer ); /* The buffer to place the string. */
-
- /* If we are to show a MCIERROR, then load it by mciGetErrorString API */
- if (fMCIError)
- {
- ulReturn =
- mciGetErrorString(
- usTextId,
- (PSZ)achMessageText,
- (USHORT) STRING_SIZE );
-
-
- /*
- * Make sure that the retrieving of the error string was successfull.
- */
- if ( ulReturn != MCIERR_SUCCESS )
- {
- WinLoadString(
- hab, /* HAB for this dialog box. */
- (HMODULE) NULL, /* Get string from .exe file. */
- IDS_CANT_PROCESS_MESSAGE, /* Which string to get. */
- (SHORT) STRING_SIZE, /* The size of the buffer. */
- achMessageText); /* Buffer to place the string.*/
-
- ulMessageBoxStyle = MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
- MB_APPLMODAL;
- } /* End of IF testing for failed Get Error String API. */
-
- }
- else
- {
- /*
- This is not an MCIError so load the Text for Message Box from
- the string table defined in the resources.
- */
- WinLoadString(
- hab, /* HAB for this dialog box. */
- (HMODULE) NULL, /* Get string from .exe file. */
- usTextId, /* Which string to get. */
- (SHORT) STRING_SIZE, /* The size of the buffer. */
- achMessageText ); /* Buffer to place the string.*/
- }
- usMessageBoxResult =
- WinMessageBox(
- HWND_DESKTOP, /* Parent handle of the message box. */
- hwndDiag, /* Owner handle of the message box. */
- achMessageText, /* String to show in the message box. */
- achStringBuffer, /* Title to shown in the message box. */
- ID_MESSAGE_BOX, /* Message Box Id. */
- ulMessageBoxStyle ); /* The style of the message box. */
-
- return( usMessageBoxResult );
-
- } /* End of ShowAMessage */
-
-
-