TWindowsMediaPlayerで個々のファイルを連続再生させるには

解決


武田  2009-03-14 04:35:37  No: 33641

みなさんお世話になっております。環境はWindowsXP Delphi6Personalです。

TWindowsMediaPlayerでファイルを個々に与えて再生終了の度に次のファイルを
連続自動再生させようとしていますがうまくいきません。
本来はWindowsMediaPlayer1.currentPlaylist.appendItem(Media);で一括してプレイヤーに読み込んで再生するのが普通だと思いますが、対応外のファイルMOVなどが混ざるとエラーになります。
 そのためWindowsMediaPlayer1.URL:=ファイル名  で再生させると実行してくれますから
WindowsMediaPlayer1PlayStateChangeのイベントを利用して
次の再生を自動でできないか試みているのですがうまくいきません。
プレイヤーの再生ボタンをクリックしてやると再生するのですが。
よろしくご指導下さい。下記のようなコードでテストしています。
PlayListNo:integer; //プレイ中のリスト番号
procedure TForm1.Button1Click(Sender: TObject);
begin
    PlayListNo:=0;//開始番号を指定する。
    MoviePlay;
end;
procedure TForm1.MoviePlay;
begin
    WindowsMediaPlayer1.URL:=ListBox1.Items.Strings[PlayListNo];
    if PlayListNo< ListBox1.Items.Count then Inc(PlayListNo);
end;
//イベントを監視して終わったら次のファイルを実行させたいのだが・・・・・?
procedure TForm1.WindowsMediaPlayer1PlayStateChange(Sender: TObject;
  NewState: Integer);
const   //  SDK そのままの説明文
    PLAY_STATE_STR: array[0..10] of string
    = ('Undefined', 'Stopped','Paused','Playing','ScanForward','ScanReverse',
       'Buffering','Waiting','MediaEnded','Transitioning','Ready');
var
    s: string;
begin
    if (Low(PLAY_STATE_STR) <= NewState) and (NewState <= High(PLAY_STATE_STR)) then
        s := PLAY_STATE_STR[NewState];

    if s='MediaEnded' then
    begin MoviePlay;end;
end;


D  2009-03-14 10:20:02  No: 33642

procedure TForm1.MoviePlay;
begin
  if (PlayListNo < ListBox1.Count) then begin
    WindowsMediaPlayer1.URL := ListBox1.Items[PlayListNo];
    WindowsMediaPlayer1.controls.play;
    Inc(PlayListNo);
  end;
end;

procedure TForm1.PlayerPlayStateChange(Sender: TObject; NewState: Integer);
begin
  case NewState of
    wmppsMediaEnded: begin
      MoviePlay;
    end;
    wmppsReady: begin
      if (Assigned(WindowsMediaPlayer1.currentMedia)) then begin
        WindowsMediaPlayer1.controls.play;
      end;
    end;
  end;
end;

これでOKと思います。

ちなみに、
http://cult-drang.com/program/tips/index.html
でTWindowsMediaPlayerを使って色々やってますのでよろしければどうぞ。


武田  2009-03-14 22:51:19  No: 33643

Dさん、有り難うございます。
さっそく今から挑戦してみます。
レベルが高くない者にとって
マルチメディアの扱いは大変難しいですね。
しかし、自作のプログラムで動画が再生されたり
音楽がなったりするのは感動です。
また、いいサイトをご紹介頂き有り難うございます。
また教えてください。


武田  2009-03-15 01:42:42  No: 33644

Dさん
実験してみましたが
クイックタイムの.MOVファイルや
音楽CDの.cdaファイルのリストの場合
連続演奏できませんでした。
引き続き挑戦してみます。


武田  2009-03-15 03:54:02  No: 33645

いろいろ自分なりにやってみたのですが
演奏中ループで回してやると
MOV、音楽CDのcdaもwmvもmpgもaviファイルも
連続再生するのですが、
なにかスマートではない気がします。
なにか、アドバイスが有りましたら、教えてください。

procedure TForm1.WindowsMediaPlayer1PlayStateChange(Sender: TObject;
  NewState: Integer);
begin
  if NewState = wmppsMediaEnded then PlayMode:=false;
end;
//開始番号を渡してやる
procedure TForm1.MoviePlay(StartNo:integer); //ナビから投げられたか?
begin
    PlayListNo:=StartNo;
  while (PlayListNo <  ListBox1.Items.Count) do
  begin
        WindowsMediaPlayer1.controls.stop;
        WindowsMediaPlayer1.currentPlaylist.clear;

      WindowsMediaPlayer1.URL:=ListBox1.Items.Strings[PlayListNo];
        WindowsMediaPlayer1.controls.play;
        PlayMode:=true;
       while PlayMode do  //演奏中ループで回す
      begin
          Application.ProcessMessages;
            Sleep(20);
      end;
      Inc(PlayListNo);
        if linksSkipFlag=1 then break;
  end;
end;


D  2009-03-15 12:04:33  No: 33646

>音楽CDの.cdaファイルのリストの場合
>連続演奏できませんでした。

あらら、これは失礼いたしました。
確かに止まりますね。

OnPlayStateChangeイベントだけでなくOnOpenStateChangeイベントも調べてみたら、*.cdaの場合wmposPlaylistOpenNoMediaで止まりますね。
ということでNewStateがwmposPlaylistOpenNoMediaのときにcontrols.playを呼んでみたら次のwmposMediaOpenで止まりました。
ならばとwmposMediaOpenでもcontrols.playを呼んでみたら連続再生できました。
が、*.wmaの次に*.cdaや*.cdaの次に*.wmaが続くと止まってしまいます。

あれこれと値を確かめたりタイミングや処理の流れを追ってみた結果、OnPlayStateChangeイベントのwmppsMediaEndedでMoviePlayを呼んだ後にも色々とイベントが起きていました。
MoviePlay中でURLに値をセットし終わる前にOnOpenStateChangeのNewStateがwmposPlaylistOpenNoMediaのイベントが起きてしまうことで、おかしなことになり止まってしまっていたようです。

ということで、MoviePlay中でURLに値をセットし終わるまでイベントを無視するF_bStopというフラグを使うようにしてみました。

  private
    { Private 宣言 }
    F_bStop:    Boolean;
    PlayListNo: Integer;

    procedure MoviePlay;
  public
    { Public 宣言 }
  end;

procedure TForm1.MoviePlay;
begin
  if (PlayListNo < ListBox1.Count) then begin
    WindowsMediaPlayer1.controls.stop;
    WindowsMediaPlayer1.currentPlaylist.clear;

    WindowsMediaPlayer1.URL := ListBox1.Items[PlayListNo];
    F_bStop := False;
    WindowsMediaPlayer1.controls.play;
    Inc(PlayListNo);
  end;
end;

procedure TForm1.PlayerOpenStateChange(Sender: TObject; NewState: Integer);
begin
  case NewState of
    wmposPlaylistOpenNoMedia, wmposMediaOpen: begin
      if not(F_bStop) and (Assigned(WindowsMediaPlayer1.currentMedia)) then begin
        WindowsMediaPlayer1.controls.play;
      end;
    end;
  end;
end;

procedure TForm1.PlayerPlayStateChange(Sender: TObject; NewState: Integer);
begin
  case NewState of
    wmppsMediaEnded: begin
      F_bStop := True;
      MoviePlay;
    end;
    wmppsReady: begin
      if not(F_bStop) and (Assigned(WindowsMediaPlayer1.currentMedia)) then begin
        WindowsMediaPlayer1.controls.play;
      end;
    end;
  end;
end;

これでどうでしょうか。
ざっと再生させてみ他結果、連続再生できているようなのですが。


武田  2009-03-16 01:36:47  No: 33647

Dさん、有り難うございます。返事が遅くなりすみません。
何か設定が違うのか以下のような現象になります。
まず、音楽CDをいれてListboxにテキストファイルからロードしておき
D:\Track01.cda
D:\Track02.cda
D:\Track03.cda
のようになります。
procedure TForm1.Button1Click(Sender: TObject);
begin
    PlayListNo:=0;
    MoviePlay;
で開始します。
一曲目が再生します。
終わるとしばらくしてから
ポーズボタンがプレイボタン(▲が横に向いた)に変わると同時に
「invalid floating point operation」というエラーがでます。
ちなみに私のXPはsp3です。wmpのヴァージョンは11.05・・です。
コンポーネントをダブルクリックして表示されるwmpの
プロパティは、再生オプションを自動再生にチェックしています。
HDDの音楽リストは
E:\マイ ドキュメント\My Music\01 ***.wma
E:\マイ ドキュメント\My Music\01 ***.wma
E:\マイ ドキュメント\My Music\01 ***.wma
エラーではなくてポーズボタンがプレイボタン(▲が横に向いた)に変わって止まります。
動画のHDDの場合は
C:\Documents and Settings\go\デスクトップ\MOVファイル\nuskin.wmv
C:\Documents and Settings\go\デスクトップ\MOVファイル\DSCN1392.MOV
C:\Documents and Settings\go\デスクトップ\MOVファイル\DSCN1402.MOV
C:\Documents and Settings\go\デスクトップ\MOVファイル\IMAG0044.AVI
エラーではなくてポーズボタンがプレイボタン(▲が横に向いた)に変わって止まります。
何かコンポーネントのセットが関係しますか念のため
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, WMPLib_TLB, StdCtrls;
です。
ひきつづきトライしてみます。
そっくり他のパソコンへ移植してやってみます。
では。


武田  2009-03-16 03:05:01  No: 33648

Dさん、ご報告します。
私が今使っているPCでコンパイルしたプログラムを
他のPCで実行すると、うまくいきました。
逆に他のPCでコンパイルしたのもそのPCでOKでした。
そのexeをこのPCで実行するとだめでした。
ということは、このPCの何かが違うことになります。
他のPCもDelphi6Personalです。XPプロフェッショナルでsp3です。
違うのはこのPCがhomeで他のPCがプロフェッショナルという違いですが
何か設定が違うのでしょう。
ご迷惑おかけしました。
もし他の人が使うソフトなら動かないということが起きるわけですから。
今から原因を探してみます。
何かヒントがございましたら、教えてください。

今回は有り難うございました。


D  2009-03-16 04:46:54  No: 33649

う〜ん、、これでも止まってしまいますか。
うちでは出ない現象なのでどこがだめな部分なのか分かりません。
ちなみに私はDelphi 6 Pro、XP HomeのSP2、WMPは10です。
PCによって動いたり動かなかったりということだと、ffdshowなどをインストールしていたら、そのあたりのからみなのかもしれないかなぁ…というくらいですかね。

とりあえず、MoviePlayのWindowsMediaPlayer1.currentPlaylist.clear;をtry文で囲ってみてください。
これでエラーが出なくなれば、、という期待をこめて。

    WindowsMediaPlayer1.controls.stop;
    try
      WindowsMediaPlayer1.currentPlaylist.clear;
    except end;

で、例えばMemoをフォームに貼り付けて、

procedure TForm1.MoviePlay;
begin
  if (PlayListNo < ListBox1.Count) then begin
    Memo1.Lines.Add('MoviePlay - in  controls.stop');
    WindowsMediaPlayer1.controls.stop;
    Memo1.Lines.Add('MoviePlay - out controls.stop');
    try
      Memo1.Lines.Add('MoviePlay - in  currentPlaylist.clear');
      WindowsMediaPlayer1.currentPlaylist.clear;
      Memo1.Lines.Add('MoviePlay - out currentPlaylist.clear');
    except end;

    Memo1.Lines.Add('MoviePlay - in  URL');
    WindowsMediaPlayer1.URL := ListBox1.Items[PlayListNo];
    Memo1.Lines.Add('MoviePlay - out URL');
    F_bStop := False;
    Memo1.Lines.Add('MoviePlay - in  controls.play');
    WindowsMediaPlayer1.controls.play;
    Memo1.Lines.Add('MoviePlay - out controls.play');
    Inc(PlayListNo);
  end;
end;

のようにデバッグコードを仕込んで走らせればエラーが出るところを特定できるかもしれません。
MoviePlayだけでなくOnPlayStateChangeイベントやOnOpenStateChangeイベント内でも同様にデバッグコードを仕込みます。
面倒ですがやってみて損はないと思います。

それでもだめなら

>演奏中ループで回してやると
>MOV、音楽CDのcdaもwmvもmpgもaviファイルも
>連続再生するのですが、

ということなので、それでも良いと思います。
たとえスマートなやり方でなくても、ちゃんと動くことの方が重要だと思いますので。
ただループを使うよりはタイマーを使って監視した方が楽ではないかなぁと思います。


武田  2009-03-16 07:30:54  No: 33650

ご指示のエラールーチンを付けると下記のようなログでエラーはでません。
が二曲目を演奏しません。
●はイベントメッセージも記録してみました。
Memo1
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
●PlayStateChange--Transitioning
●PlayStateChange--Ready
PlayStateChange--wmppsReady--in
PlayStateChange--wmppsReady--out
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
●PlayStateChange--Playing
●PlayStateChange--MediaEnded
PlayStateChange--wmppsMediaEnded--in
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
●PlayStateChange--Transitioning
●PlayStateChange--Undefined
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
●PlayStateChange--Transitioning
●PlayStateChange--Ready
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
PlayStateChange--wmppsMediaEnded--out

----------------------------------ここでストップして二曲目を演奏しません。
エラールーチンを外してもエラーはでませんでした(でたこともありましたが)
Memo1
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
●PlayStateChange--Transitioning
●PlayStateChange--Ready
PlayStateChange--wmppsReady--in
PlayStateChange--wmppsReady--out
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
●PlayStateChange--Playing
●PlayStateChange--MediaEnded
PlayStateChange--wmppsMediaEnded--in
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
●PlayStateChange--Transitioning
●PlayStateChange--Undefined
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
●PlayStateChange--Transitioning
●PlayStateChange--Ready
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
PlayStateChange--wmppsMediaEnded--out
何か解るでしょうか?


武田  2009-03-16 07:37:32  No: 33651

タイマーを使って監視する方法のヒントがありましたら
教えて頂けませんか。
明らかにマシンにより作動したりしなかったりするわけですから
完全に作動する安全パイも作成しておこうと思います。
しかし、今後もチャレンジします。


武田  2009-03-16 08:04:03  No: 33652

Dさん、すみません、OpenStateChangeの
ログをとるのを忘れていました。

そして、現在正常に連続演奏します。原因がわかりません。

タイミングなのでしょうか、デバッグコードを入れただけです。
ログは次のようです。
-------------------------------音楽CDの場合連続再生します。
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
●PlayStateChange--Ready
○PlayStateChange--wmppsReady--in
○PlayStateChange--wmppsReady--out
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
●PlayStateChange--Playing
●PlayStateChange--MediaEnded
○PlayStateChange--wmppsMediaEnded--MoviePlay--in
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
●PlayStateChange--Undefined
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
▲OpenStateChange
●PlayStateChange--Ready
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
○PlayStateChange--wmppsMediaEnded--MoviePlay--out
▲OpenStateChange
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
●PlayStateChange--Playing
-----------------------------------------動画の場合連続再生しません
Memo1
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
▲OpenStateChange
▲OpenStateChange--controls.play--in
▲OpenStateChange--controls.play--out
●PlayStateChange--Playing
●PlayStateChange--MediaEnded
○PlayStateChange--wmppsMediaEnded--MoviePlay--in
MoviePlay - in  controls.stop
MoviePlay - out controls.stop
MoviePlay - in  currentPlaylist.clear
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
●PlayStateChange--Undefined
MoviePlay - out currentPlaylist.clear
MoviePlay - in  URL
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
▲OpenStateChange
▲OpenStateChange
●PlayStateChange--Transitioning
▲OpenStateChange
MoviePlay - out URL
MoviePlay - in  controls.play
MoviePlay - out controls.play
○PlayStateChange--wmppsMediaEnded--MoviePlay--out


当たるもハッケヨイ、残った?  2009-03-17 02:06:36  No: 33653

真琴:「ハルコさん、ややこしくて次の動画が始まらない原因が分かりにくいよね?」
春子:「そうかな?」
真琴:「えっ? ハルコさんは原因が分かったの?」
春子:「マコト、ログをヨク見てごらん、止まる時は"MediaEnded"のイベントを抜ける前に次のURLのセットやPlayコマンドがあるよ」
真琴:「う〜ん…、あ、そういえばそうなってる…」
春子:「次の動画が始まる場合には、そのイベントを抜けた後に Playコマンドがあるでしょ?」
真琴:「分かったよ、ハルコさん、Playコマンドを少し遅らせればイイんじゃない?」
春子:「まぁ、そうだけど、どうやって遅らせればイイと思う?」
真琴:「Sleep()とかじゃダメ?」
春子:「MoviePlay関数の中にSleepを入れても、それは"MediaEnded"のイベントの中よ、いくら待ってもイベントからは抜けないって」
真琴:「あ、そういうコトかぁ…、じゃぁどうすればイイの?」
春子:「もし止まった時でもPlayボタンを押せばスタートするよね? だから…」

  ...........
  private
   procedure WindowsMediaPlayer1PlayStateChange(Sender: TObject; NewState: Integer);
   procedure AppMessage(var Msg: TMessage); message WM_APP;
  ...........

var
  PlayListNo: Integer;

procedure TForm1.AppMessage(var Msg: TMessage);
begin
  Memo1.Lines.Add('AppMessage-SetURL-in');
//if PlayListNo < ListBox1.Items.Count-1 then Inc(PlayListNo) else PlayListNo := 0;
  TWindowsMediaPlayer(Msg.WPARAM).URL := ListBox1.Items[PlayListNo];
//TWindowsMediaPlayer(Msg.WPARAM).Controls.Play;
  Memo1.Lines.Add('AppMessage-SetURL-out');
end;

procedure TForm1.WindowsMediaPlayer1PlayStateChange(Sender: TObject; NewState: Integer);
const
  PLAY_STATE_STR: array[0..10] of string =
   ('Undefined', 'Stopped','Paused','Playing','ScanForward','ScanReverse',
    'Buffering','Waiting','MediaEnded','Transitioning','Ready');
var
  s: string;
begin
  if Application.Terminated then exit;
  if (Low(PLAY_STATE_STR) <= NewState) and (NewState <= High(PLAY_STATE_STR)) then
   s := PLAY_STATE_STR[NewState];
  Memo1.Lines.Add('●'+ s);
  case NewState of
// wmppsMediaEnded:
   wmppsStopped:
  begin
   Memo1.Lines.Add('PlayStateChange['+ s +']-PostMessage-in');
   if PlayListNo < ListBox1.Items.Count-1 then Inc(PlayListNo) else PlayListNo := 0;
   PostMessage(Handle, WM_APP, WPARAM(TWindowsMediaPlayer(Sender)), 0);
   Memo1.Lines.Add('PlayStateChange['+ s +']-PostMessage-out');
  end;
   wmppsReady:
  begin
   Memo1.Lines.Add('PlayStateChange['+ s +']-PostMessage-in');
   if (Assigned(TWindowsMediaPlayer(Sender).currentMedia)) then begin
    PostMessage(Handle, WM_APP, WPARAM(TWindowsMediaPlayer(Sender)), 0);
   end;
   Memo1.Lines.Add('PlayStateChange['+ s +']-PostMessage-out');
  end;
  end;
end;

真琴:「あ、ナルホド〜…Messageなの…」
春子:「そぅ、この場合は PostMessageよ」
真琴:「aviやflvの動画はこれでOKね、でも、movやCDでも大丈夫かなぁ…ないから確認できないし」
春子:「質問者とはPCの環境も違うから、コレでウマクいくかは"当たるも八卦"ってトコかな?」
真琴:「ハズレもある?」
春子:「あるかもよ、なにしろ昨日の相撲で日馬富士が負けちゃったから」
真琴:「…、ハルコさん、それって、コレとどんなカンケイ?」


武田  2009-03-18 02:07:03  No: 33654

当たるもハッケヨイ、残った? さん大変有り難うございました。
その後もず〜っとやっていたのですが、難しいですね。
アドバイスをはじめから読み直してみようときてみたら
新しい返事を拝見しました。
これで、私のpcでも動きます。

有り難うございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加