ムービーの再生

動画ファイルの再生も、MCI_OPENコマンドで動画ファイルを
MCIデバイスとしてオープンし、MCI_PLAYで再生します。
しかし、音楽データとは異なり、動画を再生するには
映像を画面に表示させる必要があります。

アニメーションデバイスを開く場合はMCI_OPEN_PARMS構造体を
拡張したMCI_ANIM_OPEN_PARMS構造体を指定する事ができます。
dwStyleメンバにWS_CHILDスタイルを指定すれば、hWndParentの
クライアント領域に子ウィンドウとして動画が表示されます。
ただし、MCI_OPENコマンドでウィンドウスタイルを指定するには、
フラグにMCI_ANIM_OPEN_WSを指定しなければなりません。
同様に、親ウィンドウを指定する場合はMCI_ANIM_OPEN_PARENT
指定します。
デバイスタイプは省略してもWindowsが適切なデバイスタイプを
判断してくれます。

要所のみ抜粋

static MCI_ANIM_OPEN_PARMS maop;
static MCI_PLAY_PARMS mpp;
char strErr[256];

case WM_CREATE:
 maop.dwCallback = ( DWORD )hWnd;
 maop.lpstrElementName = "test.mpg";
 maop.dwStyle = WS_CHILD | WS_VISIBLE;
 maop.hWndParent = hWnd;

 iErr = mciSendCommand( 0, MCI_OPEN,
  MCI_OPEN_ELEMENT | MCI_ANIM_OPEN_PARENT | MCI_ANIM_OPEN_WS,
  ( DWORD )&maop );
 if ( iErr ) {
  mciGetErrorString( iErr, strErr, sizeof( strErr ) );
  MessageBox( hWnd, strErr, NULL, MB_OK | MB_ICONERROR );
  return -1;
 }
 mpp.dwCallback = ( DWORD )hWnd;
 break;

case WM_LBUTTONDOWN:
 mciSendCommand( maop.wDeviceID, MCI_PLAY, 0, ( DWORD )&mpp );
 break;

case WM_DESTROY:
 mciSendCommand( maop.wDeviceID, MCI_CLOSE, 0, 0 );
 PostQuitMessage(0);
 break;


※リファレンスで検索してもMCI_ANIM_OPEN_PARMS
がヒットしないのが気になります。ビルドはできますが
古い仕様で推奨されていないのかも知れません。
MCI_DGV_OPEN_PARMSかMCI_OVLY_OPEN_PARMSを使うべき
なんだろうか…。
Windows > マルチメディア | comments (0) | trackbacks (0)

mciGetErrorString()関数


BOOL mciGetErrorString(
 DWORD fdwError,
 LPTSTR lpszErrorText,
 UINT cchErrorText
);

指定されたMCIエラーコードについて説明するストリングを検索します。

fdwErrorError code returned by the mciSendCommand or mciSendString function.
lpszErrorTextPointer to a buffer that receives a null-terminated string describing the specified error.
cchErrorTextLength of the buffer, in characters, pointed to by the lpszErrorText parameter.

エラーコードに対応した文字列の文字数はエラーの内容によって異なりますが
最大で128文字になる可能性があると定められています。
Unicodeへの対応も考えれば256バイト以上のバッファを確保すれば十分でしょう。
Windows > マルチメディア | comments (0) | trackbacks (0)

mciSendCommand()関数


MCIERROR mciSendCommand(
 MCIDEVICEID IDDevice,
 UINT uMsg,
 DWORD fdwCommand,
 DWORD_PTR dwParam
);

IDDeviceコマンドを送信するMCIデバイスの識別子を指定します。アプリケーションは、最初にメディアデバイスを開いてこの識別子を取得する必要があります。
uMsgMCIデバイスに送信するコマンドを表す定数を指定します。
fdwCommandコマンドの追加情報となるフラグ
dwParamコマンドの情報を格納した構造体へのポインタ


MCI_OPENコマンド


static MCI_OPEN_PARMS mop;
(略)
case WM_CREATE:
 mop.dwCallback = ( DWORD )hWnd;
 mop.lpstrDeviceType = ( LPCSTR )MCI_DEVTYPE_WAVEFORM_AUDIO;
 mop.lpstrElementName = "test.wav";

 iErr = mciSendCommand( 0, MCI_OPEN,
  MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT,
  ( DWORD )&mop );
 if ( iErr ) {
  mciGetErrorString( iErr, strErr, sizeof( strErr ) );
  MessageBox( hWnd, strErr, NULL, MB_OK | MB_ICONERROR );
  return -1;
 }
 break;


文字列でデバイスの種類を指定する場合は、フラグにMCI_OPEN_TYPEを組み合わさなければなりません。
定数を使ってデバイスの種類を指定する場合は、MCI_OPEN_TYPEに加えてMCI_OPEN_TYPE_IDフラグを組み合わせます。
基本的には、文字列よりも定数の方がオーバーヘッドが少なく高速な動作を期待することができます。
MCI_OPEN_ELEMENTは所定の構造体のlpstrElementNameメンバに、ファイル名が格納されている事を表します。

MCI_PLAYコマンド


case WM_LBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_PLAY, 0, 0 );
 break;


正しくMCIデバイスをオープンすることができれば、MCI_PLAYコマンドをデバイスに送信する事で、コンテンツを再生する事ができます。
MCI_PLAYコマンドもデバイスの種類でさまざまなフラグや構造体を指定する事ができますが、特殊な再生方法を望まない限りは必要無いでしょう。

MCI_STOP、MCI_PAUSE、MCI_SEEKコマンド


case WM_RBUTTONDOWN:
 PlaySound( NULL, NULL, SND_PURGE );
 mciSendCommand( mop.wDeviceID, MCI_STOP, 0, 0 );
 mciSendCommand( mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0 );
 break;


再生を一時停止するにはMCI_PAUSE
停止するにはMCI_STOPコマンドを送信します。
これらのコマンドは独自のフラグや構造体を持ちません。
MCI_PAUSE、MCI_STOPの意味は対象デバイスによって異なります。
コンテンツの再生位置はMCI_SEEKコマンドで変更する事ができます。
フラグにMCI_SEEK_TO_STARTを指定すればコンテンツの先頭に移動します。
フラグと専用の構造体を指定すれば任意の位置も指定できます。

※WAVEの再生で試してみると、PlaySound関数では再生後、先頭に自動で巻き戻されるようですが
MCIコマンドでは再生後巻き戻らない(もしくは再生しっぱなし)のようで、
MCI_SEEKで再生位置を設定し直す必要があるようです。


MCI_CLOSEコマンド


case WM_DESTROY:
 mciSendCommand( mop.wDeviceID, MCI_CLOSE, 0, 0 );
 PostQuitMessage(0);
 break;


MCIデバイスの利用が終了し、デバイスが不要になれば解放しなければなりません。
デバイスを解放するにはMCI_CLOSEコマンドを送信して下さい。
MCI_CLOSEコマンドは独自のフラグや構造体を持ちません。

MCI_NOTIFYフラグ

MCI_NOTIFYフラグを使用すると、
デバイスはアクションを完了すると親ウィンドウに
MM_MCINOTIFYメッセージをポストします。
このメッセージは、コマンドが処理を終了した時に送られてきます。

MCI_PLAYコマンドにMCI_NOTIFYフラグを指定すれば、
MCIはトラックの再生が終了すると親ウィンドウに
MM_MCINOTIFYコマンドをポストするので、
このタイミングで再びトラックの先頭から再生するようにすれば
ループ再生ができます。


static MCI_OPEN_PARMS mop;
static MCI_PLAY_PARMS mpp;
(略)
case WM_CREATE:
 (デバイスのオープンの記述。上記参照)
 mpp.dwCallback = ( DWORD )hWnd;
 mpp.dwFrom = 0; // 演奏開始位置の設定、0ならば曲の先頭からになる
case WM_LBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, ( DWORD )&mpp );
 break;
case WM_RBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_STOP, 0, 0 );
 //mciSendCommand( mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0 );
 break;
case MM_MCINOTIFY:
 if ( wParam == MCI_NOTIFY_SUCCESSFUL )
  mciSendCommand( mop.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, ( DWORD )&mpp );
 break;
(略)


※最初から再生開始位置を指定して再生してやれば
MCI_SEEKコマンドを使う必要も無さそうです。
Windows > マルチメディア | comments (0) | trackbacks (0)

MCI_PLAY_PARMS構造体


typedef struct {
 DWORD_PTR dwCallback;
 DWORD dwFrom;
 DWORD dwTo;
} MCI_PLAY_PARMS;

MCI_PLAY_PARMS構造体は、MCI_PLAYコマンドのための位置情報を含んでいます。

dwCallbackThe low-order word specifies a window handle used for the MCI_NOTIFY flag.
dwFromPosition to play from.
dwToPosition to play to.
Windows > マルチメディア | comments (0) | trackbacks (0)

MCI_OPEN_PARMS構造体


typedef struct {
 DWORD_PTR dwCallback;
 MCIDEVICEID wDeviceID;
 LPCSTR lpstrDeviceType;
 LPCSTR lpstrElementName;
 LPCSTR lpstrAlias;
} MCI_OPEN_PARMS;


wDeviceID開いたMCIデバイスの識別子が格納されます。開いたデバイスにMCIコマンドを送信するには、このデバイス識別子を利用します。
lpstrDeviceTypeデバイスのタイプ名を保存した文字列へのポインタ、または定数を指定します。
lpstrElementName開くMCIデバイスのコンテンツを参照するパスを指定します。
lpstrAlias開くデバイスに割り当てる別名を指定します。(任意)

MCI Device Types
MCI_ALL_DEVICE_IDAny device
MCI_DEVTYPE_ANIMATIONAnimation-playback device
MCI_DEVTYPE_CD_AUDIOCD audio device
MCI_DEVTYPE_DATDigital-audio tape device
MCI_DEVTYPE_DIGITAL_VIDEODigital-video playback device
MCI_DEVTYPE_OTHERUndefined device
MCI_DEVTYPE_OVERLAYVideo-overlay device
MCI_DEVTYPE_SCANNERScanner device
MCI_DEVTYPE_SEQUENCERMIDI sequencer device
MCI_DEVTYPE_VCRVideo-cassette recorder
MCI_DEVTYPE_VIDEODISCVideodisc player
MCI_DEVTYPE_WAVEFORM_AUDIOWaveform-audio device
Windows > マルチメディア | comments (0) | trackbacks (0)

PlaySound()関数


BOOL PlaySound(
 LPCSTR pszSound,
 HMODULE hmod,
 DWORD fdwSound
);

WAVEフォームサウンドを再生します。

pszSound再生するサウンドをNULLで終わる文字列で指定します。ただしfdwSoundパラメータでSND_MEMORYを指定した時は、メモリ内に読み込まれたサウンドイメージへのポインタを指定します。NULLを指定すると、現在再生中のWAVEフォームサウンドが停止します。
hmodfdwSoundパラメータでSND_RESOURCEを指定した場合は、ロードするリソースが入った実行可能ファイルのインスタンスハンドルを指定します。そうでない場合は、NULLを指定します。
fdwSound再生フラグヲ指定します。

フラグ抜粋
SND_ASYNCサウンドを非同期的に再生します。PlaySound関数は即座に制御を返します。非同期的に再生されているサウンドを止めるには、pszSoundパラメータにNULLを指定してPlaySound関数を呼び出します。
SND_FILENAMEpszSoundパラメータは、ファイル名です。
SND_LOOPサウンドを繰り返し再生します。SND_ASYNCと同時に指定します。サウンドの再生を止めるにはpszSoundパラメータにNULLを指定してPlaySound関数を呼び出します。
SND_MEMORYpszSoundパラメータは、メモリ内に読み込まれたサウンドイメージへのポインタです。
SND_NODEFAULT指定されたサウンドが見つからなかった場合、PlaySound関数はデフォルトのサウンド(一般の警告音)を再生することなく無音で制御を返します。
SND_NOSTOP既にほかのサウンドが再生されていた場合、指定されたサウンドを再生することなく即座に制御を返します。
SND_NOWAITドライバがビジー状態であれば、サウンドを再生することなく即座に制御を返します。
SND_PURGEサウンドの再生を停止します。pszSoundパラメータがNULL以外のときは、指定したサウンドの全てのインスタンスが停止します。pszSoundパラメータがNULLの時は、呼び出し側タスクのすべてのサウンドが停止します。SND_RESOURCE指定時は、インスタンスハンドルも指定します。
SND_RESOURCEpszSoundパラメータはリソースIDです。hmodパラメータには、リソースが入った実行可能ファイルのインスタンスハンドルを指定します。
SND_SYNCサウンドを同期的に再生します。PlaySound関数は、サウンドの再生が完了した後に制御を返します。



case WM_LBUTTONDOWN:
 PlaySound( "test.wav", NULL, SND_ASYNC | SND_FILENAME );
 break;
case WM_RBUTTONDOWN:
 PlaySound( NULL, NULL, SND_PURGE );
 break;


この関数で音声データを再生するには必ずその音声データを保存できるだけの物理メモリが必要になります。
Windows > マルチメディア | comments (0) | trackbacks (0)