unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Media, FMX.Layouts, FMX.ExtCtrls, FMX.Memo, FMX.Objects,
  Winsoft.FireMonkey.Obr, FMX.ListBox, FMX.Controls.Presentation, FMX.ScrollBox,
  FMX.Memo.Types;

type
  TFormMain = class(TForm)
    ButtonStartStop: TButton;
    CameraComponent: TCameraComponent;
    Memo: TMemo;
    FObr: TFObr;
    ImageViewer: TImageViewer;
    procedure ButtonStartStopClick(Sender: TObject);
    procedure FObrBarcodeDetected(Sender: TObject);
    procedure CameraComponentSampleBufferReady(Sender: TObject;
      const ATime: TMediaTime);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    WasRealignContent: Boolean;
    procedure Start;
    procedure Stop;
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

implementation

{$if CompilerVersion >= 33}
  {$define D103PLUS} // Delphi 10.3 or higher
{$endif}

{$if CompilerVersion >= 35}
  {$define D11PLUS} // Delphi 11 or higher
{$endif}

uses System.IOUtils {$ifdef D103PLUS}, Androidapi.JNI.Os,
  Androidapi.JNI.JavaTypes, System.Permissions, FMX.DialogService,
  Androidapi.Helpers {$endif D103PLUS};

{$R *.fmx}

procedure TFormMain.FormCreate(Sender: TObject);
begin
{$ifdef D103PLUS}
  PermissionsService.RequestPermissions([
    JStringToString(TJManifest_permission.JavaClass.CAMERA)],


  {$ifdef D11PLUS}
    procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
  {$else}
    procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
  {$endif D11PLUS}
    begin
      ButtonStartStop.Enabled := (Length(AGrantResults) = 1)
        and (AGrantResults[0] = TPermissionStatus.Granted);
    end,

  {$ifdef D11PLUS}
    procedure(const APermissions: TClassicStringDynArray; const APostRationaleProc: TProc)
  {$else}
    procedure(const APermissions: TArray<string>; const APostRationaleProc: TProc)
  {$endif D11PLUS}
    begin
      APostRationaleProc;
    end);
{$endif D103PLUS}
end;

procedure TFormMain.Start;
begin
  FObr.Active := True;
  CameraComponent.Active := True;
  ButtonStartStop.Text := 'Stop';
end;

procedure TFormMain.Stop;
begin
  CameraComponent.Active := False;
  FObr.Active := False;
  ButtonStartStop.Text := 'Start';
end;

procedure TFormMain.CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
begin
  CameraComponent.SampleBufferToBitmap(ImageViewer.Bitmap, True);
  CameraComponent.SampleBufferToBitmap(FObr.Picture, True);
  FObr.Scan;

  // TImageViewer workaround for Android and iOS
  if not WasRealignContent then
  begin
    ImageViewer.RealignContent;
    WasRealignContent := True;
  end;
end;

procedure TFormMain.FObrBarcodeDetected(Sender: TObject);
var
  i: Integer;
  Barcode: TObrSymbol;
begin
  Memo.Lines.Clear;
  for i := 0 to FObr.BarcodeCount - 1 do
  begin
    Barcode := FObr.Barcode[i];
    Memo.Lines.Append(Barcode.SymbologyName + Barcode.SymbologyAddonName + ' ' + Barcode.OrientationName + ' ' + Barcode.DataUtf8);
    Memo.GoToTextEnd;
  end;
end;

procedure TFormMain.ButtonStartStopClick(Sender: TObject);
begin
  try
    if not FObr.Active then
      Start
    else
      Stop
  except
    on E: Exception do
    begin
      Stop;
      raise
    end;
  end
end;

end.
