OS/2 Multimedia Chapter – Media Control Interface

by Maria Ingold


To produce sound, display images, or record a movie, a multimedia application needs to communicate with hardware devices such as CD-ROMs, audio cards, or video cards. The application has to behave consistently regardless of the associated hardware, yet at the same time take advantage of special features if they are available. The Media Control Interface (MCI) APIs allow an application to generically communicate an action to a type of device, as well as to request information about device-specific capabilities. These APIs make the application both more portable and more extensible as there is no need to understand how each device works.

As shown in Figure X.4, the Media Control Interface is composed of three levels: the command interface, the Media Device Manager (MDM), and the Media Control Drivers (MCD). The command interface APIs allow an application to send its requests to the MCI in a device independent manner. The requests are interpreted by the Media Device Manager and are passed on to the appropriate Media Control Driver if the Media Device Manager ascertains that the appropriate resources are available. The Media Control Driver then communicates with the hardware via device-type and device-specific messages. Looking back at Figures X.2 and X.3, these messages may either go directly to the physical device driver attached to the hardware, as with the videodisc driver, or through another subsystem such as the Synchronization Streaming Manager, or the Multimedia I/O subsystem. A Media Control Driver uses the Multimedia I/O subsystem to retrieve the data from a file or memory and uses the Synchronization Streaming Manager to stream the data from one part of the system to another.

Media Control Interface Architecture

Figure X.4 Media Control Interface Architecture

X.6.1 Communicating with the Media Control Interface

The command layer is composed of the command message interface and the command string interface. Both support synchronous and asynchronous execution by respectively specifying wait or notify. For example, use wait when opening a device so that another application does not attempt to simultaneously open the same device. The notify instruction should be used with commands that take a long time to execute or can be interrupted, such as the play command.

While either the message or string interface can typically be used, each has its specific uses and advantages over the other.

The message, or procedural, interface requires C programming constructs such as messages, flags, and pointers to data structures. These are sent through the Media Device Manager to the appropriate Media Control Driver using the mciSendCommand function. The message interface is used for operations that require the return of a complex data structure, such as a CD-ROM table of contents (TOC). This interface also enables the application to identify multiple devices so that connections can be established between them (such as connecting the waveaudio media device and the ampmixer device to set the volume for playback of an audio file).

The command string interface resembles English sentences more than C code. This interface is useful for simple and quick development as seen in Figure X.5 on page X. It also makes it easy for authoring languages like REXX to take advantage of the Media Control Interface. Command strings are passed via the mciSendString function to Media Device Manager interface layer where they are converted into their equivalent command messages using a case insensitive parser. The table driven parser uses either the default OS/2 Multimedia command tables, or a custom table provided by a media driver which contains commands specific to that device. The Media Device Manager first scans the custom device-specific command tables, then the device-type tables, and finally the system default table.

X.6.2 Media Control Drivers

Once the string is resolved into a command message, the message is passed to either the MCI system, or to a Media Control Driver. Media Control Drivers are dynamic link libraries (DLLs) that implement the function of a logical media device. Each Media Control Driver handles the messages specific to the device it supports. The Media Control Driver provides device independence to the application developer by hiding all the implementation details specific to a particular device. As a result, the application developer can send generic commands, such as play a digital audio file, without being concerned as to what sound adapter is being used. The Media Control Driver receives commands through the mciDriverEntry entry point. The Media Control Drivers process and direct the commands received from the Media Device Manager to another subsystem or to a physical device driver interface. The method by which these requested command messages are communicated to the hardware device drivers is then entirely up to the Media Control Driver.

Media Control Drivers support both streaming and non-streaming devices. While both types of devices have commands passed to them the same way, they handle these commands differently. A streaming device uses the synchronization and streaming functionalities of the Stream Protocol Interface (SPI) layer to move data from a source location to a target location. The data is streamed in real time from one device to another via buffers. As shown previously in Figure X.3, when a digital audio file is played, the audio is streamed from a file to the waveform audio Media Control Driver. This Media Control Driver then uses the SPI layer to buffer data from the source waveaudio file to the target audio adapter. The data is retrieved from the file using the Multimedia I/O services.

A non-streaming device streams data within a physical device. This type of device does not require buffered I/O because both the source and destination of the data are internal to the device. Non-streaming devices use IOCtls to process commands. For example, when a CD audio MCD receives a command, such as play, it sends the appropriate IOCtl to the CD-ROM device to perform the action. The hardware then retrieves the digital information off the compact disc and translates it into an analog signal so that it can be played out of the audio jack.

Multimedia data often has to be transferred from one device to another. Jacks for line-in, line-out, speaker, and microphone are typically used to connect physical devices together. These types of connectors are also represented in software so that data can be transferred between logical devices. An application can query which connectors are supported by a logical device. The application can then control which connectors the data flows through. An example of this is determining whether to send audio output through line out or through the speakers.

Another type of connector, referred to as a stream connector, represents the flow of information from one device to another. An example of this is a wave stream where the digital audio is streamed from a file or another device, such as a CD-ROM, into an audio adapter. This flow of information from one device connector to a compatible connector on another device is called a connection. For a connection to exist, both device connector types must be compatible. This connection can be made externally, as by the wire attachment of speakers to an audio card, or internally, for the transfer of digital information.

Unless a media driver specifies otherwise, device connections are automatically established when a media device is opened. The default connection is established during the installation of the media driver and can be reestablished using the MCI_DEFAULT_CONNECTION command. An open media device can open and connect to other media devices. This is necessary if the media device requires features provided by another device in order to complete the application specified function. For example, when a waveaudio device is opened to play a digital audio file, it opens and connects to an amplifier-mixer device to produce the sound and to set the volume.

X.6.3 Media Device Manager

The Media Device Manager’s primary job is to manage logical media devices, handle device and multimedia system commands, allow an application to synchronize its use of the Media Control Drivers, and to enable sharing of the Media Control Drivers between applications. Since MDM provides device independence, saving and restoring the device states remains transparent to the application.

To better understand how the Media Control Interface works, take a look at the following example. This example plays a digital audio file, rewinds it, and plays it again. A position advise is received every 500 milliseconds worth of data. This could be used for updating a position slider, but is not necessary for the rest of the sample. The following strings would be sent using the mciSendString interface. These strings must be composed of the command or action to be performed, followed by the device name or device alias, and then any additional arguments.

  open waveaudio alias w shareable wait
  load w sound.wav wait
  set w time format ms wait
  setpositionadvise w on every 500 wait
  play w notify
  seek w to 0 wait
  play w notify
  close w wait

Figure X.5 Playing a Digital Audio File

The first step is to open the appropriate logical device, such as the waveaudio device shown here. A logical device, also called a media device, is an abstract representation of the functions provided by a hardware device, software emulation, or a combination of both. As an example, a CD-ROM drive may correspond directly to a CD audio logical device, while an audio card may be logically represented as an amplifier-mixer, a MIDI player, and a wave audio player and recorder. The actual implementation of the media device is irrelevant to the application, because the command message and command string interfaces refer to this device function by its logical name. The names corresponding to the logical device types currently managed by the Media Device Manager are listed in Table X.6. Since OS/2 Multimedia is extendible, media devices can easily be added. Specific devices that are associated with a logical device type are delineated by following the name string with a 01, 02, etc. For example, digitalvideo01 may allow video playback, while digitalvideo02 may permit video recording.

Logical Device Type
Digital video
MIDI sequencer
Video disc
Waveform audio

Table X.6 Logical Device Types

When a logical device is opened for use, using either the MCI_OPEN flag and MCI_OPEN_PARMS structure with the mciSendCommand or open command with the mciSendString, it is assigned a device ID. The device ID differentiates each device context’s usage of a logical device. Subsequent calls to that logical device require the device ID. The mciSendCommand requires this device ID as its first parameter. When a device is opened using the mciSendString, the logical device can be given an alias, or alternate name. An alias is typically used to simplify the string interface’s specification of subsequent commands to control the device. The alias is valid only within the process that opened the device context, and is only used by the string interface. If calls to both mciSendString and mciSendCommand are used within an application, the device ID needed for the mciSendCommand can be obtained by calling mciGetDeviceID with the alias name.

Device commands used by the MCD are categorized as required, basic, and device-specific. Required commands are actions that are common to all media devices. This includes actions such as opening and closing a device. Basic commands are generic enough that all device types should understand them. An example of this is the play command. The commands can be made more specific by modifying the parameters. Specific command messages apply only to an individual device. Querying a table of contents, for example, is specific to a CD ROM, and setting a playback window is necessary only for the display of video. Command messages may include flags, parameters, and data structure fields.

System commands are interpreted by the MDM but are not passed on to any of the media devices. These messages include calls to adjust the master volume, group devices, acquire and release a device, and perform connector manipulation.

System values provide information such as the current master volume level, whether closed captioning support is enabled or disabled, the location of the multimedia workpath for temporary files, and whether headphones or speakers are enabled within the system. These values are typically set during multimedia setup, but can also be set using mciSetSysValue. The current state of a system value may be retrieved by calling mciQuerySysValue.

X.6.3.1 Device Resource Management

The Media Device Manager uses device resource management to fully exploit the resources provided by the multimedia devices. When a device is used, each device instance can specify how it wants to share its available resources. By specifying the shareable flag, as shown in the first line of Figure X.5, the device is allowed to be fully shareable. Shareable hardware can be used sequentially, as in the case of a CD-ROM, or it can be used in either an unlimited or limited form in parallel. Unlimited sharing means that use of the device is restricted only by the resource limits of the system. Limited sharing is where the hardware has only a finite number of available resources. An audio card, for example, may provide only two audio channels. One stereo audio file could access the channels, or two mono files could concurrently play back using the same sound card. If the hardware’s resources are exceeded, as in the case of playback of two stereo files, the Media Device Manager would have to suspend the background application’s use of the device, and allocate the resources to the foreground application. This is achieved by acquiring and releasing devices. When a device is acquired, the window procedure of the application that is using the device receives a MM_MCIPASSDEVICE message telling it to which device it is losing access. The device instance using the device then goes inactive, and the device instance acquiring the device becomes active.

A device can also be acquired exclusively. By specifying the exclusive flag, the entire media device is held for use by that device instance. This means that no other device instances can acquire use of the device. Sometimes an action such as a record or set requires that the device instance not be made inactive at that time. Use the exclusive instance flag to accomplish this.

X.6.4 Synchronization Using the Media Control Interface

The Media Control Interface performs synchronization through device grouping, setting cuepoints and setting position advises. Device grouping allows an OS/2 Multimedia application to control more than one logical device at a time. These groups can be in piecemeal or nopiecemeal mode. When a group is created, several device instances are tied together so that each message sent to the group is broadcast to all of the device instances within that group. In piecemeal mode the states of the all of the device instances can be independent of each other, i.e. some devices can be in active use while others may be inactive. In nopiecemeal mode all of the devices must be either inactive or active. If, for example, all the devices in the group are active, and one of them goes inactive, then they all become inactive. Since a device instance is created when the logical device is opened, all the devices must have been previously opened, but they can be in any mode such as playing, stopped, or paused. When a device is closed it is removed from the group. Closing all the devices in the group or deleting the grouping ends the group association. Unless the master instance is lost, the group can be made active again.

A cuepoint is set at a discrete location or time position in the playback or recording of a media device. When a media device finds a cuepoint it notifies the application so that it can then take appropriate action. For example, the application may display an image when a cuepoint is reached during the playback of an audio file. Only one cuepoint can be set at a specified location, but this point can be at any valid location within the media, regardless of the current position. Once the cuepoint is encountered it remains set for the duration of the device context, or until a new file is loaded. To set a cuepoint use the setcuepoint command. Based on the window handle associated with the cuepoint message, the appropriate application receives a MM_MCICUEPOINT notification when the cuepoint is reached.

As shown in lines three and four of Figure X.5, notifications can also be set at periodic time intervals. These periodic notifications are referred to as position advises. A position advise could be used to update a slider that indicates the current media position. This notification is typically generated only during playback and recording, but can sometimes be generated during seeking as well. Only one periodic frequency can be set for the context of a device. Use the setpositionadvise command to set the frequency of the message. The application will then receive a MM_MCIPOSITIONCHANGE message at the interval specified.

X.6.5 MCI Functions

For a list of the MCI functions provided for use by applications see Table X.7. In addition to these there are five calls provided for use by REXX programs, and three high level APIs that provided a simplified interface to common command sequences.

The REXX commands include mciRxSendString, mciRxGetErrorString, and mciRxGetDeviceID which respectively provide access to the mciSendString, mciGetErrorString, and mciGetDeviceID APIs. These REXX commands are bounded by calls to mciRxInit and mciRxExit. Calls to these commands should specify the wait keyword, or use nothing. This is because when the notify keyword is used a notification is sent to a window procedure. While PMREXX has a window procedure, REXX does not. By not specifying either wait or notify, an asynchronous call is issued without return notification. So that other device contexts can share the device resources, the devices should be opened as shareable and acquired using exclusive instance.

The high level APIs provided are mciPlayFile, mciPlayResource, and mciRecordAudioFile. The mciPlayFile uses the default audio or video device to playback a file. This playback may be done either synchronously or asynchronously by using wait or notify. The mciPlayResource provides the same functionality, but takes the data file from a program resource. The mciRecordAudioFile provides a simplified audio recorder window to record a file. The recording is only done in 11.025 kHz, mono, PCM format.

MCI Function Description
mciSendCommand Sends a command to a media device using flags and structures
mciSendString Sends a command to a media device using string buffers
mciGetDeviceID Gets the device ID corresponding to the alias of a device
mciSetSysValue Sets or alters system wide values
mciQuerySysValue Queries OS/2 multimedia system values
mciGetErrorString Fills the caller’s buffer with the error code string

Table X.7 MCI Functions