多线程下如何创建Tmediaplayer对象 ( 积分: 30 )

  • 主题发起人 主题发起人 weismart
  • 开始时间 开始时间
W

weismart

Unregistered / Unconfirmed
GUEST, unregistred user!
多线程下如何创建Tmediaplayer对象??
主线程中若是有过程
var
Myplayer:Tmediaplayer;
begin
Myplayer:=Tmediaplayer.create(self);
Myplayer.parent:=self;
Myplayer.filename='d:/test.wav';
Myplayer.wait:=true;
Myplayer.play;
下面接着再放n个文件。。。。
end;
[green]这样做的话,播放声音时,程序界面会停住不动了,而且根本不可能同时播放几个声音文件
(可能用N个,但N事先是未知的,是动态变化的)
于是,我想在子线程中动态生成N个Tmediaplayer对象, 可不知道在线程中
Tmediaplayer.create()的参数如何写。求助[/green]
 
多线程下如何创建Tmediaplayer对象??
主线程中若是有过程
var
Myplayer:Tmediaplayer;
begin
Myplayer:=Tmediaplayer.create(self);
Myplayer.parent:=self;
Myplayer.filename='d:/test.wav';
Myplayer.wait:=true;
Myplayer.play;
下面接着再放n个文件。。。。
end;
[green]这样做的话,播放声音时,程序界面会停住不动了,而且根本不可能同时播放几个声音文件
(可能用N个,但N事先是未知的,是动态变化的)
于是,我想在子线程中动态生成N个Tmediaplayer对象, 可不知道在线程中
Tmediaplayer.create()的参数如何写。求助[/green]
 
注:这N个wav需要同时播放,而且每个音声一定要播放出来。
如果在主进程中放置一个TMediaplayer然后在线程中指定Fmediaplayer.wait:=true
这样可以播完所有wav文件,但此时主窗体停住了,动不了,所以我必须在线程中动态生成n个Tmediaplayer对象,然后其wait属性设成false
线程FreeOnTerminate:=True;就ok了,但创建时Tmediaplayer对象时create的参数不知如何写。
 
不会因为分少就没人回答吧,实在不好意思,我就这点分了呀。可怜。[:(!]
 
不明白你想要什么样的效果?是同时播放还是一首一首播放?
同时播放:用多个MediaPlayer,且Wait属性不要设成true;
一首一首播放:在MediaPlayer的OnNotify事件里处理一下,让其播放下一首即可;
我觉得不需要用多线程的。
 
是要同时播放,而且播放时主界面不能停顿,不用多线程不能达到主界面不停屯的效果。
我是想在线程中动态生成TMediaplayer对象,然后在excute中播放,wait属性设为False
这样就可以实现了。但不知道线程中动态生成Tmediaplayer对象时create()的参数应如何填写。
另外,到底应生成多少个线程实例,事先是不知道的。所以楼上的朋友说用多个mediaplayer来播放的法子好象不太好。
 
那你可以将创建并播放的代码在主界面窗体中写成一个过程(procedure),然后作为参数传入线程中,如:
type
TSkyInitThread = class(TThread)
private
FInitProc: TThreadMethod;
protected
procedure Execute;
override;
public
constructor Create(InitProc: TThreadMethod);
end;

constructor TSkyInitThread.Create(InitProc: TThreadMethod);
begin
FreeOnTerminate := True;
inherited Create(True);
FInitProc := InitProc;
end;

procedure TSkyInitThread.Execute;
begin
if Assigned(FInitProc) then
Synchronize(FInitProc);
//注意:应用Synchronize()调用!!!
end;

procedure TForm1.DoInit;
begin
//...
end;
调用:
with TSkyInitThread.Create(DoInit)do
begin
Resume();
end;
 
谢谢楼上的朋友,我先测试一下看是否可行!另外请问一个问题:线程中调用主窗体中定义的函数或过程,如果被调用的函数或过程中包含vlc,那最常用的外理办法是。。。。
因为实在不想更改那些函数或过程。
 
To dreamisx
谢谢你的帮助
经测试,还是不行呀
1、不能生成多个线程实例,否则出错。
2、如果我在doinit过程中加入参数(主要是为了选择不同的wav文件),
则线程单元中编译不能通过。
请您再帮帮看,我的doinit如下:
测试代码,不言美观
procedure TForm1.DoInit;
var
player:Tmediaplayer;
begin
player:=Tmediaplayer.Create(self);
player.Parent:=self;
player.Visible:=False;
player.close;
player.FileName:='d:/i.wav';
player.Wait:=false;
player.Open;
player.Play;
end;
 
得,给你一个例子,我刚刚做的,用线程同时放两个mp3文件:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MPlayer;
type
TInitMethod = procedure(const sFileName: String) of object;
TSkyInitThread = class(TThread)
private
FInitProc: TInitMethod;
FFileName: String;
procedure InnerProc;
protected
procedure Execute;
override;
public
constructor Create(InitProc: TInitMethod;
const sFileName: String);
end;

TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure MediaPlayer1Notify(Sender: TObject);
private
{ Private declarations }
proceduredo
Init(const sFileName: String);
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
constructor TSkyInitThread.Create(InitProc: TInitMethod;
const sFileName: String);
begin
FreeOnTerminate := True;
inherited Create(True);
FInitProc := InitProc;
FFileName := sFileName;
end;

procedure TSkyInitThread.InnerProc;
begin
if Assigned(FInitProc) then
FInitProc(FFileName);
end;

procedure TSkyInitThread.Execute;
begin
Synchronize(InnerProc);
//注意:应用Synchronize()调用!!!
end;


procedure TForm1.DoInit(const sFileName: String);
begin
with TMediaPlayer.Create(Self)do
try
Parent := Self;
Visible := False;
FileName := sFileName;
OnNotify := MediaPlayer1Notify;
//只是测试一下,可不要
Open;
Play;
finally
//Free;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
with TSkyInitThread.Create(DoInit, 'F:/Sky/mp3_A_01/DreamLand-children.mp3')do
begin
Resume();
end;
with TSkyInitThread.Create(DoInit, 'F:/Sky/mp3_A_01/三万英尺(迪克牛仔).mp3')do
begin
Resume();
end;
end;

procedure TForm1.MediaPlayer1Notify(Sender: TObject);
begin
if Sender is TMediaPlayer then
Sender.Free;
end;

end.
 
非常感谢!!可惜我没有这么多分送给你。
TInitMethod = procedure(const sFileName: String) of object;
这是什么东西呀?不太明白。
为什么把procedure 当成这样?总体上明白是怎么回事,但就这句语法看不懂。好象是回调函数什么来着?
不好意思,我刚学delphi,很多地方还很椎嫩。
 
你查一下帮助中关于Procedural types的说明(是Overview的那个)。
 
还有,我发现,如果两个线程实例调用doinit(mp3文件)之文件相同时,程序会出错。
能否再稍改一下,谢谢你的指点。一定努力多多!
 
Procedural types allow you to treat procedures and functions as values that can be assigned to variables or passed to other procedures and functions.
看到了,原来如此!看来想真正运用delphi,该用功学的东西太多了。
一个月来的少许进步,我还自以为是呢。错!!!!!
还有,我发现,如果两个线程实例调用doinit(mp3文件)之文件相同时,程序会出错。
能否再稍改一下,谢谢你的指点。一定努力多多!
 
没仔细研究过MediaPlayer,我也试了下,在Delphi下运行时的确会报错;
不过,脱离开发环境单独运行就不报错(虽然可能也只有一个在正确运行,没测试过);
本来嘛,两个相同又一起启动就没什么意义,先这样用着吧,我一时也找不到好办法噢^!^
 
我试了一下,用两个不同的Tmediaplayer(1、2)控件一先一后打开同一个文件,后打开的一定会报错。但是用两个程序各带一个mediaplayer控件,即便是同时打开同一个文件也不会报错。Tmediaplayer 控件的属性基本上我都一个个试过了(我手上没有什么资料,瞎猜着试的),没成功过。好象文件被锁定了?
我想用这个来试着做报警系统,因为同一时间可能会有同一级别的多个报警触发信息被送到(即便是一先一后,时间差可能也没有声乐文件播放时长长)
 
播放Wav不要用MediaPlayer控件,太耗资源。
用Jedi DirectX Header
然后用DirectMusic直接加载Wave文件就行了
只要建立一个TDirectMusicPerformance
对每个声音建一个TDirectMusicSegment然后调用Play/Stop方法就行了
很简单的
 
需要jedi DirectX Header的话用qq 9869281找我要
 
感觉还是用delphi自带的东西好一些。
 
后退
顶部