diff --git a/CATSerial.pas b/CATSerial.pas
index c68549b..33f165b 100644
--- a/CATSerial.pas
+++ b/CATSerial.pas
@@ -116,8 +116,8 @@ begin
end;
function TCATSerialThread.TryOpenPort: Boolean;
-var
{$IFNDEF CAT_SERIAL_STUB}
+var
cfg: TCATSerialConfig;
h: TSerialHandle;
par: TParityType;
diff --git a/ChannelStore.pas b/ChannelStore.pas
index e161573..55b87f2 100644
--- a/ChannelStore.pas
+++ b/ChannelStore.pas
@@ -8,7 +8,7 @@ unit ChannelStore;
interface
uses
- SysUtils, Classes, Math, fpJSON, jsonparser, jsonscanner;
+ SysUtils, Classes, Math, fpJSON, jsonparser, jsonscanner, PlatformUtils;
const
CHANNELS_FILE = 'channels.json';
@@ -36,7 +36,7 @@ type
function JB(O: TJSONObject; const K: string; Def: Boolean): Boolean;
function JS(O: TJSONObject; const K: string; const Def: string): string;
public
- constructor Create(const AFilePath: string = CHANNELS_FILE);
+ constructor Create(const AFilePath: string = '');
procedure Load;
procedure Save;
function Count: Integer;
@@ -69,7 +69,10 @@ end;
constructor TChannelStore.Create(const AFilePath: string);
begin
inherited Create;
- FFilePath := AFilePath;
+ if AFilePath = '' then
+ FFilePath := GetAppCfgDir + CHANNELS_FILE
+ else
+ FFilePath := AFilePath;
SetLength(FChannels, 0);
end;
diff --git a/DeviceForm.pas b/DeviceForm.pas
index 96a03c8..d445273 100644
--- a/DeviceForm.pas
+++ b/DeviceForm.pas
@@ -7,10 +7,10 @@ interface
uses
Classes, SysUtils, FlatButton, FlatEdit, FlatListBox, AppTheme, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, IniFiles,
- BoardUtils;
+ BoardUtils, PlatformUtils;
const
- DEVICE_CFG_FILE = 'hpsdr_devices.ini';
+ DEVICE_CFG_NAME = 'hpsdr_devices.ini';
type
// Запись о сохранённом устройстве
@@ -355,9 +355,9 @@ var
Section: string;
begin
FSavedCount := 0;
- if not FileExists(DEVICE_CFG_FILE) then Exit;
+ if not FileExists(GetAppCfgDir + DEVICE_CFG_NAME) then Exit;
- Ini := TIniFile.Create(DEVICE_CFG_FILE);
+ Ini := TIniFile.Create(GetAppCfgDir + DEVICE_CFG_NAME);
try
N := Ini.ReadInteger('Devices', 'Count', 0);
SetLength(FSavedDevices, N);
@@ -381,7 +381,7 @@ var
I: Integer;
Section: string;
begin
- Ini := TIniFile.Create(DEVICE_CFG_FILE);
+ Ini := TIniFile.Create(GetAppCfgDir + DEVICE_CFG_NAME);
try
Ini.WriteInteger('Devices', 'Count', FSavedCount);
for I := 0 to FSavedCount - 1 do
diff --git a/PlatformUtils.pas b/PlatformUtils.pas
index 55d955d..70a326c 100644
--- a/PlatformUtils.pas
+++ b/PlatformUtils.pas
@@ -13,6 +13,11 @@ interface
function QtPlatformAllowsOpenGLControls: Boolean;
function HasOpenGLSpectrumSwitch: Boolean;
function CurrentScreenDPI: Integer;
+// Возвращает каталог для хранения конфигурации (с завершающим разделителем).
+// macOS: ~/Library/Application Support/ewsdr/
+// Linux: ~/.config/ewsdr/
+// Windows: каталог исполняемого файла
+function GetAppCfgDir: string;
implementation
@@ -61,4 +66,15 @@ begin
if Result <= 0 then Result := 96;
end;
+function GetAppCfgDir: string;
+begin
+{$IFDEF WINDOWS}
+ Result := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
+{$ELSE}
+ Result := IncludeTrailingPathDelimiter(GetAppConfigDir(False));
+ if not DirectoryExists(Result) then
+ ForceDirectories(Result);
+{$ENDIF}
+end;
+
end.
diff --git a/Settings.pas b/Settings.pas
index 33561ae..8437c07 100644
--- a/Settings.pas
+++ b/Settings.pas
@@ -6,7 +6,7 @@ unit Settings;
}
{$mode objfpc}{$H+}
interface
-uses SysUtils, Classes, Math, fpJSON, jsonparser, jsonscanner;
+uses SysUtils, Classes, Math, fpJSON, jsonparser, jsonscanner, PlatformUtils;
const
SETTINGS_FILE = 'hpsdr_settings.json';
@@ -268,7 +268,7 @@ type
procedure JW(O: TJSONObject; const K: string; V: Boolean); overload;
procedure JWS(O: TJSONObject; const K: string; const V: string);
public
- constructor Create(const FilePath: string = SETTINGS_FILE);
+ constructor Create(const FilePath: string = '');
destructor Destroy; override;
procedure Load;
procedure Save;
@@ -428,7 +428,10 @@ end;
constructor TSettingsManager.Create(const FilePath: string);
begin
inherited Create;
- FFilePath := FilePath;
+ if FilePath = '' then
+ FFilePath := GetAppCfgDir + SETTINGS_FILE
+ else
+ FFilePath := FilePath;
FRoot := TJSONObject.Create;
end;
diff --git a/WDSP.pas b/WDSP.pas
index e39185c..bf355cd 100644
--- a/WDSP.pas
+++ b/WDSP.pas
@@ -16,8 +16,9 @@ unit WDSP;
// Если wdsp.dll / libwdsp.so отсутствует — функции будут nil вместо краша.
// WDSPEngine.Open вернёт False и программа продолжит работу в демо-режиме.
-{$IFDEF FPC}
- {$WEAKEXTERNALSYMBOLS ON}
+
+{$IFDEF DARWIN}
+ {$linklib wdsp}
{$ENDIF}
interface
@@ -28,9 +29,13 @@ uses
const
{$IFDEF WINDOWS}
WDSP_LIB = 'wdsp.dll';
-{$ELSE}
+{$ENDIF}
+{$IFDEF LINUX}
WDSP_LIB = 'libwdsp.so';
{$ENDIF}
+{$IFDEF DARWIN}
+ WDSP_LIB = 'libwdsp.dylib';
+{$ENDIF}
// Analyzer detector modes
DETECTOR_MODE_PEAK = 0;
diff --git a/WDSPEngine.pas b/WDSPEngine.pas
index 546e45e..0fc15a9 100644
--- a/WDSPEngine.pas
+++ b/WDSPEngine.pas
@@ -990,12 +990,13 @@ begin
FLastError := '';
if FInitialized then Exit;
- if not Assigned(@OpenChannel) then
+ if not Assigned(@OpenChannel) or not Assigned(@XCreateAnalyzer) or
+ not Assigned(@SetAnalyzer) then
begin
FInitialized := False;
DllPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + WDSP_LIB;
if FileExists(DllPath) then
- FLastError := Format('Symbols from %s are not resolved. Check architecture (x64/x86) and dependencies.', [DllPath])
+ FLastError := Format('Symbols from %s are not resolved. Check architecture and library version (need WDSP with analyzer API).', [DllPath])
else
FLastError := Format('WDSP library not found: %s', [DllPath]);
Exit;
diff --git a/ewsdr.lpi b/ewsdr.lpi
index 1c19b71..7379264 100644
--- a/ewsdr.lpi
+++ b/ewsdr.lpi
@@ -44,6 +44,9 @@
+
+
+
@@ -283,5 +286,8 @@
+
+
+