2

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.

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.

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 (%).

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.

Inside events that the plug-in calls out from, Get8087CW returns the same value, 4798, as I save when the app starts.

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).

Code:

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;
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • 2
    Try to disable FPU exceptions on startup `Set8087CW(₪501.75 ($133)F)` or `Math.SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);` – kobik Jul 31 '15 at 09:54
  • @kobik: Thanks, that (Set8087CW($133) )seems to have fixed it. Please post that as an answer & I'll accept. – MartynA Jul 31 '15 at 09:59
  • I had a type (in my chrome settings). should be `Set8087CW($133F)` – kobik Jul 31 '15 at 10:38
  • @kobik: It's ok, I gt the value from the first (shorter) version of your comment, which had $133f. My typo, sorry. – MartynA Jul 31 '15 at 10:43
  • I had similar problem myself, and this is also related: http://stackoverflow.com/questions/8200581/twebbrowser-crashes-with-embedded-youtube-clips – kobik Jul 31 '15 at 10:45

1 Answers1

6

Try to disable FPU exceptions on startup:

Set8087CW($133F);

Or (for modern Delphi)

Math.SetExceptionMask(exAllArithmeticExceptions);
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
kobik
  • 21,001
  • 4
  • 61
  • 121