// ==PREPROCESSOR==
// @import "%fb2k_path%scripts\marc2003\common.js"
// @import "%fb2k_path%scripts\marc2003\tooltip_buttons.js"
// @name "Playcount Sync (file tags)"
// @author "marc2003"
// ==/PREPROCESSOR==
var playcount_tag_name = "LASTFM_PLAYCOUNT";
var loved_tag_name = "LASTFM_LOVED";
var bw = 32;
var bh = 32;
var top_margin = 0;
var left_margin = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var panel_id = window.GetProperty("panel_id", window.id);
var custom_background_file = settings_path + panel_id + "buttons_background";
var custom_background = read(custom_background_file);
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 autolove_file = settings_path + "autolove";
var autolove = read(autolove_file);
window.GetProperty("auto_correct", true);
if(!g_metadb) Buttons = { but: new Button(left_margin,top_margin, bw, bh, {normal: images_path + "exclamation.png"}, null, "No selection") };
on_item_focus_change();
if(fb.IsPlaying) on_playback_new_track();
function on_notify_data(name, data) {
if(name == "lastfm_update" && data == 1) {
username = read(username_file);
api_key = read(api_key_file);
on_metadb_changed();
}
}
function on_metadb_changed() {
if(!g_metadb) return;
artist = fb.TitleFormat("%artist%").EvalWithMetadb(g_metadb);
track = fb.TitleFormat("%title%").EvalWithMetadb(g_metadb);
old_userloved = fb.TitleFormat("%" + loved_tag_name +"%").EvalWithMetadb(g_metadb) ==1 ? 1 : 0;
old_userplaycount = fb.TitleFormat("%" + playcount_tag_name + "%").EvalWithMetadb(g_metadb);
command = "Last.fm " + (old_userloved == 1 ? "Unlove" : "Love") + " Track '" + track + "' by '"+ artist + "'";
update_button();
}
function update_button() {
switch(true) {
case (username.length == 0):
case (api_key.length != 32):
n = "exclamation.png";
h = "exclamation.png";
tooltip = "Please use the context menu to set your Last.fm username and API KEY.";
func = null;
break;
case (!utils.CheckComponent("foo_softplaylists", true)):
n = "exclamation.png";
h = "exclamation.png";
tooltip = "The foo_softplaylists component is required to love tracks.";
func = null;
break;
default:
n = old_userloved == 1 ? "love_h.png" : "love.png";
h = old_userloved == 1 ? "love.png" : "love_h.png";
tooltip = command;
func = function() {lfm_track();}
break;
}
Buttons = {
but: new Button(left_margin,top_margin, bw, bh, {normal: images_path + n, hover: images_path + h}, func, tooltip)
};
window.Repaint();
}
function on_playback_new_track() {
on_item_focus_change();
time_elapsed = 0;
file_is_valid = true;
target_time = 10;
}
function on_playback_time(time) {
time_elapsed++;
if(time_elapsed == 1) {
switch(true) {
case (g_metadb.RawPath.indexOf("file://") != 0 || fb.PlaybackLength < 30 || fb.PlaybackLength > 10800 || g_metadb.Path.substring(g_metadb.Path.length - 3) == "cue"):
file_is_valid = false;
target_time = 5;
break;
case (fb.PlaybackLength == 0):
target_time = 10;
break;
case (fb.PlaybackLength >= 30):
target_time = Math.min(Math.floor(fb.PlaybackLength / 2),10);
break;
default:
target_time = 5;
}
}
if(time_elapsed == target_time) sync();
}
function lfm_track() {
fb.RunContextCommandWithMetadb(command, g_metadb);
sync();
}
function sync() {
if(username.length == 0 || api_key.length != 32) return(fb.trace("Playcount sync: Can't contact Last.fm. Check your username / API KEY settings."));
fb.trace("Playcount sync: Contacting Last.fm....");
lastfm("&method=track.getinfo&artist=" + encodeURIComponent(artist) + "&track=" + encodeURIComponent(track) + "&autocorrect=" + (window.GetProperty("auto_correct") ? 1 : 0), "foo_playcount_sync", function() {process();});
}
function process() {
fb.trace("Playcount sync: Last.fm responded 'OK'");
xmlDoc = xmlhttp.responseXML;
try { userplaycount = ++xmlDoc.getElementsByTagName("userplaycount")[0].childNodes[0].nodeValue; } catch(e) { userplaycount = fb.PlaybackLength < 30 ? 0 : 1;}
try { userloved = xmlDoc.getElementsByTagName("userloved")[0].childNodes[0].nodeValue; } catch(e) { userloved = 0; }
if(file_is_valid) {
if(fb.IsPlaying && time_elapsed >= target_time)
fb.trace("Old value: " + old_userplaycount);
fb.trace("New value: " + userplaycount);
if(fb.TitleFormat(autolove).Eval() == 1 && old_userloved == 0) {
fb.trace("Playcount Sync: Automatically loving this track....");
lfm_track();
}
// PREVENT LOWER VALUE FROM LAST.FM
if (old_userplaycount > userplaycount ) {
fb.trace("Last.fm playcount is lower, not updating tags!");
}
else { update_tag(playcount_tag_name,old_userplaycount,userplaycount); //ORIG
}
update_tag(loved_tag_name,old_userloved,userloved);
} else {
fb.trace("Can't write tags to this file! Possible reasons: too long, too short, it's a stream, it references an external cue sheet.");
old_userloved = userloved == 1 ? 1: 0;
update_button();
}
}
function update_tag(tag, o, n) {
if(o == "?") {o = 0;}
if(o != n) {
fb.trace("Playcount sync: Updating " + tag + " " + o + " > " + n);
g_metadb.UpdateFileInfoSimple(tag, n != 0 ? n : '');
} else {
fb.trace("Playcount sync: Not updating " + tag + ". No changes found.")
}
}
function on_size() {
ww = window.Width;
wh = window.Height;
}
function on_mouse_rbtn_up(x, y) {
var _menu = window.CreatePopupMenu();
var _au = window.CreatePopupMenu();
var _child = window.CreatePopupMenu();
var _auto = window.CreatePopupMenu();
var idx;
_au.AppendMenuItem(MF_STRING, 6, "Use spelling correction");
_au.CheckMenuItem(6, window.GetProperty("auto_correct"));
_menu.AppendMenuItem(MF_STRING | MF_POPUP, _au.ID, "Auto-updates");
_child.AppendMenuItem(MF_STRING, 101, "None");
_child.AppendMenuItem(MF_STRING, 102, (dui ? "Default UI " : "Columns UI ") + "default");
_child.AppendMenuItem(MF_STRING, 103, "Splitter");
_child.AppendMenuItem(MF_STRING, 104, "Custom ");
_child.AppendMenuItem(MF_SEPARATOR, 0, 0);
_child.AppendMenuItem(window.GetProperty("mode") == 104 ? MF_STRING : MF_GRAYED, 105, "Set custom colour...");
_child.CheckMenuRadioItem(101, 104, window.GetProperty("mode", 101));
_menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
_auto.AppendMenuItem(window.GetProperty("auto_menu") ? MF_STRING : MF_STRING, 202, "Condition");
_auto.CheckMenuRadioItem(200, 201, window.GetProperty("auto_menu") ? 201 : 200);
_menu.AppendMenuItem(MF_STRING | MF_POPUP, _auto.ID, "Automatically love tracks");
_menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
_menu.AppendMenuItem(MF_STRING, 2, "Set your Last.fm username...");
_menu.AppendMenuItem(MF_STRING, 3, "Set your API KEY...");
_menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
_menu.AppendMenuItem(username.length > 0 ? MF_STRING : MF_GRAYED, 1, "Visit your Last.fm user profile page");
_menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
_menu.AppendMenuItem(MF_STRING | MF_POPUP, _child.ID, "Background");
_menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
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:
try {
WshShell.run("http://www.last.fm/user/" + encodeURIComponent(username));
} catch(e) {
fb.ShowPopupMessage("Unable to launch your default browser.", "Playcount Sync");
}
break;
case 2:
username = text_input_box("Playcount Sync", "Please enter your Last.fm username", username_file);
on_metadb_changed();
window.NotifyOthers("lastfm_update", 1);
break;
case 3:
api_key = text_input_box("Playcount Sync", "Please enter your Last.fm API KEY\n\nhttp://www.last.fm/api/account", api_key_file);
on_metadb_changed();
window.NotifyOthers("lastfm_update", 1);
break;
case 6:
window.SetProperty("auto_correct", !window.GetProperty("auto_correct"));
break;
case 7:
window.SetProperty("debug", !window.GetProperty("debug"));
break;
case 101:
case 102:
case 103:
case 104:
window.SetProperty("mode", idx);
window.Repaint();
break;
case 105:
custom_background = text_input_box("Playcount Sync", "Enter a custom colour for the background. Uses RGB. Example usage:\n\n234-211-74", custom_background_file);
window.Repaint();
break;
case 201:
window.SetProperty("auto_menu", idx == 200 ? false : true);
break;
case 202:
autolove = text_input_box("Playcount Sync", "The result of the title formatting set here must equal 1 for a track to be automatically loved.\n\nExample:\n\n$ifequal(%rating%,5,1,0)", autolove_file);
break;
case 9:
window.ShowProperties();
break;
case 10:
window.ShowConfigure();
break;
}
_menu.Dispose();
_auto.Dispose();
_au.Dispose();
_child.Dispose();
return true;
}
function on_paint(gr) {
buttons_background(gr);
buttonsDraw(gr);
}