MMAPG - Captioning
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
The Toolkit provides a sample captioning system to assist application programmers in adding captioning to multimedia applications. The sample captioning system consists of three parts: the Caption Creation Utility program, Caption DLL, and Caption Sample Application. The Caption Creation Utility program (located in \TOOLKIT\SAMPLES\MM\CAPTION subdirectory) creates a 'caption' file. This is a text file containing timing information relating to its associated audio file. The Caption DLL (located in the \TOOLKIT\SAMPLES\MM\CAPDLL directory) provides functions that drive the display and management of the caption file in a 'caption window' in a PM application. The Caption Sample Application (located in the \TOOLKIT\SAMPLES\MM\CAPSAMP subdirectory) demonstrates how an application uses the functions provided by the Caption DLL to take advantage of its services. As with all OS/2 multimedia samples, the source code is provided for all three components. You can use the three components as provided or modify them to meet specific requirements. See Sample Application Programs for more information on the captioning components.
Creating a Caption File
The Caption Creation Utility enables synchronization of the line-by-line display of a text file with the playing of an audio file. You can start this program from either an OS/2 command prompt by typing CAPTION (while in the \TOOLKIT\SAMPLES\MM\CAPTION subdirectory), or by selecting the Caption Creation Utility object from the Toolkit folder. You can open an audio file, open a text file to synchronize with it, play the audio file, and select (by clicking a mouse button) the moment in the audio when the current line of text should scroll to display the next line of text. This allows the user to synchronize an audio file with a text file.
┌─────────┐ ┌─────────┐
│ Text │ │ Audio │
│ File │ │ File │
└─────────┘ └─────────┘
└──────┐ ┌──────┘
↓ ↓
┌─────────────┐
│ Caption │
│Creation │
│ Utility │
└──────┬──────┘
│
┌──────────┐
│Caption │
│ File │
└──────────┘
In order to start the synchronization process, the user selects Start timing. The audio file begins playing and Advance line is enabled. When you want to scroll to the next line of text, you select Advance line. This scrolls the line of text in the text window and displays the next line. When Advance line is selected, the Caption Creation Utility issues an MCI_STATUS message with mciSendCommand as shown in the following figure. The device ID passed is obtained when the application opens the audio device. The MCI_STATUS_ITEM flag is set and the ulItem field in the MCI_STATUS_PARMS data structure contains MCI_STATUS_POSITION. Upon return, the ulReturn field in the MCI_STATUS_PARMS data structure contains the current position of the device in MMTIME units.
case ID_NEXTLINE:
if ( usNextline < usLineCount ) /* (1) Check usNextline. */
{
msp.hwndCallback = (HWND) NULL; /* (2) Get audio
position. */
msp.ulItem = MCI_STATUS_POSITION;
ulError = mciSendCommand ( mop.usDeviceID,
MCI_STATUS,
MCI_WAIT | MCI_STATUS_ITEM,
(PVOID) &msp,
(USHORT) UP_STATUS );
When the Caption Creation Utility receives the position value, it writes the time value and the line of text to the caption file. A caption file contains a copy of the text file and (before each line of text) the multimedia time unit when that line of text should be displayed in conjunction with the audio file. The file name of the caption file is the same as the file name of the text file, with an extension of ._CC. The caption file can then be used by an application in conjunction with the Caption DLL to caption an application.
Displaying Captions in a Window
The Caption DLL works with an application to display caption files in the requesting application's window. The DLL does all of the work to display the text window and scroll the text in synchronization with the appropriate audio file. Applications can utilize this DLL to display captioned text (in synchronization with an audio file) in their application's window. To perform this function, the Caption DLL utilizes the captioned text files, created by the Caption Creation Utility, and position advise messages that it sets on the specified audio device. As described earlier, the caption files contain an MMTIME unit before every line of text. The Caption DLL requests position advise messages from the Media Device Manager (MDM) every 1500 MMTIME units on the specified device. When it receives MM_MCIPOSITIONCHANGE messages from MDM, it examines the MMTIME units in front of the text lines and displays the correct line of text in the text window of the application. The maximum size of the caption file is 500 lines long, but this can be modified by changing the limit in the Caption DLL source code. This DLL supports the following functions:
ccInitialize: Creates a captioning window and returns the handle of the window to the application.
ccSendCommand: Controls the captioning window, when it has been created, using the following commands: CC_START, CC_STOP, CC_STATUS, and CC_SET.
ccTerminate: Destroys the captioning window and releases any resources allocated for captioning.
See Caption DLL for more information on the captioning functions and data structures.
Caption Sample Application
The Caption Sample Application demonstrates the incorporation of captioning in an application using caption files and the Caption DLL.
As part of its initialization and termination routines, the Caption Sample Application issues ccInitialize and ccTerminate respectively. This notifies the DLL to begin and end captioning.
/*
* Create the caption window and save the handle for further use.
*/
hwndCaption = ccInitialize ( (HWND) hwndMainDialogBox );
When the ccInitialize function is called, the DLL creates the caption window, but keeps it hidden until the DLL receives a ccSendCommand with a CC_START message.
/* * Close the captioning system. This will release all the resources * that were allocated. */ ccTerminate(hwndCaption);
When the user selects Play, the Caption Sample Application opens the audio file and obtains a device ID. It then plays the audio file. Finally, it checks the system's captioning flag. If it is set, the Caption Sample Application issues ccSendCommand with a CC_START command. This is all an application must do to implement captioning with OS/2 multimedia. The Caption DLL then starts providing captioning for the application. Three important parameters are sent with this function. First, the device ID or alias is passed. This tells the DLL the correct audio device for which to request position-advise messages. Second, the name of the caption file is passed, and third, the application's window handle is passed. This tells the DLL which caption file to display and the handle of the window to display it in.
/*
* Test the MMPM/2 Captioning Flag. If it is ON, then the user
* wants to see captioning. If it is OFF, the user does not want to
* see captioning.
*/
mciQuerySysValue ( MSV_CLOSEDCAPTION, &bCCflag );
.
.
.
/*
* Captioning flag is ON.
* Fill in the CC_START_PARMS structure and then call ccSendCommand
* to make the captioning window visible. The hwndOwner field holds
* the window handle that we want the Caption DLL to send the
* position change messages to, when it is done processing them.
*/
csp.pszDeviceName = (PSZ) 'capsamp'; /* Alias name */
csp.pszCaptionFile = (PSZ) 'CAPSAMP._CC'; /* File name to use */
csp.hwndOwner = hwnd; /* for position change */
ulReturn = ccSendCommand ( CC_START, MPFROMHWND(hwndCaption), &csp );
/* Start captioning */
If you pause the audio file, change the volume, or move the audio slider position, the Caption Sample Application does not have to do any special processing to manage the caption window. The Caption DLL handles this.
If you select Stop, the Caption Sample Application issues an MCI_STOP to the audio device, and then it issues a ccSendCommand of CC_STOP to the Caption DLL. This function informs the Caption DLL to stop displaying the caption window in the application and hide the caption window.
case IDC_GPB_STOP: /* User selected 'Stop' push button */
/*
* If the audio is not in stopped state, stop the device
* and hide the text window.
*/
if (eState != ST_STOPPED)
{
StopTheDevice();
ccSendCommand( CC_STOP, MPFROMHWND(hwndCaption), 0 );
}
break;
The application issues a ccSendCommand with CC_STATUS to determine the current properties of the caption window. This function initializes the settings dialog box to display it to the user. The following figure shows the status request for the text columns. Requests for the status of the text rows, background color, text color, and window position are handled similarly.
/*
* Query the current status of the text columns.
* The CC_STATUS returns the actual value in the ulReturn field.
*/
ccStatusParms.ulItem = CC_STATUS_TEXT_COLUMNS;
ccSendCommand( CC_STATUS, MPFROMHWND(hwndCaption), &ccStatusParms );
/*
* Get the index value for the ulReturn field.
*/
if (ccStatusParms.ulReturn == 15)
ulArrayIndexValue = 0;
else
if (ccStatusParms.ulReturn == 35)
ulArrayIndexValue = 1;
else
if (ccStatusParms.ulReturn == 50)
ulArrayIndexValue = 2;
/*
* Set the current index value in the spin button.
*/
WinSendDlgItemMsg( hwnd, /* Handle to the dialog box */
IDC_TEXT_COLUMNS_SB, /* ID of the spin button */
SPBM_SETCURRENTVALUE, /* Set current index value */
MPFROMLONG(ulArrayIndexValue),/* Current index */
NULL ); /* Ignore */
You can change several properties of the caption window by selecting Settings from the Options pull-down menu of the Caption Sample Application. When you select OK to save the desired properties, the Caption Sample Application issues ccSendCommand with a CC_SET message. The Caption DLL handles changing and displaying the new properties of the caption window. The following figure shows sample code from the Caption Sample Application that sets up the CC_SET_PARMS data structure for the text rows. Changing the settings for the background color, text color, window position, and text columns is handled similarly.
CC_SET_PARMS ccSetParms; /* Set parms for CC_SET */
ULONG ulArrayIndexValue=0; /* For spin button return
value */
/*
* Query the text rows spin button. The array index
* value will be returned in ulArrayIndexValue variable.
*/
WinSendDlgItemMsg(
hwnd,
IDC_TEXT_ROWS_SB,
SPBM_QUERYVALUE,
(MPARAM) &ulArrayIndexValue,
MPFROMLONG(0));
/*
* Get the actual value and initialize the CC_SET_PARMS
* data structure with the appropriate information.
*/
ccSetParms.ulRows = (ULONG) atoi( textRows[ulArrayIndexValue] );
/*
* Issue the CC_SET command with the ccSendCommand and close
* the dialog box.
*/
ccSendCommand(CC_SET, MPFROMHWND(hwndCaption), &ccSetParms);
WinDismissDlg( hwnd, TRUE );
return( 0 );