1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-25 02:09:48 +01: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
EchoNestPlugin::EchoNestPlugin(QObject *parent)
EchoNestPlugin::EchoNestPlugin(InfoSystemWorker *parent)
: InfoPlugin(parent)
{
qDebug() << Q_FUNC_INFO;
QSet< InfoType > supportedTypes;
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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,11 +31,108 @@ namespace Tomahawk
namespace InfoSystem
{
InfoPlugin::InfoPlugin(QObject *parent)
:QObject( parent )
InfoPlugin::InfoPlugin( InfoSystemWorker *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;
@ -59,59 +156,29 @@ InfoSystem::InfoSystem(QObject *parent)
m_cache->moveToThread( m_infoSystemCacheThreadController );
m_infoSystemCacheThreadController->start( QThread::IdlePriority );
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 );
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 ) )
);
}
m_infoSystemWorkerThreadController = new QThread( this );
m_worker = new InfoSystemWorker();
m_worker->moveToThread( m_infoSystemWorkerThreadController );
m_infoSystemWorkerThreadController->start();
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 );
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()
{
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 )
{
m_infoSystemCacheThreadController->quit();
while( !m_infoSystemCacheThreadController->isFinished() )
{
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
@ -127,55 +194,44 @@ InfoSystem::~InfoSystem()
delete m_infoSystemCacheThreadController;
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)
{
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;
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)
{
Q_FOREACH( InfoType type, input.keys() )
getInfo(caller, type, input[type], customData);
}
void InfoSystem::infoSlot(QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData)
{
qDebug() << Q_FUNC_INFO;

View File

@ -36,6 +36,7 @@ namespace Tomahawk {
namespace InfoSystem {
class InfoSystemCache;
class InfoSystemWorker;
enum InfoType {
InfoTrackID = 0,
@ -104,7 +105,7 @@ class DLLEXPORT InfoPlugin : public QObject
Q_OBJECT
public:
InfoPlugin( QObject *parent );
InfoPlugin( InfoSystemWorker *parent );
virtual ~InfoPlugin()
{
@ -142,8 +143,26 @@ typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
class DLLEXPORT InfoSystemWorker : public QObject
{
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
@ -156,8 +175,6 @@ public:
InfoSystem( QObject *parent );
~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 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 );
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;
InfoSystemCache* m_cache;