as i'm a glutton for punishment, i've had another go at this.
some constructive criticisms...
add some padding around the panels. they look crap with content right up to the edge. of course i can fix that myself but the average end user isn't going to want to
don't remove the "configure" context menu item. you have no way to edit the panel.
uses system colours
fix your bio panel. once you click on it, it scrolls even without dragging and you can't stop it.
sort out the popup command windows. i doubt many people can live with that. i can't.
and my biggest complaint for last. what's the point of caching data only to have to wait a few seconds for it to display when switching tracks? you should only have to wait when it's downloading, not using cached files.
and i think your whole "manager" system is unnecessarily complex for no reason at all. just a simple external file with a few variables set would have done the trick.
I didnt remove the configure thingy. You get it on every panel with a SHIFT+LClick. When i use my config on a day by day basis, i dont like to see unnecessary entries.
For padding they look good here. I mean it depends on what you use on top of them. I use PSS so i want my panel to fit their all content , so no padding. BUt i guess you must be using DUI.
You are wrong about the cache. Cached data is loaded on track start or selection change. After 3 seconds it only updates the cache if necessary
Hi carmenm. This is truly a powerful tool you've put together here!
First question: Is there anyway to manipulate the panel backgrounds?
Not right now but you can easily add a line like this
gr.DrawImage(img, 0, 0, ww, wh, 0, 0, img.width, img.height, 0, 255);
at the beginning of every panel paint function to draw an image.
Or may be you only want solid background?
So... I've been wrestling with this for several hours, and I'm just trying to get the artist art to show. Do I need the Albumartdownloader installed? It looks like the script downloads art just fine as is. It downloads properly to my last.fm cache folder, but I have to use some fancy title formatting (replace " " with "%20", etc.) in foobar's settings to recognize it. Is this really necessary? If so, can you post the proper command to get it working? Thanks.
Also, I'm using the wget tool you posted, yet I'm experiencing UI pauses/freezes a few seconds in to each track when the info updates itself. Is this normal?
By the way, I can tell you've put a lot into this. I really appreciate the time and effort you've spent to help us all do something really cool with our foobar configs. However, the actual script is VERY cumbersome and difficult to work with. It tries to do way, way too much. I'll echo some of the other responses you've received by saying that combining all of this into a "suite" is actually causing much more headache than warranted. A series of simple scripts would be much better.
Wget does not freeze even a bit here. I am not sure why it does for you :s
FOr The problem with %20 i think i see what it is. I added some modification yesterday for wget to manage unicode characters. FOr now the only i found for him to deal with it was to use encodeURIComponent. But that broke with the artreader.
I am not sure how to handle unicode characters between wget and the artreader
Here is a working version of the manager
// ==PREPROCESSOR==
// @import "%fb2k_path%scripts\simple_buttons.js"
// @import "%fb2k_path%scripts\utils.js"
// ==/PREPROCESSOR==
MK_SHIFT = 0x0004;
window.NotifyOthers("config_updated", inipath);
window.GetProperty("lastfm.username", utils.ReadINI(inipath, "LASTFM", "username", ""));
window.GetProperty("lastfm.apikey", utils.ReadINI(inipath, "LASTFM", "apikey", ""));
window.GetProperty("albumad.gui", utils.ReadINI(inipath, "ALBUMAD", "gui", ""));
window.GetProperty("artistad.gui", utils.ReadINI(inipath, "ARTISTAD", "gui", ""));
window.GetProperty("albumad.args", utils.ReadINI(inipath, "ALBUMAD", "args", ""));
window.GetProperty("albumad.output", utils.ReadINI(inipath, "ALBUMAD", "output", ""));
window.GetProperty("albumad.minsize", utils.ReadINI(inipath,"ALBUMAD", "minsize",""));
window.GetProperty("albumad.maxsize", utils.ReadINI(inipath,"ALBUMAD", "maxsize",""));
window.GetProperty("artistad.args", utils.ReadINI(inipath, "ARTISTAD", "args", ""));
window.GetProperty("artistad.minsize", utils.ReadINI(inipath,"ARTISTAD", "minsize",""));
window.GetProperty("artistad.maxsize", utils.ReadINI(inipath,"ARTISTAD", "maxsize",""));
window.GetProperty("artistad.output", utils.ReadINI(inipath, "ARTISTAD", "output", ""));
//path properties are not treated as others as they need to be translated
window.GetProperty("lastfm.datapath", utils.ReadINI(inipath, "LASTFM", "datapath", ""));
window.GetProperty("skin.imgpath",utils.ReadINI(inipath, "SKIN", "imgpath",""));
window.GetProperty("tools.wget",utils.ReadINI(inipath, "TOOLS", "wget",""));
var skinimgpath = translatePath(window.GetProperty("skin.imgpath"),true);
var lastfmdatapath = translatePath(window.GetProperty("lastfm.datapath"),true);
var wgetpath = translatePath(window.GetProperty("tools.wget"),true);
if (!utils.FileTest(wgetpath, "e"))
{
wgetpath = "";
}
function on_script_unload()
{
utils.WriteINI(inipath, "LASTFM", "datapath", window.GetProperty("lastfm.datapath"));
utils.WriteINI(inipath, "SKIN", "imgpath", window.GetProperty("skin.imgpath"));
utils.WriteINI(inipath, "TOOLS", "wget", window.GetProperty("tools.wget"));
utils.WriteINI(inipath, "LASTFM", "username", window.GetProperty("lastfm.username"));
utils.WriteINI(inipath, "LASTFM", "apikey", window.GetProperty("lastfm.apikey"));
utils.WriteINI(inipath, "ALBUMAD", "gui", window.GetProperty("albumad.gui"));
utils.WriteINI(inipath, "ARTISTAD", "gui", window.GetProperty("artistad.gui"));
utils.WriteINI(inipath, "ALBUMAD", "args", window.GetProperty("albumad.args"));
utils.WriteINI(inipath, "ALBUMAD", "minsize", window.GetProperty("albumad.minsize"));
utils.WriteINI(inipath, "ALBUMAD", "maxsize", window.GetProperty("albumad.maxsize"));
utils.WriteINI(inipath, "ALBUMAD", "output", window.GetProperty("albumad.output"));
utils.WriteINI(inipath, "ARTISTAD", "args", window.GetProperty("artistad.args"));
utils.WriteINI(inipath, "ARTISTAD", "minsize", window.GetProperty("artistad.minsize"));
utils.WriteINI(inipath, "ARTISTAD", "maxsize", window.GetProperty("artistad.maxsize"));
utils.WriteINI(inipath, "ARTISTAD", "output", window.GetProperty("artistad.output"));
window.NotifyOthers("config_updated", inipath);
}
var currentbio = "";
var currentsimilar = "";
fso = new ActiveXObject("Scripting.FileSystemObject");
var WshShell = new ActiveXObject("WScript.Shell");
on_item_focus_change();
setError(0);
function on_playback_time(time)
{
if(time == 3)
{
var g_metadb = fb.GetNowPlaying();
if (g_metadb)
{
get_lastfm_info(fb.TitleFormat("%artist%").EvalWithMetadb(g_metadb) , "");
}
}
if(time == 4)
{
var g_metadb = fb.GetNowPlaying();
if (g_metadb) {
}
get_lastfm_info(fb.TitleFormat("%artist%").EvalWithMetadb(g_metadb) , fb.TitleFormat("%title%").EvalWithMetadb(g_metadb));
}
}
function on_item_focus_change()
{
var g_metadb = (fb.IsPlaying || fb.isPaused )? fb.GetNowPlaying():fb.GetFocusItem();
if (g_metadb)
{
load_lastfm_info(fb.TitleFormat("%artist%").EvalWithMetadb(g_metadb));
}
}
function on_metadb_changed()
{
}
function on_playback_new_track(metadb)
{
}
function load_lastfm_info(artist)
{
currentbio = "";
currentsimilar = "";
var filename = lastfmdatapath + ansi(artist) + ".lastfm";
if (utils.FileTest(filename,"e"))
{
// Open the file for input.
f = fso.OpenTextFile(filename, 1, false, -1);
// Read from the file and display the results.
while (!f.AtEndOfStream)
{
var r = f.ReadLine();
var res = r.split(" %separator% ");
if (res.length == 2)
{
switch (res[0])
{
case "lastfm_biography":
currentbio = res[1].replace(/%newline%/g,"\n");
break;
case "lastfm_similars":
currentsimilar = res[1];
break;
}
}
}
f.close();
}
window.NotifyOthers("lastfm_bio", currentbio);
window.NotifyOthers("lastfm_similarArtists", currentsimilar);
}
function get_lastfm_info(artist, title) {
if (window.GetProperty("lastfm.apikey").length != 32)
{
setError(1, "You need to enter a LastFM API Key");
return;
}
if (window.GetProperty("lastfm.username") == "")
{
setError(1, "You need to enter a LastFM username");
return;
}
if (!utils.FileTest(lastfmdatapath, "e"))
{
setError(1, "You need to set a LastFM data path");
return;
}
var url;
if (title == "")
{
//fb.trace("getting lastfm infos for:"+artist);
var artistbio = currentbio;
var artistsimilar = currentsimilar;
url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=" + window.GetProperty("lastfm.apikey") + "&artist=" + encodeURIComponent(artist);
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("GET", url + "&s=" + Math.random(), true);
xmlhttp.setRequestHeader('User-Agent','foo_lastfm_artist_info');
xmlhttp.send();
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState == 4)
{
if (xmlhttp.status == 200)
{
xmlDoc = xmlhttp.responseXML;
try {
strInputCode = xmlDoc.getElementsByTagName("content")[0].childNodes[0].nodeValue;
strInputCode = strInputCode.replace(/&(lt|gt);/g, function (strMatch, p1){
return (p1 == "lt")? "<" : ">";
});
text = strInputCode.replace(/<\/?[^>]+(>|$)/g, "");
text = text.replace(/\n/g, "<br/>");
text = decodeXMLEntites(text);
text = text.replace(/<BR>/g, "\n");
text = text.replace(/"/g, '"');
artistbio = text.replace(/&/g,"&");
} catch(e) {
}
try {
artistsimilar = "";
var artistsArray = xmlDoc.getElementsByTagName("artist");
for (i = 0; i != artistsArray.length; i++)
{
if (i == 0)
{
var artistname = (artistsArray[i].childNodes[0].childNodes[0])?artistsArray[i].childNodes[0].childNodes[0].nodeValue:"";
var artistpicture = (artistsArray[i].childNodes[7].childNodes[0])?artistsArray[i].childNodes[7].childNodes[0].nodeValue:"";
if (artistname != "" && artistpicture != "")
{
var imageextension = artistpicture.substring(artistpicture.length-3);
var artistImage = lastfmdatapath + ansi(artistname) + "." + imageextension;
if(!fso.FileExists(artistImage))
{
DownloadFile(artistpicture, artistImage);
window.NotifyOthers("lastfm_newArtistImage", artistImage);
}
}
}
else
{
var artistname = (artistsArray[i].childNodes[0].childNodes[0])?artistsArray[i].childNodes[0].childNodes[0].nodeValue:"";
var artistsmallpicture = (artistsArray[i].childNodes[3].childNodes[0])?artistsArray[i].childNodes[3].childNodes[0].nodeValue:"";
//fb.trace("aritst:"+artistname+";picture:"+artistsmallpicture);
if (artistname != "")
{
if (artistsmallpicture != "")
{
var imageextension = artistsmallpicture.substring(artistsmallpicture.length-3);
var artistImage = lastfmdatapath + encodeURIComponent(ansi(artistname)) + "_small." + imageextension;
if(!fso.FileExists(artistImage))
{
DownloadFile(artistsmallpicture, artistImage);
}
}
artistsimilar = artistsimilar + artistname + ";";
}
}
}
} catch(e) {
}
var needwriting = false;
if (artistbio != currentbio)
{
needwriting = true;
currentbio = artistbio;
window.NotifyOthers("lastfm_bio",currentbio);
}
if (artistsimilar != currentsimilar)
{
needwriting = true;
currentsimilar = artistsimilar;
window.NotifyOthers("lastfm_similarArtists",currentsimilar);
}
if (needwriting)
{
ts = fso.CreateTextFile(lastfmdatapath + ansi(artist) + ".lastfm", 2, true);
if (!ts)
{
setError(1, "Impossible to write in your LastFM data path!");
return;
}
var bio = currentbio.replace(/\n/g,"%newline%");
ts.WriteLine("lastfm_biography %separator% " +bio);
ts.WriteLine("lastfm_similars %separator% " +currentsimilar);
ts.close();
}
} else {
fb.trace(xmlhttp.responsetext);
}
}
}
}
else if (window.GetProperty("lastfm.username") != "")
{
url = "http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=" + window.GetProperty("lastfm.apikey") + "&username=" + window.GetProperty("lastfm.username") + "&artist=" + encodeURIComponent(artist) + "&track=" + encodeURIComponent(title);
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("GET", url + "&s=" + Math.random(), true);
xmlhttp.setRequestHeader('User-Agent','foo_lastfm_playcount_sync');
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
//fb.trace(xmlhttp.responsetext);
var xmlDoc = xmlhttp.responseXML;
var up = xmlDoc.getElementsByTagName("userplaycount");
var ul = xmlDoc.getElementsByTagName("userloved");
var userplaycount = (up.length == 1) ? xmlDoc.getElementsByTagName("userplaycount")[0].childNodes[0].nodeValue : "0";
var userloved = (ul.length == 1) ? userloved = xmlDoc.getElementsByTagName("userloved")[0].childNodes[0].nodeValue : "0";
window.NotifyOthers("lastfm_loved", userloved + ";" + userplaycount);
} else {
fb.trace(xmlhttp.responsetext);
}
}
}
}
}
function DownloadFile(sURL, sFilename)
{
//fb.trace("\""+wgetpath +"\" -O\""+sFilename +"\" " + sURL);
if (wgetpath != "")
{
WshShell.Run( "\""+wgetpath +"\" -O\""+sFilename +"\" " + sURL , 0, true);
}
else
{
try
{
var oStream = new ActiveXObject('ADODB.Stream');
}
catch(e)
{
return;
}
// Fetch the file
var oXMLHTTP = new ActiveXObject('MSXML2.XMLHTTP');
oXMLHTTP.open('GET', sURL, false);
oXMLHTTP.send();
if (oXMLHTTP.Status == 200)
{
oStream.Open();
oStream.Type = 1; //adTypeBinary
oStream.Write(oXMLHTTP.ResponseBody);
oStream.SaveToFile (sFilename, 2); // adSaveCreateNotExist AND adSaveCreateOverWrite
oStream.Close();
oStream = null;
}
else
{
return;
}
oXMLHTTP = null;
}
}
function setError(b, message) {
switch(b) {
case 0:
n = "ok.png";
h = "ok.png";
tooltip = "LastFM account: " +window.GetProperty("lastfm.username") ;
func = function() {window.ShowProperties();}
break;
case 1:
n = "error.png";
h = "error.png";
tooltip = message;
func = function() {window.ShowProperties();}
break;
}
var img = gdi.image(skinimgpath + n);
if (img)
{
delete Buttons;
Buttons = {
but: new Button(0,0, img.width, img.height, {normal: skinimgpath + n, hover: skinimgpath + h}, func, tooltip)
};
window.Repaint();
}
}
Now yes the code of the manager is heavy but i dont think it does too much. It just downloads a few images and write a few files.