Files
lazarus-ccr/applications/cactusjukebox/source/last_fm.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

256 lines
6.6 KiB
ObjectPascal

{
written by Sebastian Kraft
sebastian_kraft@gmx.de
This software is free under the GNU Public License
(c)2007
}
Unit last_fm;
{$mode objfpc}{$H+}
Interface
Uses
{$ifdef linux}
cthreads,
{$endif}
Classes, SysUtils, xmlread, dom, httpsend, debug, strutils;
Type
TCoverSize = (LargeImage, MediumImage, SmallImage, ExtralargeImage);
TAlbumInfoRecord = record
Artist, Album, WikiSummary, WikiContent : string;
CoverURL, CoverSavePath: string;
end;
THTTPCallbackProc = function : boolean of object;
{ TScanThread }
{ TNetworkThread }
TNetworkThread = Class(TThread)
Private
FHTTP: THTTPSend;
FErrorCode: string;
FUrl: string;
Protected
Procedure Execute;override;
Public
fStatus : byte;
URL: string;
Errorcode: string;
ReceiveProc: THTTPCallbackProc;
ReceiveData: ^TMemoryStream;
Constructor Create(Suspd : boolean);
End;
{ TScanThread }
{ TLastfmAPIObject }
TLastfmAPIObject = Class
constructor Create;
destructor destroy;
Private
{ private declarations }
// FAlbumCover: TFPImage;
FArtist, FAlbum: string;
FAPIKey: string;
FUrl, FURLPrefix: string;
XMLResult: TXMLDocument;
HTTPRecData: TMemoryStream;
HTTPThread: TNetworkThread;
FSavePath: ansistring;
FData_Ready, FImgNotFound: boolean;
FAlbumInfo: TAlbumInfoRecord;
function album_getInfosRCV: boolean;
function album_downloadCoverRCV: boolean;
procedure SendRequest(callback: THTTPCallbackProc);
Public
{ public declarations }
CoverSize: TCoverSize;
property data_ready: boolean read FData_Ready;
property AlbumInfo: TAlbumInfoRecord read FAlbumInfo;
procedure album_getInfos(artist, album:string);
procedure album_downloadCover(artist, album, savepath:string);
End;
Implementation
Uses functions;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
constructor TLastfmAPIObject.Create;
Begin
CoverSize:=MediumImage;
HTTPRecData := TMemoryStream.Create;
FData_Ready := false;
FImgNotFound := false;
FAPIKey := 'a364faa0dad3b90a2ebd2fccd2bd2173';
FURLPrefix:='http://ws.audioscrobbler.com/2.0/';
End;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
destructor TLastfmAPIObject.destroy;
Begin
HTTPRecData.Free;
End;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function TLastfmAPIObject.album_getInfosRCV:boolean;
Var node: TDOMNode;
ImgString: string;
done: boolean;
Begin
Try
XMLResult := TXMLDocument.Create;
ReadXMLFile(XMLResult, HTTPRecData);
node := XMLResult.DocumentElement.FindNode('album');
if Assigned(node) then begin
FAlbumInfo.Album:=node.FindNode('name').FirstChild.NodeValue;
FAlbumInfo.Artist:=node.FindNode('artist').FirstChild.NodeValue;
case CoverSize of
LargeImage: ImgString:='large';
MediumImage: ImgString:='medium';
ExtralargeImage: ImgString:='extralarge';
end;
node:=node.FindNode('image');
done:= false;
while ((node.Attributes.Item[0].NodeValue<>ImgString) and (done=false)) do begin
if node.NextSibling.NodeName='image' then
node:=node.NextSibling
else done:= true;
end;
if node.FirstChild<>nil then
FAlbumInfo.CoverURL:=node.FirstChild.NodeValue
else
FAlbumInfo.CoverURL:='';
// FAlbumInfo.CoverURL:=StringReplace(FAlbumInfo.CoverURL, #10, '', [rfReplaceAll]);
// FAlbumInfo.CoverURL:=StringReplace(FAlbumInfo.CoverURL, #13, '', [rfReplaceAll]);
// TODO: Clean up linebreaks in strings retrieved from XML files
end;
XMLResult.Free;
//fdata_ready := true;
finally
end;
end;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function TLastfmAPIObject.album_downloadCoverRCV: boolean;
var HTTPConnection: THTTPSend;
begin
album_getInfosRCV;
FData_Ready:=false;
If FAlbumInfo.CoverURL<>'' Then
Begin
If Not DirectoryExists(ExtractFileDir(FSavePath)) Then mkdir(ExtractFileDir(FSavePath));
HTTPConnection:=THTTPSend.Create;
DebugOutln('loading cover... ', 5);DebugOutLn(FAlbumInfo.CoverURL, 5);
HTTPConnection.HTTPMethod('GET', FAlbumInfo.CoverURL);
DebugOutLn('done', 5);
try
HTTPConnection.Document.SaveToFile(FAlbumInfo.CoverSavePath);
except
writeln('EXCEPTION writing cover art to disk');
end;
HTTPConnection.Free;
End else DebugOutLn('No cover found :(', 5);
fdata_ready:=true;
end;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
procedure TLastfmAPIObject.album_getInfos(artist, album: string);
begin
FAlbum:=album;
FArtist:=artist;
furl := Furlprefix + Format('?method=album.getinfo&api_key=%s&artist=%s&album=%s', [FAPIKey, FArtist, FAlbum]);
furl := AnsiReplaceStr(furl, ' ', '%20');
writeln(furl);
SendRequest(@album_getInfosRCV);
end;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
procedure TLastfmAPIObject.album_downloadCover(artist, album, savepath: string);
begin
FAlbum:=album;
FArtist:=artist;
furl := Furlprefix + Format('?method=album.getinfo&api_key=%s&artist=%s&album=%s', [FAPIKey, FArtist, FAlbum]);
furl := AnsiReplaceStr(furl, ' ', '%20');
FAlbumInfo.CoverSavePath:=savepath;
DebugOutLn('Sending album cover request to last.fm... ', 5);
DebugOutLn(furl, 5);
SendRequest(@album_downloadCoverRCV);
end;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Procedure TLastfmAPIObject.SendRequest(callback: THTTPCallbackProc);
Begin
fdata_ready := false;
HTTPThread := TNetworkThread.Create(true);
HTTPThread.URL := furl;
HTTPThread.ReceiveProc := callback;
HTTPThread.ReceiveData := @HTTPRecData;
HTTPThread.Resume;
End;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{ TNetworkThread }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Procedure TNetworkThread.Execute;
Begin
FHTTP := THTTPSend.Create;
FHTTP.HTTPMethod('GET', URL);
ReceiveData^ := FHTTP.Document;
ReceiveProc; // calls ReceiveProc when data is ready
FHTTP.Free;
End;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
constructor TNetworkThread.Create(Suspd: boolean);
Begin
inherited Create(suspd);
FreeOnTerminate := True;
fStatus := 255;
End;
End.