{******************************************************************************}
{ FileName............: MajorScriptPushSourceUnit002                           }
{ Project.............: DirectShow                                             }
{ Author(s)...........: MM                                                     }
{ Version.............: 1.00                                                   }
{------------------------------------------------------------------------------}
{  DirectShow push source filter property page + debug                         }
{                                                                              }
{  Copyright (C) 2003-2006  M.Majoor                                           }
{                                                                              }
{  This program is free software; you can redistribute it and/or               }
{  modify it under the terms of the GNU General Public License                 }
{  as published by the Free Software Foundation; either version 2              }
{  of the License, or (at your option) any later version.                      }
{                                                                              }
{  This program is distributed in the hope that it will be useful,             }
{  but WITHOUT ANY WARRANTY; without even the implied warranty of              }
{  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               }
{  GNU General Public License for more details.                                }
{                                                                              }
{  You should have received a copy of the GNU General Public License           }
{  along with this program; if not, write to the Free Software                 }
{  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. }
{                                                                              }
{------------------------------------------------------------------------------}
{                                                                              }
{ Version   Date   Comment                                                     }
{  1.00   20060205 - Initial release                                           }
{******************************************************************************}
unit MajorScriptPushSourceUnit002;

interface
uses
  BaseClass,
  Classes,
  Controls,
  ActiveX,
  DirectShow9,
  ExtCtrls,
  Graphics,
  MajorScriptPushSourceUnit001,
  Messages,
  StdCtrls,
  SysUtils,
  MMSystem,
  Windows, Mask, ComCtrls, Dialogs;

const
  CPushedDataSize = 64;

type
  TfrmProperties = class(TFormPropertyPage)
    Image1             : TImage;
    tmrUpdate          : TTimer;
    pnlInfo            : TPanel;
    Label1             : TLabel;
    lblVersion         : TLabel;
    mmoInformation: TMemo;
    grpMediaType: TGroupBox;
    mskGuidMajor: TMaskEdit;
    mskGuidMinor: TMaskEdit;
    mskGuidFormat: TMaskEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    grpPushedData: TGroupBox;
    lblInformation: TLabel;
    lblBytes: TLabel;
    lblInformation2: TLabel;
    Label2: TLabel;
    btnSetMediaType: TButton;
    btnGetMediaType: TButton;
    Label10: TLabel;
    btnLogOn: TButton;
    btnLogOff: TButton;
    chkMedia: TCheckBox;
    mmoPushedData: TMemo;
    btnLoadScript: TButton;
    btnExecuteScript: TButton;
    edtScriptLine: TEdit;
    btnExecuteScriptTimed: TButton;
    cmbCard: TComboBox;
    cmbChipset: TComboBox;
    Label11: TLabel;
    Label14: TLabel;
    btnSetChipsetCard: TButton;
    dlgOpen: TOpenDialog;
    Label6: TLabel;
    lblOvertaken: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    btnDataFile: TButton;
    procedure tmrUpdateTimer(Sender: TObject);
    procedure btnGetMediaTypeClick(Sender: TObject);
    procedure btnSetMediaTypeClick(Sender: TObject);
    procedure btnLogOnClick(Sender: TObject);
    procedure btnLogOffClick(Sender: TObject);
    procedure btnLoadScriptClick(Sender: TObject);
    procedure btnExecuteScriptClick(Sender: TObject);
    procedure btnExecuteScriptTimedClick(Sender: TObject);
    procedure btnSetChipsetCardClick(Sender: TObject);
    procedure btnDataFileClick(Sender: TObject);
  private
    FSourceFilter: IMajorScriptPushSource;
    FLastTime    : Dword;
    FLastCount   : Integer;
    FFirstTime   : Boolean;
    FPushedData  : PByteArray;
    function GetPart(LookIn: AnsiString; Part: Integer; var PartsIn: Integer; var IsString: Boolean): AnsiString;
  public
    function  OnConnect(Unknown: IUnknown): HRESULT; override;
    function  OnDisconnect: HRESULT; override;
    function  OnApplyChanges: HRESULT; override;
  end;

implementation

{$R *.DFM}


{------------------------------------------------------------------------------
  Params  : <Unknown>
  Returns : <Result>

  Descript: On connect property page.
  Notes   :
 ------------------------------------------------------------------------------}
function TfrmProperties.OnConnect(Unknown: IUnknown): HRESULT;
var
  hr     : HRESULT;
  Version: PChar;
begin
  Version := nil;
  if not Assigned(Unknown) then
  begin
    Result := E_POINTER;
    Exit;
  end;
  // Next will fail if connected to a running graph from the *ROT* ...
  hr := Unknown.QueryInterface(IMajorScriptPushSource, FSourceFilter);
  if (FAILED(hr)) then
  begin
    FSourceFilter := nil;
    Result := E_NOINTERFACE;
    Exit;
  end;
  // Place version information in tab header
  // This will fail if displayed from a running graph, since the Caption is
  // then 'locked'!
  GetMem(Version, 128);
  FSourceFilter.GetVersionInformation(Version);
  Caption := Version;
  FreeMem(Version);
  FFirstTime  := True;
  GetMem(FPushedData, CPushedDataSize);

  Result := NOERROR;
end;


{------------------------------------------------------------------------------
  Params  : -
  Returns : <Result>

  Descript: On disconnect property page.
  Notes   :
 ------------------------------------------------------------------------------}
function TfrmProperties.OnDisconnect: HRESULT;
begin
  FreeMem(FPushedData);
  FPushedData := nil;
  // Disable debug buffering
  if Assigned(FSourceFilter) then
    FSourceFilter.GetPushedData(nil, 0);
  Result := NOERROR;
end;


{------------------------------------------------------------------------------
  Params  : -
  Returns : -

  Descript: On apply changes property page.
  Notes   :
 ------------------------------------------------------------------------------}
function TfrmProperties.OnApplyChanges: HRESULT;
begin
  Result := NOERROR;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>
  Returns : -

  Descript: Update form.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.tmrUpdateTimer(Sender: TObject);
var
  Info      : PChar;
  Data      : Integer;
  TickCount : Dword;
  DeltaTime : Integer;
  DeltaCount: Integer;
  Calc      : Extended;
  AString   : AnsiString;
  Loop      : Integer;
  MaxLoop   : Integer;
begin
  if Assigned(FSourceFilter) then
  begin
    // Update information
    GetMem(Info, 256);
    repeat
      FSourceFilter.GetInformation(Info);
      if Length(Info) > 0 then
        mmoInformation.Lines.Add(Info);
    until (Length(Info) = 0);
    FSourceFilter.GetDeliveredCount(Data);
    TickCount := GetTickCount;
    DeltaTime := TickCount - FLastTime;
    DeltaCount := Data - FLastCount;
    Calc := (DeltaCount / 1000) * DeltaTime;
    if Calc > 10000000 then
      lblInformation2.Caption := '>10000000'
    else
      lblInformation2.Caption := format('%d', [Round(Calc)]);
    lblInformation.Caption  := format('%d', [Data]);
    FLastTime  := TickCount;
    FLastCount := Data;
    // Pushed data display
    if Assigned(FPushedData) then
    begin
      FSourceFilter.GetPushedData(PByte(FPushedData), CPushedDataSize);
      AString := '';
      MaxLoop := CPushedDataSize;
      if MaxLoop > 64 then
        MaxLoop := 64;
      for Loop := 0 to MaxLoop - 1 do
      begin
        if Loop <> 0 then
          AString := AString + ' ';
        AString := AString + format('%2.2x', [FPushedData[Loop]]);
      end;
      mmoPushedData.Text := AString;
    end;
    // First time initialization
    if FFirstTime then
    begin
      FSourceFilter.GetVersionInformation(Info);
      lblVersion.Caption := Info;
      btnGetMediaTypeClick(nil);
      FFirstTime := False;
    end;

    // Execute script
    if (btnExecuteScriptTimed.Tag <> 0) and (edtScriptLine.Text <> '') then
      btnExecuteScriptClick(nil);

    FSourceFilter.GetOvertaken(Data);
    lblOvertaken.Caption := format('%d', [Data]);

    FreeMem(Info);
  end
  else
  begin
    lblInformation.Caption := '-';
  end;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Set media types.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnSetMediaTypeClick(Sender: TObject);
var
  MajorType : TCLSID;
  MinorType : TCLSID;
  FormatType: TCLSID;
  AText     : AnsiString;
  Error     : Integer;
begin
  if Assigned(FSourceFilter) then
  begin
    try
      AText := mskGuidMajor.Text;
      while (Pos(' ', AText) <> 0) do
        AText[Pos(' ', AText)] := '0';
      Val('$' + Copy(AText, 1, 8), MajorType.D1, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 10, 4), MajorType.D2, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 15, 4), MajorType.D3, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 20, 2), MajorType.D4[0], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 22, 2), MajorType.D4[1], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 25, 2), MajorType.D4[2], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 27, 2), MajorType.D4[3], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 29, 2), MajorType.D4[4], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 31, 2), MajorType.D4[5], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 33, 2), MajorType.D4[6], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 35, 2), MajorType.D4[7], Error);
      AText := mskGuidMinor.Text;
      while (Pos(' ', AText) <> 0) do
        AText[Pos(' ', AText)] := '0';
      Val('$' + Copy(AText, 1, 8), MinorType.D1, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 10, 4), MinorType.D2, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 15, 4), MinorType.D3, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 20, 2), MinorType.D4[0], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 22, 2), MinorType.D4[1], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 25, 2), MinorType.D4[2], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 27, 2), MinorType.D4[3], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 29, 2), MinorType.D4[4], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 31, 2), MinorType.D4[5], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 33, 2), MinorType.D4[6], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 35, 2), MinorType.D4[7], Error);
      AText := mskGuidFormat.Text;
      while (Pos(' ', AText) <> 0) do
        AText[Pos(' ', AText)] := '0';
      Val('$' + Copy(AText, 1, 8), FormatType.D1, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 10, 4), FormatType.D2, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 15, 4), FormatType.D3, Error);
      if Error = 0 then
        Val('$' + Copy(AText, 20, 2), FormatType.D4[0], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 22, 2), FormatType.D4[1], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 25, 2), FormatType.D4[2], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 27, 2), FormatType.D4[3], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 29, 2), FormatType.D4[4], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 31, 2), FormatType.D4[5], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 33, 2), FormatType.D4[6], Error);
      if Error = 0 then
        Val('$' + Copy(AText, 35, 2), FormatType.D4[7], Error);
      if Error = 0 then
        FSourceFilter.SetMediaType(@MajorType, @MinorType, @FormatType, chkMedia.Checked);
    except
    end;
  end;

end;

{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Get media types.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnGetMediaTypeClick(Sender: TObject);
var
  MajorType : TCLSID;
  MinorType : TCLSID;
  FormatType: TCLSID;
  CheckType : Boolean;
begin
  if Assigned(FSourceFilter) then
  begin
    try
      FSourceFilter.GetMediaType(@MajorType, @MinorType, @FormatType, CheckType);
      mskGuidMajor.Text := format('%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x',
      [MajorType.D1,    MajorType.D2,    MajorType.D3,
       MajorType.D4[0], MajorType.D4[1],
       MajorType.D4[2], MajorType.D4[3], MajorType.D4[4],
       MajorType.D4[5], MajorType.D4[6], MajorType.D4[7]]);
      mskGuidMinor.Text := format('%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x',
      [MinorType.D1,    MinorType.D2,    MinorType.D3,
       MinorType.D4[0], MinorType.D4[1],
       MinorType.D4[2], MinorType.D4[3], MinorType.D4[4],
       MinorType.D4[5], MinorType.D4[6], MinorType.D4[7]]);
      mskGuidFormat.Text := format('%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x',
      [FormatType.D1,    FormatType.D2,    FormatType.D3,
       FormatType.D4[0], FormatType.D4[1],
       FormatType.D4[2], FormatType.D4[3], FormatType.D4[4],
       FormatType.D4[5], FormatType.D4[6], FormatType.D4[7]]);
      chkMedia.Checked := CheckType;
    except
    end;
  end;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Enable logfile.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnLogOnClick(Sender: TObject);
begin
  if Assigned(FSourceFilter) then
    FSourceFilter.SetLog(True);
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Disable log file.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnLogOffClick(Sender: TObject);
begin
  if Assigned(FSourceFilter) then
    FSourceFilter.SetLog(False);
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Load a script.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnLoadScriptClick(Sender: TObject);
var
  TempStr: PChar;
begin
  if Assigned(FSourceFilter) then
  begin
    dlgOpen.Options := dlgOpen.Options + [ofFileMustExist];
    dlgOpen.Filter := 'Script files (*.pico)|*.pico|All files (*.*)|*.*';
    if dlgOpen.Execute then
    begin
      GetMem(TempStr, 255);
      try
        StrPCopy(TempStr, dlgOpen.FileName);
        FSourceFilter.SetScript(TempStr);
      finally
        FreeMem(TempStr);
      end;
    end;
  end;
end;


{------------------------------------------------------------------------------
  Params  : <LookIn>    String to look in
            <Part>      Part to retrieve (1 ...)
                        <0 if all to retrieve (only comments are removed and
                           some reformatting is done, e.g. spaces and comma)
  Returns : <Result>    String retrieved
            <PartsIn>   Detected parts
            <IsString>  True indicates the part contains a string

  Descript: Get part from string were each part is separated by a delimiter.
            String parts can be enclosed by ' or ". Comments (';') are removed.
  Notes   :
 ------------------------------------------------------------------------------}
function TfrmProperties.GetPart(LookIn: AnsiString; Part: Integer; var PartsIn: Integer; var IsString: Boolean): AnsiString;
type
  TParts = record
    Part     : string;
    Delimiter: Char;         // Contains character delimiter of part (0 if none)
  end;
var
  Parts     : array of TParts;
  Position  : Integer;
  Position2 : Integer;
  ProcessStr: string;
  PartStr   : string;
  StringChar: Char;
  Search    : Integer;
  Loop      : Integer;
  CommaFound: Boolean;

  procedure StringToParts(ProcessStr: AnsiString);
    procedure CheckFirstStringChar(CharSearch: Char);
    var
      PosChar: Integer;
    begin
      PosChar := Pos(CharSearch, ProcessStr);
      if PosChar <> 0 then
      begin
        if (StringChar = #0) or (PosChar < Position) then
        begin
          StringChar := CharSearch;
          Position   := PosChar;
        end;
      end;
    end;
  var
    SkipSeparatorSearch: Boolean;
  begin
    while (ProcessStr <> '') do
    begin
      // If we start with a string delimiter then we have to look for the ending
      // delimiter. Otherwise find a separator.
      SkipSeparatorSearch := False;
      case ProcessStr[1] of
        '''', '"': begin
                     // Find ending delimiter
                     PartStr   := Copy(ProcessStr, 2, 255);
                     Position2 := Pos(ProcessStr[1], PartStr);
                     if Position2 > 0 then
                     begin
                       // Ending delimiter found, add part
                       SetLength(Parts, Length(Parts) + 1);
                       Parts[Length(Parts) - 1].Part := Copy(ProcessStr, 2, Position2 - 1);
                       Parts[Length(Parts) - 1].Delimiter := ProcessStr[1];
                       Delete(ProcessStr, 1, Position2 + 1);
                       SkipSeparatorSearch := True;
                     end;
                   end;
      end;
      if not SkipSeparatorSearch then
      begin
        StringChar := #0;                                  // First separator found (none)
        Position   := 0;                                   // Position first separator found
        CheckFirstStringChar(',');
        CheckFirstStringChar(' ');
        if Position = 0 then                               // No separator found, all as a part
        begin
          SetLength(Parts, Length(Parts) + 1);
          Parts[Length(Parts) - 1].Part := ProcessStr;
          Parts[Length(Parts) - 1].Delimiter := #0;
          ProcessStr := '';
        end
        else
        begin
          if StringChar = ',' then
            CommaFound := True;
          SetLength(Parts, Length(Parts) + 1);
          Parts[Length(Parts) - 1].Part := Copy(ProcessStr, 1, Position-1);
          Parts[Length(Parts) - 1].Delimiter := #0;
          Delete(ProcessStr, 1, Position);
        end;
      end;
      ProcessStr := Trim(ProcessStr);                      // Remove leading/trailing spaces
    end;
  end;

begin
  Result     := '';
  PartsIn    := 0;
  IsString   := False;
  CommaFound := false;
  // Process the string by dividing it in parts
  Parts := nil;
  ProcessStr := Trim(LookIn);                              // Remove leading/trailing spaces
  StringToParts(ProcessStr);                               // Divide into parts
  if not Assigned(Parts) then
    Exit;

  // Find possible comment (only look in the non-string parts)
  Search := -1;
  for Loop := 0 to Length(Parts) - 1 do
    if (Parts[Loop].Delimiter = #0) and (Search = -1) then
    begin
      Position := Pos(';', Parts[Loop].Part);
      if Position > 0 then
      begin
        Delete(Parts[Loop].Part, Position, 255);
        Parts[Loop].Part := Trim(Parts[Loop].Part);
        if Parts[Loop].Part = '' then
          Search := Loop
        else
          Search := Loop + 1;
      end;
    end;
  // Remove all parts belonging to the comment (including string parts following it)
  if Search >= 0 then
    SetLength(Parts, Search);
  // Return information
  PartsIn := Length(Parts);
  if (Part <= PartsIn) then
  begin
    if Part < 0 then
    begin
      // If we need to return just the reformatted/commentless data
      Result := '';
      for Loop := 0 to Length(Parts) - 1 do
      begin
        if Loop <> 0 then
          if CommaFound then
            Result := Result + ', '
          else
            Result := Result + ' ';
        if Parts[Loop].Delimiter <> #0 then
          Result := Result + Parts[Loop].Delimiter + Parts[Loop].Part + Parts[Loop].Delimiter
        else
          Result := Result + Parts[Loop].Part;
      end;
      IsString := True;
    end
    else
    begin
      Result := Parts[Part-1].Part;
      IsString := (Parts[Part-1].Delimiter <> #0);
    end;
  end;
  Parts := nil;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Execute script line.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnExecuteScriptClick(Sender: TObject);
var
  Part         : Integer;
  Parts        : Integer;
  PartString   : AnsiString;
  ProcessString: AnsiString;
  Index        : Integer;
  Error        : Integer;

  ParIn        : OleVariant;
  ParOut       : OleVariant;
  ParamsStr    : array of WideString;
  AReal        : Double;
  AnInteger    : LongInt;
  FunctionName : PChar;
  CurrentVar   : OleVariant;
  IsString     : Boolean;
begin
  if Assigned(FSourceFilter) then
  begin
    VarClear(ParIn);
    VarClear(ParOut);
    ProcessString := edtScriptLine.Text;
    Part := 2;
    repeat
      PartString := GetPart(ProcessString, Part, Parts, IsString);
      // If additional parameters
      if Parts > 1 then
      begin
        VarClear(CurrentVar);
        Index := Part - 2;
        // Check for first run
        if (Index = 0) then
        begin
          if Parts > 2 then
            ParIn := VarArrayCreate([0, Parts-2], varVariant)
          else
            ParIn := Null;
          SetLength(ParamsStr, Parts-1);
        end;
        if IsString then
        begin
          ParamsStr[Index] := PartString;
          CurrentVar       := VarAsType(CurrentVar, varOleStr);
          CurrentVar       := ParamsStr[Index];
        end
        else
        begin
          Val(PartString, AnInteger, Error);
          if Error = 0 then
          begin
            CurrentVar := VarAsType(CurrentVar, varInteger);
            CurrentVar := AnInteger;
          end
          else
          begin
            Val(PartString, AReal, Error);
            if Error = 0 then
            begin
              CurrentVar := VarAsType(CurrentVar, varDouble);
              CurrentVar := AReal;
            end
            else
            begin
              ParamsStr[Index] := PartString;
              CurrentVar       := VarAsType(CurrentVar, varOleStr);
              CurrentVar       := ParamsStr[Index];
            end;
          end;
        end;
        if VarIsArray(ParIn) then
          ParIn[Index] := CurrentVar
        else
          ParIn := CurrentVar;
      end;
      Inc(Part);
    until Part > Parts;
    // Call script funtion
    if Parts > 0 then
    begin
      GetMem(FunctionName, 128);
      StrPCopy(FunctionName, GetPart(ProcessString, 1, Parts, IsString));
      try
        FSourceFilter.ScriptExecute(FunctionName, ParIn, ParOut);
      finally
        FreeMem(FunctionName);
      end;
    end;
  end;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Enable/disable timed script execution.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnExecuteScriptTimedClick(Sender: TObject);
begin
  if btnExecuteScriptTimed.Tag = 0 then
  begin
    btnExecuteScriptTimed.Tag := 1;
    btnExecuteScriptTimed.Caption := 'Stop execute script repeatedly';
  end
  else
  begin
    btnExecuteScriptTimed.Tag := 0;
    btnExecuteScriptTimed.Caption := 'Execute script line repeatedly';
  end;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Set chipset and card.
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnSetChipsetCardClick(Sender: TObject);
var
  Info: PChar;
begin
  if Assigned(FSourceFilter) then
  begin
    GetMem(Info, 128);
    try
      if cmbChipset.ItemIndex = 2 then
      begin
        if cmbCard.ItemIndex > 0 then
        begin
          dlgOpen.Options := dlgOpen.Options + [ofFileMustExist];
          dlgOpen.Filter := 'Transport stream files (*.ts)|*.ts|All files (*.*)|*.*';
          if not dlgOpen.Execute then
            Exit;
          StrPCopy(Info, dlgOpen.Filename);
        end
        else
          StrPCopy(Info, '');
      end
      else
        StrPCopy(Info, cmbChipset.Text);
      FSourceFilter.SetChipsetAndCard(Info, cmbCard.ItemIndex - 1);
    finally
      FreeMem(Info);
    end;
  end;
end;


{------------------------------------------------------------------------------
  Params  : <Sender>  Sender
  Returns : -

  Descript: Start/stop saving file
  Notes   :
 ------------------------------------------------------------------------------}
procedure TfrmProperties.btnDataFileClick(Sender: TObject);
var
  TempStr: PChar;
begin
  if Assigned(FSourceFilter) then
  begin
    if btnDataFile.Tag = 0 then
    begin
      dlgOpen.Options := dlgOpen.Options - [ofFileMustExist];
      dlgOpen.Filter := 'Transport stream files (*.ts)|*.ts|All files (*.*)|*.*';
      if dlgOpen.Execute then
      begin
        GetMem(TempStr, 255);
        try
          StrPCopy(TempStr, dlgOpen.FileName);
          if FSourceFilter.SetDataFile(TempStr) = S_OK then
          begin
            btnDataFile.Tag := 1;
            btnDataFile.Caption := 'Stop receiving data';
          end;
        finally
          FreeMem(TempStr);
        end;
      end;
    end
    else
    begin
      FSourceFilter.SetDataFile('');
      btnDataFile.Tag := 0;
      btnDataFile.Caption := 'Save received data to file';
    end;
  end;

end;

{------------------------------------------------------------------------------
  Params  : -
  Returns : -

  Descript: Initialization
  Notes   :
 ------------------------------------------------------------------------------}
initialization
  TBCClassFactory.CreatePropertyPage(TfrmProperties, CLSID_MajorScriptPushSourcePropertyPage);
end.

