1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 19:30:21 +02:00

Port ScriptInfoPlugin to new generic script plugin infrastructure

This commit is contained in:
Dominik Schmidt
2015-01-05 00:57:13 +01:00
parent 5e5ff7938a
commit 07838afaa6
20 changed files with 167 additions and 404 deletions

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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

View File

@@ -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
{

View File

@@ -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;

View File

@@ -1,116 +0,0 @@
/* === 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 "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() );
}

View File

@@ -1,55 +0,0 @@
/* === 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 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<JSInfoSystemHelperPrivate> d_ptr;
};
} // ns: Tomahawk
#endif // TOMAHAWK_JSINFOSYSTEMHELPER_H

View File

@@ -1,49 +0,0 @@
/* === 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, JSAccount* scriptAccount )
: q_ptr ( q )
, scriptAccount ( scriptAccount )
{
}
JSInfoSystemHelper* q_ptr;
Q_DECLARE_PUBLIC ( JSInfoSystemHelper )
private:
JSAccount* scriptAccount;
QMap<int,ScriptInfoPlugin*> infoPlugins;
};
} // ns: Tomahawk
#endif // TOMAHAWK_JSINFOSYSTEMHELPER_P_H

View File

@@ -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

View File

@@ -25,7 +25,6 @@
#include "JSResolver.h"
#include "JSResolverHelper.h"
#include "JSInfoSystemHelper.h"
#include "database/fuzzyindex/FuzzyIndex.h"
#include <memory> // 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> fuzzyIndex;
QPointer< AccountConfigWidget > configWidget;
QList< QVariant > dataWidgets;

View File

@@ -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";

View File

@@ -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;
};

View File

@@ -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<Tomahawk::InfoSystem::InfoStringHash>() ) ) ); // infoHash
QVariantMap arguments;
arguments[ "type" ] = requestData.type;
arguments[ "data" ] = convertInfoStringHashToQVariantMap( requestData.input.value<Tomahawk::InfoSystem::InfoStringHash>() );
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 )
{

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -18,12 +18,14 @@
#include "ScriptJob.h"
#include "ScriptObject.h"
#include <QMetaObject>
#include <QThread>
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 )

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -35,7 +35,7 @@ public:
ScriptObject* scriptObject() const;
protected: // TODO: pimple
ScriptObject* m_object;
ScriptObject* m_scriptObject;
};