Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: [WSH Panel Mod]LastFM suite (Read 53058 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

[WSH Panel Mod]LastFM suite

Hi everyone.

It s finally time for me to release what i have put together so far.

The Manager
Everything here is based on one single panel, the manager. It s aim is to allow to have one single configuration shared by many wsh panel mods. It will allow you to set properties.
The first thing you have to know about those properties is that you may use variables in them. If what you want is a foobar variable (related to a song) enter it just like you would in other components(%artist% for example). But there is also other variables related to wsh panel mod and that suite. They must differ from foobar properties so the syntax is different. Right now there is 2 of them, ?foobarpath? and ?lastfmdatapath?. I might introduce more in the future.


- First you have lastfm settings. You need to set a lastfm data path where everything will be cached. This might be the most important property. You must also set a LastFm API key and an account name. For that you obviously need a LastFM account!

- One very important setting is the path to wget(tools.wget). This is very important as it is used to download lastfm data. If wget is not found the manager will download directly in foobar and so it might freeze foobar while downloading!
In this release wget in installed in the directory "tools" in your foobar directory, though the "?foobarpath?tools/wget.exe" but you may change it if you want (but dont forget the dlls that goes with wget!!!).

- Then come the settings related to the art downloader. Here i use AlbumArtDownloader to download album art as well as artist art. But as other tools exist to download artist art, i made it possible to use a different tool for artist and album art. So there is a "albumad.gui" and "artistad.gui". Those properties are optional, but if there are empty or the file doesnt exist, related features will be removed in the different panels. After that there are related properties like args, minsize or ouptut(where you can use foobar variables as well as ?? variables).

Finally there is "skin.imgpath". The idea is to have a single variables shared by all panel. So one skin shared by all panels. Makes it easier to switch skin.

All those settings are saved in a INI file. Why? Because i like to save my datas, because it means that you can share a WSH suite config without sharing your all config.Because it means that you can clear properties without actually loosing all your settings. And mostly because other panels need it to read the config!!!
The ini file is saved everytime you modify your properties, yet it s not lost when you clear your properties!
The ini file is in your foobar folder under the name WSH.ini. This is the only hardcoded propertym and there is no other way around.
Still you can change it in scripts\utils.js

When you have set the properties, the manager is up and running.
- How does it work? if playing or pause, the manager will first look at the cache for playing track data (if stopped it will look for selected track data).  If found all panels will be notified and so updated with the data.
After 3 seconds of playing the manager will start looking for new data. It will look for biography, Artist mega art, similar artists and thumbnail images for similar(i might add more in the future). Bios and similars will always be grabbed, if they are different from the cache then the cache is updated. For images only missing data is fetched.
After 4 seconds of playing, the manager will look for LOVE and PLAYCOUNT stats from lastfm (thanks to marc2003). The same way, other panels will be notified.
- how do i insert the manager in my config? Just like any other panel, the one thing you need to now is that the only thing drawn in this panel is a button to open properties. It also gives feedback on errors

As you can see images are used. The manager will look for "ok.png" and "error.png" in your skin.imgpath directory. If not found there will be nothing drawn. If found the button will have the size of the image.
By the way i use a different version of "tooltip_buttons.js"(packaged in the release) where the hover image does not need to have the "border", the border is drawn by the object. So only image suffice for a button.

The manager is made so that you dont have to change anything in the script itself, i wont support any modified version of it, just the one i use everyday. Yet i am more than ok to add new features if they look necessary.

- How does the manager notify other panels? That s the magic of WSH panel Mod. TPWang made an amazing work and made things very easy.
The manager sends different signals. A signal is made of a name and value. If you want to catch those notifications in your panel just use the function "on_notify_data(name, info)". Switching the name you can get which notification you are getting. And if the notification comes with a value it s in "option"
Here is the list of notifications that the manager sends"
- name:"config_updated" , "info": path to the inifile(mostly unecessary if you include utils.js)
- name:"lastfm_bio" , "info": the actual biography
- name:"lastfm_similars" , "info": list of similars. (';' separated)
- name:"lastfm_newArtistImage", "info": path to the newly downloaded image
- name:"lastfm_loved", "info": lastfm love and playcount info (';' separated)

The art panel
The art panel is the first of my panel Suite. It s also the most complicated one. It s made to be used in many different configs


All the options are set through properties and contextual menu.
Most of them dont need any explanation. For the others:
- Buttons: THe art panel has the possibility to have buttons. Those buttons will fade in when the mouse enter the panel. Fade even more when the mouse is over them. And fade out when the mouse leave.
BUttons are defined through properties. buttons.show must  be set to 1 to show buttons. buttons.list contains the names of the buttons. For each button, a corresponding image must be in your skin.imgpath.
Available buttons are prev(prev.png), playpause(play.png and pause.png), next(next.png), refresh(refresh.png) and download(download.png).
Buttons will appear in the order you enter them (';' separated).
buttons.VA decide of the vertical alignment (0=top, 1=center, 2=bottom). The horizontal alignment is always centered. I dont see the point of left or right. But if requested i can add the option.
- Downloader: As explained in the manager, you can set up an album art downloader and an artist art downloader. This is where you use them! You can use it through double click, contextual menu or button. But those options will only appear if the downloader path is correct! When a download is finished, the panel will refresh itself automatically. Only one instance of the downloader at a time per panel!

- FillImage: I wrote a special algorithm taht i use for artist art panel. It will take your panel rectangle and choose the best according rectangle in the image. That way no ratio, no blank areas. After in the properties you can help the algorithm choose the rectangle by choosing vertical and horizontal alignments.

Note that this panel uses foobar 1.0 artreader. Also the manager will notify it if there is a new image available.

Similars Panels

This is a simple panel showing similar artists of the playing or selected song. It waits for notification from the manager for new entries.
There are simple properties for now. I will let you look at them. This panel uses the lastfm.datapath to look for images.
For each artist there are feature on click and right click.

Bio Panel
Simple bio panel using the manager, scroll, drag and right click menu.


Love panel

A very simple panel with one button to love a track. It s based on marc2003 work and has not been updated to the latest version for customdb.
As others there is no lastfm query in there!!! It works with the manager.

Conclusion

That s about everything you need to know. You can easily write you own panels. Please if you want new features in the manager or the existing panels. Ask for it and i ll implement it. I prefer that than seeing too many forks.

Requirements & Package

You need WSH Panel Mod 1.3.0 to run that suite. Everything else is  in the package.

Just extract the package in your foobar config.
In the wsh folder you will find the scripts.
In the tools folder, there are everything wget related.
In the scripts folder are common scripts used by all panels.
You will also find in the package a WSHExample.ini. If you want to use it you have to rename it to WSH.ini
I gave a skin example in the folder skin/example with all necessary images.

That s about it. Hope you will all like it. And dont hesitate to ask, i am willing to answer to any question

I will finish with an amazing thanks for TPWang without who none of that would have been possible.

[WSH Panel Mod]LastFM suite

Reply #1
Write install instructions please. I extracted and imported the manager.txt file in a WSH panel but the properites are all blank.

where to put wsh.ini etc?

This is the problem with huge bundles like this. There is no simple way to install.


EDIT: wsh.ini needs to be put in place before you create the WSH Panel for Manager.txt
This was not immediately obvious until you actually read the scripts.
And I'm not a professional programmer.

[WSH Panel Mod]LastFM suite

Reply #2
Write install instructions please. I extracted and imported the manager.txt file in a WSH panel but the properites are all blank.

where to put wsh.ini etc?

This is the problem with huge bundles like this. There is no simple way to install.


EDIT: wsh.ini needs to be put in place before you create the WSH Panel for Manager.txt
This was not immediately obvious until you actually read the scripts.
And I'm not a professional programmer.

Now you dont and it s written in the previous post. You dont need a wsh.ini at first. But everything will be blank.
It s also written that the wsh.ini is saved in your foobar folder.
I wrote everything you need now (at least i hope so as there are a lot of things to know.)

[WSH Panel Mod]LastFM suite

Reply #3
yes but I don't want to configure everything. I want sane defaults and only have to set in API key, username. datapath should default to fb2k profile folder

like %appdata%\foobar2000\lastfmcache\


Also use 0 instead of 1 in wsh.run so the console windows don't show up.

I know you probably used it during debugging, but release stuff shouldn't have that.

Also you use a mix of forward slash and backward slash everywhere. Stick to proper Windows directory separator which is backslash.

in script use \\ to escape it

"c:\\my\\long path\\";

In properties you don't need this as it's outside the script. just use \ like:
c:\my\long path\

Also don't demand that people end their paths in a slash.
Write a simple function that checks if the path ends in a slash and appends on if not.

Code: [Select]
function as(path) {
if (path.substr(path.length-1,1) == '\\') {
return path;
}
else {
return path + '\\';
}
}


then use as(somepath) everywhere in your script. simple.


[WSH Panel Mod]LastFM suite

Reply #4
gj carmenm!, looking forward to get home and try the bio downloader stuff.

But, is it necessary to download the bio, if it is already in the cache? it kind of removes the idea of "caching it" in the first place. I know you use the cache to "display something while looking for something", but since bio's don't get updated that often, reducing overhead to the lastfm servers would seem like a good idea, hence the idea of caching the bio only once.
Then, with a right click menu, you could force a cache update and everything would be great.
I won't have any problem modifying the manager, just wanted to point out that "issue".
everything else looks great, looks like an approach to a "framework" for WSH script development.

[WSH Panel Mod]LastFM suite

Reply #5
yes but I don't want to configure everything. I want sane defaults and only have to set in API key, username. datapath should default to fb2k profile folder

like %appdata%\foobar2000\lastfmcache\

no point i dont want to initialize it to anything! if you dont set it just wont be used. That s all

Quote
Also use 0 instead of 1 in wsh.run so the console windows don't show up.

Thanks shouldnt be there anymore

Quote
Also you use a mix of forward slash and backward slash everywhere. Stick to proper Windows directory separator which is backslash.

in script use \\ to escape it

"c:\\my\\long path\\";

In properties you don't need this as it's outside the script. just use \ like:
c:\my\long path\

Also don't demand that people end their paths in a slash.
Write a simple function that checks if the path ends in a slash and appends on if not.

Code: [Select]
function as(path) {
if (path.substr(path.length-1,1) == '\\') {
return path;
}
else {
return path + '\\';
}
}


then use as(somepath) everywhere in your script. simple.

Thanks already in

New file uploaded

[WSH Panel Mod]LastFM suite

Reply #6
gj carmenm!, looking forward to get home and try the bio downloader stuff.

But, is it necessary to download the bio, if it is already in the cache? it kind of removes the idea of "caching it" in the first place. I know you use the cache to "display something while looking for something", but since bio's don't get updated that often, reducing overhead to the lastfm servers would seem like a good idea, hence the idea of caching the bio only once.
Then, with a right click menu, you could force a cache update and everything would be great.
I won't have any problem modifying the manager, just wanted to point out that "issue".
everything else looks great, looks like an approach to a "framework" for WSH script development.

Changes happens a lot in bios, like when there is a new album, or events in the band(split for example). caching is not only about not downloading(it is for images), it s also to have offline data and immediate data when starting a song.
Now it doesnt cost me anything to download the bio as i still query lastfm data. i just update the bio cache file if it has changed.

PS: to any admin, could i have the possibility to change my first post anytime? I doesnt appear to able to do so. Thanks

[WSH Panel Mod]LastFM suite

Reply #7
i can't even set a data path. 

edit: ah you have to create the folder yourself. i thought the script would create it for me.

[WSH Panel Mod]LastFM suite

Reply #8
Still many bugs like that one marc2003. The script should auto-create missing folders. This has to be automatic or we might as well do it all manually.

Also the mouse gets stuck when dragging the bios panel. I think I'm going to stick with marc2003's bios panel. Looks a lot better too.


You got two function on_mouse_lbtn_up(x, y) handlers in the javascript code.
consider consolidating them. then mouse dragging works properly.


Also why do you use WGET instead of XMLHTTPRequest?
The script hangs foobar2000 while the numerous wget processes are running.
Things like that has to be threaded somehow.

[WSH Panel Mod]LastFM suite

Reply #9
That similair is nice  LEts see if i can get it stripped down to get it working by just that ;D

[WSH Panel Mod]LastFM suite

Reply #10
Still many bugs like that one marc2003. The script should auto-create missing folders. This has to be automatic or we might as well do it all manually.

Also the mouse gets stuck when dragging the bios panel. I think I'm going to stick with marc2003's bios panel. Looks a lot better too.


You got two function on_mouse_lbtn_up(x, y) handlers in the javascript code.
consider consolidating them. then mouse dragging works properly.


Sorry but i really dont like your tone. You dont like it? Dont use it!
I mean you speak like you know everything. So why dont you write your own scripts?
Quote
Also why do you use WGET instead of XMLHTTPRequest?
The script hangs foobar2000 while the numerous wget processes are running.
Things like that has to be threaded somehow.

Already talked about that in the wsh panel mod thread
foobar doesnt hang her. And it s worth using javascript directly.
You want to do it, just let the wget setting blank

[WSH Panel Mod]LastFM suite

Reply #11
No I don't like *YOUR* tone. I'm giving you feedback. And suggestions for improvement.
If you don't like that just don't post your scripts here. I did not criticize your work.
Now end this bickering before a moderator closes the thread
This will be the final word on this. Now back on topic!


Yes I'm going to improve the scripts. But I don't like working with foreign code that much, and I don't think it's wise for me to make a bunch of modifications if it doesn't benefit others in some way or another.

I like the way you set up this Manager script. But something that would be much better is if WSH Panels mod had a global properties store which scripts could share. Yes some scripts might interfere with other scripts in a bad way but ultimately it's your own responsibility to check what scripts you have installed. I just think the manager script is more about extending WSH Panels mod than the panels themselves.

I have looked at AngelScript which is a lot like C++ and uses C/C++ datatypes. If WSH Panels mod used AngelScript instead of the Windows Script host it could more easily integrate with the foobar2000 API and you might one day create new panels directly in AngelScript and bypass the WSH Panels mod altogether (WSH Panels mod just becoming a pure scripting engine for foobar2000 which loads scripts from a folder). Many panels contain relatively little code and could just as easily be scripted instead of coded in C++.


These are just ramblings.

[WSH Panel Mod]LastFM suite

Reply #12
edit: i give up. i'm not wasting any more time. good luck to anybody else. you'll need it.

[WSH Panel Mod]LastFM suite

Reply #13
No I don't like *YOUR* tone. I'm giving you feedback. And suggestions for improvement.
If you don't like that just don't post your scripts here. I did not criticize your work.
Now end this bickering before a moderator closes the thread
This will be the final word on this. Now back on topic!


Yes I'm going to improve the scripts. But I don't like working with foreign code that much, and I don't think it's wise for me to make a bunch of modifications if it doesn't benefit others in some way or another.

I like the way you set up this Manager script. But something that would be much better is if WSH Panels mod had a global properties store which scripts could share. Yes some scripts might interfere with other scripts in a bad way but ultimately it's your own responsibility to check what scripts you have installed. I just think the manager script is more about extending WSH Panels mod than the panels themselves.

I have looked at AngelScript which is a lot like C++ and uses C/C++ datatypes. If WSH Panels mod used AngelScript instead of the Windows Script host it could more easily integrate with the foobar2000 API and you might one day create new panels directly in AngelScript and bypass the WSH Panels mod altogether (WSH Panels mod just becoming a pure scripting engine for foobar2000 which loads scripts from a folder). Many panels contain relatively little code and could just as easily be scripted instead of coded in C++.


These are just ramblings.

Ok. Seeing this post i apologize. You need to understand that i know my scripts are not perfect. Any dev knows taht when you dev something in your corner, there are things you dont see and that only appear when shared/released to others. I am glad in a way that you criticize my work, i really am. But for instance you didnt even said thanks or show a little of appreciation until this post.

Now you are right i wanted to write something that extends wsh panel mod. I love the work that marc2003 has done for example. But when you use a lot of those panels together, it becomes a real mess. Now i totally agree on the problem of shared variables, that s why i went for the ini file. The notification system of wsh panel mod allowed me to share that ini file among panels.
Wsh panel mod is actually close to what you want with AngelScript, it just doesnt load scripts directly, they are stored in foobar config.

[WSH Panel Mod]LastFM suite

Reply #14
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.


[WSH Panel Mod]LastFM suite

Reply #16
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.

[WSH Panel Mod]LastFM suite

Reply #17
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

Quote
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
Code: [Select]
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?

Quote
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
Code: [Select]
// ==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(/&quot;/g, '"');
                            artistbio = text.replace(/&amp;/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.



 

[WSH Panel Mod]LastFM suite

Reply #20
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.


oh so this is about your personal preference? and there was me thinking you were releasing this as an easy to use tool for other people to use.

Quote
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.


maybe you should test your panels in a standard columns UI layout and default UI to see how bad it looks. now that WSH panel mod is UI independent, i think you should cater for everyone, not just yourself.  you shouldn't have started this thread if this is a personal project. 

Quote
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


i'm wrong? you're telling me what i'm seeing with my own eyes is wrong? nice attitude you have there. you obviously haven't spent enough time testing this.

here's another rather large fault....if i play an artist where there is no biography, your script writes the previous artist's biography to the new, wrong cache.  and your method for saving text? hahahahahaha.      if you wanted to use multiple tags, why didn't you save the whole xml file instead. what you've hacked to together is amazing. and i mean that in the worst possible sense. 

you've obviously spent a huge amount of time and effort on this but i think you've been concentrating in the wrong areas.

[WSH Panel Mod]LastFM suite

Reply #21
There seems to be a lot of hostility here for some reason.  I'm not really sure why.

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


Thanks for the update.  However, was the new manager script supposed to fix something?  I tried it and all it did was break my similar artist panel (that was working).

Also, the wget thing was my fault.  I typed the full path to the .exe in properties, which was incorrect.  The freezing was due to not using wget.  It's fixed now.

Finally, how am I supposed to get the artist art?  I mean, step-by-step.  I still can't figure that out for the life of me.

[WSH Panel Mod]LastFM suite

Reply #22
Or may be you only want solid background?


Correct, I just want solid black instead of white.

Code: [Select]
gr.FillSolidRect(0, 0, ww, wh, RGB(0,0,0));



Cool... Now how would I get the text to be white? 

[WSH Panel Mod]LastFM suite

Reply #23
Ok, I got the artist art working by just using $replace(%artist%, ,'%20',&,'%26') in the artwork preferences.

Now I'm experiencing a bug with the artwork panel.  My artist art panel is on a tab "artist biography".  If I close foobar while the "artist biography" tab is in focus, everything is fine.  However, if I close foobar when the "artist biography" tab is not in focus, I have the following problem:  When I re-open foobar, and switch to the "artist biography" tab, it crashes with the following error:

Code: [Select]
Error: WSH Panel Mod (GUID: DB3CA228-739E-4AF9-B0A9-E1B85A04E558): Microsoft JScript runtime error:
Overflow
Ln: 150, Col: 15
<source text only available in compile time>


I should note that if I right-click > configure on the artwork panel after it's crashed and hit "ok" or "apply", it works fine.

[WSH Panel Mod]LastFM suite

Reply #24
I played around a bit more with the code and managed to fix it (for myself, anyway).

Code: [Select]
function myDrawImage(gr, img, size,  opacity, fill ) {
    if(size.width > 1)   
    {
        if(fill)
        {
            gr.DrawImage(img, 0, 0, ww, wh, size.x, size.y, size.width, size.height, 0, opacity);
        }
        else
        {
            gr.DrawImage(img, size.x, size.y, size.width, size.height, 0, 0, img.width, img.height, 0, opacity);
        }
    }
}

This may not be the most elegant implementation, but replacing myDrawImage with the above code fixed the issue for me.