247 lines
8.7 KiB
JavaScript
247 lines
8.7 KiB
JavaScript
|
function faveFinder(returnall) {
|
||
|
|
||
|
// faveFinder is used to find tracks which have just been tagged or rated but don't have a URI.
|
||
|
// These would be tracks from a radio station. It's also used by lastFMImporter.
|
||
|
var self = this;
|
||
|
var queue = new Array();
|
||
|
var throttle = null;
|
||
|
var priority = [];
|
||
|
var checkdb = true;
|
||
|
var exact = false;
|
||
|
|
||
|
// Prioritize - local, beetslocal, beets, spotify, gmusic - in that order
|
||
|
// There's currently no way to change these for tracks that are rated from radio stations
|
||
|
// which means that these are the only domains that will be searched, but this is better
|
||
|
// than including podcasts and radio stations, which we'll never want
|
||
|
|
||
|
// I'm also not including SoundCloud because it produces far too many false positives
|
||
|
|
||
|
if (prefs.player_backend == 'mopidy') {
|
||
|
priority = ["gmusic", "spotify", "beets", "beetslocal", "local"];
|
||
|
}
|
||
|
|
||
|
function brk(b) {
|
||
|
if (b) {
|
||
|
return '<br />';
|
||
|
} else {
|
||
|
return ' ';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getImageUrl(list) {
|
||
|
var im = null;
|
||
|
for (var i in list) {
|
||
|
if (list[i] != "") {
|
||
|
im = list[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (im && im.substr(0,4) == "http") {
|
||
|
im = "getRemoteImage.php?url="+im;
|
||
|
}
|
||
|
return im;
|
||
|
}
|
||
|
|
||
|
function compare_tracks(lookingfor, found) {
|
||
|
if (found.title == null) {
|
||
|
return false;
|
||
|
} else if (lookingfor.title == null || lookingfor.title.removePunctuation().toLowerCase() == found.title.removePunctuation().toLowerCase()) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function compare_tracks_with_artist(lookingfor, found) {
|
||
|
if (lookingfor.title !== null && lookingfor.artist !== null) {
|
||
|
if (lookingfor.title.removePunctuation().toLowerCase() == found.title.removePunctuation().toLowerCase() &&
|
||
|
lookingfor.artist.removePunctuation().toLowerCase() == found.artist.removePunctuation().toLowerCase()) {
|
||
|
return true;
|
||
|
}
|
||
|
} else if (lookingfor.title === null) {
|
||
|
if (lookingfor.artist.removePunctuation().toLowerCase() == found.artist.removePunctuation().toLowerCase()) {
|
||
|
return true;
|
||
|
}
|
||
|
} else if (lookingfor.artist === null) {
|
||
|
if (lookingfor.title.removePunctuation().toLowerCase() == found.title.removePunctuation().toLowerCase()) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function foundNothing(req) {
|
||
|
debug.log("FAVEFINDER","Nothing found",req);
|
||
|
if (returnall) {
|
||
|
req.callback([req.data]);
|
||
|
} else {
|
||
|
req.callback(req.data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.getPriorities = function() {
|
||
|
return priority.reverse();
|
||
|
}
|
||
|
|
||
|
this.setPriorities = function(p) {
|
||
|
priority = p;
|
||
|
debug.log("FAVEFINDER","Domains We Will Search",priority);
|
||
|
}
|
||
|
|
||
|
this.queueLength = function() {
|
||
|
return queue.length;
|
||
|
}
|
||
|
|
||
|
this.handleResults = function(data) {
|
||
|
|
||
|
if (queue.length == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
var req = queue[0];
|
||
|
debug.trace("FAVEFINDER","Raw Results for",req,data);
|
||
|
|
||
|
var results = new Array();
|
||
|
var best_matches = new Array();
|
||
|
var medium_matches = new Array();
|
||
|
var worst_matches = new Array();
|
||
|
// Sort the results
|
||
|
for (var i in data) {
|
||
|
if (data[i].tracks) {
|
||
|
for (var k = 0; k < data[i].tracks.length; k++) {
|
||
|
if (data[i].tracks[k].uri.isArtistOrAlbum()) {
|
||
|
debug.trace("FAVEFINDER", "Ignoring non-track ",data[i].tracks[k].uri);
|
||
|
} else {
|
||
|
debug.trace("FAVEFINDER","Found Track",data[i].tracks[k]);
|
||
|
var r = cloneObject(req);
|
||
|
for (var g in data[i].tracks[k]) {
|
||
|
r.data[g] = data[i].tracks[k][g];
|
||
|
}
|
||
|
|
||
|
if (r.data.title == null && r.data.artist == null) {
|
||
|
|
||
|
} else {
|
||
|
if (r.data.albumartist != "Various Artists") {
|
||
|
if (compare_tracks_with_artist(req.data, r.data)) {
|
||
|
// Exactly matching track and artist are preferred...
|
||
|
best_matches.push(r.data);
|
||
|
} else if (compare_tracks(req.data, r.data)) {
|
||
|
// .. over matching track title only ...
|
||
|
medium_matches.push(r.data);
|
||
|
} else {
|
||
|
// .. over non-matching track titles ..
|
||
|
worst_matches.unshift(r.data);
|
||
|
}
|
||
|
} else {
|
||
|
// .. and compilation albums ..
|
||
|
worst_matches.push(r.data);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
results = results.concat(best_matches, medium_matches, worst_matches);
|
||
|
debug.debug("FAVEFINDER","Prioritised Results are",results);
|
||
|
if (results.length == 0) {
|
||
|
foundNothing(req);
|
||
|
} else {
|
||
|
if (returnall) {
|
||
|
req.callback(results);
|
||
|
} else {
|
||
|
var f = false;
|
||
|
for (var i in results) {
|
||
|
if (results.length == 1 || compare_tracks_with_artist(req.data, results[i])) {
|
||
|
for (var g in results[i]) {
|
||
|
req.data[g] = results[i][g];
|
||
|
}
|
||
|
f = true;
|
||
|
req.callback(req.data);
|
||
|
debug.log("FAVEFINDER","Single track asked for, returning",req.data);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!f) {
|
||
|
foundNothing(req);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
throttle = setTimeout(self.next, 1000);
|
||
|
queue.shift();
|
||
|
}
|
||
|
|
||
|
this.findThisOne = function(data, callback) {
|
||
|
debug.log("FAVEFINDER","New thing to look for",data);
|
||
|
queue.push({data: data, callback: callback});
|
||
|
if (throttle == null && queue.length == 1) {
|
||
|
self.next();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.next = function() {
|
||
|
var req = queue[0];
|
||
|
clearTimeout(throttle);
|
||
|
if (req) {
|
||
|
self.searchForTrack();
|
||
|
} else {
|
||
|
throttle = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.stop = function() {
|
||
|
clearTimeout(throttle)
|
||
|
queue = new Array();
|
||
|
}
|
||
|
|
||
|
this.searchForTrack = function() {
|
||
|
var req = queue[0];
|
||
|
var st = {};
|
||
|
if (req.data.title) {
|
||
|
st.title = [req.data.title];
|
||
|
}
|
||
|
if (req.data.artist) {
|
||
|
st.artist = [req.data.artist];
|
||
|
}
|
||
|
if (req.data.album) {
|
||
|
st.album = [req.data.album];
|
||
|
}
|
||
|
debug.log("FAVEFINDER","Performing search",st,priority);
|
||
|
player.controller.rawsearch(st, priority, exact, self.handleResults, checkdb);
|
||
|
}
|
||
|
|
||
|
this.trackHtml = function(data, breaks) {
|
||
|
var html = "";
|
||
|
// html += '<i class="icon-no-response-playbutton clickicon playable collectionicon" name="'+data.uri+'"></i>';
|
||
|
var u = data.uri;
|
||
|
if (u.match(/spotify:/)) {
|
||
|
html += '<i class="icon-spotify-circled collectionicon"></i>';
|
||
|
} else if (u.match(/soundcloud:/)) {
|
||
|
html += '<i class="icon-soundcloud-circled collectionicon"></i>';
|
||
|
} else if (u.match(/youtube:/)) {
|
||
|
html += '<i class="icon-youtube-circled collectionicon"></i>';
|
||
|
} else if (u.match(/gmusic:/)) {
|
||
|
html += '<i class="icon-gmusic-circled collectionicon"></i>';
|
||
|
} else if (u.match(/^podcast/)) {
|
||
|
html += '<i class="icon-podcast-circled collectionicon"></i>';
|
||
|
}
|
||
|
html += '<b>'+data.title+'</b>'+brk(breaks);
|
||
|
if (data.artist) {
|
||
|
html += '<i>by </i>'+data.artist+brk(breaks);
|
||
|
}
|
||
|
html += '<i>on </i>'+data.album;
|
||
|
var arse = data.uri;
|
||
|
if (arse.indexOf(":") > 0) {
|
||
|
html += ' <i>(' + arse.substr(0, arse.indexOf(":")) + ')</i>';
|
||
|
}
|
||
|
return html;
|
||
|
}
|
||
|
|
||
|
this.setCheckDb = function(d) {
|
||
|
checkdb = d;
|
||
|
}
|
||
|
|
||
|
this.setExact = function(e) {
|
||
|
exact = e;
|
||
|
}
|
||
|
|
||
|
}
|