1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 11:20:22 +02:00

Initial work on threadifying

This commit is contained in:
Jeff Mitchell
2011-04-30 11:10:29 -04:00
parent 2af7c9f18e
commit 4fb41ff417
8 changed files with 165 additions and 99 deletions

View File

@@ -25,13 +25,13 @@ using namespace Echonest;
// for internal neatness // for internal neatness
EchoNestPlugin::EchoNestPlugin(QObject *parent) EchoNestPlugin::EchoNestPlugin(InfoSystemWorker *parent)
: InfoPlugin(parent) : InfoPlugin(parent)
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QSet< InfoType > supportedTypes; QSet< InfoType > supportedTypes;
supportedTypes << Tomahawk::InfoSystem::InfoArtistBiography << Tomahawk::InfoSystem::InfoArtistFamiliarity << Tomahawk::InfoSystem::InfoArtistHotttness << Tomahawk::InfoSystem::InfoArtistTerms << Tomahawk::InfoSystem::InfoMiscTopTerms; supportedTypes << Tomahawk::InfoSystem::InfoArtistBiography << Tomahawk::InfoSystem::InfoArtistFamiliarity << Tomahawk::InfoSystem::InfoArtistHotttness << Tomahawk::InfoSystem::InfoArtistTerms << Tomahawk::InfoSystem::InfoMiscTopTerms;
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes); parent->registerInfoTypes(this, supportedTypes);
} }
EchoNestPlugin::~EchoNestPlugin() EchoNestPlugin::~EchoNestPlugin()

View File

@@ -39,7 +39,7 @@ class EchoNestPlugin : public InfoPlugin
Q_OBJECT Q_OBJECT
public: public:
EchoNestPlugin(QObject *parent); EchoNestPlugin( InfoSystemWorker *parent );
virtual ~EchoNestPlugin(); virtual ~EchoNestPlugin();
protected slots: protected slots:

View File

@@ -41,14 +41,14 @@ md5( const QByteArray& src )
} }
LastFmPlugin::LastFmPlugin( QObject* parent ) LastFmPlugin::LastFmPlugin( InfoSystemWorker* parent )
: InfoPlugin(parent) : InfoPlugin(parent)
, m_scrobbler( 0 ) , m_scrobbler( 0 )
, m_authJob( 0 ) , m_authJob( 0 )
{ {
QSet< InfoType > supportedTypes; QSet< InfoType > supportedTypes;
supportedTypes << InfoMiscSubmitScrobble << InfoMiscSubmitNowPlaying << InfoAlbumCoverArt << InfoArtistImages; supportedTypes << InfoMiscSubmitScrobble << InfoMiscSubmitNowPlaying << InfoAlbumCoverArt << InfoArtistImages;
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes); parent->registerInfoTypes(this, supportedTypes);
/* /*
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a Your API Key is 7194b85b6d1f424fe1668173a78c0c4a

View File

@@ -40,7 +40,7 @@ class LastFmPlugin : public InfoPlugin
Q_OBJECT Q_OBJECT
public: public:
LastFmPlugin( QObject *parent ); LastFmPlugin( InfoSystemWorker *parent );
virtual ~LastFmPlugin(); virtual ~LastFmPlugin();
public slots: public slots:

View File

@@ -27,14 +27,14 @@ using namespace Tomahawk::InfoSystem;
// for internal neatness // for internal neatness
MusixMatchPlugin::MusixMatchPlugin(QObject *parent) MusixMatchPlugin::MusixMatchPlugin(InfoSystemWorker *parent)
: InfoPlugin(parent) : InfoPlugin(parent)
, m_apiKey("61be4ea5aea7dd942d52b2f1311dd9fe") , m_apiKey("61be4ea5aea7dd942d52b2f1311dd9fe")
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QSet< InfoType > supportedTypes; QSet< InfoType > supportedTypes;
supportedTypes << Tomahawk::InfoSystem::InfoTrackLyrics; supportedTypes << Tomahawk::InfoSystem::InfoTrackLyrics;
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes); parent->registerInfoTypes(this, supportedTypes);
} }
MusixMatchPlugin::~MusixMatchPlugin() MusixMatchPlugin::~MusixMatchPlugin()

View File

@@ -34,7 +34,7 @@ class MusixMatchPlugin : public InfoPlugin
Q_OBJECT Q_OBJECT
public: public:
MusixMatchPlugin( QObject *parent ); MusixMatchPlugin( InfoSystemWorker *parent );
virtual ~MusixMatchPlugin(); virtual ~MusixMatchPlugin();
public slots: public slots:

View File

@@ -31,11 +31,108 @@ namespace Tomahawk
namespace InfoSystem namespace InfoSystem
{ {
InfoPlugin::InfoPlugin(QObject *parent) InfoPlugin::InfoPlugin( InfoSystemWorker *parent )
:QObject( parent ) :QObject( parent )
{
qDebug() << Q_FUNC_INFO;
}
InfoSystemWorker::InfoSystemWorker()
{
InfoPluginPtr enptr( new EchoNestPlugin( this ) );
m_plugins.append( enptr );
InfoPluginPtr mmptr( new MusixMatchPlugin( this ) );
m_plugins.append( mmptr );
InfoPluginPtr lfmptr( new LastFmPlugin( this ) );
m_plugins.append( lfmptr );
InfoSystemCache *cache = InfoSystem::instance()->getCache();
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{ {
qDebug() << Q_FUNC_INFO; connect(
plugin.data(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
InfoSystem::instance(),
SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
Qt::UniqueConnection
);
connect(
plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
cache,
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
);
connect(
cache,
SIGNAL( notInCache( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
plugin.data(),
SLOT( notInCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
);
connect(
plugin.data(),
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
cache,
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
);
} }
}
InfoSystemWorker::~InfoSystemWorker()
{
qDebug() << Q_FUNC_INFO;
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{
if( plugin )
delete plugin.data();
}
}
void
InfoSystemWorker::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
{
qDebug() << Q_FUNC_INFO;
Q_FOREACH(InfoType type, types)
m_infoMap[type].append(plugin);
}
QLinkedList< InfoPluginPtr >
InfoSystemWorker::determineOrderedMatches(const InfoType type) const
{
//Dummy function for now that returns the various items in the QSet; at some point this will
//probably need to support ordering based on the data source
QLinkedList< InfoPluginPtr > providers;
Q_FOREACH(InfoPluginPtr ptr, m_infoMap[type])
providers << ptr;
return providers;
}
void
InfoSystemWorker::getInfo( QString caller, InfoType type, QVariant input, InfoCustomData customData )
{
qDebug() << Q_FUNC_INFO;
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
if (providers.isEmpty())
{
emit info(caller, type, QVariant(), QVariant(), customData);
return;
}
InfoPluginPtr ptr = providers.first();
if (!ptr)
{
emit info(caller, type, QVariant(), QVariant(), customData);
return;
}
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
}
InfoSystem* InfoSystem::s_instance = 0; InfoSystem* InfoSystem::s_instance = 0;
@@ -59,59 +156,29 @@ InfoSystem::InfoSystem(QObject *parent)
m_cache->moveToThread( m_infoSystemCacheThreadController ); m_cache->moveToThread( m_infoSystemCacheThreadController );
m_infoSystemCacheThreadController->start( QThread::IdlePriority ); m_infoSystemCacheThreadController->start( QThread::IdlePriority );
InfoPluginPtr enptr( new EchoNestPlugin( this ) ); m_infoSystemWorkerThreadController = new QThread( this );
m_plugins.append( enptr ); m_worker = new InfoSystemWorker();
InfoPluginPtr mmptr( new MusixMatchPlugin( this ) ); m_worker->moveToThread( m_infoSystemWorkerThreadController );
m_plugins.append( mmptr ); m_infoSystemWorkerThreadController->start();
InfoPluginPtr lfmptr( new LastFmPlugin( this ) );
m_plugins.append( lfmptr );
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{
connect(
plugin.data(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
this,
SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
Qt::UniqueConnection
);
connect(
plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
m_cache,
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
);
connect(
m_cache,
SIGNAL( notInCache( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
plugin.data(),
SLOT( notInCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
);
connect(
plugin.data(),
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
m_cache,
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
);
}
connect( m_cache, SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), connect( m_cache, SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection ); this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
connect( m_worker, SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
} }
InfoSystem::~InfoSystem() InfoSystem::~InfoSystem()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{
if( plugin )
delete plugin.data();
}
if ( m_infoSystemCacheThreadController )
m_infoSystemCacheThreadController->quit();
if ( m_infoSystemWorkerThreadController )
m_infoSystemWorkerThreadController->quit();
if( m_infoSystemCacheThreadController ) if( m_infoSystemCacheThreadController )
{ {
m_infoSystemCacheThreadController->quit();
while( !m_infoSystemCacheThreadController->isFinished() ) while( !m_infoSystemCacheThreadController->isFinished() )
{ {
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 ); QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
@@ -127,55 +194,44 @@ InfoSystem::~InfoSystem()
delete m_infoSystemCacheThreadController; delete m_infoSystemCacheThreadController;
m_infoSystemCacheThreadController = 0; m_infoSystemCacheThreadController = 0;
} }
if( m_infoSystemWorkerThreadController )
{
while( !m_infoSystemWorkerThreadController->isFinished() )
{
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
TomahawkUtils::Sleep::msleep( 100 );
}
if( m_worker )
{
delete m_worker;
m_worker = 0;
}
delete m_infoSystemWorkerThreadController;
m_infoSystemWorkerThreadController = 0;
}
} }
void InfoSystem::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
{
qDebug() << Q_FUNC_INFO;
Q_FOREACH(InfoType type, types)
m_infoMap[type].append(plugin);
}
QLinkedList< InfoPluginPtr > InfoSystem::determineOrderedMatches(const InfoType type) const
{
//Dummy function for now that returns the various items in the QSet; at some point this will
//probably need to support ordering based on the data source
QLinkedList< InfoPluginPtr > providers;
Q_FOREACH(InfoPluginPtr ptr, m_infoMap[type])
providers << ptr;
return providers;
}
void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVariant& input, InfoCustomData customData) void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVariant& input, InfoCustomData customData)
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
if (providers.isEmpty())
{
emit info(caller, InfoNoInfo, QVariant(), QVariant(), customData);
emit finished(caller);
return;
}
InfoPluginPtr ptr = providers.first();
if (!ptr)
{
emit info(caller, InfoNoInfo, QVariant(), QVariant(), customData);
emit finished(caller);
return;
}
m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1; m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1;
qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type]; qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type];
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) ); QMetaObject::invokeMethod( m_worker, "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
} }
void InfoSystem::getInfo(const QString &caller, const InfoMap &input, InfoCustomData customData) void InfoSystem::getInfo(const QString &caller, const InfoMap &input, InfoCustomData customData)
{ {
Q_FOREACH( InfoType type, input.keys() ) Q_FOREACH( InfoType type, input.keys() )
getInfo(caller, type, input[type], customData); getInfo(caller, type, input[type], customData);
} }
void InfoSystem::infoSlot(QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData) void InfoSystem::infoSlot(QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData)
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;

View File

@@ -36,6 +36,7 @@ namespace Tomahawk {
namespace InfoSystem { namespace InfoSystem {
class InfoSystemCache; class InfoSystemCache;
class InfoSystemWorker;
enum InfoType { enum InfoType {
InfoTrackID = 0, InfoTrackID = 0,
@@ -104,7 +105,7 @@ class DLLEXPORT InfoPlugin : public QObject
Q_OBJECT Q_OBJECT
public: public:
InfoPlugin( QObject *parent ); InfoPlugin( InfoSystemWorker *parent );
virtual ~InfoPlugin() virtual ~InfoPlugin()
{ {
@@ -142,8 +143,26 @@ typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
class DLLEXPORT InfoSystemWorker : public QObject class DLLEXPORT InfoSystemWorker : public QObject
{ {
Q_OBJECT Q_OBJECT
InfoSystemWorker() {};
~InfoSystemWorker() {}; public:
InfoSystemWorker();
~InfoSystemWorker();
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &types );
signals:
void info( QString target, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
public slots:
void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
private:
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
// For now, statically instantiate plugins; this is just somewhere to keep them
QLinkedList< InfoPluginPtr > m_plugins;
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoMap;
}; };
class DLLEXPORT InfoSystem : public QObject class DLLEXPORT InfoSystem : public QObject
@@ -156,8 +175,6 @@ public:
InfoSystem( QObject *parent ); InfoSystem( QObject *parent );
~InfoSystem(); ~InfoSystem();
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &types );
void getInfo( const QString &caller, const InfoType type, const QVariant &input, InfoCustomData customData ); void getInfo( const QString &caller, const InfoType type, const QVariant &input, InfoCustomData customData );
void getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData ); void getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData );
@@ -171,13 +188,6 @@ public slots:
void infoSlot( const QString target, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const QVariant output, const Tomahawk::InfoSystem::InfoCustomData customData ); void infoSlot( const QString target, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const QVariant output, const Tomahawk::InfoSystem::InfoCustomData customData );
private: private:
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoMap;
// For now, statically instantiate plugins; this is just somewhere to keep them
QLinkedList< InfoPluginPtr > m_plugins;
QHash< QString, QHash< InfoType, int > > m_dataTracker; QHash< QString, QHash< InfoType, int > > m_dataTracker;
InfoSystemCache* m_cache; InfoSystemCache* m_cache;