mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 03:10:12 +02:00
Merge pull request #326 from theli-ua/api
First attempt at 0.9 js resolver API
This commit is contained in:
@@ -231,6 +231,9 @@ var TomahawkResolver = {
|
|||||||
collection: function () {
|
collection: function () {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
getStreamUrl: function(params) {
|
||||||
|
Tomahawk.reportStreamUrl(params.qid, params.url);
|
||||||
|
},
|
||||||
_testConfig: function (config) {
|
_testConfig: function (config) {
|
||||||
return Promise.resolve(this.testConfig(config)).then(function() {
|
return Promise.resolve(this.testConfig(config)).then(function() {
|
||||||
return { result: Tomahawk.ConfigTestResultType.Success };
|
return { result: Tomahawk.ConfigTestResultType.Success };
|
||||||
@@ -240,25 +243,85 @@ var TomahawkResolver = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Tomahawk.Resolver = {};
|
|
||||||
Tomahawk.Resolver.Promise = Tomahawk.extend(TomahawkResolver, {
|
Tomahawk.Resolver = Tomahawk.extend(TomahawkResolver, {
|
||||||
|
saveUserConfig: function () {
|
||||||
|
window.localStorage[this.scriptPath()] = JSON.stringify(Tomahawk.resolverData().config);
|
||||||
|
this.newConfigSaved(Tomahawk.resolverData().config);
|
||||||
|
},
|
||||||
|
|
||||||
|
_convertUrls: function(results) {
|
||||||
|
var that = this;
|
||||||
|
return results.map(function(r){
|
||||||
|
if(r && r.url) {
|
||||||
|
r.url = that._urlProtocol + '://' + r.url;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
_adapter_resolve: function (qid, artist, album, title) {
|
_adapter_resolve: function (qid, artist, album, title) {
|
||||||
Promise.resolve(this.resolve(artist, album, title)).then(function(results){
|
var that = this;
|
||||||
Tomahawk.addTrackResults({
|
var collectionPromises = [];
|
||||||
'qid': qid,
|
Tomahawk.collections.forEach(function(col) {
|
||||||
'results': results
|
if(col.resolve)
|
||||||
|
collectionPromises.push(col.resolve({artist: artist, album: album, track:title}));
|
||||||
|
});
|
||||||
|
Promise.all(collectionPromises).then(function(collectionResults){
|
||||||
|
var merged = [];
|
||||||
|
return merged.concat.apply(merged,collectionResults);
|
||||||
|
}).then(function(collectionResults) {
|
||||||
|
Promise.resolve(that.resolve({artist: artist, album: album, track:title})).then(function(results){
|
||||||
|
Tomahawk.addTrackResults({
|
||||||
|
'qid': qid,
|
||||||
|
'results': that._convertUrls(results.concat(collectionResults))
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_adapter_init: function ()
|
||||||
|
{
|
||||||
|
this._urlProtocol = this.settings.name.replace(/[^a-zA-Z]/g, '').toLowerCase();
|
||||||
|
Tomahawk.addCustomUrlHandler( this._urlProtocol, 'getStreamUrl', true );
|
||||||
|
Tomahawk.log('Registered custom url handler for protocol "' + this._urlProtocol + '"');
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
|
||||||
|
_adapter_getStreamUrl: function (params) {
|
||||||
|
params.url = params.url.slice(this._urlProtocol.length + 3);
|
||||||
|
Promise.resolve(this.getStreamUrl(params)).then(function(result){
|
||||||
|
Tomahawk.reportStreamUrl(params.qid, result.url, result.headers);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
_adapter_search: function (qid, query)
|
_adapter_search: function (qid, query)
|
||||||
{
|
{
|
||||||
Promise.resolve(this.search(query)).then(function(results){
|
var that = this;
|
||||||
Tomahawk.addTrackResults({
|
var collectionPromises = [];
|
||||||
'qid': qid,
|
Tomahawk.collections.forEach(function(col) {
|
||||||
'results': results
|
if(col.search)
|
||||||
|
collectionPromises.push(col.search({query: query}));
|
||||||
|
});
|
||||||
|
Promise.all(collectionPromises).then(function(collectionResults){
|
||||||
|
var merged = [];
|
||||||
|
return merged.concat.apply(merged,collectionResults);
|
||||||
|
}).then(function(collectionResults) {
|
||||||
|
Promise.resolve(that.search({query:query})).then(function(results){
|
||||||
|
Tomahawk.log(JSON.stringify(results));
|
||||||
|
Tomahawk.log(JSON.stringify(collectionResults));
|
||||||
|
Tomahawk.addTrackResults({
|
||||||
|
'qid': qid,
|
||||||
|
'results': that._convertUrls(results.concat(collectionResults))
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_adapter_testConfig: function (config) {
|
||||||
|
return Promise.resolve(this.testConfig(config)).then(function() {
|
||||||
|
return { result: Tomahawk.ConfigTestResultType.Success };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -561,6 +624,9 @@ Tomahawk.ajax = function(url, settings) {
|
|||||||
settings.errorHandler = reject;
|
settings.errorHandler = reject;
|
||||||
Tomahawk.asyncRequest(settings.url, resolve, settings.headers, settings);
|
Tomahawk.asyncRequest(settings.url, resolve, settings.headers, settings);
|
||||||
}).then(function(xhr) {
|
}).then(function(xhr) {
|
||||||
|
if (settings.rawResponse) {
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
var responseText = xhr.responseText;
|
var responseText = xhr.responseText;
|
||||||
var contentType;
|
var contentType;
|
||||||
if (settings.dataType === 'json') {
|
if (settings.dataType === 'json') {
|
||||||
@@ -742,9 +808,15 @@ Tomahawk.removeDiacritics = function (str) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Tomahawk.localStorage = Tomahawk.localStorage || {
|
Tomahawk.localStorage = Tomahawk.localStorage || {
|
||||||
setItem: function() {},
|
setItem: function(key, value) {
|
||||||
getItem: function() {},
|
window.localStorage[key] = value;
|
||||||
removeItem: function() {}
|
},
|
||||||
|
getItem: function(key) {
|
||||||
|
return window.localStorage[key];
|
||||||
|
},
|
||||||
|
removeItem: function(key) {
|
||||||
|
delete window.localStorage[key];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// some aliases
|
// some aliases
|
||||||
@@ -765,6 +837,10 @@ Tomahawk.PluginManager = {
|
|||||||
},
|
},
|
||||||
registerPlugin: function (type, object) {
|
registerPlugin: function (type, object) {
|
||||||
this.objects[this.identifyObject(object)] = object;
|
this.objects[this.identifyObject(object)] = object;
|
||||||
|
if (type === 'collection')
|
||||||
|
{
|
||||||
|
Tomahawk.collections.push(object);
|
||||||
|
}
|
||||||
|
|
||||||
Tomahawk.log("registerPlugin: " + type + " id: " + object.id);
|
Tomahawk.log("registerPlugin: " + type + " id: " + object.id);
|
||||||
Tomahawk.registerScriptPlugin(type, object.id);
|
Tomahawk.registerScriptPlugin(type, object.id);
|
||||||
@@ -779,6 +855,9 @@ Tomahawk.PluginManager = {
|
|||||||
|
|
||||||
resolve: [],
|
resolve: [],
|
||||||
invokeSync: function (requestId, objectId, methodName, params) {
|
invokeSync: function (requestId, objectId, methodName, params) {
|
||||||
|
Tomahawk.log('invokeSync ' + methodName);
|
||||||
|
Tomahawk.log('invokeSync params ' + JSON.stringify(params));
|
||||||
|
Tomahawk.log(Tomahawk.resolver.instance.appVersion);
|
||||||
if (!Tomahawk.resolver.instance.apiVersion || Tomahawk.resolver.instance.apiVersion < 0.9) {
|
if (!Tomahawk.resolver.instance.apiVersion || Tomahawk.resolver.instance.apiVersion < 0.9) {
|
||||||
if (methodName === 'artistAlbums') {
|
if (methodName === 'artistAlbums') {
|
||||||
methodName = 'albums';
|
methodName = 'albums';
|
||||||
@@ -816,6 +895,8 @@ Tomahawk.PluginManager = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tomahawk.log(methodName);
|
||||||
|
Tomahawk.log(JSON.stringify(params));
|
||||||
return this.objects[objectId][methodName](params);
|
return this.objects[objectId][methodName](params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,6 +904,8 @@ Tomahawk.PluginManager = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
invoke: function (requestId, objectId, methodName, params ) {
|
invoke: function (requestId, objectId, methodName, params ) {
|
||||||
|
Tomahawk.log('invoke ' + methodName);
|
||||||
|
Tomahawk.log('invoke params ' + JSON.stringify(params));
|
||||||
Promise.resolve(this.invokeSync(requestId, objectId, methodName, params)).then(function (result) {
|
Promise.resolve(this.invokeSync(requestId, objectId, methodName, params)).then(function (result) {
|
||||||
if (typeof result === 'object') {
|
if (typeof result === 'object') {
|
||||||
Tomahawk.reportScriptJobResults({
|
Tomahawk.reportScriptJobResults({
|
||||||
@@ -1106,11 +1189,671 @@ Tomahawk.Country = {
|
|||||||
LatinAmericaAndTheCaribbean: 246
|
LatinAmericaAndTheCaribbean: 246
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Tomahawk.collections = [];
|
||||||
|
|
||||||
Tomahawk.Collection = {
|
Tomahawk.Collection = {
|
||||||
BrowseCapability: {
|
BrowseCapability: {
|
||||||
Artists: 1,
|
Artists: 1,
|
||||||
Albums: 2,
|
Albums: 2,
|
||||||
Tracks: 4
|
Tracks: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
cachedDbs: {},
|
||||||
|
|
||||||
|
Transaction: function (collection, id) {
|
||||||
|
|
||||||
|
this.ensureDb = function () {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
return new RSVP.Promise(function (resolve, reject) {
|
||||||
|
if (!collection.cachedDbs.hasOwnProperty(id)) {
|
||||||
|
Tomahawk.log("Opening database");
|
||||||
|
var estimatedSize = 5 * 1024 * 1024; // 5MB
|
||||||
|
collection.cachedDbs[id] =
|
||||||
|
openDatabase(id + "_collection", "", "Collection", estimatedSize);
|
||||||
|
|
||||||
|
collection.cachedDbs[id].transaction(function (tx) {
|
||||||
|
Tomahawk.log("Creating initial db tables");
|
||||||
|
tx.executeSql("CREATE TABLE IF NOT EXISTS artists(" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
"artist TEXT ," +
|
||||||
|
"artistDisambiguation TEXT," +
|
||||||
|
"UNIQUE (artist, artistDisambiguation) ON CONFLICT IGNORE)", []);
|
||||||
|
tx.executeSql("CREATE TABLE IF NOT EXISTS albumArtists(" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
"albumArtist TEXT ," +
|
||||||
|
"albumArtistDisambiguation TEXT," +
|
||||||
|
"UNIQUE (albumArtist, albumArtistDisambiguation) ON CONFLICT IGNORE)",
|
||||||
|
[]);
|
||||||
|
tx.executeSql("CREATE TABLE IF NOT EXISTS albums(" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
"album TEXT," +
|
||||||
|
"albumArtistId INTEGER," +
|
||||||
|
"UNIQUE (album, albumArtistId) ON CONFLICT IGNORE," +
|
||||||
|
"FOREIGN KEY(albumArtistId) REFERENCES albumArtists(_id))", []);
|
||||||
|
tx.executeSql("CREATE TABLE IF NOT EXISTS artistAlbums(" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
"albumId INTEGER," +
|
||||||
|
"artistId INTEGER," +
|
||||||
|
"UNIQUE (albumId, artistId) ON CONFLICT IGNORE," +
|
||||||
|
"FOREIGN KEY(albumId) REFERENCES albums(_id)," +
|
||||||
|
"FOREIGN KEY(artistId) REFERENCES artists(_id))", []);
|
||||||
|
tx.executeSql("CREATE TABLE IF NOT EXISTS tracks(" +
|
||||||
|
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
"track TEXT," +
|
||||||
|
"artistId INTEGER," +
|
||||||
|
"albumId INTEGER," +
|
||||||
|
"url TEXT," +
|
||||||
|
"duration INTEGER," +
|
||||||
|
"albumPos INTEGER," +
|
||||||
|
"linkUrl TEXT," +
|
||||||
|
'releaseyear INTEGER,' +
|
||||||
|
'bitrate INTEGER,' +
|
||||||
|
"UNIQUE (track, artistId, albumId) ON CONFLICT IGNORE," +
|
||||||
|
"FOREIGN KEY(artistId) REFERENCES artists(_id)," +
|
||||||
|
"FOREIGN KEY(albumId) REFERENCES albums(_id))", []);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
resolve(collection.cachedDbs[id]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.beginTransaction = function () {
|
||||||
|
var that = this;
|
||||||
|
return this.ensureDb().then(function (db) {
|
||||||
|
return new RSVP.Promise(function (resolve, reject) {
|
||||||
|
that.db = db;
|
||||||
|
that.statements = [];
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.execDefferedStatements = function (resolve, reject) {
|
||||||
|
var that = this;
|
||||||
|
that.stmtsToResolve = that.statements.length;
|
||||||
|
that.results = that.statements.slice();
|
||||||
|
Tomahawk.log('Executing ' + that.stmtsToResolve + ' deffered SQL statements in transaction');
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
if (that.statements.length == 0)
|
||||||
|
resolve([]);
|
||||||
|
else{
|
||||||
|
that.db.transaction(function (tx) {
|
||||||
|
for (var i = 0; i < that.statements.length; ++i)
|
||||||
|
{
|
||||||
|
var stmt = that.statements[i];
|
||||||
|
tx.executeSql(stmt.statement, stmt.args,
|
||||||
|
(function () {
|
||||||
|
//A function returning a function to
|
||||||
|
//capture value of i
|
||||||
|
var originalI = i;
|
||||||
|
return function (tx, results) {
|
||||||
|
if (typeof that.statements[originalI].map !== 'undefined')
|
||||||
|
{
|
||||||
|
var map = that.statements[originalI].map;
|
||||||
|
that.results[originalI] = [];
|
||||||
|
for (var ii = 0; ii < results.rows.length; ii++) {
|
||||||
|
that.results[originalI].push(map(
|
||||||
|
results.rows.item(ii)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
that.results[originalI] = results;
|
||||||
|
that.stmtsToResolve--;
|
||||||
|
if(that.stmtsToResolve == 0)
|
||||||
|
{
|
||||||
|
that.statements = [];
|
||||||
|
resolve(that.results);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(), function (tx, error) {
|
||||||
|
Tomahawk.log("Error in tx.executeSql: " + error.code + " - "
|
||||||
|
+ error.message);
|
||||||
|
that.statements = [];
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
this.sql = function (sqlStatement, sqlArgs, mapFunction) {
|
||||||
|
this.statements.push({statement: sqlStatement, args: sqlArgs, map: mapFunction});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sqlSelect = function (table, mapResults, fields, where, join) {
|
||||||
|
var whereKeys = [];
|
||||||
|
var whereValues = [];
|
||||||
|
for (var whereKey in where) {
|
||||||
|
if (where.hasOwnProperty(whereKey)) {
|
||||||
|
whereKeys.push(table + "." + whereKey + " = ?");
|
||||||
|
whereValues.push(where[whereKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var whereString = whereKeys.length > 0 ? " WHERE " + whereKeys.join(" AND ") : "";
|
||||||
|
|
||||||
|
var joinString = "";
|
||||||
|
for (var i = 0; join && i < join.length; i++) {
|
||||||
|
var joinConditions = [];
|
||||||
|
for (var joinKey in join[i].conditions) {
|
||||||
|
if (join[i].conditions.hasOwnProperty(joinKey)) {
|
||||||
|
joinConditions.push(table + "." + joinKey + " = " + join[i].table + "."
|
||||||
|
+ join[i].conditions[joinKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
joinString += " INNER JOIN " + join[i].table + " ON "
|
||||||
|
+ joinConditions.join(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldsString = fields && fields.length > 0 ? fields.join(", ") : "*";
|
||||||
|
var statement = "SELECT " + fieldsString + " FROM " + table + joinString + whereString;
|
||||||
|
return this.sql(statement, whereValues, mapResults);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sqlInsert = function (table, fields) {
|
||||||
|
var fieldsKeys = [];
|
||||||
|
var fieldsValues = [];
|
||||||
|
var valuesString = "";
|
||||||
|
for (var key in fields) {
|
||||||
|
fieldsKeys.push(key);
|
||||||
|
fieldsValues.push(fields[key]);
|
||||||
|
if (valuesString.length > 0) {
|
||||||
|
valuesString += ", ";
|
||||||
|
}
|
||||||
|
valuesString += "?";
|
||||||
|
}
|
||||||
|
var statement = "INSERT INTO " + table + " (" + fieldsKeys.join(", ") + ") VALUES ("
|
||||||
|
+ valuesString + ")";
|
||||||
|
return this.sql(statement, fieldsValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sqlDrop = function (table) {
|
||||||
|
var statement = "DROP TABLE IF EXISTS " + table;
|
||||||
|
return this.sql(statement, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
addTracks: function (params) {
|
||||||
|
var that = this;
|
||||||
|
var id = params.id;
|
||||||
|
var tracks = params.tracks;
|
||||||
|
|
||||||
|
var cachedAlbumArtists = {},
|
||||||
|
cachedArtists = {},
|
||||||
|
cachedAlbums = {},
|
||||||
|
cachedArtistIds = {},
|
||||||
|
cachedAlbumIds = {};
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
// First we insert all artists and albumArtists
|
||||||
|
t.sqlInsert("artists", {
|
||||||
|
artist: "Various Artists",
|
||||||
|
artistDisambiguation: ""
|
||||||
|
});
|
||||||
|
for (var i = 0; i < tracks.length; i++) {
|
||||||
|
tracks[i].track = tracks[i].track || "";
|
||||||
|
tracks[i].album = tracks[i].album || "";
|
||||||
|
tracks[i].artist = tracks[i].artist || "";
|
||||||
|
tracks[i].artistDisambiguation = tracks[i].artistDisambiguation || "";
|
||||||
|
tracks[i].albumArtist = tracks[i].albumArtist || "";
|
||||||
|
tracks[i].albumArtistDisambiguation = tracks[i].albumArtistDisambiguation || "";
|
||||||
|
(function (track) {
|
||||||
|
t.sqlInsert("artists", {
|
||||||
|
artist: track.artist,
|
||||||
|
artistDisambiguation: track.artistDisambiguation
|
||||||
|
});
|
||||||
|
t.sqlInsert("albumArtists", {
|
||||||
|
albumArtist: track.albumArtist,
|
||||||
|
albumArtistDisambiguation: track.albumArtistDisambiguation
|
||||||
|
});
|
||||||
|
})(tracks[i]);
|
||||||
|
}
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function () {
|
||||||
|
// Get all artists' and albumArtists' db ids
|
||||||
|
t.sqlSelect("albumArtists", function(r) {
|
||||||
|
return {
|
||||||
|
albumArtist: r.albumArtist,
|
||||||
|
albumArtistDisambiguation: r.albumArtistDisambiguation,
|
||||||
|
_id: r._id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.sqlSelect("artists", function(r) {
|
||||||
|
return {
|
||||||
|
artist: r.artist,
|
||||||
|
artistDisambiguation: r.artistDisambiguation,
|
||||||
|
_id: r._id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (resultsArray) {
|
||||||
|
// Store the db ids in a map
|
||||||
|
var i, row, albumArtists = {};
|
||||||
|
for (i = 0; i < resultsArray[0].length; i++) {
|
||||||
|
row = resultsArray[0][i];
|
||||||
|
albumArtists[row.albumArtist + "♣" + row.albumArtistDisambiguation] = row._id;
|
||||||
|
}
|
||||||
|
for (i = 0; i < resultsArray[1].length; i++) {
|
||||||
|
row = resultsArray[1][i];
|
||||||
|
cachedArtists[row.artist + "♣" + row.artistDisambiguation] = row._id;
|
||||||
|
cachedArtistIds[row._id] = {
|
||||||
|
artist: row.artist,
|
||||||
|
artistDisambiguation: row.artistDisambiguation
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < tracks.length; i++) {
|
||||||
|
var track = tracks[i];
|
||||||
|
var album = cachedAlbumArtists[track.album];
|
||||||
|
if (!album) {
|
||||||
|
album = cachedAlbumArtists[track.album] = {
|
||||||
|
artists: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
album.artists[track.artist] = true;
|
||||||
|
var artistCount = Object.keys(album.artists).length;
|
||||||
|
if (artistCount == 1) {
|
||||||
|
album.albumArtistId =
|
||||||
|
cachedArtists[track.artist + "♣" + track.artistDisambiguation];
|
||||||
|
} else if (artistCount == 2) {
|
||||||
|
album.albumArtistId = cachedArtists["Various Artists♣"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
// Insert all albums
|
||||||
|
var promises = [];
|
||||||
|
for (var i = 0; i < tracks.length; i++) {
|
||||||
|
(function (track) {
|
||||||
|
var albumArtistId = cachedAlbumArtists[track.album].albumArtistId;
|
||||||
|
t.sqlInsert("albums", {
|
||||||
|
album: track.album,
|
||||||
|
albumArtistId: albumArtistId
|
||||||
|
});
|
||||||
|
})(tracks[i]);
|
||||||
|
}
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function () {
|
||||||
|
// Get the albums' db ids
|
||||||
|
t.sqlSelect("albums", function(r) {
|
||||||
|
return {
|
||||||
|
album: r.album,
|
||||||
|
albumArtistId: r.albumArtistId,
|
||||||
|
_id: r._id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
// Store the db ids in a map
|
||||||
|
results = results[0];
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
var row = results[i];
|
||||||
|
cachedAlbums[row.album + "♣" + row.albumArtistId] = row._id;
|
||||||
|
cachedAlbumIds[row._id] = {
|
||||||
|
album: row.album,
|
||||||
|
albumArtistId: row.albumArtistId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
// Now we are ready to insert the tracks
|
||||||
|
var promises = [];
|
||||||
|
for (var i = 0; i < tracks.length; i++) {
|
||||||
|
(function (track) {
|
||||||
|
// Get all relevant ids that we stored in the previous steps
|
||||||
|
var artistId = cachedArtists[track.artist + "♣" + track.artistDisambiguation];
|
||||||
|
var albumArtistId = cachedAlbumArtists[track.album].albumArtistId;
|
||||||
|
var albumId = cachedAlbums[track.album + "♣" + albumArtistId];
|
||||||
|
// Insert the artist <=> album relations
|
||||||
|
t.sqlInsert("artistAlbums", {
|
||||||
|
albumId: albumId,
|
||||||
|
artistId: artistId
|
||||||
|
});
|
||||||
|
// Insert the tracks
|
||||||
|
t.sqlInsert("tracks", {
|
||||||
|
track: track.track,
|
||||||
|
artistId: artistId,
|
||||||
|
albumId: albumId,
|
||||||
|
url: track.url,
|
||||||
|
duration: track.duration,
|
||||||
|
linkUrl: track.linkUrl,
|
||||||
|
releaseyear: track.releaseyear,
|
||||||
|
bitrate: track.bitrate,
|
||||||
|
albumPos: track.albumpos
|
||||||
|
});
|
||||||
|
})(tracks[i]);
|
||||||
|
}
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function () {
|
||||||
|
var resultMap = function (r) {
|
||||||
|
return {
|
||||||
|
_id : r._id,
|
||||||
|
artistId: r.artistId,
|
||||||
|
albumId: r.albumId,
|
||||||
|
track: r.track
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Get the tracks' db ids
|
||||||
|
t.sqlSelect("tracks", resultMap, ["_id", "artistId", "albumId", "track"]);
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
that._trackCount = results[0].length;
|
||||||
|
Tomahawk.log("Added " + results[0].length + " tracks to collection '" + id + "'");
|
||||||
|
// Add the db ids together with the basic metadata to the fuzzy index list
|
||||||
|
var fuzzyIndexList = [];
|
||||||
|
for (var i = 0; i < results[0].length; i++) {
|
||||||
|
var row = results[0][i];
|
||||||
|
fuzzyIndexList.push({
|
||||||
|
id: row._id,
|
||||||
|
artist: cachedArtistIds[row.artistId].artist,
|
||||||
|
album: cachedAlbumIds[row.albumId].album,
|
||||||
|
track: row.track
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Tomahawk.createFuzzyIndex(fuzzyIndexList);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
wipe: function (params) {
|
||||||
|
var id = params.id;
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
t.sqlDrop("artists");
|
||||||
|
t.sqlDrop("albumArtists");
|
||||||
|
t.sqlDrop("albums");
|
||||||
|
t.sqlDrop("artistAlbums");
|
||||||
|
t.sqlDrop("tracks");
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function () {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
that.cachedDbs[id].changeVersion(that.cachedDbs[id].version, "", null,
|
||||||
|
function (err) {
|
||||||
|
if (console.error) {
|
||||||
|
console.error("Error!: %o", err);
|
||||||
|
}
|
||||||
|
reject();
|
||||||
|
}, function () {
|
||||||
|
delete that.cachedDbs[id];
|
||||||
|
Tomahawk.deleteFuzzyIndex(id);
|
||||||
|
Tomahawk.log("Wiped collection '" + id + "'");
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_fuzzyIndexIdsToTracks: function(resultIds, id) {
|
||||||
|
var that = this;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
var mapFn = function(row) {
|
||||||
|
return {
|
||||||
|
artist: row.artist,
|
||||||
|
artistDisambiguation: row.artistDisambiguation,
|
||||||
|
album: row.album,
|
||||||
|
track: row.track,
|
||||||
|
duration: row.duration,
|
||||||
|
url: row.url,
|
||||||
|
linkUrl: row.linkUrl,
|
||||||
|
releaseyear: row.releaseyear,
|
||||||
|
bitrate: row.bitrate,
|
||||||
|
albumpos: row.albumPos
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (var idx = 0; resultIds && idx < resultIds.length; idx++) {
|
||||||
|
var trackid = resultIds[idx][0];
|
||||||
|
var where = { _id : trackid };
|
||||||
|
t.sqlSelect("tracks",mapFn,
|
||||||
|
[],
|
||||||
|
where, [
|
||||||
|
{
|
||||||
|
table: "artists",
|
||||||
|
conditions: {
|
||||||
|
artistId: "_id"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
table: "albums",
|
||||||
|
conditions: {
|
||||||
|
albumId: "_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
var merged = [];
|
||||||
|
return merged.concat.apply(merged,
|
||||||
|
results.map(function(e){
|
||||||
|
//every result has one track
|
||||||
|
return e[0];
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: function(params) {
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
var resultIds = Tomahawk.resolveFromFuzzyIndex(params.artist, params.album, params.track);
|
||||||
|
return this._fuzzyIndexIdsToTracks(resultIds);
|
||||||
|
},
|
||||||
|
|
||||||
|
search: function(params) {
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
var resultIds = Tomahawk.searchFuzzyIndex(params.query);
|
||||||
|
return this._fuzzyIndexIdsToTracks(resultIds);
|
||||||
|
},
|
||||||
|
|
||||||
|
tracks: function (params, where) {
|
||||||
|
//TODO filter/where support
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
var mapFn = function(row) {
|
||||||
|
return {
|
||||||
|
artist: row.artist,
|
||||||
|
artistDisambiguation: row.artistDisambiguation,
|
||||||
|
album: row.album,
|
||||||
|
track: row.track,
|
||||||
|
duration: row.duration,
|
||||||
|
url: row.url,
|
||||||
|
linkUrl: row.linkUrl,
|
||||||
|
releaseyear: row.releaseyear,
|
||||||
|
bitrate: row.bitrate,
|
||||||
|
albumpos: row.albumPos
|
||||||
|
};
|
||||||
|
};
|
||||||
|
t.sqlSelect("tracks",mapFn,
|
||||||
|
[],
|
||||||
|
where, [
|
||||||
|
{
|
||||||
|
table: "artists",
|
||||||
|
conditions: {
|
||||||
|
artistId: "_id"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
table: "albums",
|
||||||
|
conditions: {
|
||||||
|
albumId: "_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
return {results: Tomahawk.resolver.instance._convertUrls(results[0])};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
albums: function (params, where) {
|
||||||
|
//TODO filter/where support
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
var mapFn = function(row) {
|
||||||
|
return {
|
||||||
|
albumArtist: row.artist,
|
||||||
|
albumArtistDisambiguation: row.artistDisambiguation,
|
||||||
|
album: row.album
|
||||||
|
};
|
||||||
|
};
|
||||||
|
t.sqlSelect("albums",mapFn,
|
||||||
|
["album", "artist", "artistDisambiguation"],
|
||||||
|
where, [
|
||||||
|
{
|
||||||
|
table: "artists",
|
||||||
|
conditions: {
|
||||||
|
albumArtistId: "_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
results = results[0].filter(function(e){
|
||||||
|
return (e.albumArtist != '' && e.album != '');
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
artists: results.map(function(i){ return i.albumArtist;}),
|
||||||
|
albums: results.map(function(i){ return i.album;})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
artists: function (params) {
|
||||||
|
//TODO filter/where support
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
var mapFn = function(r)
|
||||||
|
{
|
||||||
|
return r.artist;
|
||||||
|
};
|
||||||
|
t.sqlSelect("artists", mapFn, ["artist", "artistDisambiguation"]);
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (artists) {
|
||||||
|
return {artists: artists[0]};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
//TODO: not exactly sure how is this one supposed to work
|
||||||
|
//albumArtists: function (params) {
|
||||||
|
//var id = params.id;
|
||||||
|
|
||||||
|
//var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
//return t.beginTransaction().then(function () {
|
||||||
|
//var mapFn = function(row) {
|
||||||
|
//return {
|
||||||
|
//albumArtist: row.albumArtist,
|
||||||
|
//albumArtistDisambiguation: row.albumArtistDisambiguation
|
||||||
|
//};
|
||||||
|
//};
|
||||||
|
//t.sqlSelect("albumArtists", ["albumArtist", "albumArtistDisambiguation"]);
|
||||||
|
//return t.execDefferedStatements();
|
||||||
|
//}).then(function (results) {
|
||||||
|
//return results[0];
|
||||||
|
//});
|
||||||
|
//},
|
||||||
|
|
||||||
|
artistAlbums: function (params) {
|
||||||
|
//TODO filter/where support
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
var artist = params.artist;
|
||||||
|
//var artistDisambiguation = params.artistDisambiguation;
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
|
||||||
|
t.sqlSelect("artists",function(r){return r._id;}, ["_id"], {
|
||||||
|
artist: artist
|
||||||
|
//artistDisambiguation: artistDisambiguation
|
||||||
|
});
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
var artistId = results[0][0];
|
||||||
|
t.sqlSelect("artistAlbums",function(r){return r.album;}, ["albumId", 'album'], {
|
||||||
|
artistId: artistId
|
||||||
|
},[
|
||||||
|
{
|
||||||
|
table: "albums",
|
||||||
|
conditions: {
|
||||||
|
albumId: "_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
return {
|
||||||
|
artist: artist,
|
||||||
|
albums: results[0]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
albumTracks: function (params) {
|
||||||
|
//TODO filter/where support
|
||||||
|
var id = params.id;
|
||||||
|
if(typeof id === 'undefined')
|
||||||
|
id = this.settings.id;
|
||||||
|
var albumArtist = params.artist;
|
||||||
|
//var albumArtistDisambiguation = params.albumArtistDisambiguation;
|
||||||
|
var album = params.album;
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var t = new Tomahawk.Collection.Transaction(this, id);
|
||||||
|
return t.beginTransaction().then(function () {
|
||||||
|
t.sqlSelect("artists", function(r){return r._id;},["_id"], {
|
||||||
|
artist: albumArtist,
|
||||||
|
//artistDisambiguation: albumArtistDisambiguation
|
||||||
|
});
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
var albumArtistId = results[0][0];
|
||||||
|
t.sqlSelect("albums",function(r){return r._id;}, ["_id"], {
|
||||||
|
album: album,
|
||||||
|
albumArtistId: albumArtistId
|
||||||
|
});
|
||||||
|
return t.execDefferedStatements();
|
||||||
|
}).then(function (results) {
|
||||||
|
var albumId = results[0][0];
|
||||||
|
return that.tracks(params, {
|
||||||
|
albumId: albumId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
collection: function () {
|
||||||
|
this.settings.trackcount = this._trackCount;
|
||||||
|
if(! this.settings.description)
|
||||||
|
this.settings.description = this.settings.prettyname;
|
||||||
|
this.settings.capabilities = [Tomahawk.Collection.BrowseCapability.Artists,
|
||||||
|
Tomahawk.Collection.BrowseCapability.Albums, Tomahawk.Collection.BrowseCapability.Tracks];
|
||||||
|
return this.settings;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -711,7 +711,13 @@ JSResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr&, const QStr
|
|||||||
if ( m_urlCallbackIsAsync )
|
if ( m_urlCallbackIsAsync )
|
||||||
{
|
{
|
||||||
QString qid = uuid();
|
QString qid = uuid();
|
||||||
QString getUrl = QString( "Tomahawk.resolver.instance.%1( '%2', '%3' );" ).arg( m_urlCallback )
|
QString getUrl = QString(
|
||||||
|
"if(Tomahawk.resolver.instance['_adapter_%1']) {"
|
||||||
|
" Tomahawk.resolver.instance._adapter_%1( {qid: '%2', url: '%3'} );"
|
||||||
|
"} else {"
|
||||||
|
" Tomahawk.resolver.instance.%1( {qid: '%2', url: '%3'} );"
|
||||||
|
"}"
|
||||||
|
).arg( m_urlCallback )
|
||||||
.arg( qid )
|
.arg( qid )
|
||||||
.arg( url );
|
.arg( url );
|
||||||
|
|
||||||
|
@@ -145,7 +145,7 @@ ScriptAccount::invoke( const scriptobject_ptr& scriptObject, const QString& meth
|
|||||||
void
|
void
|
||||||
ScriptAccount::reportScriptJobResult( const QVariantMap& result )
|
ScriptAccount::reportScriptJobResult( const QVariantMap& result )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO << result;
|
//tLog() << Q_FUNC_INFO << result;
|
||||||
const QString requestId = result[ "requestId" ].toString();
|
const QString requestId = result[ "requestId" ].toString();
|
||||||
Q_ASSERT( !requestId.isEmpty() );
|
Q_ASSERT( !requestId.isEmpty() );
|
||||||
|
|
||||||
|
@@ -252,6 +252,20 @@ ScriptCollection::parseMetaData( const QVariantMap& metadata )
|
|||||||
bool ok = iconPixmap.load( iconPath );
|
bool ok = iconPixmap.load( iconPath );
|
||||||
if ( ok && !iconPixmap.isNull() )
|
if ( ok && !iconPixmap.isNull() )
|
||||||
setIcon( iconPixmap );
|
setIcon( iconPixmap );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//see if it is a new way of specifying path
|
||||||
|
//like "contents/images/icon.png"
|
||||||
|
iconPath = QFileInfo( scriptAccount()->filePath() ).path();
|
||||||
|
for(int i = 0; i < 3 && !ok ; ++i)
|
||||||
|
{
|
||||||
|
iconPath += "/../";
|
||||||
|
ok = iconPixmap.load(iconPath + metadata.value("iconfile").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ok && !iconPixmap.isNull() )
|
||||||
|
setIcon( iconPixmap );
|
||||||
|
}
|
||||||
|
|
||||||
fetchIcon( metadata.value( "iconurl" ).toString() );
|
fetchIcon( metadata.value( "iconurl" ).toString() );
|
||||||
}
|
}
|
||||||
|
@@ -106,7 +106,7 @@ ScriptCommand_AllTracks::onTracksJobDone( const QVariantMap& result )
|
|||||||
ScriptJob* job = qobject_cast< ScriptJob* >( sender() );
|
ScriptJob* job = qobject_cast< ScriptJob* >( sender() );
|
||||||
Q_ASSERT( job );
|
Q_ASSERT( job );
|
||||||
|
|
||||||
qDebug() << "Resolver reporting album tracks:" << result;
|
//qDebug() << "Resolver reporting album tracks:" << result;
|
||||||
|
|
||||||
if ( job->error() )
|
if ( job->error() )
|
||||||
{
|
{
|
||||||
|
@@ -49,6 +49,8 @@ ScriptEngine::ScriptEngine( JSAccount* parent )
|
|||||||
settings()->setAttribute( QWebSettings::LocalStorageDatabaseEnabled, true );
|
settings()->setAttribute( QWebSettings::LocalStorageDatabaseEnabled, true );
|
||||||
settings()->setAttribute( QWebSettings::LocalContentCanAccessFileUrls, true );
|
settings()->setAttribute( QWebSettings::LocalContentCanAccessFileUrls, true );
|
||||||
settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
|
settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
|
||||||
|
settings()->setOfflineStorageDefaultQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||||
|
settings()->setOfflineWebApplicationCacheQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||||
|
|
||||||
// HACK
|
// HACK
|
||||||
QStringList cmdArgs = QCoreApplication::instance()->arguments();
|
QStringList cmdArgs = QCoreApplication::instance()->arguments();
|
||||||
|
@@ -171,6 +171,10 @@ TomahawkApp::init()
|
|||||||
|
|
||||||
tLog() << "Starting Tomahawk...";
|
tLog() << "Starting Tomahawk...";
|
||||||
|
|
||||||
|
QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
|
||||||
|
//QWebSettings::setOfflineStoragePath(QLatin1String("/tmp"));
|
||||||
|
|
||||||
|
|
||||||
m_headless = true;
|
m_headless = true;
|
||||||
m_headless = arguments().contains( "--headless" );
|
m_headless = arguments().contains( "--headless" );
|
||||||
setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
|
setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
|
||||||
|
Reference in New Issue
Block a user