Files
lazarus-ccr/applications/cactusjukebox/source/functions.pas
jesusr 00a628b20a compile with 2.5.1 and lazarus trunk,
reading unicode tags and filenames, 
show/hide app window with single click tray icon, 
create album cover if not exists, 
several fixes when there is just one song in collection, 
artist tree icons, handling of track numbers in n[/m] format, 
show path of current file (in playlist and title list), 
log output was corrupt due the use of crt unit, 
etc.


git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1761 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2011-07-26 06:36:09 +00:00

468 lines
11 KiB
ObjectPascal

{
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
Classes, SysUtils, math, config;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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.