MCI は WAVE 以外の形式である MIDI や MP3 はもちろん、動画形式も扱う事ができます。
様々な形式に対応していて、機能性が高いという事で、
マルチメディア操作に一番よく使われています。
MCIには「MCIウィンドウ、MCI文字列、MCIコマンド」という複数の操作方法が提供されていますが、
一番直接的で、一番よく使われるのはMCIコマンドです。
従って、ここではMCIコマンドについてのみ解説します。
PlaySound 関数とは違い、MCIコマンドは色々と面倒です。
ここでは、動画については扱わず、
また、よく使う操作だけに絞って解説します。
■MCIコマンド
MCIコマンドによる指示は全て mciSendCommand 関数で行います。
統一されているので簡単に思えるかもしれませんが、
それぞれの操作に専用の構造体が定義されていて、設定が面倒です……。
MCIERROR mciSendCommand(
MCIDEVICEID IDDevice, // デバイス識別子
UINT uMsg, // コマンドメッセージ
DWORD fdwCommand, // フラグ
DWORD dwParam // パラメータを保持している構造体
);
winmm.lib をリンクする必要があります。
IDDevice には操作したいデバイスの識別子を指定します。MCI_OPEN の時は NULL
を指定します。
uMsg には希望の操作を表す定数を指定します。
fdwCommand にはそれぞれの操作に対応した追加情報を指定します。
dwParam にはそれぞれの操作に対応した構造体を指定します。
fdwCommand と dwParam は追加情報です。
uMsg に指定するコマンドメッセージでよく使うのはこれくらいでしょう。
MCI_PLAY …… 再生
MCI_STOP …… 停止
MCI_SEEK …… 再生開始場所の移動
MCI_PAUSE …… 一時停止
MCI_RESUME …… 一時停止解除
ここで注意しなければならないのは、MCI_STOP です。
MCI_STOP の意味はデバイスによって異なります。
つまり、再生を停止して先頭に巻き戻してくれるかもしれませんし、
停止するだけかもしれないのです。
再生は現在の位置から行われるので、停止後は次の再生の為に先頭に巻き戻す必要があります。
同じく、MCI_PAUSE についてもデバイス依存です。
また、一時停止は MCI_PLAY でも解除できるかもしれません。
それぞれの操作では必要に応じて、fdwCommand と dwParam を設定します。
難しいのは構造体の設定なので、少しずつ解説していきます。
■MCIデバイスを開く
とりあえずMCIデバイスをオープンしなければ始まりません。
MCIデバイスをオープンするには MCI_OPEN コマンドを使います。
MCI_OPEN では構造体の設定は避けられません。
MCI_OPEN_PARMS という専用の構造体を使います。
typedef struct {
DWORD_PTR dwCallback;
MCIDEVICEID wDeviceID;
LPCSTR lpstrDeviceType;
LPCSTR lpstrElementName;
LPCSTR lpstrAlias;
} MCI_OPEN_PARMS;
dwCallBack はコールバックウィンドウのハンドルです。
wDeviceID はデバイス識別子です。
lpstrDeviceType はデバイス形式です。
lpstrElementName はファイル名です。
lpstrAlias はデバイスの別名です。使いません。
この中で最低限設定しなければならないのは、lpstrDeviceType と lpstrElementName です。
lpstrDeviceType に設定できる値はレジストリの
「 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions 」
に一覧があります。
私の環境では以下のようになっていました。
他にも、定数を使う方法があります。
コールバックについては次節で解説します。
構造体を設定したら、構造体のどのメンバを設定したかを
mciSendCommand 関数の fdwCommand 引数にフラグで指定します。
フラグで指定したメンバしか参照しないので、フラグを指定しなければ構造体は必要ありません。
MCI_OPEN_TYPE …… MCI_OPEN_PARMS の lpstrDeviceType に形式を表す文字列か定数が設定されている
MCI_OPEN_TYPE_ID …… MCI_OPEN_PARMS の lpstrDeviceType は定数である
MCI_OPEN_ELEMENT …… MCI_OPEN_PARMS の lpstrElementName にファイル名が設定されている
lpstrDeviceType に定数を設定した場合は、
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID と指定しなければならない事に注意して下さい。
定数にはない形式もありますし、フラグが一つ多くなるので、文字列で指定した方が良いでしょう。
MCI_OPEN に関係したフラグは他にも大量に定義されていますが、あまり使わないのでここでは取り上げません。
更に、それぞれの操作についても大量のフラグが定義されています。
それでは、WAVEファイルをオープンするプログラムを組んでみましょう。
// winmm.lib をリンクする #pragma comment(lib,"winmm") static MCI_OPEN_PARMS mop; mop.lpstrDeviceType="WaveAudio"; mop.lpstrElementName="Windows XP Startup.wav"; mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,(DWORD)&mop);
MCI_OPEN が成功すると、
MCI_OPEN_PARMS 構造体の wDeviceID メンバにデバイス識別子が設定されます。
以降の操作はこのデバイス識別子を対象にして行います。
従って、MCI_OPEN_PARMS 構造体型の変数は静的である必要があります。
■再生&MCIデバイスを閉じる
再生は MCI_PLAY コマンドで行います。
普通に再生するだけなら構造体を設定する必要はないので、フラグも指定しません。
mciSendCommand(mop.wDeviceID,MCI_PLAY,0,0);
操作対象として MCI_OPEN で取得したデバイス識別子を指定している事に注目して下さい。
クローズは MCI_CLOSE コマンドで行います。
こちらも特別な操作は必要ないので、フラグと構造体は設定しません。
そもそも MCI_CLOSE には専用の構造体が無く、必要ならば全コマンド共通の構造体を使います。
それぞれの構造体については次節でもう少し詳しく解説します。
mciSendCommand(mop.wDeviceID,MCI_CLOSE,0,0);
★☆ ソースファイル表示 ☆★
難しいのは星の数ほどある設定項目の意味を理解する事で、プログラム自体は簡単ですね。
MIDI や MP3 , WMA 等も再生させてみて下さい。
■よく使うコマンド
先程のプログラムは「オープン→再生→クローズ」という最低限の操作しかしていませんでしたが、
停止後の巻き戻しは欠かせませんし、一時停止もよく使うでしょう。
以下のプログラムでは、よく使う操作を実装しています。
本来は一緒に実行すべき操作も個別に割り当てているので、手動で動作を確認してみましょう。
case WM_KEYDOWN: switch(wParam){ case 'A': //再生 mciSendCommand(mop.wDeviceID,MCI_PLAY,0,0); return 0; case 'S': //停止 mciSendCommand(mop.wDeviceID,MCI_STOP,0,0); return 0; case 'D': //巻き戻し mciSendCommand(mop.wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,0); return 0; case 'F': //一時停止 mciSendCommand(mop.wDeviceID,MCI_PAUSE,0,0); return 0; case 'G': //一時停止解除 mciSendCommand(mop.wDeviceID,MCI_RESUME,0,0); return 0; } return 0;
停止の動作が不定なので、本来、停止と巻き戻しはセットで実行するべきです。
mciSendCommand(mop.wDeviceID,MCI_STOP,0,0);
mciSendCommand(mop.wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,0);
また、一時停止は MCI_PLAY でも解除できるかもしれません。
MCI_SEEK のフラグ MCI_SEEK_TO_START は先頭にシークする事を意味しています。
MCI_SEEK_TO_END を指定すれば最後にシークします。
任意の位置にシークする事もできますが、それは次節で解説します。
★☆ ソースファイル表示 ☆★
■MCIの欠点
MCI はメモリにあるWAVE等を操作する事ができません。
リソースからの操作もできません。
ファイルだけです。
従って、リソースデータを操作するには、一時ファイルに書き出す必要があります。
また、オープンしたスレッド以外からは操作できません。
他のスレッドから操作したい場合は、オープンしたスレッドに独自メッセージを投げて、
そちらで操作してもらいます。
特にこちらは見落としやすいので注意して下さい。