unit DlgRemote;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Mask, Spin, ComCtrls, FileCtrl,
  Buttons, Inifiles, AppEvnts, Registry,
  ThreadMessage, CamRemote, CamDefines;

const REMOTE_SUBKEY         = 'RemoteTemplate'; //Key used when reading writing to registry
      THUMBNAIL_FILENAME    = '\thumbnail.jpg'; //Thumbnail name
      LOG_FILE_NAME         = '\log.txt';       //Log-file name
      MAX_LOG_SIZE          = 65000;            //Max size of log-file
      START_REMOTE_TXT      = '&Start taking pictures remote';
      STOP_REMOTE_TXT       = '&Stop taking pictures remote';
      START_REMOTE_PROC_TXT = '&Start remote process';
      STOP_REMOTE_PROC_TXT  = '&Stop remote process';

//List all supported cameras, which is sused to separatelu define supported
//parameters per camera. This function is however done by CamRemote when
//starting the remote process.
type AvailRemoteCamerasType =
       (
         AllParameters,
         ConnectedCameraParameters
       );

//String corresponding type to AvailRemoteCamerasType
const RemoteCamerasStringType : array[AvailRemoteCamerasType] of string =
       ( 'All parameters',
         'Connected camera parameters'
       );

//A record of supported remote parameters
type CameraRemoteParamType =
           record
             CompQuality         : array of RemoteFormatQualityType;
             ImageSize           : array of RemoteFormatSizeType;
             StrobeSetting       : array of RemoteFormatFlashType;
             StrobeCompSetting   : array of RemoteFormatFlashCompType;
             ImageMode           : array of RemoteFormatShootingModeType;
             MLWeiMode           : array of RemoteFormatMLWeiType;
             AFDistance          : array of RemoteFormatAFDistType;
             WhiteBalanceSetting : array of RemoteFormatWBType;
             Contrast            : array of RemoteFormatLevelType;
             ColorGain           : array of RemoteFormatLevelType;
             Sharpness           : array of RemoteFormatLevelType;
             ISO                 : array of RemoteFormatISOType;
             ExposureComp        : array of RemoteFormatExposureCompType;
             AV                  : array of RemoteFormatAVType;
             TV                  : array of RemoteFormatTVType;
             PhotoEffect         : array of RemoteFormatPhotoEffectType;
             Beep                : array of RemoteFormatBeepType;
           end;

//------------------------------------------------------------------------------
//- Global variables including texts used in the comboboxes when handling
//- remote paramters
//------------------------------------------------------------------------------
var gCompQualArrayText : array[low(RemoteFormatQualityType)..high(RemoteFormatQualityType)] of string =
  ('-', 'Normal', 'Fine', 'Lossless', 'Super Fine','RAW');

var gImageSizeArrayText : array[low(RemoteFormatSizeType)..high(RemoteFormatSizeType)] of string =
  ('-', 'Large', 'Medium',  'Small', 'Medium2', 'Medium1');

var gStrobeSettingArrayText : array[low(RemoteFormatFlashType)..high(RemoteFormatFlashType)] of string =
  ('-', 'Off', 'Auto', 'On', 'auto+red eye', 'auto+slow sync', 'auto+red eye', 'on+red eye');

var gStrobeCompSettingArrayText : array[low(RemoteFormatFlashCompType)..high(RemoteFormatFlashCompType)] of string =
  ('-', '+2.00', '+1.66', '+1.33', '+1.00', '+0.66', '+0.33', '0',
   '-0.33', '-0.66', '-1.00', '-1.33', '-1.66', '-2.00');

var gImageModeArrayText : array[low(RemoteFormatShootingModeType)..high(RemoteFormatShootingModeType)] of string =
 ('-',            'Auto',        'Manual mode',     'Far Scene', 'Fast Shutter',
  'Slow Shutter', 'Night Scene', 'Gray Scene',      'Sepia',     'Portrait',
  'Sport',        'Macro',       'Black and White', 'Pan Focus', 'Vivid',
  'Neutral',      'Program',     'TV',              'AV'
  );

var gMLWeiModeArrayText : array[low(RemoteFormatMLWeiType)..high(RemoteFormatMLWeiType)] of string =
  ('-', 'Center-weighted', 'Spot', 'Averaging', 'Evaluative', 'Partial',
   'Center-weighted averaging');

var gAFDistanceArrayText : array[low(RemoteFormatAFDistType)..high(RemoteFormatAFDistType)] of string =
  ('-', 'Manual', 'Auto', 'Unknown', 'Zone Focus(Close up)',
   'Zone Focus(The shortest distance)', 'Zone Focus(Short distance)',
   'Zone Focus(Medium distance)',       'Zone Focus(Far distance)'
  );

var gWhiteBalanceSetArrayText : array[low(RemoteFormatWBType)..high(RemoteFormatWBType)] of string =
  ('-', 'Auto', 'Daylight', 'Cloudy', 'Tungsten', 'Fluorscent', 'Flash', 'Preset',
   'Fluorescent light', 'Custom');

var gContrastArrayText : array[low(RemoteFormatLevelType)..high(RemoteFormatLevelType)] of string =
  ('-', 'Low', 'Default', 'High');

var gColorGainArrayText : array[low(RemoteFormatLevelType)..high(RemoteFormatLevelType)] of string =
  ('-', 'Low', 'Default', 'High');

var gSharpnessArrayText : array[low(RemoteFormatLevelType)..high(RemoteFormatLevelType)] of string =
  ('-', 'Low', 'Default', 'High');

var gIsoArrayText : array[low(RemoteFormatISOType)..high(RemoteFormatISOType)] of string =
  ('-', 'Auto', '50', '100', '200', '400', '800', '1600', '3200');

var gExposureCompArrayText : array[low(RemoteFormatExposureCompType)..high(RemoteFormatExposureCompType)] of string =
  ('-', '+2.00', '+1.66', '+1.33', '+1.00', '+0.66', '+0.33', '0',
   '-0.33', '-0.66', '-1.00', '-1.33', '-1.66', '-2.00');

var gAvArrayText : array[low(RemoteFormatAVType)..high(RemoteFormatAVType)] of string =
  ('-', '1.0', '1.4', '2.0', '2.8', '4.0', '5.6', '8.0', '11', '16', '22', '32', '45', '64', '91');

var gTvArrayText : array[low(RemoteFormatTVType)..high(RemoteFormatTVType)] of string =
  ('-', '30"', '15"', '8"', '4"', '2"', '1"', '1/2', '1/4', '1/8',
   '1/15', '1/30', '1/60', '1/125', '1/250', '1/500', '1/1000',
   '1/2000', '1/4000', '1/8000', '1/16000');

var gPhotoEffectArrayText : array[low(RemoteFormatPhotoEffectType)..high(RemoteFormatPhotoEffectType)] of string =
  ('-', 'Off', 'Vivid', 'Neutral', 'Low Sharpening', 'Sepia', 'Black and White');

var gBeepArrayText : array[low(RemoteFormatBeepType)..high(RemoteFormatBeepType)] of string =
  ('-', 'Off', 'On');

//Remote form type
type
  TFormRemote = class(TForm)
    StatusBar: TStatusBar;
    PageControl: TPageControl;
    TabSheetRemote: TTabSheet;
    LabelComputerDir: TLabel;
    Image: TImage;
    LabelPreview: TLabel;
    ButtonTakePic: TButton;
    BitBtnClose: TBitBtn;
    ButtonStartRemoteProcess: TButton;
    TabSheetRelParams: TTabSheet;
    LabelTV: TLabel;
    LabelAv: TLabel;
    ComboBoxTv: TComboBox;
    ComboBoxAv: TComboBox;
    LabelExpComp: TLabel;
    ComboBoxExpComp: TComboBox;
    LabelFlash: TLabel;
    ComboBoxFlash: TComboBox;
    LabelFlashComp: TLabel;
    ComboBoxFlashComp: TComboBox;
    LabelSize: TLabel;
    LabelQuality: TLabel;
    ComboBoxSize: TComboBox;
    ComboBoxQuality: TComboBox;
    LabelWhiteBalance: TLabel;
    ComboBoxWhiteBalance: TComboBox;
    LabelISO: TLabel;
    ComboBoxISO: TComboBox;
    CheckBoxBeep: TCheckBox;
    LabelImageMode: TLabel;
    ComboBoxImageMode: TComboBox;
    LabelMeteringMode: TLabel;
    ComboBoxMeteringMode: TComboBox;
    LabelAFDistance: TLabel;
    ComboBoxAFDistance: TComboBox;
    LabelContrast: TLabel;
    ComboBoxContrast: TComboBox;
    LabelColorGain: TLabel;
    ComboBoxColorGain: TComboBox;
    LabelSharpness: TLabel;
    ComboBoxSharpness: TComboBox;
    ButtonGetCamSet: TButton;
    LabelZoom: TLabel;
    TrackBarZoom: TTrackBar;
    ButtonViewFinder: TButton;
    ButtonSetCameraSettings: TButton;
    ProgressBar: TProgressBar;
    LabelPhotoEffect: TLabel;
    ComboBoxPhotoEffect: TComboBox;
    LabelZoomPos: TLabel;
    ApplicationEvents1: TApplicationEvents;
    TabSheetAbout: TTabSheet;
    CheckBoxDebug: TCheckBox;
    LabelVersion: TLabel;
    CamRemote: TCamRemote;
    ComboBoxTransferMode: TComboBox;
    LabelTransfer: TLabel;
    CheckBoxActiveMode: TCheckBox;
    CheckBoxOnlySupportedParam: TCheckBox;
    EditPCDirectory: TEdit;
    TimerTakePicture: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure ButtonTakePicClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ButtonStartRemoteProcessClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ButtonGetCamSetClick(Sender: TObject);
    procedure TrackBarZoomChange(Sender: TObject);
    procedure ButtonViewFinderClick(Sender: TObject);
    procedure ButtonSetCameraSettingsClick(Sender: TObject);
    procedure CheckBoxDebugClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure CamRemoteEvent(Event: EventCallbackType);
    procedure CamRemoteViewfinderEvent(Jpegdata: TMemoryStream);
    procedure CamRemoteRemoteGetPictureEvent(PercentageDone: Integer);
    procedure CamRemoteRemoteTakePictureEvent(PercentageDone: Integer);
    procedure CamRemoteRemoteEvent(Event: RemoteEventCallbackType);
    procedure TimerTakePictureTimer(Sender: TObject);
  private
    mReleaseProcessActive  : boolean;                //Is true when the releasestart proc has been called
    mCameraIsActive        : boolean;                //Is true if the camera is ready to take a picture
    mViewFinderEnabled     : boolean;                //Is true when viewfinder functions are on
    mCameraRemoteParam     : CameraRemoteParamType;  //Contains remote parameters possible to set for current camera
    mCurrentCamera         : AvailRemoteCamerasType; //Current connected camera
    mPictureReqTime        : TDateTime;              //The time when the request for taking a picture
    mIniFile               : TRegistryIniFile;       //The registry entry
    mLogFile               : TFileStream;            //The log-file
    mConnToCamera          : boolean;                //Is true during connection to camera
    mMessageThread         : TMessageThread;         //Thread to handle event messages from the camera
    mCameraInfo            : ConnectInfoType;        //Info about the camera received when connecting
    mCameraCapability      : RemoteFuncType;         //Remote capability of the connected camera
    mReleaseMode           : ReleaseModeType;        //The selected transfer mode in "Transfer mode"

    procedure Initvar;
    procedure StartReleasePic;
    procedure StopReleasePic;
    procedure TakePicture;
    procedure TakeThePictures;
    procedure SetRemoteParameters(inParam : RemoteReleaseParametersType);
    function  GetRemoteParameters : RemoteReleaseParametersType;
    procedure LogRemoteParameters(RemoteParameters : RemoteReleaseParametersType);
    procedure PictureTaken;
    procedure EnableButtons(Active : boolean);
    function  Versiontext : string;
    function  GetLogFileName : string;
    procedure AppException(Sender: TObject; E: Exception);
    procedure WriteVerToLog;
    procedure DisconnectFromCamera;
    procedure ConnectToCamera;
    procedure UpdateRemoteParamVCL;
  public
    { Public declarations }
    property  ViewFinderEnabled  : boolean          read mViewFinderEnabled  write mViewFinderEnabled;
    property  MessageThread      : TMessageThread   read mMessageThread      write mMessageThread;
    procedure Log(Text : string);
  end;

var
  FormRemote: TFormRemote;

implementation

uses DlgViewFinder, Jpeg;

{$R *.DFM}

//Takes a picture remotely and gets the picture data if the remote transfer
//mode is active and not passive
procedure TFormRemote.TakeThePictures;
begin
  TakePicture;
  if (CheckBoxActiveMode.Checked) then
  begin
    PictureTaken;
  end;
end;

//Form create procedure
procedure TFormRemote.FormCreate(Sender: TObject);
begin
  //Set the application exception handler
  Application.OnException := AppException;
  //Create the registry ini-file
  mIniFile := TRegistryIniFile.Create('Software');
  CheckBoxDebug.Checked := mIniFile.ReadBool(REMOTE_SUBKEY,
                                             CheckBoxDebug.Name,
                                             false);
  //Create the debug file if the checkbox is set
  if (CheckBoxDebug.Checked) then
  begin
    if FileExists(GetLogFileName) then
    begin
      mLogFile := TFileStream.Create(GetLogFileName,
                                     (fmOpenReadWrite or fmShareDenyWrite));
      mLogFile.Seek(0, soFromEnd);
      //Check if size is exceeded
      if (mLogFile.Size > MAX_LOG_SIZE) then
      begin
        mLogFile.Free;
        //Create the new file
        mLogFile := TFileStream.Create(GetLogFileName,
                                       (fmCreate or fmShareDenyWrite));
      end;
    end else
    begin
      mLogFile := TFileStream.Create(GetLogFileName,(fmCreate or fmShareDenyWrite));
    end;
  end;
  Log('');
  Log('');
  Log('Remote template version ' + Versiontext + ' started');
  Log('Date and time=' + DateTimeToStr(Now));
  //Write OS version in LOG
  WriteVerToLog;
  //Initialize
  mConnToCamera        := false;
  StatusBar.SimpleText := '';
  //Set the global time variable format
  TimeSeparator   := ':';
  LongTimeFormat  := 'HH:mm:ss';
  //Creates the message thread. The message thread is started immidiately.
  mMessageThread  := TMessageThread.Create(false);
  mCameraIsActive := false;
  //Read data stored in the registry
  EditPCDirectory.Text := mIniFile.ReadString(REMOTE_SUBKEY,
                                              EditPCDirectory.Name,
                                              GetCurrentDir);
  CheckBoxDebug.Checked := mIniFile.ReadBool(REMOTE_SUBKEY,
                                             CheckBoxDebug.Name,
                                             CheckBoxDebug.Checked);
  ComboBoxTransferMode.ItemIndex := mIniFile.ReadInteger(REMOTE_SUBKEY,
                                                         ComboBoxTransferMode.Name,
                                                         ComboBoxTransferMode.ItemIndex);
  CheckBoxActiveMode.Checked := mIniFile.ReadBool(REMOTE_SUBKEY,
                                                  CheckBoxActiveMode.Name,
                                                  CheckBoxActiveMode.Checked);
  CheckBoxOnlySupportedParam.Checked := mIniFile.ReadBool(REMOTE_SUBKEY,
                                                          CheckBoxOnlySupportedParam.Name,
                                                          CheckBoxOnlySupportedParam.Checked);
  Initvar;
  //Deaktivate buttons since the remote process not started
  EnableButtons(false);
  PageControl.ActivePageIndex := 0;
  //Set about version text
  LabelVersion.Caption := 'Remote version ' + Versiontext;
  inherited;
end;

//Procedure for the "Take a picture" button
procedure TFormRemote.ButtonTakePicClick(Sender: TObject);
begin
  //Takes the picture(s) manually triggered
  Log('Enters ButtonTakePicClick');
  //Check if destination directory exists
  if not DirectoryExists(EditPCDirectory.Text) then
  begin
    raise EInOutError.Create('Destination directory does not exist');
  end;
  try
    Initvar;
    EnableButtons(false);
    StatusBar.SimpleText := 'Taking the picture';
    TakeThePictures;
    EnableButtons(true);
  except
    on E:exception do
      begin
        Log('Button_TakePicClick Exception=' + E.Message);
        Initvar;
        StopReleasePic;
        StatusBar.SimpleText := 'Remote process stopped';
        raise;
      end;
  end;
end;

//Gets the thumbnail and picture when a picture has been taken
procedure TFormRemote.PictureTaken;
var thumb_file_name   : string;
    pic_file_name     : string;
    time_string       : string;
begin
  //Is called when the event for a remote picture is sent
  Log('Enters PictureTaken');
  try
    if ((mReleaseProcessActive) and
        (mReleaseMode <> ReleaseModeOnlyToCamera)) then
    begin
      //First get the thumbnail
      thumb_file_name := extractFileDir(ParamStr(0)) + THUMBNAIL_FILENAME;
      Log('Remote: Thumbnail receive request. Time = ' +
          floattostr((Now - mPictureReqTime) * 24* 3600));
      CamRemote.RemoteGetPicture(thumb_file_name);
      Log('Remote: Thumbnail received. Time = ' +
          floattostr((Now - mPictureReqTime) * 24* 3600));
      Image.Picture.LoadFromFile(thumb_file_name);
      DateTimeToString(time_string, 'yymmddhhnnss', Now);
      pic_file_name := Format('%s%s.jpg', [EditPCDirectory.Text + '\',
                                           time_string]);
      //Get the picure
      Log('Remote: Picture receive request. Time = ' +
          floattostr((Now - mPictureReqTime) * 24* 3600));
      CamRemote.RemoteGetPicture(pic_file_name);
      Log('Remote: Picture received. Time = ' +
          floattostr((Now - mPictureReqTime) * 24* 3600));
    end else begin
      Log('Exception, nearly. mReleaseProcessActive');
    end;
    ProgressBar.Position := 0;
  except
    on E:Exception do
       begin
         Log('Exception=' + E.Message);
         Initvar;
         StopReleasePic;
         StatusBar.SimpleText := 'Remote process stopped';
         raise;
       end;
  end;
end;

procedure TFormRemote.Initvar;
begin
  Log('Enters Initvar');
  if (ButtonStartRemoteProcess.Caption = STOP_REMOTE_PROC_TXT) then
  begin
    ButtonTakePic.Enabled := true;
  end;
  ButtonTakePic.Enabled;
end;

//Procedure used when starting the remote process
procedure TFormRemote.StartReleasePic;
var i              : integer;
    temp_tab_sheet : TTabSheet;
begin
  Log('Enters StartReleasePic');
  Log('Checks if the camera supports remote');
  if (not CamRemote.RemoteSupported) then
  begin
    ECamException.Create('The connected camera does not support remote mode');
  end;
  StatusBar.SimpleText := 'Starts remote process and probes remote parameters';
  //Starts the remote mode
  Log('Opens remote mode');
  mCameraCapability := CamRemote.RemoteStart(mReleaseMode,
                                             ReleaseDataKingTakeBothThumbAndPic);
{$IFNDEF VER130} //Not supported by Delphi 5
  Log('Remote capabaility DoSupportZoom = '                + BoolToStr(mCameraCapability.DoSupportZoom));
  Log('Remote capabaility DoSupportShootingPara = '        + BoolToStr(mCameraCapability.DoSupportShootingPara));
  Log('Remote capabaility DoSupportViewfinder = '          + BoolToStr(mCameraCapability.DoSupportViewfinder));
  Log('Remote capabaility ReqViewfinderOffWhenShooting = ' + BoolToStr(mCameraCapability.ReqViewfinderOffWhenShooting));
  Log('Remote capabaility DoSupportAfLockUnlock = '        + BoolToStr(mCameraCapability.DoSupportAfLockUnlock));
{$ENDIF}  
  mCameraIsActive       := true;
  mReleaseProcessActive := true;
  //Disable not supported VCL
  if (not mCameraCapability.DoSupportViewfinder) then
  begin
    ButtonViewFinder.Visible := false;
    Log('ViewFinder is not allowed');
  end else begin
    ButtonViewFinder.Enabled := true;
    Log('ViewFinder is allowed');
  end;
  if (not mCameraCapability.DoSupportZoom) then
  begin
    LabelZoom.Visible    := false;
    TrackBarZoom.Visible := false;
  end;
  if (not mCameraCapability.DoSupportShootingPara) then
  begin
    //Disable the parameters tab
    for i := 0 to PageControl.PageCount - 1 do
    begin
       temp_tab_sheet := PageControl.Pages[i];
       if (temp_tab_sheet.Name = 'TabSheetRelParams') then
       begin
         temp_tab_sheet.TabVisible := false;
       end;
    end;
  end;
  EnableButtons(true);
  StatusBar.SimpleText := 'Remote process is opened';
end;

//Procedure used when stopping the remote process
procedure TFormRemote.StopReleasePic;
begin
  //Ends the release process
  Log('Enters StopReleasePic');
  if (mReleaseProcessActive) then
  begin
    EnableButtons(false);
    ButtonStartRemoteProcess.Caption := START_REMOTE_PROC_TXT;
    CamRemote.RemoteEnd;
    mCameraIsActive := false;
    Log('StopReleasePic, ReleaseEnd');
    mReleaseProcessActive := false;
  end;
  StatusBar.SimpleText := 'Remote process stopped';
  Initvar;
end;

//Procedure used when taking a picture remotely
procedure TFormRemote.TakePicture;
var remote_parameters : RemoteReleaseParametersType;
begin
  //Takes one picture
  Log('Enters TakePicture');
  mPictureReqTime := Now();
  Log('Remote: Request to take a picture. Time = ' +
      floattostr((Now - mPictureReqTime) * 24* 3600));
  if (mCameraCapability.DoSupportShootingPara) then
  begin
    //Gets release parameters from the Parameters tab
    remote_parameters := GetRemoteParameters;
    Log('Sets remote parameters');
    CamRemote.RemoteSetRemoteParams(remote_parameters);
    Log('Remote: Remote parameters set. Time = ' +
        floattostr((Now - mPictureReqTime) * 24* 3600));
  end;
  Log('Takes a remote pic. Zoom = ' + inttostr(TrackBarZoom.Position)+
      ', maxZoom = ' + inttostr(TrackBarZoom.Max));
  //Check if Viewfinder must be closed before taking the picture
  if (FormViewFinder.Showing) and (mCameraCapability.ReqViewfinderOffWhenShooting) then
  begin
    FormViewFinder.Close;
  end;
  CamRemote.RemoteTakePicture(CheckBoxActiveMode.Checked);
  Log('Remote: Request for taking picture done. Time = ' +
      floattostr((Now - mPictureReqTime) * 24* 3600));
end;

//Procedure called when exiting the application and the form is freed.
procedure TFormRemote.FormDestroy(Sender: TObject);
begin
  Log('Enters TForm_Remote.FormDestroy');
  //Stores data in the registry
  mIniFile.WriteInteger(REMOTE_SUBKEY, 'RemoteWidth',                   FormRemote.Width);
  mIniFile.WriteInteger(REMOTE_SUBKEY, 'RemoteHeight',                  FormRemote.Height);
  mIniFile.WriteString (REMOTE_SUBKEY, EditPCDirectory.Name,            EditPCDirectory.Text);
  mIniFile.WriteBool   (REMOTE_SUBKEY, CheckBoxDebug.Name,              CheckBoxDebug.Checked);
  mIniFile.WriteInteger(REMOTE_SUBKEY, ComboBoxTransferMode.Name,       ComboBoxTransferMode.ItemIndex);
  mIniFile.WriteBool   (REMOTE_SUBKEY, CheckBoxActiveMode.Name,         CheckBoxActiveMode.Checked);
  mIniFile.WriteBool   (REMOTE_SUBKEY, CheckBoxOnlySupportedParam.Name, CheckBoxOnlySupportedParam.Checked);
  mIniFile.Free;
  if (CheckBoxDebug.Checked) then
  begin
    mLogFile.Free;
  end;
  //Close the message thread
  mMessageThread.Terminate;
  mMessageThread.WaitFor;
  mMessageThread.free;
end;

//EnableButtons enables or disables buttons that only can be used when remote
//process has been started or stopped.
procedure TFormRemote.EnableButtons(Active : boolean);
begin
  Log('Enters TFormRemote.EnableButtons');
  ButtonTakePic.Enabled           := Active;
  ButtonGetCamSet.Enabled         := Active;
  ButtonSetCameraSettings.Enabled := Active;
  ButtonViewFinder.Enabled        := Active;
end;

procedure TFormRemote.ButtonStartRemoteProcessClick(Sender: TObject);
begin
  //Starts the remote process
  Log('Enters TForm_Remote.Button_StartRemoteProcessClick');
  if (ButtonStartRemoteProcess.Caption = START_REMOTE_PROC_TXT) then
  begin
    //Connects to the camera and starts the remote mode
    if (ComboBoxTransferMode.ItemIndex <> -1) then
    begin
      mReleaseMode := ReleaseModeType(ComboBoxTransferMode.ItemIndex);
    end;
    ButtonStartRemoteProcess.Caption   := STOP_REMOTE_PROC_TXT;
    ComboBoxTransferMode.Enabled       := false;
    CheckBoxActiveMode.Enabled         := false;
    CheckBoxOnlySupportedParam.Enabled := false;
    ConnectToCamera;
    if (CheckBoxOnlySupportedParam.Checked) then
    begin
      mCurrentCamera := ConnectedCameraParameters;
    end else begin
      mCurrentCamera := AllParameters;
    end;
    StartReleasePic;
    UpdateRemoteParamVCL;
  end else
  begin
    //Closes the viewfinder, if opened, then stops the remote mode and
    //disconnects from the camera
    if (FormViewFinder.Visible) then
    begin
      FormViewFinder.Close;
    end;
    //Disconnects from the camera
    ButtonStartRemoteProcess.Caption   := START_REMOTE_PROC_TXT;
    ComboBoxTransferMode.Enabled       := true;
    CheckBoxActiveMode.Enabled         := true;
    CheckBoxOnlySupportedParam.Enabled := true;
    try
      StopReleasePic;
    finally
      DisconnectFromCamera;
    end;
  end;
end;

procedure TFormRemote.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  //Closes the viewfinder, if opened, then stops the remote mode and
  //disconnects from the camera
  Log('Enters TForm_Remote.FormClose');
  if (FormViewFinder.Visible) then
  begin
    FormViewFinder.Close;
  end;
  if mCameraIsActive then
  begin
    StopReleasePic;
    DisconnectFromCamera;
  end;
end;

procedure TFormRemote.ButtonGetCamSetClick(Sender: TObject);
var remote_param    : RemoteReleaseParametersType;
    zoom_capability : RemoteZoomCapabilityType;
begin
  //Gets remote parameters from the camera and sets the VCL components
  remote_param := CamRemote.RemoteGetRemoteParams;
  Log('Sets remote parameters to dialogue');
  LogRemoteParameters(remote_param);
  SetRemoteParameters(remote_param);
  if (mCameraCapability.DoSupportZoom) then begin
    //Get zoom position
    zoom_capability        := CamRemote.RemoteGetZoomPos;
    TrackBarZoom.Max       := zoom_capability.MaxOpticalZoomPos;
    TrackBarZoom.Position  := zoom_capability.CurrentZoomPos;
    LabelZoomPos.Caption   := IntToStr(TrackBarZoom.Position);
    TrackBarZoom.Frequency := TrackBarZoom.Max DIV 10;
  end;
end;

procedure TFormRemote.FormShow(Sender: TObject);
begin
  //Resize dialogue
  FormRemote.Width  := mIniFile.ReadInteger(REMOTE_SUBKEY, 'RemoteWidth',  FormRemote.Width);
  FormRemote.Height := mIniFile.ReadInteger(REMOTE_SUBKEY, 'RemoteHeight', FormRemote.Height);
  //Set current camera
  Initvar;
end;

//Updates the comboboxes in the remote tab
procedure TFormRemote.UpdateRemoteParamVCL;
var i                           : integer;
    quality_counter             : RemoteFormatQualityType;
    imagesize_counter           : RemoteFormatSizeType;
    strobesetting_counter       : RemoteFormatFlashType;
    imagemode_counter           : RemoteFormatShootingModeType;
    mlweimode_counter           : RemoteFormatMLWeiType;
    afdistance_counter          : RemoteFormatAFDistType;
    whitebalancesetting_counter : RemoteFormatWBType;
    iso_counter                 : RemoteFormatISOType;
    expcomp_counter             : RemoteFormatExposureCompType;
    av_counter                  : RemoteFormatAVType;
    tv_counter                  : RemoteFormatTVType;
    photoeffect_counter         : RemoteFormatPhotoEffectType;
    strobecomp_counter          : RemoteFormatFlashCompType;
    level_counter               : RemoteFormatLevelType;
    beep_counter                : RemoteFormatBeepType;
begin
  //Assign camera parameters possible to set
  //CompQuality
  i := 0;
  SetLength(mCameraRemoteParam.CompQuality, 0);
  for quality_counter := Succ(Low(RemoteFormatQualityType)) to High(RemoteFormatQualityType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.CompQuality[quality_counter] = true)) or
        (mCurrentCamera = AllParameters)) then
    begin
      SetLength(mCameraRemoteParam.CompQuality, i + 1);
      mCameraRemoteParam.CompQuality[i] := quality_counter;
      i := i + 1;
    end;
  end;

  //Image size
  i := 0;
  SetLength(mCameraRemoteParam.ImageSize, 0);
  for imagesize_counter := Succ(Low(RemoteFormatSizeType)) to High(RemoteFormatSizeType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.ImageSize[imagesize_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.ImageSize, i + 1);
       mCameraRemoteParam.ImageSize[i] := imagesize_counter;
       i := i + 1;
    end;
  end;

  //StrobeSetting
  i := 0;
  SetLength(mCameraRemoteParam.StrobeSetting, 0);
  for strobesetting_counter := Succ(Low(RemoteFormatFlashType)) to High(RemoteFormatFlashType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.StrobeSetting[strobesetting_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.StrobeSetting, i + 1);
       mCameraRemoteParam.StrobeSetting[i] := strobesetting_counter;
       i := i + 1;
    end;
  end;

  //StrobeCompSetting
  i := 0;
  SetLength(mCameraRemoteParam.StrobeCompSetting, 0);
  for strobecomp_counter := Succ(Low(RemoteFormatFlashCompType)) to High(RemoteFormatFlashCompType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.StrobeCompSetting[strobecomp_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.StrobeCompSetting, i + 1);
       mCameraRemoteParam.StrobeCompSetting[i] := strobecomp_counter;
       i := i + 1;
    end;
  end;

  //ImageMode
  i := 0;
  SetLength(mCameraRemoteParam.ImageMode, 0);
  for imagemode_counter := Succ(Low(RemoteFormatShootingModeType)) to High(RemoteFormatShootingModeType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.ImageMode[imagemode_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.ImageMode, i + 1);
       mCameraRemoteParam.ImageMode[i] := imagemode_counter;
       i := i + 1;
    end;
  end;

  //MLWeiMode
  i := 0;
  SetLength(mCameraRemoteParam.MLWeiMode, ord(high(RemoteFormatMLWeiType)) + 1);
  for mlweimode_counter := Succ(Low(RemoteFormatMLWeiType)) to High(RemoteFormatMLWeiType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.MLWeiMode[mlweimode_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.MLWeiMode, i + 1);
       mCameraRemoteParam.MLWeiMode[i] := mlweimode_counter;
       i := i + 1;
    end;
  end;

  //AFDistance
  i := 0;
  SetLength(mCameraRemoteParam.AFDistance, 0);
  for afdistance_counter := Succ(Low(RemoteFormatAFDistType)) to High(RemoteFormatAFDistType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.AFDistance[afdistance_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.AFDistance, i + 1);
       mCameraRemoteParam.AFDistance[i] := afdistance_counter;
       i := i + 1;
    end;
  end;

  //WhiteBalanceSetting
  i := 0;
  SetLength(mCameraRemoteParam.WhiteBalanceSetting, 0);
  for whitebalancesetting_counter := Succ(Low(RemoteFormatWBType)) to High(RemoteFormatWBType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.WhiteBalanceSetting[whitebalancesetting_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.WhiteBalanceSetting, i + 1);
       mCameraRemoteParam.WhiteBalanceSetting[i] := whitebalancesetting_counter;
       i := i + 1;
    end;
  end;

  //Contrast
  i := 0;
  SetLength(mCameraRemoteParam.Contrast, 0);
  for level_counter := Succ(Low(RemoteFormatLevelType)) to High(RemoteFormatLevelType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.Contrast[level_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.Contrast, i + 1);
       mCameraRemoteParam.Contrast[i] := level_counter;
       i := i + 1;
    end;
  end;

  //ColorGain
  i := 0;
  SetLength(mCameraRemoteParam.ColorGain, 0);
  for level_counter := Succ(Low(RemoteFormatLevelType)) to High(RemoteFormatLevelType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.ColorGain[level_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.ColorGain, i + 1);
       mCameraRemoteParam.ColorGain[i] := level_counter;
       i := i + 1;
    end;
  end;

  //Sharpness
  i := 0;
  SetLength(mCameraRemoteParam.Sharpness, 0);
  for level_counter := Succ(Low(RemoteFormatLevelType)) to High(RemoteFormatLevelType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.Sharpness[level_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.Sharpness, i + 1);
       mCameraRemoteParam.Sharpness[i] := level_counter;
       i := i + 1;
    end;
  end;

  //ISO
  i := 0;
  SetLength(mCameraRemoteParam.ISO, 0);
  for iso_counter := Succ(Low(RemoteFormatISOType)) to High(RemoteFormatISOType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.ISO[iso_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.ISO, i + 1);
       mCameraRemoteParam.ISO[i] := iso_counter;
       i := i + 1;
    end;
  end;

  //ExposureComp
  i := 0;
  SetLength(mCameraRemoteParam.ExposureComp, 0);
  for expcomp_counter := Succ(Low(RemoteFormatExposureCompType)) to High(RemoteFormatExposureCompType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.ExposureCompensation[expcomp_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.ExposureComp, i + 1);
       mCameraRemoteParam.ExposureComp[i] := expcomp_counter;
       i := i + 1;
    end;
  end;

  //AV
  i := 0;
  SetLength(mCameraRemoteParam.AV, 0);
  for AV_counter := Succ(Low(RemoteFormatAVType)) to High(RemoteFormatAVType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.Av[AV_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.AV, i + 1);
       mCameraRemoteParam.AV[i] := AV_counter;
       i := i + 1;
    end;
  end;

  //TV
  i := 0;
  SetLength(mCameraRemoteParam.TV, 0);
  for TV_counter := Succ(Low(RemoteFormatTVType)) to High(RemoteFormatTVType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.Tv[TV_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.TV, i + 1);
       mCameraRemoteParam.TV[i] := TV_counter;
       i := i + 1;
    end;
  end;

  //PhotoEffect
  i := 0;
  SetLength(mCameraRemoteParam.PhotoEffect, 0);
  for photoeffect_counter := Succ(Low(RemoteFormatPhotoEffectType)) to High(RemoteFormatPhotoEffectType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.PhotoEffect[photoeffect_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.PhotoEffect, i + 1);
       mCameraRemoteParam.PhotoEffect[i] := photoeffect_counter;
       i := i + 1;
    end;
  end;

  //Beep
  i := 0;
  SetLength(mCameraRemoteParam.Beep, 0);
  for beep_counter := Succ(Low(RemoteFormatBeepType)) to High(RemoteFormatBeepType) do
  begin
    if (((mCurrentCamera = ConnectedCameraParameters) and (mCameraCapability.RemoteParamSupported.Beep[beep_counter])) or
        (mCurrentCamera = AllParameters)) then
    begin
       SetLength(mCameraRemoteParam.Beep, i + 1);
       mCameraRemoteParam.Beep[i] := beep_counter;
       i := i + 1;
    end;
  end;

  //Get the items in the parameters comboboxes
  //Compression quality combobox
  ComboBoxQuality.Enabled := false;
  ComboBoxQuality.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.CompQuality) do begin
    ComboBoxQuality.Enabled := true;
    ComboBoxQuality.Items.Add(gCompQualArrayText[mCameraRemoteParam.CompQuality[i]]);
  end;

  //ImageSize combobox
  ComboBoxSize.Enabled := false;
  ComboBoxSize.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.ImageSize) do begin
    ComboBoxSize.Enabled := true;
    ComboBoxSize.Items.Add(gImageSizeArrayText[mCameraRemoteParam.ImageSize[i]]);
  end;

  //StrobeSetting combobox
  ComboBoxFlash.Enabled := false;
  ComboBoxFlash.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.StrobeSetting) do begin
    ComboBoxFlash.Enabled := true;
    ComboBoxFlash.Items.Add(gStrobeSettingArrayText[mCameraRemoteParam.StrobeSetting[i]]);
  end;

  //StrobeCompSetting combobox
  ComboBoxFlashComp.Enabled := false;
  ComboBoxFlashComp.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.StrobeCompSetting) do begin
    ComboBoxFlashComp.Enabled := true;
    ComboBoxFlashComp.Items.Add(gStrobeCompSettingArrayText[mCameraRemoteParam.StrobeCompSetting[i]]);
  end;

  //ImageMode combobox
  ComboBoxImageMode.Enabled := false;
  ComboBoxImageMode.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.ImageMode) do begin
    ComboBoxImageMode.Enabled := true;
    ComboBoxImageMode.Items.Add(gImageModeArrayText[mCameraRemoteParam.ImageMode[i]]);
  end;

  //MLWeiMode combobox
  ComboBoxMeteringMode.Enabled := false;
  ComboBoxMeteringMode.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.MLWeiMode) do begin
    ComboBoxMeteringMode.Enabled := true;
    ComboBoxMeteringMode.Items.Add(gMLWeiModeArrayText[mCameraRemoteParam.MLWeiMode[i]]);
  end;

  //AFDistance combobox
  ComboBoxAFDistance.Enabled := false;
  ComboBoxAFDistance.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.AFDistance) do begin
    ComboBoxAFDistance.Enabled := true;
    ComboBoxAFDistance.Items.Add(gAFDistanceArrayText[mCameraRemoteParam.AFDistance[i]]);
  end;

  //WhiteBalanceSetting combobox
  ComboBoxWhiteBalance.Enabled := false;
  ComboBoxWhiteBalance.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.WhiteBalanceSetting) do begin
    ComboBoxWhiteBalance.Enabled := true;
    ComboBoxWhiteBalance.Items.Add(gWhiteBalanceSetArrayText[mCameraRemoteParam.WhiteBalanceSetting[i]]);
  end;

  //Photo Effect combobox
  ComboBoxPhotoEffect.Enabled := false;
  ComboBoxPhotoEffect.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.PhotoEffect) do begin
    ComboBoxPhotoEffect.Enabled := true;
    ComboBoxPhotoEffect.Items.Add(gPhotoEffectArrayText[mCameraRemoteParam.PhotoEffect[i]]);
  end;

  //Contrast combobox
  ComboBoxContrast.Enabled := false;
  ComboBoxContrast.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.Contrast) do begin
    ComboBoxContrast.Enabled := true;
    ComboBoxContrast.Items.Add(gContrastArrayText[mCameraRemoteParam.Contrast[i]]);
  end;

  //Colorgain combobox
  ComboBoxColorGain.Enabled := false;
  ComboBoxColorGain.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.Colorgain) do begin
    ComboBoxColorGain.Enabled := true;
    ComboBoxColorGain.Items.Add(gColorGainArrayText[mCameraRemoteParam.Colorgain[i]]);
  end;

  //Sharpness combobox
  ComboBoxSharpness.Enabled := false;
  ComboBoxSharpness.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.Sharpness) do begin
    ComboBoxSharpness.Enabled := true;
    ComboBoxSharpness.Items.Add(gSharpnessArrayText[mCameraRemoteParam.Sharpness[i]]);
  end;

  //ISO combobox
  ComboBoxISO.Enabled := false;
  ComboBoxISO.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.ISO) do begin
    ComboBoxISO.Enabled := true;
    ComboBoxISO.Items.Add(gISOArrayText[mCameraRemoteParam.ISO[i]]);
  end;

  //ExposureCompensation combobox
  ComboBoxExpComp.Enabled := false;
  ComboBoxExpComp.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.ExposureComp) do begin
    ComboBoxExpComp.Enabled := true;
    ComboBoxExpComp.Items.Add(gExposureCompArrayText[mCameraRemoteParam.ExposureComp[i]]);
  end;

  //AV combobox
  ComboBoxAv.Enabled := false;
  ComboBoxAv.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.AV) do begin
    ComboBoxAv.Enabled := true;
    ComboBoxAv.Items.Add(gAvArrayText[mCameraRemoteParam.AV[i]]);
  end;

  //TV combobox
  ComboBoxTv.Enabled := false;
  ComboBoxTv.Items.Clear;
  for i := 0 to high(mCameraRemoteParam.TV) do begin
    ComboBoxTv.Enabled := true;
    ComboBoxTv.Items.Add(gTvArrayText[mCameraRemoteParam.TV[i]]);
  end;

  //Beep checkbox
  CheckBoxBeep.Enabled := false;
  if (high(mCameraRemoteParam.Beep) > 0) then begin
    CheckBoxBeep.Enabled := true;
  end;
end;

//Sets new remote parameters in the VCLs in the parameters tab
procedure TFormRemote.SetRemoteParameters(inParam : RemoteReleaseParametersType);
begin
  ComboBoxQuality.ItemIndex      := ComboBoxQuality.Items.IndexOf(gCompQualArrayText[inParam.CompQuality]);
  ComboBoxSize.ItemIndex         := ComboBoxSize.Items.IndexOf(gImageSizeArrayText[inParam.ImageSize]);
  ComboBoxFlash.ItemIndex        := ComboBoxFlash.Items.IndexOf(gStrobeSettingArrayText[inParam.StrobeSetting]);
  ComboBoxFlashComp.ItemIndex    := ComboBoxFlashComp.Items.IndexOf(gStrobeCompSettingArrayText[inParam.StrobeCompSetting]);
  ComboBoxImageMode.ItemIndex    := ComboBoxImageMode.Items.IndexOf(gImageModeArrayText[inParam.ImageMode]);
  ComboBoxMeteringMode.ItemIndex := ComboBoxMeteringMode.Items.IndexOf(gMLWeiModeArrayText[inParam.MLWeiMode]);
  ComboBoxAFDistance.ItemIndex   := ComboBoxAFDistance.Items.IndexOf(gAFDistanceArrayText[inParam.AFDistance]);
  ComboBoxWhiteBalance.ItemIndex := ComboBoxWhiteBalance.Items.IndexOf(gWhiteBalanceSetArrayText[inParam.WhiteBalanceSetting]);
  ComboBoxPhotoEffect.ItemIndex  := ComboBoxPhotoEffect.Items.IndexOf(gPhotoEffectArrayText[inParam.PhotoEffect]);
  ComboBoxContrast.ItemIndex     := ComboBoxContrast.Items.IndexOf(gContrastArrayText[inParam.Contrast]);
  ComboBoxColorGain.ItemIndex    := ComboBoxColorGain.Items.IndexOf(gColorGainArrayText[inParam.ColorGain]);
  ComboBoxSharpness.ItemIndex    := ComboBoxSharpness.Items.IndexOf(gSharpnessArrayText[inParam.Sharpness]);
  ComboBoxISO.ItemIndex          := ComboBoxISO.Items.IndexOf(gISOArrayText[inParam.ISO]);
  ComboBoxAv.ItemIndex           := ComboBoxAv.Items.IndexOf(gAVArrayText[inParam.AV]);
  ComboBoxTv.ItemIndex           := ComboBoxTv.Items.IndexOf(gTVArrayText[inParam.TV]);
  ComboBoxExpComp.ItemIndex      := ComboBoxExpComp.Items.IndexOf(gExposureCompArrayText[inParam.ExposureCompensation]);
  CheckBoxBeep.Checked := false;
  if (inParam.Beep = RemoteFormatBeepOn) then
  begin
    CheckBoxBeep.Checked := true;
  end;
end;

//Event when changing the zoom trackbar
procedure TFormRemote.TrackBarZoomChange(Sender: TObject);
begin
  LabelZoomPos.Caption := IntToStr(TrackBarZoom.Position);
  if ((mReleaseProcessActive) and (mCameraCapability.DoSupportZoom)) then
  begin
    //Turn of Viewfinder temporarily when changing zoom. May not be necessary.
    if mViewFinderEnabled then begin
      CamRemote.RemoteStopViewfinder;
      sleep(1000);
    end;
    CamRemote.RemoteSetZoomPos(TrackBarZoom.Position);
    if mViewFinderEnabled then begin
      sleep(1000);
      CamRemote.RemoteStartViewfinder;
    end;
  end;
end;

procedure TFormRemote.ButtonViewFinderClick(Sender: TObject);
begin
  mViewFinderEnabled := true;
  FormViewFinder.Show;
end;

procedure TFormRemote.ButtonSetCameraSettingsClick(Sender: TObject);
var remote_parameters : RemoteReleaseParametersType;
begin
  //Sets release parameters
  remote_parameters := GetRemoteParameters;
  Log('Sets remote parameters');
  LogRemoteParameters(remote_parameters);
  CamRemote.RemoteSetRemoteParams(remote_parameters);
end;

//Gets remote parameters from the VCL in the remote tab
function TFormRemote.GetRemoteParameters : RemoteReleaseParametersType;
begin
  if (ComboBoxQuality.Enabled) then
    result.CompQuality  := mCameraRemoteParam.CompQuality[ComboBoxQuality.ItemIndex]
  else
    result.CompQuality := RemoteFormatQualityNotUsed;

  if (ComboBoxSize.Enabled) then
    result.ImageSize := mCameraRemoteParam.ImageSize[ComboBoxSize.ItemIndex]
  else
    result.ImageSize := RemoteFormatSizeNotUsed;

  if (ComboBoxFlash.Enabled) then
    result.StrobeSetting := mCameraRemoteParam.StrobeSetting[ComboBoxFlash.ItemIndex]
  else
    result.StrobeSetting := RemoteFormatFlashNotUsed;

  if (ComboBoxFlashComp.Enabled) then
    result.StrobeCompSetting := mCameraRemoteParam.StrobeCompSetting[ComboBoxFlashComp.ItemIndex]
  else
    result.StrobeCompSetting := RemoteFormatFlashCompNotUsed;

  if (ComboBoxImageMode.Enabled) then
    result.ImageMode := mCameraRemoteParam.ImageMode[ComboBoxImageMode.ItemIndex]
  else
    result.ImageMode := RemoteFormatShootingModeNotUsed;

  if (ComboBoxMeteringMode.Enabled) then
    result.MLWeiMode := mCameraRemoteParam.MLWeiMode[ComboBoxMeteringMode.ItemIndex]
  else
    result.MLWeiMode := RemoteFormatMLWeiNotUsed;

  if (ComboBoxAFDistance.Enabled) then
    result.AFDistance := mCameraRemoteParam.AFDistance[ComboBoxAFDistance.ItemIndex]
  else
    result.AFDistance := RemoteFormatAFDistNotUsed;

  if (ComboBoxWhiteBalance.Enabled) then
    result.WhiteBalanceSetting  := mCameraRemoteParam.WhiteBalanceSetting[ComboBoxWhiteBalance.ItemIndex]
  else
    result.WhiteBalanceSetting  := RemoteFormatWBNotUsed;

  if (ComboBoxPhotoEffect.Enabled) then
    result.PhotoEffect := mCameraRemoteParam.PhotoEffect[ComboBoxPhotoEffect.ItemIndex]
  else
    result.PhotoEffect := RemoteFormatPhotoEffectNotUsed;

  if (ComboBoxContrast.Enabled) then
    result.Contrast := mCameraRemoteParam.Contrast[ComboBoxContrast.ItemIndex]
  else
    result.Contrast := RemoteFormatLevelNotUsed;

  if (ComboBoxColorGain.Enabled) then
    result.ColorGain := mCameraRemoteParam.ColorGain[ComboBoxColorGain.ItemIndex]
  else
    result.ColorGain := RemoteFormatLevelNotUsed;

  if (ComboBoxSharpness.Enabled) then
    result.Sharpness := mCameraRemoteParam.Sharpness[ComboBoxSharpness.ItemIndex]
  else
    result.Sharpness := RemoteFormatLevelNotUsed;

  if (ComboBoxISO.Enabled) then
    result.ISO := mCameraRemoteParam.ISO[ComboBoxISO.ItemIndex]
  else
    result.ISO := RemoteFormatISONotUsed;

  if (ComboBoxAV.Enabled) then
    result.AV := mCameraRemoteParam.AV[ComboBoxAv.ItemIndex]
  else
    result.AV := RemoteFormatAVNotUsed;

  if (ComboBoxTV.Enabled) then
    result.TV := mCameraRemoteParam.TV[ComboBoxTv.ItemIndex]
  else
    result.TV := RemoteFormatTVNotUsed;

  if (ComboBoxExpComp.Enabled) then
    result.ExposureCompensation := mCameraRemoteParam.ExposureComp[ComboBoxExpComp.ItemIndex]
  else
    result.ExposureCompensation := RemoteFormatExposureCompNotUsed;

  if (CheckBoxBeep.Enabled) then
  begin
    if (CheckBoxBeep.Checked) then
    begin
      result.Beep := RemoteFormatBeepOn;
    end else begin
      result.Beep := RemoteFormatBeepOff;
    end;
  end else begin
    result.Beep := RemoteFormatBeepNotUsed;
  end;
end;

procedure TFormRemote.LogRemoteParameters(RemoteParameters : RemoteReleaseParametersType);
begin
  //Log remote properties
  Log('Logs remote parameters');
  Log('CompQuality          = ' + inttostr(ord(RemoteParameters.CompQuality)));
  Log('ImageSize            = ' + inttostr(ord(RemoteParameters.ImageSize)));
  Log('StrobeSetting        = ' + inttostr(ord(RemoteParameters.StrobeSetting)));
  Log('StrobeCompSetting    = ' + inttostr(ord(RemoteParameters.StrobeCompSetting)));
  Log('ImageMode            = ' + inttostr(ord(RemoteParameters.ImageMode)));
  Log('MLWeiMode            = ' + inttostr(ord(RemoteParameters.MLWeiMode)));
  Log('AFDistance           = ' + inttostr(ord(RemoteParameters.AFDistance)));
  Log('WhiteBalanceSetting  = ' + inttostr(ord(RemoteParameters.WhiteBalanceSetting)));
  Log('PhotoEffect          = ' + inttostr(ord(RemoteParameters.PhotoEffect)));
  Log('Contrast             = ' + inttostr(ord(RemoteParameters.Contrast)));
  Log('ColorGain            = ' + inttostr(ord(RemoteParameters.ColorGain)));
  Log('Sharpness            = ' + inttostr(ord(RemoteParameters.Sharpness)));
  Log('ISO                  = ' + inttostr(ord(RemoteParameters.ISO)));
  Log('Av                   = ' + inttostr(ord(RemoteParameters.Av)));
  Log('Tv                   = ' + inttostr(ord(RemoteParameters.Tv)));
  Log('ExposureCompensation = ' + inttostr(ord(RemoteParameters.ExposureCompensation)));
  Log('Beep                 = ' + inttostr(ord(RemoteParameters.Beep)));
end;

//Gets application version text
function TFormRemote.Versiontext : string;
var
  size  : DWord;
  size2 : DWord;
  pt    : Pointer;
  pt2   : Pointer;
begin
  //Get the version of application
  result := '';
  size   := GetFileVersionInfoSize(PChar(ParamStr(0)), size2);
  if (size > 0) then
  begin
    GetMem(pt, size);
    try
       GetFileVersionInfo(PChar(ParamStr(0)), 0, size, pt);
       // show the fixed information
       VerQueryValue(pt, '\', pt2, size2);
       with TVSFixedFileInfo(pt2^) do
       begin
         result := result + IntToStr(HiWord(dwFileVersionMS)) + '.';
         result := result + IntToStr(LoWord(dwFileVersionMS)) + '.';
         result := result + IntToStr(HiWord(dwFileVersionLS));
         result := result + ' Build:' + IntToStr(LoWord(dwFileVersionLS));
       end;
    finally
      FreeMem(pt);
    end;
  end;
end;

//Separate application exception handler, making it possible to log
//all exceptions.
procedure TFormRemote.AppException(Sender: TObject; E: Exception);
begin
  log('AppException. Exception=' + E.Message);
  Application.ShowException(E);
end;

//Function to get the filename of the log-file
function TFormRemote.GetLogFileName : string;
var file_dir : string;
begin
  file_dir := ParamStr(0);
  file_dir := extractFileDir(file_dir);
  result   := file_dir + LOG_FILE_NAME;
end;

//Write OS information to log
procedure TFormRemote.WriteVerToLog;
var
  ver_info : TOSVERSIONINFO;
  str      : String;
  i        : Word;
begin
  ver_info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
  if GetVersionEx(ver_info) then begin
    Log('Size of OS-version text:' + IntToStr(ver_info.dwOSVersionInfoSize));
    Log('Major OS-version:'        + IntToStr(ver_info.dwMajorVersion));
    Log('Minor OS-version:'        + IntToStr(ver_info.dwMinorVersion));
    Log('Build of OS-version:'     + IntToStr(ver_info.dwBuildNumber));
    case ver_info.dwPlatformId of
      VER_PLATFORM_WIN32s         : Log('Win16 running Win32s');
      VER_PLATFORM_WIN32_WINDOWS  : Log('Win32 Windows, probably Win95');
      VER_PLATFORM_WIN32_NT       : Log('WinNT, full 32-bit');
    end;
    str := '';
    for i := 0 to 127 do
    begin
      str := str + ver_info.szCSDVersion[i];
    end;
    Log('Additional OS data:' + str);
  end;
end;

//Procedure for writing a string to the log
procedure TFormRemote.Log(Text : string);
var buffer : array[1..512] of char;
    i      : integer;
begin
  if (CheckBoxDebug.Checked) then
  begin
    Text := DateTimeToStr(now) + ':' + Text;
    for i := 1 to length(Text) do
    begin
      buffer[i] := Text[i];
    end;
    buffer[length(Text) + 1] := #13;
    buffer[length(Text) + 2] := #10;
    mLogFile.Write(buffer, length(Text) + 2);
  end;
end;

//Procedure to connect to a camera
procedure TFormRemote.ConnectToCamera;
begin
  //See if already conected
  if (not mConnToCamera) then
  begin
    try
      mCameraInfo := CamRemote.Connect;
      StatusBar.SimpleText := 'Camera is connected';
      mConnToCamera := true;
      Log('Camera model='        + mCameraInfo.CameraModelName);
      Log('Camera name='         + mCameraInfo.OwnerName);
      Log('Camera connected');
    except
      on E:exception do
        begin
          log('Connect_to_powershot. Exception=' + E.Message);
          StatusBar.SimpleText := 'Connection to camera failed';
          mConnToCamera        := false;
          raise;
        end;
    end;
  end;
end;

//Procedure to disconnect from a camera
procedure TFormRemote.DisconnectFromCamera;
begin
  //See if not connected
  if (mConnToCamera) then
  begin
    try
      mConnToCamera := false;
      CamRemote.Disconnect;
      StatusBar.SimpleText := 'Camera is disconnected';
      Log('Camera is disconnected');
    except
      on E:exception do
        begin
          log('Disconnect_from_powershot. Exception=' + E.Message);
          StatusBar.SimpleText := 'Camera communication error';
          raise;
        end;
    end;
  end else begin
    StatusBar.SimpleText := 'Camera already disconnected';
  end;
end;

procedure TFormRemote.CheckBoxDebugClick(Sender: TObject);
var default_string : string;
begin
  if FormRemote.Visible then
  begin
    if (not CheckBoxDebug.Checked) then
    begin
      default_string := Format('Debug is disabled. The logfile (%s) will be removed',
                               [GetLogFileName]);
      MessageDlg(default_string, mtInformation, [mbYes], 0);
      mLogFile.Free;
      DeleteFile(GetLogFileName);
    end else begin
      default_string := Format('Debug is enabled. The logfile (%s) will be created',
                               [GetLogFileName]);
      MessageDlg(default_string, mtInformation, [mbYes], 0);
      mLogFile := TFileStream.Create(GetLogFileName, (fmCreate or fmShareDenyWrite));
    end;
  end;
end;

//Camera event handler
procedure TFormRemote.CamRemoteEvent(Event: EventCallbackType);
var camera_text   : string;
    text_message  : string;
    message_out   : MessageQueueElementType;
begin
  FormRemote.Log('Callback Severity=' + inttostr(Ord(Event.Severity)) +
                 'Event =' + inttostr(Ord(Event.Event)));
  //Do not handle information message, not of interest
  if (Event.Severity = EventSeverityInfo) then
    exit;
  camera_text := 'Camera event-';
  case Event.Severity of
    EventSeverityWarning : text_message := 'Camera warning event';
    EventSeverityClosing : text_message := 'Camera shutdown event';
  end;
  case Event.Event of
    EventBatteryLevelNormal :     camera_text := camera_text + 'Battery level normal';
    EventBatteryLevelWeak :       camera_text := camera_text + 'Battery level weak';
    EventBatteryLevelSafetyLow :  camera_text := camera_text + 'Battery level safety low';
    EventBatteryLevelLB :         camera_text := camera_text + 'Battery level LB';
    EventDialChanged :            camera_text := camera_text + 'Dial changed';
    EventCFGateOpened :           camera_text := camera_text + 'CF gate opened';
    EventBatteryCoverOpened :     camera_text := camera_text + 'Battery cover opened';
    EventConnectionDisappeared :  camera_text := camera_text + 'Camera connection disappeared';
    EventUnrecoverableError :     camera_text := camera_text + 'Unrecoverable error';
    EventUnkonwnCommandReceived : camera_text := camera_text + 'Unknown command received';
    EventRemoteParamterChanged :  camera_text := camera_text + 'Remote parameter changed';
  end;
  //Send the event text to the message thread
  message_out.MessageText   := text_message;
  message_out.Caption       := camera_text;
  message_out.Style         := MB_OK or MB_ICONWARNING;
  message_out.Critical      := false;
  FormRemote.MessageThread.AddMessage(message_out);
end;

//Viewfinder event handler.
procedure TFormRemote.CamRemoteViewfinderEvent(Jpegdata: TMemoryStream);
var jpg : TJpegImage;
begin
  jpg := TJpegImage.Create;
  //Get the 320x240 picture and update the image on the dialogue
  try
    jpg.LoadFromStream(Jpegdata);
    FormViewFinder.Image.Picture.Assign(jpg);
  finally
    jpg.Free;
  end;
end;

//Get picture after taking a picture event handler
procedure TFormRemote.CamRemoteRemoteGetPictureEvent(
  PercentageDone: Integer);
begin
  FormRemote.StatusBar.SimpleText := 'Receiving the picture to disc';
  FormRemote.ProgressBar.Position := PercentageDone;
end;

//Receiving picture event handler when taking a picture
procedure TFormRemote.CamRemoteRemoteTakePictureEvent(
  PercentageDone: Integer);
begin
  FormRemote.StatusBar.SimpleText := 'Handles the picture';
  FormRemote.ProgressBar.Position := PercentageDone;
end;

//Remote process event handler
procedure TFormRemote.CamRemoteRemoteEvent(Event: RemoteEventCallbackType);
begin
  FormRemote.Log('Remote callback event=' + inttostr(Ord(Event)));
  //Check if the release button was pressed on the camera.
  //This applies to PowerShot cameras. EOS cameras do not generate
  //this event when pressing the shutter butten. Instead the EOS camera
  //takes the picture and generates a RemoteEventCallbackReleaseStart event.
  if (Event = RemoteEventCallbackCamReleaseOn) then
  begin
    TimerTakePicture.Enabled := true;
  end;
  if (not FormRemote.CheckBoxActiveMode.Checked) then
  begin
    if (Event = RemoteEventCallbackReleaseComplete) then
    begin
      FormRemote.PictureTaken;
    end;
  end;
end;

procedure TFormRemote.TimerTakePictureTimer(Sender: TObject);
begin
   TimerTakePicture.Enabled := false;
   ButtonTakePicClick(Application);
end;

end.
