MCI的主要特点是其设备独立性。通过设备驱动程序,MCI提供了与设备无关的虚拟接口。
多媒体应用程序
||
\/
MCI命令
||
\/
MCI设备驱动程序
||
\/
多媒体设备
MCI的核心是MCI的设备驱动程序,它用于解释和执行MCI的命令,可分成如下三类:
直接控制媒体设备硬件,如CD音乐、影碟机
间接控制目标设备,通过低层MMAPI间接控制,如MIDI、WAV
提供DLL高层接口,如AVI/MPEG影片播放器
12.3.1 MCI设备
MCI设备可分为如下两种类型:
简单设备——不需要提供数据文件,如CD音乐、激光视盘机
复合设备——需要提供数据文件,如MIDI音序器(.MID)、波形音频设备(.WAV)、影片播放器(.AVI/.MPG)
每类MCI设备都有对应的命令集,但也有若干同类MCI驱动程序共用同一命令集,为了区分不同的驱动程序,MCI引入设备名:(按字母序排列)
animation——动画播放设备
cdaudio——CD音乐播放设备
dat——数字音频磁带机(DAT = Digital Audio Tape数字录音带)
digitalvideo——数字视频(不基于GUI)
mmmovie——多媒体影片播放设备
other——未定义的MCI设备(扩展用)
overlay——窗口中的模拟视频接口(基于GUI)
scanner——图像扫描仪
sequencer——MIDI音序器
vcr——盒式磁带录像机(VCR = Video Cassette Recorder)
videodisc——影碟机
waveaudio——波形音频设备
这些设备名所对应的设备驱动程序在Win32/64的注册表或老版本Windows的win.ini中定义。如win.ini的mci段:
[mci]
cdaudio=mcicda.drv
waveaudio=mciwave.drv
sequencer=mciseq.drv
mmmovie=mcimmp.drv
12.3.2 接口、函数与命令
多媒体应用程序通过发送命令来控制多媒体设备,MCI有串和消息两种命令接口方式。这些命令接口,又由若干MCI函数来具体实现。
接口
应用程序通过向MCI设备发送命令来控制它,这种命令有两种接口方式:(功能等价)
命令串方式——用近似英语的句法与MCI设备通信,直观、面向用户。是一种文本形式的接口,常用于VB等可视化编程平台和ToolBook等多媒体著作工具。如
mciExcute(L"play cdaudio from 2 to 5");
命令消息方式——利用消息和数据结构与MCI设备通信,快速、面向程序员。常用于C/C++语言的应用程序,以直接控制多媒体设备。如:
MCI_PLAY_PARMS playParms;
playParms.dwFrom = MCI_MAKE_TMSF(2, 0, 0, 0);
playParms.dwTo = MCI_MAKE_TMSF(6, 0, 0, 0);
mciSendCommand(wDevID, MCI_PLAY, MCI_FROM | MCI_TO,
(DWORD)(LPVOID)&playParms);
函数
MCI函数中,有些只适用于一种接口方式,有些则两种接口都可以用。
1)仅命令串方式
只适用于命令串接口方式的有下列2个函数:(命令串中不区分大小写)
mciSendString(发送命令串),函数原型为:
MCIERROR mciSendString( // 出错返回非零值(错误代码)
// 可用mciGetErrorString获得错误的文本描述
LPCTSTR lpszCommand, // 指向以null结尾的命令字符串:”命令 设备[ 参数]”
LPTSTR lpszReturnString,// 指向接收返回信息的缓冲区,为NULL时不返回信息
UINT cchReturn, // 上述缓冲区的大小
HANDLE hwndCallback // 在命令串中含notify时,它指定一个回调窗口的句柄
// 一般为NULL
);
如:mciSendString(L"open sample.wav type waveaudio alias wave", NULL, 0, NULL);
mciExcute(执行)是mciSendString的简化形式:
BOOL mciExcute(LPCTSTR lpszCommand); // 成功返回TRUE
该函数只有Win16支持,Win32不支持,可自写一函数实现:
BOOL mciExcute(LPCTSTR lpszCommand) {
if (mciSendString(lpszCommand, NULL, 0, NULL)) return FALSE;
return TRUE;
}
如:mciExcute(L"open sample.wav type waveaudio alias wave");
2)仅命令消息方式
只适用于命令消息接口方式的只有一个函数:
mciSendCommand(发送命令),函数原型为:
MCIERROR mciSendCommand( // 出错返回非零值(低字错误代码,高字驱动程序ID)
// 也可用mciGetErrorString获得错误的文本描述
MCIDEVICEID IDDevice, // 接收命令消息的MCI设备ID
// 对MCI_OPEN消息为NULL
UINT uMsg, // 命令消息
DWORD fdwCommand, // 命令消息的附加标志
DWORD dwParam // 命令消息参数的结构指针(可统一函数形式)
);
如:
MCI_OPEN_PARMS openParms;
openParms.lpstrDeviceType = L"waveaudio";
openParms.lpstrElementName = L"sample.wav";
openParms.lpstrAlias = L"wave";
mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT
| MCI_OPEN_ALIAS, (DWORD)(LPVOID)&playParms);
MCIDEVICEID wDevID = openParms.wDeviceID;
3)两种接口方式
两种接口方式都支持的函数有五个:
mciGetErrorString(获得出错文本串)
BOOL mciGetErrorString( // 成功返回TRUE
DWORD fdwError, // 由mciSendString或mciSendCommand返回的错误代码
LPTSTR lpszErrorText, // 指向接收返回错误信息的文本缓冲区
UINT cchErrorText // 上述缓冲区的长度
);
如:
MCIERROR err = mciSendString(L"open sample.wav type waveaudio alias wave",
NULL, 0, NULL);
if (err) {
wchar_t errStr[256];
if (mciGetErrorString(err, errStr, 256)) MessageBox(errStr, L"Error");
}
mciGetDeviceID(获得设备ID),函数原型为:
MCIDEVICEID mciGetDeviceID( // 出错返回非零
LPCTSTR lpszDevice // 已经打开的设备[别]名
);
如:
wDevID = mciGetDeviceID(L"waveaudio");
或
wDevID = mciGetDeviceID(L"wave");
mciSetYieldProc(设置等待时调用的过程)
UINT mciSetYieldProc(// 成功返回非零值
MCIDEVICEID IDDevice, // 指定设备ID
YIELDPROC yp, // 等待时调用的过程
DWORD dwYieldData // 传送给过程的参数
);
mciGetYieldProc(获得等待时调用的过程)
YIELDPROC mciGetYieldProc( // 成功返回回调函数,失败返回NULL
MCIDEVICEID IDDevice, // 被监控的MCI设备的ID
LPDWORD lpdwYieldData // 指向传送给过程的参数之缓冲区,可为NULL
);
mciGetCreatorTask(获取创建任务)
HANDLE mciGetCreatorTask( // 成功返回创建指定设备的任务句柄,失败返回NULL
MCIDEVICEID IDDevice // 已经打开的设备ID
);
其中,后三个函数少用。
命令
MCI的命令很多,可以分为如下四类:
系统命令——直接由MCI系统解释和处理,不传送到MCI设备。如break或MCI_BREAK
通用命令——所有MCI设备都支持的命令。如open或MCI_OPEN
可选命令——MCI设备可选择使用的命令。如play或MCI_PLAY
专用命令——为某类MCI设备[集]专有。如list或MCI_LIST(DV/VCR)
前三类中部分命令参见表12-5:
类型 消息 串 说明
系统 MCI_BREAK break 为指定MCI设备设置终止键
系统MCI_SOUND sound 播放Windows指定的系统声音
系统MCI_SYSINFO sysinfo 返回有关MCI设备的信息
通用 MCI_CLOSE close 关闭MCI设备
通用MCI_GETDEVCAPS getdevcaps 获得MCI设备的性能参数
通用MCI_INFO info 获得MCI设备的有关信息
通用MCI_OPEN open 打开(初始化)MCI设备
通用MCI_STATUS status 返回MCI设备的状态信息
可选 MCI_LOAD load 从文件中加载数据
可选MCI_PAUSE pause 暂停播放/记录
可选MCI_PLAY play 开始播放数据
可选MCI_RECORD record 开始记录数据
可选MCI_RESUME resume 重新开始播放/记录
可选MCI_SAVE save 保存数据到文件
可选MCI_SEEK seek 改变当前位置
可选MCI_SET set 改变控制设置
可选MCI_STOP stop 停止播放/记录
标志 MCI_WAIT wait MCI命令执行完后才返回
标志MCI_NOTIFY notify MCI命令执行完后向应用程序发送MM_MCINOTIFY消息
注:接收MM_MCINOTIFY消息的窗口句柄由mciSendString的最后一个输入参数指定,或由mciSendCommand的最后一个输入参数——MCIDEVICEID结构的第一个域指定。
附加标志与参数结构
复杂的命令一般都有附加标志,并需要设置相应数据结构。如打开命令MCI_OPEN消息的附加标志见表12-6(可以位或|)
=========================================
标志 含义(在MCI_OPEN_PARMS结构的)
===========================================
MCI_OPEN_ALIAS lpstrAlias域指定了别名
MCI_OPEN_ELEMENT lpstrElementName域指定了元素(文件)名
MCI_OPEN_SHAREABLE 按共享方式打开MCI设备
MCI_OPEN_TYPE lpstrDeviceType域指定了设备类型
MCI_OPEN_TYPE_ID wDeviceID域指定了设备类型的ID
====================================================
其中,结构MCI_OPEN_PARMS的定义为:
typedef struct {
DWORD dwCallback;
MCIDEVICEID wDeviceID;
LPCSTR lpstrDeviceType;
LPCSTR lpstrElementName;
LPCSTR lpstrAlias;
} MCI_OPEN_PARMS;
12.3.3 编程
下面以播放CD音乐与波形音频文件为例,介绍简单与复杂MCI设备的多媒体编程。
准备
为了使用MCI编程,必须包含多媒体头文件:
#include
并在项目属性中添加对多媒体库winmm.lib链接。
命令串
1)CD
wchar_t buf[256];
MCIERROR err = mciSendString(L"open cdaudio alias cd", NULL, 0, NULL); // 打开CD
if (err) {
if (mciGetErrorString(err, buf, 256))
MessageBox(buf, L"Error"); // 获得并显示错误串
return;
}
mciSendString(L"status cd number of tracks", buf, 256, NULL); // 获得音轨总数
m_nTracks = wcstol(buf, NULL, 10); // 这里使用了宽字符版的字符串到整数的
// 转换函数:long wcstol( const wchar_t *nptr, wchar_t **endptr, int base );
wsprintf(buf, L"play cd from %d to %d", m_nFrom, m_nTo);
mciSendString(buf, NULL, 0, NULL); // 从音轨m_nFrom头播放到音轨m_nTo–1尾
其他常用命令:
mciSendString(L"set cd time format tmsf", NULL,0,NULL); // 设置时间格式为
// 轨(<100):分(<100):秒(<60):帧(<75),一秒=75块,一块=98帧
mciSendString(L"set cd door open", NULL, 0, NULL); // 打开光驱
mciSendString(L"set cd door closed", NULL, 0, NULL); // 关闭光驱
mciSendString(L"pause cd", NULL, 0, NULL); // 暂停播放
mciSendString(L"resume cd", NULL, 0, NULL); // 恢复播放
mciSendString(L"stop cd", NULL, 0, NULL); // 停止播放
mciSendString(L"close cd", NULL, 0, NULL); // 关闭CD设备
mciSendString(L"status cd length", buf, 256, NULL); // 获得整个CD的音轨总长度
mciSendString(L"status cd length track 5", buf, 256, NULL); // 获得第5个音轨的长度
mciSendString(L"status cd current track", buf, 256, NULL); // 获得当前音轨号
注意:
"play cd from m_nFrom to m_nTo"是完整形式,它还有其他形式:
"play cd from m_nFrom"从m_nFrom播放到盘尾
"play cd to m_nTo"从当前位置播放到指定音轨
"play cd" 从当前位置播放到盘尾
例如播放最后一首歌:"play cd from m_nLast"
2)WAV
wchar_t buf[256];
wsprintf(buf, L"open \"%s\" alias sound type waveaudio", pDoc->strFilePath);
MCIERROR err = mciSendString(buf, NULL, 0, NULL);
if (err) {
if (mciGetErrorString(err, buf, 256)) MessageBox(buf, L“Error”);
return;
}
// t1和t2为用户指定的起止时间(单位为秒,浮点变量)
DWORD start = (DWORD)(t1 * 1000 + 0.5), end = (DWORD)(t2 * 1000 + 0.5);
wsprintf(buf, L"play sound from %ld to %ld", start, end);
mciSendString(buf, NULL, 0, NULL);
其他常用命令:
mciSendString(L"status sound length", buf, 256, NULL);
mciSendString(L"pause sound", NULL, 0, NULL);
mciSendString(L"play sound", NULL, 0, NULL); // 从当前位置播放到文件尾
mciSendString(L"stop sound", NULL, 0, NULL);
mciSendString(L"close sound", NULL, 0, NULL);
命令消息
1)CD
// 打开CD
wchar_t buf[256];
MCI_OPEN_PARMS openParms;
openParms.lpstrDeviceType = L"cdaudio";
openParms.lpstrAlias = L"cd";
MCIERROR err = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE
| MCI_OPEN_ALIAS, (DWORD)(LPVOID)&playParms);
if (err) {
if (mciGetErrorString(err, buf, 256)) MessageBox(buf, L"Error");
return;
}
MCIDEVICEID wDevID = openParms.wDeviceID;
// 设置时间格式
MCI_SET_PARMS setParms;
setParms.dwTimeFormat = MCI_FORMAT_TMSF;
mciSendCommand(wDevID, MCI_SET, MCI_SET_TIME_FORMAT,
(DWORD)(LPVOID)&setParms);
// 播放CD
MCI_PLAY_PARMS playParms;
playParms.dwFrom = MCI_MAKE_TMSF(m_nFrom, 0, 0, 0);
playParms.dwTo = MCI_MAKE_TMSF(m_nTo, 0, 0, 0);
mciSendCommand(wDevID, MCI_PLAY, MCI_FROM | MCI_TO,
(DWORD)(LPVOID)&playParms);
其中,设置结构MCI_SET_PARMS的定义为:
typedef struct {
DWORD dwCallback;
DWORD dwTimeFormat;
DWORD dwAudio;
} MCI_SET_PARMS;
播放结构MCI_PLAY_PARMS的定义为:
typedef struct {
DWORD dwCallback;
DWORD dwFrom;
DWORD dwTo;
} MCI_PLAY_PARMS;
2)WAV
// 打开
wchar_t buf[256];
MCI_OPEN_PARMS openParms;
openParms.lpstrDeviceType = L"waveaudio";
openParms.lpstrElementName = L"sample.wav";
openParms.lpstrAlias = L"wave";
MCIERROR err = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE |
MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS, (DWORD)(LPVOID)&playParms);
if (err) {
if (mciGetErrorString(err, buf, 256)) MessageBox(buf, L"Error");
return;
}
MCIDEVICEID wDevID = openParms.wDeviceID;
mciSendCommand(wDevID, MCI_PLAY, NULL, NULL); // 播放
没有评论:
发表评论