unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, Buttons, ImgList, ToolWin, ExtCtrls, Menus, StdCtrls,
  AppEvnts;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    StatusBar1: TStatusBar;
    ToolBar1: TToolBar;
    ImageList: TImageList;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    SpeedButton1: TSpeedButton;
    ToolButton8: TToolButton;
    TrackBar2: TTrackBar;
    ToolButton1: TToolButton;
    PaintBox1: TPaintBox;
    OpenDialog1: TOpenDialog;
    VisTimer: TTimer;
    Timer1: TTimer;
    PopupMenu1: TPopupMenu;
    Source1: TMenuItem;
    N431: TMenuItem;
    N1691: TMenuItem;
    Free1: TMenuItem;
    ToolButton9: TToolButton;
    SoundLevel: TTrackBar;
    ToolButton10: TToolButton;
    SaveDialog1: TSaveDialog;
    N1: TMenuItem;
    Filter1: TMenuItem;
    ApplicationEvents1: TApplicationEvents;
    Label1: TLabel;
    TrackBar1: TTrackBar;
    Label2: TLabel;
    Button1: TButton;
    CheckBox1: TCheckBox;
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure FormDblClick(Sender: TObject);
    procedure VisTimerTimer(Sender: TObject);
    procedure SoundLevelChange(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
    procedure ToolButton5Click(Sender: TObject);
    procedure ToolButton2Click(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    procedure ToolButton3Click(Sender: TObject);
    procedure Source1Click(Sender: TObject);
    procedure N431Click(Sender: TObject);
    procedure N1691Click(Sender: TObject);
    procedure Free1Click(Sender: TObject);
    procedure ToolButton9Click(Sender: TObject);
    procedure ToolButton10Click(Sender: TObject);
    procedure ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    procedure CheckBox1Click(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    isFullScreen : Boolean;
    OldRect : TRect;
    OldStyle : Longint;
    procedure WndProc(var Msg : TMessage); override;
    procedure ActiveSomeStuff;
    procedure WhenFormResize;

  end;

var
  Form1: TForm1;
  chan : DWORD;
  source : WideString;
implementation

uses BassVideo, bass, osc_vis;

var Vis : TOcilloScope;
    PData : PByte;
{$R *.dfm}

// function to convert time to string data
function FormatNum(i, num : integer): string;
begin
 str(i, result);
 while length(result) < num do result := '0' + result;
end;

function TimeToStr5(sec : Double) : string;
var Hours, Minutes, Seconds : Double;
begin
  Hours := Trunc(sec / 3600);
  sec := sec - (Hours * 3600);
  Minutes := Trunc(sec / 60);
  sec := sec - (Minutes * 60);
  Seconds := Trunc(sec);
//  sec := (sec - Seconds) * 1000;
  Result := FormatNum(Trunc(Hours), 2) + ':' + FormatNum(Trunc(Minutes), 2) + ':'
           + FormatNum(Trunc(Seconds), 2);// + ':' + FormatNum(Trunc(sec), 3);
end;

function myVideoProc(Handle : DWORD; Action, param1, param2 : DWORD; user : Pointer): BOOL; stdcall;
var R : TRect;
begin
 case Action of
  BassVideo_FoundVideo :
    begin
      R := Form1.ClientRect;
      R.Left := 0;
      R.Top := 0;
      R.Bottom := R.Bottom - Form1.Panel1.Height - Form1.StatusBar1.Height;
      BASSVideo_SetVideoWindow(Handle, Form1.Handle, R, 0);
    end;
  BassVideo_EndStream :
   begin
    MessageBox(0, 'End of stream', 'Done', 0);
   end;
 end;
 result := TRUE;
end;

{ TForm1 }
procedure TForm1.WndProc(var Msg: TMessage);
var dc : HDC;
    ps : TPaintStruct;
begin
  if chan <> 0 then
  case Msg.Msg of
   WM_MOVE  : begin
                // apply for Windowed Renderer
                BassVideo_WindowMove(chan, Msg.Msg, Msg.WParam, Msg.LParam, 0);
              end;

   WM_SIZE  : begin
               WhenFormResize;
              end;

   WM_PAINT : begin
                 // this apply for application that use VMR9-Windowless
                 dc := BeginPaint(Handle, ps);
                 BASSVideo_Repaint(chan, Handle, DC, 0);
                 EndPaint(Handle, ps);
              end;
  end;
   inherited;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 if Shift = [ssLeft] then
  begin
   ReleaseCapture;
   Perform(WM_SYSCOMMAND, $f012, 0);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 source := '';
 Bass_Init(-1, 44100, 0, Handle, nil);
 BassVideo_Init();
 Vis := TOcilloScope.Create(PaintBox1.Width, PaintBox1.Height);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 BassVideo_Free;
 Bass_Free;
end;

function isAVI(s :string): BOOL;
begin
 result := (Pos('.avi', s) > 0) or (Pos('.AVI', s) > 0);
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var h, w : integer;
    hFile : THandle;
    sz : ULARGE_INTEGER;
    nr, videotype : DWORD;
begin
 if not OpenDialog1.Execute then exit;
 if chan <> 0 then
  begin
    BassVideo_CloseWindow(chan, 0);
    BassVideo_Stop(chan);
    BassVideo_StreamFree(chan);
  end;

 if isAVI(opendialog1.FileName) then
  videotype := BASSVIDEO_MEDIA_AVI
 else
  videotype := 0;
 hFile := CreateFile(PChar(OpenDialog1.FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 if hFile = DWORD(-1) then exit;
 sz.LowPart := GetFileSize(hFile, @sz.HighPart);
 if pData <> nil then
  Freemem(pData);
 Getmem(PData, sz.LowPart);
 if ReadFile(hFile, PData^, sz.LowPart, nr, nil) then
 chan := BassVideo_StreamCreateFileMem(PData, nr, videotype, 0, 0, @myVideoProc, nil)
 else chan := 0;
 CloseHandle(hFile);

 // chan := BassVideo_StreamCreateFile(PChar(OpenDialog1.FileName), 0, 0, @myVideoProc, nil);
 if chan <> 0 then
  begin
   ActiveSomeStuff;
   BassVideo_Play(chan);
   source := OpenDialog1.FileName;
   BassVideo_GetVideoInfo(chan, h, w);
   if (h <> 0) and (w <> 0) then
    begin
      Height := h + Panel1.Height + StatusBar1.Height;
      Width := w;
    end;
  end
 else source := '';
end;

procedure TForm1.FormDblClick(Sender: TObject);
begin
 isFullScreen := not isFullScreen;
 if isFullScreen then
  begin
    OldRect.Left := Left;
    OldRect.Top := Top;
    OldRect.Right := Width;
    OldRect.Bottom := Height;
    OldStyle := GetWindowLong(Handle, GWL_STYLE);
    SetWindowLong(Handle, GWL_STYLE, integer(WS_POPUPWINDOW or WS_VISIBLE));
    Left := 0;
    Top := 0;
    Height := Screen.Height;
    Width := Screen.Width;
  end
 else
  begin
   SetWindowLong(Handle, GWL_STYLE, OldStyle);
   SetWindowPos(Handle, 0, OldRect.Left , OldRect.Top, OldRect.Right, OldRect.Bottom , 0);
  end;
end;

procedure TForm1.VisTimerTimer(Sender: TObject);
var Data : TWaveData;
begin
 if chan = 0 then exit;
 Bass_ChannelGetData(chan, @Data, 2048 + 1);
 Vis.Draw(PaintBox1.Canvas.Handle, Data, 0, PaintBox1.Height div 2);
end;

procedure TForm1.SoundLevelChange(Sender: TObject);
begin
BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, SoundLevel.Position / 10000);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var p : Double;
begin
 if chan = 0 then exit;

 p := BASSVideo_GetPosition(chan);

 StatusBar1.Panels[0].Text := TimeToStr5(p) + ' / ' + TimeToStr5(TrackBar2.Max);
 TrackBar2.OnChange := nil;
 TrackBar2.Position := Round(p);
 TrackBar2.OnChange := TrackBar2Change;
end;

procedure TForm1.TrackBar2Change(Sender: TObject);
begin
 BassVideo_SetPosition(chan, TrackBar2.Position);
end;

function FilterProc(Handle : DWORD; FilterName : PChar; Filter : Pointer; User : Pointer): BOOL; stdcall;
var mt : TMenuItem;
begin
 result := TRUE;
 mt := TMenuItem.Create(Form1);
 mt.Caption := FilterName;
 mt.Enabled := BassVideo.BassVideo_HasFilterPropertyPage(Handle, Filter, 0); //
 Form1.Filter1.Insert(0, mt);
end;

procedure TForm1.ActiveSomeStuff;
var p : Double;
    i : integer;
begin
 p := BASSVideo_GetLength(chan);
 TrackBar2.Max := Round(p);
 TrackBar2.Frequency := Round(p/100);
 TrackBar2.Min := 0;
 SoundLevelChange(nil); // set vol
 // Enum all filter in the graph and show it for user
 for i := 0 to Filter1.Count - 1 do
  Filter1.Delete(0);
 BassVideo.BassVideo_EnumFilter(chan, @FilterProc, nil);
 CheckBox1Click(nil);
end;

procedure TForm1.ToolButton5Click(Sender: TObject);
begin
 TrackBar2.Position := TrackBar2.Position + 5;
end;

procedure TForm1.ToolButton2Click(Sender: TObject);
begin
 if Bass_ChannelIsActive(chan) = BASS_ACTIVE_PLAYING then
  BassVideo_Pause(chan)
 else
  BassVideo_Play(chan);
end;

procedure TForm1.ToolButton4Click(Sender: TObject);
begin
 BassVideo_Stop(chan)
end;

procedure TForm1.ToolButton1Click(Sender: TObject);
begin
 TrackBar2.Position := TrackBar2.Position - 5;
end;

procedure TForm1.ToolButton3Click(Sender: TObject);
begin
 BassVideo_Play(chan);
end;

procedure TForm1.Source1Click(Sender: TObject);
begin
 BassVideo_SetRatio(chan, RSource, 0, 0);
 WhenFormResize; // should call it if you use windowed mode
end;

procedure TForm1.WhenFormResize;
var R : TRect;
begin
  R := Form1.ClientRect;
  R.Left := 0; R.Top := 0;
  R.Bottom := R.Bottom - Form1.Panel1.Height - Form1.StatusBar1.Height;
  BassVideo_WindowResize(chan, R, 0);
end;

procedure TForm1.N431Click(Sender: TObject);
begin
 BassVideo_SetRatio(chan, R43, 0, 0);
 WhenFormResize; // should call it if you use windowed mode

end;

procedure TForm1.N1691Click(Sender: TObject);
begin
 BassVideo_SetRatio(chan, R169, 0, 0);
 WhenFormResize; // should call it if you use windowed mode

end;

procedure TForm1.Free1Click(Sender: TObject);
begin
 BassVideo_SetRatio(chan, RFree, 0, 0);
 WhenFormResize; // should call it if you use windowed mode

end;

procedure TForm1.ToolButton9Click(Sender: TObject);
begin
 BassVideo_Pause(chan);
 BassVideo_FrameStep(chan)
end;

procedure TForm1.ToolButton10Click(Sender: TObject);
var s : widestring;
    pos : Double;
begin
 if chan = 0 then exit;
 pos := BassVideo_GetPosition(chan);
 if not SaveDialog1.Execute then exit;
 s := SaveDialog1.FileName;
 BassVideo.BassVideo_CaptureBitmap(PWideChar(source), pos, PWideChar(s), BASS_UNICODE); // use unicode file name
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
  var id, i : integer;
begin
 if Msg.message = WM_COMMAND  then
             begin
              id := Msg.WParam;
              for i := 0 to Filter1.Count - 1 do
               begin
                if Filter1.Items[i].Command = id then
                 if Filter1.Items[i].Enabled then
                 begin
                   BassVideo.BassVideo_ShowFilterPropertyPage(chan, PChar(Filter1.Items[i].Caption), Handle, BASSVIDEO_FILTERNAME);
                   exit;
                 end;
               end;
             end;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 if chan <> 0 then
  begin
    BassVideo.BassVideo_SetTempoEnable(chan, checkbox1.Checked);
    TrackBar1Change(nil);
  end;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
 Label2.Caption := inttostr(Trackbar1.Position);
 if chan <> 0 then
 BassVideo.BassVideo_SetTempoValue(chan, Trackbar1.Position)
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 trackbar1.Position := 1000;
end;

end.
