From 54aef2cd2e482809c71b19bc0e0ba4d53f39dbe7 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell <tomahawk@jefferai.org> Date: Tue, 10 Apr 2012 16:39:12 -0400 Subject: [PATCH] More work towards cleaning up and making safer the info plugins. Twitter should be pretty good, but need to make lastfm and xmpp use the same paradigm --- src/accounts/lastfm/LastFmAccount.cpp | 10 +-- src/accounts/lastfm/LastFmAccount.h | 2 +- src/accounts/spotify/SpotifyAccount.h | 2 +- src/accounts/twitter/twitteraccount.cpp | 45 ++++++++--- src/accounts/twitter/twitteraccount.h | 4 +- src/accounts/twitter/twitterinfoplugin.cpp | 2 + src/accounts/xmpp/sip/xmppsip.cpp | 9 +-- src/accounts/xmpp/sip/xmppsip.h | 4 +- src/accounts/xmpp/xmppaccount.cpp | 4 +- src/accounts/xmpp/xmppaccount.h | 2 +- src/accounts/zeroconf/zeroconfaccount.h | 2 +- src/libtomahawk/accounts/Account.h | 9 +-- src/libtomahawk/accounts/AccountManager.cpp | 38 +++++++-- src/libtomahawk/accounts/AccountManager.h | 5 +- src/libtomahawk/accounts/ResolverAccount.h | 2 +- src/libtomahawk/audio/audioengine.cpp | 1 + src/libtomahawk/infosystem/infosystem.cpp | 46 +++++++++-- src/libtomahawk/infosystem/infosystem.h | 6 +- .../infosystem/infosystemworker.cpp | 81 ++++++++++++++----- src/libtomahawk/infosystem/infosystemworker.h | 7 +- src/musicscanner.cpp | 3 +- src/scanmanager.cpp | 1 - src/tomahawkapp.cpp | 31 ++++--- src/tomahawkapp.h | 1 + 24 files changed, 227 insertions(+), 90 deletions(-) diff --git a/src/accounts/lastfm/LastFmAccount.cpp b/src/accounts/lastfm/LastFmAccount.cpp index a7f566850..1561d49db 100644 --- a/src/accounts/lastfm/LastFmAccount.cpp +++ b/src/accounts/lastfm/LastFmAccount.cpp @@ -74,9 +74,9 @@ LastFmAccount::LastFmAccount( const QString& accountId ) if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() ) { - infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); + infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() ); - QMetaObject::invokeMethod( infoPlugin(), "init", Qt::QueuedConnection ); + QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection ); } } @@ -164,12 +164,12 @@ LastFmAccount::icon() const } -InfoPlugin* +InfoPluginPtr LastFmAccount::infoPlugin() { if ( m_infoPlugin ) - return m_infoPlugin.data(); - return 0; + return InfoPluginPtr( m_infoPlugin.data() ); + return InfoPluginPtr(); } bool diff --git a/src/accounts/lastfm/LastFmAccount.h b/src/accounts/lastfm/LastFmAccount.h index 7988c37d6..e7fc5adf6 100644 --- a/src/accounts/lastfm/LastFmAccount.h +++ b/src/accounts/lastfm/LastFmAccount.h @@ -72,7 +72,7 @@ public: virtual void authenticate(); virtual SipPlugin* sipPlugin() { return 0; } - virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin(); + virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin(); virtual bool isAuthenticated() const; diff --git a/src/accounts/spotify/SpotifyAccount.h b/src/accounts/spotify/SpotifyAccount.h index f83021177..323c989a3 100644 --- a/src/accounts/spotify/SpotifyAccount.h +++ b/src/accounts/spotify/SpotifyAccount.h @@ -66,7 +66,7 @@ public: virtual QPixmap icon() const; virtual QWidget* aclWidget() { return 0; } - virtual InfoSystem::InfoPlugin* infoPlugin() { return 0; } + virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); } virtual SipPlugin* sipPlugin() { return 0; } void addPlaylist( const QString &qid, const QString& title, QList< Tomahawk::query_ptr > tracks ); diff --git a/src/accounts/twitter/twitteraccount.cpp b/src/accounts/twitter/twitteraccount.cpp index 899f87de7..fca1b9932 100644 --- a/src/accounts/twitter/twitteraccount.cpp +++ b/src/accounts/twitter/twitteraccount.cpp @@ -48,6 +48,7 @@ TwitterAccountFactory::createAccount( const QString& accountId ) TwitterAccount::TwitterAccount( const QString &accountId ) : Account( accountId ) , m_isAuthenticated( false ) + , m_isAuthenticating( false ) { setAccountServiceName( "Twitter" ); setTypes( AccountTypes( StatusPushType | SipType ) ); @@ -100,22 +101,48 @@ TwitterAccount::sipPlugin() } -Tomahawk::InfoSystem::InfoPlugin* +Tomahawk::InfoSystem::InfoPluginPtr TwitterAccount::infoPlugin() { if ( m_twitterInfoPlugin.isNull() ) { m_twitterInfoPlugin = QWeakPointer< Tomahawk::InfoSystem::TwitterInfoPlugin >( new Tomahawk::InfoSystem::TwitterInfoPlugin( this ) ); - return m_twitterInfoPlugin.data(); + return Tomahawk::InfoSystem::InfoPluginPtr( m_twitterInfoPlugin.data() ); } - return m_twitterInfoPlugin.data(); + return Tomahawk::InfoSystem::InfoPluginPtr( m_twitterInfoPlugin.data() ); } void TwitterAccount::authenticate() { + // Since we need to have a chance for deletion (via the infosystem) to work on the info plugin, we put this on the event loop + tDebug() << Q_FUNC_INFO; + QTimer::singleShot( 0, this, SLOT( authenticateSlot() ) ); +} + + +void +TwitterAccount::authenticateSlot() +{ + tDebug() << Q_FUNC_INFO; + if ( m_twitterInfoPlugin.isNull() ) + { + if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() ) + { + infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); + Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() ); + QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection ); + } + } + + if ( m_isAuthenticating ) + { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Already authenticating"; + return; + } + tDebug() << Q_FUNC_INFO << "credentials: " << credentials().keys(); if ( credentials()[ "oauthtoken" ].toString().isEmpty() || credentials()[ "oauthtokensecret" ].toString().isEmpty() ) @@ -126,6 +153,7 @@ TwitterAccount::authenticate() if ( refreshTwitterAuth() ) { + m_isAuthenticating = true; tDebug() << Q_FUNC_INFO << "Verifying credentials"; QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this ); connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) ); @@ -143,9 +171,10 @@ TwitterAccount::deauthenticate() sipPlugin()->disconnectPlugin(); if ( m_twitterInfoPlugin ) - m_twitterInfoPlugin.data()->deleteLater(); + Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( m_twitterInfoPlugin.data() ); m_isAuthenticated = false; + m_isAuthenticating = false; emit nowDeauthenticated(); } @@ -176,6 +205,7 @@ TwitterAccount::refreshTwitterAuth() void TwitterAccount::connectAuthVerifyReply( const QTweetUser &user ) { + m_isAuthenticating = false; if ( user.id() == 0 ) { qDebug() << "TwitterAccount could not authenticate to Twitter"; @@ -191,13 +221,6 @@ TwitterAccount::connectAuthVerifyReply( const QTweetUser &user ) sipPlugin()->connectPlugin(); - if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() ) - { - infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); - Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() ); - QMetaObject::invokeMethod( infoPlugin(), "init", Qt::QueuedConnection ); - } - m_isAuthenticated = true; emit nowAuthenticated( m_twitterAuth, user ); } diff --git a/src/accounts/twitter/twitteraccount.h b/src/accounts/twitter/twitteraccount.h index fb8a08981..2ec8e4079 100644 --- a/src/accounts/twitter/twitteraccount.h +++ b/src/accounts/twitter/twitteraccount.h @@ -70,7 +70,7 @@ public: ConnectionState connectionState() const; - Tomahawk::InfoSystem::InfoPlugin* infoPlugin(); + Tomahawk::InfoSystem::InfoPluginPtr infoPlugin(); SipPlugin* sipPlugin(); QWidget* configurationWidget() { return m_configWidget.data(); } @@ -84,12 +84,14 @@ signals: void nowDeauthenticated(); private slots: + void authenticateSlot(); void configDialogAuthedSignalSlot( bool authed ); void connectAuthVerifyReply( const QTweetUser &user ); private: QIcon m_icon; bool m_isAuthenticated; + bool m_isAuthenticating; QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth; QWeakPointer< TwitterConfigWidget > m_configWidget; QWeakPointer< TwitterSipPlugin > m_twitterSipPlugin; diff --git a/src/accounts/twitter/twitterinfoplugin.cpp b/src/accounts/twitter/twitterinfoplugin.cpp index 6811b6b8c..ae8fb373e 100644 --- a/src/accounts/twitter/twitterinfoplugin.cpp +++ b/src/accounts/twitter/twitterinfoplugin.cpp @@ -116,6 +116,7 @@ TwitterInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) tDebug() << Q_FUNC_INFO; if ( !isValid() ) { + tDebug() << Q_FUNC_INFO << "Plugin not valid, deleting and returning"; deleteLater(); return; } @@ -141,6 +142,7 @@ TwitterInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( m_twitterAuth.data(), this ); connect( statUpdate, SIGNAL( postedStatus(const QTweetStatus &) ), SLOT( postLovedStatusUpdateReply(const QTweetStatus &) ) ); connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postLovedStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) ); + tDebug() << Q_FUNC_INFO << "Posting message: " << msg; statUpdate->post( msg ); } diff --git a/src/accounts/xmpp/sip/xmppsip.cpp b/src/accounts/xmpp/sip/xmppsip.cpp index da1c105bf..698db7613 100644 --- a/src/accounts/xmpp/sip/xmppsip.cpp +++ b/src/accounts/xmpp/sip/xmppsip.cpp @@ -86,7 +86,6 @@ JreenMessageHandler(QtMsgType type, const char *msg) XmppSipPlugin::XmppSipPlugin( Account *account ) : SipPlugin( account ) - , m_infoPlugin( 0 ) , m_state( Account::Disconnected ) #ifndef ENABLE_HEADLESS , m_menu( 0 ) @@ -174,10 +173,10 @@ XmppSipPlugin::~XmppSipPlugin() } -InfoSystem::InfoPlugin* +InfoSystem::InfoPluginPtr XmppSipPlugin::infoPlugin() { - return m_infoPlugin; + return InfoSystem::InfoPluginPtr( m_infoPlugin.data() ); } @@ -273,8 +272,8 @@ XmppSipPlugin::onConnect() // load XmppInfoPlugin if( !m_infoPlugin ) { - m_infoPlugin = new Tomahawk::InfoSystem::XmppInfoPlugin( this ); - InfoSystem::InfoSystem::instance()->addInfoPlugin( m_infoPlugin ); + m_infoPlugin = QWeakPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) ); + InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() ); } //FIXME: this implementation is totally broken atm, so it's disabled to avoid harm :P diff --git a/src/accounts/xmpp/sip/xmppsip.h b/src/accounts/xmpp/sip/xmppsip.h index 33b7b61dd..0a56ad9fa 100644 --- a/src/accounts/xmpp/sip/xmppsip.h +++ b/src/accounts/xmpp/sip/xmppsip.h @@ -67,7 +67,7 @@ public: //FIXME: Make this more correct virtual bool isValid() const { return true; } - Tomahawk::InfoSystem::InfoPlugin* infoPlugin(); + Tomahawk::InfoSystem::InfoPluginPtr infoPlugin(); #ifndef ENABLE_HEADLESS virtual QMenu* menu(); @@ -131,7 +131,7 @@ private: int m_currentPort; QString m_currentResource; - Tomahawk::InfoSystem::InfoPlugin* m_infoPlugin; + QWeakPointer< Tomahawk::InfoSystem::XmppInfoPlugin> m_infoPlugin; Tomahawk::Accounts::Account::ConnectionState m_state; // sort out diff --git a/src/accounts/xmpp/xmppaccount.cpp b/src/accounts/xmpp/xmppaccount.cpp index 4d79fb7fa..cda891237 100644 --- a/src/accounts/xmpp/xmppaccount.cpp +++ b/src/accounts/xmpp/xmppaccount.cpp @@ -91,13 +91,13 @@ XmppAccount::saveConfig() } -InfoSystem::InfoPlugin* +InfoSystem::InfoPluginPtr XmppAccount::infoPlugin() { if( !m_xmppSipPlugin.isNull() ) return m_xmppSipPlugin.data()->infoPlugin(); - return 0; + return InfoSystem::InfoPluginPtr(); } diff --git a/src/accounts/xmpp/xmppaccount.h b/src/accounts/xmpp/xmppaccount.h index bae5fbc12..7b8d215c6 100644 --- a/src/accounts/xmpp/xmppaccount.h +++ b/src/accounts/xmpp/xmppaccount.h @@ -69,7 +69,7 @@ public: void deauthenticate(); bool isAuthenticated() const; - Tomahawk::InfoSystem::InfoPlugin* infoPlugin(); + Tomahawk::InfoSystem::InfoPluginPtr infoPlugin(); SipPlugin* sipPlugin(); diff --git a/src/accounts/zeroconf/zeroconfaccount.h b/src/accounts/zeroconf/zeroconfaccount.h index 29a6673fd..4733cf22b 100644 --- a/src/accounts/zeroconf/zeroconfaccount.h +++ b/src/accounts/zeroconf/zeroconfaccount.h @@ -64,7 +64,7 @@ public: bool isAuthenticated() const; ConnectionState connectionState() const; - Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; } + virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); } SipPlugin* sipPlugin(); QWidget* configurationWidget() { return 0; } diff --git a/src/libtomahawk/accounts/Account.h b/src/libtomahawk/accounts/Account.h index 43e98ff67..66349a724 100644 --- a/src/libtomahawk/accounts/Account.h +++ b/src/libtomahawk/accounts/Account.h @@ -31,16 +31,13 @@ #include "dllmacro.h" #include "tomahawksettings.h" +#include "libtomahawk/infosystem/infosystem.h" + class SipPlugin; namespace Tomahawk { -namespace InfoSystem -{ - class InfoPlugin; -} - namespace Accounts { @@ -100,7 +97,7 @@ public: virtual QString errorMessage() const { QMutexLocker locker( &m_mutex ); return m_cachedError; } - virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() = 0; + virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() = 0; virtual SipPlugin* sipPlugin() = 0; AccountTypes types() const; diff --git a/src/libtomahawk/accounts/AccountManager.cpp b/src/libtomahawk/accounts/AccountManager.cpp index 507e9fe53..7c3f68035 100644 --- a/src/libtomahawk/accounts/AccountManager.cpp +++ b/src/libtomahawk/accounts/AccountManager.cpp @@ -51,14 +51,7 @@ AccountManager::AccountManager( QObject *parent ) { s_instance = this; - connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) ); - - loadPluginFactories( findPluginFactories() ); - - // We include the resolver factory manually, not in a plugin - ResolverAccountFactory* f = new ResolverAccountFactory(); - m_accountFactories[ f->factoryId() ] = f; - registerAccountFactoryForFilesystem( f ); + QTimer::singleShot( 0, this, SLOT( init() ) ); } @@ -72,6 +65,29 @@ AccountManager::~AccountManager() } +void +AccountManager::init() +{ + if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().isNull() ) + { + //We need the info system worker to be alive so that we can move info plugins into its thread + QTimer::singleShot( 0, this, SLOT( init() ) ); + return; + } + + connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) ); + + loadPluginFactories( findPluginFactories() ); + + // We include the resolver factory manually, not in a plugin + ResolverAccountFactory* f = new ResolverAccountFactory(); + m_accountFactories[ f->factoryId() ] = f; + registerAccountFactoryForFilesystem( f ); + + emit ready(); +} + + QStringList AccountManager::findPluginFactories() { @@ -180,6 +196,7 @@ AccountManager::loadPluginFactory( const QString& path ) void AccountManager::enableAccount( Account* account ) { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; if ( account->enabled() ) return; @@ -195,6 +212,7 @@ AccountManager::enableAccount( Account* account ) void AccountManager::disableAccount( Account* account ) { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; if ( !account->enabled() ) return; @@ -209,6 +227,7 @@ AccountManager::disableAccount( Account* account ) void AccountManager::connectAll() { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; foreach( Account* acc, m_accounts ) { acc->authenticate(); @@ -222,6 +241,7 @@ AccountManager::connectAll() void AccountManager::disconnectAll() { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; foreach( Account* acc, m_enabledAccounts ) acc->deauthenticate(); @@ -234,6 +254,7 @@ AccountManager::disconnectAll() void AccountManager::toggleAccountsConnected() { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; if ( m_connected ) disconnectAll(); else @@ -367,6 +388,7 @@ AccountManager::hookupAccount( Account* account ) const void AccountManager::hookupAndEnable( Account* account, bool startup ) { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; SipPlugin* p = account->sipPlugin(); if ( p ) SipHandler::instance()->hookUpPlugin( p ); diff --git a/src/libtomahawk/accounts/AccountManager.h b/src/libtomahawk/accounts/AccountManager.h index 16dcf72fc..1e1820476 100644 --- a/src/libtomahawk/accounts/AccountManager.h +++ b/src/libtomahawk/accounts/AccountManager.h @@ -43,7 +43,7 @@ public: explicit AccountManager( QObject *parent ); virtual ~AccountManager(); - + void loadFromConfig(); void initSIP(); @@ -84,6 +84,8 @@ public slots: void toggleAccountsConnected(); signals: + void ready(); + void added( Tomahawk::Accounts::Account* ); void removed( Tomahawk::Accounts::Account* ); @@ -94,6 +96,7 @@ signals: void stateChanged( Account* p, Accounts::Account::ConnectionState state ); private slots: + void init(); void onStateChanged( Tomahawk::Accounts::Account::ConnectionState state ); void onError( int code, const QString& msg ); diff --git a/src/libtomahawk/accounts/ResolverAccount.h b/src/libtomahawk/accounts/ResolverAccount.h index b115d8fc4..4846d0e59 100644 --- a/src/libtomahawk/accounts/ResolverAccount.h +++ b/src/libtomahawk/accounts/ResolverAccount.h @@ -80,7 +80,7 @@ public: // Not relevant virtual QPixmap icon() const { return QPixmap(); } virtual SipPlugin* sipPlugin() { return 0; } - virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; } + virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); } virtual QWidget* aclWidget() { return 0; } private slots: diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 36681e8ab..f5c57489d 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -328,6 +328,7 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty else { _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); + Q_UNUSED( closure ); m_currentTrack->album()->cover( QSize( 0, 0 ) ); } #endif diff --git a/src/libtomahawk/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp index 5cafa1032..9db1bfe80 100644 --- a/src/libtomahawk/infosystem/infosystem.cpp +++ b/src/libtomahawk/infosystem/infosystem.cpp @@ -210,22 +210,56 @@ InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input, const Pus void -InfoSystem::addInfoPlugin( InfoPlugin* plugin ) +InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ) { - // Init is not complete (waiting for worker th read to start and create worker object) so keep trying till then + // Init is not complete (waiting for worker thread to start and create worker object) so keep trying till then if ( !m_inited || !m_infoSystemWorkerThreadController->worker() ) { - QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) ); + QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) ); return; } - if ( plugin->thread() != m_infoSystemWorkerThreadController->worker()->thread() ) + if ( plugin.isNull() ) + { + tDebug() << Q_FUNC_INFO << "Given plugin is null!"; + return; + } + + if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() ) { tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()"; return; } - - QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) ); + + tDebug() << Q_FUNC_INFO << plugin.data(); + QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) ); +} + + +void +InfoSystem::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ) +{ + // Init is not complete (waiting for worker th read to start and create worker object) so keep trying till then + if ( !m_inited || !m_infoSystemWorkerThreadController->worker() ) + { + QMetaObject::invokeMethod( this, "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) ); + return; + } + + if ( plugin.isNull() ) + { + tDebug() << Q_FUNC_INFO << "Given plugin is null!"; + return; + } + + if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() ) + { + tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()"; + return; + } + + tDebug() << Q_FUNC_INFO << plugin.data(); + QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) ); } diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index f7bab5884..c59b6d62e 100644 --- a/src/libtomahawk/infosystem/infosystem.h +++ b/src/libtomahawk/infosystem/infosystem.h @@ -286,7 +286,8 @@ public: public slots: // InfoSystem takes ownership of InfoPlugins - void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin ); + void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); + void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); signals: void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); @@ -309,7 +310,6 @@ private: } - inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash ) { QCryptographicHash md5( QCryptographicHash::Md5 ); @@ -331,6 +331,7 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash ) return returnval; } + Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPushData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash ); @@ -339,6 +340,7 @@ Q_DECLARE_METATYPE( Tomahawk::InfoSystem::PushInfoFlags ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoType ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoSystemCache* ); Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > ); +Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPluginPtr ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* ); #endif // TOMAHAWK_INFOSYSTEM_H diff --git a/src/libtomahawk/infosystem/infosystemworker.cpp b/src/libtomahawk/infosystem/infosystemworker.cpp index a0ba17c05..a59bdd4ad 100644 --- a/src/libtomahawk/infosystem/infosystemworker.cpp +++ b/src/libtomahawk/infosystem/infosystemworker.cpp @@ -82,44 +82,51 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache ) m_shortLinksWaiting = 0; m_cache = cache; #ifndef ENABLE_HEADLESS - addInfoPlugin( new EchoNestPlugin() ); - addInfoPlugin( new MusixMatchPlugin() ); - addInfoPlugin( new MusicBrainzPlugin() ); - addInfoPlugin( new ChartsPlugin() ); - addInfoPlugin( new RoviPlugin() ); - addInfoPlugin( new SpotifyPlugin() ); - addInfoPlugin( new hypemPlugin() ); + addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new ChartsPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new RoviPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new SpotifyPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new hypemPlugin() ) ); #endif #ifdef Q_WS_MAC - addInfoPlugin( new AdiumPlugin() ); + addInfoPlugin( InfoPluginPtr( new AdiumPlugin() ) ); #endif #ifndef ENABLE_HEADLESS #ifdef Q_WS_X11 - addInfoPlugin( new FdoNotifyPlugin() ); - addInfoPlugin( new MprisPlugin() ); + addInfoPlugin( InfoPluginPtr( new FdoNotifyPlugin() ) ); + addInfoPlugin( InfoPluginPtr( new MprisPlugin() ) ); #endif #endif } void -InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin ) +InfoSystemWorker::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ) { tDebug() << Q_FUNC_INFO << plugin; foreach ( InfoPluginPtr ptr, m_plugins ) { - if ( ptr.data() == plugin ) + if ( ptr == plugin ) + { tDebug() << Q_FUNC_INFO << "This plugin is already added to the infosystem."; + return; + } + } + + if ( plugin.isNull() ) + { + tDebug() << Q_FUNC_INFO << "passed-in plugin is null"; return; } - InfoPluginPtr weakptr( plugin ); - m_plugins.append( weakptr ); - registerInfoTypes( weakptr, weakptr.data()->supportedGetTypes(), weakptr.data()->supportedPushTypes() ); + m_plugins.append( plugin ); + registerInfoTypes( plugin, plugin.data()->supportedGetTypes(), plugin.data()->supportedPushTypes() ); connect( - plugin, + plugin.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), this, SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), @@ -127,14 +134,14 @@ InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin ) ); connect( - plugin, + plugin.data(), SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ), m_cache, SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ), Qt::QueuedConnection ); connect( - plugin, + plugin.data(), SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ), m_cache, SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ), @@ -143,6 +150,32 @@ InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin ) } +void +InfoSystemWorker::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ) +{ + tDebug() << Q_FUNC_INFO << plugin; + + if ( plugin.isNull() ) + { + tDebug() << Q_FUNC_INFO << "passed-in plugin is null"; + return; + } + + foreach ( InfoPluginPtr ptr, m_plugins ) + { + if ( ptr == plugin ) + break; + + tDebug() << Q_FUNC_INFO << "This plugin does not exist in the infosystem."; + return; + } + + m_plugins.removeOne( plugin ); + deregisterInfoTypes( plugin, plugin.data()->supportedGetTypes(), plugin.data()->supportedPushTypes() ); + delete plugin.data(); +} + + void InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes ) { @@ -153,6 +186,16 @@ InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< In } +void +InfoSystemWorker::deregisterInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes ) +{ + Q_FOREACH( InfoType type, getTypes ) + m_infoGetMap[type].removeOne( plugin ); + Q_FOREACH( InfoType type, pushTypes ) + m_infoPushMap[type].removeOne( plugin ); +} + + QList< InfoPluginPtr > InfoSystemWorker::determineOrderedMatches( const InfoType type ) const { @@ -242,6 +285,8 @@ InfoSystemWorker::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) } } + tDebug() << Q_FUNC_INFO << "number of matching plugins: " << m_infoPushMap[ pushData.type ].size(); + Q_FOREACH( InfoPluginPtr ptr, m_infoPushMap[ pushData.type ] ) { if( ptr ) diff --git a/src/libtomahawk/infosystem/infosystemworker.h b/src/libtomahawk/infosystem/infosystemworker.h index 6a51299b5..e949329ec 100644 --- a/src/libtomahawk/infosystem/infosystemworker.h +++ b/src/libtomahawk/infosystem/infosystemworker.h @@ -49,8 +49,6 @@ public: InfoSystemWorker(); ~InfoSystemWorker(); - void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes ); - signals: void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); void finished( QString target ); @@ -64,7 +62,8 @@ public slots: void infoSlot( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); - void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin ); + void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); + void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); void getShortUrl( Tomahawk::InfoSystem::InfoPushData data ); void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj ); @@ -73,6 +72,8 @@ private slots: void checkTimeoutsTimerFired(); private: + void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes ); + void deregisterInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes ); void checkFinished( const Tomahawk::InfoSystem::InfoRequestData &target ); QList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const; diff --git a/src/musicscanner.cpp b/src/musicscanner.cpp index 0edd230a4..06a0cf2c6 100644 --- a/src/musicscanner.cpp +++ b/src/musicscanner.cpp @@ -174,7 +174,6 @@ MusicScanner::scan() SLOT( commitBatch( QVariantList, QVariantList ) ), Qt::DirectConnection ); m_dirListerThreadController = new QThread( this ); - m_dirListerThreadController->setPriority( QThread::IdlePriority ); m_dirLister = QWeakPointer< DirLister >( new DirLister( m_dirs ) ); m_dirLister.data()->moveToThread( m_dirListerThreadController ); @@ -186,7 +185,7 @@ MusicScanner::scan() connect( m_dirLister.data(), SIGNAL( finished() ), SLOT( listerFinished() ), Qt::QueuedConnection ); - m_dirListerThreadController->start(); + m_dirListerThreadController->start( QThread::IdlePriority ); QMetaObject::invokeMethod( m_dirLister.data(), "go" ); } diff --git a/src/scanmanager.cpp b/src/scanmanager.cpp index c82438481..cf3c8a7bd 100644 --- a/src/scanmanager.cpp +++ b/src/scanmanager.cpp @@ -196,7 +196,6 @@ ScanManager::runDirScan() { m_scanTimer->stop(); m_musicScannerThreadController = new QThread( this ); - m_musicScannerThreadController->setPriority( QThread::IdlePriority ); m_scanner = QWeakPointer< MusicScanner >( new MusicScanner( paths ) ); m_scanner.data()->moveToThread( m_musicScannerThreadController ); connect( m_scanner.data(), SIGNAL( finished() ), SLOT( scannerFinished() ) ); diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index dbd1ab4b7..3d7d5b529 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -35,6 +35,8 @@ #include "collection.h" #include "infosystem/infosystem.h" #include "accounts/AccountManager.h" +#include "accounts/spotify/SpotifyAccount.h" +#include "accounts/lastfm/LastFmAccount.h" #include "database/database.h" #include "database/databasecollection.h" #include "database/databasecommand_collectionstats.h" @@ -60,8 +62,6 @@ #include "utils/jspfloader.h" #include "utils/logger.h" #include "utils/tomahawkutilsgui.h" -#include "accounts/lastfm/LastFmAccount.h" -#include "accounts/spotify/SpotifyAccount.h" #include "config.h" @@ -227,16 +227,8 @@ TomahawkApp::init() tDebug() << "Init AccountManager."; m_accountManager = QWeakPointer< Tomahawk::Accounts::AccountManager >( new Tomahawk::Accounts::AccountManager( this ) ); - - Tomahawk::Accounts::LastFmAccountFactory* lastfmFactory = new Tomahawk::Accounts::LastFmAccountFactory(); - m_accountManager.data()->addAccountFactory( lastfmFactory ); - - Tomahawk::Accounts::SpotifyAccountFactory* spotifyFactory = new Tomahawk::Accounts::SpotifyAccountFactory; - m_accountManager.data()->addAccountFactory( spotifyFactory ); - m_accountManager.data()->registerAccountFactoryForFilesystem( spotifyFactory ); - - Tomahawk::Accounts::AccountManager::instance()->loadFromConfig(); - + connect( m_accountManager.data(), SIGNAL( ready() ), SLOT( accountManagerReady() ) ); + Echonest::Config::instance()->setNetworkAccessManager( TomahawkUtils::nam() ); #ifndef ENABLE_HEADLESS EchonestGenerator::setupCatalogs(); @@ -447,6 +439,7 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< Tomahawk::InfoSystem::InfoRequestData >( "Tomahawk::InfoSystem::InfoRequestData" ); qRegisterMetaType< Tomahawk::InfoSystem::InfoPushData >( "Tomahawk::InfoSystem::InfoPushData" ); qRegisterMetaType< Tomahawk::InfoSystem::InfoSystemCache* >( "Tomahawk::InfoSystem::InfoSystemCache*" ); + qRegisterMetaType< Tomahawk::InfoSystem::InfoPluginPtr >( "Tomahawk::InfoSystem::InfoPluginPtr" ); qRegisterMetaType< Tomahawk::InfoSystem::InfoPlugin* >( "Tomahawk::InfoSystem::InfoPlugin*" ); qRegisterMetaType< QList< Tomahawk::InfoSystem::InfoStringHash > >("QList< Tomahawk::InfoSystem::InfoStringHash > "); @@ -598,6 +591,20 @@ TomahawkApp::spotifyApiCheckFinished() } +void +TomahawkApp::accountManagerReady() +{ + Tomahawk::Accounts::LastFmAccountFactory* lastfmFactory = new Tomahawk::Accounts::LastFmAccountFactory(); + m_accountManager.data()->addAccountFactory( lastfmFactory ); + + Tomahawk::Accounts::SpotifyAccountFactory* spotifyFactory = new Tomahawk::Accounts::SpotifyAccountFactory; + m_accountManager.data()->addAccountFactory( spotifyFactory ); + m_accountManager.data()->registerAccountFactoryForFilesystem( spotifyFactory ); + + Tomahawk::Accounts::AccountManager::instance()->loadFromConfig(); +} + + void TomahawkApp::activate() { diff --git a/src/tomahawkapp.h b/src/tomahawkapp.h index 24f2acba8..e9ade964f 100644 --- a/src/tomahawkapp.h +++ b/src/tomahawkapp.h @@ -111,6 +111,7 @@ private slots: void initHTTP(); void spotifyApiCheckFinished(); + void accountManagerReady(); private: void registerMetaTypes();