使用Delphi自动化VideoLan的VLC

Mar*_*ynA 2 delphi exception-handling vlc

我已经从VideoLan的VLC播放器的v.2.2.1生成了一个类型库导入单元,并将生成的插件组件嵌入到一个简单的Delphi(D7和XE8)表单中.代码提取如下.

组件的基本功能很好 - 我可以播放(本地).MP4文件,停止它,上下加速等等,没有任何问题.但是,有一个基本功能不起作用,即音量控制.

插件显示v.简单(与作为应用程序运行的VLC中的插件相比)底部有两个轨道条,一个用于显示+更改视频中的播放位置,另一个用于控制音量.后者最初显示体积为100(%).

如果我尝试通过单击轨迹栏来更改它,我会收到"太多未处理的异常"错误(EInvalidOp).如果我安装Application.OnException处理程序并捕获异常,插件将无响应,我必须在IDE中重置应用程序.如果我在代码中读取音量设置然后将其设置为我刚读过的值,则会发生同样的情况.

在插件调用的内部事件中,Get8087CW返回相同的值4798,就像应用程序启动时保存的那样.

我的问题是:如何在尝试通过GUI轨道栏或代码更改音量时避免这些异常?我可能错过了一个步骤,或者在设置8087值或异常处理方面我能做些什么以防止应用程序锁定?(顺便说一下,可以在代码中打开插件工具栏的显示,所以如果其他所有方法都失败了,我可以用我自己的替换它,但我宁愿让VLC工作正常,如果可能的话).

码:

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;
Run Code Online (Sandbox Code Playgroud)

kob*_*bik 6

尝试在启动时禁用FPU异常:

Set8087CW($133F);
Run Code Online (Sandbox Code Playgroud)

或者(对于现代德尔福)

Math.SetExceptionMask(exAllArithmeticExceptions);
Run Code Online (Sandbox Code Playgroud)