unit uFileManager;

(*
  To modify the SML schema, rebuild the XML Bindings and for examples of use see:
  361 - Rebuilding File Manager XML bindings 2016-05-11
  In the notebook
*)
interface

{$REGION ' Header '}

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Spin, ExtCtrls, Buttons, Mask, ComCtrls,
  Menus, ToolWin, xmldom, XMLIntf, msxmldom, XMLDoc, FileCtrl, Registry, Xml.omnixmldom, Xml.adomxmldom,

  SDL_NumLab, AbNumEdit, _GClass, AbSwitch, AbGradient, AbLED, SETI_SML,

  uSETICommon,
  Vcl.TMSLogging, TMSLoggingEventLogOutputHandler, TMSLoggingUtils, TMSLoggingTextOutputHandler, JvExControls, JvgImage, JvExExtCtrls,
  JvImage, JvExForms, JvCustomItemViewer, JvImagesViewer,
  uRiff, uRiffIF;

const
  sbStatusID = 0;
  sbStatus = sbStatusID + 1;
  sbHintID = sbStatus + 1;
  sbHint = sbHintID + 1;
  sbEventID = sbHint + 1;
  sbEvent = sbEventID + 1;
  SETINetFileManagerKey = '\SOFTWARE\SETI Net\File Manager';

type
  time_set = record
    yr, mo, dy, hr, mi, se, hu: word;
  end;

type
  TfrmFileManager = class(TForm)
    docSML: TXMLDocument;
    dlgSaveSML: TSaveDialog;
    mnuMain: TMainMenu;
    mnuFileExitItem: TMenuItem;
    mnuPrintSetup: TMenuItem;
    FilePrintItem: TMenuItem;
    mnuSaveSMLAs: TMenuItem;
    mnuSaveSML: TMenuItem;
    mnuSMLFileOpen: TMenuItem;
    dlgOpenSML: TOpenDialog;
    PrintDialog: TPrintDialog;

    mnuHelp: TMenuItem;
    mnuAbout: TMenuItem;
    mnuShowHints: TMenuItem;
    dlgOpenWAV: TOpenDialog;
    dlgSaveWAV: TSaveDialog;
    mnuSMLFile: TMenuItem;
    mnuWAVFile: TMenuItem;
    mnuOpenWAV: TMenuItem;
    mnuTagSaveWAV: TMenuItem;
    mnuTagSaveWAVAs: TMenuItem;

    mnuJPGFile: TMenuItem;
    mnuOpenJPG: TMenuItem;
    mnuTagSaveJPG: TMenuItem;
    mnuTagSaveJPGAs: TMenuItem;
    dlgOpenJPG: TOpenDialog;
    dlgSaveJPG: TSaveDialog;
    mnuDefaultSML: TMenuItem;
    N3: TMenuItem;
    pcFileManager: TPageControl;
    tsSETIStation: TTabSheet;
    gradTitleBlock: TAbGradient;
    lblTitleBlock: TLabel;
    gbStationLocation: TGroupBox;
    lblStationID: TLabel;
    edGridSquare: TEdit;
    gbFiles: TGroupBox;
    gbWavFile: TGroupBox;
    edWAVFileName: TEdit;
    btnWaveFileOpen: TButton;
    btnSaveAsWAV: TButton;
    btnSaveWAV: TButton;
    gbSML: TGroupBox;
    btnOpenSMLFile: TButton;
    btnSMLSaveAs: TButton;
    edSMLFileName: TEdit;
    btnSMLSave: TButton;
    gbJPGFile: TGroupBox;
    btnJPGFileOpen: TButton;
    edJPGFileName: TEdit;
    btnSaveAsJPG: TButton;
    btnSaveJPG: TButton;
    gbPersonell: TGroupBox;
    gbTarget: TGroupBox;
    cbFalsified: TCheckBox;
    edTargetNote: TEdit;
    edConstellationName: TEdit;
    tsAntenna: TTabSheet;
    pnlEquip: TPanel;
    lblAntennaSystem: TLabel;
    gbBandPassFIlterandRFAmp: TGroupBox;
    lblXdB: TLabel;
    lblYdB: TLabel;
    gbBandPassFilter: TGroupBox;
    lblHighFreq: TLabel;
    lblLowerFreq: TLabel;
    lblInsLoss: TLabel;
    lblBPFdb: TLabel;
    lblHz: TLabel;
    lblHiFreqHz: TLabel;
    lblBPFNote: TLabel;
    nsBPFLoss: TAbNumSpin;
    neHiCutoff: TAbNumEdit;
    neLoCutoff: TAbNumEdit;
    edBPFNote: TEdit;
    gbRFAmp: TGroupBox;
    edRFAmpModel: TEdit;
    edRFAmpManufacture: TEdit;
    gbAntenna: TGroupBox;
    lblAntMfg: TLabel;
    lblAntModel: TLabel;
    lblAntNote: TLabel;
    gbHorn: TGroupBox;
    lblHornShape: TLabel;
    lblFeed: TLabel;
    edHornNote: TEdit;
    gbLNA: TGroupBox;
    lblLNAGain: TLabel;
    lblNF: TLabel;
    lblLNAdB: TLabel;
    lblLNAMfg: TLabel;
    lblLNAModel: TLabel;
    lblLNANFdB: TLabel;
    lblLNANote: TLabel;
    edLNAManufacture: TEdit;
    edLNAModel: TEdit;
    nsLNAGain: TAbNumSpin;
    nsLNANF: TAbNumSpin;
    edAntennaLNANote: TEdit;
    gbMount: TGroupBox;
    lblMountMfg: TLabel;
    lblMountModel: TLabel;
    edMountManufacture: TEdit;
    edMountModel: TEdit;
    gbShape: TGroupBox;
    lblDia: TLabel;
    lblFl: TLabel;
    lblRD: TLabel;
    lblShapeGain: TLabel;
    lblHPBW: TLabel;
    lblShapeNote: TLabel;
    rgKind: TRadioGroup;
    nsReflectorDiameter: TAbNumSpin;
    nsFocalLength: TAbNumSpin;
    nsReflectorDepth: TAbNumSpin;
    nsShapeGain: TAbNumSpin;
    nsHPBW: TAbNumSpin;
    edShapeNote: TEdit;
    edAntennaManufacture: TEdit;
    edAntennaModel: TEdit;
    edAntennaNote: TEdit;
    gbPointingCoordinates: TGroupBox;
    gbDecRa: TGroupBox;
    XlblRA: TLabel;
    gbAzEl: TGroupBox;
    tsReceiver: TTabSheet;
    lblReceivingSystem: TLabel;
    gbReceiver: TGroupBox;
    lblRecvMfg: TLabel;
    lblRcvModel: TLabel;
    lblRcvNote: TLabel;
    edReceiverManufacture: TEdit;
    edReceiverModel: TEdit;
    edReceiverNote: TEdit;
    gbAnalogFilter: TGroupBox;
    ckAnalogFilter: TCheckBox;
    edAnalogFilter: TEdit;
    gbA_To_D: TGroupBox;
    lblMfg: TLabel;
    lblATODModel: TLabel;
    lblBits: TLabel;
    lblSampleRate: TLabel;
    lblContentLeft: TLabel;
    lblContentRight: TLabel;
    lblADNote: TLabel;
    edA_To_DManfacture: TEdit;
    edA_To_DModel: TEdit;
    rgChannels: TRadioGroup;
    edA_To_DContentLeft: TEdit;
    edA_To_DContentRight: TEdit;
    nsA_To_DSamplingRate: TAbNumSpin;
    nsA_To_DEncodingBits: TAbNumSpin;
    edA_To_DNote: TEdit;
    gbCalibration: TGroupBox;
    lblCalGain: TLabel;
    lblOffset: TLabel;
    nsCalibrationGain: TAbNumSpin;
    nsCalibrationOffset: TAbNumSpin;
    gbWeightingWindow: TGroupBox;
    lblWeightType: TLabel;
    ckWeightingWindow: TCheckBox;
    edWeightingWindowNote: TEdit;
    gbDSP: TGroupBox;
    lblDSPMfg: TLabel;
    lblDSMModel: TLabel;
    lblAlgorithm: TLabel;
    lblDSPNote: TLabel;
    edDSPManfacture: TEdit;
    edDSPModel: TEdit;
    edDSPAlgorithm: TEdit;
    ckDSP: TCheckBox;
    edDSPNote: TEdit;
    gbDigitalFilter: TGroupBox;
    lblLower: TLabel;
    lblUpper: TLabel;
    lblDifFilNote: TLabel;
    lblSkirt: TLabel;
    rgDSPFilterType: TRadioGroup;
    edDSPFilterNote: TEdit;
    neDSPFilterUpperSkirt: TAbNumEdit;
    neDSPFilterLowerSkirt: TAbNumEdit;
    ckDigitalFilter: TCheckBox;
    gbTimeKeeping: TGroupBox;
    lblDescription: TLabel;
    edTimeKeepingDescription: TEdit;
    gbSpectrumAnalyzerInstance: TGroupBox;
    lblVertical: TLabel;
    lblSpectrumSize: TLabel;
    lblInt: TLabel;
    lblThreshold: TLabel;
    lblSegment: TLabel;
    neThreshold: TAbNumEdit;
    neSegmentSize: TAbNumEdit;
    gbTuning: TGroupBox;
    tsXML: TTabSheet;
    neChirp: TAbNumEdit;
    lblChirp: TLabel;
    gradeAntenna: TAbGradient;
    gradeReceiver: TAbGradient;
    lblObserverName: TLabel;
    lblOperatorName: TLabel;
    gbVersion: TGroupBox;
    lblConst: TLabel;
    lblTarget: TLabel;
    lblHitNote: TLabel;
    edSysOpName: TEdit;
    edObserverNames: TEdit;
    lblVersion: TLabel;
    lblCreatorVersion: TLabel;
    edHornShape: TEdit;
    edHornFeed: TEdit;
    neCenterFrequency: TAbNumEdit;
    neBin: TAbNumEdit;
    lblCenterFreq: TLabel;
    lblFrequency: TLabel;
    Label4: TLabel;
    neIntegeration: TAbNumEdit;
    edWeightingWindowType: TEdit;
    gbTitleSML: TGroupBox;
    lblXMLVers: TLabel;
    lblXMLVersion: TLabel;
    lblSMLVersion: TLabel;
    lblSMLVers: TLabel;
    lblHornDia: TLabel;
    neHornDiameter: TAbNumEdit;
    edETNote: TEdit;
    LblHints: TLabel;
    edVerticalRange: TEdit;
    edSpectrumSize: TEdit;
    gbOpMode: TGroupBox;
    edOpMode: TEdit;
    lblWindowNote: TLabel;
    neAz: TAbNumEdit;
    neEl: TAbNumEdit;
    lblAzDeg: TLabel;
    lblElDeg: TLabel;
    lblAz: TLabel;
    lblEl: TLabel;
    neDEC: TAbNumEdit;
    neRa: TAbNumEdit;
    lblDec: TLabel;
    lblDecDeg: TLabel;
    lblRaDeg: TLabel;
    lblRa: TLabel;
    lblCreatedOn: TLabel;
    edDateTimeUTC: TEdit;
    ledSkyMapLocked: TAbLED;
    LabeledEdit2: TLabeledEdit;
    moSML: TMemo;
    btnDefaultSML: TButton;
    sbFileManager: TStatusBar;
    edReceiverMode: TEdit;
    lblReceiverMode: TLabel;
    lblETAmplitude: TLabel;
    neAmplitude: TAbNumEdit;
    lblAmplitude: TLabel;
    neAmbiant: TAbNumEdit;
    lblSETIVersion: TLabel;
    lblSETIVers: TLabel;
    cbLNAInSystem: TCheckBox;
    lblReceiverNote: TLabel;
    lblReceiverBandwidth: TLabel;
    neReceiverBandwidth: TAbNumEdit;
    AbLED1: TAbLED;
    pnlDecimal: TPanel;
    lblLat: TLabel;
    lblLon: TLabel;
    gbMoutSettings: TGroupBox;
    nsElMin: TAbNumSpin;
    nsElMax: TAbNumSpin;
    nsAzMax: TAbNumSpin;
    nsAzMin: TAbNumSpin;
    lblAzMin: TLabel;
    lblAzMax: TLabel;
    rgMountType: TRadioGroup;
    lblMountEl: TLabel;
    lblMountAz: TLabel;
    ledSMLOpen: TAbLED;
    tsPrototypeBlockDiagram: TTabSheet;

    gbID: TGroupBox;
    neConstID: TAbNumEdit;
    neTargetID: TAbNumEdit;
    lblScanID: TLabel;
    neScanID: TAbNumEdit;
    neHitID: TAbNumEdit;
    lblHitID: TLabel;
    lblTargetID: TLabel;
    lblConstID: TLabel;
    edTargetName: TEdit;
    pnlL1: TPanel;
    lblL1dB: TLabel;
    nsL1: TAbNumSpin;
    ckL1: TCheckBox;
    pnlL2: TPanel;
    ckL2: TCheckBox;
    nsL2: TAbNumSpin;
    lblL2dB: TLabel;
    pnlL3: TPanel;
    lblL3dB: TLabel;
    ckL3: TCheckBox;
    nsL3: TAbNumSpin;
    pnlRFAmp: TPanel;
    ckRFAmp: TCheckBox;
    nsRFAmpGain: TAbNumSpin;
    edRFAmpNote: TEdit;
    lblGainDB: TLabel;
    lblRFGain: TLabel;
    lblRFAmpNote: TLabel;
    lblRFAmpMfg: TLabel;
    lblRFAmpModel: TLabel;
    pnlBPFInSystem: TPanel;
    ckBPFInSys: TCheckBox;
    neBinCount: TAbNumEdit;
    lblBinCount: TLabel;
    neBinWidth: TAbNumEdit;
    lblBinWidth: TLabel;
    neLinesPerFrame: TAbNumEdit;
    lblLinesPerFrame: TLabel;
    lblThresholdPerCent: TLabel;
    lblVerticalRangeMv: TLabel;
    neSETIDataID: TAbNumEdit;
    lblSETIDataID: TLabel;
    neDecLat: TAbNumEdit;
    neDecLon: TAbNumEdit;
    btnTest: TButton;
    neFrequency: TAbNumEdit;
    pnlSML: TPanel;
    btnRefreshSML: TButton;
    tsLog: TTabSheet;
    moLog: TMemo;
    btnStartLogging: TButton;
    btnClearLog: TButton;
    ledWAVOpen: TAbLED;
    pnlSpacer1: TPanel;
    pnlSpacer2: TPanel;
    ledJPGOpen: TAbLED;
    Image1: TImage;
    JvImage1: TJvImage;
    Test1: TMenuItem;

    procedure FormCreate(Sender: TObject);

    procedure mnuFileExitItemClick(Sender: TObject);
    procedure FilePrintItemClick(Sender: TObject);

    procedure rgMountTypeClick(Sender: TObject);
    procedure rgKindClick(Sender: TObject);
    procedure mnuShowHintsClick(Sender: TObject);
    procedure mnuCloseFileClick(Sender: TObject);

    procedure btnSaveCombinedClick(Sender: TObject);
    procedure ComboBox3KeyPress(Sender: TObject; var Key: Char);
    procedure ComboBox1KeyPress(Sender: TObject; var Key: Char);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnSMLSaveAsClick(Sender: TObject);
    procedure DropFileTarget1Drop(Sender: TObject; ShiftState: TShiftState; APoint: TPoint; var Effect: Integer);
    procedure tsAntennaShow(Sender: TObject);
    procedure tsSETIStationShow(Sender: TObject);
    procedure tsReceiverShow(Sender: TObject);
    procedure tsBlockDiagramShow(Sender: TObject);
    procedure tsWaterfallShow(Sender: TObject);
    procedure tsXMLShow(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure btnSaveAsJPGClick(Sender: TObject);
    procedure btnJPGFileOpenClick(Sender: TObject);
    procedure btnWaveFileOpenClick(Sender: TObject);
    procedure btnSaveAsWAVClick(Sender: TObject);
    procedure btnOpenSMLFileClick(Sender: TObject);
    procedure mnuSaveSMLClick(Sender: TObject);
    procedure btnSMLSaveClick(Sender: TObject);
    procedure btnSaveWAVClick(Sender: TObject);
    procedure btnSaveJPGClick(Sender: TObject);

    procedure mnuAboutClick(Sender: TObject);
    procedure btnDefaultSMLClick(Sender: TObject);

    procedure moSMLEnter(Sender: TObject);
    procedure docSMLAfterOpen(Sender: TObject);
    procedure docSMLBeforeClose(Sender: TObject);
    procedure docSMLAfterClose(Sender: TObject);
    procedure docSMLAfterNodeChange(const Node: IXMLNode; ChangeType: TNodeChange);

    procedure setStationConstellation(value: String);
    procedure setStationTarget(value: String);
    procedure setConstellationID(value: Integer);
    procedure setTargetID(value: Integer);
    procedure setScanID(value: Integer);
    procedure setHitID(value: Integer);
    procedure setSETI_Data(value: Integer);
    procedure setSMLCreateDateTime(value: String);
    Procedure setOperatingMode(value: String);
    Procedure setStationGridSquare(value: String);
    procedure setAzimuthMaximum(value: Single);
    procedure setAzimuthMinimum(value: Single);
    procedure setElevationMinimum(value: Single);
    procedure setElevationMaximum(value: Single);
    procedure setAzimuth(value: Single);
    procedure setElevation(value: Single);
    procedure setDeclination(value: Single);
    procedure setRightAscension(value: Single);
    Procedure setMountType(value: TMount);
    Procedure setSkyMapLocked(value: boolean);

    Procedure setVerticalRange(value: Single);
    Procedure setFFTSize(value: Integer);
    Procedure setIntegration(value: Integer);
    Procedure setThreshold(value: Integer);
    Procedure setSegmentSize(value: Integer);

    Procedure setFrequency(value: int64);
    Procedure setCenterFrequency(value: int64);
    Procedure setETBin(value: Integer);
    Procedure setAmplitude(value: Single);
    Procedure setAmbiant(value: Single);
    Procedure setBandWidth(value: Integer);
    Procedure setChirp(value: Single);
    Procedure setLatitude(value: Single);
    Procedure setLongitude(value: Single);
    Procedure setLinesPerFrame(value: Integer);

    procedure neFrequencyValueChanged(Sender: TObject);
    procedure btnRefreshSMLClick(Sender: TObject);
    procedure mnuDefaultSMLClick(Sender: TObject);
    procedure btnStartLoggingClick(Sender: TObject);
    procedure btnClearLogClick(Sender: TObject);
    procedure Test1Click(Sender: TObject);

  private
    { Private declarations }
    SETI_Station: IXMLSeti_Station;
    TitleBlockNode: IXMLSETI_Station_TitleBlock;
    EquipmentSetupNode: IXMLSETI_Station_EquipmentSetup;

    // Title Block
    FInUse: boolean;
    SETINetReg: TRegistry;
    FSMLFileName: String;
    FJPGFileName: String;
    FWAVFileName: String;
    // Antenna Nodes and children
    msJPG: TmemoryStream;
    WAVRiff: TRiff; // RIFF File interface
    function LoadDefaultSML: boolean;
    procedure DisplayHint(Sender: TObject);
    procedure OpenSML(FileName: String);
    procedure SaveSML(FileName: string);

    procedure OpenWAVfile(FileName: string);
    procedure SaveWAV(FileName: string);
    procedure OpenJPG(FileName: String);
    Procedure SaveJPG(FileName: String; msJPG: TmemoryStream);

    procedure TitleSMLToControls;
    procedure AntennaSMLToControls;
    procedure ReceiverSMLToControls;
    procedure TitleControlsToSML;
    procedure AntennaControlsToSML;
    procedure ReceiverControlsToSML;

    function getSysOpName: string;
    function getObserversNames: string;
    procedure setFalsified(value: boolean);
    procedure setBPFInSystem(value: boolean);
    procedure setBinWidth(value: Single);

  public

    procedure DoOutput(Sender: TObject; AOutputInformation: TTMSLoggerOutputInformation);
    function GetSML: ANSIString;

    // TitlePage
    Property Constellation: string write setStationConstellation;
    Property Target: string write setStationTarget;
    Property SysOp: string Read getSysOpName;
    Property Observers: string Read getObserversNames;
    Property InUse: boolean read FInUse write FInUse;
    Property ConstellationID: Integer write setConstellationID;
    Property TargetID: Integer write setTargetID;
    Property ScanID: Integer write setScanID;
    Property HitID: Integer write setHitID;
    Property SETIDataID: Integer write setSETI_Data;
    Property SMLCreateDateTime: String write setSMLCreateDateTime;
    Property WAVFileName: string write FWAVFileName;
    Property JPGFileName: string write FJPGFileName;
    Property SMLFileName: string read FSMLFileName write FSMLFileName;
    Property OperatingMode: string write setOperatingMode;
    property Latitude: Single write setLatitude;
    Property Longitude: Single write setLongitude;
    Property StationGridSquare: String write setStationGridSquare;
    Property MountType: TMount write setMountType;

    // Antenna
    Property Azimuth: Single write setAzimuth;
    Property Elevation: Single write setElevation;
    Property Declination: Single write setDeclination;
    Property RightAscension: Single write setRightAscension;
    Property AzimuthMinimum: Single write setAzimuthMinimum;
    Property AzimuthMaximum: Single write setAzimuthMaximum;
    Property ElevationMinimum: Single write setElevationMinimum;
    Property ElevationMaximum: Single write setElevationMaximum;
    Property SkyMapLocked: boolean write setSkyMapLocked;
    Property Falsified: boolean write setFalsified;

    // Spectrum Analyzer
    Property VerticalRange: Single write setVerticalRange;
    Property FFTSize: Integer write setFFTSize;
    Property Integration: Integer write setIntegration;
    Property Threshold: Integer write setThreshold;
    Property SegmentSize: Integer write setSegmentSize;
    Property LinesPerFrame: Integer write setLinesPerFrame;
    Property BinWidth: Single write setBinWidth;

    // Tuning
    Property Frequency: int64 write setFrequency;
    Property CenterFrequency: int64 write setCenterFrequency;
    Property Chirp: Single write setChirp;
    Property ETBin: Integer write setETBin;
    Property Amplitude: Single write setAmplitude;
    Property Ambiant: Single write setAmbiant;
    Property BandWidth: Integer write setBandWidth;

    Property BPFInSystem: boolean write setBPFInSystem;
  end;

var

  frmFileManager: TfrmFileManager;

{$ENDREGION}

implementation

{$R *.dfm}

uses uTime, uJPGComments, SDL_stringl, uAbout, ShellApi, SDL_FileSys;

//
procedure TfrmFileManager.DoOutput(Sender: TObject; AOutputInformation: TTMSLoggerOutputInformation);
begin
  moLog.Lines.Insert(0, TTMSLoggerUtils.StripHTML(TTMSLoggerUtils.GetConcatenatedLogMessage(AOutputInformation, false)));
end;

{$REGION ' Create '}

resourcestring
  sSaveChanges = 'Save changes to %s?';
  sOverWrite = 'OK to overwrite %s';
  sUntitled = 'No File';
  sModified = 'Modified';
  sColRowInfo = 'Line: %3d   Col: %3d';

  (* REGISTRY ENTRIES *)

  (* C  R  E  A  T  E *)
procedure TfrmFileManager.FormCreate(Sender: TObject);

begin
  SETINetReg := TRegistry.Create;
  SETINetReg.LazyWrite := false;
  try
    SETINetReg.RootKey := HKEY_CURRENT_USER;

    if SETINetReg.KeyExists(SETINetFileManagerKey) then
    begin { Key Exists }
      if SETINetReg.OpenKey(SETINetFileManagerKey, false) then { //This will NOT create the key }
      begin
        try
          with SETINetReg do
          begin
            frmFileManager.Left := ReadInteger('Left');
            frmFileManager.Top := ReadInteger('Top');
            If (Screen.MonitorCount = 1) AND (frmFileManager.Left > 640) then
              frmFileManager.Left := 200; // Set for Single monitor
            FSMLFileName := ReadString('SMLFile');

          end { with SETINetReg }
        except // an exception s raised is there isn't a version entry

          // D E F A U L T   R E G   E N T R I E S
          begin { New User }
            with SETINetReg do
            begin
              // OpenKey will create the key if the second parameter is true and the key does not already exist
              // Default Antenna/SRT setup
              WriteInteger('Left', 10);
              WriteInteger('Top', 100);
              writeString('SMLFile', '');
            end;
          end;
        end;
      end;
    end;

  finally
    SETINetReg.Free;
  end;

  begin
    pcFileManager.ActivePage := tsSETIStation;
    // DropFileTarget1.Register(tsSETIStation)
  end;
  // btnExpandTreeClick(Self);
  mnuShowHintsClick(Self);
{$IF Defined(SETI)}
  frmFileManager.Visible := false;
  frmFileManager.InUse := false;
{$ELSE}
  frmFileManager.Visible := false;
{$IFEND}
  begin
    TMSLogger.RegisterOutputHandlerClass(TTMSLoggerEventLogOutputHandler);

    TMSLogger.OnOutput := DoOutput;
    TMSLogger.Active := false;
    TMSLogger.Clear;
    moLog.Clear;
  end;
  If FileExists(FSMLFileName) then
    OpenSML(FSMLFileName) // Open the last SML File
  else
  begin
    LoadDefaultSML
  end;

{$IF Defined(EUREKALOG) AND Defined(FileManager)}
  Caption := frmAntenna.Caption + (' + EurekaLog ');
  Caption := Caption + ' (' + IntToStr(SizeOf(Pointer) * 8) + ' Bit)';
{$IFEND}
  moSML.Clear;
end; { FormCreate }
{$ENDREGION}
//
{$REGION ' Getter/Setter '}

function TfrmFileManager.LoadDefaultSML: boolean;
var
  List: TStringList;
  Stream: TResourceStream;
begin

  btnSMLSave.Enabled := false;
  mnuSaveSML.Enabled := false;
  btnSMLSaveAs.Enabled := false;
  Stream := TResourceStream.Create(HInstance, 'GeneratedSML', RT_RCDATA);
  try
    List := TStringList.Create;
    try
      docSML.LoadFromStream(Stream);
    finally
      List.Free
    end;
  finally
    Stream.Free;
  end;

  if docSML.Active then
    sbFileManager.Panels[sbStatus].Text := 'SML is Active'
  else
    sbFileManager.Panels[sbStatus].Text := 'SML NOT Active';

  SETI_Station := GetSETI_Station(docSML);
  TitleBlockNode := SETI_Station.TitleBlock;
  EquipmentSetupNode := SETI_Station.EquipmentSetup;
  TitleBlockNode.Files.SML := '<default>';
  TitleBlockNode.Files.WAV := FWAVFileName;
  TitleBlockNode.Files.JPG := FJPGFileName;
  TitleSMLToControls;
  AntennaSMLToControls;
  ReceiverSMLToControls;

  moSML.Clear;
  // -----------------------
  moSML.Lines.Text := XMLDoc.FormatXMLData(docSML.Xml.Text);
  // -----------------------

  btnSMLSave.Enabled := false;
  mnuSaveSML.Enabled := false;
  btnSMLSaveAs.Enabled := true;
  FSMLFileName := ''; // dont save a good name either dude.
end;

procedure TfrmFileManager.setSETI_Data(value: Integer);
begin
  neSETIDataID.value := value;
end;

procedure TfrmFileManager.setBinWidth(value: Single);
begin
  neBinWidth.value := value;
end;

Procedure TfrmFileManager.setLinesPerFrame(value: Integer);
begin
  neLinesPerFrame.ValueAsInt := value;
end;

procedure TfrmFileManager.setBPFInSystem(value: boolean);
begin
  ckBPFInSys.Checked := value;
end;

procedure TfrmFileManager.setFalsified(value: boolean);
begin
  if value = true then
    cbFalsified.Checked := true
  else
    cbFalsified.Checked := false
end;

function TfrmFileManager.getObserversNames: string;
begin
  Result := edObserverNames.Text;
end;

function TfrmFileManager.getSysOpName: string;
begin
  Result := edSysOpName.Text;
end;

Procedure TfrmFileManager.setChirp(value: Single);
begin
  neChirp.value := value;
end;

Procedure TfrmFileManager.setFrequency(value: int64);
begin
  neFrequency.ValueAsInt := value;
end;

Procedure TfrmFileManager.setCenterFrequency(value: int64);
begin
  neCenterFrequency.ValueAsInt := value;
end;

Procedure TfrmFileManager.setETBin(value: Integer);
begin
  neBin.ValueAsInt := value;
end;

Procedure TfrmFileManager.setAmplitude(value: Single);
begin
  neAmplitude.value := value;
end;

Procedure TfrmFileManager.setAmbiant(value: Single);
begin
  neAmbiant.value := value;
end;

Procedure TfrmFileManager.setBandWidth(value: Integer);
begin
  neReceiverBandwidth.ValueAsInt := value;
end;

Procedure TfrmFileManager.setVerticalRange(value: Single);
begin
  edVerticalRange.Text := FloatToStr(value);
end;

Procedure TfrmFileManager.setFFTSize(value: Integer);
begin
  edSpectrumSize.Text := IntToStr(value);
end;

Procedure TfrmFileManager.setIntegration(value: Integer);
begin
  neIntegeration.ValueAsInt := value;
end;

Procedure TfrmFileManager.setThreshold(value: Integer);
begin
  neThreshold.ValueAsInt := value;
end;

Procedure TfrmFileManager.setSegmentSize(value: Integer);
begin
  neSegmentSize.ValueAsInt := value;
end;

procedure TfrmFileManager.setSkyMapLocked(value: boolean);
begin
  ledSkyMapLocked.Checked := value;
end;

procedure TfrmFileManager.setAzimuth(value: Single);
begin
  neAz.value := value;
end;

procedure TfrmFileManager.setElevation(value: Single);
begin
  neEl.value := value;
end;

procedure TfrmFileManager.setDeclination(value: Single);
begin
  neDEC.value := value;
end;

procedure TfrmFileManager.setRightAscension(value: Single);
begin
  neRa.value := value;
end;

procedure TfrmFileManager.setAzimuthMaximum(value: Single);
begin
  nsAzMax.value := value;
end;

procedure TfrmFileManager.setAzimuthMinimum(value: Single);
begin
  nsAzMin.value := value;
end;

procedure TfrmFileManager.setElevationMinimum(value: Single);
begin
  nsElMin.value := value;
end;

procedure TfrmFileManager.setElevationMaximum(value: Single);
begin
  nsElMax.value := value;
end;

procedure TfrmFileManager.setMountType(value: TMount);
begin
  // strColor := GetEnumName(TypeInfo(TCustomColor), Ord(Color));
  rgMountType.ItemIndex := Integer(value);
end;

procedure TfrmFileManager.setStationGridSquare(value: String);
begin
  edGridSquare.Text := value;
end;

procedure TfrmFileManager.setLatitude(value: Single);
begin
  neDecLat.value := value;
end;

procedure TfrmFileManager.setLongitude(value: Single);
begin
  neDecLon.value := value;
end;

procedure TfrmFileManager.setOperatingMode(value: String);
begin
  edOpMode.Text := (value);
end;

procedure TfrmFileManager.setSMLCreateDateTime(value: string);
begin
  edDateTimeUTC.Text := value;
end;

procedure TfrmFileManager.setScanID(value: Integer);
begin
  neScanID.value := value;
end;

procedure TfrmFileManager.setHitID(value: Integer);
begin
  neHitID.value := value;
end;

procedure TfrmFileManager.setTargetID(value: Integer);
begin
  neTargetID.value := value;
end;

procedure TfrmFileManager.setStationTarget(value: String);
begin
  edTargetName.Text := value;
end;

procedure TfrmFileManager.setStationConstellation(value: String);
begin
  edConstellationName.Text := value;
end;

procedure TfrmFileManager.setConstellationID(value: Integer);
begin
  neConstID.value := value;
end;

function TfrmFileManager.GetSML: ANSIString;
(* G E T   S M L *)
begin
  TitleControlsToSML;
  AntennaControlsToSML;
  ReceiverControlsToSML;
  Result := moSML.Text;
end;

(* E n d   G e t t e r s  and    S e t t e r s *)
{$ENDREGION}
//
{$REGION ' SML To Controls '}

(* T i t l e   S M L   T o   C o n t r o l s *)
procedure TfrmFileManager.TitleSMLToControls;

begin
  with TitleBlockNode do
  begin
    // Version
    with Version do
    begin
      if HasAttribute('XML') then
        lblXMLVersion.Caption := SML
      else
        lblXMLVersion.Caption := 'unknown';

      if HasAttribute('SML') then
        lblSMLVersion.Caption := SML
      else
        lblSMLVersion.Caption := 'unknown';

      if HasAttribute('SETI') then
        lblSETIVersion.Caption := SETI
      else
        lblSETIVersion.Caption := 'unknown';

      edDateTimeUTC.Text := CreatedOn;

    end; // Version
    // Target
    with Target do
    begin
      edConstellationName.Text := ConstellationName;
      neConstID.ValueAsInt := ConstID;
      edTargetName.Text := TargetName;
      neTargetID.ValueAsInt := TargetID;
      neScanID.ValueAsInt := ScanID;
      neHitID.ValueAsInt := HitID;
      neSETIDataID.ValueAsInt := SETIDataID;
      cbFalsified.Checked := Falsified;
      if Target.HasAttribute('Note') then
        edTargetNote.Text := Note
      else
        edTargetNote.Text := '';
    end;

    // OperatingMode
    edOpMode.Text := OperatingMode;

    // Station_Location
    with Location do
    begin
      edGridSquare.Text := GridSquare;

    end;

    // SysOp
    with Personel do
    begin
      edSysOpName.Text := Personel.SysOp;

      // Observer_Name
      if (ChildNodes.FindNode('Observers') <> nil) then
        edObserverNames.Text := Personel.Observers
      else
        edObserverNames.Text := 'No Observers';
    end;
    // Files
    edSMLFileName.Text := MinimizeName(TitleBlockNode.Files.SML, Canvas, 170);
    edJPGFileName.Text := MinimizeName(TitleBlockNode.Files.JPG, Canvas, 170);
    edWAVFileName.Text := MinimizeName(TitleBlockNode.Files.WAV, Canvas, 170);
  end;
  { TitleBlock }
end;

(* A N T E N N A  S M L   T o   C O N T R O L S *)
procedure TfrmFileManager.AntennaSMLToControls;
begin
  with EquipmentSetupNode do
  begin

    with Antenna do
    begin

      if HasAttribute('Manufacture') then
        edAntennaManufacture.Text := Manufacture
      else
        edAntennaManufacture.Text := '';

      if HasAttribute('Model') then
        edAntennaModel.Text := Model
      else
        edAntennaModel.Text := '';
      if HasAttribute('Note') then
        edAntennaNote.Text := Note
      else
        edAntennaNote.Text := '';

      // Pointing_Coordinates
      with PointingCoordinates do
      begin
        // testSing:= Az;
        neAz.ValueAsSingle := Az;
        neEl.ValueAsSingle := El;

        if HasAttribute('SkyMapLock') then
          ledSkyMapLocked.Checked := SkyMapLock
        else
          ledSkyMapLocked.Checked := false;
        if HasAttribute('DEC') then
          neDEC.ValueAsSingle := DEC
        else
          neDEC.ValueAsSingle := 0.0;
        if HasAttribute('Ra') then
          neRa.ValueAsSingle := Ra
        else
          neRa.ValueAsSingle := 0.0;
      end;

      // Mount
      with Mount do
      begin
        if HasAttribute('Manufacture') then
          edMountManufacture.Text := Manufacture;
        if HasAttribute('Model') then
          edMountModel.Text := Model;

        if ChildNodes[0].LocalName = 'AzEl' then
        begin
          with AzEl do
          begin
            rgMountType.ItemIndex := 2;
            nsAzMax.value := MaximumAzimuth;
            nsAzMin.value := MinimumAzimuth;
            nsElMin.value := MaximumElevation;
            nsElMax.value := MinimumElevation;
          end; // AzEl
        end;

        if ChildNodes[0].LocalName = 'DriftScan' then
        begin
          with DriftScan do
          begin
            rgMountType.ItemIndex := 0;
            nsAzMax.value := Azimuth;
            nsAzMin.value := nsAzMax.ValueAsSingle;
            nsElMax.value := Elevation;
            nsElMin.value := nsElMax.ValueAsSingle;
          end; // DriftScan
        end;

        if (ChildNodes[0].LocalName = 'BirdBath') then
        begin
          rgMountType.ItemIndex := 1;
          nsAzMax.value := 0;
          nsAzMin.value := 0;
          nsElMax.value := 90;
          nsElMin.value := 90;
        end;

      end;

      // Shape
      with Shape do
      begin
        if HasAttribute('Note') then
          edShapeNote.Text := GetAttribute('Note')
        else
          edShapeNote.Text := '';

        nsShapeGain.Visible := false; // Make everything invisible first
        nsReflectorDiameter.Visible := false;
        nsFocalLength.Visible := false;
        nsReflectorDepth.Visible := false;
        nsHPBW.Visible := false;
        lblDia.Visible := false;
        lblFl.Visible := false;
        lblRD.Visible := false;
        lblShapeGain.Visible := false;
        lblHPBW.Visible := false;

        // Shape  Circular
        if ChildNodes[0].LocalName = 'Circular' then
        begin
          with Circular do
          begin
            rgKind.ItemIndex := 0;
            lblDia.Visible := true;
            lblFl.Visible := true;
            lblRD.Visible := true;
            nsReflectorDiameter.Visible := true;
            nsFocalLength.Visible := true;
            nsReflectorDepth.Visible := true;
            nsReflectorDiameter.value := ReflectorDiameter;
            nsFocalLength.value := FocalLength;
            nsReflectorDepth.value := ReflectorDepth;
          end;
        end; // Circular

        // Shape Other
        if ChildNodes[0].LocalName = 'Other' then
        begin
          with Other do
          begin
            rgKind.ItemIndex := 1;
            nsShapeGain.Visible := true;
            nsShapeGain.ValueAsSingle := ShapeGain;
            nsHPBW.Visible := true;
            nsHPBW.ValueAsSingle := HPBW;
          end;
        end; // Other
      end; // Shape
      // Horn
      with Horn do
      begin
        if HasAttribute('Shape') then
          edHornShape.Text := Shape
        else
          edHornShape.Text := '';

        if HasAttribute('Feed') then
          edHornFeed.Text := Feed
        else
          edHornFeed.Text := '';

        if HasAttribute('Diameter') then
          neHornDiameter.value := Diameter
        else
          neHornDiameter.value := 0.0;

        if HasAttribute('Note') then
          edHornNote.Text := Note
        else
          edHornNote.Text := '';
      end; // Horn
      // LNA
      if ChildNodes.FindNode('LNA') <> nil then
      begin
        with LNA do
        begin
          cbLNAInSystem.Checked := true;
          edLNAManufacture.Text := Manufacture;
          edLNAModel.Text := Model;
          nsLNAGain.value := Gain;
          nsLNANF.value := NoiseFigure; // Required
          edAntennaLNANote.Text := Note;
        end; // LNA
      end
      else
        cbLNAInSystem.Checked := false; //

      // L1
      if ChildNodes.FindNode('L1') <> nil then
      begin
        nsL1.value := L1.InsertionLoss;
        ckL1.Checked := true
      end
      else
        ckL1.Checked := false;

      // BPF
      if ChildNodes.FindNode('BPF') <> nil then
      begin
        neHiCutoff.ValueAsInt := BPF.HiCutOff; // Required
        neLoCutoff.ValueAsInt := BPF.LoCutoff; // Required
        nsBPFLoss.value := BPF.InsertionLoss;
        edBPFNote.Text := BPF.Note;
        ckBPFInSys.Checked := true;
      end
      else
        ckBPFInSys.Checked := false;
      // BPF

      // L2
      if ChildNodes.FindNode('L2') <> nil then
      begin
        nsL2.value := L2.InsertionLoss;
        ckL2.Checked := true;
      end
      else
        ckL2.Checked := false;
      // L2

      // RF Amp
      if (ChildNodes.FindNode('RFAmp') <> nil) then
      begin
        nsRFAmpGain.value := RFAmp.Gain;
        edRFAmpManufacture.Text := RFAmp.Manufacture;
        edRFAmpModel.Text := RFAmp.Model;
        edRFAmpNote.Text := RFAmp.Note;
        ckRFAmp.Checked := true;
      end
      else
        ckRFAmp.Checked := false;

      begin { L3 }
        if (ChildNodes.FindNode('L3') <> nil) then
        begin
          nsL3.value := L3.InsertionLoss;
          ckL3.Checked := true;
        end
        else
          ckL3.Checked := false;
      end; // L3
    end; // Antenna
  end; //
end; // AntennaToControls
(* R E C E I V E R   S M L   T O   C o n t r o l s *)

procedure TfrmFileManager.ReceiverSMLToControls;

begin
  with EquipmentSetupNode.Receiver do
  begin

    // edTimeKeepingDescription.Text := TimeKeeping.Description;
    edReceiverManufacture.Text := Manufacture;

    if HasAttribute('Model') then
      edReceiverModel.Text := Model
    else
      edReceiverModel.Text := '';

    if HasAttribute('Mode') then
      edReceiverMode.Text := Mode
    else
      edReceiverMode.Text := '';

    if HasAttribute('Bandwidth') then
      neReceiverBandwidth.ValueAsSingle := BandWidth
    else
      neReceiverBandwidth.ValueAsSingle := 0.0;

    if HasAttribute('Note') then
      edReceiverNote.Text := Note
    else
      edReceiverNote.Text := '';

    // tuning
    With Tuning do
    begin
      neFrequency.ValueAsInt := Frequency;
      neCenterFrequency.ValueAsInt := CenterFrequency;

      neChirp.value := Chirp;
      neBin.ValueAsInt := Bin;
      neAmplitude.value := Amplitude;
      if HasAttribute('Ambiant') then
        neAmbiant.value := Ambiant
      else
        neAmbiant.value := 0.0;
      if HasAttribute('Note') then
        edETNote.Text := Note
      else
        edETNote.Text := '';
    end;

    // Spectrum Analyzer
    With SpectrumAnalyzer do
    begin
      edVerticalRange.Text := VerticalRange;
      edSpectrumSize.Text := SpectrumSize;
      neIntegeration.ValueAsInt := Integration;
      neThreshold.ValueAsSingle := Threshold;
      neSegmentSize.ValueAsInt := SegmentSize;

      // if HasAttribute('LinesPerFrame') then
      neLinesPerFrame.ValueAsInt := LinesPerFrame;

    end;

    // A_TO_D
    with A_TO_D do
    begin
      // Manufacture
      if (HasAttribute('Manufacture')) then
        edA_To_DManfacture.Text := Manufacture
      else
        edA_To_DManfacture.Text := '';

      if (HasAttribute('Model')) then
        edA_To_DModel.Text := Model
      else
        edA_To_DModel.Text := '';

      nsA_To_DSamplingRate.value := SamplingRate;

      nsA_To_DEncodingBits.value := EncodingBits;

      If (Stereo = true) then
      begin
        rgChannels.ItemIndex := 1;
        edA_To_DContentLeft.Text := ContentLeft;
        edA_To_DContentRight.Text := ContentRight;
      end
      Else
      begin
        rgChannels.ItemIndex := 0;
        edA_To_DContentLeft.Text := ContentLeft;
        edA_To_DContentRight.Text := '';
      end;

      if (HasAttribute('CalibrationGain')) then
        nsCalibrationGain.value := CalibrationGain
      else
        nsCalibrationGain.value := 1.0;

      if (HasAttribute('CalibrationOffset')) then
        nsCalibrationOffset.value := CalibrationOffset
      else
        nsCalibrationOffset.value := 0.0;

      if HasAttribute('Note') then
        edA_To_DNote.Text := Note;
    end; // A_TO_D

    // WeightingWindow
    if (ChildNodes.FindNode('WeightingWindow') <> nil) then
    begin
      ckWeightingWindow.Checked := true;
      edWeightingWindowType.Text := WeightingWindow.Wintype;
      if HasAttribute('Note') then
        edWeightingWindowNote.Text := WeightingWindow.Note
      else
        edWeightingWindowNote.Text := '';
    end
    else
      ckWeightingWindow.Checked := false;

    // DSP
    if (ChildNodes.FindNode('DSP') <> nil) then
    begin { DSP }
      ckDSP.Checked := true;

      if (HasAttribute('Manufacture')) then
        edDSPManfacture.Text := DSP.Manufacture
      else
        edDSPManfacture.Text := '';

      if (HasAttribute('Model')) then
        edDSPModel.Text := DSP.Model
      else
        edDSPModel.Text := '';

      if (HasAttribute('Algorithm')) then
        edDSPAlgorithm.Text := DSP.Algorithm;

      if HasAttribute('Note') then
        edDSPNote.Text := DSP.Note
      else
        edDSPNote.Text := '';
    end
    else
      ckDSP.Checked := false; // DSP

    if (ChildNodes.FindNode('DigitalFilter') <> nil) then
    begin { DigitalFilter }
      ckDigitalFilter.Checked := true;
      if (DigitalFilter.FilterType = 'IIR') then
        rgDSPFilterType.ItemIndex := 0;
      if (DigitalFilter.FilterType = 'FIR') then
        rgDSPFilterType.ItemIndex := 1;
      neDSPFilterUpperSkirt.value := DigitalFilter.UpperSkirtFreq;
      neDSPFilterLowerSkirt.value := DigitalFilter.LowerSkirtFreq;

      if HasAttribute('Note') then
        edDSPFilterNote.Text := DigitalFilter.Note
      else
        edDSPFilterNote.Text := '';
    end
    else
      ckDigitalFilter.Checked := false;
    // DigitalFilter
    { TimeKeeping }

    edTimeKeepingDescription.Text := TimeKeeping.Description;

    if (ChildNodes.FindNode('AnalogFilter') <> nil) then
    begin
      ckAnalogFilter.Checked := true;
      if (Length(AnalogFilter.Description) > 0) then
        edAnalogFilter.Text := AnalogFilter.Description;
    end
    else
      ckAnalogFilter.Checked := false;
  end;
end;
// Receiver

{$ENDREGION}
//
{$REGION ' Controls to SML '}
(* T i t l e  C o n t r o l s   T o  S M L *)

procedure TfrmFileManager.TitleControlsToSML;
begin

  with TitleBlockNode do
  begin
    // Version
    with Version do
    begin
      Xml := lblXMLVersion.Caption;
      SML := lblSMLVersion.Caption;
      SETI := lblSETIVersion.Caption;
      CreatedOn := edDateTimeUTC.Text;
    end;

    // Target
    With Target do
    begin
      ConstellationName := edConstellationName.Text;
      ConstID := neConstID.ValueAsInt;
      TargetName := edTargetName.Text;
      TargetID := neTargetID.ValueAsInt;
      ScanID := neScanID.ValueAsInt;
      HitID := neHitID.ValueAsInt;
      SETIDataID := neSETIDataID.ValueAsInt;
      Falsified := cbFalsified.Checked;
      Note := edTargetNote.Text;
    end;

    // Created_On
    with CreatedOn do
    begin
      // Date := edDate.Text;
      // Time := edTime.Text;
    end;

    // OperatingMode
    OperatingMode := edOpMode.Text;

    // Location
    with Location do
    begin
      GridSquare := edGridSquare.Text;
      Latitude := neDecLat.value;
      Longitude := neDecLon.value;
    end;
    // Personel
    with Personel do
    begin
      SysOp := edSysOpName.Text;
      Observers := edObserverNames.Text;
    end;
    // Files
    Files.SML := FSMLFileName;
    Files.JPG := FJPGFileName;
    Files.WAV := FWAVFileName;
  end; // TitleBlock
end { TitleControlsToSML };

(* A N T E N N A  C o n t r o l s   T o   S M L *)
procedure TfrmFileManager.AntennaControlsToSML;
begin
  With EquipmentSetupNode.Antenna do
  begin
    if edAntennaManufacture.Text <> '' then
      Manufacture := edAntennaManufacture.Text;

    if edAntennaModel.Text <> '' then
      Model := edAntennaModel.Text;

    if edAntennaNote.Text <> '' then
      Note := edAntennaNote.Text;

    // Pointing Coordinates
    begin
      with PointingCoordinates do
      begin
        SkyMapLock := ledSkyMapLocked.Checked;
        Az := neAz.ValueAsSingle;
        El := neEl.ValueAsSingle;
        DEC := neDEC.ValueAsSingle;
        Ra := neRa.ValueAsSingle;
      end;
    end { Pointing Coordinates };

    // Mount
    With Mount do
    begin
      EquipmentSetupNode.Antenna.Mount.ChildNodes.Delete('DriftScan'); // Kill all Nodes
      EquipmentSetupNode.Antenna.Mount.ChildNodes.Delete('BirdBath');
      EquipmentSetupNode.Antenna.Mount.ChildNodes.Delete('AzEl');

      case rgMountType.ItemIndex of
        0: { DriftScan }
          begin
            AddChild('DriftScan');
            DriftScan.SetAttribute('Azimuth', nsAzMax.ValueAsSingle);
            DriftScan.SetAttribute('Elevation', nsElMax.ValueAsSingle);
          end;
        1: { BirdBath }
          begin
            AddChild('BirdBath');
          end;
        2: { AzEl }
          begin
            AddChild('AzEl');
            AzEl.SetAttribute('MaximumAzimuth', nsAzMax.ValueAsSingle);
            AzEl.SetAttribute('MinimumAzimuth', nsElMax.ValueAsSingle);
            AzEl.SetAttribute('MaximumElevation', nsAzMin.ValueAsSingle);
            AzEl.SetAttribute('MinimumElevation', nsElMin.ValueAsSingle);
          end;
      end; // Case
      Manufacture := edMountManufacture.Text;
      Model := edMountModel.Text;
    end; // Mount

    // Shape
    with Shape do
    begin
      EquipmentSetupNode.Antenna.Shape.ChildNodes.Delete('Circular');
      EquipmentSetupNode.Antenna.Shape.ChildNodes.Delete('Other');
      // Kill any Shape Node
      if (rgKind.ItemIndex = 0) then
      begin { Circular }
        AddChild('Circular');
        Circular.SetAttribute('ReflectorDiameter', nsReflectorDiameter.ValueAsSingle);
        Circular.SetAttribute('FocalLength', nsFocalLength.ValueAsSingle);
        Circular.SetAttribute('ReflectorDepth', nsReflectorDepth.ValueAsSingle);
      end { Circular }
      else
      begin { Other }
        AddChild('Other');
        Shape.Other.ShapeGain := nsShapeGain.ValueAsSingle;
        Shape.Other.HPBW := nsHPBW.value;
      end { Other };
      if edShapeNote.Text <> '' then
        Note := edShapeNote.Text;
    end;

    // Horn
    with Horn do
    begin
      Shape := edHornShape.Text;
      Feed := edHornFeed.Text;
      Diameter := neHornDiameter.value;
      Note := edHornNote.Text;
    end;
    // Horn

    // LNA
    with LNA do
    begin
      if cbLNAInSystem.Checked then
      begin // User wants LNA but does not exist
        if (LNA = nil) then
          AddChild('LNA') // Add the LNA
        else
        begin
          Manufacture := edLNAManufacture.Text;
          Model := edLNAModel.Text;
          Gain := nsLNAGain.ValueAsSingle;
          NoiseFigure := nsLNANF.ValueAsSingle;
          Note := edAntennaLNANote.Text;
        end;
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('LNA');
      // Remove the LNA
    end;

    // L1
    with L1 do
    begin
      if ckL1.Checked then
      begin
        if (L1 = nil) then
          AddChild('L1')
        else
          SetAttribute('InsertionLoss', FloatToStr(nsL1.ValueAsSingle));
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('L1');
    end;
    { L1 };

    // BPF
    with BPF do
    begin
      if (ckBPFInSys.Checked = true) then
      begin
        if BPF = nil then
          AddChild('BPF')
        else
        begin
          BPF.HiCutOff := neHiCutoff.ValueAsInt;
          BPF.LoCutoff := neLoCutoff.ValueAsInt;
          BPF.InsertionLoss := nsBPFLoss.value;

          BPF.Note := edBPFNote.Text;
        end;
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('BPF');
    end { BPF };

    // L2
    with L2 do
    begin
      if ckL2.Checked then
      begin
        if (L2 = nil) then
          AddChild('L2')
        else
          SetAttribute('InsertionLoss', FloatToStr(nsL2.ValueAsSingle));
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('L2');
    end; // L2

    // RFAmp
    with RFAmp do
    begin
      if (ckRFAmp.Checked) then
      begin
        if (RFAmp = nil) then
          AddChild('RFAmp')
        else
          RFAmp.Manufacture := edRFAmpManufacture.Text;
        RFAmp.Model := edRFAmpModel.Text;
        Note := edRFAmpNote.Text;
        Gain := nsRFAmpGain.ValueAsSingle;
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('RFAmp');
    end { RFAmp };

    // L3
    with L3 do
    begin
      if ckL3.Checked then
      begin
        if (L3 = nil) then
          AddChild('L3')
        else
          SetAttribute('InsertionLoss', FloatToStr(nsL3.ValueAsSingle));
      end
      else
        EquipmentSetupNode.Antenna.ChildNodes.Delete('L3');
    end; // L3
  end; // Antenna
end; // EquipmentSetup

(* R E C E I V E R  C O N T R O L S   T O   S M L *)
procedure TfrmFileManager.ReceiverControlsToSML;

begin // Update Receiver

  with EquipmentSetupNode.Receiver do
  begin { Receiver }
    Manufacture := edReceiverManufacture.Text;
    Model := edReceiverModel.Text;
    Mode := edReceiverMode.Text;
    BandWidth := neReceiverBandwidth.ValueAsInt;
    BandWidth := neReceiverBandwidth.ValueAsInt;
    Note := edReceiverNote.Text;

    // Tuning
    with Tuning do
    begin
      Frequency := neFrequency.ValueAsInt;
      CenterFrequency := neCenterFrequency.ValueAsInt;
      Chirp := neChirp.ValueAsSingle;
      Bin := neBin.ValueAsInt;
      Amplitude := neAmplitude.ValueAsSingle;
      Ambiant := neAmbiant.ValueAsSingle;
      Note := edETNote.Text;
    end;

    // Spectrum Analyzer
    with SpectrumAnalyzer do
    begin
      VerticalRange := edVerticalRange.Text;
      SpectrumSize := edSpectrumSize.Text;
      Integration := neIntegeration.ValueAsInt;
      Threshold := neThreshold.ValueAsSingle;
      SegmentSize := neSegmentSize.ValueAsInt;
      LinesPerFrame := neLinesPerFrame.ValueAsInt;
    end;

    // A_To_D
    With A_TO_D do
    begin
      Manufacture := edA_To_DManfacture.Text;
      Model := edA_To_DModel.Text;
      SamplingRate := nsA_To_DSamplingRate.ValueAsInt;
      EncodingBits := nsA_To_DEncodingBits.ValueAsInt;
      if (rgChannels.ItemIndex = 0) then
      begin { Mono }
        Stereo := false;
        ContentLeft := edA_To_DContentLeft.Text;
        ContentRight := '';
      end { Mono }
      else
      begin { Stereo }
        Stereo := true;
        ContentLeft := edA_To_DContentLeft.Text;
        ContentRight := edA_To_DContentRight.Text;
      end { Stereo };
      CalibrationGain := nsCalibrationGain.ValueAsSingle;
      CalibrationOffset := nsCalibrationOffset.ValueAsSingle;
      Note := edA_To_DNote.Text;
      CalibrationOffset := nsCalibrationOffset.value;
    end;

    // WeightingWindow
    with WeightingWindow do
    begin
      if (ckWeightingWindow.Checked) then
      begin
        if (WeightingWindow = Nil) then
          AddChild('WeightingWindow')
        else
        begin
          Wintype := edWeightingWindowType.Text;
          Note := edWeightingWindowNote.Text;
        end
      end
      else
        EquipmentSetupNode.Receiver.ChildNodes.Delete('WeightingWindow');
    end;

    // DSP
    with DSP do
    begin
      if (ckDSP.Checked) then
      begin
        if (DSP = nil) then
          AddChild('DSP')
        else
        begin
          Manufacture := edDSPManfacture.Text;
          Model := edDSPModel.Text;
          Algorithm := edDSPAlgorithm.Text;
          Note := edDSPNote.Text;
        end;
      end
      else
        EquipmentSetupNode.Receiver.ChildNodes.Delete('DSP');
    end; // DSP

    // DigitalFilter
    with DigitalFilter do
    begin
      if (ckDigitalFilter.Checked = true) then
      begin
        if (DigitalFilter = nil) then
          AddChild('DigitalFilter')
        else
        begin
          if (rgDSPFilterType.ItemIndex = 0) then { IIR }
            FilterType := 'IIR'
          else
            if (rgDSPFilterType.ItemIndex = 1) then { FIR }
              FilterType := 'FIR';
          LowerSkirtFreq := neDSPFilterLowerSkirt.ValueAsInt;
          UpperSkirtFreq := neDSPFilterUpperSkirt.ValueAsInt;
          Note := edDSPFilterNote.Text;
        end;
      end
      else
        EquipmentSetupNode.Receiver.ChildNodes.Delete('DigitalFilter');
    end; // DigitalFilter update

    // TimeKeeping
    TimeKeeping.Description := edTimeKeepingDescription.Text;

    // AnalogFilter
    if (ckAnalogFilter.Checked = true) then
      AnalogFilter.Description := edAnalogFilter.Text;

  end; // Receiver Update
end; // Receiver Controls To SML

{$ENDREGION}
//
{$REGION ' Instance Update '}
{$ENDREGION}
//
{$REGION ' Scan '}

function mmioFOURCC(A: Char; B: Char; C: Char; D: Char): DWORD;
begin
  Result := DWORD(A) or DWORD(B) shl 8 or DWORD(C) shl 16 or DWORD(D) shl 24;
end;

{$ENDREGION}
//
{$REGION 'Drag/Drop '}

(* Drag Drop *)
procedure TfrmFileManager.DropFileTarget1Drop(Sender: TObject; ShiftState: TShiftState; APoint: TPoint; var Effect: Integer);
var
  FileName: String;
  BaseName: String;
  Extension: String;
begin
  // The OnDrop event handler is called when the user drags files and drops them  onto your application.
  // FileName := DropFileTarget1.Files[0];
  Extension := ExtractSubString(FileName, 1, '.');
  BaseName := StripExtension(FileName);

  if UpperCase(Extension) = 'JPG' then
  begin
    OpenJPG(FileName);
    btnSaveJPG.Enabled := true;
    btnSaveAsJPG.Enabled := true;
    edJPGFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
  end;
  if UpperCase(Extension) = 'WAV' then
  begin
    OpenWAVfile(FileName);
    btnSaveWAV.Enabled := true;
    btnSaveAsWAV.Enabled := true;
    edWAVFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
  end;
  if UpperCase(Extension) = 'XML' then
    OpenSML(FileName);
  edSMLFileName.Text := MinimizeName(FileName, Canvas, 170);
  // Minimize it
end;

procedure TfrmFileManager.tsAntennaShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsAntenna);
end;

procedure TfrmFileManager.tsSETIStationShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsTitleBlock);
end;

procedure TfrmFileManager.tsReceiverShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsReceiver);
end;

procedure TfrmFileManager.tsBlockDiagramShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsBlockDiagram);
end;

procedure TfrmFileManager.tsWaterfallShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsWaterfall);
end;

procedure TfrmFileManager.tsXMLShow(Sender: TObject);
begin
  // DropFileTarget1.Register(tsXML);
end;
{$ENDREGION}
//
{$REGION 'Buttons '}

procedure TfrmFileManager.DisplayHint(Sender: TObject);
begin
  sbFileManager.Panels[sbHint].Text := GetLongHint(Application.Hint);
end;

procedure TfrmFileManager.docSMLAfterClose(Sender: TObject);
begin
  ledSMLOpen.Checked := false;
  gbWavFile.Enabled := false;
  gbJPGFile.Enabled := false;
  mnuWAVFile.Enabled := false;
  mnuJPGFile.Enabled := false;
end;

procedure TfrmFileManager.docSMLAfterNodeChange(const Node: IXMLNode; ChangeType: TNodeChange);

begin

  moSML.Clear;
  // -----------------------
  moSML.Lines.Text := XMLDoc.FormatXMLData(docSML.Xml.Text);
  // -----------------------

end;

procedure TfrmFileManager.docSMLAfterOpen(Sender: TObject);
begin
  sbFileManager.Panels[sbStatus].Text := 'Doc Now Open';
  gbWavFile.Enabled := true;
  gbWavFile.Color := clGradientActiveCaption;
  gbSML.Color := clGradientActiveCaption;
  mnuWAVFile.Enabled := true;
  btnWaveFileOpen.Enabled := true;
  btnSaveWAV.Enabled := false;
  btnSaveAsWAV.Enabled := false;

  gbJPGFile.Enabled := true;
  gbJPGFile.Color := clGradientActiveCaption;
  mnuJPGFile.Enabled := true;
  btnJPGFileOpen.Enabled := true;
  btnSaveJPG.Enabled := false;
  btnSaveAsJPG.Enabled := false;

  btnSMLSaveAs.Enabled := true;
  gbJPGFile.Enabled := true;
  ledSMLOpen.Checked := true;
end;

procedure TfrmFileManager.docSMLBeforeClose(Sender: TObject);
begin
  sbFileManager.Panels[sbStatus].Text := 'Doc about to close';
  gbWavFile.Color := clScrollBar;
  gbSML.Color := clScrollBar;
  mnuWAVFile.Enabled := false;
  mnuJPGFile.Enabled := false;
  ledSMLOpen.Checked := false;
end;

procedure TfrmFileManager.mnuFileExitItemClick(Sender: TObject);
begin
  Close
end;

(* C l o s e   F i l e *)
procedure TfrmFileManager.mnuAboutClick(Sender: TObject);
begin
  frmAbout.ShowVersion;
end;

procedure TfrmFileManager.mnuCloseFileClick(Sender: TObject);
begin
  moSML.Clear;
  if (docSML.Active = true) then
  begin
    docSML.Xml.Clear;
    // treeViewer.Items.Clear;
    moSML.Clear;
    FSMLFileName := sUntitled;
    docSML.Active := false;
  end;
end;

procedure TfrmFileManager.mnuDefaultSMLClick(Sender: TObject);
begin
  btnDefaultSMLClick(Self);
end;

procedure TfrmFileManager.FilePrintItemClick(Sender: TObject);
begin
  if PrintDialog.Execute then
    ShowMessage('This function not implemented yet.');
end;

(* Click Mount Type *)
procedure TfrmFileManager.rgMountTypeClick(Sender: TObject);
begin
  case rgMountType.ItemIndex of
    0:
      begin // For Drift Scan

      end;
    1:
      begin // For Birdbath

      end;
    2:
      begin // For AzEl

      end;
  end;
  if (docSML.Modified) then
    AntennaControlsToSML;
end;

procedure TfrmFileManager.mnuShowHintsClick(Sender: TObject);
begin
  mnuShowHints.Checked := not mnuShowHints.Checked;

  pcFileManager.ShowHint := mnuShowHints.Checked;
  if mnuShowHints.Checked then
    LblHints.Caption := 'Hints On'
  else
    LblHints.Caption := 'Hints Off'
end;

procedure TfrmFileManager.moSMLEnter(Sender: TObject);
begin
  moSML.Clear;

  moSML.Lines.Text := XMLDoc.FormatXMLData(docSML.Xml.Text);
end;

procedure TfrmFileManager.neFrequencyValueChanged(Sender: TObject);
begin
  ReceiverControlsToSML
end;

procedure TfrmFileManager.btnSaveCombinedClick(Sender: TObject);
begin
  ShowMessage('SaveCombined');
end;

procedure TfrmFileManager.ComboBox3KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = chr(VK_RETURN)) then
    beep;
end;

procedure TfrmFileManager.ComboBox1KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = chr(VK_RETURN)) then
    beep;
end;

procedure TfrmFileManager.FormActivate(Sender: TObject);
begin
  { Assign the application’s OnHint event handler at runtime }
  { because the Application is not available in the Object Inspector at design time }
  Application.OnHint := DisplayHint;

end;

(* =====      J P G   H a n d l i n g    ======= *)

Procedure TfrmFileManager.SaveJPG(FileName: String; msJPG: TmemoryStream);

(* JPG Save *)
var
  msSML: TStringStream;

begin

  gbJPGFile.Enabled := false;
  gbJPGFile.Color := clScrollBar;
  Application.ProcessMessages;

  SETI_Station := GetSETI_Station(docSML);
  TitleBlockNode := SETI_Station.TitleBlock;
  EquipmentSetupNode := SETI_Station.EquipmentSetup;

  TitleControlsToSML;
  AntennaControlsToSML;
  ReceiverControlsToSML;

  msSML := TStringStream.Create;
  msSML.writeString(moSML.Lines.Text);
  If FileExists(FileName) then
  begin
    sbFileManager.Panels[2].Text := 'File Exists.  ';
    AddCommentToStream(FileName, msJPG, msSML);
  end
  else
  begin
    sbFileManager.Panels[2].Text := 'File Does Not Exist so creating';
    edJPGFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
    AddCommentToStream(FileName, msJPG, msSML);
  end;
  gbJPGFile.Enabled := true;
  gbJPGFile.Color := clGradientActiveCaption;
  sbFileManager.Panels[sbEvent].Text := '... JPG save complete';

end;

(* O P E N   J P G *)
procedure TfrmFileManager.OpenJPG(FileName: String);
var
  comment: String;
  SaveResp: Integer;
begin
  msJPG := TmemoryStream.Create;
  try
    msJPG.LoadFromFile(FileName);
  except
    begin
      btnSaveAsJPG.Enabled := false;
      ShowMessage(ExtractFileName(FileName) + ' is invalid or not a recognized JPG format');
      ledJPGOpen.Checked := false;
      exit;
    end;
  end;
  edJPGFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
  JvImage1.LoadFromStream(msJPG);
  comment := ExtractComment(msJPG);
  if comment <> '' then
  begin
    SaveResp := messagedlg('File: ''' + MinimizeName(FileName, Canvas, 170) + ''' Contains SML ' + #13#10 + ' - Yes to Overwrite current SML from this file. ' +
      #13#10 + ' - No Don''t change current SML', mtCustom, [mbYes, mbNo, mbCancel], 0);
    case SaveResp of
      idYes:
        begin // Load SML From incomming file
          docSML.Xml.Clear;
          docSML.LoadFromXML(comment);

          moSML.Clear;
          moSML.Lines.AddStrings(docSML.Xml);

          SETI_Station := GetSETI_Station(docSML);
          TitleBlockNode := SETI_Station.TitleBlock;
          EquipmentSetupNode := SETI_Station.EquipmentSetup;

          TitleSMLToControls;
          AntennaSMLToControls;
          ReceiverSMLToControls;
          ledJPGOpen.Checked := true;

          btnSaveJPG.Enabled := true;
          btnSaveAsJPG.Enabled := true;
        end;

      idNo:
        begin
          // DeleteSML(FileName);
          ledJPGOpen.Checked := true;
          btnSaveJPG.Enabled := true;
          btnSaveAsJPG.Enabled := true;
        end;

      idCancel:
        begin
          edJPGFileName.Text := 'No JPG Selected'; // Minimize it
          msJPG.Clear;
          ledJPGOpen.Checked := false;
          btnSaveJPG.Enabled := false;
          btnSaveAsJPG.Enabled := false;
        end; { case }
    end;
  end
  else
  begin
    sbFileManager.Panels[sbEvent].Text := MinimizeName(FileName, Canvas, 170) + ' No SML';
    ledJPGOpen.Checked := true;
    btnSaveJPG.Enabled := true;
    btnSaveAsJPG.Enabled := true;
  end;
end;

procedure TfrmFileManager.btnClearLogClick(Sender: TObject);
begin
  moLog.Clear;
end;

procedure TfrmFileManager.btnDefaultSMLClick(Sender: TObject);
var
  buttonSelected: Integer;
begin
  buttonSelected := messagedlg('Default SML will overwrite any current. Continue?', mtCustom, [mbYes, mbCancel], 0);
  if buttonSelected = mrCancel then
    exit;
  if buttonSelected = mrYes then
    if LoadDefaultSML then // Load SML from the Resources
      sbFileManager.Panels[sbStatus].Text := 'SML is Active'
    else
      sbFileManager.Panels[sbStatus].Text := 'SML NOT Active';
end;

procedure TfrmFileManager.btnJPGFileOpenClick(Sender: TObject);
(* JPG Open *)
begin
  if dlgOpenJPG.Execute then
  begin
    FJPGFileName := dlgOpenJPG.FileName;
    OpenJPG(FJPGFileName);
  end;
end;

procedure TfrmFileManager.btnSaveJPGClick(Sender: TObject);
begin
  if dlgOpenJPG.FileName <> '' then
    SaveJPG(dlgOpenJPG.FileName, msJPG);
  edJPGFileName.Text := MinimizeName(dlgOpenJPG.FileName, Canvas, 170);

end;

(* J P G  S a v e  A s *)
procedure TfrmFileManager.btnSaveAsJPGClick(Sender: TObject);

begin
  if dlgSaveJPG.Execute then
  begin
    FJPGFileName := dlgSaveJPG.FileName;
    edJPGFileName.Text := MinimizeName(FJPGFileName, Canvas, 170);
    SaveJPG(FJPGFileName, msJPG);
  end
end;

(* =====     W A V   H a n d l i n g    ======= *)
(* O p e n  W A V  f i l e *)
Procedure TfrmFileManager.OpenWAVfile(FileName: string);
var
  SaveResp: Integer;

  SMLChunkIndex: Integer;
  FMTChunkIndex: Integer;
  DataChunkIndex: Integer;
begin
  ledWAVOpen.Checked := false;
  edWAVFileName.Text := MinimizeName(FileName, Canvas, 170);

  try
    WAVRiff := TRiff.Create;
    WAVRiff.LoadFromFile(FileName); // Load WAV file and create streams for each chunk
  except
    sbFileManager.Panels[sbEvent].Text := 'Error Loading file.';
    WAVRiff.Clear;
    exit;
  end;
  FMTChunkIndex := WAVRiff.IndexOf('fmt '); // Check file
  DataChunkIndex := WAVRiff.IndexOf('data');
  if ((FMTChunkIndex) OR (DataChunkIndex)) = -1 then
  begin
    sbFileManager.Panels[sbEvent].Text := 'Corrupt file: ' + MinimizeName(FileName, Canvas, 170);
    ShowMessage('This WAV File is corrupt...');
    WAVRiff.Clear;
    exit;
  end;

  SMLChunkIndex := WAVRiff.IndexOf('SML ');
  If (SMLChunkIndex <> -1) then // Check for SML
  begin
    SaveResp := messagedlg('File: ''' + MinimizeName(FileName, Canvas, 170) + ''' Contains SML ' + #13#10 + ' - Yes to Overwrite current SML from this file. ' +
      #13#10 + ' - No Don''t change current SML', mtCustom, [mbYes, mbNo, mbCancel], 0);
    case SaveResp of
      mrYes:
        begin // Load SML From incomming file
          docSML.LoadFromStream(WAVRiff.Chunk[WAVRiff.IndexOf('SML ')], xetUnknown);
          moSML.Clear;
          moSML.Lines.AddStrings(docSML.Xml);

          SETI_Station := GetSETI_Station(docSML);
          TitleBlockNode := SETI_Station.TitleBlock;
          EquipmentSetupNode := SETI_Station.EquipmentSetup;

          TitleSMLToControls;
          AntennaSMLToControls;
          ReceiverSMLToControls;
          ledWAVOpen.Checked := true;
          btnSaveWAV.Enabled := true;
          btnSaveAsWAV.Enabled := true;
          edWAVFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
        end;
      mrNo: // Keep current SML
        begin
          ledWAVOpen.Checked := true;
          btnSaveWAV.Enabled := true;
          btnSaveAsWAV.Enabled := true;
          exit;
        end;
      mrCancel:
        begin
          WAVRiff.Clear;
          ledWAVOpen.Checked := false;
          btnSaveWAV.Enabled := false;
          btnSaveAsWAV.Enabled := false;
        end
    end;
  end
  else
  begin
    sbFileManager.Panels[sbEvent].Text := MinimizeName(FileName, Canvas, 170) + ' No SML';
    ledWAVOpen.Checked := true;
    btnSaveWAV.Enabled := true;
    btnSaveAsWAV.Enabled := true;
  end;
end;

(* S a v e   W A V   F i l e *)
procedure TfrmFileManager.SaveWAV(FileName: string);
var
  SMLChunkIndex: Integer;
  SML: ANSIString;
begin
  sbFileManager.Panels[sbEvent].Text := 'Start Saving WAV file';
  gbWavFile.Enabled := false;
  gbWavFile.Color := clScrollBar;
  Application.ProcessMessages;

  SETI_Station := GetSETI_Station(docSML);
  TitleBlockNode := SETI_Station.TitleBlock;
  EquipmentSetupNode := SETI_Station.EquipmentSetup;

  TitleControlsToSML;
  AntennaControlsToSML;
  ReceiverControlsToSML;

  if Assigned(WAVRiff) then
  begin
    SML := moSML.Text;
    SMLChunkIndex := WAVRiff.IndexOf('SML ');
    if SMLChunkIndex <> -1 then
      WAVRiff.DeleteChunkByIndex(SMLChunkIndex);

    WAVRiff.AddChunk('SML ');
    SMLChunkIndex := WAVRiff.IndexOf('SML ');
    WAVRiff.Chunk[SMLChunkIndex].WriteBuffer(Pointer(SML)^, Length(SML));
    // ^   ---- the trick -------------------------------------------   ^

  end
  else
  begin
    ShowMessage('No WAVRiff...');
    gbWavFile.Color := clScrollBar;
    exit;
  end;
  WAVRiff.SaveToFile(FileName);

  gbWavFile.Enabled := true;
  gbWavFile.Color := clGradientActiveCaption;
  sbFileManager.Panels[sbEvent].Text := '... WAV save complete';
end;

procedure TfrmFileManager.btnSaveWAVClick(Sender: TObject);
begin
  if dlgOpenWAV.FileName <> '' then
    SaveWAV(dlgOpenWAV.FileName);
  edWAVFileName.Text := MinimizeName(dlgOpenWAV.FileName, Canvas, 170);
end;

(* b t n  S a v e  A s   W A V   F i l e *)
procedure TfrmFileManager.btnSaveAsWAVClick(Sender: TObject);

begin
  if dlgSaveWAV.Execute then
  begin
    FWAVFileName := dlgSaveWAV.FileName;
    edWAVFileName.Text := MinimizeName(FWAVFileName, Canvas, 170);
    SaveWAV(FWAVFileName);
  end
end;

(* b t n  W A V   F i l e   O p e n *)
procedure TfrmFileManager.btnWaveFileOpenClick(Sender: TObject);
begin
  if dlgOpenWAV.Execute then
  begin
    FWAVFileName := dlgOpenWAV.FileName;
    OpenWAVfile(FWAVFileName);
  end;
end;

(* =====     S M L   H a n d l i n g    ======= *)
procedure TfrmFileManager.SaveSML(FileName: string);
(* S a v e  S M L  T o   F i l e *)
begin
  if docSML.Active then
  begin
    gbSML.Color := clScrollBar;
    gbSML.Enabled := false;
    Application.ProcessMessages;
    TitleControlsToSML;
    AntennaControlsToSML;
    ReceiverControlsToSML;

    docSML.SaveToFile(FileName);
    edSMLFileName.Text := MinimizeName(FileName, Canvas, 170); // Minimize it
    gbSML.Enabled := true;
    gbSML.Color := clGradientActiveCaption;
  end
  else
    sbFileManager.Panels[sbEvent].Text := '... No SML saved.';
end;

procedure TfrmFileManager.btnOpenSMLFileClick(Sender: TObject);
(* SML Open *)
begin
  btnSMLSave.Enabled := true;
  mnuSaveSML.Enabled := true;
  if dlgOpenSML.Execute then
  begin
    FSMLFileName := dlgOpenSML.FileName; // FSMLSaveFileName: String;
    OpenSML(dlgOpenSML.FileName);
    btnSMLSave.Enabled := true;
    btnSMLSaveAs.Enabled := true;
  end;
end;

procedure TfrmFileManager.btnRefreshSMLClick(Sender: TObject);
begin
  if docSML.Active then
  begin
    TMSLogger.Info('Before TitleControlsToSML ');
    TitleControlsToSML;
    TMSLogger.Info('After TitleControlsToSML ');

    TMSLogger.Info('Before ReceiverControlsToSML; ');
    ReceiverControlsToSML;
    TMSLogger.Info('After ReceiverControlsToSML; ');

    TMSLogger.Info('Before  AntennaControlsToSML ; ');
    AntennaControlsToSML;
    TMSLogger.Info('After  AntennaControlsToSML; ');
  end;
end;

procedure TfrmFileManager.OpenSML(FileName: String);
(* O P E N   S M L *)
begin
  if FileName = '' then
  begin
    ShowMessage('File Manager SML File is blank. Select and restart SETI');
    exit;
  end;
  docSML.LoadFromFile(FileName);
  if docSML.Active then
    sbFileManager.Panels[sbStatus].Text := 'SML is Active'
  else
    sbFileManager.Panels[sbStatus].Text := 'SML NOT Active';

  SETI_Station := GetSETI_Station(docSML);
  TitleBlockNode := SETI_Station.TitleBlock;
  EquipmentSetupNode := SETI_Station.EquipmentSetup;

  TitleSMLToControls;
  AntennaSMLToControls;
  ReceiverSMLToControls;
  edSMLFileName.Text := MinimizeName(FileName, Canvas, 170);
  // Minimize it
  moSML.Clear;
  // -----------------------
  moSML.Lines.Text := XMLDoc.FormatXMLData(docSML.Xml.Text);
  // -----------------------

end;

procedure TfrmFileManager.btnSMLSaveClick(Sender: TObject);
begin

  If dlgOpenSML.FileName <> '' then
  begin
    sbFileManager.Panels[sbStatus].Text := '... SAVE working...';
    SaveSML(dlgOpenSML.FileName);
    //
    FSMLFileName := dlgSaveSML.FileName;
    sbFileManager.Panels[sbStatus].Text := 'Save Complete';

  end;
end;

procedure TfrmFileManager.btnStartLoggingClick(Sender: TObject);
begin
  TMSLogger.Active := Not TMSLogger.Active;
  if TMSLogger.Active then
  begin
    TMSLogger.LogSystemInformation;
    TMSLogger.Info('Start Logging');
    btnStartLogging.Caption := 'Logging ON';
  end
  else
  begin
    btnStartLogging.Caption := 'Logging OFF';
  end;
end;

procedure TfrmFileManager.btnSMLSaveAsClick(Sender: TObject);
begin
  btnSMLSave.Enabled := true;
  mnuSaveSML.Enabled := true;
  sbFileManager.Panels[sbStatus].Text := '... SaveAs working...';
  dlgSaveSML.FileName := '';
  if dlgSaveSML.Execute then
  begin
    // edDateTimeUTC.Text := getCurrentUTCDateTime; // SaveAs so update the SML date/time UTC
    edDateTimeUTC.Text := DateTimeToStr(getCurrentUTC); // SaveAs so update the SML date/time UTC
    SaveSML(dlgSaveSML.FileName);
    FSMLFileName := dlgSaveSML.FileName;
    sbFileManager.Panels[sbStatus].Text := 'SaveAs Complete';
  end;
end;

procedure TfrmFileManager.rgKindClick(Sender: TObject);
begin
  if (rgKind.ItemIndex = 0) then
  begin { Circular }
    nsReflectorDiameter.Visible := true;
    nsFocalLength.Visible := true;
    nsReflectorDepth.Visible := true;
    lblDia.Visible := true;
    lblFl.Visible := true;
    lblRD.Visible := true;
    nsShapeGain.Visible := false;
    nsHPBW.Visible := false;
    lblShapeGain.Visible := false;
    lblHPBW.Visible := false;
  end
  else
  begin { Other }
    nsReflectorDiameter.Visible := false;
    nsFocalLength.Visible := false;
    nsReflectorDepth.Visible := false;
    lblDia.Visible := false;
    lblFl.Visible := false;
    lblRD.Visible := false;
    nsShapeGain.Visible := true;
    nsHPBW.Visible := true;
    lblShapeGain.Visible := true;
    lblHPBW.Visible := true;
  end;

  AntennaControlsToSML;
end;

procedure TfrmFileManager.mnuSaveSMLClick(Sender: TObject);
begin
  If dlgOpenSML.FileName <> '' then
  begin
    SaveSML(dlgOpenSML.FileName);
    //
  end;
end;

{$ENDREGION}
//
{$REGION 'Close '}

{ F O R M   C L O S E }
procedure TfrmFileManager.FormClose(Sender: TObject; var Action: TCloseAction);

begin
  docSML.Active := false; // Without this an exception is generated
  SETINetReg := TRegistry.Create;
  try
    with SETINetReg do
    begin
      RootKey := HKEY_CURRENT_USER;
      OpenKey(SETINetFileManagerKey, true);
      // OpenKey will create the key if the second parameter is true and the key does not already exist
      WriteInteger('Left', Left);
      WriteInteger('Top', Top);
      writeString('SMLFile', FSMLFileName);
      CloseKey;
    end { with SETINetReg }
  finally
    SETINetReg.Free;
  end; // try..finally
  if Assigned(WAVRiff) then
    WAVRiff.Clear;
end;
{$ENDREGION}

procedure TfrmFileManager.Test1Click(Sender: TObject);
var
  ansiSML: ANSIString;
begin
  // ansiSML := GetSML;
  //
  TitleControlsToSML;
  AntennaControlsToSML;
  ReceiverControlsToSML;
  ansiSML := moSML.Text;

end;

end.
