A command table consists of command lists, which define to the MDM parser how to parse certain commands. For example, illustrates a command list for MCI_SEEK:
"seek", MCI_SEEK, 0, MCI_COMMAND_HEAD, "notify", MCI_NOTIFY, MCI_FLAG, "wait", MCI_WAIT, MCI_FLAG, "to start", MCI_TO_START, MCI_FLAG, "to end", MCI_TO_END, MCI_FLAG, "to", MCI_TO, MCI_INTEGER, "", 0L, MCI_END_COMMAND,
The SEEK command list tells the parser how to create the associated data structure for the pParam2 parameter of mciSendCommand to point to, when it finds "seek" in the pszCommand parameter of mciSendString.
Notice that each line is broken into a null-terminated string and two ULONGs. The ULONG following "seek" is composed of two parts; MCI_SEEK and 0. The command message (in this case, MCI_SEEK) is a USHORT, and therefore we need another USHORT as a filler. The MCI_COMMAND_HEAD Line_type tells MDM that the first ULONG (actually, the first USHORT) contains the usMessage parameter for mciDriverEntry.
If the line type of a line is MCI_FLAG, then the first ULONG for that line is ORed together with all the other ULONGs for MCI_FLAG lines, to form the ulParam1 parameter.
The string parser makes two passes through the command list. The first pass is to determine the size of the structure to allocate for the command. The second pass parses the command string, fills in the command structure, and creates a ulParam1 flag.
Each command is composed of a number of ULONGs. All commands have a minimum of one ULONG for the hwndCallback field. The parser provides this ULONG automatically. The remaining size of the command structure is based on the Line_types used for the command.
If the line type of a line is MCI_INTEGER, then the text following string S, where S is the null-terminated string in the command line, in pszCommand is an integer and should be put in the corresponding ULONG in the structure of ULONGs that pParam2 points to.
If the line type is MCI_STRING, then the text following string S in pszCommand is a string, and a pointer to this string will be put in the corresponding ULONG in the structure of ULONGs that pParam2 points to.
Finally, if the line type is MCI_RETURN, then the first ULONG of that line specifies the value that is to be returned through the data structure pointed to by pParam2.
The pParam2 data structure is laid out based on the command list. The first ULONG is always hwndCallback. The next one or two ULONGs represent MCI_RETURN:
"status\0", MCI_STATUS, 0, MCI_COMMAND_HEAD, "\0", MCI_INTEGER, MCI_RETURN, "notify\0", MCI_NOTIFY, MCI_FLAG, "wait\0", MCI_WAIT, MCI_FLAG, "\0", MCI_STATUS_ITEM, MCI_CONSTANT, "mode\0", MCI_STATUS_MODE, MCI_INTEGER, "ready\0", MCI_STATUS_READY, MCI_INTEGER, "current track\0", MCI_STATUS_CURRENT_TRACK, MCI_INTEGER, "length\0", MCI_STATUS_LENGTH, MCI_INTEGER, "number of tracks\0", MCI_STATUS_NUMBER_OF_TRACKS, MCI_INTEGER, "position\0", MCI_STATUS_POSITION, MCI_INTEGER, "position in track\0", MCI_STATUS_POSITION_IN_TRACK, MCI_INTEGER, "time format\0", MCI_STATUS_TIME_FORMAT, MCI_INTEGER, "speed format\0", MCI_STATUS_SPEED_FORMAT, MCI_INTEGER, "\0", 0L, MCI_END_CONSTANT, "track\0", MCI_TRACK, MCI_INTEGER, "\0", 0L, MCI_END_COMMAND,
The string parser produces the pParam2 parameter shown in the following figure.
{ HWND hwndCallback; ULONG ulReturn; ULONG ulItem; ULONG ulTrack; }
Notice that the MCI_CONSTANT block is defined in order to fill in the ulItem field of the status structure. If the keyword field on the MCI_CONSTANT line is "\0" or NULL, then the parser is looking for any keyword defined in the block, and the first ULONG of the matching keyword is put in the ulItem field. If the keyword on the MCI_CONSTANT line is not "\0" then the parser looks for that keyword and ORs the first ULONG of the MCI_CONSTANT line with ulParam1. The parser continues to look for a keyword match in the constant block. For example:
"capability", MCI_GETDEVCAPS, 0, MCI_COMMAND_HEAD, "", MCI_PREROLL_TYPE_RETURN, 0, MCI_RETURN_TYPE, "deterministic", MCI_PREROLL_DETERMINISTIC, MCI_RETURN_TYPE_STRING, "notified" MCI_PREROLL_NOTIFIED, MCI_RETURN_TYPE_STRING, "none", MCI_PREROLL_NONE, MCI_RETURN_TYPE_STRING, "none", 0L, MCI_END_RETURN_TYPE, "", MCI_TRUE_FALSE_RETURN, 0, MCI_RETURN_TYPE, "TRUE", 1L, MCI_RETURN_TYPE_STRING, "FALSE", 0L, MCI_RETURN_TYPE_STRING, "", 0L, MCI_END_RETURN_TYPE, "", MCI_DEVICENAME_RETURN, 0, MCI_RETURN_TYPE, "Videotape", MCI_DEVTYPE_VIDEOTAPE, 0, MCI_RETURN_TYPE_STRING, "Videodisc", MCI_DEVTYPE_VIDEODISC, 0, MCI_RETURN_TYPE_STRING, "CDaudio", MCI_DEVTYPE_CD_AUDIO, 0, MCI_RETURN_TYPE_STRING, "DAT", MCI_DEVTYPE_DAT, 0, MCI_RETURN_TYPE_STRING, "Audiotape", MCI_DEVTYPE_AUDIO_TAPE, 0, MCI_RETURN_TYPE_STRING, "Other", MCI_DEVTYPE_OTHER, 0, MCI_RETURN_TYPE_STRING, "Waveaudio", MCI_DEVTYPE_WAVEFORM_AUDIO, 0, MCI_RETURN_TYPE_STRING, "Sequencer", MCI_DEVTYPE_SEQUENCER, 0, MCI_RETURN_TYPE_STRING, "Ampmix", MCI_DEVTYPE_AUDIO_AMPMIX, 0, MCI_RETURN_TYPE_STRING, "Overlay", MCI_DEVTYPE_OVERLAY, 0, MCI_RETURN_TYPE_STRING, "Digitalvideo", MCI_DEVTYPE_DIGITAL_VIDEO, 0, MCI_RETURN_TYPE_STRING, "Speaker", MCI_DEVTYPE_SPEAKER, 0, MCI_RETURN_TYPE_STRING, "Headphone", MCI_DEVTYPE_HEADPHONE, 0, MCI_RETURN_TYPE_STRING, "Microphone", MCI_DEVTYPE_MICROPHONE, 0, MCI_RETURN_TYPE_STRING, "Monitor", MCI_DEVTYPE_MONITOR, 0, MCI_RETURN_TYPE_STRING, "CDXA", MCI_DEVTYPE_CDXA, 0, MCI_RETURN_TYPE_STRING, "", 0L, MCI_END_RETURN_TYPE, "", MCI_INTEGER, MCI_RETURN, "notify", MCI_NOTIFY, MCI_FLAG, "wait", MCI_WAIT, MCI_FLAG, "", MCI_GETDEVCAPS_ITEM, MCI_CONSTANT, "can record", MCI_GETDEVCAPS_CAN_RECORD, MCI_INTEGER, "can insert", MCI_GETDEVCAPS_CAN_RECORD_INSERT, MCI_INTEGER, "has audio", MCI_GETDEVCAPS_HAS_AUDIO, MCI_INTEGER, "has video", MCI_GETDEVCAPS_HAS_VIDEO, MCI_INTEGER, "can eject", MCI_GETDEVCAPS_CAN_EJECT, MCI_INTEGER, "can play", MCI_GETDEVCAPS_CAN_PLAY, MCI_INTEGER, "can save", MCI_GETDEVCAPS_CAN_SAVE, MCI_INTEGER, "uses files", MCI_GETDEVCAPS_USES_FILES, MCI_INTEGER, "compound device", MCI_GETDEVCAPS_USES_FILES, MCI_INTEGER, "can lockeject", MCI_GETDEVCAPS_CAN_LOCKEJECT, MCI_INTEGER, "can setvolume", MCI_GETDEVCAPS_CAN_SETVOLUME, MCI_INTEGER, "preroll type", MCI_GETDEVCAPS_PREROLL_TYPE, MCI_INTEGER, "preroll time", MCI_GETDEVCAPS_PREROLL_TIME, MCI_INTEGER, "device type", MCI_GETDEVCAPS_DEVICE_TYPE, MCI_INTEGER, "can stream", MCI_GETDEVCAPS_CAN_STREAM, MCI_INTEGER, "can process internal",MCI_GETDEVCAPS_CAN_PROCESS_INTERNAL, MCI_INTEGER, "", 0L, MCI_END_CONSTANT, "message", MCI_GETDEVCAPS_MESSAGE, MCI_CONSTANT, "acquire", MCI_ACQUIREDEVICE, 0, MCI_INTEGER, "release", MCI_RELEASEDEVICE, 0, MCI_INTEGER, "open", MCI_OPEN, 0, MCI_INTEGER, "close", MCI_CLOSE, 0, MCI_INTEGER, "escape", MCI_ESCAPE, 0, MCI_INTEGER, "play", MCI_PLAY, 0, MCI_INTEGER, "seek", MCI_SEEK, 0, MCI_INTEGER, "stop", MCI_STOP, 0, MCI_INTEGER, "pause", MCI_PAUSE, 0, MCI_INTEGER, "info", MCI_INFO, 0, MCI_INTEGER, "capability", MCI_GETDEVCAPS, 0, MCI_INTEGER, "status", MCI_STATUS, 0, MCI_INTEGER, "spin", MCI_SPIN, 0, MCI_INTEGER, "set", MCI_SET, 0, MCI_INTEGER, "step", MCI_STEP, 0, MCI_INTEGER, "record", MCI_RECORD, 0, MCI_INTEGER, "sysinfo", MCI_SYSINFO, 0, MCI_INTEGER, "save", MCI_SAVE, 0, MCI_INTEGER, "cue", MCI_CUE, 0, MCI_INTEGER, "update", MCI_UPDATE, 0, MCI_INTEGER, "setcuepoint", MCI_SET_CUEPOINT, 0, MCI_INTEGER, "setpositionadvise", MCI_SET_POSITION_ADVISE, 0, MCI_INTEGER, "setsyncoffset", MCI_SET_SYNC_OFFSET, 0, MCI_INTEGER, "load", MCI_LOAD, 0, MCI_INTEGER, "masteraudio", MCI_MASTERAUDIO, 0, MCI_INTEGER, "gettoc", MCI_GETTOC, 0, MCI_INTEGER, "connector", MCI_CONNECTOR, 0, MCI_INTEGER, "resume", MCI_RESUME, 0, MCI_INTEGER, "", 0L, MCI_END_CONSTANT, "", 0L, MCI_END_COMMAND,
The pParam2 parameter would look like:
{ ULONG hwndCallback; ULONG ulReturn; ULONG ulltem; ULONG ulMessage; }
Notice the second constant block with the keyword "message". The parser would be looking for something like "message open". This constant block would OR the MCI_GETDEVCAPS_MESSAGE with the ulParam1 parameter and put the value MCI_OPEN in the ulMessage field.
The multimedia string parser also supports one default INTEGER and STRING value. The constants MCI_DEFAULT_INTEGER and MCI_DEFAULT_STRING are used by the string parser to locate unknown keywords. For example, if a command needed a file name as its only parameter, then the following line could be used in the command table.
"\0", MCI_FILENAME, MCI_DEFAULT_STRING,
This item takes up a ULONG in the structure, just as in MCI_STRING.
Support for device-specific command tables is provided by the multimedia installation application. When a device is installed, one of the parameters to the install process is the command table (resource DLL). The required and device-type command tables are provided by the system.