diff --git a/data/js/tomahawk-infosystem.js b/data/js/tomahawk-infosystem.js index 6fde5f1e1..1c7652790 100644 --- a/data/js/tomahawk-infosystem.js +++ b/data/js/tomahawk-infosystem.js @@ -4,7 +4,7 @@ if(window.Promise === undefined) { } // TODO: find a way to enumerate TypeInfo instead of copying this manually - +Tomahawk.InfoSystem = Tomahawk.InfoSystem || {}; Tomahawk.InfoSystem.InfoType = Object.create(null); Tomahawk.InfoSystem.InfoType.InfoNoInfo = 0; //WARNING: *ALWAYS* keep this first! @@ -92,25 +92,6 @@ 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) { @@ -119,13 +100,8 @@ Tomahawk.InfoSystem.InfoPlugin = { } } }, - // 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 (params) { + return this.notInCache(params.type, params.criteria); }, notInCache: function (infoType, criteria) { var requestMethod = 'request' + this.infoTypeString(infoType); @@ -136,14 +112,8 @@ Tomahawk.InfoSystem.InfoPlugin = { 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 (params) { + return this.getInfo(params.type, params.data); }, getInfo: function (type, infoHash) { var getInfoMethod = 'get' + this.infoTypeString(type); diff --git a/data/js/tomahawk.js b/data/js/tomahawk.js index 80e9168ac..5eb498080 100644 --- a/data/js/tomahawk.js +++ b/data/js/tomahawk.js @@ -615,8 +615,8 @@ Tomahawk.PluginManager = { Tomahawk.registerScriptPlugin(type, object.id); }, - invoke: function (requestId, objectId, methodName, params ) { - Tomahawk.log("requestId: " + requestId + " objectId: " + objectId + " methodName: " + methodName + " params: " + params); + + invokeSync: function (objectId, methodName, params) { if (!this.objects[objectId]) { Tomahawk.log("Object not found!"); } else { @@ -625,7 +625,15 @@ Tomahawk.PluginManager = { } } - Promise.resolve(this.objects[objectId][methodName](params)).then(function (result) { + if (typeof this.objects[objectId][methodName] === 'function') { + return this.objects[objectId][methodName](params); + } + + return this.objects[objectId][methodName]; + }, + + invoke: function (requestId, objectId, methodName, params ) { + Promise.resolve(this.invokeSync(objectId, methodName, params)).then(function (result) { if (typeof result === 'object') { Tomahawk.reportScriptJobResults({ requestId: requestId, @@ -634,7 +642,7 @@ Tomahawk.PluginManager = { } else { Tomahawk.reportScriptJobResults({ requestId: requestId, - error: "Scripts need to return objects for requests" + error: "Scripts need to return objects for requests: methodName: " + methodName + " params: " + JSON.encode(params) }); } }, function (error) { diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index d3819a607..a4d64b576 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -85,7 +85,6 @@ set( libGuiSources resolvers/ExternalResolverGui.cpp resolvers/ScriptResolver.cpp resolvers/ScriptInfoPlugin.cpp - resolvers/JSInfoSystemHelper.cpp resolvers/JSResolver.cpp resolvers/JSResolverHelper.cpp resolvers/ScriptEngine.cpp diff --git a/src/libtomahawk/resolvers/JSAccount.cpp b/src/libtomahawk/resolvers/JSAccount.cpp index 4899853e1..fae5af4f1 100644 --- a/src/libtomahawk/resolvers/JSAccount.cpp +++ b/src/libtomahawk/resolvers/JSAccount.cpp @@ -32,8 +32,8 @@ using namespace Tomahawk; JSAccount::JSAccount( const QString& name ) - : m_engine( new ScriptEngine( this ) ) - , m_name( name ) + : ScriptAccount( name ) + , m_engine( new ScriptEngine( this ) ) { } @@ -58,7 +58,7 @@ JSAccount::scriptPluginFactory( const QString& type, ScriptObject* object ) if ( type == "resolver" ) { Q_ASSERT( m_resolver ); - m_resolver->m_object = object; + m_resolver->m_scriptObject = object; } else { @@ -150,6 +150,26 @@ JSAccount::startJob( ScriptJob* scriptJob ) } +const QVariant +JSAccount::syncInvoke( ScriptObject* scriptObject, const QString& methodName, const QVariantMap& arguments ) +{ + QString eval = QString( + "Tomahawk.PluginManager.invokeSync(" + "'%1'," // objectId + "'%2'," // methodName + "%3" // arguments + ");" + ).arg( scriptObject->id() ) + .arg( methodName ) + .arg( serializeQVariantMap( arguments ) ); + + // Remove when new scripting api turned out to work reliably + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval; + + return evaluateJavaScriptWithResult( eval ); +} + + const QString JSAccount::name() const { diff --git a/src/libtomahawk/resolvers/JSAccount.h b/src/libtomahawk/resolvers/JSAccount.h index b4a51ca35..42cd778b6 100644 --- a/src/libtomahawk/resolvers/JSAccount.h +++ b/src/libtomahawk/resolvers/JSAccount.h @@ -45,6 +45,7 @@ public: JSAccount( const QString& name ); void startJob( ScriptJob* scriptJob ) override; + const QVariant syncInvoke( ScriptObject* scriptObject, const QString& methodName, const QVariantMap& arguments ) override; const QString name() const; diff --git a/src/libtomahawk/resolvers/JSInfoSystemHelper.cpp b/src/libtomahawk/resolvers/JSInfoSystemHelper.cpp deleted file mode 100644 index 0da167c88..000000000 --- a/src/libtomahawk/resolvers/JSInfoSystemHelper.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* === This file is part of Tomahawk Player - === -* -* Copyright 2014, Dominik Schmidt -* -* 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 . -*/ - -#include "JSInfoSystemHelper_p.h" -#include "ScriptInfoPlugin.h" - -#include "JSAccount.h" -#include "../utils/Logger.h" - -using namespace Tomahawk; - -JSInfoSystemHelper::JSInfoSystemHelper( JSAccount* 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 - ScriptInfoPlugin* scriptInfoPlugin = new ScriptInfoPlugin( id, d->scriptAccount ); - Tomahawk::InfoSystem::InfoPluginPtr infoPlugin( scriptInfoPlugin ); - - // move it to infosystem thread - infoPlugin->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); - - // add it to local list of infoplugins - d->infoPlugins[id] = scriptInfoPlugin; - - // 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() ); -} diff --git a/src/libtomahawk/resolvers/JSInfoSystemHelper.h b/src/libtomahawk/resolvers/JSInfoSystemHelper.h deleted file mode 100644 index 209e2fce7..000000000 --- a/src/libtomahawk/resolvers/JSInfoSystemHelper.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === This file is part of Tomahawk Player - === -* -* Copyright 2014, Dominik Schmidt -* -* 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 . -*/ - -#ifndef TOMAHAWK_JSINFOSYSTEMHELPER_H -#define TOMAHAWK_JSINFOSYSTEMHELPER_H - -#include - -namespace Tomahawk -{ - -class JSAccount; -class JSInfoSystemHelperPrivate; - -class JSInfoSystemHelper : public QObject -{ - Q_OBJECT - -public: - JSInfoSystemHelper( JSAccount* 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 d_ptr; -}; - -} // ns: Tomahawk - -#endif // TOMAHAWK_JSINFOSYSTEMHELPER_H diff --git a/src/libtomahawk/resolvers/JSInfoSystemHelper_p.h b/src/libtomahawk/resolvers/JSInfoSystemHelper_p.h deleted file mode 100644 index 3913adcc9..000000000 --- a/src/libtomahawk/resolvers/JSInfoSystemHelper_p.h +++ /dev/null @@ -1,49 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2014, Dominik Schmidt - * - * 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 . - */ - -#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, JSAccount* scriptAccount ) - : q_ptr ( q ) - , scriptAccount ( scriptAccount ) - { - } - - JSInfoSystemHelper* q_ptr; - Q_DECLARE_PUBLIC ( JSInfoSystemHelper ) - -private: - JSAccount* scriptAccount; - QMap infoPlugins; - -}; - -} // ns: Tomahawk - -#endif // TOMAHAWK_JSINFOSYSTEMHELPER_P_H diff --git a/src/libtomahawk/resolvers/JSResolver.cpp b/src/libtomahawk/resolvers/JSResolver.cpp index a733cc36c..7ea293eb0 100644 --- a/src/libtomahawk/resolvers/JSResolver.cpp +++ b/src/libtomahawk/resolvers/JSResolver.cpp @@ -233,15 +233,10 @@ JSResolver::init() // tomahawk-infosystem.js { - // TODO: be smarter about this, only instantiate this if the resolver supports infoplugins - - // add c++ part of tomahawk infosystem bindings as Tomahawk.InfoSystem - d->infoSystemHelper = new JSInfoSystemHelper( d->scriptAccount.get() ); - d->scriptAccount->addToJavaScriptWindowObject( "_TomahawkInfoSystem", d->infoSystemHelper ); - d->scriptAccount->evaluateJavaScript( "Tomahawk.InfoSystem = _TomahawkInfoSystem;" ); + // TODO: be smarter about this, only include this if the resolver supports infoplugins // add deps - d->scriptAccount->loadScripts( d->infoSystemHelper->requiredScriptPaths() ); + d->scriptAccount->loadScript( RESPATH "js/tomahawk-infosystem.js" ); } // add resolver dependencies, if any diff --git a/src/libtomahawk/resolvers/JSResolver_p.h b/src/libtomahawk/resolvers/JSResolver_p.h index bd29fa83e..21d8b539d 100644 --- a/src/libtomahawk/resolvers/JSResolver_p.h +++ b/src/libtomahawk/resolvers/JSResolver_p.h @@ -25,7 +25,6 @@ #include "JSResolver.h" #include "JSResolverHelper.h" -#include "JSInfoSystemHelper.h" #include "database/fuzzyindex/FuzzyIndex.h" #include // unique_ptr @@ -44,7 +43,6 @@ public: , stopped( true ) , error( Tomahawk::ExternalResolver::NoError ) , resolverHelper( new JSResolverHelper( scriptPath, q ) ) - , infoSystemHelper( nullptr ) , requiredScriptPaths( additionalScriptPaths ) { } @@ -63,7 +61,6 @@ private: Tomahawk::ExternalResolver::ErrorState error; JSResolverHelper* resolverHelper; - JSInfoSystemHelper* infoSystemHelper; QScopedPointer fuzzyIndex; QPointer< AccountConfigWidget > configWidget; QList< QVariant > dataWidgets; diff --git a/src/libtomahawk/resolvers/ScriptAccount.cpp b/src/libtomahawk/resolvers/ScriptAccount.cpp index 7fd013bd6..4a97a72a9 100644 --- a/src/libtomahawk/resolvers/ScriptAccount.cpp +++ b/src/libtomahawk/resolvers/ScriptAccount.cpp @@ -21,13 +21,21 @@ #include "ScriptObject.h" #include "../utils/Logger.h" - // TODO: register factory methods instead of hardcoding all plugin types in here #include "../utils/LinkGenerator.h" #include "ScriptLinkGeneratorPlugin.h" +#include "ScriptInfoPlugin.h" using namespace Tomahawk; + +ScriptAccount::ScriptAccount( const QString& name ) + : QObject() + , m_name( name ) +{ +} + + static QString requestIdGenerator() { @@ -43,6 +51,9 @@ ScriptAccount::invoke( ScriptObject* scriptObject, const QString& methodName, co QString requestId = requestIdGenerator(); ScriptJob* job = new ScriptJob( requestId, scriptObject, methodName, arguments ); + // TODO: setParent through QueuedConnection + + connect( job, SIGNAL( destroyed( QString ) ), SLOT( onJobDeleted( QString ) ) ); m_jobs.insert( requestId, job ); @@ -97,6 +108,18 @@ ScriptAccount::scriptPluginFactory( const QString& type, ScriptObject* object ) ScriptLinkGeneratorPlugin* lgp = new ScriptLinkGeneratorPlugin( object ); Utils::LinkGenerator::instance()->addPlugin( lgp ); } + else if ( type == "infoPlugin" ) + { + // create infoplugin instance + ScriptInfoPlugin* scriptInfoPlugin = new ScriptInfoPlugin( object, m_name ); + Tomahawk::InfoSystem::InfoPluginPtr infoPlugin( scriptInfoPlugin ); + + // move it to infosystem thread + infoPlugin->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); + + // add it to infosystem + Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin ); + } else { tLog() << "This plugin type is not handled by Tomahawk"; diff --git a/src/libtomahawk/resolvers/ScriptAccount.h b/src/libtomahawk/resolvers/ScriptAccount.h index cbb42b599..b3b37c6b2 100644 --- a/src/libtomahawk/resolvers/ScriptAccount.h +++ b/src/libtomahawk/resolvers/ScriptAccount.h @@ -39,9 +39,12 @@ class DLLEXPORT ScriptAccount : public QObject Q_OBJECT public: + ScriptAccount( const QString& name ); virtual ~ScriptAccount() {} ScriptJob* invoke( ScriptObject* scriptObject, const QString& methodName, const QVariantMap& arguments ); + virtual const QVariant syncInvoke( ScriptObject* scriptObject, const QString& methodName, const QVariantMap& arguments ) = 0; + virtual void startJob( ScriptJob* scriptJob ) = 0; void reportScriptJobResult( const QVariantMap& result ); @@ -53,6 +56,7 @@ private slots: void onJobDeleted( const QString& jobId ); private: // TODO: pimple, might be renamed before tho + QString m_name; QHash< QString, ScriptJob* > m_jobs; QHash< QString, ScriptObject* > m_objects; }; diff --git a/src/libtomahawk/resolvers/ScriptInfoPlugin.cpp b/src/libtomahawk/resolvers/ScriptInfoPlugin.cpp index 502de09b8..0a6e12b96 100644 --- a/src/libtomahawk/resolvers/ScriptInfoPlugin.cpp +++ b/src/libtomahawk/resolvers/ScriptInfoPlugin.cpp @@ -20,22 +20,25 @@ #include "JSAccount.h" #include "Typedefs.h" +#include "ScriptObject.h" +#include "ScriptJob.h" #include "../utils/Logger.h" #include "../utils/Json.h" using namespace Tomahawk; -ScriptInfoPlugin::ScriptInfoPlugin( int id, JSAccount *resolver ) - : d_ptr( new ScriptInfoPluginPrivate( this, id, resolver ) ) +ScriptInfoPlugin::ScriptInfoPlugin( ScriptObject* scriptObject, const QString& name ) + : d_ptr( new ScriptInfoPluginPrivate( this ) ) + , ScriptPlugin( scriptObject ) { - Q_ASSERT( resolver ); + Q_ASSERT( scriptObject ); // 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" ) ); + m_supportedGetTypes = parseSupportedTypes( m_scriptObject->syncInvoke( "supportedGetTypes" ) ); + m_supportedPushTypes = parseSupportedTypes( m_scriptObject->syncInvoke( "supportedPushTypes" ) ); - setFriendlyName( QString( "ScriptInfoPlugin: %1" ).arg( resolver->name() ) ); + setFriendlyName( QString( "ScriptInfoPlugin: %1" ).arg( name ) ); } @@ -55,28 +58,29 @@ ScriptInfoPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) { Q_D( ScriptInfoPlugin ); - 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( serializeQVariantMap( convertInfoStringHashToQVariantMap( requestData.input.value() ) ) ); // infoHash + QVariantMap arguments; + arguments[ "type" ] = requestData.type; + arguments[ "data" ] = convertInfoStringHashToQVariantMap( requestData.input.value() ); - callMethodOnInfoPlugin( eval ); + ScriptJob* job = m_scriptObject->invoke( "_getInfo", arguments ); + connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onGetInfoRequestDone( QVariantMap ) ) ); + + d->requestDataCache[ job->id().toInt() ] = requestData; + job->start(); } void ScriptInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) { - QString eval = QString( "pushInfo({ type: %1, pushFlags: %2, input: %3, additionalInput: %4})" ) - .arg( pushData.type ) - .arg( pushData.pushFlags ) - .arg( serializeQVariantMap ( pushData.infoPair.second.toMap() ) ) - .arg( serializeQVariantMap( pushData.infoPair.first ) ); + QVariantMap arguments; + arguments[ "type" ] = pushData.type; + arguments[ "pushFlags" ] = pushData.pushFlags; + arguments[ "input" ] = serializeQVariantMap ( pushData.infoPair.second.toMap() ); + arguments[ "additionalInput" ] = serializeQVariantMap( pushData.infoPair.first ); - callMethodOnInfoPlugin( eval ); + m_scriptObject->invoke( "pushInfo", arguments ); } @@ -85,112 +89,70 @@ ScriptInfoPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, { Q_D( ScriptInfoPlugin ); - d->requestDataCache[ requestData.requestId ] = requestData; - d->criteriaCache[ requestData.requestId ] = criteria; + QVariantMap arguments; + arguments[ "type" ] = requestData.type; + arguments[ "criteria" ] = convertInfoStringHashToQVariantMap( criteria ); + ScriptJob* job = m_scriptObject->invoke( "_notInCache", arguments ); + connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onNotInCacheRequestDone( QVariantMap ) ) ); + d->requestDataCache[ job->id().toInt() ] = requestData; + d->criteriaCache[ job->id().toInt() ] = criteria; - QString eval = QString( "_notInCache(%1, %2, %3, %4)" ) - .arg( d->id ) - .arg( requestData.requestId ) - .arg( requestData.type ) - .arg( serializeQVariantMap( convertInfoStringHashToQVariantMap( criteria ) ) ); - - callMethodOnInfoPlugin( eval ); + job->start(); } void -ScriptInfoPlugin::addInfoRequestResult( int requestId, qint64 maxAge, const QVariantMap& returnedData ) +ScriptInfoPlugin::onGetInfoRequestDone( const QVariantMap& result ) { - if ( QThread::currentThread() != thread() ) - { - QMetaObject::invokeMethod( this, "addInfoRequestResult", Qt::QueuedConnection, Q_ARG( int, requestId ), Q_ARG( qint64, maxAge ), Q_ARG( QVariantMap, returnedData ) ); - return; - } + Q_ASSERT( QThread::currentThread() == thread() ); Q_D( ScriptInfoPlugin ); + + + ScriptJob* job = qobject_cast< ScriptJob* >( sender() ); + + if ( job->error() ) + { + emit info( d->requestDataCache[ job->id().toInt() ], QVariantMap() ); + } + else + { + + emit getCachedInfo( convertQVariantMapToInfoStringHash( result[ "criteria" ].toMap() ), result[ "newMaxAge" ].toLongLong(), d->requestDataCache[ job->id().toInt() ] ); + } + + d->requestDataCache.remove( job->id().toInt() ); + sender()->deleteLater(); +} + + +void +ScriptInfoPlugin::onNotInCacheRequestDone( const QVariantMap& result ) +{ + Q_ASSERT( QThread::currentThread() == thread() ); + + Q_D( ScriptInfoPlugin ); + + ScriptJob* job = qobject_cast< ScriptJob* >( sender() ); + // retrieve requestData from cache and delete it - Tomahawk::InfoSystem::InfoRequestData requestData = d->requestDataCache[ requestId ]; - d->requestDataCache.remove( requestId ); + Tomahawk::InfoSystem::InfoRequestData requestData = d->requestDataCache[ job->id().toInt() ]; + d->requestDataCache.remove( job->id().toInt() ); - emit info( requestData, returnedData ); + emit info( requestData, result[ "data" ].toMap() ); // retrieve criteria from cache and delete it - Tomahawk::InfoSystem::InfoStringHash criteria = d->criteriaCache[ requestId ]; - d->criteriaCache.remove( requestId ); + Tomahawk::InfoSystem::InfoStringHash criteria = d->criteriaCache[ job->id().toInt() ]; + d->criteriaCache.remove( job->id().toInt() ); - emit updateCache( criteria, maxAge, requestData.type, returnedData ); + emit updateCache( criteria, result[ "maxAge" ].toLongLong(), requestData.type, result[ "data" ].toMap() ); + + sender()->deleteLater(); } -void -ScriptInfoPlugin::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( ScriptInfoPlugin ); - - - emit getCachedInfo( convertQVariantMapToInfoStringHash( criteria ), newMaxAge, d->requestDataCache[ requestId ]); -} - - -void -ScriptInfoPlugin::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( ScriptInfoPlugin ); - - emit info( d->requestDataCache[ requestId ], output ); -} - - -QString -ScriptInfoPlugin::serviceGetter() const -{ - Q_D( const ScriptInfoPlugin ); - - return QString( "Tomahawk.InfoSystem.getInfoPlugin(%1)" ).arg( d->id ); -} - -// TODO: DRY, really move things into base class -void -ScriptInfoPlugin::callMethodOnInfoPlugin( const QString& scriptSource ) -{ - Q_D( ScriptInfoPlugin ); - - QString eval = QString( "%1.%2" ).arg( serviceGetter() ).arg( scriptSource ); - - tLog() << Q_FUNC_INFO << eval; - - d->resolver->evaluateJavaScript( eval ); -} - - -QVariant -ScriptInfoPlugin::callMethodOnInfoPluginWithResult(const QString& scriptSource) -{ - Q_D( ScriptInfoPlugin ); - - QString eval = QString( "%1.%2" ).arg( serviceGetter() ).arg( scriptSource ); - - tLog() << Q_FUNC_INFO << eval; - - return d->resolver->evaluateJavaScriptWithResult( eval ); -} - - - QSet< Tomahawk::InfoSystem::InfoType > ScriptInfoPlugin::parseSupportedTypes( const QVariant& variant ) { diff --git a/src/libtomahawk/resolvers/ScriptInfoPlugin.h b/src/libtomahawk/resolvers/ScriptInfoPlugin.h index 8c8b280ae..cab46ba96 100644 --- a/src/libtomahawk/resolvers/ScriptInfoPlugin.h +++ b/src/libtomahawk/resolvers/ScriptInfoPlugin.h @@ -20,6 +20,7 @@ #define TOMAHAWK_SCRIPTINFOPLUGIN_H #include "../infosystem/InfoSystem.h" +#include "ScriptPlugin.h" #include "DllMacro.h" @@ -29,9 +30,10 @@ namespace Tomahawk class JSAccount; class ScriptInfoPluginPrivate; +class ScriptObject; -class DLLEXPORT ScriptInfoPlugin : public Tomahawk::InfoSystem::InfoPlugin +class DLLEXPORT ScriptInfoPlugin : public Tomahawk::InfoSystem::InfoPlugin, Tomahawk::ScriptPlugin { Q_OBJECT @@ -39,14 +41,9 @@ public: /** * @param id unique identifier to identify an infoplugin in its scope */ - ScriptInfoPlugin( int id, JSAccount* resolver ); + ScriptInfoPlugin( ScriptObject* scriptObject, const QString& name ); virtual ~ScriptInfoPlugin(); - - 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; @@ -54,11 +51,8 @@ protected slots: void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) override; void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) override; -protected: - // TODO: create JSAccount base class and move these methods there - QString serviceGetter() const; // = 0 - void callMethodOnInfoPlugin( const QString& scriptSource ); - QVariant callMethodOnInfoPluginWithResult( const QString& scriptSource ); + void onGetInfoRequestDone( const QVariantMap& result ); + void onNotInCacheRequestDone( const QVariantMap& result ); private: static QSet< Tomahawk::InfoSystem::InfoType > parseSupportedTypes(const QVariant& variant); diff --git a/src/libtomahawk/resolvers/ScriptInfoPlugin_p.h b/src/libtomahawk/resolvers/ScriptInfoPlugin_p.h index 91d93a14d..f7b003b03 100644 --- a/src/libtomahawk/resolvers/ScriptInfoPlugin_p.h +++ b/src/libtomahawk/resolvers/ScriptInfoPlugin_p.h @@ -28,20 +28,14 @@ class ScriptInfoPluginPrivate { friend class ScriptInfoPlugin; public: - ScriptInfoPluginPrivate( ScriptInfoPlugin* q, int id, JSAccount* resolver ) + ScriptInfoPluginPrivate( ScriptInfoPlugin* q ) : q_ptr ( q ) - , id( id ) - , resolver( resolver ) { } ScriptInfoPlugin* q_ptr; Q_DECLARE_PUBLIC ( ScriptInfoPlugin ) private: - int id; - // HACK: ScriptInfoPlugin needs to be refactored to track a ScriptObject - JSAccount* resolver; - QMap< int, Tomahawk::InfoSystem::InfoRequestData > requestDataCache; QMap< int, Tomahawk::InfoSystem::InfoStringHash > criteriaCache; }; diff --git a/src/libtomahawk/resolvers/ScriptJob.cpp b/src/libtomahawk/resolvers/ScriptJob.cpp index f342d389c..5b4b27dad 100644 --- a/src/libtomahawk/resolvers/ScriptJob.cpp +++ b/src/libtomahawk/resolvers/ScriptJob.cpp @@ -18,12 +18,14 @@ #include "ScriptJob.h" #include "ScriptObject.h" + #include +#include using namespace Tomahawk; ScriptJob::ScriptJob( const QString& id, ScriptObject* scriptObject, const QString& methodName, const QVariantMap& arguments ) - : QObject( scriptObject ) + : QObject( scriptObject->thread() == QThread::currentThread() ? scriptObject : nullptr ) , m_error( false ) , m_id( id ) , m_scriptObject( scriptObject ) diff --git a/src/libtomahawk/resolvers/ScriptObject.cpp b/src/libtomahawk/resolvers/ScriptObject.cpp index f569db7b6..d991c9aae 100644 --- a/src/libtomahawk/resolvers/ScriptObject.cpp +++ b/src/libtomahawk/resolvers/ScriptObject.cpp @@ -43,6 +43,15 @@ ScriptObject::invoke( const QString& methodName, const QVariantMap& arguments ) } +const QVariant +ScriptObject::syncInvoke(const QString& methodName, const QVariantMap& arguments) +{ + Q_D( ScriptObject ); + + return d->scriptAccount->syncInvoke( this, methodName, arguments ); +} + + QString ScriptObject::id() const { diff --git a/src/libtomahawk/resolvers/ScriptObject.h b/src/libtomahawk/resolvers/ScriptObject.h index b34584ea9..caec59db2 100644 --- a/src/libtomahawk/resolvers/ScriptObject.h +++ b/src/libtomahawk/resolvers/ScriptObject.h @@ -42,6 +42,11 @@ public: ScriptJob* invoke( const QString& methodName, const QVariantMap& arguments = QVariantMap() ); + /** + * Avoid using this if possible, it's blocking and can only be used from the gui thread + */ + const QVariant syncInvoke( const QString& methodName, const QVariantMap& arguments = QVariantMap() ); + protected: QString id() const; diff --git a/src/libtomahawk/resolvers/ScriptPlugin.cpp b/src/libtomahawk/resolvers/ScriptPlugin.cpp index 681349397..1264705ea 100644 --- a/src/libtomahawk/resolvers/ScriptPlugin.cpp +++ b/src/libtomahawk/resolvers/ScriptPlugin.cpp @@ -21,7 +21,7 @@ using namespace Tomahawk; ScriptPlugin::ScriptPlugin( ScriptObject* object ) - : m_object( object ) + : m_scriptObject( object ) { } @@ -35,5 +35,5 @@ ScriptPlugin::~ScriptPlugin() ScriptObject* ScriptPlugin::scriptObject() const { - return m_object; + return m_scriptObject; } diff --git a/src/libtomahawk/resolvers/ScriptPlugin.h b/src/libtomahawk/resolvers/ScriptPlugin.h index a509b7080..1a88e6eb4 100644 --- a/src/libtomahawk/resolvers/ScriptPlugin.h +++ b/src/libtomahawk/resolvers/ScriptPlugin.h @@ -35,7 +35,7 @@ public: ScriptObject* scriptObject() const; protected: // TODO: pimple - ScriptObject* m_object; + ScriptObject* m_scriptObject; };