使用Delphi自动化VideoLan的VLC [英] Automating VideoLan's VLC using Delphi
问题描述
我已经从VideoLan VLC播放器的v.2.2.1
生成了一个类型库导入单元,并将所得的插件组件嵌入到一个简单的Delphi(D7和XE8)表单中。代码摘要在下面。
I've generated a type-library import unit from v.2.2.1 of VideoLan's VLC player and embedded the resulting plug-in component in a simple Delphi (D7 and XE8) form. Code extract is below.
组件的基本功能很好 - 我可以播放(本地).MP4文件,
停止它,加快速度和下来等没有任何问题。但是,有一个基本的
函数不起作用,即音量控制。
The basic functionality of the component is fine - I can play a (local) .MP4 file, stop it, speed it up and down, etc without any problem. However, there is one basic function which is not working, namely volume control.
插件显示v。simple(与VLC作为应用程序运行)
toobar在底部有两个轨道栏,一个显示+更改播放
在视频中的位置,另一个用于控制音频音量。后者是
,最初显示为100(%)。
The plug-in displays a v. simple (compared with the one in VLC running as an app) toobar at the bottom with two track-bars, one to display + change the playing position in the video and the other for controlling audio volume. The latter is initially shown with the volume at 100 (%).
如果我尝试通过点击轨道栏来更改它,我得到一个太多未处理的
异常错误(EInvalidOp)。如果我安装了一个Application.OnException处理程序,并且
捕获异常,插件将变得无响应,我必须在IDE中重新设置
。如果我在代码中读取Volume设置,然后将
设置为刚刚读取的值,那么也会发生。
If I attempt to change it by clicking on the track bar, I get a "Too many unhandled exceptions" error (EInvalidOp). If I install an Application.OnException handler and catch the exception, the plug-in becomes unresponsive and I have to reset the app in the IDE. The same happens if I read the Volume setting in code and then just set it to the value I've just read.
在事件中,在呼叫中,Get8087CW返回相同的值,
4798,因为我在应用启动时保存。
Inside events that the plug-in calls out from, Get8087CW returns the same value, 4798, as I save when the app starts.
我的问题是:如何避免这些异常尝试通过GUI跟踪栏或代码更改
卷?我错过了一步,也许或者是有
我可以做的是将8087的值或异常处理设置为
,阻止应用锁定? (btw,可以在代码中显示插件的工具栏,所以如果一切都失败,我可以用自己的方式替换它,但是如果可能,我宁愿让VLC一个正常工作)。
My question is: How to avoid these exceptions when attempting to change the volume via the GUI trackbar or in code? Am I missing a step, maybe, or is there something I could do in terms of setting the 8087 value or exception-handling to prevent the app locking up? (btw, it is possible to turn the display of the plug-in's toolbar in code, so I could replace it by one of my own if all else fails, but I'd rather get the VLC one working properly, if possible).
代码:
TForm1 = class(TForm)
VLCPlugin1: TVLCPlugin;
[...]
public
{ Public declarations }
IPlugIn : IVlcControl;
IPlugIn2 : IVlcControl2;
Input : IVlcInput;
PlayList : IVlcPlayList;
IAudio : IVlcAudio;
Speed : Integer;
Volume : Integer;
Saved8087CW : Integer;
procedure PlayFile;
property FileName : WideString read FFileName write SetFileName;
end;
// This routine, NoOp, is one I've used since D1 to facilitate single-stepping
// through code and checking values on the way. It accesses the NoOpCount
// global variable because I assumed/hoped the compiler's optimiser wouldn't optimise it away.
var
NoOpCount : Integer;
procedure NoOp;
begin
Inc(NoOpCount);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnException := HandleException;
Saved8087CW := Get8087CW;
end;
procedure TForm1.PlayFile;
begin
Assert((Trim(FileName) <> '') and (FileExists(FileName)));
if VLCPlugIn1.Playing then
VLCPlugIn1.stop;
IPlugIn := VlcPlugIn1.ControlInterface;
//VLC's VLCPlugIn2 contains some extra methods compared to VLCPlugIn, so
IPlugIn.QueryInterface(VlcPlugIn2, IPlugIn2);
if IPlugIn2 = Nil then
NoOp
else
NoOp;
IAudio := IPlugIn2.Audio; // this is the interface to the object which gets/sets the volume
if IAudio = Nil then
NoOp
else
NoOp;
Input := IPlugIn2.Input;
if Input = Nil then
NoOp
else
NoOp;
VLCPlugin1.addTarget('file:///' + FileName, null, VLCPlayListInsert, 0);
{ The following assignment to IAudio.Volume causes an EInvalidOp exception
Volume := IAudio.Volume;
IAudio.Volume := Volume;
}
VlcPlugIn1.AutoLoop := True;
IPlugIn2.playlist.play;
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if IPlugIn.Playing then
IPlugIn.Stop;
end;
procedure TForm1.VLCPlugin1MediaPlayerPlaying(Sender: TObject);
begin
if Saved8087CW = Get8087CW then
NoOp
else
NoOp;
end;
procedure TForm1.VLCPlugin1play(Sender: TObject);
begin
if IAudio <> Nil then begin
Volume := IAudio.Volume;
// IAudio.Volume := Volume; <- provokes EInvalidOp
end;
end;
procedure TForm1.HandleException(Sender: TObject; E: Exception);
begin
if Saved8087CW = Get8087CW then
NoOp
else
NoOp;
end;
推荐答案
尝试在启动时禁用FPU异常:
Try to disable FPU exceptions on startup:
Set8087CW($133F);
或(用于现代Delphi)
Or (for modern Delphi)
Math.SetExceptionMask(exAllArithmeticExceptions);
这篇关于使用Delphi自动化VideoLan的VLC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!