mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-20 15:59:42 +01:00
Merge pull request #276 from tomahawk-player/jsinfoplugins
Add JavaScript InfoPlugins
This commit is contained in:
commit
5fa223428e
18
data/js/es6-promise-2.0.0.min.js
vendored
Normal file
18
data/js/es6-promise-2.0.0.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @overview es6-promise - a tiny implementation of Promises/A+.
|
||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
||||
* @license Licensed under MIT license
|
||||
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
|
||||
* @version 2.0.0
|
||||
*/
|
||||
|
||||
(function(){function r(a,b){n[l]=a;n[l+1]=b;l+=2;2===l&&A()}function s(a){return"function"===typeof a}function F(){return function(){process.nextTick(t)}}function G(){var a=0,b=new B(t),c=document.createTextNode("");b.observe(c,{characterData:!0});return function(){c.data=a=++a%2}}function H(){var a=new MessageChannel;a.port1.onmessage=t;return function(){a.port2.postMessage(0)}}function I(){return function(){setTimeout(t,1)}}function t(){for(var a=0;a<l;a+=2)(0,n[a])(n[a+1]),n[a]=void 0,n[a+1]=void 0;
|
||||
l=0}function p(){}function J(a,b,c,d){try{a.call(b,c,d)}catch(e){return e}}function K(a,b,c){r(function(a){var e=!1,f=J(c,b,function(c){e||(e=!0,b!==c?q(a,c):m(a,c))},function(b){e||(e=!0,g(a,b))});!e&&f&&(e=!0,g(a,f))},a)}function L(a,b){1===b.a?m(a,b.b):2===a.a?g(a,b.b):u(b,void 0,function(b){q(a,b)},function(b){g(a,b)})}function q(a,b){if(a===b)g(a,new TypeError("You cannot resolve a promise with itself"));else if("function"===typeof b||"object"===typeof b&&null!==b)if(b.constructor===a.constructor)L(a,
|
||||
b);else{var c;try{c=b.then}catch(d){v.error=d,c=v}c===v?g(a,v.error):void 0===c?m(a,b):s(c)?K(a,b,c):m(a,b)}else m(a,b)}function M(a){a.d&&a.d(a.b);x(a)}function m(a,b){void 0===a.a&&(a.b=b,a.a=1,0!==a.f.length&&r(x,a))}function g(a,b){void 0===a.a&&(a.a=2,a.b=b,r(M,a))}function u(a,b,c,d){var e=a.f,f=e.length;a.d=null;e[f]=b;e[f+1]=c;e[f+2]=d;0===f&&a.a&&r(x,a)}function x(a){var b=a.f,c=a.a;if(0!==b.length){for(var d,e,f=a.b,g=0;g<b.length;g+=3)d=b[g],e=b[g+c],d?C(c,d,e,f):e(f);a.f.length=0}}function D(){this.error=
|
||||
null}function C(a,b,c,d){var e=s(c),f,k,h,l;if(e){try{f=c(d)}catch(n){y.error=n,f=y}f===y?(l=!0,k=f.error,f=null):h=!0;if(b===f){g(b,new TypeError("A promises callback cannot return that same promise."));return}}else f=d,h=!0;void 0===b.a&&(e&&h?q(b,f):l?g(b,k):1===a?m(b,f):2===a&&g(b,f))}function N(a,b){try{b(function(b){q(a,b)},function(b){g(a,b)})}catch(c){g(a,c)}}function k(a,b,c,d){this.n=a;this.c=new a(p,d);this.i=c;this.o(b)?(this.m=b,this.e=this.length=b.length,this.l(),0===this.length?m(this.c,
|
||||
this.b):(this.length=this.length||0,this.k(),0===this.e&&m(this.c,this.b))):g(this.c,this.p())}function h(a){O++;this.b=this.a=void 0;this.f=[];if(p!==a){if(!s(a))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof h))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");N(this,a)}}var E=Array.isArray?Array.isArray:function(a){return"[object Array]"===
|
||||
Object.prototype.toString.call(a)},l=0,w="undefined"!==typeof window?window:{},B=w.MutationObserver||w.WebKitMutationObserver,w="undefined"!==typeof Uint8ClampedArray&&"undefined"!==typeof importScripts&&"undefined"!==typeof MessageChannel,n=Array(1E3),A;A="undefined"!==typeof process&&"[object process]"==={}.toString.call(process)?F():B?G():w?H():I();var v=new D,y=new D;k.prototype.o=function(a){return E(a)};k.prototype.p=function(){return Error("Array Methods must be provided an Array")};k.prototype.l=
|
||||
function(){this.b=Array(this.length)};k.prototype.k=function(){for(var a=this.length,b=this.c,c=this.m,d=0;void 0===b.a&&d<a;d++)this.j(c[d],d)};k.prototype.j=function(a,b){var c=this.n;"object"===typeof a&&null!==a?a.constructor===c&&void 0!==a.a?(a.d=null,this.g(a.a,b,a.b)):this.q(c.resolve(a),b):(this.e--,this.b[b]=this.h(a))};k.prototype.g=function(a,b,c){var d=this.c;void 0===d.a&&(this.e--,this.i&&2===a?g(d,c):this.b[b]=this.h(c));0===this.e&&m(d,this.b)};k.prototype.h=function(a){return a};
|
||||
k.prototype.q=function(a,b){var c=this;u(a,void 0,function(a){c.g(1,b,a)},function(a){c.g(2,b,a)})};var O=0;h.all=function(a,b){return(new k(this,a,!0,b)).c};h.race=function(a,b){function c(a){q(e,a)}function d(a){g(e,a)}var e=new this(p,b);if(!E(a))return (g(e,new TypeError("You must pass an array to race.")), e);for(var f=a.length,h=0;void 0===e.a&&h<f;h++)u(this.resolve(a[h]),void 0,c,d);return e};h.resolve=function(a,b){if(a&&"object"===typeof a&&a.constructor===this)return a;var c=new this(p,b);
|
||||
q(c,a);return c};h.reject=function(a,b){var c=new this(p,b);g(c,a);return c};h.prototype={constructor:h,then:function(a,b,c){var d=this.a;if(1===d&&!a||2===d&&!b)return this;this.d=null;var e=new this.constructor(p,c),f=this.b;if(d){var g=arguments[d-1];r(function(){C(d,e,g,f)})}else u(this,e,a,b);return e},"catch":function(a,b){return this.then(null,a,b)}};var z={Promise:h,r:function(){var a;a="undefined"!==typeof global?global:"undefined"!==typeof window&&window.document?window:self;"Promise"in
|
||||
a&&"resolve"in a.Promise&&"reject"in a.Promise&&"all"in a.Promise&&"race"in a.Promise&&function(){var b;new a.Promise(function(a){b=a});return s(b)}()||(a.Promise=h)}};"function"===typeof define&&define.amd?define(function(){return z}):"undefined"!==typeof module&&module.exports?module.exports=z:"undefined"!==typeof this&&(this.ES6Promise=z)}).call(this);
|
153
data/js/tomahawk-infosystem.js
Normal file
153
data/js/tomahawk-infosystem.js
Normal file
@ -0,0 +1,153 @@
|
||||
// install ES6Promise as global Promise
|
||||
if(window.Promise === undefined) {
|
||||
window.Promise = window.ES6Promise.Promise;
|
||||
}
|
||||
|
||||
// TODO: find a way to enumerate TypeInfo instead of copying this manually
|
||||
|
||||
Tomahawk.InfoSystem.InfoType = Object.create(null);
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoNoInfo = 0; //WARNING: *ALWAYS* keep this first!
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackID = 1;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackArtist = 2;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackAlbum = 3;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackGenre = 4;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackComposer = 5;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackDate = 6;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackNumber = 7;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackDiscNumber = 8;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackBitRate = 9;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackLength = 10;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackSampleRate = 11;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackFileSize = 12;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackBPM = 13;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackReplayGain = 14;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackReplayPeakGain = 15;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackLyrics = 16;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackLocation = 17;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackProfile = 18;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackEnergy = 19;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackDanceability = 20;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackTempo = 21;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackLoudness = 22;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackSimilars = 23; // cached -- do not change
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistID = 25;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistName = 26;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistBiography = 27;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistImages = 28; //cached -- do not change
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistBlog = 29;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistFamiliarity = 30;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistHotttness = 31;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistSongs = 32; //cached -- do not change
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistSimilars = 33; //cached -- do not change
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistNews = 34;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistProfile = 35;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistReviews = 36;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistTerms = 37;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistLinks = 38;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistVideos = 39;
|
||||
Tomahawk.InfoSystem.InfoType.InfoArtistReleases = 40;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumID = 42;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumCoverArt = 43; //cached -- do not change
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumName = 44;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumArtist = 45;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumDate = 46;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumGenre = 47;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumComposer = 48;
|
||||
Tomahawk.InfoSystem.InfoType.InfoAlbumSongs = 49;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoChartCapabilities = 50;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoChart = 51;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoNewReleaseCapabilities = 52;
|
||||
Tomahawk.InfoSystem.InfoType.InfoNewRelease = 53;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoMiscTopHotttness = 60;
|
||||
Tomahawk.InfoSystem.InfoType.InfoMiscTopTerms = 61;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoSubmitNowPlaying = 70;
|
||||
Tomahawk.InfoSystem.InfoType.InfoSubmitScrobble = 71;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoNowPlaying = 80;
|
||||
Tomahawk.InfoSystem.InfoType.InfoNowPaused = 81;
|
||||
Tomahawk.InfoSystem.InfoType.InfoNowResumed = 82;
|
||||
Tomahawk.InfoSystem.InfoType.InfoNowStopped = 83;
|
||||
Tomahawk.InfoSystem.InfoType.InfoTrackUnresolved = 84;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoLove = 90;
|
||||
Tomahawk.InfoSystem.InfoType.InfoUnLove = 91;
|
||||
Tomahawk.InfoSystem.InfoType.InfoShareTrack = 92;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoNotifyUser = 100;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoInboxReceived = 101;
|
||||
|
||||
Tomahawk.InfoSystem.InfoType.InfoLastInfo = 102; //WARNING: *ALWAYS* keep this last!
|
||||
|
||||
// PushInfoFlags
|
||||
Tomahawk.InfoSystem.PushInfoFlags = Object.create(null);
|
||||
Tomahawk.InfoSystem.PushInfoFlags.PushNoFlag = 1;
|
||||
Tomahawk.InfoSystem.PushInfoFlags.PushShortUrlFlag = 2;
|
||||
|
||||
|
||||
Tomahawk.InfoSystem._infoPluginIdCounter = 0;
|
||||
Tomahawk.InfoSystem._infoPluginHash = Object.create(null);
|
||||
|
||||
Tomahawk.InfoSystem.addInfoPlugin = function (infoPlugin) {
|
||||
var infoPluginId = Tomahawk.InfoSystem._infoPluginIdCounter++;
|
||||
Tomahawk.InfoSystem._infoPluginHash[infoPluginId] = infoPlugin;
|
||||
Tomahawk.InfoSystem.nativeAddInfoPlugin(infoPluginId);
|
||||
};
|
||||
|
||||
Tomahawk.InfoSystem.getInfoPlugin = function (infoPluginId) {
|
||||
return Tomahawk.InfoSystem._infoPluginHash[infoPluginId];
|
||||
};
|
||||
|
||||
Tomahawk.InfoSystem.removeInfoPlugin = function (infoPluginId) {
|
||||
Tomahawk.log('Removing info plugins from JS is not implemented yet');
|
||||
Tomahawk.assert(false);
|
||||
};
|
||||
|
||||
Tomahawk.InfoSystem.InfoPlugin = {
|
||||
infoTypeString: function (infoType) {
|
||||
for (var currentInfoTypeString in Tomahawk.InfoSystem.InfoType) {
|
||||
if (Tomahawk.InfoSystem.InfoType[currentInfoTypeString] === infoType) {
|
||||
return currentInfoTypeString;
|
||||
}
|
||||
}
|
||||
},
|
||||
// we can get around infoPluginId here probably ... but internal either way
|
||||
_notInCache: function (infoPluginId, requestId, requestType, criteria) {
|
||||
this.notInCache(requestType, criteria).then(function(result) {
|
||||
Tomahawk.InfoSystem.nativeAddInfoRequestResult(infoPluginId, requestId, result.maxAge, result.data);
|
||||
}).catch(function() {
|
||||
// TODO: how to handle errors here?!
|
||||
});
|
||||
},
|
||||
notInCache: function (infoType, criteria) {
|
||||
var requestMethod = 'request' + this.infoTypeString(infoType);
|
||||
|
||||
return Promise.resolve(this[requestMethod](criteria));
|
||||
},
|
||||
pushInfo: function (pushData) {
|
||||
var pushMethod = 'push' + this.infoTypeString(pushData.type);
|
||||
return this[pushMethod](pushData);
|
||||
},
|
||||
// we can get around infoPluginId here probably ... but internal either way
|
||||
_getInfo: function (infoPluginId, requestId, type, infoHash) {
|
||||
this.getInfo(type, infoHash).then(function(result) {
|
||||
Tomahawk.InfoSystem.nativeGetCachedInfo(infoPluginId, requestId, result.newMaxAge, result.criteria)
|
||||
}, function() {
|
||||
Tomahawk.log("Call nativeDataError");
|
||||
Tomahawk.InfoSystem.nativeDataError();
|
||||
});
|
||||
},
|
||||
getInfo: function (type, infoHash) {
|
||||
var getInfoMethod = 'get' + this.infoTypeString(type);
|
||||
|
||||
return Promise.resolve(this[getInfoMethod](infoHash));
|
||||
}
|
||||
};
|
@ -409,6 +409,10 @@ Tomahawk.asyncRequest = function (url, callback, extraHeaders, options) {
|
||||
}
|
||||
};
|
||||
|
||||
Tomahawk.assert = function (assertion, message) {
|
||||
Tomahawk.nativeAssert(assertion, message);
|
||||
}
|
||||
|
||||
Tomahawk.sha256 = Tomahawk.sha256 || CryptoJS.SHA256;
|
||||
Tomahawk.md5 = Tomahawk.md5 || CryptoJS.MD5;
|
||||
// Return a HMAC (md5) signature of the input text with the desired key
|
||||
|
@ -65,6 +65,8 @@
|
||||
<file>data/sql/dbmigrate-27_to_28.sql</file>
|
||||
<file>data/sql/dbmigrate-28_to_29.sql</file>
|
||||
<file>data/js/tomahawk.js</file>
|
||||
<file>data/js/tomahawk-infosystem.js</file>
|
||||
<file>data/js/es6-promise-2.0.0.min.js</file>
|
||||
<file>data/images/drop-all-songs.svg</file>
|
||||
<file>data/images/drop-local-songs.svg</file>
|
||||
<file>data/images/drop-top-songs.svg</file>
|
||||
|
@ -182,7 +182,7 @@ EchonestPlugin::getArtistBiographySlot()
|
||||
QVariantMap biographyMap;
|
||||
Q_FOREACH( const Echonest::Biography& biography, biographies )
|
||||
{
|
||||
QVariantHash siteData;
|
||||
QVariantMap siteData;
|
||||
siteData[ "site" ] = biography.site();
|
||||
siteData[ "url" ] = biography.url().toString();
|
||||
siteData[ "text" ] = biography.text();
|
||||
@ -228,7 +228,7 @@ EchonestPlugin::getArtistTermsSlot()
|
||||
Echonest::TermList terms = artist.terms();
|
||||
QVariantMap termsMap;
|
||||
Q_FOREACH( const Echonest::Term& term, terms ) {
|
||||
QVariantHash termHash;
|
||||
QVariantMap termHash;
|
||||
termHash[ "weight" ] = QString::number( term.weight() );
|
||||
termHash[ "frequency" ] = QString::number( term.frequency() );
|
||||
termsMap[ term.name() ] = termHash;
|
||||
@ -246,7 +246,7 @@ EchonestPlugin::getMiscTopSlot()
|
||||
Echonest::TermList terms = Echonest::Artist::parseTopTerms( reply );
|
||||
QVariantMap termsMap;
|
||||
Q_FOREACH( const Echonest::Term& term, terms ) {
|
||||
QVariantHash termHash;
|
||||
QVariantMap termHash;
|
||||
termHash[ "weight" ] = QString::number( term.weight() );
|
||||
termHash[ "frequency" ] = QString::number( term.frequency() );
|
||||
termsMap[ term.name() ] = termHash;
|
||||
|
@ -547,7 +547,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
foreach ( const QString& source, bmap.keys() )
|
||||
{
|
||||
if ( source == "last.fm" )
|
||||
m_biography = bmap[ source ].toHash()[ "text" ].toString();
|
||||
m_biography = bmap[ source ].toMap()[ "text" ].toString();
|
||||
}
|
||||
|
||||
m_biographyLoaded = true;
|
||||
|
@ -84,6 +84,8 @@ set( libGuiSources
|
||||
|
||||
resolvers/ExternalResolverGui.cpp
|
||||
resolvers/ScriptResolver.cpp
|
||||
resolvers/JSInfoPlugin.cpp
|
||||
resolvers/JSInfoSystemHelper.cpp
|
||||
resolvers/JSResolver.cpp
|
||||
resolvers/JSResolverHelper.cpp
|
||||
resolvers/ScriptEngine.cpp
|
||||
|
@ -736,7 +736,7 @@ LastFmInfoPlugin::artistInfoReturned()
|
||||
.replace( trackRegExp, "<a href=\"tomahawk://view/track?artist=\\2&album=\\3&name=\\4\">" )
|
||||
.replace( "&album=_", "" );
|
||||
|
||||
QVariantHash siteData;
|
||||
QVariantMap siteData;
|
||||
siteData[ "site" ] = "last.fm";
|
||||
siteData[ "text" ] = biography.replace( "\r", "\n" ).replace( "\n\n", "\n" );
|
||||
siteData[ "summary" ] = lfm["artist"]["bio"]["summary"].text().trimmed().replace( "\r", "\n" ).replace( "\n\n", "\n" );
|
||||
|
@ -33,11 +33,10 @@
|
||||
//class SpotifyPlaylistUpdater;
|
||||
class QTimer;
|
||||
|
||||
class ScriptResolver;
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
class SpotifyParser;
|
||||
class ScriptResolver;
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
@ -48,11 +48,11 @@ class DLLEXPORT ExternalResolver : public Resolver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ::ScriptCommandQueue;
|
||||
friend class ::ScriptCommand_AllArtists;
|
||||
friend class ::ScriptCommand_AllAlbums;
|
||||
friend class ::ScriptCommand_AllTracks;
|
||||
friend class ::ScriptCommand_LookupUrl;
|
||||
friend class ScriptCommandQueue;
|
||||
friend class ScriptCommand_AllArtists;
|
||||
friend class ScriptCommand_AllAlbums;
|
||||
friend class ScriptCommand_AllTracks;
|
||||
friend class ScriptCommand_LookupUrl;
|
||||
|
||||
public:
|
||||
enum ErrorState {
|
||||
|
272
src/libtomahawk/resolvers/JSInfoPlugin.cpp
Normal file
272
src/libtomahawk/resolvers/JSInfoPlugin.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "JSInfoPlugin_p.h"
|
||||
|
||||
#include "JSResolver.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include "../utils/Logger.h"
|
||||
#include "../utils/Json.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
JSInfoPlugin::JSInfoPlugin( int id, JSResolver *resolver )
|
||||
: d_ptr( new JSInfoPluginPrivate( this, id, resolver ) )
|
||||
{
|
||||
Q_ASSERT( resolver );
|
||||
|
||||
// read in supported GetTypes and PushTypes - we can do this safely because we are still in WebKit thread here
|
||||
m_supportedGetTypes = parseSupportedTypes( callMethodOnInfoPluginWithResult( "supportedGetTypes" ) );
|
||||
m_supportedPushTypes = parseSupportedTypes( callMethodOnInfoPluginWithResult( "supportedPushTypes" ) );
|
||||
|
||||
setFriendlyName( QString( "JSInfoPlugin: %1" ).arg( resolver->name() ) );
|
||||
}
|
||||
|
||||
|
||||
JSInfoPlugin::~JSInfoPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
d->requestDataCache[ requestData.requestId ] = requestData;
|
||||
|
||||
QString eval = QString( "_getInfo(%1, %2, %3, %4)" )
|
||||
.arg( d->id ) // infoPluginId
|
||||
.arg( requestData.requestId ) // requestId
|
||||
.arg( requestData.type ) // type
|
||||
.arg( JSResolver::escape( serializeQVariantMap( convertInfoStringHashToQVariantMap( requestData.input.value<Tomahawk::InfoSystem::InfoStringHash>() ) ) ) ); // infoHash
|
||||
|
||||
callMethodOnInfoPlugin( eval );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
{
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
QString eval = QString( "pushInfo({ type: %1, pushFlags: %2, input: %3, additionalInput: %4})" )
|
||||
.arg( pushData.type )
|
||||
.arg( pushData.pushFlags )
|
||||
.arg( JSResolver::escape( serializeQVariantMap ( pushData.infoPair.second.toMap() ) ) )
|
||||
.arg( JSResolver::escape( serializeQVariantMap( pushData.infoPair.first ) ) );
|
||||
|
||||
callMethodOnInfoPlugin( eval );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
d->requestDataCache[ requestData.requestId ] = requestData;
|
||||
d->criteriaCache[ requestData.requestId ] = criteria;
|
||||
|
||||
|
||||
QString eval = QString( "_notInCache(%1, %2, %3, %4)" )
|
||||
.arg( d->id )
|
||||
.arg( requestData.requestId )
|
||||
.arg( requestData.type )
|
||||
.arg( JSResolver::escape( serializeQVariantMap( convertInfoStringHashToQVariantMap( criteria ) ) ) );
|
||||
|
||||
callMethodOnInfoPlugin( eval );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::addInfoRequestResult( int requestId, qint64 maxAge, const QVariantMap& returnedData )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "addInfoRequestResult", Qt::QueuedConnection, Q_ARG( int, requestId ), Q_ARG( qint64, maxAge ), Q_ARG( QVariantMap, returnedData ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
// retrieve requestData from cache and delete it
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = d->requestDataCache[ requestId ];
|
||||
d->requestDataCache.remove( requestId );
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
// retrieve criteria from cache and delete it
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria = d->criteriaCache[ requestId ];
|
||||
d->criteriaCache.remove( requestId );
|
||||
|
||||
emit updateCache( criteria, maxAge, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::emitGetCachedInfo( int requestId, const QVariantMap& criteria, int newMaxAge )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "emitGetCachedInfo", Qt::QueuedConnection, Q_ARG( int, requestId ), Q_ARG( QVariantMap, criteria ), Q_ARG( int, newMaxAge ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
|
||||
emit getCachedInfo( convertQVariantMapToInfoStringHash( criteria ), newMaxAge, d->requestDataCache[ requestId ]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoPlugin::emitInfo( int requestId, const QVariantMap& output )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "emitInfo", Qt::QueuedConnection, Q_ARG( int, requestId ), Q_ARG( QVariantMap, output ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
emit info( d->requestDataCache[ requestId ], output );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSInfoPlugin::serviceGetter() const
|
||||
{
|
||||
Q_D( const JSInfoPlugin );
|
||||
|
||||
return QString( "Tomahawk.InfoSystem.getInfoPlugin(%1)" ).arg( d->id );
|
||||
}
|
||||
|
||||
// TODO: DRY, really move things into base class
|
||||
void
|
||||
JSInfoPlugin::callMethodOnInfoPlugin( const QString& scriptSource )
|
||||
{
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
QString eval = QString( "%1.%2" ).arg( serviceGetter() ).arg( scriptSource );
|
||||
|
||||
tLog() << Q_FUNC_INFO << eval;
|
||||
|
||||
d->resolver->evaluateJavaScript( eval );
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
JSInfoPlugin::callMethodOnInfoPluginWithResult(const QString& scriptSource)
|
||||
{
|
||||
Q_D( JSInfoPlugin );
|
||||
|
||||
QString eval = QString( "%1.%2" ).arg( serviceGetter() ).arg( scriptSource );
|
||||
|
||||
tLog() << Q_FUNC_INFO << eval;
|
||||
|
||||
return d->resolver->evaluateJavaScriptWithResult( eval );
|
||||
}
|
||||
|
||||
|
||||
|
||||
QSet< Tomahawk::InfoSystem::InfoType >
|
||||
JSInfoPlugin::parseSupportedTypes( const QVariant& variant )
|
||||
{
|
||||
QVariantList list = variant.toList();
|
||||
|
||||
QSet < Tomahawk::InfoSystem::InfoType > results;
|
||||
foreach( const QVariant& type, list )
|
||||
{
|
||||
bool ok;
|
||||
int intType = type.toInt( &ok );
|
||||
if ( ok )
|
||||
{
|
||||
results.insert( static_cast< Tomahawk::InfoSystem::InfoType >( intType ) );
|
||||
}
|
||||
tLog() << type << intType;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSInfoPlugin::serializeQVariantMap( const QVariantMap& map )
|
||||
{
|
||||
QVariantMap localMap = map;
|
||||
|
||||
foreach( const QString& key, localMap.keys() )
|
||||
{
|
||||
QVariant currentVariant = localMap[ key ];
|
||||
|
||||
// strip unserializable types - at least QJson needs this, check with QtJson
|
||||
if( currentVariant.canConvert<QImage>() )
|
||||
{
|
||||
localMap.remove( key );
|
||||
}
|
||||
|
||||
// convert InfoStringHash to QVariantMap
|
||||
if( currentVariant.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoStringHash currentHash = currentVariant.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
localMap[ key ] = convertInfoStringHashToQVariantMap( currentHash );
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray serialized = TomahawkUtils::toJson( localMap );
|
||||
|
||||
return QString( "JSON.parse('%1')" ).arg( QString::fromUtf8( serialized ) );
|
||||
}
|
||||
|
||||
|
||||
QVariantMap
|
||||
JSInfoPlugin::convertInfoStringHashToQVariantMap( const Tomahawk::InfoSystem::InfoStringHash& hash )
|
||||
{
|
||||
QVariantMap map;
|
||||
|
||||
foreach( const QString& key, hash.keys() )
|
||||
{
|
||||
map[key] = QVariant::fromValue< QString >( hash.value( key ) );
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash
|
||||
JSInfoPlugin::convertQVariantMapToInfoStringHash( const QVariantMap& map )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoStringHash hash;
|
||||
|
||||
foreach( const QString& key, map.keys() )
|
||||
{
|
||||
hash.insert( key, map[ key ].toString() );
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
75
src/libtomahawk/resolvers/JSInfoPlugin.h
Normal file
75
src/libtomahawk/resolvers/JSInfoPlugin.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWK_JSINFOPLUGIN_H
|
||||
#define TOMAHAWK_JSINFOPLUGIN_H
|
||||
|
||||
#include "../infosystem/InfoSystem.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSResolver;
|
||||
class JSInfoPluginPrivate;
|
||||
|
||||
|
||||
class DLLEXPORT JSInfoPlugin : public Tomahawk::InfoSystem::InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param id unique identifier to identify an infoplugin in its scope
|
||||
*/
|
||||
JSInfoPlugin( int id, JSResolver* resolver );
|
||||
virtual ~JSInfoPlugin();
|
||||
|
||||
|
||||
Q_INVOKABLE void addInfoRequestResult( int requestId, qint64 maxAge, const QVariantMap& returnedData );
|
||||
Q_INVOKABLE void emitGetCachedInfo( int requestId, const QVariantMap& criteria, int newMaxAge );
|
||||
Q_INVOKABLE void emitInfo( int requestId, const QVariantMap& output );
|
||||
|
||||
protected slots:
|
||||
void init() override;
|
||||
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) override;
|
||||
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) override;
|
||||
void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) override;
|
||||
|
||||
protected:
|
||||
// TODO: create JSPlugin base class and move these methods there
|
||||
QString serviceGetter() const; // = 0
|
||||
void callMethodOnInfoPlugin( const QString& scriptSource );
|
||||
QVariant callMethodOnInfoPluginWithResult( const QString& scriptSource );
|
||||
|
||||
private:
|
||||
static QSet< Tomahawk::InfoSystem::InfoType > parseSupportedTypes(const QVariant& variant);
|
||||
static QString serializeQVariantMap(const QVariantMap& map);
|
||||
static QVariantMap convertInfoStringHashToQVariantMap(const Tomahawk::InfoSystem::InfoStringHash& hash);
|
||||
static Tomahawk::InfoSystem::InfoStringHash convertQVariantMapToInfoStringHash( const QVariantMap& map );
|
||||
|
||||
Q_DECLARE_PRIVATE( JSInfoPlugin )
|
||||
QScopedPointer<JSInfoPluginPrivate> d_ptr;
|
||||
};
|
||||
|
||||
}; // ns: Tomahawk
|
||||
|
||||
#endif // TOMAHAWK_JSINFOPLUGIN_H
|
50
src/libtomahawk/resolvers/JSInfoPlugin_p.h
Normal file
50
src/libtomahawk/resolvers/JSInfoPlugin_p.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWK_JSINFOPLUGIN_P_H
|
||||
#define TOMAHAWK_JSINFOPLUGIN_P_H
|
||||
|
||||
#include "JSInfoPlugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSInfoPluginPrivate
|
||||
{
|
||||
friend class JSInfoPlugin;
|
||||
public:
|
||||
JSInfoPluginPrivate( JSInfoPlugin* q, int id, JSResolver* resolver )
|
||||
: q_ptr ( q )
|
||||
, id( id )
|
||||
, resolver( resolver )
|
||||
{
|
||||
}
|
||||
JSInfoPlugin* q_ptr;
|
||||
Q_DECLARE_PUBLIC ( JSInfoPlugin )
|
||||
|
||||
private:
|
||||
int id;
|
||||
JSResolver* resolver;
|
||||
|
||||
QMap< int, Tomahawk::InfoSystem::InfoRequestData > requestDataCache;
|
||||
QMap< int, Tomahawk::InfoSystem::InfoStringHash > criteriaCache;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // TOMAHAWK_JSINFOPLUGIN_P_H
|
115
src/libtomahawk/resolvers/JSInfoSystemHelper.cpp
Normal file
115
src/libtomahawk/resolvers/JSInfoSystemHelper.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "JSInfoSystemHelper_p.h"
|
||||
#include "JSInfoPlugin.h"
|
||||
|
||||
#include "../utils/Logger.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
JSInfoSystemHelper::JSInfoSystemHelper( JSResolver* parent )
|
||||
: QObject( parent )
|
||||
, d_ptr( new JSInfoSystemHelperPrivate( this, parent ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JSInfoSystemHelper::~JSInfoSystemHelper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QStringList JSInfoSystemHelper::requiredScriptPaths() const
|
||||
{
|
||||
return QStringList()
|
||||
<< RESPATH "js/tomahawk-infosystem.js";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoSystemHelper::nativeAddInfoPlugin( int id )
|
||||
{
|
||||
Q_D( JSInfoSystemHelper );
|
||||
|
||||
// create infoplugin instance
|
||||
JSInfoPlugin* jsInfoPlugin = new JSInfoPlugin( id, d->resolver );
|
||||
Tomahawk::InfoSystem::InfoPluginPtr infoPlugin( jsInfoPlugin );
|
||||
|
||||
// move it to infosystem thread
|
||||
infoPlugin->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
|
||||
// add it to local list of infoplugins
|
||||
d->infoPlugins[id] = jsInfoPlugin;
|
||||
|
||||
// add it to infosystem
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoSystemHelper::nativeRemoveInfoPlugin( int id )
|
||||
{
|
||||
Q_UNUSED( id );
|
||||
tLog() << "Removing Info plugins from JS is not implemented yet";
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoSystemHelper::nativeAddInfoRequestResult( int infoPluginId, int requestId, int maxAge, const QVariantMap& returnedData )
|
||||
{
|
||||
Q_D( JSInfoSystemHelper );
|
||||
|
||||
if ( !d->infoPlugins[ infoPluginId ] )
|
||||
{
|
||||
Q_ASSERT( d->infoPlugins[ infoPluginId ] );
|
||||
return;
|
||||
}
|
||||
|
||||
d->infoPlugins[ infoPluginId ]->addInfoRequestResult( requestId, maxAge, returnedData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSInfoSystemHelper::nativeGetCachedInfo( int infoPluginId, int requestId, int newMaxAge, const QVariantMap& criteria )
|
||||
{
|
||||
Q_D( JSInfoSystemHelper );
|
||||
|
||||
if ( !d->infoPlugins[ infoPluginId ] )
|
||||
{
|
||||
Q_ASSERT( d->infoPlugins[ infoPluginId ] );
|
||||
return;
|
||||
}
|
||||
|
||||
d->infoPlugins[ infoPluginId ]->emitGetCachedInfo( requestId, criteria, newMaxAge );
|
||||
}
|
||||
|
||||
|
||||
void JSInfoSystemHelper::nativeDataError( int infoPluginId, int requestId )
|
||||
{
|
||||
Q_D( JSInfoSystemHelper );
|
||||
|
||||
if ( !d->infoPlugins[ infoPluginId ] )
|
||||
{
|
||||
Q_ASSERT( d->infoPlugins[ infoPluginId ] );
|
||||
return;
|
||||
}
|
||||
|
||||
d->infoPlugins[ infoPluginId ]->emitInfo( requestId, QVariantMap() );
|
||||
}
|
55
src/libtomahawk/resolvers/JSInfoSystemHelper.h
Normal file
55
src/libtomahawk/resolvers/JSInfoSystemHelper.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWK_JSINFOSYSTEMHELPER_H
|
||||
#define TOMAHAWK_JSINFOSYSTEMHELPER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSResolver;
|
||||
class JSInfoSystemHelperPrivate;
|
||||
|
||||
class JSInfoSystemHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JSInfoSystemHelper( JSResolver* parent );
|
||||
~JSInfoSystemHelper();
|
||||
|
||||
QStringList requiredScriptPaths() const;
|
||||
|
||||
Q_INVOKABLE void nativeAddInfoPlugin( int id );
|
||||
Q_INVOKABLE void nativeRemoveInfoPlugin( int id );
|
||||
|
||||
Q_INVOKABLE void nativeAddInfoRequestResult( int infoPluginId, int requestId, int maxAge, const QVariantMap& returnedData );
|
||||
Q_INVOKABLE void nativeGetCachedInfo( int infoPluginId, int requestId, int newMaxAge, const QVariantMap& criteria);
|
||||
Q_INVOKABLE void nativeDataError( int infoPluginId, int requestId );
|
||||
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE( JSInfoSystemHelper )
|
||||
QScopedPointer<JSInfoSystemHelperPrivate> d_ptr;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // TOMAHAWK_JSINFOSYSTEMHELPER_H
|
49
src/libtomahawk/resolvers/JSInfoSystemHelper_p.h
Normal file
49
src/libtomahawk/resolvers/JSInfoSystemHelper_p.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWK_JSINFOSYSTEMHELPER_P_H
|
||||
#define TOMAHAWK_JSINFOSYSTEMHELPER_P_H
|
||||
|
||||
#include "JSResolver.h"
|
||||
#include "JSInfoSystemHelper.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSInfoSystemHelperPrivate
|
||||
{
|
||||
friend class JSInfoSystemHelper;
|
||||
public:
|
||||
JSInfoSystemHelperPrivate( JSInfoSystemHelper* q, JSResolver* resolver )
|
||||
: q_ptr ( q )
|
||||
, resolver ( resolver )
|
||||
{
|
||||
}
|
||||
|
||||
JSInfoSystemHelper* q_ptr;
|
||||
Q_DECLARE_PUBLIC ( JSInfoSystemHelper )
|
||||
|
||||
private:
|
||||
JSResolver* resolver;
|
||||
QMap<int,JSInfoPlugin*> infoPlugins;
|
||||
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // TOMAHAWK_JSINFOSYSTEMHELPER_P_H
|
@ -42,6 +42,7 @@
|
||||
#include "TomahawkSettings.h"
|
||||
#include "TomahawkVersion.h"
|
||||
#include "Track.h"
|
||||
#include "JSInfoPlugin.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
@ -53,6 +54,8 @@
|
||||
#include <QTime>
|
||||
#include <QWebFrame>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
JSResolver::JSResolver( const QString& accountId, const QString& scriptPath, const QStringList& additionalScriptPaths )
|
||||
: Tomahawk::ExternalResolverGui( scriptPath )
|
||||
, d_ptr( new JSResolverPrivate( this, accountId, scriptPath, additionalScriptPaths ) )
|
||||
@ -204,57 +207,48 @@ JSResolver::init()
|
||||
|
||||
d->engine->mainFrame()->setHtml( "<html><body></body></html>", QUrl( "file:///invalid/file/for/security/policy" ) );
|
||||
|
||||
// add c++ part of tomahawk javascript library
|
||||
d->engine->mainFrame()->addToJavaScriptWindowObject( "Tomahawk", d->resolverHelper );
|
||||
|
||||
// Load CrytoJS
|
||||
{
|
||||
d->engine->setScriptPath( "cryptojs-core.js" );
|
||||
QFile jslib( RESPATH "js/cryptojs-core.js" );
|
||||
jslib.open( QIODevice::ReadOnly );
|
||||
d->engine->mainFrame()->evaluateJavaScript( jslib.readAll() );
|
||||
jslib.close();
|
||||
}
|
||||
// tomahawk.js
|
||||
{
|
||||
// add c++ part of tomahawk javascript library
|
||||
d->engine->mainFrame()->addToJavaScriptWindowObject( "Tomahawk", d->resolverHelper );
|
||||
|
||||
// load es6-promises shim
|
||||
loadScript( RESPATH "js/es6-promise-2.0.0.min.js" );
|
||||
|
||||
|
||||
// Load CrytoJS core
|
||||
loadScript( RESPATH "js/cryptojs-core.js" );
|
||||
|
||||
// Load CryptoJS modules
|
||||
QStringList jsfiles;
|
||||
jsfiles << "*.js";
|
||||
QDir cryptojs( RESPATH "js/cryptojs" );
|
||||
foreach ( QString jsfile, cryptojs.entryList( jsfiles ) )
|
||||
{
|
||||
d->engine->setScriptPath( RESPATH "js/cryptojs/" + jsfile );
|
||||
QFile jslib( RESPATH "js/cryptojs/" + jsfile );
|
||||
jslib.open( QIODevice::ReadOnly );
|
||||
d->engine->mainFrame()->evaluateJavaScript( jslib.readAll() );
|
||||
jslib.close();
|
||||
loadScript( RESPATH "js/cryptojs/" + jsfile );
|
||||
}
|
||||
|
||||
// Load tomahawk.js
|
||||
loadScript( RESPATH "js/tomahawk.js" );
|
||||
}
|
||||
|
||||
// tomahawk-infosystem.js
|
||||
{
|
||||
// Load the tomahawk javascript utilities
|
||||
d->engine->setScriptPath( "tomahawk.js" );
|
||||
QFile jslib( RESPATH "js/tomahawk.js" );
|
||||
jslib.open( QIODevice::ReadOnly );
|
||||
d->engine->mainFrame()->evaluateJavaScript( jslib.readAll() );
|
||||
jslib.close();
|
||||
// add c++ part of tomahawk infosystem bindings as Tomahawk.InfoSystem
|
||||
d->engine->mainFrame()->addToJavaScriptWindowObject( "_TomahawkInfoSystem", d->infoSystemHelper );
|
||||
d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.InfoSystem = _TomahawkInfoSystem;" );
|
||||
|
||||
// add deps
|
||||
loadScripts( d->infoSystemHelper->requiredScriptPaths() );
|
||||
}
|
||||
|
||||
// add resolver dependencies, if any
|
||||
foreach ( const QString& s, d->requiredScriptPaths )
|
||||
{
|
||||
QFile reqFile( s );
|
||||
if ( !reqFile.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
qWarning() << "Failed to read contents of file:" << s << reqFile.errorString();
|
||||
return;
|
||||
}
|
||||
const QByteArray reqContents = reqFile.readAll();
|
||||
loadScripts( d->requiredScriptPaths );
|
||||
|
||||
d->engine->setScriptPath( s );
|
||||
d->engine->mainFrame()->evaluateJavaScript( reqContents );
|
||||
}
|
||||
|
||||
// add resolver
|
||||
d->engine->setScriptPath( filePath() );
|
||||
d->engine->mainFrame()->evaluateJavaScript( scriptContents );
|
||||
loadScript( filePath() );
|
||||
|
||||
// init resolver
|
||||
resolverInit();
|
||||
@ -332,10 +326,10 @@ JSResolver::artists( const Tomahawk::collection_ptr& collection )
|
||||
return;
|
||||
}
|
||||
|
||||
QString eval = QString( "Tomahawk.resolver.instance.artists( '%1' );" )
|
||||
.arg( collection->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
QString eval = QString( "artists( '%1' )" )
|
||||
.arg( escape( collection->name() ) );
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( eval ).toMap();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
@ -368,11 +362,11 @@ JSResolver::albums( const Tomahawk::collection_ptr& collection, const Tomahawk::
|
||||
return;
|
||||
}
|
||||
|
||||
QString eval = QString( "Tomahawk.resolver.instance.albums( '%1', '%2' );" )
|
||||
.arg( collection->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( artist->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
QString eval = QString( "albums( '%1', '%2' )" )
|
||||
.arg( escape( collection->name() ) )
|
||||
.arg( escape( artist->name() ) );
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( eval ).toMap();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
@ -405,12 +399,12 @@ JSResolver::tracks( const Tomahawk::collection_ptr& collection, const Tomahawk::
|
||||
return;
|
||||
}
|
||||
|
||||
QString eval = QString( "Tomahawk.resolver.instance.tracks( '%1', '%2', '%3' );" )
|
||||
.arg( collection->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( album->artist()->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( album->name().replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
QString eval = QString( "tracks( '%1', '%2', '%3' )" )
|
||||
.arg( escape( collection->name() ) )
|
||||
.arg( escape( album->artist()->name() ) )
|
||||
.arg( escape( album->name() ) );
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( eval ).toMap();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
@ -438,10 +432,10 @@ JSResolver::canParseUrl( const QString& url, UrlType type )
|
||||
|
||||
if ( d->capabilities.testFlag( UrlLookup ) )
|
||||
{
|
||||
QString eval = QString( "Tomahawk.resolver.instance.canParseUrl( '%1', %2 );" )
|
||||
.arg( QString( url ).replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
QString eval = QString( "canParseUrl( '%1', %2 )" )
|
||||
.arg( escape( QString( url ) ) )
|
||||
.arg( (int) type );
|
||||
return d->engine->mainFrame()->evaluateJavaScript( eval ).toBool();
|
||||
return callOnResolver( eval ).toBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -469,10 +463,10 @@ JSResolver::lookupUrl( const QString& url )
|
||||
return;
|
||||
}
|
||||
|
||||
QString eval = QString( "Tomahawk.resolver.instance.lookupUrl( '%1' );" )
|
||||
.arg( QString( url ).replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
QString eval = QString( "lookupUrl( '%1' )" )
|
||||
.arg( escape( QString( url ) ) );
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( eval ).toMap();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
@ -485,6 +479,39 @@ JSResolver::lookupUrl( const QString& url )
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
JSResolver::evaluateJavaScriptInternal(const QString& scriptSource)
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
return d->engine->mainFrame()->evaluateJavaScript( scriptSource );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::evaluateJavaScript( const QString& scriptSource )
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "evaluateJavaScript", Qt::QueuedConnection, Q_ARG( QString, scriptSource ) );
|
||||
return;
|
||||
}
|
||||
|
||||
evaluateJavaScriptInternal( scriptSource );
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
JSResolver::evaluateJavaScriptWithResult( const QString& scriptSource )
|
||||
{
|
||||
Q_ASSERT( QThread::currentThread() == thread() );
|
||||
|
||||
return evaluateJavaScriptInternal( scriptSource );
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::ExternalResolver::ErrorState
|
||||
JSResolver::error() const
|
||||
{
|
||||
@ -508,20 +535,20 @@ JSResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
QString eval;
|
||||
if ( !query->isFullTextQuery() )
|
||||
{
|
||||
eval = QString( "Tomahawk.resolver.instance.resolve( '%1', '%2', '%3', '%4' );" )
|
||||
.arg( query->id().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( query->queryTrack()->artist().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( query->queryTrack()->album().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( query->queryTrack()->track().replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
eval = QString( "resolve( '%1', '%2', '%3', '%4' )" )
|
||||
.arg( escape( query->id() ) )
|
||||
.arg( escape( query->queryTrack()->artist() ) )
|
||||
.arg( escape( query->queryTrack()->album() ) )
|
||||
.arg( escape( query->queryTrack()->track() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
eval = QString( "Tomahawk.resolver.instance.search( '%1', '%2' );" )
|
||||
.arg( query->id().replace( "\\", "\\\\" ).replace( "'", "\\'" ) )
|
||||
.arg( query->fullTextQuery().replace( "\\", "\\\\" ).replace( "'", "\\'" ) );
|
||||
eval = QString( "search( '%1', '%2' )" )
|
||||
.arg( escape( query->id() ) )
|
||||
.arg( escape( query->fullTextQuery() ) );
|
||||
}
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( eval ).toMap();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
@ -667,7 +694,7 @@ JSResolver::loadUi()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
QVariantMap m = d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.getConfigUi();" ).toMap();
|
||||
QVariantMap m = callOnResolver( "getConfigUi()" ).toMap();
|
||||
d->dataWidgets = m["fields"].toList();
|
||||
|
||||
bool compressed = m.value( "compressed", "false" ).toBool();
|
||||
@ -716,7 +743,7 @@ JSResolver::saveConfig()
|
||||
// qDebug() << Q_FUNC_INFO << saveData;
|
||||
|
||||
d->resolverHelper->setResolverConfig( saveData.toMap() );
|
||||
d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.saveUserConfig();" );
|
||||
callOnResolver( "saveUserConfig()" );
|
||||
}
|
||||
|
||||
|
||||
@ -815,7 +842,7 @@ JSResolver::loadCollections()
|
||||
|
||||
if ( d->capabilities.testFlag( Browsable ) )
|
||||
{
|
||||
const QVariantMap collectionInfo = d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.collection();" ).toMap();
|
||||
const QVariantMap collectionInfo = callOnResolver( "collection()" ).toMap();
|
||||
if ( collectionInfo.isEmpty() ||
|
||||
!collectionInfo.contains( "prettyname" ) ||
|
||||
!collectionInfo.contains( "description" ) )
|
||||
@ -912,7 +939,7 @@ JSResolver::resolverSettings()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
return d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.settings;" ).toMap();
|
||||
return callOnResolver( "settings" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
@ -921,7 +948,7 @@ JSResolver::resolverUserConfig()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
return d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.getUserConfig();" ).toMap();
|
||||
return callOnResolver( "getUserConfig()" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
@ -930,7 +957,7 @@ JSResolver::resolverInit()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
return d->engine->mainFrame()->evaluateJavaScript( "Tomahawk.resolver.instance.init();" ).toMap();
|
||||
return callOnResolver( "init()" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
@ -943,3 +970,61 @@ JSResolver::resolverCollections()
|
||||
// Then when there's callbacks from a resolver, it sends source name, collection id
|
||||
// + data.
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::loadScript( const QString& path )
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
QFile file( path );
|
||||
|
||||
if ( !file.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
qWarning() << "Failed to read contents of file:" << path << file.errorString();
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray contents = file.readAll();
|
||||
|
||||
d->engine->setScriptPath( path );
|
||||
d->engine->mainFrame()->evaluateJavaScript( contents );
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::loadScripts( const QStringList& paths )
|
||||
{
|
||||
foreach ( const QString& path, paths )
|
||||
{
|
||||
loadScript( path );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
JSResolver::callOnResolver( const QString& scriptSource )
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
QString propertyName = scriptSource.split('(').first();
|
||||
|
||||
return d->engine->mainFrame()->evaluateJavaScript( QString(
|
||||
"if(Tomahawk.resolver.instance['_adapter_%1']) {"
|
||||
" Tomahawk.resolver.instance._adapter_%2;"
|
||||
"} else {"
|
||||
" Tomahawk.resolver.instance.%2"
|
||||
"}"
|
||||
).arg( propertyName ).arg( scriptSource ) );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSResolver::escape( const QString& source )
|
||||
{
|
||||
QString copy = source;
|
||||
return copy.replace( "\\", "\\\\" ).replace( "'", "\\'" );
|
||||
}
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include "ExternalResolverGui.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSInfoPlugin;
|
||||
class JSResolverHelper;
|
||||
class JSResolverPrivate;
|
||||
class ScriptEngine;
|
||||
@ -35,7 +39,7 @@ class DLLEXPORT JSResolver : public Tomahawk::ExternalResolverGui
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ::JSResolverHelper;
|
||||
friend class JSResolverHelper;
|
||||
|
||||
public:
|
||||
explicit JSResolver( const QString& accountId, const QString& scriptPath, const QStringList& additionalScriptPaths = QStringList() );
|
||||
@ -60,6 +64,21 @@ public:
|
||||
|
||||
bool canParseUrl( const QString& url, UrlType type ) override;
|
||||
|
||||
/**
|
||||
* Evaluate JavaScript on the WebKit thread
|
||||
*/
|
||||
Q_INVOKABLE void evaluateJavaScript( const QString& scriptSource );
|
||||
|
||||
/**
|
||||
* This method must be called from the WebKit thread
|
||||
*/
|
||||
QVariant evaluateJavaScriptWithResult( const QString& scriptSource );
|
||||
|
||||
/**
|
||||
* Escape \ and ' in strings so they are safe to use in JavaScript
|
||||
*/
|
||||
static QString escape( const QString& source );
|
||||
|
||||
public slots:
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
void stop() override;
|
||||
@ -75,6 +94,9 @@ public slots:
|
||||
signals:
|
||||
void stopped();
|
||||
|
||||
protected:
|
||||
QVariant callOnResolver( const QString& scriptSource );
|
||||
|
||||
private slots:
|
||||
void onCollectionIconFetched();
|
||||
|
||||
@ -88,6 +110,13 @@ private:
|
||||
void fillDataInWidgets( const QVariantMap& data );
|
||||
void onCapabilitiesChanged( Capabilities capabilities );
|
||||
void loadCollections();
|
||||
void loadScript( const QString& path );
|
||||
void loadScripts( const QStringList& paths );
|
||||
|
||||
/**
|
||||
* Wrap the pure evaluateJavaScript call in here, while the threadings guards are in public methods
|
||||
*/
|
||||
QVariant evaluateJavaScriptInternal( const QString& scriptSource );
|
||||
|
||||
// encapsulate javascript calls
|
||||
QVariantMap resolverSettings();
|
||||
@ -104,4 +133,5 @@ private:
|
||||
QScopedPointer<JSResolverPrivate> d_ptr;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
#endif // JSRESOLVER_H
|
||||
|
@ -125,7 +125,7 @@ JSResolverHelper::resolverData()
|
||||
void
|
||||
JSResolverHelper::log( const QString& message )
|
||||
{
|
||||
tLog() << m_scriptPath << ":" << message;
|
||||
tLog() << "JAVASCRIPT:" << m_scriptPath << ":" << message;
|
||||
}
|
||||
|
||||
|
||||
@ -460,6 +460,17 @@ JSResolverHelper::reportStreamUrl( const QString& qid, const QString& streamUrl
|
||||
}
|
||||
|
||||
|
||||
void JSResolverHelper::nativeAssert(bool assertion, const QString& message)
|
||||
{
|
||||
if ( !assertion )
|
||||
{
|
||||
tLog() << "Assertion failed" << message;
|
||||
Q_ASSERT( assertion );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr&, const QString& url,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback )
|
||||
|
@ -34,9 +34,14 @@
|
||||
#include <functional>
|
||||
|
||||
|
||||
class JSResolver;
|
||||
|
||||
Q_DECLARE_METATYPE( std::function< void( QSharedPointer< QIODevice >& ) > )
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSResolver;
|
||||
|
||||
class DLLEXPORT JSResolverHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -60,6 +65,11 @@ public:
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl );
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl, const QVariantMap& headers );
|
||||
|
||||
/**
|
||||
* Make Tomahawk assert the assertion is true, probably not to be used by resolvers directly
|
||||
*/
|
||||
Q_INVOKABLE void nativeAssert( bool assertion, const QString& message = QString() );
|
||||
|
||||
/**
|
||||
* Retrieve metadata for a media stream.
|
||||
*
|
||||
@ -156,4 +166,7 @@ private:
|
||||
QString m_pendingUrl;
|
||||
Tomahawk::album_ptr m_pendingAlbum;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // JSRESOLVERHELPER_H
|
||||
|
@ -25,11 +25,15 @@
|
||||
#include "JSResolver.h"
|
||||
|
||||
#include "JSResolverHelper.h"
|
||||
#include "JSInfoSystemHelper.h"
|
||||
#include "database/fuzzyindex/FuzzyIndex.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSResolverPrivate
|
||||
{
|
||||
friend class ::JSResolverHelper;
|
||||
friend class JSResolverHelper;
|
||||
public:
|
||||
JSResolverPrivate( JSResolver* q, const QString& pAccountId, const QString& scriptPath, const QStringList& additionalScriptPaths )
|
||||
: q_ptr ( q )
|
||||
@ -38,6 +42,8 @@ public:
|
||||
, stopped( true )
|
||||
, error( Tomahawk::ExternalResolver::NoError )
|
||||
, resolverHelper( new JSResolverHelper( scriptPath, q ) )
|
||||
// TODO: be smarter about this, only instantiate this if the resolver supports infoplugins
|
||||
, infoSystemHelper( new JSInfoSystemHelper( q ) )
|
||||
, requiredScriptPaths( additionalScriptPaths )
|
||||
{
|
||||
}
|
||||
@ -58,11 +64,13 @@ private:
|
||||
Tomahawk::ExternalResolver::ErrorState error;
|
||||
|
||||
JSResolverHelper* resolverHelper;
|
||||
JSInfoSystemHelper* infoSystemHelper;
|
||||
QScopedPointer<FuzzyIndex> fuzzyIndex;
|
||||
QPointer< AccountConfigWidget > configWidget;
|
||||
QList< QVariant > dataWidgets;
|
||||
QStringList requiredScriptPaths;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // JSRESOLVER_P_H
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand : public QObject
|
||||
{
|
||||
public:
|
||||
@ -36,4 +39,6 @@ protected:
|
||||
virtual void reportFailure() = 0;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_H
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <QMetaType>
|
||||
#include <QMutex>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommandQueue::ScriptCommandQueue( QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_timer( new QTimer( this ) )
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include <QMetaType>
|
||||
#include <QMutex>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommandQueue : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -47,6 +50,8 @@ private:
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( QSharedPointer< ScriptCommand > )
|
||||
} // ns: Tomahawk
|
||||
|
||||
Q_DECLARE_METATYPE( QSharedPointer< Tomahawk::ScriptCommand > )
|
||||
|
||||
#endif // SCRIPTCOMMANDQUEUE_H
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "PlaylistEntry.h"
|
||||
#include "ScriptCollection.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_AllAlbums::ScriptCommand_AllAlbums( const Tomahawk::collection_ptr& collection,
|
||||
const Tomahawk::artist_ptr& artist,
|
||||
QObject* parent )
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "collection/Collection.h"
|
||||
#include "resolvers/ScriptCommand.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand_AllAlbums : public ScriptCommand, public Tomahawk::AlbumsRequest
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -54,4 +57,6 @@ private:
|
||||
QString m_filter;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_ALLALBUMS_H
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_AllArtists::ScriptCommand_AllArtists( const Tomahawk::collection_ptr& collection,
|
||||
QObject* parent )
|
||||
: ScriptCommand( parent )
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "collection/Collection.h"
|
||||
#include "resolvers/ScriptCommand.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand_AllArtists : public ScriptCommand, public Tomahawk::ArtistsRequest
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -52,4 +55,6 @@ private:
|
||||
QString m_filter;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_ALLARTISTS_H
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_AllTracks::ScriptCommand_AllTracks( const Tomahawk::collection_ptr& collection,
|
||||
const Tomahawk::album_ptr& album,
|
||||
QObject* parent )
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "collection/Collection.h"
|
||||
#include "resolvers/ScriptCommand.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand_AllTracks : public ScriptCommand, public Tomahawk::TracksRequest
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -51,4 +54,6 @@ private:
|
||||
Tomahawk::album_ptr m_album;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_ALLTRACKS_H
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "PlaylistEntry.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_LookupUrl::ScriptCommand_LookupUrl( Tomahawk::ExternalResolver* resolver, const QString& url, QObject* parent )
|
||||
: ScriptCommand( parent )
|
||||
, d_ptr( new ScriptCommand_LookupUrlPrivate( this, resolver, url ) )
|
||||
|
@ -26,15 +26,12 @@
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
class ScriptCommand_LookupUrlPrivate;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand_LookupUrlPrivate;
|
||||
class ExternalResolver;
|
||||
|
||||
}
|
||||
|
||||
class DLLEXPORT ScriptCommand_LookupUrl : public ScriptCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -62,4 +59,6 @@ private:
|
||||
ScriptCommand_LookupUrlPrivate* d_ptr;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_LOOKUPURL_H
|
||||
|
@ -23,6 +23,9 @@
|
||||
|
||||
#include "ExternalResolver.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ScriptCommand_LookupUrlPrivate
|
||||
{
|
||||
public:
|
||||
@ -40,4 +43,6 @@ private:
|
||||
Tomahawk::ExternalResolver* resolver;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTCOMMAND_LOOKUPURL_P_H
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptEngine::ScriptEngine( JSResolver* parent )
|
||||
: QWebPage( (QObject*) parent )
|
||||
, m_parent( parent )
|
||||
|
@ -27,9 +27,13 @@
|
||||
#include <QSslError>
|
||||
#include <QWebPage>
|
||||
|
||||
class JSResolver;
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class JSResolver;
|
||||
|
||||
class DLLEXPORT ScriptEngine : public QWebPage
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -55,4 +59,6 @@ private:
|
||||
QString m_header;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
||||
#endif // SCRIPTENGINE_H
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <shlwapi.h>
|
||||
#endif
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptResolver::ScriptResolver( const QString& exe )
|
||||
: Tomahawk::ExternalResolverGui( exe )
|
||||
, m_num_restarts( 0 )
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT ScriptResolver : public Tomahawk::ExternalResolverGui
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -107,4 +110,6 @@ private:
|
||||
ExternalResolver::ErrorState m_error;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SCRIPTRESOLVER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user