DirectShowを利用して再生・その3
前回は再生、一時停止、停止ボタンとシークバーをつけました。
今回は連続再生を行います。
ビデオの表示は別ウィンドウのままです。
イベント取得
連続再生を行うには今再生しているメディアが終わりに達したら次のファイルを開いて再生を始めるということをします。
そのためには再生が終了したことを知る必要があります。
タイマーを使って逐一再生位置を取得してメディアの長さと一致したら終わりに達したと判断するという方法でも良いのですがもっとスマートな方法があります。
終了イベントの取得です。
メディアが終わりに達したら知らせてくれるという便利な機能です。
その終了イベント取得するにはIMediaEventExインターフェースを使います。
const
//イベントを受け取るためのユニークなメッセージ番号
WM_GRAPH_NOTIFY = (WM_APP +1);
type
TForm1 = class(TForm)
...
private
{ Private 宣言 }
F_GraphBuilder : IGraphBuilder;
F_MediaEventEx : IMediaEventEx;
//イベント通知のためのメッセージ番号を受け取れるようにする
procedure WMGraphNotify(var Msg: TMessage); message WM_GRAPH_NOTIFY;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
//グラフ作成
CoCreateInstance(
CLSID_FilterGraph,
nil,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
F_GraphBuilder
);
//イベント通知ウィンドウをセット
F_GraphBuilder.QueryInterface(IMediaEventEx, F_MediaEventEx);
F_MediaEventEx.SetNotifyWindow(Self.Handle, WM_GRAPH_NOTIFY, 0);
...
procedure TForm1.WMGraphNotify(var Msg: TMessage);
//イベント処理
var
li_EventCode : Longint;
li_Param1 : Longint;
li_Param2 : Longint;
begin
if (F_MediaEventEx = nil) then begin
Exit;
end;
// イベントを全て取得
while (Succeeded(F_MediaEventEx.GetEvent(li_EventCode, li_Param1, li_Param2,
0))) do begin
case (li_EventCode) of
EC_COMPLETE //再生が終わりに来た
:begin
//連続再生のための処理をここに書く
end;
end;
F_MediaEventEx.FreeEventParams(li_EventCode, li_Param1, li_Param2);
end;
end;
IMediaEventExインターフェースはフォームのprivate部でF_MediaEventExとして宣言しておきます。
イベントはSetNotifyWindowメソッドで指定したウィンドウで受け取ることができます。
SetNotifyWindowは第一引数にメッセージを受け取るウィンドウハンドル、第二引数にメッセージの番号を指定します。
第三引数は特に必要がなければ(大抵は必要ないと思います)0で構いません。
メッセージの番号は他のメッセージと区別できるようにしなければなりません。
そこでWM_GRAPH_NOTIFYという識別子をグローバルで宣言して値にWM_APP +1を割り当てておきます。
メッセージを受け取るウィンドウ(今回はForm1)はメッセージハンドラでこのWM_GRAPH_NOTIFYを受け取れるようにしておきます。
このWM_GRAPH_NOTIFYという識別子はソースコードで区別がつけば良いものなのでエラーにならなければ何でも構いません。
値も必ずWM_APP +1である必要はなく他のメッセージ番号とかぶらなければ(WM_APP+1〜WM_APP+16383の間であれば)何でもかまいません。
参考サイト
WM_APPの薦め。
http://akky.cjb.net/mfc/message.html
イベント処理ではGetEventメソッドでイベントを取得します。
GetEventの第一引数にはイベントの種類を表す値がセットされます。
第二引数と第三引数にはイベント種類に応じた追加情報を表す値がセットされます。
そして第一引数の値をチェックしてEC_COMPLETEならメディアの終了に達したということになります。
ここに連続再生を行う処理を書けばOKとなります。
ソースコード
dplay_3.zip ソースコードと実行ファイル詰め合わせ。
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls,
DirectShow9;
const
//イベントを受け取るためのユニークなメッセージ番号
WM_GRAPH_NOTIFY = (WM_APP +1);
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
Button_Open: TButton;
Button_Delete: TButton;
Button_Clear: TButton;
Button_Play: TButton;
Button_Pause: TButton;
Button_Stop: TButton;
TrackBar1: TTrackBar;
Label_Time: TLabel;
Label_Size: TLabel;
CheckBox_Event: TCheckBox;
Timer1: TTimer;
OpenDialog1: TOpenDialog;
procedure FormCreate (Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button_OpenClick (Sender: TObject);
procedure Button_DeleteClick(Sender: TObject);
procedure Button_ClearClick (Sender: TObject);
procedure Button_PlayClick (Sender: TObject);
procedure Button_PauseClick (Sender: TObject);
procedure Button_StopClick (Sender: TObject);
procedure ComboBox1Select (Sender: TObject);
procedure TrackBar1Change (Sender: TObject);
procedure Timer1Timer (Sender: TObject);
private
{ Private 宣言 }
F_GraphBuilder : IGraphBuilder;
F_MediaEventEx : IMediaEventEx;
F_MediaPosition : IMediaPosition;
F_fDuration : TRefTime;
//イベント通知のためのメッセージ番号を受け取れるようにする
procedure WMGraphNotify(var Msg: TMessage); message WM_GRAPH_NOTIFY;
procedure F_Close;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
ActiveX,
debug_msg; //デバッグ出力用
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Label_Size.Caption := '';
Label_Time.Caption := '';
//グラフ作成
CoCreateInstance(
CLSID_FilterGraph,
nil,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
F_GraphBuilder
);
//イベント通知ウィンドウをセット。
F_GraphBuilder.QueryInterface(IMediaEventEx, F_MediaEventEx);
F_MediaEventEx.SetNotifyWindow(Self.Handle, WM_GRAPH_NOTIFY, 0);
//時間取得のため
F_GraphBuilder.QueryInterface(IMediaPosition, F_MediaPosition);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
F_Close;
F_MediaPosition := nil;
F_MediaEventEx := nil;
F_GraphBuilder := nil;
end;
procedure TForm1.Button_PlayClick(Sender: TObject);
//再生開始
var
l_MediaControl : IMediaControl;
begin
if (Assigned(F_GraphBuilder)) then begin
F_GraphBuilder.QueryInterface(IMediaControl, l_MediaControl);
l_MediaControl.Run;
l_MediaControl := nil;
Timer1.Enabled := True;
end;
end;
procedure TForm1.Button_PauseClick(Sender: TObject);
//一時停止
var
l_MediaControl : IMediaControl;
begin
Timer1.Enabled := False;
if (Assigned(F_GraphBuilder)) then begin
F_GraphBuilder.QueryInterface(IMediaControl, l_MediaControl);
l_MediaControl.Pause;
l_MediaControl := nil;
end;
end;
procedure TForm1.Button_StopClick(Sender: TObject);
//停止
var
l_MediaControl : IMediaControl;
begin
Timer1.Enabled := False;
if (Assigned(F_GraphBuilder)) then begin
F_GraphBuilder.QueryInterface(IMediaControl, l_MediaControl);
l_MediaControl.Stop;
//ただ停止させただけではPauseと変わらない
//先頭に戻すにはIMediaPositionを使う
F_MediaPosition.put_CurrentPosition(0);
//移動させただけでは現在位置のフレームが描画されない。
//現在位置のフレームを描画させるためにPauseあるいはStopWhenReadyを呼ぶ。
l_MediaControl.StopWhenReady;
l_MediaControl := nil;
Timer1.Tag := 1;
TrackBar1.Position := 0;
Timer1.Tag := 0;
end;
end;
//--- シークバー ---
procedure TForm1.Timer1Timer(Sender: TObject);
//現在位置表示
function FloatToTime(fTime : TRefTime) : String;
var
li_Time, li_Hour, li_Min, li_Sec : Integer;
begin
li_Time := Trunc(fTime);
li_Hour := li_Time div 60 div 60;
li_Min := li_Time div 60 mod 60;
li_Sec := li_Time mod 60;
Result := Format('%d:%.2d:%.2d', [li_Hour, li_Min, li_Sec]);
end;
function IsDragThumb: Boolean;
//トラックバーのスライダーを触っているか。
//実際はトラックバーがマウスキャプチャしているか。
begin
if not(BOOL(Hi(GetAsyncKeyState(VK_LBUTTON)))) then begin
Result := False;
Exit;
end;
Result := (GetCapture = TrackBar1.Handle);
end;
var
lf_Pos : TRefTime;
begin
if (Assigned(F_GraphBuilder)) then begin
Timer1.Tag := 1;
F_MediaPosition.get_CurrentPosition(lf_Pos);
Label_Time.Caption := Format('%s/%s', [FloatToTime(lf_Pos), FloatToTime(F_fDuration)]);
if not(IsDragThumb) then begin
//トラックバーのスライダーを触っていなかったらスライダーを現在位置に移動させる。
TrackBar1.Position := Trunc(lf_Pos);
end;
Timer1.Tag := 0;
end;
end;
procedure TForm1.TrackBar1Change(Sender: TObject);
//トラックバー移動
var
l_MediaPosition : IMediaPosition;
begin
if (Timer1.Tag <> 0) then begin
Exit;
end;
if (Assigned(F_GraphBuilder)) then begin
if not(BOOL(Hi(GetAsyncKeyState(VK_LBUTTON)))) then begin
F_GraphBuilder.QueryInterface(IMediaPosition, l_MediaPosition);
l_MediaPosition.put_CurrentPosition(TrackBar1.Position);
l_MediaPosition := nil;
end;
end;
end;
//------------------
procedure TForm1.WMGraphNotify(var Msg: TMessage);
//イベント処理
var
li_EventCode : Longint;
li_Param1 : Longint;
li_Param2 : Longint;
begin
if (F_MediaEventEx = nil) then begin
Exit;
end;
// イベントを全て取得
while (Succeeded(F_MediaEventEx.GetEvent(li_EventCode, li_Param1, li_Param2, 0))) do begin
if (CheckBox_Event.Checked) then begin
debug_msg.ShowEvent(li_EventCode, li_Param1, li_Param2);
end;
case (li_EventCode) of
EC_COMPLETE
:begin
//再生が終わりに来た
//連続再生
if (ComboBox1.Items.Count = 0) then begin
F_Close;
end else begin
if (ComboBox1.ItemIndex < ComboBox1.Items.Count -1) then begin
ComboBox1.ItemIndex := ComboBox1.ItemIndex +1;
end else begin
ComboBox1.ItemIndex := 0;
end;
ComboBox1Select(nil);
end;
end;
end;
F_MediaEventEx.FreeEventParams(li_EventCode, li_Param1, li_Param2);
end;
end;
procedure TForm1.F_Close;
var
l_MediaControl : IMediaControl;
l_EnumFilters : IEnumFilters;
l_BaseFilter : IBaseFilter;
begin
Timer1.Enabled := False;
Label_Size.Caption := '';
Label_Time.Caption := '';
if (F_GraphBuilder <> nil) then begin
F_GraphBuilder.QueryInterface(IMediaControl, l_MediaControl);
l_MediaControl.Stop;
l_MediaControl := nil;
//Sotpしただけではフィルタはまだ接続されたままなのでフィルタを列挙して削除する。
//http://msdn.microsoft.com/ja-jp/library/cc973418.aspx
F_GraphBuilder.EnumFilters(l_EnumFilters);
while (l_EnumFilters.Next(1, l_BaseFilter, nil) = S_OK) do begin
F_GraphBuilder.RemoveFilter(l_BaseFilter);
l_BaseFilter := nil;
l_EnumFilters.Reset;
end;
l_EnumFilters := nil;
end;
end;
procedure TForm1.Button_OpenClick(Sender: TObject);
//開く
var
li_Count : Integer;
begin
if (OpenDialog1.Execute) then begin
li_Count := ComboBox1.Items.Count;
ComboBox1.Items.AddStrings(OpenDialog1.Files);
ComboBox1.ItemIndex := li_Count;
ComboBox1Select(nil); //再生開始
end;
end;
procedure TForm1.Button_DeleteClick(Sender: TObject);
//リストから再生中のファイルを削除
var
li_Index : Integer;
begin
li_Index := ComboBox1.ItemIndex;
F_Close;
ComboBox1.Items.Delete(li_Index);
ComboBox1.ItemIndex := li_Index;
ComboBox1Select(nil);
end;
procedure TForm1.Button_ClearClick(Sender: TObject);
//リストクリア
begin
ComboBox1.Items.Clear;
end;
procedure TForm1.ComboBox1Select(Sender: TObject);
//ファイル選択→再生
var
ls_FileName : String;
l_BasicVideo : IBasicVideo;
li_Width : Integer;
li_Height : Integer;
begin
F_Close;
if (ComboBox1.Items.Count = 0) then begin
Exit;
end;
if (ComboBox1.ItemIndex < 0) then begin
ComboBox1.ItemIndex := 0;
end;
ls_FileName := ComboBox1.Items[ComboBox1.ItemIndex];
//読み込み
if not(Succeeded(F_GraphBuilder.RenderFile(POLESTR(WideString(ls_FileName)), nil))) then begin
ShowMessage(ls_FileName + #13'は開けません');
ComboBox1.Items.Delete(ComboBox1.ItemIndex);
ComboBox1.Text := '';
Exit;
end;
//タイトルバーにファイル名を表示
Caption := ExtractFileName(ls_FileName);
//ビデオのサイズを取得
F_GraphBuilder.QueryInterface(IBasicVideo, l_BasicVideo);
//li_Widthとli_Heightの初期化は必須。
li_Width := 0;
li_Height := 0;
l_BasicVideo.get_VideoWidth (li_Width);
l_BasicVideo.get_VideoHeight(li_Height);
l_BasicVideo := nil;
if (li_Width > 0) and (li_Height > 0) then begin
Label_Size.Caption := Format('%d×%d', [li_Width, li_Height]);
end else begin
Label_Size.Caption := '';
end;
//長さ取得
F_fDuration := 0;
F_MediaPosition.get_Duration(F_fDuration); //この後CurrentPositionが変わってしまうことがある
TrackBar1.Max := Trunc(F_fDuration);
//長さを取得した後CurrentPositionが終わりに移動してしまうことがあるので頭に戻す
//F_MediaPosition.put_CurrentPosition(0);
//Button_StopClickの中でやっている
//再生開始
Button_StopClick(nil);
Button_PlayClick(nil);
end;
end.
デバッグ出力
イベントの確認用にデバッグ出力用のフォームを作ってみました。
Form1にMemoを置いて書き込んでも良いのですが、別フォームにして分けた方がコードも分離されて楽なので分けました。
今回はイベントの出力にしか使っていませんが、ソースコード中の気になる所にデバッグ用の出力コードを書けば動かしながら値を確認できて便利です。
unit debug_msg;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
procedure ShowDbg(AValue : array of Variant); overload;
procedure ShowDbg(sValue : String); overload;
procedure ShowSuc(hRes : HResult; sSuc, sFail : String);
//イベント
procedure ShowEvent(iEventCode, iParam1, iParam2: Longint);
type
TForm_Debug = class(TForm)
ListBox1: TListBox;
Button_Clear: TButton;
procedure Button_ClearClick(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form_Debug: TForm_Debug;
implementation
uses
ActiveX,
DirectShow9,
WMF9;
{$R *.dfm}
procedure TForm_Debug.Button_ClearClick(Sender: TObject);
begin
ListBox1.Items.Clear;
end;
procedure _DbgAdds(sStrs : array of String);
const
lci_MAXLINE = 1000;
var
lb_Create : Boolean;
i : Integer;
l_Rect : TRect;
li_Page : Integer;
ls_Text : WideString;
l_Strings : TStrings;
l_ListBox : TListBox;
begin
if not(Assigned(Form2)) then begin
Form_Debug := TForm_Debug.Create(Application);
end else begin
lb_Create := True;
for i := 0 to Screen.FormCount-1 do begin
if (Screen.Forms[i] is TForm_Debug) then begin
lb_Create := False;
Break;
end;
end;
if (lb_Create) then begin
Form_Debug := TForm_Debug.Create(Application);
end;
end;
Form_Debug.Show;
l_ListBox := Form_Debug.ListBox1;
l_Strings := l_ListBox.Items;
for i := 0 to High(sStrs) do begin
if (i = 0) then begin
ls_Text := sStrs[i];
end else begin
ls_Text := ls_Text + ' ' + sStrs[i];
end;
end;
//追加
l_Strings.Add(ls_Text);
if (l_Strings.Count > lci_MAXLINE) then begin
for i := 0 to l_Strings.Count - lci_MAXLINE do begin
l_Strings.Delete(0);
end;
end;
//最後の行を画面に表示
with l_ListBox do begin
l_Rect := ItemRect(0);
li_Page := Trunc(ClientHeight / (l_Rect.Bottom - l_Rect.Top));
if (Items.Count <= li_Page) then begin
TopIndex := 0;
end else begin
TopIndex := Count - li_Page;
end;
end;
end;
procedure ShowDbg(AValue : array of Variant);
var
ls_Arg : array of String;
i : Integer;
begin
SetLength(ls_Arg, High(AValue) +1);
for i := 0 to High(AValue) do begin
ls_Arg[i] := String(VarAsType(AValue[i], varOleStr));
end;
_DbgAdds(ls_Arg);
end;
procedure ShowDbg(sValue : String);
begin
ShowDbg([sValue]);
end;
procedure ShowSuc(hRes : HResult; sSuc, sFail : String);
var
ls_Msg : String;
begin
if (Succeeded(hRes)) then begin
ls_Msg := sSuc;
end else begin
ls_Msg := sFail;
end;
ShowDbg([ls_Msg, Format('0x%x', [hRes])]);
end;
procedure ShowEvent(iEventCode, iParam1, iParam2: Longint);
var
ls_Msg : String;
ls_Msg1 : String;
ls_Msg2 : String;
li_Len : Integer;
begin
case (iEventCode) of
EC_ACTIVATE: begin
ls_Msg := 'EC_ACTIVATE';
ls_Msg1 := 'ビデオウィンドウがアクティブまたは非アクティブである。';
end;
EC_BUFFERING_DATA: begin
ls_Msg := 'EC_BUFFERING_DATA';
ls_Msg1 := 'グラフがデータをバッファリングしている、またはデータのバッファリングを停止した。';
end;
EC_BUILT: begin
ls_Msg := 'EC_BUILT';
ls_Msg1 := 'グラフを作成し終えたときにビデオコントロールによって送信される。アプリケーションには転送されない。';
end;
EC_CLOCK_CHANGED: begin
ls_Msg := 'EC_CLOCK_CHANGED';
ls_Msg1 := '基準クロックが変更された。';
end;
EC_CLOCK_UNSET: begin
ls_Msg := 'EC_CLOCK_UNSET';
ls_Msg1 := 'クロックプロバイダの接続が解除された。';
end;
EC_CODECAPI_EVENT: begin
ls_Msg := 'EC_CODECAPI_EVENT';
ls_Msg1 := 'エンコーディングイベントを通知するためにエンコーダによって送信される。';
end;
EC_COMPLETE: begin
ls_Msg := 'EC_COMPLETE';
ls_Msg1 := '特定のストリームからのすべてのデータをレンダリングし終えた。';
end;
EC_DEVICE_LOST: begin
ls_Msg := 'EC_DEVICE_LOST';
ls_Msg1 := 'プラグアンドプレイデバイスが取り外された、または再び使用できるようになった。';
end;
EC_DISPLAY_CHANGED: begin
ls_Msg := 'EC_DISPLAY_CHANGED';
ls_Msg1 := 'ディスプレイモードが変更された。';
end;
EC_END_OF_SEGMENT: begin
ls_Msg := 'EC_END_OF_SEGMENT';
ls_Msg1 := 'セグメントの終わりに到達した。';
end;
EC_ERROR_STILLPLAYING: begin
ls_Msg := 'EC_ERROR_STILLPLAYING';
ls_Msg1 := 'グラフを実行する非同期コマンドが失敗した。';
end;
EC_ERRORABORT: begin
ls_Msg := 'EC_ERRORABORT';
ls_Msg1 := 'エラーのため処理が中止された。';
end;
EC_EXTDEVICE_MODE_CHANGE: begin
ls_Msg := 'EC_EXTDEVICE_MODE_CHANGE';
ls_Msg1 := 'サポートされていない。';
end;
EC_FULLSCREEN_LOST: begin
ls_Msg := 'EC_FULLSCREEN_LOST';
ls_Msg1 := 'ビデオレンダラがフルスクリーンモードから切り替わろうとしている。';
end;
EC_GRAPH_CHANGED: begin
ls_Msg := 'EC_GRAPH_CHANGED';
ls_Msg1 := 'フィルタグラフが変更された。';
end;
EC_LENGTH_CHANGED: begin
ls_Msg := 'EC_LENGTH_CHANGED';
ls_Msg1 := 'ソースの長さが変更された。';
end;
EC_NEED_RESTART: begin
ls_Msg := 'EC_NEED_RESTART';
ls_Msg1 := 'フィルタがグラフの再開を要求している。';
end;
EC_NOTIFY_WINDOW: begin
ls_Msg := 'EC_NOTIFY_WINDOW';
ls_Msg1 := 'フィルタにビデオレンダラのウィンドウを通知する。';
end;
EC_OLE_EVENT: begin
ls_Msg := 'EC_OLE_EVENT';
ls_Msg1 := 'フィルタがアプリケーションにテキスト文字列を渡している。';
end;
EC_OPENING_FILE: begin
ls_Msg := 'EC_OPENING_FILE';
ls_Msg1 := 'グラフがファイルを開いている、またはファイルを開き終えた。';
end;
EC_PALETTE_CHANGED: begin
ls_Msg := 'EC_PALETTE_CHANGED';
ls_Msg1 := 'ビデオパレットが変更された。';
end;
EC_PAUSED: begin
ls_Msg := 'EC_PAUSED';
ls_Msg1 := 'ポーズ要求が完了した。';
end;
EC_QUALITY_CHANGE: begin
ls_Msg := 'EC_QUALITY_CHANGE';
ls_Msg1 := '品質コントロールのため、グラフがサンプルを削除した。';
end;
EC_REPAINT: begin
ls_Msg := 'EC_REPAINT';
ls_Msg1 := 'ビデオレンダラが再描画を要求している。';
end;
EC_SEGMENT_STARTED: begin
ls_Msg := 'EC_SEGMENT_STARTED';
ls_Msg1 := '新しいセグメントが開始した。';
end;
EC_SHUTTING_DOWN: begin
ls_Msg := 'EC_SHUTTING_DOWN';
ls_Msg1 := 'フィルタグラフが破棄前にシャットダウンしている。';
end;
EC_SNDDEV_IN_ERROR: begin
ls_Msg := 'EC_SNDDEV_IN_ERROR';
ls_Msg1 := '入力ピンでオーディオデバイスエラーが発生した。';
end;
EC_SNDDEV_OUT_ERROR: begin
ls_Msg := 'EC_SNDDEV_OUT_ERROR';
ls_Msg1 := '出力ピンでオーディオデバイスエラーが発生した。';
end;
EC_STARVATION: begin
ls_Msg := 'EC_STARVATION';
ls_Msg1 := 'フィルタは十分なデータを受け取っていない。';
end;
EC_STATE_CHANGE: begin
ls_Msg := 'EC_STATE_CHANGE';
ls_Msg1 := 'フィルタグラフが変更された。';
end;
EC_STEP_COMPLETE: begin
ls_Msg := 'EC_STEP_COMPLETE';
ls_Msg1 := 'コマ送りを実行しているフィルタが、指定数のコマ送りを完了した。';
end;
EC_STREAM_CONTROL_STARTED: begin
ls_Msg := 'EC_STREAM_CONTROL_STARTED';
ls_Msg1 := 'ストリーム制御開始コマンドが有効になった。';
end;
EC_STREAM_CONTROL_STOPPED: begin
ls_Msg := 'EC_STREAM_CONTROL_STOPPED';
ls_Msg1 := 'ストリーム制御停止コマンドが有効になった。';
end;
EC_STREAM_ERROR_STILLPLAYING: begin
ls_Msg := 'EC_STREAM_ERROR_STILLPLAYING';
ls_Msg1 := 'ストリーム中にエラーが発生した。ストリームは引き続き再生中である。';
end;
EC_STREAM_ERROR_STOPPED: begin
ls_Msg := 'EC_STREAM_ERROR_STOPPED';
ls_Msg1 := 'エラーのためストリームが停止した。';
end;
EC_TIMECODE_AVAILABLE: begin
ls_Msg := 'EC_TIMECODE_AVAILABLE';
ls_Msg1 := 'サポートされていない。';
end;
EC_UNBUILT: begin
ls_Msg := 'EC_UNBUILT';
ls_Msg1 := 'グラフを破棄し終えたときにビデオコントロールによって送信される。アプリケーションには転送されない。';
end;
EC_USERABORT: begin
ls_Msg := 'EC_USERABORT';
ls_Msg1 := 'ユーザーが再生を強制終了した。';
end;
EC_VIDEO_SIZE_CHANGED: begin
ls_Msg := 'EC_VIDEO_SIZE_CHANGED';
ls_Msg1 := 'ネイティブビデオサイズが変更された。';
ls_Msg2 := Format('%d×%d', [LoWord(iParam1), HiWord(iParam1)]);
end;
EC_VMR_RENDERDEVICE_SET: begin
ls_Msg := 'EC_VMR_RENDERDEVICE_SET';
ls_Msg1 := 'VMRがレンダリングメカニズムを選択し終えた。';
case iParam1 of
VMR_RENDER_DEVICE_OVERLAY: ls_Msg2 := 'VMR はオーバーレイ サーフェイスにレンダリングする (VMR-7 のみ)。';
VMR_RENDER_DEVICE_VIDMEM: ls_Msg2 := 'VMR はビデオ メモリにレンダリングする。';
VMR_RENDER_DEVICE_SYSMEM: ls_Msg2 := 'VMR はシステム メモリにレンダリングする (VMR-7 のみ)。'
end;
end;
EC_VMR_SURFACE_FLIPPED: begin
ls_Msg := 'EC_VMR_SURFACE_FLIPPED';
ls_Msg1 := 'VMR-7のアロケータプレゼンタが、表示するサーフェイスのDirectDraw Flipメソッドを呼び出したときに送信される。';
end;
EC_VMR_RECONNECTION_FAILED: begin
ls_Msg := 'EC_VMR_RECONNECTION_FAILED';
ls_Msg1 := 'アップストリームデコーダから動的フォーマット変更要求を受け入れることができなかった場合に、VMR-7およびVMR-9によって送信される。';
end;
EC_WINDOW_DESTROYED: begin
ls_Msg := 'EC_WINDOW_DESTROYED';
ls_Msg1 := 'ビデオレンダラが破棄またはグラフから削除された。';
end;
EC_WMT_EVENT: begin
ls_Msg := 'EC_WMT_EVENT';
ls_Msg1 := 'アプリケーションがASF Readerフィルタを使用して、DRM (digital rights management)によって保護されているASFファイルを再生する場合に、Windows Media Format SDKによって送信される。';
end;
EC_WMT_INDEX_EVENT: begin
ls_Msg := 'EC_WMT_INDEX_EVENT';
ls_Msg1 := 'アプリケーションがASF Writerを使用して、Windows Media Videoファイルにインデックスを付ける場合に、Windows Media Format SDKによって送信される。';
case iParam1 of
Integer(WMT_STARTED): ls_Msg2 := 'インデックス付けが開始された。';
Integer(WMT_CLOSED): ls_Msg2 := 'インデックス付けが完了した。';
Integer(WMT_INDEX_PROGRESS): ls_Msg2 := 'インデックス付けが進行中である。lParam2 は進捗の度合いをパーセントで表す。';
end;
end;
else begin
ls_Msg := '';
ls_Msg1 := '';
ls_Msg2 := '';
end;
end;
li_Len := 2;
ShowDbg(Format('%s (%2d, %d, %d)', [ls_Msg, iEventCode, iParam1, iParam2]));
ShowDbg(Format('%*s %s', [li_Len, ' ', ls_Msg1]));
if (ls_Msg2 <> '') then begin
ShowDbg(Format('%*s %s', [li_Len, ' ', ls_Msg2]));
end;
end;
end.