Sure, here you go:
// ==PREPROCESSOR==
// @import "%fb2k_profile_path%marc2003\common4.js"
// @name "Last.fm"
// @author "marc2003 (modified by kimgronqvist)"
// @feature "v1.4"
// @feature "watch-metadb"
// ==/PREPROCESSOR==
var script_name = "Last.fm";
var username_file = settings_path + "username";
var username = read(username_file);
var api_key_file = settings_path + "api_key";
var api_key = read(api_key_file);
var lfm_img = gdi.Image(images_path + "lastfm_red_small.gif");
var spotify_img = gdi.Image(images_path + "spotify.png");
var lastfm_play_img = gdi.Image(images_path + "lastfm_play.png");
var auto_img = gdi.Image(images_path + "search_small.png");
var up_img = gdi.Image(images_path + "up.png");
var down_img = gdi.Image(images_path + "down.png");
var text_x = 6;
var but_x = 0;
var offset = 0;
var rows = 0;
var items = 0;
var artist = "";
var folder = "";
var g_text = "";
var names = [];
var names_c = [];
var names_widths = [];
var all_width;
var urls = [];
var methods = ["artist.getSimilar", "artist.getTopTags", "artist.getTopFans", "artist.getTopAlbums", "artist.getTopTracks"];
var nice_lastfm_types = ["similar artists", "top tags", "top fans", "top albums", "top tracks"];
var g_tooltip = window.CreateTooltip();
var link = window.GetProperty("link", "spotify");
var lastfm_type = window.GetProperty("lastfm_type", 0);
var lastfm_artist = window.GetProperty("lastfm_artist", "%artist%");
var pause = window.GetProperty("pause", true);
on_item_focus_change();
function on_notify_data(name, data) {
if (name == "lastfm_update" && data == 1) {
username = read(username_file);
api_key = read(api_key_file);
artist = Date();
on_item_focus_change();
}
}
function on_size() {
ww = window.Width;
wh = window.Height;
but_x = Math.round((ww - 15) / 2);
offset = 0;
rows = Math.floor((wh - 58) / 20);
up_btn = new sb(but_x, 32, 15, 15, up_img, "offset > 0", function() { on_mouse_wheel(1); });
down_btn = new sb(but_x, wh - 15, 15, 15, down_img, "offset < items - rows", function() { on_mouse_wheel(-1); });
}
function on_paint(gr) {
gr.FillSolidRect(0, 0, ww, wh, g_backcolor);
switch(true) {
case username.length == 0:
case api_key.length != 32:
gr.GdiDrawText("Please use the context menu to set your Last.fm username and API KEY.", normal_font, g_textcolor, 10, 0, ww - 20, wh, DT_VCENTER | DT_CENTER | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
break;
case !g_metadb:
gr.GdiDrawText("[no selection]", normal_font, g_textcolor, 0, 0, ww, wh, DT_VCENTER | DT_CENTER | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
break;
default:
gr.GdiDrawText(nice_lastfm_types[lastfm_type], title_font, g_textcolor_hl, 6, 6, ww - 77, 24, DT_VCENTER | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX);
//gr.DrawImage(lfm_img, ww - 60, 8, 50, 18, 0, 0, 50, 18);
gr.DrawLine(5, 29, ww - 10, 29, 1, g_textcolor_hl);
if (items == 0) {
gr.GdiDrawText("[no data]", normal_font, g_textcolor, 0, 0, ww, wh, DT_VCENTER | DT_CENTER | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
} else {
gr.GdiDrawText("[ALL]", list_font, g_textcolor, text_x, 32, ww - 36, 18, DT_VCENTER | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX);
for (i = 0; i < Math.min(rows, items); i++) {
//if (lastfm_type == 0) gr.DrawImage(link == "spotify" ? spotify_img : link == "lastfm" ? lastfm_play_img : auto_img, 6, 45 + (i * 20), 20, 20, 0, 0, 20, 20);
gr.GdiDrawText(names[i + offset], list_font, g_textcolor, text_x, 52 + (i * 20), ww - 36, 18, DT_VCENTER | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX);
}
up_btn.draw(gr);
down_btn.draw(gr);
}
}
}
function on_playback_new_track() {
on_item_focus_change();
}
function on_playback_dynamic_info_track() {
on_item_focus_change();
}
function on_playback_stop() {
on_item_focus_change();
}
function on_metadb_changed() {
if (!g_metadb) return;
my_metadb_changed(lastfm_artist, function() { load(); });
}
function load() {
names = [];
names_widths = [];
urls = [];
data = [];
offset = 0;
items = 0;
text_x = 6;
if (!fso.FolderExists(folder)) fso.CreateFolder(folder);
filename = folder + "\\" + methods[lastfm_type] + ".json";
if (fso.fileExists(filename)) {
file = fso.Getfile(filename);
ts = fso.OpenTextFile(filename, 1, false, -1);
g_text = ts.ReadAll();
ts.close();
parsed_data = JSON.parse(g_text);
switch(true) {
case parsed_data.error > 0:
fb.trace(script_name + ": " + g_text);
break;
case lastfm_type == 0 && typeof parsed_data.similarartists.artist == "object":
//text_x = 30;
data = parsed_data.similarartists.artist;
break;
case lastfm_type == 1 && typeof parsed_data.toptags.tag == "object":
data = parsed_data.toptags.tag;
break;
case lastfm_type == 2 && typeof parsed_data.topfans.user == "object":
data = parsed_data.topfans.user;
break;
case lastfm_type == 3 && typeof parsed_data.topalbums.album == "object":
data = parsed_data.topalbums.album;
break;
case lastfm_type == 4 && typeof parsed_data.toptracks.track == "object":
data = parsed_data.toptracks.track;
break;
}
items = data.length;
var temp_bmp = gdi.CreateImage(1, 1);
var temp_gr = temp_bmp.GetGraphics();
for (i = 0; i < items; i++) {
names[i] = data[i].name;
urls[i] = data[i].url;
names_widths[i] = temp_gr.CalcTextWidth(names[i], list_font);
}
all_width = temp_gr.CalcTextWidth("[ALL]", list_font);
temp_bmp.ReleaseGraphics(temp_gr);
temp_bmp.Dispose();
temp_gr = null;
temp_bmp = null;
if (Date.parse(Date()) - Date.parse(file.DateLastModified) > 86400000) get();
} else {
get();
}
window.Repaint();
}
function get() {
var fn = filename;
lastfm("&method=" + methods[lastfm_type] + "&artist=" + encodeURIComponent(artist), "foo_wsh_lastfm_similar", function() { save(xmlhttp.responsetext, fn); load(); });
}
function on_mouse_wheel(delta) {
if (items < rows) return;
offset -= delta * 3;
if (offset < 0) offset = 0;
if (rows + offset > items) offset = items - rows;
window.Repaint();
}
function on_mouse_move(x, y) {
index = Math.floor((y - 45 ) / 20) + offset;
in_range = index >= offset && index < Math.min(offset + rows, items);
switch(true) {
case !g_metadb:
case username.length == 0:
case api_key.length != 32:
return;
//case lastfm_type == 0 && link == "spotify" && in_range && x > 6 && x < 26:
// tt('spotify:search:"' + names[index].replace(/\s+/g,"+") + '"');
// window.SetCursor(IDC_HAND);
// break;
// case lastfm_type == 0 && link == "lastfm" && in_range && x > 6 && x < 26:
// tt("Last.fm radio: " + names[index]);
// window.SetCursor(IDC_HAND);
// break;
// case lastfm_type == 0 && link == "auto" && in_range && x > 6 && x < 26:
// tt("Autoplaylist: " + names[index]);
// window.SetCursor(IDC_HAND);
// break;
//text_x, 32, ww - 36, 18,
case y > 32 && y < 50 && x > text_x && x < text_x + all_width:
//tt(urls[index]);
tt("Autoplaylist: Everything");
window.SetCursor(IDC_HAND);
break;
case in_range && x > text_x && x < text_x + names_widths[index]:
//tt(urls[index]);
tt("Autoplaylist: " + names[index]);
window.SetCursor(IDC_HAND);
break;
case up_btn.trace(x, y):
case down_btn.trace(x, y):
window.SetCursor(IDC_HAND);
break;
default:
window.SetCursor(IDC_ARROW);
g_tooltip.Text = "";
g_tooltip.Deactivate();
break;
}
}
function on_mouse_lbtn_up(x, y) {
switch(true) {
case !g_metadb:
case username.length == 0:
case api_key.length != 32:
return;
// case lastfm_type == 0 && link == "spotify" && in_range && x > 6 && x < 26:
// try {
// WshShell.run('spotify:search:"' + names[index].replace(/\s+/g,"+") + '"');
// if (fb.IsPlaying && !fb.IsPaused && pause) fb.Pause();
// } catch(e) {
// MsgBox("Unable to launch Spotify.", 0, script_name);
// }
// break;
// case lastfm_type == 0 && link == "lastfm" && in_range && x > 6 && x < 26:
// if (!utils.CheckComponent("foo_lastfm_radio", true)) return(MsgBox("foo_lastfm_radio is not installed.", 0, script_name));
// try { WshShell.run("lastfm://artist/" + names[index].replace(/\s+/g,"+") + "/similarartists"); } catch(e) { MsgBox('Unable to launch last.fm radio. Check foobar is set as the default handler for the lastfm:// protocol. Use the "Manage file type associations" tool found under File>Preferences>Shell Integration.', 0, script_name); }
// break;
// case lastfm_type == 0 && link == "auto" && in_range && x > 6 && x < 26:
// fb.CreateAutoPlaylist(fb.PlaylistCount, names[index], "artist HAS " + names[index]);
// fb.ActivePlaylist = fb.PlaylistCount - 1;
// break;
case y > 32 && y < 50 && x > text_x && x < text_x + all_width:
playlist_name = "#Search";
i = 0;
while(i < fb.PlaylistCount) {
if (fb.GetPlaylistName(i) == playlist_name) fb.RemovePlaylist(i);
else i++;
}
switch(true) {
case lastfm_type == 0:
var auto_search = "artist IS " + names[0];
for (i = 1; i < items; i++) {
auto_search += " OR artist IS " + names[i];
}
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, auto_search);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 1:
var auto_search = "genre IS " + names[0] + " OR style IS " + names[0];
for (i = 1; i < items; i++) {
auto_search += " OR genre IS " + names[i] + " OR style IS " + names[i];
}
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, auto_search);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 2:
try { WshShell.run(urls[0]); } catch(e) { MsgBox("Unable to launch your default browser.", 0, script_name); }
break;
case lastfm_type == 3:
var auto_search = "(album IS " + names[0];
for (i = 1; i < items; i++) {
auto_search += " OR album IS " + names[i];
}
auto_search += ") AND artist IS " + artist;
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, auto_search);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 4:
var auto_search = "(title IS " + names[0];
for (i = 1; i < items; i++) {
auto_search += " OR title IS " + names[i];
}
auto_search += ") AND artist IS " + artist;
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, auto_search);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
}
break;
case in_range && x > text_x && x < text_x + names_widths[index]:
//try { WshShell.run(urls[index]); } catch(e) { MsgBox("Unable to launch your default browser.", 0, script_name); }
//break;
playlist_name = "#Search";
i = 0;
while(i < fb.PlaylistCount) {
if (fb.GetPlaylistName(i) == playlist_name) fb.RemovePlaylist(i);
else i++;
}
switch(true) {
case lastfm_type == 0:
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, "artist HAS " + names[index]);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 1:
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, "genre HAS " + names[index] + " OR style HAS " + names[index]);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 2:
try { WshShell.run(urls[index]); } catch(e) { MsgBox("Unable to launch your default browser.", 0, script_name); }
break;
case lastfm_type == 3:
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, "album HAS " + names[index] + " AND artist IS " + artist);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
case lastfm_type == 4:
fb.CreateAutoPlaylist(fb.PlaylistCount, playlist_name, "title HAS " + names[index] + " AND artist IS " + artist);
fb.ActivePlaylist = fb.PlaylistCount - 1;
break;
}
break;
case up_btn.trace(x, y):
up_btn.click(x, y);
break;
case down_btn.trace(x, y):
down_btn.click(x, y);
break;
}
}
function on_mouse_rbtn_up(x, y) {
var _menu = window.CreatePopupMenu();
var _links = window.CreatePopupMenu();
var _selection = window.CreatePopupMenu();
var _panel = window.CreatePopupMenu();
var idx;
_menu.AppendMenuItem(username.length > 0 && api_key.length == 32 && g_metadb ? MF_STRING : MF_GRAYED, 1, "Update");
_menu.AppendMenuSeparator();
_menu.AppendMenuItem(MF_STRING, 8, "Artist field remapping...");
_menu.AppendMenuSeparator();
for (i = 0; i < nice_lastfm_types.length; i++) {
_panel.AppendMenuItem(MF_STRING, 30 + i, nice_lastfm_types[i]);
}
_panel.CheckMenuRadioItem(30, 34, lastfm_type + 30);
_panel.AppendTo(_menu, MF_STRING, "Panel");
_menu.AppendMenuSeparator();
if(lastfm_type == 0) {
_menu.AppendMenuItem(link == "spotify" ? MF_STRING : MF_GRAYED, 7, "Pause playback when launching Spotify");
_menu.CheckMenuItem(7, pause);
_menu.AppendMenuSeparator();
_links.AppendMenuItem(MF_STRING, 4, "Spotify");
_links.AppendMenuItem(MF_STRING, 5, "Last.fm radio");
_links.AppendMenuItem(MF_STRING, 6, "Autoplaylist");
_links.CheckMenuRadioItem(4, 6, link == "spotify" ? 4 : link == "lastfm" ? 5 : 6);
_links.AppendTo(_menu, MF_STRING, "Buttons");
_menu.AppendMenuSeparator();
}
_selection.AppendMenuItem(MF_STRING, 900, "Use display preferences");
_selection.AppendMenuItem(MF_STRING, 901, "Prefer now playing");
_selection.AppendMenuItem(MF_STRING, 902, "Follow selected track");
_selection.CheckMenuRadioItem(900, 903, selection_mode + 900);
_selection.AppendTo(_menu, MF_STRING, "Selection mode");
_menu.AppendMenuSeparator();
_menu.AppendMenuItem(MF_STRING, 2, "Set your Last.fm username...");
_menu.AppendMenuItem(MF_STRING, 3, "Set your API KEY...");
_menu.AppendMenuSeparator();
if (utils.IsKeyPressed(0x10)) _menu.AppendMenuItem(MF_STRING, 9, "Properties");
_menu.AppendMenuItem(MF_STRING, 10, "Configure...");
idx = _menu.TrackPopupMenu(x, y);
switch(idx) {
case 1:
get();
break;
case 2:
set_username();
artist = Date();
on_item_focus_change();
break;
case 3:
set_api_key();
artist = Date();
on_item_focus_change();
break;
case 4:
case 5:
case 6:
link = idx == 4 ? "spotify" : idx == 5 ? "lastfm" : "auto";
window.SetProperty("link", link);
window.Repaint();
break;
case 8:
lastfm_artist = InputBox("Enter a tag that should be used to query Last.fm. The default is %artist%\n\nYou can use full foobar title formatting syntax to make it conditional.", script_name, lastfm_artist);
if (lastfm_artist == "") lastfm_artist = "%artist%";
window.SetProperty("lastfm_artist", lastfm_artist);
on_item_focus_change();
break;
case 7:
pause = !pause;
window.SetProperty("pause", pause);
break;
case 9:
window.ShowProperties();
break;
case 10:
window.ShowConfigure();
break;
case 30:
case 31:
case 32:
case 33:
case 34:
lastfm_type = idx - 30;
window.SetProperty("lastfm_type", lastfm_type);
artist = Date();
on_item_focus_change();
break;
case 900:
case 901:
case 902:
selection_mode = idx - 900;
window.SetProperty("selection_mode", selection_mode);
on_item_focus_change();
break;
}
_panel.Dispose();
_selection.Dispose();
_menu.Dispose();
_links.Dispose();
return true;
}