diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-08 18:43:29 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-08 18:43:29 +0000 |
commit | 864081102a5f252415f41950b3039a896b4ae9c5 (patch) | |
tree | c6b764651e9dd1f8f53b98eab05f16ba4a492a79 /plugins/Watrack/lastfm | |
parent | db5149b48346c417e18add5702a9dfe7f6e28dd0 (diff) |
Awkwars's plugins - welcome to our trunk
git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Watrack/lastfm')
-rw-r--r-- | plugins/Watrack/lastfm/i_const.inc | 17 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/i_last_api.inc | 599 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/i_last_dlg.inc | 120 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/i_last_opt.inc | 44 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/lastfm.ico | bin | 0 -> 2550 bytes | |||
-rw-r--r-- | plugins/Watrack/lastfm/lastfm.pas | 300 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/lastfm.rc | 38 | ||||
-rw-r--r-- | plugins/Watrack/lastfm/lastfm.res | bin | 0 -> 3720 bytes |
8 files changed, 1118 insertions, 0 deletions
diff --git a/plugins/Watrack/lastfm/i_const.inc b/plugins/Watrack/lastfm/i_const.inc new file mode 100644 index 0000000000..9a0365e506 --- /dev/null +++ b/plugins/Watrack/lastfm/i_const.inc @@ -0,0 +1,17 @@ +const
+ IDC_LOGIN = 1025;
+ IDC_PASS = 1026;
+ IDC_TRIES = 1027;
+
+ IDC_INFO_ARTIST = 1030;
+ IDC_INFO_TRACK = 1031;
+ IDC_INFO_ALBUM = 1032;
+ IDC_LANGUAGE = 1033;
+
+ IDC_DATA_PIC = 1040;
+ IDC_DATA_ARTIST = 1041;
+ IDC_DATA_ALBUM = 1042;
+ IDC_DATA_TRACK = 1043;
+ IDC_DATA_TAGS = 1044;
+ IDC_DATA_INFO = 1045;
+ IDC_ALT = 1046;
diff --git a/plugins/Watrack/lastfm/i_last_api.inc b/plugins/Watrack/lastfm/i_last_api.inc new file mode 100644 index 0000000000..73328366ba --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_api.inc @@ -0,0 +1,599 @@ +{}
+
+const
+ client_id = 'wat';//'wat'; 'tst'
+ client_ver = '1.0';
+ api_key = '51f5d25159da31b0814609c3a12900e2';
+
+const
+ defreq = 'http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=<client-id>&v=<client-ver>&u=<user>&t=<timestamp>&a=<auth>';
+
+function GetMD5Str(digest:TMD5Hash; buf:pAnsiChar):PAnsiChar;
+begin
+ buf[00]:=HexDigitChrLo[digest[00] shr 4]; buf[01]:=HexDigitChrLo[digest[00] and $0F];
+ buf[02]:=HexDigitChrLo[digest[01] shr 4]; buf[03]:=HexDigitChrLo[digest[01] and $0F];
+ buf[04]:=HexDigitChrLo[digest[02] shr 4]; buf[05]:=HexDigitChrLo[digest[02] and $0F];
+ buf[06]:=HexDigitChrLo[digest[03] shr 4]; buf[07]:=HexDigitChrLo[digest[03] and $0F];
+ buf[08]:=HexDigitChrLo[digest[04] shr 4]; buf[09]:=HexDigitChrLo[digest[04] and $0F];
+ buf[10]:=HexDigitChrLo[digest[05] shr 4]; buf[11]:=HexDigitChrLo[digest[05] and $0F];
+ buf[12]:=HexDigitChrLo[digest[06] shr 4]; buf[13]:=HexDigitChrLo[digest[06] and $0F];
+ buf[14]:=HexDigitChrLo[digest[07] shr 4]; buf[15]:=HexDigitChrLo[digest[07] and $0F];
+ buf[16]:=HexDigitChrLo[digest[08] shr 4]; buf[17]:=HexDigitChrLo[digest[08] and $0F];
+ buf[18]:=HexDigitChrLo[digest[09] shr 4]; buf[19]:=HexDigitChrLo[digest[09] and $0F];
+ buf[20]:=HexDigitChrLo[digest[10] shr 4]; buf[21]:=HexDigitChrLo[digest[10] and $0F];
+ buf[22]:=HexDigitChrLo[digest[11] shr 4]; buf[23]:=HexDigitChrLo[digest[11] and $0F];
+ buf[24]:=HexDigitChrLo[digest[12] shr 4]; buf[25]:=HexDigitChrLo[digest[12] and $0F];
+ buf[26]:=HexDigitChrLo[digest[13] shr 4]; buf[27]:=HexDigitChrLo[digest[13] and $0F];
+ buf[28]:=HexDigitChrLo[digest[14] shr 4]; buf[29]:=HexDigitChrLo[digest[14] and $0F];
+ buf[30]:=HexDigitChrLo[digest[15] shr 4]; buf[31]:=HexDigitChrLo[digest[15] and $0F];
+ buf[32]:=#0;
+ result:=@buf;
+end;
+
+function GetMD5(const data;datalen:integer;var digest:TMD5Hash):TMD5Hash;
+begin
+ FillChar(digest,16,0);
+
+ mir_md5_hash(pmir_md5_byte_t(data),datalen,digest);
+
+ result:=digest;
+end;
+
+function HandShake(login, password:PAnsiChar; notify:bool=false):bool;
+var
+ buf:array [0..32] of AnsiChar;
+ digest:TMD5Hash;
+ stat:mir_md5_state_t;
+ timestamp:array [0..31] of AnsiChar;
+ request:array [0..511] of AnsiChar;
+ tmp,res:pAnsiChar;
+begin
+ result:=false;
+ GetMD5Str(GetMD5(password,StrLen(password),digest),buf);
+ mir_md5_init(@stat);
+ mir_md5_append(@stat,@buf,32);
+ IntToStr(timestamp,GetCurrentTime);
+ mir_md5_append(@stat,@timestamp,StrLen(timestamp));
+ mir_md5_finish(@stat,digest);
+ GetMD5Str(digest,buf);
+ StrCopy(request,defreq);
+ StrReplace(request,'<client-id>' ,client_id);
+ StrReplace(request,'<client-ver>',client_ver);
+ StrReplace(request,'<user>' ,login);
+ StrReplace(request,'<timestamp>' ,timestamp);
+ StrReplace(request,'<auth>' ,buf);
+
+ res:=SendRequest(request,REQUEST_GET);
+ if (res<>nil) and (uint_ptr(res)>$0FFF) then
+ begin
+ if StrCmp(CharReplace(res,#10,#0),'OK')=0 then
+ begin
+ result:=true;
+ tmp:=StrEnd(res)+1; StrDup(session_id,tmp);
+ tmp:=StrEnd(tmp)+1; StrDup(np_url ,tmp);
+ tmp:=StrEnd(tmp)+1; StrDup(sub_url ,tmp);
+ end
+ else if notify then
+ begin
+ tmp:=StrCopyE(request,Translate('Last.fm error: '));
+ if StrCmp(res,'BANNED' )=0 then StrCopy(tmp,Translate('Client is banned'))
+ else if StrCmp(res,'BADAUTH' )=0 then StrCopy(tmp,Translate('Bad Auth. Check login and password'))
+ else if StrCmp(res,'BADTIME' )=0 then StrCopy(tmp,Translate('Bad TimeStamp'))
+ else if StrCmp(res,'FAILED',6)=0 then StrCopy(tmp,res+7);
+ CallService(MS_POPUP_SHOWMESSAGEW,wparam(@request),SM_ERROR);
+ end;
+ mFreeMem(res);
+ end;
+end;
+
+function encode(dst,src:pAnsiChar):PAnsiChar;
+begin
+ while src^<>#0 do
+ begin
+ if not (src^ in [' ','%','+','&','?',#128..#255]) then
+ dst^:=src^
+ else
+ begin
+ dst^:='%'; inc(dst);
+ dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst);
+ dst^:=HexDigitChr[ord(src^) and $0F];
+ end;
+ inc(src);
+ inc(dst);
+ end;
+ dst^:=#0;
+ result:=dst;
+end;
+
+function SendNowPlaying:integer;
+var
+ si:pSongInfoA;
+ buf :array [0..31 ] of AnsiChar;
+ args :array [0..1023] of AnsiChar;
+ res,pc:PAnsiChar;
+begin
+ result:=-1;
+ if session_id<>nil then
+ begin
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0));
+
+ pc:=@args;
+ pc:=StrCopyE(pc,'s='); pc:=StrCopyE(pc,session_id); //'?s='
+ pc:=StrCopyE(pc,'&a=');
+ if si^.artist=nil then pc:=StrCopyE(pc,'Unknown')
+ else pc:=encode(pc,si^.artist);
+ pc:=StrCopyE(pc,'&t=');
+ if si^.title =nil then pc:=StrCopyE(pc,'Unknown')
+ else pc:=encode(pc,si^.title);
+ pc:=StrCopyE(pc,'&l='); if si^.total>0 then pc:=StrCopyE(pc,IntToStr(buf,si^.total));
+ pc:=StrCopyE(pc,'&b='); pc:=encode(pc,si^.album);
+ pc:=StrCopyE(pc,'&n=');
+ if si^.track<>0 then
+ {pc:=}StrCopyE(pc,IntToStr(buf,si^.track));
+
+ res:=SendRequest(np_url,REQUEST_POST,args);
+ if (res<>nil) and (uint_ptr(res)>$0FFF) then
+ begin
+ if StrCmp(CharReplace(res,#10,#0),'OK')=0 then
+ result:=1
+ else if StrCmp(res,'BADSESSION')=0 then
+ result:=-1;
+ mFreeMem(res);
+ end;
+ end;
+end;
+
+function Scrobble:integer;
+var
+ si:pSongInfoA;
+ buf,timestamp:array [0..31] of AnsiChar;
+ args :array [0..1023] of AnsiChar;
+ res,pc:PAnsiChar;
+begin
+ result:=-1;
+ if session_id<>nil then
+ begin
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0));
+ IntToStr(timestamp,GetCurrentTime);
+
+ pc:=@args;
+ pc:=StrCopyE(pc,'s=' ); pc:=StrCopyE(pc,session_id);
+ pc:=StrCopyE(pc,'&a[0]=');
+ if si^.artist=nil then pc:=StrCopyE(pc,'Unknown')
+ else pc:=encode(pc,si^.artist);
+ pc:=StrCopyE(pc,'&t[0]=');
+ if si^.title =nil then pc:=StrCopyE(pc,'Unknown')
+ else pc:=encode(pc,si^.title);
+ pc:=StrCopyE(pc,'&i[0]='); pc:=StrCopyE(pc,timestamp);
+ pc:=StrCopyE(pc,'&r[0]=&m[0]=');
+ pc:=StrCopyE(pc,'&l[0]=');
+ if si^.total>0 then
+ begin
+ pc:=StrCopyE(pc,IntToStr(buf,si^.total));
+ pc:=StrCopyE(pc,'&o[0]=P');
+ end
+ else
+ begin
+ pc:=StrCopyE(pc,'&o[0]=R');
+ end;
+ pc:=StrCopyE(pc,'&b[0]='); pc:=encode(pc,si^.album);
+ pc:=StrCopyE(pc,'&n[0]=');
+ if si^.track<>0 then
+ {pc:=}StrCopyE(pc,IntToStr(buf,si^.track));
+
+ res:=SendRequest(sub_url,REQUEST_POST,args);
+ if (res<>nil) and (uint_ptr(res)>$0FFF) then
+ begin
+ if StrCmp(CharReplace(res,#10,#0),'OK')=0 then
+ result:=1
+ else if StrCmp(res,'BADSESSION')=0 then
+ begin
+ result:=-1;
+ end
+ else if StrCmp(res,'FAILED',6)=0 then
+ begin
+ StrCopy(StrCopyE(args,Translate('Last.fm error: ')),res+7);
+ CallService(MS_POPUP_SHOWMESSAGE,wparam(@args),SM_NOTIFY);
+ result:=0;
+ end;
+ mFreeMem(res);
+ end;
+ end;
+end;
+
+//----- Get Info service functions -----
+
+function FullEncode(dst,src:pAnsiChar):PAnsiChar;
+begin
+ while src^<>#0 do
+ begin
+ if src^ in ['A'..'Z','a'..'z','0'..'9'] then
+ dst^:=src^
+ else
+ begin
+ dst^:='%'; inc(dst);
+ dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst);
+ dst^:=HexDigitChr[ord(src^) and $0F];
+ end;
+ inc(src);
+ inc(dst);
+ end;
+ dst^:=#0;
+ result:=dst;
+end;
+
+var
+ xmlparser:XML_API_W;
+
+function FixInfo(info:pWideChar):pWideChar;
+var
+ pc,ppc:pWideChar;
+ cnt:cardinal;
+ need:boolean;
+begin
+ pc:=info;
+ cnt:=0;
+ need:=false;
+ while pc^<>#0 do
+ begin
+ if pc^=#$0D then
+ begin
+ inc(cnt);
+ inc(pc);
+ if pc^<>#$0A then
+ need:=true;
+ end
+ else
+ inc(pc);
+ end;
+ if need then
+ begin
+ mGetMem(result,(StrLenW(info)+1+cnt)*SizeOf(WideChar));
+ pc:=info;
+ ppc:=result;
+ while pc^<>#0 do
+ begin
+ ppc^:=pc^;
+ if pc^=#$0D then
+ begin
+ inc(ppc);
+ ppc^:=#$0A;
+ end;
+ inc(pc);
+ inc(ppc);
+ end;
+ ppc^:=#0;
+ end
+ else
+ StrDupW(result,info);
+end;
+
+function GetArtistInfo(var data:tLastFMInfo;lang:integer):int;
+var
+ si:pSongInfo;
+ res,pc:pAnsiChar;
+ request:array [0..1023] of AnsiChar;
+ root,actnode,node,nnode:HXML;
+ i:integer;
+ pcw,p,pp:PWideChar;
+ artist:pAnsiChar;
+begin
+ result:=0;
+ if data.artist=nil then
+ begin
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0));
+ pWideChar(artist):=si^.artist;
+ end
+ else
+ pWideChar(artist):=data.artist;
+ if artist=nil then
+ exit;
+ WideToUTF8(pWideChar(artist),artist);
+ pc:=FullEncode(StrCopyE(request,
+ 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key='+api_key+'&artist='),
+ artist);
+ mFreeMem(artist);
+ if lang<>0 then
+ StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang));
+ res:=SendRequest(request,REQUEST_GET);
+ if (res<>nil) and (uint_ptr(res)>$0FFF) then
+ begin
+ UTF8ToWide(res,pcw);
+ mFreeMem(res);
+ xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W);
+ CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser));
+ with xmlparser do
+ begin
+ i:=StrLenW(pcw)*SizeOf(WideChar);
+ root:=parseString(pcw,@i,nil);
+
+ actnode:=getChild(getChild(root,0),0); // "artist"
+
+ if data.artist=nil then
+ StrDupW(data.artist,getText(GetNthChild(actnode,'name',0)));
+
+ i:=0;
+ repeat
+ node:=GetNthChild(actnode,'image',i);
+ if node=0 then break;
+ if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then
+ begin
+ WideToUTF8(GetText(node),data.image);
+ break;
+ end;
+ inc(i);
+ until false;
+
+ // bio
+ p:=StrPosW(pcw,'<content><![CDATA[');
+ if p<>nil then
+ begin
+ inc(p,18);
+ pp:=StrPosW(p,']]');
+ if pp<> nil then pp^:=#0;
+ data.info:=FixInfo(p);
+ end;
+
+ // similar
+ i:=0;
+ pcw:=pWideChar(@request); pcw^:=#0;
+ node:=GetNthChild(actnode,'similar',0);
+ repeat
+ nnode:=GetNthChild(GetNthChild(node,'artist',i),'name',0);
+ if nnode=0 then break;
+ if pcw<>@request then
+ begin
+ pcw^:=','; inc(pcw);
+ pcw^:=' '; inc(pcw);
+ end;
+ pcw:=StrCopyEW(pcw,GetText(nnode));
+ inc(i);
+ until false;
+ pcw:=#0;
+ StrDupW(data.similar,pWideChar(@request));
+
+ // tags
+ i:=0;
+ pcw:=pWideChar(@request); pcw^:=#0;
+ node:=GetNthChild(actnode,'tags',0);
+ repeat
+ nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0);
+ if nnode=0 then break;
+ if pcw<>@request then
+ begin
+ pcw^:=','; inc(pcw);
+ pcw^:=' '; inc(pcw);
+ end;
+ pcw:=StrCopyEW(pcw,GetText(nnode));
+ inc(i);
+ until false;
+ pcw:=#0;
+ StrDupW(data.tags,pWideChar(@request));
+ DestroyNode(root);
+ mFreeMem(pcw);
+ end;
+ end;
+end;
+
+function GetAlbumInfo(var data:tLastFMInfo;lang:integer):int;
+var
+ si:pSongInfo;
+ res,pc:pAnsiChar;
+ request:array [0..1023] of AnsiChar;
+ root,actnode,node,nnode:HXML;
+ i:integer;
+ p,pp,pcw:PWideChar;
+ album,artist:pAnsiChar;
+begin
+ result:=0;
+ si:=nil;
+ if data.album=nil then
+ begin
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0));
+ pWideChar(album):=si^.album;
+ end
+ else
+ pWideChar(album):=data.album;
+ if album=nil then
+ exit;
+ WideToUTF8(pWideChar(album),album);
+ pc:=FullEncode(StrCopyE(request,
+ 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key='+api_key+'&album='),
+ album);
+ mFreeMem(album);
+ if data.artist=nil then
+ begin
+ if si=nil then
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0));
+ pWideChar(artist):=si^.artist;
+ end
+ else
+ pWideChar(artist):=data.artist;
+ if artist<>nil then
+ begin
+ WideToUTF8(pWideChar(artist),artist);
+ pc:=FullEncode(StrCopyE(pc,'&artist='),artist);
+ mFreeMem(artist);
+ end;
+
+ if lang<>0 then
+ StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang));
+
+ res:=SendRequest(request,REQUEST_GET);
+ if res<>nil then
+ begin
+ UTF8ToWide(res,pcw);
+ mFreeMem(res);
+ xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W);
+ CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser));
+ with xmlparser do
+ begin
+ i:=StrLenW(pcw)*SizeOf(WideChar);
+ root:=parseString(pcw,@i,nil);
+
+ actnode:=getChild(getChild(root,0),0); // "album"
+
+ if data.album=nil then
+ StrDupW(data.album,getText(GetNthChild(actnode,'name',0)));
+ StrDupW(data.release,getText(GetNthChild(actnode,'releasedate',0)));
+ if data.artist=nil then
+ StrDupW(data.artist,getText(GetNthChild(actnode,'artist',0)));
+
+ i:=0;
+ repeat
+ node:=GetNthChild(actnode,'image',i);
+ if node=0 then break;
+ if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then
+ begin
+ WideToUTF8(GetText(node),data.image);
+ break;
+ end;
+ inc(i);
+ until false;
+
+ p:=StrPosW(pcw,'<content><![CDATA[');
+ if p<>nil then
+ begin
+ inc(p,18);
+ pp:=StrPosW(p,']]');
+ if pp<> nil then pp^:=#0;
+ data.info:=FixInfo(p);
+ end;
+
+ // tags
+ i:=0;
+ pcw:=pWideChar(@request); pcw^:=#0;
+ node:=GetNthChild(actnode,'toptags',0);
+ repeat
+ nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0);
+ if nnode=0 then break;
+ if pcw<>@request then
+ begin
+ pcw^:=','; inc(pcw);
+ pcw^:=' '; inc(pcw);
+ end;
+ pcw:=StrCopyEW(pcw,GetText(nnode));
+ inc(i);
+ until false;
+ pcw:=#0;
+ StrDupW(data.tags,pWideChar(@request));
+
+ DestroyNode(root);
+ mFreeMem(pcw);
+ end;
+ end;
+end;
+
+function GetTrackInfo(var data:tLastFMInfo;lang:integer):int;
+var
+ si:pSongInfo;
+ res,pc:pAnsiChar;
+ request:array [0..1023] of AnsiChar;
+ root,actnode,node,anode:HXML;
+ i:integer;
+ p,pp,pcw:PWideChar;
+ title,artist:pAnsiChar;
+begin
+ result:=0;
+ si:=nil;
+ if data.album=nil then
+ begin
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0));
+ pWideChar(title):=si^.title;
+ end
+ else
+ pWideChar(title):=data.title;
+ if title=nil then
+ exit;
+ WideToUTF8(pWideChar(title),title);
+ pc:=FullEncode(StrCopyE(request,
+ 'http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key='+api_key+'&track='),
+ title);
+ mFreeMem(title);
+ if data.artist=nil then
+ begin
+ if si=nil then
+ si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0));
+ pWideChar(artist):=si^.artist;
+ end
+ else
+ pWideChar(artist):=data.artist;
+ if artist<>nil then
+ begin
+ WideToUTF8(pWideChar(artist),artist);
+ pc:=FullEncode(StrCopyE(pc,'&artist='),artist);
+ mFreeMem(artist);
+ end;
+
+ if lang<>0 then
+ StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang));
+
+ res:=SendRequest(request,REQUEST_GET);
+ if res<>nil then
+ begin
+ UTF8ToWide(res,pcw);
+ mFreeMem(res);
+ xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W);
+ CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser));
+ with xmlparser do
+ begin
+ i:=StrLenW(pcw)*SizeOf(WideChar);
+ root:=parseString(pcw,@i,nil);
+
+ actnode:=getChild(getChild(root,0),0); // "track"
+ if data.artist=nil then
+ StrDupW(data.artist,getText(GetNthChild(GetNthChild(actnode,'artist',0),'name',0)));
+
+ anode:=GetNthChild(actnode,'album',i);
+
+ if data.album=nil then
+ StrDupW(data.album,getText(GetNthChild(anode,'title',0)));
+
+ data.trknum:=StrToInt(getAttrValue(anode,'position'));
+ if data.title=nil then
+ StrDupW(data.title,getText(GetNthChild(actnode,'name',0)));
+
+ i:=0;
+ repeat
+ node:=GetNthChild(anode,'image',i);
+ if node=0 then break;
+ if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then
+ begin
+ WideToUTF8(GetText(node),data.image);
+ break;
+ end;
+ inc(i);
+ until false;
+
+ p:=StrPosW(pcw,'<content><![CDATA[');
+ if p<>nil then
+ begin
+ inc(p,18);
+ pp:=StrPosW(p,']]');
+ if pp<> nil then pp^:=#0;
+ data.info:=FixInfo(p);
+ end;
+
+ // tags
+ i:=0;
+ pcw:=pWideChar(@request); pcw^:=#0;
+ node:=GetNthChild(actnode,'toptags',0);
+ repeat
+ anode:=GetNthChild(GetNthChild(node,'tag',i),'name',0);
+ if anode=0 then break;
+ if pcw<>@request then
+ begin
+ pcw^:=','; inc(pcw);
+ pcw^:=' '; inc(pcw);
+ end;
+ pcw:=StrCopyEW(pcw,GetText(anode));
+ inc(i);
+ until false;
+ pcw:=#0;
+ StrDupW(data.tags,pWideChar(@request));
+
+ DestroyNode(root);
+ mFreeMem(pcw);
+ end;
+ end;
+end;
diff --git a/plugins/Watrack/lastfm/i_last_dlg.inc b/plugins/Watrack/lastfm/i_last_dlg.inc new file mode 100644 index 0000000000..b72545843e --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_dlg.inc @@ -0,0 +1,120 @@ +{}
+const
+ MaxLangs = 11;
+ LangArray:array [0..MaxLangs-1] of record
+ code:array [0..1] of AnsiChar;
+ name:pWideChar;
+ end= (
+ (code:#0#0 ; name: 'no language';),
+ (code:'zh' ; name: 'Chinese' ;),
+ (code:'en' ; name: 'English' ;),
+ (code:'fr' ; name: 'French' ;),
+ (code:'de' ; name: 'German' ;),
+ (code:'hi' ; name: 'Hindi' ;),
+ (code:'it' ; name: 'Italian' ;),
+ (code:'ja' ; name: 'Japanese' ;),
+ (code:'pt' ; name: 'Portuguese' ;),
+ (code:'ru' ; name: 'Russian' ;),
+ (code:'es' ; name: 'Spanish' ;)
+ );
+
+procedure ClearInfo(dlg:HWND);
+begin
+ SetDlgItemTextW(dlg,IDC_DATA_ARTIST,'');
+ SetDlgItemTextW(dlg,IDC_DATA_ALBUM ,'');
+ SetDlgItemTextW(dlg,IDC_DATA_TRACK ,'');
+ SetDlgItemTextW(dlg,IDC_DATA_TAGS ,'');
+ SetDlgItemTextW(dlg,IDC_DATA_INFO ,'');
+end;
+
+procedure ClearData(var data:tLastFMInfo);
+begin
+ mFreeMem(data.artist);
+ mFreeMem(data.album);
+ mFreeMem(data.title);
+ mFreeMem(data.tags);
+ mFreeMem(data.info);
+ mFreeMem(data.image);
+end;
+
+function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall;
+var
+ tmp:longbool;
+ bmp,wnd:HWND;
+ lang:integer;
+ data:tLastFMInfo;
+begin
+ result:=0;
+ case hMessage of
+ WM_INITDIALOG: begin
+ TranslateDialogDefault(Dialog);
+ SetDlgItemTextA(Dialog,IDC_LOGIN,lfm_login);
+ SetDlgItemTextA(Dialog,IDC_PASS ,lfm_password);
+ SetDlgItemInt (Dialog,IDC_TRIES,lfm_tries,false);
+ wnd:=GetDlgItem(Dialog,IDC_LANGUAGE);
+ for lang:=0 to MaxLangs-1 do
+ with LangArray[lang] do
+ CB_AddStrDataW(wnd,TranslateW(name),
+ ord(code[0])+(ord(code[1]) shl 8),lang);
+ CB_SelectData(wnd,lfm_lang);
+ end;
+
+ WM_COMMAND: begin
+ case wParam shr 16 of
+ BN_CLICKED: begin
+ ClearInfo(Dialog);
+ FillChar(data,SizeOf(data),0);
+ lfm_lang:=CB_GetData(GetDlgItem(Dialog,IDC_LANGUAGE));
+
+ if loword(wParam)=IDC_INFO_ARTIST then
+ begin
+ SetDlgItemTextW(Dialog,IDC_ALT,TranslateW('Similar artists'));
+ GetArtistInfo(data,lfm_lang);
+ SetDlgItemTextW(Dialog,IDC_DATA_ALBUM,data.similar);
+ end
+ else
+ begin
+ SetDlgItemTextW(Dialog,IDC_ALT,TranslateW('Album'));
+ if loword(wParam)=IDC_INFO_TRACK then
+ GetTrackInfo (data,lfm_lang)
+ else
+ GetAlbumInfo (data,lfm_lang);
+ SetDlgItemTextW(Dialog,IDC_DATA_ALBUM,data.album);
+ end;
+
+ SetDlgItemTextW(Dialog,IDC_DATA_ARTIST,data.artist);
+ SetDlgItemTextW(Dialog,IDC_DATA_TRACK ,data.title);
+ SetDlgItemTextW(Dialog,IDC_DATA_TAGS ,data.tags);
+ SetDlgItemTextW(Dialog,IDC_DATA_INFO ,data.info);
+ bmp:=LoadImageURL(data.image,64);
+ if bmp<>0 then
+ DeleteObject(SendDlgItemMessage(Dialog,IDC_DATA_PIC,STM_SETIMAGE,IMAGE_BITMAP,bmp));
+
+ ClearData(data);
+ end;
+ EN_CHANGE:
+ case loword(wParam) of
+ IDC_LOGIN,IDC_PASS,IDC_TRIES:
+ SendMessage(GetParent(Dialog),PSM_CHANGED,0,0);
+ end;
+ end;
+ end;
+
+ WM_NOTIFY: begin
+ if integer(PNMHdr(lParam)^.code)=PSN_APPLY then
+ begin
+ mFreeMem(lfm_login ); lfm_login :=GetDlgText(Dialog,IDC_LOGIN,true);
+ mFreeMem(lfm_password); lfm_password:=GetDlgText(Dialog,IDC_PASS ,true);
+ mFreeMem(session_id);
+ mFreeMem(np_url);
+ mFreeMem(sub_url);
+ lfm_tries:=GetDlgItemInt(Dialog,IDC_TRIES,tmp,false);
+ lfm_lang:=CB_GetData(GetDlgItem(Dialog,IDC_LANGUAGE));
+
+ SaveOpt;
+ end;
+ end;
+ else
+ {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam);
+ end;
+end;
diff --git a/plugins/Watrack/lastfm/i_last_opt.inc b/plugins/Watrack/lastfm/i_last_opt.inc new file mode 100644 index 0000000000..f18b590a87 --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_opt.inc @@ -0,0 +1,44 @@ +{}
+const
+ optLogin :pAnsiChar='lfm/login';
+ optPassword:pAnsiChar='lfm/password';
+ optTries :pAnsiChar='lfm/tries';
+ optScrobble:pAnsiChar='lfm/scrobble';
+ optLanguage:pAnsiChar='lfm/language';
+
+procedure SaveOpt;
+var
+ tmppass:array [0..255] of AnsiChar;
+begin
+ if lfm_password<>nil then
+ begin
+ StrCopy(tmppass,lfm_password);
+ CallService(MS_DB_CRYPT_ENCODESTRING,StrLen(tmppass)+1,lparam(@tmppass));
+ end;
+ DBWriteString(0,PluginShort,optPassword,tmppass);
+ DBWriteString(0,PluginShort,optLogin ,lfm_login);
+ DBWriteByte (0,PluginShort,optTries ,lfm_tries);
+ DBWriteByte (0,PluginShort,optScrobble,lfm_on and 1);
+ DBWriteWord (0,PluginShort,optLanguage,lfm_lang);
+end;
+
+procedure LoadOpt;
+begin
+ lfm_lang :=DBReadWord(0,PluginShort,optLanguage,0);
+ lfm_tries:=DBReadByte(0,PluginShort,optTries ,3);
+ lfm_on :=DBReadByte(0,PluginShort,optScrobble,0);
+ mFreeMem(lfm_login ); lfm_login :=DBReadString(0,PluginShort,optLogin);
+ mFreeMem(lfm_password); lfm_password:=DBReadString(0,PluginShort,optPassword);
+ if lfm_password<>nil then
+ CallService(MS_DB_CRYPT_DECODESTRING,StrLen(lfm_password)+1,lparam(lfm_password));
+ if (lfm_login=nil) or (lfm_password=nil) then
+ CallService(MS_POPUP_SHOWMESSAGEW,
+ wparam(TranslateW('Don''t forget to enter Login and Password to use Last.fm service')),
+ SM_WARNING);
+end;
+
+procedure FreeOpt;
+begin
+ mFreeMem(lfm_login);
+ mFreeMem(lfm_password);
+end;
diff --git a/plugins/Watrack/lastfm/lastfm.ico b/plugins/Watrack/lastfm/lastfm.ico Binary files differnew file mode 100644 index 0000000000..6ed701e2a5 --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.ico diff --git a/plugins/Watrack/lastfm/lastfm.pas b/plugins/Watrack/lastfm/lastfm.pas new file mode 100644 index 0000000000..7f2d90b0dd --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.pas @@ -0,0 +1,300 @@ +unit lastfm;
+{$include compilers.inc}
+interface
+{$Resource lastfm.res}
+implementation
+
+uses windows, messages, commctrl,
+ common,
+ m_api,dbsettings,wrapper,mirutils,
+ wat_api,global;
+
+const
+ opt_ModStatus:PAnsiChar = 'module/lastfm';
+const
+ IcoLastFM:pAnsiChar = 'WATrack_lasfm';
+var
+ lfm_tries:integer;
+ sic:THANDLE;
+ slastinf:THANDLE;
+ slast:THANDLE;
+const
+ lfm_lang :integer=0;
+ lfm_on :integer=0;
+ hMenuLast :HMENU = 0;
+ lfm_login :pAnsiChar=nil;
+ lfm_password:pAnsiChar=nil;
+ session_id :pAnsiChar=nil;
+ np_url :pAnsiChar=nil;
+ sub_url :pAnsiChar=nil;
+
+function GetModStatus:integer;
+begin
+ result:=DBReadByte(0,PluginShort,opt_ModStatus,1);
+end;
+
+procedure SetModStatus(stat:integer);
+begin
+ DBWriteByte(0,PluginShort,opt_ModStatus,stat);
+end;
+
+{$i i_const.inc}
+{$i i_last_opt.inc}
+{$i i_last_api.inc}
+
+procedure ThScrobble(param:LPARAM); cdecl;
+var
+ count:integer;
+ npisok:bool;
+begin
+ count:=lfm_tries;
+ npisok:=false;
+ while count>0 do
+ begin
+ if not npisok then
+ npisok:=SendNowPlaying>=0;
+ if Scrobble>=0 then break;
+ HandShake(lfm_login,lfm_password, count=1); // just last time
+ dec(count);
+ end;
+ if count=0 then ;
+end;
+
+const
+ hTimer:THANDLE=0;
+
+procedure TimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall;
+begin
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+
+ if (lfm_login <>nil) and (lfm_login^ <>#0) and
+ (lfm_password<>nil) and (lfm_password^<>#0) then
+ CloseHandle(mir_forkthread(@ThScrobble,nil));
+end;
+
+function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ flag:integer;
+ mi:TCListMenuItem;
+begin
+ result:=0;
+ case wParam of
+ WAT_EVENT_NEWTRACK: begin
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+ if lfm_on=0 then
+ hTimer:=SetTimer(0,0,30000,@TimerProc)
+ end;
+
+ WAT_EVENT_PLUGINSTATUS: begin
+ case lParam of
+ dsEnabled: begin
+ lfm_on:=lfm_on and not 2;
+ flag:=0;
+ end;
+ dsPermanent: begin
+ lfm_on:=lfm_on or 2;
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+ flag:=CMIF_GRAYED;
+ end;
+ else // like 1
+ exit
+ end;
+ FillChar(mi,sizeof(mi),0);
+ mi.cbSize:=sizeof(mi);
+ mi.flags :=CMIM_FLAGS+flag;
+ CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi));
+ end;
+
+ WAT_EVENT_PLAYERSTATUS: begin
+ case Integer(loword(lParam)) of
+ WAT_PLS_NOMUSIC,WAT_PLS_NOTFOUND: begin
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+ end;
+ end;
+ end;
+ end;
+end;
+
+{$i i_last_dlg.inc}
+
+function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ mi:TCListMenuItem;
+begin
+ result:=0;
+ FillChar(mi,SizeOf(mi),0);
+ mi.cbSize:=sizeof(mi);
+ mi.flags :=CMIM_ICON;
+ mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoLastFM));
+ CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi));
+end;
+
+function SrvLastFMInfo(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ data:tLastFMInfo;
+begin
+ case wParam of
+ 0: result:=GetArtistInfo(data,lParam);
+ 1: result:=GetAlbumInfo (data,lParam);
+ 2: result:=GetTrackInfo (data,lParam);
+ else
+ result:=0;
+ end;
+end;
+
+function SrvLastFM(wParam:WPARAM;lParam:LPARAM):int;cdecl;
+var
+ mi:TCListMenuItem;
+begin
+ FillChar(mi,sizeof(mi),0);
+ mi.cbSize:=sizeof(mi);
+ mi.flags :=CMIM_NAME;
+ if odd(lfm_on) then
+ begin
+ mi.szName.a:='Disable scrobbling';
+ lfm_on:=lfm_on and not 1;
+ end
+ else
+ begin
+ mi.szName.a:='Enable scrobbling';
+ lfm_on:=lfm_on or 1;
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+ end;
+ CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi));
+ result:=ord(not odd(lfm_on));
+end;
+
+procedure CreateMenus;
+var
+ mi:TCListMenuItem;
+ sid:TSKINICONDESC;
+begin
+ FillChar(sid,SizeOf(TSKINICONDESC),0);
+ sid.cbSize:=SizeOf(TSKINICONDESC);
+ sid.cx:=16;
+ sid.cy:=16;
+ sid.szSection.a:='WATrack';
+
+ sid.hDefaultIcon :=LoadImage(hInstance,'IDI_LAST',IMAGE_ICON,16,16,0);
+ sid.pszName :=IcoLastFM;
+ sid.szDescription.a:='LastFM';
+ Skin_AddIcon(@sid);
+ DestroyIcon(sid.hDefaultIcon);
+
+ FillChar(mi, sizeof(mi), 0);
+ mi.cbSize :=sizeof(mi);
+ mi.szPopupName.a:=PluginShort;
+
+ mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoLastFM));
+ mi.szName.a :='Disable scrobbling';
+ mi.pszService :=MS_WAT_LASTFM;
+ mi.popupPosition:=500050000;
+ hMenuLast:=Menu_AddMainMenuItem(@mi);
+end;
+
+// ------------ base interface functions -------------
+
+function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer;
+begin
+ tmpl:='LASTFM';
+ proc:=@DlgProcOptions;
+ name:='LastFM';
+ result:=0;
+end;
+
+var
+ plStatusHook:THANDLE;
+
+function InitProc(aGetStatus:boolean=false):integer;
+begin
+ slastinf:=CreateServiceFunction(MS_WAT_LASTFMINFO,@SrvLastFMInfo);
+ if aGetStatus then
+ begin
+ if GetModStatus=0 then
+ begin
+ result:=0;
+ exit;
+ end;
+ end
+ else
+ begin
+ SetModStatus(1);
+ lfm_on:=lfm_on and not 4;
+ end;
+ result:=1;
+
+ LoadOpt;
+
+ slast:=CreateServiceFunction(MS_WAT_LASTFM,@SrvLastFM);
+ if hMenuLast=0 then
+ CreateMenus;
+ sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged);
+ if (lfm_on and 4)=0 then
+ plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus);
+end;
+
+procedure DeInitProc(aSetDisable:boolean);
+begin
+ if aSetDisable then
+ SetModStatus(0)
+ else
+ DestroyServiceFunction(slastinf);
+
+ CallService(MS_CLIST_REMOVEMAINMENUITEM,hMenuLast,0);
+ hMenuLast:=0;
+ DestroyServiceFunction(slast);
+ UnhookEvent(plStatusHook);
+ UnhookEvent(sic);
+
+ if hTimer<>0 then
+ begin
+ KillTimer(0,hTimer);
+ hTimer:=0;
+ end;
+
+ FreeOpt;
+
+ mFreeMem(session_id);
+ mFreeMem(np_url);
+ mFreeMem(sub_url);
+
+ lfm_on:=lfm_on or 4;
+end;
+
+var
+ last:twModule;
+
+procedure Init;
+begin
+ last.Next :=ModuleLink;
+ last.Init :=@InitProc;
+ last.DeInit :=@DeInitProc;
+ last.AddOption:=@AddOptionsPage;
+ last.ModuleName:='Last.FM';
+ ModuleLink :=@last;
+
+end;
+
+begin
+ Init;
+end.
diff --git a/plugins/Watrack/lastfm/lastfm.rc b/plugins/Watrack/lastfm/lastfm.rc new file mode 100644 index 0000000000..320eebe8cc --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.rc @@ -0,0 +1,38 @@ +#include "i_const.inc"
+
+LANGUAGE 0,0
+
+LASTFM DIALOGEX 0, 0, 304, 226, 0
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0
+{
+ LTEXT "Login" , -1, 108, 2, 70, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_LOGIN , 4, 4, 100, 12,
+ LTEXT "Password", -1, 108, 18, 70, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_PASS , 4, 20, 100, 12, ES_PASSWORD
+ LTEXT "Attempts", -1, 40, 34, 64, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_TRIES , 4, 36, 32, 12, ES_RIGHT | ES_NUMBER
+
+ LTEXT "Content language", -1, 80, 52, 76, 16, SS_CENTERIMAGE
+ COMBOBOX IDC_LANGUAGE, 160, 53, 74, 96, CBS_DROPDOWNLIST | WS_VSCROLL
+
+ PUSHBUTTON "Get Artist Info", IDC_INFO_ARTIST, 4, 166, 72, 16
+ PUSHBUTTON "Get Track Info" , IDC_INFO_TRACK , 4, 186, 72, 16
+ PUSHBUTTON "Get Album Info" , IDC_INFO_ALBUM , 4, 206, 72, 16
+
+ CONTROL "", IDC_DATA_PIC, "STATIC", SS_BITMAP | WS_BORDER, 236, 2, 64, 64
+ RTEXT "Artist", -1 , 0, 70, 76, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_DATA_ARTIST, 80, 71, 220, 14, ES_READONLY | ES_AUTOHSCROLL
+ RTEXT "Album",IDC_ALT, 0, 86, 76, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_DATA_ALBUM , 80, 87, 220, 14, ES_READONLY | ES_AUTOHSCROLL
+ RTEXT "Track" , -1 , 0, 102, 76, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_DATA_TRACK , 80, 103, 220, 14, ES_READONLY | ES_AUTOHSCROLL
+ RTEXT "Tags" , -1 , 0, 118, 76, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_DATA_TAGS , 80, 119, 220, 14, ES_READONLY | ES_AUTOHSCROLL
+ RTEXT "Info" , -1 , 0, 134, 76, 16, SS_CENTERIMAGE
+ EDITTEXT IDC_DATA_INFO , 80, 135, 220, 88,
+ ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL
+}
+
+IDI_LAST ICON "lastfm.ico"
diff --git a/plugins/Watrack/lastfm/lastfm.res b/plugins/Watrack/lastfm/lastfm.res Binary files differnew file mode 100644 index 0000000000..0ed756fb33 --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.res |