2011-07-21 09:39:48 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
some helper functions/procedures
|
|
|
|
|
|
|
|
written by Sebastian Kraft
|
|
|
|
sebastian_kraft@gmx.de
|
|
|
|
|
|
|
|
This software is free under the GNU Public License
|
|
|
|
|
|
|
|
(c)2005-2008
|
|
|
|
}
|
|
|
|
|
|
|
|
Unit functions;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
Interface
|
|
|
|
|
|
|
|
Uses
|
2011-07-26 06:36:09 +00:00
|
|
|
Classes, SysUtils, math, config;
|
2011-07-21 09:39:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function crc32(path: String): longint;
|
|
|
|
|
|
|
|
Function crc32_math(path: String): int64;
|
|
|
|
|
|
|
|
Function DirectoryIsEmpty(Directory: String): Boolean;
|
|
|
|
|
|
|
|
Function EraseDirectory(Directory: String): Boolean; //delete directory and all subdirectories/files in it
|
|
|
|
|
|
|
|
Function UTF8toLatin1(utfstring: ansistring): ansistring;
|
|
|
|
|
|
|
|
Function Latin1toUTF8(latin1string: ansistring): ansistring;
|
|
|
|
|
|
|
|
Function rmZeroChar(s: ansistring): ansistring;
|
|
|
|
|
|
|
|
Function FileCopy(Const FromFile, ToFile: String): boolean;
|
|
|
|
|
|
|
|
Function FreeSpaceOnDAP: int64;
|
|
|
|
|
|
|
|
Function ByteToFmtString(bytes: int64; d1, d2: byte): string;
|
|
|
|
// converts i.e. 1024 to 1,0 KB
|
|
|
|
// d1, d2 sets amount of digits before and after ','
|
|
|
|
|
|
|
|
Function SecondsToFmtStr(seconds: longint): string;//converts integer to mm:ss time format
|
|
|
|
|
|
|
|
Function MSecondsToFmtStr(MSeconds: longint): string;
|
|
|
|
|
|
|
|
function MakeValidFilename(Filename: String): string;
|
|
|
|
|
|
|
|
procedure BubbleSort(var Items: TStrings);
|
|
|
|
|
|
|
|
function IntTodB(i, ref: longint):integer;
|
|
|
|
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function crc32(path: String): longint;
|
|
|
|
//creates an very, very basic checksum to identify files
|
|
|
|
|
|
|
|
Var fhandle: THandle;
|
|
|
|
buf: array [0..63] Of word;
|
|
|
|
z: byte;
|
|
|
|
i, eofile: longint;
|
|
|
|
l: longint;
|
|
|
|
Begin
|
|
|
|
{$Q-}
|
|
|
|
fhandle := sysutils.fileopen(path, fmOpenRead);
|
|
|
|
l := 0;
|
|
|
|
i := 0;
|
|
|
|
z := 0;
|
|
|
|
eofile := 0;
|
|
|
|
While (eofile<>-1) And (i<256) Do
|
|
|
|
Begin
|
|
|
|
eofile := FileRead(fhandle, buf, sizeof(buf));
|
|
|
|
If (eofile<>-1) Then For z:=0 To high(buf) Do begin
|
|
|
|
L := L+buf[z];
|
|
|
|
end;
|
|
|
|
inc(i);
|
|
|
|
End;
|
|
|
|
FileClose(fhandle);
|
|
|
|
result := l;
|
|
|
|
{$Q+}
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function crc32_math(path: String): int64;
|
|
|
|
//creates an very, very basic checksum to identify files
|
|
|
|
|
|
|
|
Var fhandle: THandle;
|
|
|
|
buf: array [0..63] Of int64;
|
|
|
|
z: byte;
|
|
|
|
i, eofile: longint;
|
|
|
|
l: int64;
|
|
|
|
Begin
|
|
|
|
fhandle := sysutils.fileopen(path, fmOpenRead);
|
|
|
|
l := 0;
|
|
|
|
i := 0;
|
|
|
|
z := 0;
|
|
|
|
eofile := 0;
|
|
|
|
While (eofile<>-1) And (i<256) Do
|
|
|
|
Begin
|
|
|
|
eofile := FileRead(fhandle, buf, high(buf));
|
|
|
|
l := l+sumInt(buf);
|
|
|
|
inc(i);
|
|
|
|
End;
|
|
|
|
FileClose(fhandle);
|
|
|
|
result := l;
|
|
|
|
|
|
|
|
End;
|
|
|
|
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function EraseDirectory(Directory: String): Boolean;
|
|
|
|
|
|
|
|
Var Srec: TSearchRec;
|
|
|
|
Begin
|
|
|
|
result := false;
|
|
|
|
If DirectoryExists(Directory)Then
|
|
|
|
Begin
|
|
|
|
Try
|
|
|
|
FindFirst(IncludeTrailingPathDelimiter(Directory) + '*', faAnyFile, Srec);
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
If (Srec.Name <> '.') And (Srec.Name <> '..') Then
|
|
|
|
DeleteFile(Directory+DirectorySeparator+Srec.Name);
|
|
|
|
End;
|
|
|
|
Until FindNext(Srec)<>0;
|
|
|
|
FindClose(Srec);
|
|
|
|
result := RemoveDir(Directory);
|
|
|
|
Except
|
|
|
|
result := false;
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function UTF8toLatin1(utfstring: ansistring): ansistring;
|
|
|
|
|
|
|
|
Var i: integer;
|
|
|
|
tmps: string;
|
|
|
|
utf16: boolean;
|
|
|
|
Begin
|
|
|
|
i := 0;
|
|
|
|
tmps := '';
|
|
|
|
utf16 := false;
|
|
|
|
|
|
|
|
If length(utfstring)>0 Then
|
|
|
|
Begin
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
inc(i);
|
|
|
|
Case byte(utfstring[i]) Of
|
|
|
|
$ff: If byte(utfstring[i+1])=$fe Then utf16 := true;
|
|
|
|
$c3:
|
|
|
|
Begin
|
|
|
|
Delete(utfstring, i, 1);
|
|
|
|
utfstring[i] := char(byte(utfstring[i])+64);
|
|
|
|
End;
|
|
|
|
$c2:
|
|
|
|
Begin
|
|
|
|
Delete(utfstring, i, 1);
|
|
|
|
dec(i);
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
Until (i>=length(utfstring)-1) Or utf16;
|
|
|
|
//if utf16 detected
|
|
|
|
If utf16 Then
|
|
|
|
Begin
|
|
|
|
i := i+2;
|
|
|
|
writeln('utf16');
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
inc(i);
|
|
|
|
If byte(utfstring[i])<>0 Then tmps := tmps+utfstring[i];
|
|
|
|
End;
|
|
|
|
Until (i>=length(utfstring));
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
If Not utf16 Then result := utfstring
|
|
|
|
Else Result := tmps;
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function rmZeroChar(s: ansistring): ansistring;
|
|
|
|
|
|
|
|
Var i: integer;
|
|
|
|
Begin
|
|
|
|
i := 0;
|
|
|
|
If s<>'' Then
|
|
|
|
Begin
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
inc(i);
|
|
|
|
If byte(s[i])=0 Then
|
|
|
|
Begin
|
|
|
|
Delete(s, i, 1);
|
|
|
|
dec(i);
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
Until i>=length(s)-1;
|
|
|
|
End;
|
|
|
|
Result := s;
|
|
|
|
End;
|
|
|
|
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function Latin1toUTF8(latin1string: ansistring): ansistring;
|
|
|
|
|
|
|
|
Var i: integer;
|
|
|
|
c: char;
|
|
|
|
tmps: string;
|
|
|
|
utf16: boolean;
|
|
|
|
Begin
|
|
|
|
i := 0;
|
|
|
|
utf16 := false;
|
|
|
|
If length(latin1string)>0 Then
|
|
|
|
Begin
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
inc(i);
|
|
|
|
Case byte(latin1string[i]) Of
|
|
|
|
$ff: If byte(latin1string[i+1])=$fe Then utf16 := true;
|
|
|
|
$00..$1f:
|
|
|
|
Begin
|
|
|
|
Delete(latin1string, i, 1);
|
|
|
|
dec(i);
|
|
|
|
End;
|
|
|
|
$c0..$fd:
|
|
|
|
Begin
|
|
|
|
//c0..ff ist der gesamte wertebereich!!
|
|
|
|
If (byte(latin1string[i])=$c3) And (byte(latin1string[i+1])<$C0) Then inc(i)
|
|
|
|
Else
|
|
|
|
Begin
|
|
|
|
latin1string[i] := char(byte(latin1string[i])-64);
|
|
|
|
insert(char($c3), latin1string, i);
|
|
|
|
inc(i);
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
{ $a1..$bf: begin
|
|
|
|
c:=latin1string[i];
|
|
|
|
insert(char($c2), latin1string, i);
|
|
|
|
// utfstring[i]:=char(byte(utfstring[i])+64);
|
|
|
|
inc(i);
|
|
|
|
end;}
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
Until (i>=length(latin1string)-1) Or utf16;
|
|
|
|
//if utf16 detected
|
|
|
|
If utf16 Then
|
|
|
|
Begin
|
|
|
|
|
|
|
|
//latin1string:=AnsiToUtf8(latin1string); may also work instead of following own utf16->utf8 routine
|
|
|
|
inc(i);
|
|
|
|
Repeat
|
|
|
|
Begin
|
|
|
|
inc(i);
|
|
|
|
If byte(latin1string[i])>$1f Then
|
|
|
|
If byte(latin1string[i])<$c0 Then
|
|
|
|
tmps := tmps+char(byte(latin1string[i]))
|
|
|
|
Else
|
|
|
|
tmps := tmps+char($c3)+char(byte(latin1string[i])-64);
|
|
|
|
End;
|
|
|
|
Until (i>=length(latin1string));
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
If Not utf16 Then result := latin1string
|
|
|
|
Else Result := tmps;
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
{ Function to copy a file FromFile -> ToFile , mainly used while upload to player device}
|
|
|
|
Function FileCopy(Const FromFile, ToFile: String): boolean;
|
|
|
|
|
|
|
|
Var
|
|
|
|
FromF, ToF: file;
|
|
|
|
NumRead, NumWritten: Word;
|
|
|
|
Buf: array[1..4096] Of byte;
|
|
|
|
Begin
|
|
|
|
Try
|
|
|
|
AssignFile(FromF, FromFile);
|
|
|
|
Reset(FromF, 1); { Record size = 1 }
|
|
|
|
AssignFile(ToF, ToFile); { Open output file }
|
|
|
|
Rewrite(ToF, 1); { Record size = 1 }
|
|
|
|
Repeat
|
|
|
|
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
|
|
|
|
BlockWrite(ToF, Buf, NumRead, NumWritten);
|
|
|
|
Until (NumRead = 0) Or (NumWritten <> NumRead);
|
|
|
|
CloseFile(FromF);
|
|
|
|
CloseFile(ToF);
|
|
|
|
result := true;
|
|
|
|
Except
|
|
|
|
result := false;
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function FreeSpaceOnDAP: int64;
|
|
|
|
|
|
|
|
Var tmps: string;
|
|
|
|
Begin
|
|
|
|
tmps := GetCurrentDir;
|
|
|
|
// get free memory on player, format string
|
|
|
|
SetCurrentDir(CactusConfig.DAPPath);
|
|
|
|
result := DiskFree(0);
|
|
|
|
writeln('------>');
|
|
|
|
writeln(DiskFree(0));
|
|
|
|
SetCurrentDir(tmps);
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function ByteToFmtString(bytes: int64; d1, d2: byte): string;
|
|
|
|
|
|
|
|
Var r: real;
|
|
|
|
count: byte;
|
|
|
|
comma, prefix, s1, s2: string;
|
|
|
|
subzero:boolean;
|
|
|
|
Begin
|
|
|
|
count := 0;
|
|
|
|
if bytes>=0 then subzero:=false else subzero:=true;
|
|
|
|
|
|
|
|
r := abs(bytes);
|
|
|
|
While (r>=power(10, d1)) Do
|
|
|
|
Begin
|
|
|
|
r := r / 1024;
|
|
|
|
inc(count);
|
|
|
|
End;
|
|
|
|
|
|
|
|
Case count Of
|
|
|
|
0: prefix := 'Byte';
|
|
|
|
1: prefix := 'KB';
|
|
|
|
2: prefix := 'MB';
|
|
|
|
3: prefix := 'GB';
|
|
|
|
4: prefix := 'TB';
|
|
|
|
5: prefix := 'PB';
|
|
|
|
End;
|
|
|
|
|
|
|
|
str(round (r*power(10, d2)) , s2);
|
|
|
|
|
|
|
|
If r >= 1 Then
|
|
|
|
Begin
|
|
|
|
s1 := copy(s2, 0, length(s2)-d2);
|
|
|
|
s2 := copy(s2, length(s2)-d2+1, d2);
|
|
|
|
End
|
|
|
|
Else s1 := '0';
|
|
|
|
|
|
|
|
If d2<>0 Then comma := ','
|
|
|
|
Else
|
|
|
|
Begin
|
|
|
|
comma := '';
|
|
|
|
s2 := '';
|
|
|
|
End;
|
|
|
|
if subzero=false then result := s1+comma+s2+' '+prefix else result := '- ' + s1+comma+s2+' '+prefix
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function SecondsToFmtStr(seconds: longint): string;
|
|
|
|
|
|
|
|
Var min, sec: longint;
|
|
|
|
s, s2: string;
|
|
|
|
Begin
|
|
|
|
if seconds>0 then begin
|
|
|
|
min := seconds Div 60;
|
|
|
|
sec := seconds Mod 60;
|
|
|
|
str(min, s);
|
|
|
|
str(sec, s2);
|
|
|
|
If min<10 Then s := '0'+s;
|
|
|
|
If sec<10 Then s2 := '0'+s2;
|
|
|
|
result := s+':'+s2;
|
|
|
|
end else Result:='00:00';
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function MSecondsToFmtStr(MSeconds: longint): string;
|
|
|
|
Begin
|
|
|
|
if MSeconds>1000 then result := SecondsToFmtStr(MSeconds Div 1000)
|
|
|
|
else Result:='00:00';
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
Function DirectoryIsEmpty(Directory: String): Boolean;
|
|
|
|
|
|
|
|
Var
|
|
|
|
SeR: TSearchRec;
|
|
|
|
i: Integer;
|
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
FindFirst(IncludeTrailingPathDelimiter(Directory) + '*', faAnyFile, SeR);
|
|
|
|
For i := 1 To 2 Do
|
|
|
|
If (SeR.Name = '.') Or (SeR.Name = '..') Then
|
|
|
|
Result := FindNext(SeR) <> 0;
|
|
|
|
FindClose(SeR);
|
|
|
|
End;
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
function MakeValidFilename(Filename: String): string;
|
|
|
|
var
|
|
|
|
I: integer;
|
|
|
|
{ for long file names } // FIXME taken from code for win32 - list correct/complete??
|
|
|
|
LongForbiddenChars : set of Char = ['<', '>', '|', '"', '\', '/', ':', '*', '?'];
|
|
|
|
begin
|
|
|
|
for I := 1 to Length(Filename) do
|
|
|
|
if (Filename[I] in LongForbiddenChars) then
|
|
|
|
Filename[I] := ' ';
|
|
|
|
result := Filename;
|
|
|
|
end;
|
|
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
procedure BubbleSort(var Items: TStrings);
|
|
|
|
var
|
|
|
|
done: boolean;
|
|
|
|
i, n: integer;
|
|
|
|
Dummy: string;
|
|
|
|
begin
|
|
|
|
n := Items.Count;
|
|
|
|
|
|
|
|
repeat
|
|
|
|
done := true;
|
|
|
|
for i := 0 to n - 2 do
|
|
|
|
if Items[i] > Items[i + 1] then
|
|
|
|
begin
|
|
|
|
Dummy := Items[i];
|
|
|
|
Items[i] := Items[i + 1];
|
|
|
|
Items[i + 1] := Dummy;
|
|
|
|
|
|
|
|
done := false;
|
|
|
|
end;
|
|
|
|
until done;
|
|
|
|
end;
|
|
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
function IntTodB(i, ref: longint): integer;
|
|
|
|
var dB: Real;
|
|
|
|
begin
|
|
|
|
if i=0 then db:=0.001 else dB:=i;
|
|
|
|
dB:= 20*log10(dB/ref);
|
|
|
|
result:=round(dB);
|
|
|
|
end;
|
|
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
|
|
End.
|