mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
169 lines
4.3 KiB
ObjectPascal
169 lines
4.3 KiB
ObjectPascal
unit DMRBindings;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, DynLibs;
|
|
|
|
const
|
|
DMR_ABI_VERSION = 1;
|
|
DMR_AMBE_BITS = 96;
|
|
DMR_PCM_SAMPLES = 160;
|
|
|
|
type
|
|
TDMRMbeResult = packed record
|
|
ErrorsC0: LongInt;
|
|
ErrorsTotal: LongInt;
|
|
end;
|
|
PDMRMbeResult = ^TDMRMbeResult;
|
|
|
|
function DMRLoad: Boolean;
|
|
procedure DMRUnload;
|
|
function DMRLoaded: Boolean;
|
|
function DMRLastError: string;
|
|
|
|
function DMRMbeCreate(UVQuality: Integer): Pointer;
|
|
procedure DMRMbeDestroy(Decoder: Pointer);
|
|
procedure DMRMbeReset(Decoder: Pointer);
|
|
function DMRMbeDecode(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
|
ResultInfo: PDMRMbeResult): Integer;
|
|
|
|
implementation
|
|
|
|
type
|
|
TAbiVersion = function: LongWord; cdecl;
|
|
TMbeCreate = function(UVQuality: LongInt): Pointer; cdecl;
|
|
TMbeDestroy = procedure(Decoder: Pointer); cdecl;
|
|
TMbeReset = procedure(Decoder: Pointer); cdecl;
|
|
TMbeDecode = function(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
|
ResultInfo: Pointer): LongInt; cdecl;
|
|
|
|
var
|
|
GLib: TLibHandle = dynlibs.NilHandle;
|
|
GLastError: string = '';
|
|
GAbiVersion: TAbiVersion = nil;
|
|
GMbeCreate: TMbeCreate = nil;
|
|
GMbeDestroy: TMbeDestroy = nil;
|
|
GMbeReset: TMbeReset = nil;
|
|
GMbeDecode: TMbeDecode = nil;
|
|
|
|
function Symbol(const Name: PChar): Pointer;
|
|
begin
|
|
Result := GetProcedureAddress(GLib, Name);
|
|
if Result = nil then
|
|
GLastError := 'Missing DMR symbol: ' + string(Name);
|
|
end;
|
|
|
|
function DMRLoad: Boolean;
|
|
const
|
|
{$IFDEF WINDOWS}
|
|
Names: array[0..0] of string = ('ewsdr_dmr.dll');
|
|
{$ELSE}
|
|
{$IFDEF DARWIN}
|
|
Names: array[0..0] of string = ('libewsdr_dmr.dylib');
|
|
{$ELSE}
|
|
Names: array[0..1] of string = ('libewsdr_dmr.so', 'libewsdr_dmr.so.1');
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
var
|
|
i: Integer;
|
|
LocalName, BuildName: string;
|
|
begin
|
|
if GLib <> dynlibs.NilHandle then Exit(True);
|
|
GLastError := '';
|
|
for i := Low(Names) to High(Names) do
|
|
begin
|
|
LocalName := ExtractFilePath(ParamStr(0)) + Names[i];
|
|
GLib := LoadLibrary(LocalName);
|
|
// Lazarus debug binaries live in bin/<target>/ while the documented
|
|
// optional adapter build lives in build/dmr. Make an in-tree build
|
|
// immediately usable without a system-wide cmake --install.
|
|
if GLib = dynlibs.NilHandle then
|
|
begin
|
|
BuildName := ExpandFileName(ExtractFilePath(ParamStr(0)) +
|
|
'../../build/dmr/' + Names[i]);
|
|
GLib := LoadLibrary(BuildName);
|
|
end;
|
|
if GLib = dynlibs.NilHandle then GLib := LoadLibrary(Names[i]);
|
|
if GLib <> dynlibs.NilHandle then Break;
|
|
end;
|
|
if GLib = dynlibs.NilHandle then
|
|
begin
|
|
GLastError := 'Optional EWSDR DMR library not found';
|
|
Exit(False);
|
|
end;
|
|
|
|
GAbiVersion := TAbiVersion(Symbol('ewsdr_dmr_abi_version'));
|
|
GMbeCreate := TMbeCreate(Symbol('ewsdr_dmr_mbe_create'));
|
|
GMbeDestroy := TMbeDestroy(Symbol('ewsdr_dmr_mbe_destroy'));
|
|
GMbeReset := TMbeReset(Symbol('ewsdr_dmr_mbe_reset'));
|
|
GMbeDecode := TMbeDecode(Symbol('ewsdr_dmr_mbe_decode'));
|
|
if not Assigned(GAbiVersion) or not Assigned(GMbeCreate) or
|
|
not Assigned(GMbeDestroy) or not Assigned(GMbeReset) or
|
|
not Assigned(GMbeDecode) then
|
|
begin
|
|
DMRUnload;
|
|
Exit(False);
|
|
end;
|
|
if GAbiVersion() <> DMR_ABI_VERSION then
|
|
begin
|
|
GLastError := Format('Unsupported EWSDR DMR ABI: %d', [GAbiVersion()]);
|
|
DMRUnload;
|
|
Exit(False);
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure DMRUnload;
|
|
begin
|
|
GAbiVersion := nil;
|
|
GMbeCreate := nil;
|
|
GMbeDestroy := nil;
|
|
GMbeReset := nil;
|
|
GMbeDecode := nil;
|
|
if GLib <> dynlibs.NilHandle then
|
|
begin
|
|
UnloadLibrary(GLib);
|
|
GLib := dynlibs.NilHandle;
|
|
end;
|
|
end;
|
|
|
|
function DMRLoaded: Boolean;
|
|
begin
|
|
Result := GLib <> dynlibs.NilHandle;
|
|
end;
|
|
|
|
function DMRLastError: string;
|
|
begin
|
|
Result := GLastError;
|
|
end;
|
|
|
|
function DMRMbeCreate(UVQuality: Integer): Pointer;
|
|
begin
|
|
if Assigned(GMbeCreate) then Result := GMbeCreate(UVQuality)
|
|
else Result := nil;
|
|
end;
|
|
|
|
procedure DMRMbeDestroy(Decoder: Pointer);
|
|
begin
|
|
if Assigned(GMbeDestroy) and (Decoder <> nil) then GMbeDestroy(Decoder);
|
|
end;
|
|
|
|
procedure DMRMbeReset(Decoder: Pointer);
|
|
begin
|
|
if Assigned(GMbeReset) and (Decoder <> nil) then GMbeReset(Decoder);
|
|
end;
|
|
|
|
function DMRMbeDecode(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
|
ResultInfo: PDMRMbeResult): Integer;
|
|
begin
|
|
if not Assigned(GMbeDecode) then Exit(-1);
|
|
Result := GMbeDecode(Decoder, Bits, PCM, ResultInfo);
|
|
end;
|
|
|
|
end.
|