Jump to content

MMAPG - Sample Application Programs

From EDM2
Multimedia Application Programming Guide
  1. Introduction
  2. What's New...
  3. Multimedia Application Programming Environment
  4. Media Control Interface
  5. Multimedia Logical Devices
  6. Amplifier-Mixer Device
  7. Waveform Audio Device
  8. Sequencer Device
  9. CD Audio Device
  10. CD-XA Device
  11. Videodisc Device
  12. Digital Video Device
  13. Direct Interface Video Extensions (DIVE)
  14. Captioning
  15. OS/2 Multimedia Controls
  16. Multimedia I/O File Services
  17. Resource Interchange File Format (RIFF) Services
  18. Sample Application Programs
  19. Installing a Program Using MINSTALL
  20. Caption DLL
  21. High-Level Service API
  22. Notices
  23. Glossary

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

This section gives a brief overview of the sample application programs provided with the Toolkit, including programming concepts and program flow diagrams for each of the sample programs.

The purpose of the OS/2 multimedia sample programs is to illustrate multimedia programming concepts and establish a basis for creating your own multimedia applications. The programs provide you with practical examples that span a range of multimedia concepts. The source code provided shows you how to use multimedia controls and functions to create multimedia applications. Each sample program serves as a template that can be modified easily to meet your multimedia application requirements. The samples were compiled and verified using the IBM C Set ++ and VisualAge C++ compilers.

Some samples require specific hardware devices. Without these devices, you can still compile and run the sample programs; however, you might not receive the full effect of the program. For example, if a sample program has audio, you will not hear it unless you have a supported audio adapter and speakers installed.

Subdirectory Structure

Code for the sample programs (and associated files such as waveform audio files and movie files) are located in the following subdirectories.

TOOLKIT - OS/2 Developer's Toolkit
    |
    +--- H        - Header Files
    |
    +--- INC      - Include Files
    |
    +--- LIB      - Library Files
    |
    +--- SAMPLES  - Samples
          |
          +--- MM       - OS/2 Multimedia Samples
                |
                +--- SYMREC  - Asymmetric Recording Sample
                |
                +--- VCINST  - AVC I/O Procedure Installation Sample
                |
                +--- CAPDLL  - Caption DLL
                |
                +--- APSAMP  - Caption Sample Application
                |
                +--- APTION  - Caption Creation Utility
                |
                +--- CLOCK   - Memory Playlist Sample
                |
                +--- OUBPLAY - Double Buffering Playlist Sample
                |
                +--- DIVE    - Direct Interface Video Extensions Sample
                |
                +--- DUET1   - Streaming Device Duet Sample
                |
                +--- DUET2   - Streaming and Non-Streaming Device Duet Sample
                |
                +--- MCISPY  - MCISpy Sample
                |
                +--- CISTRNG - Media Control Interface String Test Sample
                |
                +--- MBROWSE - Image Browser Sample
                |
                +--- MOVIE   - Movie Sample
                |
                +--- ECORDER - Audio Recorder Sample
                |
                +--- HORTCF  - Control File Templates
                |
                +--- TUNER   - TV Tuner Sample
                |
                +--- LTIEYES - Non-Linear Video Sample

Note: The SHORTCF subdirectory contains control file templates you can utilize when installing a program using MINSTALL. See Installing a Program Using MINSTALL for further details.

ASYMREC - Asymmetric Recording Sample

This sample (ASYMREC) illustrates how to include asymmetric recording function in your multimedia application. Modules include source code extracted from the Video IN Recorder application, which enables frame-step recording using Ultimotion compression techniques.

Frame-step recording captures the audio and video in a two-pass operation. First, it captures the audio in real time. It then returns to the point in the media where recording started to capture the video frame by frame.

Source Code

The following files are located in the \TOOLKIT\SAMPLES\MM\ASYMREC subdirectory.

ASYMREC.H Is the header file for the asymmetric recording sample. See this file for a complete description of the asymmetric recorder data structures.

ASYMREC.C Is the sample program code for the asymmetric recording sample. It includes code for the following functions:

OpenMMIO Opens and identifies the I/O procedure to install.

IdentifyIOProc Loads and installs the known I/O procedure. Also, attempts to open the movie file using this I/O procedure.

AssociateCodec Sends MMIOM_SET to associate the CODEC for later use in compression.

InitiateFrameStepRecord Initializes the environment for frame-step recording and starts a frame-step record thread.

CompressBuffer Calls the AVI I/O procedure and Ultimotion CODEC procedure to compress a buffer.

StartVideoThread Starts a recording thread for doing the frame-step.

Detailed information about each function is provided in the source code.

Real-Time Capture and Asymmetric Capture

Typically, a stream is established to read a series of moving images from the device. This continuous capture mode is called symmetric or real-time capture, and is performed at a constant frame rate and constant frame size. When established, a stream captures images continuously without assistance from the application code. However, video images can be captured one frame at a time when directed by the application. This type of capture mode is referred to as asymmetric capture because the time between successive frames is not constant. The frame rate is determined by how long the application delays between taking image snapshots. Asymmetric capture is performed with IOCtls only; the OS/2 multimedia streaming mechanism is not used.

Asymmetric Recording Architecture

Several passes through the source data are required to produce an Ultimotion movie file.

During the first pass, the capture routines position the video source device to the starting position in the source video. It then uses OS/2 multimedia to record the desired audio track. If the desired final format for the movie requires both audio and video to be interleaved, MULTITRACKWRITE interleaves them.

During the second pass, capture routines use OS/2 multimedia to position the video source at the desired location. For each frame in the movie, an MCI_STEP message is sent to the MCD controlling the source device. When the resulting image has been 'grabbed' or 'digitized' by the capture hardware, the video data is retrieved and written to disk through the AVI I/O procedure. This process continues until the required video is captured.

Note: Only the second pass is used if you are recording video without audio.

The following figure illustrates the architecture of the components involved in doing asymmetric capture and compression of video from frame accurate devices.

 +----------------------------------------------------------------------------+
 | Asymmetric Recorder <--------------------------+                          |
 |                                                |                          |
 | Media Control Interface Commands and Notifications                        |
 +---------------------------------------------------------+------------------+
   Media Device Manager                                    |
 +------------+------------------+-----------------+-------+------------------+
 | WAV data   |                  |                 |                          |
 |     +------+-------+   +------+-------+  +------+-------+   +----------+   |
 |     |Amplifier Mixer|  |Video Disc    |  |Digital Media |   |AVI       |   |
 |     |Media Driver   |  |Driver        |  |Driver        |   |IOProc    |   |
 |     +------+-------+---+------+-------+--+------+-------+---+------+---+   |
 |            |          |       |                 |                  |       |
 |     +------+-------+  +-------+-------+  +------+-------+          |       |
 |     |Audio         |  |SPI Interfaces |  |VSD           |   uncompressed   |
 |     |Adapter       |  |SSM            |  |Driver        |   video frame    |
 |     +--------------+  +---------------+  +--------------+          |       |
 |            audio data        +------------------+                  |       |
 |     +------+          +------+--------+         +-------+   +------+---+   |
 |     | MMIO |          | Multitrack    |         |Video  |   |CODEC     |   |
 |     +------+          |Stream Handler |         |Capture|   |          |   |
 +-----------------------+---------------+---------+-------+---+----------+   |
                                 |                 |                  |       |
                         +-------+-------+         +-------+          |       |
                         |MMIO           |         |Video  |          |       |
                         |Manager        |         |Adapter|          |       |
                         +-------+-------+---------+-------+----------+       |
                                 |                                    |
                         +-------+-------+                       Compressed   |
                         |AVI            |                          Data      |
                         |IOProc         |                                    |
                         +-------+-------+                                    |
                                 |                                    |
                         +-------+-------+                                    |
                         |Movie          |                                    |
                         |File           |                                    |
                         +---------------+                                    |

MMMULTITRACKREAD Operations

The MMMULTITRACKREAD structure contains the following parameters:

  • Pointer to the read buffer (pBuffer)
  • Length of the read buffer (ulLength)
  • Read flags (ulFlags)
  • Number of track entries or number of tracks (ulNumTracks)
  • Pointer to a track map list (pTrackMapList)
  • Actual buffer length available in MULTITRACKREAD extended mode (ulBufferLength)

The track map list is a list of valid track numbers for the current file and is used to map a track to a record table. Each track map list contains:

  • A track ID (ulTrackID)
  • The number of record entries (ulNumEntries)
  • A pointer to a record table (pRecordTabList)

Each element of the record table contains a pointer to (pBuffer) and the length (ulLength) of the corresponding data in the buffer.

For example, if the number of track entries is two, the track map list will contain two track map tables, one for each track. There is a corresponding record table for each track. The number of entries in the track map table for each track is the number of entries in the record table for a particular track. The following figure illustrates the multitrack read data structure.

  MMMULTITRACKREAD                                        pBuffer
 +---------------+  +-------------------------------------------------------+
 | ulLength      |  | TRACKMAP           RECORDTAB                          |
 | pBuffer       |  |  TABLE                AUDIO                           |
 | ulFlags       |  +---------------+  +-------------+       +--------------+
 | ulNumTracks   |  | ulTrackID     |  | pRecord   1 | ----> | Audio        |
 | pTrackMapList |  | ulNumEntries  |  | ulLength    |       | Data 1       |
 |               |  | pRecordTabList|  | ulParm1     |       +--------------+
 |               |  +---------------+  | ulParm2     |       | Video        |
 | ulBufferLength|  | ulTrackID     |  +-------------+       | Data 1       |
 |(extended mode)|  | ulNumEntries  |  | .           |       +--------------+
 +---------------+  | pRecordTabList|  | .           |       | Audio        |
                    +---------------+  | .           |       | Data 2       |
                    | .             |  +-------------+       +--------------+
                    | .             |  RECORDTAB             | Video        |
                    | .             |      VIDEO             | Data 2       |
                    +---------------+  +-------------+       +--------------+
                                       | pRecord   1 |       | .            |
                                       | ulLength    |       | .            |
                                       | ulParm1     |       | .            |
                                       | ulParm2     |       +--------------+
                                       +-------------+
                                       | .           |
                                       | .           |
                                       | .           |
                                       +-------------+

Multitrack Reading

MULTITRACKREAD is supplied an empty buffer. The size is determined by ulLength, and it is pointed to by pBuffer. MULTITRACKREAD processes the data by reading ulLength bytes of data into the buffer, and then parsing the data in the buffer by media type (audio or video) into records. A pointer to the data in the buffer is placed in the appropriate record table.

Note: A record is a contiguous buffer containing data of the same media type.

During the processing of MULTITRACKREAD in extended mode, pBuffer points to the beginning of the buffer on the first call to MULTITRACKREAD and ulLength indicates the number of bytes to be read into the buffer. With each call to MULTITRACKREAD, ulBufferLength (the actual total buffer length) is reduced by ulLength bytes, and pBuffer points to the current location in the buffer. Subsequent calls to MULTITRACKREAD reads ulLength bytes of data into the buffer starting at pBuffer and repeats the process until ulBufferLength is reached.

This implementation of MULTITRACKREAD allows smaller amounts of data to be read at one time while allowing frames greater than the ulLength of the read. For example, if the program wanted to fill a 128KB buffer while doing 32KB reads, the calling sequence to MULTITRACKREAD would be (32KB, 128KB), (32KB, 96KB), (32KB, 64KB), and (32KB, 32KB) for (ulLength, ulBufferLength). With this setup, MULTITRACKREAD can span frames across the 32KB buffers and know the size of the 128KB buffer.

During MULTITRACKREAD processing in regular mode, pBuffer always points to the beginning of the buffer and ulLength indicates the number of bytes to be read into the buffer. The buffer is filled completely with each call to MULTITRACKREAD and subsequent calls, to MULTITRACKREAD, read ulLength bytes of data into the buffer starting at the beginning of the buffer (pointed to by pBuffer).

Note: If the MULTITRACKREAD_EXTENDED bit flag is set, the calling routine has passed the extended MMMULTITRACKREAD structure with the new ulBufferLength field in this structure.

MMMULTITRACKWRITE Operations

The MMMULTITRACKWRITE structure contains the following parameters:

  • Number of tracks (ulNumTracks)
  • A pointer to a track map list (pTrackMapList)
  • Read flags (ulFlags)

The track map list is a list of valid track numbers for the current file and is used to map a track for a record table. Each track map list contains:

  • A track ID (ulTrackID)
  • Number of record entries (ulNumEntries)
  • A pointer to a record table (pRecordTabList)

Each element of the record table contains a pointer (pRecord) to and the length (ulLength) of the corresponding data in the buffer.

For example, if the number of track entries is two, the track map list contains two track map tables, one for each track. There is a corresponding write record table for each track. The number of entries in the track map table for each track is the number of entries in the write record table for a particular track.

Note: A record is a contiguous buffer containing data of the same media type.

The following figure illustrates the multitrack write data structure.

    MMMULTITRACKWRITE
 +---------------+  +---------------------------------------+
 | ulNumtracks   |  | TRACKMAP           RECORDTAB          |
 | pTrackMapList |  |  TABLE                AUDIO           |
 | ulFlags       |  +---------------+  +-------------+      +----------+
 | ulNumTracks   |  | ulTrackID     |  | pRecord   1 | ---> | Audio    |
 |               |  | ulNumEntries  |  | ulLength    |      | Data 1   |
 |               |  | pRecordTabList|  | ulParm1     |      +----------+
 +---------------+  +---------------+  | ulParm2     |      +----------+
                    | ulTrackID     |  +-------------+      | Audio    |
                    | ulNumEntries  |  | .         2 | ---> | Data 2   |
                    | pRecordTabList|  | .           |      +----------+
                    +---------------+  | .           |
                    | .             |  +-------------+
                    | .             |
                    | .             |
                    +---------------+  +-------------+      +----------+
                                       | pRecord   1 |      | Video    |
                                       | ulLength    | ---> | Data 1   |
                                       | ulParm1     |      +----------+
                                       | ulParm2     |      +----------+
                                       +-------------+      | Video    |
                                       | .         2 | ---> | Data 2   |
                                       | .           |      +----------+
                                       | .           |
                                       +-------------+

Multitrack Writing

MULTITRACKWRITE provides a list of records by media type and processes the data by using the pointers in the write record table to locate the data in the buffers and write the data to the file.

If the MULTITRACKWRITE_MERGE bit flag is not set, MULTITRACKWRITE writes all of the records sequentially from the first entry in the track map table (for the first track) followed by all records for the second track.

If the MULTITRACKWRITE_MERGE bit flag is set, MULTITRACKWRITE attempts to interleave the digitalvideo track with the digitalaudio track. Interleaving is accomplished based on the size of the audio buffer. For example, if a 4KB audio buffer represents one-third of a second and the frame rate is 15 frames per second, the interleave factor would be 5:1 (5 video frames to 1 audio chunk).

AVCINST - AVC I/O Procedure Installation Sample

This sample (AVCINST) explains how an application can install and remove an I/O procedure to use multimedia input/output (MMIO) file services. The AVC I/O Procedure Installation Sample is a simple PM application that allows you to install or deinstall the audio AVC I/O procedure, AVCAPROC.DLL.

Note: This sample shows the installation and removal of a system-defined I/O procedure. Typically, you would install a custom I/O procedure that was not built into the MMPMMMIO.INI file during installation.

Program Flow

The following figure illustrates the interaction between OS/2 multimedia system components and the AVC I/O Procedure Installation sample program. Source code is located in the \TOOLKIT\SAMPLES\MM\AVCINST subdirectory.

+--------------------------------+
| AVC I/O Procedure Installation |
|       Sample Program           |
+--------------+-----------------+
               | (1)
        +------+-------+
        | MMIO Manager |
        +------+-------+
               | (2)
        +------+-----------+
        | AVC I/O Procedure|
        +------------------+

(1) When OK is selected, the AVC I/O Procedure Installation program calls the mmioInstallfIOProc function to install or deinstall the AVC I/O procedure (AVCAPROC.DLL) in the system.

(2) The MMIO Manager installs or deinstalls the AVC I/O procedure.

CAPTION - Caption Creation Utility

The Caption Creation Utility (CAPTION) is part of the sample captioning system provided with the Toolkit. See Captioning for additional information on this sample captioning system.

The Caption Creation Utility program enables the synchronization of an audio file with a text file.

Note: This concept can be extended beyond audio and text to apply to many possibilities, such as synchronizing audio and video, or synchronizing video and text.

While the audio file is playing, the Caption Creation Utility program issues the MCI_STATUS command to obtain a media-position value of the audio file. The media-position value is combined with the text file to produce a caption file. An application can use the resulting caption file in conjunction with the Caption DLL to provide captioning in an application.

Program Flow

The following figure illustrates the interaction between the audio, text, and caption file with the Caption Creation Utility program. Source code for the Caption Creation Utility is located in the \TOOLKIT\SAMPLES\MM\CAPTION subdirectory.

(1) Select an audio file and a corresponding text file to synchronize with the selected audio file. For example, you might want to synchronize the text of a poem with an audio file of someone reading the poem. When you open a text file, the first line of text appears at the bottom of the text window. The first line of the text file selected in the example shown in the previous figure is 'Welcome to MMPM/2's sample captioning system.'

(2) In order to begin the synchronization process, you must select Start timing. The audio file begins to play and Advance line becomes enabled.

(3) Select Advance line to scroll to the next line of text. The next line of text is scrolled and appears in the text window.

(4) When you select Advance line, the Caption Creation Utility program passes the device ID, the MCI_STATUS command with the MCI_STATUS_ITEM flag, and the MCI_STATUS_PARMS data structure with the ulItem field set to MCI_STATUS_POSITION to the Media Device Manager (MDM). Upon return, the ulReturn field of the MCI_STATUS_PARMS data structure contains the current position of the device in MMTIME units.

(5) When the Caption Creation Utility program receives the position value, it writes the time value and the line of text to the caption file. The caption file contains the same text as the text file, but each line in the caption file is preceded by the time in the audio file when that line of text should be displayed.

CAPSAMP and CAPDLL

The Caption Sample Application (CAPSAMP) and Caption DLL (CAPDLL) are part of the sample captioning system provided with the Toolkit. See Captioning for additional information on this sample captioning system.

The Caption Sample Application and Caption DLL are provided to demonstrate how captioning can be integrated into applications using caption files in conjunction with the Caption DLL.

Program Flow

The following figure illustrates the interaction between the captioning components and the media control interface layer. Source code for the Caption Sample Application and Caption DLL are located respectively in the \TOOLKIT\SAMPLES\MM\CAPSAMP and \TOOLKIT\SAMPLES\MM\CAPDLL subdirectories.

+---------------------+
|      Caption        |
|      Sample         +----(2D)-----+
|    Application      |             |
+--+--+--+--+--+--+---+             |
(2)(3)(4)(1)(2)(4)(5)               |
 |  |  |  |  |  |  |                |
 |  |  | +---------+------+   +-----+-----+
 |  |  | | Caption DLL    |   | Caption   |
 |  |  | |                |   | File      |
 |  |  | +---------+------+   +-----------+
 |  |  |      (2B) ^
 |  |  |           | (2C)
-+--+--+-----------+-----------------------
+-----------------------------+ OS/2 Multimedia
| Media Control Interface     |
+-----------------------------+

(1) As part of its initialization and termination routines, the Caption Sample Application issues ccInitialize and ccTerminate, respectively, to notify the Caption DLL to begin and end captioning. As part of the termination process, the Caption DLL releases any resources previously allocated for captioning.

(2) When you select Play, the Caption Sample Application opens the audio file, obtains a device ID, and plays the audio file. The Caption Sample Application queries the captioning flag. (You can set this flag by selecting the Captioning check box on the System page of the Multimedia Setup.) If this flag is set, the application issues ccSendCommand with a CC_START message to the Caption DLL. The Caption DLL then begins to provide captioning for the application.

(2B) When the Caption DLL receives the request to begin captioning, it issues a set position advise message to the multimedia system for every 1500 time units.

(2C) When the device moves 1500 time units, the Caption DLL receives an MM_MCIPOSITIONCHANGE message from the multimedia system.

(2D) Whenever the Caption DLL receives the MM_MCIPOSITIONCHANGE message, it checks the caption file for the appropriate line to display, based on the current position of the audio file. The Caption DLL then scrolls the caption window in the application, to display the appropriate line.

(3) If you pause the audio file, change the volume, or move the audio slider position, the Caption Sample Application does not have to perform any additional processing to manage the caption window. This processing is managed by the Caption DLL.

(4) When you select Stop, the Caption Sample Application sends an MCI_STOP message to the audio device. The application then issues ccSendCommand with a CC_STOP message, informing the Caption DLL to stop displaying the caption window in the application.

(5) You can change several properties of the caption window by selecting Settings from the Options menu of the Caption Sample Application. The application issues ccSendCommand with a CC_STATUS message to query the current properties of the caption window. When you select OK to save the desired properties, the Caption Sample Application issues the ccSendCommand with a CC_SET message to the Caption DLL. The Caption DLL handles changing and displaying the new properties of the caption window.

CLOCK - Memory Playlist Sample

The Memory Playlist Sample (CLOCK) illustrates the use of the memory playlist feature of OS/2 multimedia. The memory playlist feature provides for easy manipulation of multimedia data in memory to create unique effects based on user input or other dynamic events. In the case of the Memory Playlist Sample, multimedia data is manipulated dynamically to create sound effects (chimes) based on the time. The sample program also illustrates the use of the captioning flag provided by OS/2 multimedia. The Memory Playlist Sample uses this flag to decide if it should provide users with a visual cue of chimes.

Program Flow

The following figure illustrates the interaction between OS/2 multimedia system components and the Memory Playlist Sample. Source code is located in the \TOOLKIT\SAMPLES\MM\CLOCK subdirectory. (Source code for the Waveform Audio Media Driver is located in \TOOLKIT\SAMPLES\MM\ADMCT)

+-----------------+      +----------+
| Memory Playlist | (2)  | Audio    |
| Sample Program  | <--- | File     |
+--------+--------+      +----------+
         | (1)
+--------+--------+
| Media Device    |
|   Manager       |
+--------+--------+
         | (3)
+--------+--------+
|Waveform Audio   |
|Media Driver     |
+--------+--------+
         | (3)
+--------+--------+
|    Memory       |
|   Playlist      |
+-----------------+

(1) The Memory Playlist Sample queries the Media Device Manager using the mciQuerySysValue function to determine whether the captioning flag is set. If the flag is set, the bell in the primary window will swing back and forth when a chime occurs.

(2) The Memory Playlist Sample program initializes the playlist and loads the audio files into memory.

(3) When a chime occurs, the Memory Playlist Sample program calls the Waveform Audio Media Driver through the MDM to interpret instructions for the playing of three audio files in memory. The clock chimes are stored in three files: A, B, and C. Depending on the time a chime is requested, the memory playlist consists of the following:

  • At 15 minutes past the hour, the chime plays A.
  • At 30 minutes past the hour, the chime plays A+B.
  • At 45 minutes past the hour, the chime plays A+B+A.
  • On the hour, the chime plays A+B+A+B+ (C x Hour).

Playing a Chime

Every time you want to play a chime, open the device you want to play, play it, and close it. The logic for the Memory Playlist Sample implementation of the playlist is outlined in in the following figure.

                                                           (6)
                                                           │
                                                           
┌─────────────────┐     ┌─────────────────┐      ┌─────────────────┐
│  "Play Chime"   │     │Deal with chiming│      │  MM_MCINOTIFY   │
│  push button    │     │     (Open)      │      │ (Play or Open)  │
│                 │     │                 │      │                 │
└────┬────────────┘     └───────┬─────────┘      └─────────┬───────┘
 (1)                         (2)│                       (7)
┌─────────────────┐             │                   ┌─────────────────┐
│Find the nearest │             │                   │ Chiming is done.│
│chime time and   │             │                   │ Stop swinging   │
│play it (Open)   │             │                   │   the bell      │
└────┬────────────┘             │                   └─────────────────┘
     │                          
     │                  ┌─────────────────┐
     │                  │  Find and play  │
     └───────────────── │   the correct   │
                        │      chime      │
                        └───────┬─────────┘
                             (3)│
                                
                        ┌─────────────────┐
                        │  Open Playlist  │
                        │   chime device  │
                        │with MCI_WAIT set│
                        └───────┬─────────┘
                             (4)│
                                
                        ┌─────────────────┐
                        │Set up chime file│
                        │   information   │
                        │                 │
                        └───────┬─────────┘
                             (5)│
                                
                        ┌─────────────────┐
                        │  Play Playlist  │
                        │ with notify set │
                        │                 │
                        └───────┬─────────┘
                                │
                                
                               (6)

(1) If Play chime is selected, processing is passed to the FindTheNearestChimeTimeAndPlayIt procedure, which calculates the next hour so its chime can be played. The procedure calls FindAndPlayTheCorrectChime to do the actual work required to play the chime.

(2) If it is a normally scheduled chime time (if a quarter hour has been reached), processing is passed to FindAndPlayTheCorrectChime.

(3) FindAndPlayTheCorrectChime calls OpenPlaylistChimeDevice to do open processing with MCI_WAIT specified.

(4) When the OPEN command completes, the Waveform Audio Media Driver needs information about the waveform file. The FindAndPlayTheCorrectChime procedure calls SetupChimeFileInformation to pass this information to the driver.

(5) After calling SetupChimeFileInformation, the FindAndPlayTheCorrectChime procedure issues the mciSendCommand request to play the chime with the notify flag set.

(6) After the chime has finished playing, a notification message is sent to the MainDialogProc and handled by the MM_MCINOTIFY case of the switch statement.

(7) In the MM_MCINOTIFY case of MainDialogProc, when usMCIUserParameter is set to indicate the chime has stopped playing, the swinging of the bell is stopped and the device is closed.

DOUBPLAY - Double Buffering Playlist Sample

DOUBPLAY allows an application to play audio files directly from application memory buffers. An array of multiple playlist structures can be constructed that combines playlist commands with data buffers to perform complex operations on multiple buffers.

This sample takes a single wave file, MYWAVE.WAV, and plays it using a memory playlist. The playlist is constructed as a circular buffer composed of a series of small buffers, the sum of which may or may not be larger than the size of the .WAV file. This circular buffer is used to repeatedly play an audio file when the PLAY button is selected. As each buffer in the playlist is expended, the application refills the expended buffer with new data from the .WAV file. When all the buffers in the playlist have been expended, the playlist branches back to the first buffer to play the new data. This circular buffering process continues until the STOP button is selected or the application is closed.

DIVE - Direct Interface Video Extensions Sample

The DIVE Sample illustrates the use of direct interface video extensions (DIVE), which provides optimized blitting performance for motion video subsystems and applications that perform rapid screen updates in the OS/2 PM and full-screen environments. Using DIVE interfaces, applications can either write directly to video memory or use the DIVE blitter. The DIVE blitter will take advantage of acceleration hardware when present and applicable to the function being performed.

Using DIVE, the sample program blits a series of 16 compressed 256-color bit maps to the screen. For more information on how to use the DIVE functions included in this sample program, see Direct Interface Video Extensions (DIVE).

Note: The DIVE sample requires OS/2 Warp, Version 3 in order to execute properly. The files for the samples will be installed when the samples are selected, but Workplace Shell objects will not be created for them if the installed operating system is not OS/2 Warp, Version 3.

The OS/2 Warp color support defaults to 16 colors. This means that your setup needs to be updated, otherwise the DIVE sample will not run.

The maximum window size of this sample has been limited to 640x480 because larger window sizes may cause excessive swapping on machines with less than 16MB.

Duet Samples

This section describes the use of the media control interface layer of the OS/2 multimedia system to manipulate devices in a hardware-independent manner. The Duet sample programs (DUET1 and DUET2) illustrate the OS/2 multimedia concept of device grouping and integrating multimedia into an application's help information. See the example in the Duet Player IPF Sample section for an example of how multimedia can be used in an application's help information.

The Duet sample programs communicate with the media control interface subsystem to control multimedia devices from an application in a device-independent manner. This concept is illustrated by the Duet samples when they play, pause, resume, stop, and change the volume of their songs. This function is implemented using the procedural interface, as opposed to the string interface described in the MCISTRNG - Media Control Interface String Test Sample

The Duet sample applications are identical except for minor software differences in how the hardware devices are controlled. DUET1 plays both parts of the duet on a streaming device—a device that streams data through the SPI subsystem of OS/2 multimedia. DUET2 groups a streaming and a non-streaming device—a device that handles data internally and does not stream data through the SPI subsystem.

The hardware differences between the Duet samples have little impact on the applications. The media drivers and stream handlers manage the hardware-dependent function.

Note: To hear the duets when you run the Duet sample programs, an audio device is required, for example, the M-Audio adapter. If you do not have an audio adapter, you can still compile and run the sample programs; however, you will not be able to play any duets or audio help.

DUET1 - Streaming Device Duet Sample

The Streaming Device Duet Sample (DUET1) illustrates the concepts of grouping two streaming devices. Each song that is played by DUET1 is recorded into two separate waveform files (instead of a single waveform file, which is the most common and efficient means to record). Think of each song as a duet, with each part of the duet stored in a separate waveform file.

Note: The DUET1 program will not execute correctly when using a Sound Blaster adapter because the adapter does not support playing two wave files simultaneously.

Program Flow

The following figure illustrates how the DUET1 sample program interfaces with the Media Device Manager (MDM) to handle the concept of grouping. Source code for DUET1 is located in the \TOOLKIT\SAMPLES\MM\DUET1 subdirectory.

                              ┌───────────────┐
                              │    DUET1      │
                              │    Sample     │
                              │    Program    │
                              └───┬───────┬───┘
                               ┌──┘  (1)  └─┐
                                           
                ┌────────────────┐          ┌────────────────┐
                │   Waveform     │          │   Waveform     │
                │     Audio      │          │     Audio      │
                │Device Context 1│   (2)    │Device Context 2│
                └────────────┬───┘          └──┬─────────────┘
                             └─┐             ┌─┘
                                            
                              ┌───────────────┐
                              │ Media Device  │
                              │    Manager    │
                              │               │
                              └───────┬───────┘
                                      │
┌────┐                                
│WAVE│                        ┌───────────────┐
│File│ ┐                      │   Waveform    │
└────┘ │  ┌─┐                 │ Audio Media   │
       └─ │M│                 │    Driver     │
          │M│                 └───────┬───────┘
       ┌─ │I│                    (3)  │
       │  │O│                          
┌────┐ │  └─┘                 ┌───────────────┐
│WAVE│ ┘                      │  Sync/Stream  │
│File│     │                  │    Manager    │
└────┘     │                  │               │
           │                  └───────────────┘
           │                               
           │       ┌────────────┘           └────────────┐
           │                                            
     ┌─────┴────────┐                (4)           ┌──────────────┐
     │  File System │            ┌─┬─┬─┬─┬─┐       │     Audio    │
     │Stream Handler├────────────┤ │ │ │ │ ├───────┤Stream Handler│
     └──────────────┘            └─┴─┴─┴─┴─┘       └──────┬───────┘
                                                             (5)
                                                   ┌──────────────┐
                                                   │   Audio DD   │
                                                   │              │
                                                   └──────┬───────┘
                                                           
                                                   ┌──────────────┐
                                                   │   Audio HW   │
                                                   │              │
                                                   └────────┐    ┌┘
                                                            └────┘

(1) The DUET1 program directly interfaces with media control interface services using the procedural interface.

Each part of the duet is played through the OS/2 multimedia system using a separate instance of a logical media device. In this case, it uses two instances of the logical waveform device, the Waveform Audio Media Driver. When the Duet Player is ready to play a song, it issues the MCI_GROUP command to the MDM to set up a group of two logical waveform devices. The MDM returns a group handle to the application, so that the application can refer to that group as a single unit (instead of having to manage each logical device separately). The MDM handles the management of the logical media devices for the application.

(2) The MDM sets up two Waveform Audio Media Drivers as a group.

(3) The Waveform Audio Media Driver handles the creation and management of the source and target stream handlers. In this example, the source stream handler is the File System Stream Handler, and the target stream handler is the Audio Stream Handler. When the Waveform Audio Media Driver receives an MCI_OPEN command from the program, it creates the stream handlers.

When you select Play, Pause, or Stop, the application issues an MCI_PLAY, MCI_PAUSE, or MCI_STOP message to the MDM. The MDM then passes this message to the appropriate media devices in the group.

(4) The media driver issues SPI functions to the Sync/Stream Manager (SSM) to process the play, pause, resume, and close messages from the application. The SSM controls the registration and activities of all stream handlers. SPI services enable media drivers to create, start, and end data streams. SPI also provides real-time services to enable stream handlers to synchronize events. The File System Stream Handler and the Audio Stream Handler are responsible for controlling the flow of application data in a continuous, real-time manner.

(5) The target stream handlers interface with the audio device driver through the inter-device-driver communication (IDC) interface. This is the interface between the stream handler and the physical device driver (PDD). The IDC interface includes Stream Handler Device (SHD) messages and device driver command (DDCMD) messages.

DUET2 - Streaming and Non-Streaming Device Duet Sample

Code for the Streaming and Non-Streaming Device Duet Sample (DUET2) is almost identical to DUET1. The difference is that DUET2 demonstrates how one of the devices in the multimedia device group can be a non-streaming device. The song in DUET2 is divided in two parts, just as the song in DUET1. However, DUET2 plays one part of the song from a CD in a CD-ROM device connected to the system. This difference in hardware is almost totally isolated from the application. There is a difference of approximately 10 lines of code between the Duet sample programs to handle the major difference in hardware configurations.

This major difference in hardware configuration is buffered from DUET2 by the media drivers. The CD Media Driver performs differently from the Waveform Audio Media Driver because it is dealing with a non-streaming device. When the CD media driver receives a media control interface message from the program (such as PLAY or STOP), it must communicate with the CD-ROM device driver through the IOCtl interface. This is the difference between a media driver that controls a streaming device and a media driver that controls a non-streaming device.

MCISPY - MCISpy Sample

The MCISpy Sample (MCISPY) monitors media control interface messages that are exchanged between applications and the OS/2 multimedia subsystem. In addition to teaching you about multimedia messages, MCISpy also serves as a debugging aid.

To begin monitoring messages and saving them in a log file:

1. Start MCISpy. 2. Select LogFile from the MCISpy menu bar. 3. Select Enable Message Logging. 4. Start the multimedia application you want to monitor.

As you interact with the application, information is displayed in the MCISpy window and written to the default log file MCISPY.LOG. MCISpy monitors both the string interface and the command message interface.

For the command message interface, the information consists of:

  • Originating process ID (PID)
  • Device ID
  • Message name
  • Message flag value
  • User parameter
  • Data

For the string interface, the information consists of the PID and the string input.

To specify a log file other than the default log file, select Open. Use the Edit functions to manage the contents of the log file.

The View menu provides views of useful information. The Installed Devices view lists the logical and physical device names and product information for each installed multimedia device. The MCI Flag Values view shows you the text string equivalents for the hexadecimal flag values that accompany the messages displayed by MCISpy during the monitoring process.

The Filter menu offers a variety of filters for the messages that are displayed in the log file. You can filter the messages by:

  • Selecting the message names you want to see.
  • Selecting the device type or open device ID of the device whose messages you want to see.
  • Disabling input from mciSendCommand, mciSendString or mdmDriverNotify functions. This choice takes precedence over any other filters in effect.

Initially no filters are in effect and therefore all messages are displayed.

Program Flow

The following diagram depicts the MCISpy application implementation model. The stub or proxy DLL replaces the true MDM.DLL, which is renamed to MCI.DLL. The proxy MDM exports the same APIs at the same ordinals as the true MDM. The proxy MDM has forwarder entries into the MCI.DLL for the API workers. That is, the proxy exports and also imports the same APIs from the true MDM.

                  ┌────────────────┐
                  │ Shared Memory  │
                  │  (Named)       │
                  ├────────────────┤                     ┌──────────────┐
 Exported APIs    │                │                     │ True MDM     │
                  │ Stub or        │                     │ containing   │
 mciSendCommand() │ Proxy          │ Forwarder entry     │ the API      │
 ─────────────────┤ MDM.DLL        ├────────────────────>┤ workers is   │
 mciSendString()  │                │ Forwarder entry     │ renamed to   │
 ─────────────────┤ Maintain Open  ├────────────────────>┤ MCI.DLL.     │
 mdmDriverNotify()│ Device Ids     │ Forwarder entry     │              │
 ─────────────────┤                ├────────────────────>┤              │
                  │ Notify Spy     │                     │              │
                  │ Application    │                     │              │
                  └────────────────┘                     └──────────────┘
                  ┌────────────────┐
                  │ Shared Memory  │
                  │  (Named)       │
                  ├────────────────┤
                  │ MCISpy         │
                  │ Sample Program │
                  └────────────────┘

MCISTRNG - Media Control Interface String Test Sample

The String Test Sample serves as a powerful testing and debugging tool that enables developers writing media drivers to control their devices at the application level. The String Test Sample illustrates how an application uses the interpretive string interface provided by the media control interface. It also illustrates how notification messages are returned from the media drivers to the application.

The media control interface of OS/2 multimedia provides the primary mechanism for application control of media devices. Applications interface with the media control interface (and thus with media devices) in two ways—through a procedural interface or through a string interface. The procedural interface (also referred to as command message interface) is used for sending messages to the media control interface from an application using the mciSendCommand function. The string interface is used for sending command language statements to the media control interface from an application using the mciSendString function.

The string interface has a few advantages over the procedural interface. First, the string interface enables you to interactively control devices with a PM or command line interface. In addition, applications that currently use script languages can integrate 'string commands' in their script languages allowing you to integrate multimedia in your applications with a very low cost and development impact. Finally, in certain programming circumstances, the string interface is also easier to use than the procedural interface. The string interface simply passes a character-string buffer to the function, in contrast to the procedural interface, which requires the setup of certain data structures.

Note: The procedural interface is illustrated in the Duet Samples.

Program Flow

The following figure illustrates the interaction between OS/2 multimedia system components and the Media Control Interface String Test Sample program. Source code is located in the \TOOLKIT\SAMPLES\MM\MCISTRNG subdirectory.

┌──────────────┐
│ String Test  │
│Sample Program│
└─────────┬────┘
          │
(4)│   (1) 
┌──┴───────────┐─── ┌──────────────┐
│ Media Device │(2) │   Command    │
│    Manager   │ ───│    Table     │
└─────────┬────┘    └──────────────┘
          │
(4)│   (3) 
┌──┴───────────┐
│ Media Driver │
│              │
└──────────────┘

(1) String Test waits for you to enter a string command. When you select Send, the program calls mciSendString to send the string command to the Media Device Manager (MDM).

(2) The MDM receives the string command and uses the command table to parse the string and convert it to the media control interface command format.

(3) The Media Device Manager passes the command to the appropriate media driver, which acts on the command.

(4) Notification messages are sent back to the application from the media device to indicate such operations as completion of a device function or the passing of device ownership from one process to another. These messages can be viewed in the Display Messages dialog box of the String Test Sample.

MMBROWSE - Image Browser Sample

The Image Browser Sample (MMBROWSE) illustrates how to use the multimedia I/O subsystem (MMIO) to install I/O procedures for various image formats and then convert these image formats to any of the supported image formats.

This sample demonstrates the various ways to install an I/O procedure:

  • On a temporary basis for an individual file.
  • On a semi-permanent basis for the duration of a process.
  • On a permanent basis for use by any process in the system.

To install an I/O procedure, you must know its four-character code. For more information on how to use the functions included in this sample program, see Multimedia I/O File Services.

MOVIE - Movie Sample

The Movie Sample (MOVIE) demonstrates device control of a software motion video device. It also illustrates how to cut, copy, paste, and delete movie data from an application. A movie can be played in an application-defined window or in the system default window provided by the software motion video subsystem. The Movie Sample program uses the string interface to interact with the media control interface layer.

Program Flow

The following figure illustrates the interaction between the Movie Sample program and the Media Device Manager (MDM). Source code for the Movie Sample is located in the \TOOLKIT\SAMPLES\MM\MOVIE subdirectory.

              ┌─────────────────┐    ┌─────────────────┐
              │     Movie       ├─── │    Initialize   │
              │     Sample      │(1) │      Open       │
              │                 │    │     Device      │
              └──┬───────────┬──┘    └─────────────────┘
  Application  (2)         (3) Default
    Window                     Window
             ┌─────────────────┐
             │     Media       │
             │     Device      │
             │    Manager      │
             └───────┬─────────┘
                    (4)
                     
             ┌─────────────────┐
             │     Digital     │
             │      Video      │
             │       MCD       │
             └─────────────────┘

(1) The Movie Sample creates a standard window with a style of CS_MOVENOTIFY for the application window during initialization. The Movie Sample also initializes and loads a movie file into memory during initialization time.

(2) If you choose to play the movie in an application window, three string commands are generated and sent to the digital video MCD. They are window, load, and put. The following list describes these commands.

window Specifies the characteristics of the application-defined window.

Note: When a window handle is selected with the window command, the digital video MCD queries the size and position of the window. If the window is visible, the digital video MCD alters the size and position of the video accordingly. However, if the window size and position is changed while the window is hidden, the digital video MCD does not note the new size and position.

load Loads the digital video file.

put Places the movie in the application-defined window.

These commands (window, load, and put) must be issued in sequence to play the movie in the application-defined window.

(3) If you choose to play the movie in a default window, the load command is generated and issued to the digital video MCD.

(4) When you select Play, the Movie Sample program calls the digital video MCD, through the Media Device Manager, to play the movie file.

If you select Edit, processing is passed to the EditTheMovie procedure which loads the movie, and sets the data format to frames. It copies the first 25 frames to the clipboard. The 25 frames are pasted four times to the end of the movie file (duplicating the first 25 frames four times). Next, the EditTheMovie procedure cuts the first 10 frames from the movie, seeks to the end of the movie, and pastes the 10 frames to the end. The cut command deletes the specified number of frames from the position the application specifies to start the cut. Once the movie is edited, selecting Play causes the edited version of the movie to play. To play the original 'unedited' movie file, exit the Movie Sample program, restart it, and select Play.

RECORDER - Audio Recorder Sample

The Audio Recorder Sample (RECORDER) illustrates the concept of recording audio through the media control interface and how to query a device to find out the recording capabilities. The sample program also illustrates how to change the audio recording and audio device properties, such as bits per sample, samples per second, input level, and input source.

Program Flow

The following figure illustrates how the Audio Recorder Sample program interfaces with the Media Device Manager (MDM). Source code for the Audio Recorder Sample is located in the \TOOLKIT\SAMPLES\MM\RECORDER subdirectory.

         ┌───────────────┐
         │ Audio Recorder│
         │    Sample     │
         └──┬────────┬───┘
           (1)      (2)
                    
       ┌─────────────────┐
       │  Media Device   │
       │   Manager       │
       └┬───┬────────┬───┘
       (1) (2)      (2)
                  
     ┌──────────┐┌──────────┐
     │Wave Audio││ Amp-Mixer│
     │   MCD    ││   MCD    │
     └──────────┘└──────────┘

(1) Upon initialization, the Audio Recorder Sample program issues an MCI_GETDEVCAPS command, with the MCI_GETDEVCAPS_EXTENDED flag set. The Audio Recorder Sample uses the device capability information that is returned to disable any options in the Audio Recorder Sample menus that do not apply to the installed audio device.

(2) When you select Record, the Audio Recorder Sample program checks all of the menu settings and sets up the device accordingly. The Audio Recorder Sample issues an MCI_SET command to the Waveform Audio Media Driver to set up the bits per sample, samples per second, and channels of the recording. The sample also issues an MCI_CONNECTOR command to the Waveform Audio Media Driver to set up the input source. It gets the device ID of the Amp-Mixer Media Driver and issues an MCI_SET command to that device to set up monitor input and input level. It also sends an MCI_SET command to the Amp-Mixer Media Driver to set the input level of the recording. Finally, the Audio Recorder Sample sends an MCI_RECORD command to the waveaudio device to begin recording.

TUNER - TV Tuner Sample

TV tuner cards allow a desktop PC to receive and display broadcasted television signals. TUNER provides an example of how to use the MCI string interface to control a tuner card.

Note: A TV tuner card (such as the WinTV Basic) is required to run the TUNER sample.

Once the application is running, the display window can be sized and a TV channel can be selected. The channel can be selected through up/down buttons or a text entry field displayed both at the bottom of the window.

A TV tuner card is handled as a digital video device by the multimedia subsystem. A typical system has one or more digital video devices, with digitalvideo01 assigned to software motion video. By default this sample opens the digitalvideo02 device. If the tuner card is not assigned to digitalvideo02 an alternate device ordinal must be provided at the command line with the format:

  /d=digitalvideo''xx''

where xx is a two digit number, padded on the left with zero.

For example:

  /d=digitalvideo03

Most TV tuner cards, such as the Hauppauge WinTV card, support several video sources. The connector number that corresponds to the tuner video source is dependent on the hardware and may not be the same for each tuner card. The connector number is not changed by this sample. Instead, it uses the default connector number set in the Multimedia Setup application.

ULTIEYES - Non-Linear Video Sample

The Non-Linear Video Sample (ULITEYES) demonstrates the use of non-linear video by displaying segments from a movie clip in response to input from the mouse. Whenever the mouse changes position, ULTIEYES calculates the angle of the mouse pointer to the center of the ULTIEYES video window. It then displays a frame from the movie ULTIEYES.AVI that corresponds to the position of the mouse pointer. As the mouse pointer is moved around the desk top, the eyes shown in the video window appear to follow the mouse. The movie file also contains segments of the eyes winking and blinking. ULTIEYES shows these segments when it detects a mouse button 1 click on the left side, center or right side of the video window.

Creating a Movie Clip

If you have Video IN and one of the supported video capture cards, you can easily replace ULTIEYES.AVI with a movie clip of your own eyes. Make the following updates in the Video IN Recorder Settings notebook before you record the movie:

1. Set the reference frame rate to 1. 2. Set the audio to Record no audio.

After you record the movie, you are ready to select the frames the ULTIEYES program will display when the mouse pointer is at various positions in relation to ULTIEYES: East, East by Northeast, Northeast, and so on.

1. Set the time format of the Video IN Recorder to frames. 2. Step through the movie frame by frame. 3. Jot down the frame number for each position on the compass. Also note the beginning and ending frames of the segments for the left and right winks and the blink. (Note that video segments must be at least one second in length.) 4. Create an ASCII file that contains 25 lines in the following format:

The first line in the file is the name of the AVI movie file.

The next 24 lines comprise the frame number table (0-23). A description of the table contents is shown in the following figure. Letter characters on each line indicate the direction of the gaze associated with that particular line number. For example, in the frame on line 12 the eyes should be gazing south by southwest. To see what an actual frame table looks like, open the ULTIEYES.EYE file.

 0      - Eyes turned inward frame.
 1      - E
 2      - ENE
 3      - NE
 4      - NNE
 5      - N
 6      - NNW
 7      - NW
 8      - WNW
 9      - W
10      - WSW
11      - SW
12      - SSW
13      - S
14      - SSE
15      - SE
16      - ESE
17      - E (again)
18-19   - Right-eye wink sequence (left side of video)
20-21   - Left-eye wink sequence (right side of video)
22-23   - Blink sequence

To start your version of ULTIEYES, enter:

ULTIEYES filename

where filename is the name of the ASCII file you created.