diff --git a/src/accounts/lastfm/LastFmAccount.cpp b/src/accounts/lastfm/LastFmAccount.cpp index 7e4ac519f..61de6bec7 100644 --- a/src/accounts/lastfm/LastFmAccount.cpp +++ b/src/accounts/lastfm/LastFmAccount.cpp @@ -54,8 +54,6 @@ LastFmAccountFactory::icon() const LastFmAccount::LastFmAccount( const QString& accountId ) : CustomAtticaAccount( accountId ) { - m_infoPlugin = QWeakPointer< LastFmPlugin >( new LastFmPlugin( this ) ); - setAccountFriendlyName( "Last.Fm" ); m_icon.load( RESPATH "images/lastfm-icon.png" ); @@ -70,12 +68,22 @@ LastFmAccount::LastFmAccount( const QString& accountId ) { hookupResolver(); } + + + 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 ); + } } LastFmAccount::~LastFmAccount() { - delete m_infoPlugin.data(); + if ( m_infoPlugin ) + Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() ); + delete m_resolver.data(); } @@ -155,10 +163,13 @@ LastFmAccount::icon() const } -InfoPlugin* +InfoPluginPtr LastFmAccount::infoPlugin() { - return m_infoPlugin.data(); + if ( m_infoPlugin.isNull() ) + m_infoPlugin = QWeakPointer< LastFmPlugin >( new LastFmPlugin( this ) ); + + return InfoPluginPtr( m_infoPlugin.data() ); } bool @@ -178,7 +189,8 @@ LastFmAccount::saveConfig() setScrobble( m_configWidget.data()->scrobble() ); } - m_infoPlugin.data()->settingsChanged(); + if ( m_infoPlugin ) + QTimer::singleShot( 0, m_infoPlugin.data(), SLOT( settingsChanged() ) ); } 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/lastfm/lastfmplugin.cpp b/src/accounts/lastfm/lastfmplugin.cpp index 7e824fa53..3a9275323 100644 --- a/src/accounts/lastfm/lastfmplugin.cpp +++ b/src/accounts/lastfm/lastfmplugin.cpp @@ -46,17 +46,27 @@ LastFmPlugin::LastFmPlugin( LastFmAccount* account ) { m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities; m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove; +} + +void +LastFmPlugin::init() +{ + if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() && thread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ) + { + tDebug() << "Failure: move to the worker thread before running init"; + return; + } // Flush session key cache // TODO WHY FLUSH // m_account->setSessionKey( QByteArray() ); lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a"; lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f"; - lastfm::ws::Username = m_account->username(); + lastfm::ws::Username = m_account.data()->username(); lastfm::setNetworkAccessManager( TomahawkUtils::nam() ); - m_pw = m_account->password(); + m_pw = m_account.data()->password(); //HACK work around a bug in liblastfm---it doesn't create its config dir, so when it // tries to write the track cache, it fails silently. until we have a fixed version, do this @@ -707,23 +717,26 @@ LastFmPlugin::artistImagesReturned() void LastFmPlugin::settingsChanged() { - if ( !m_scrobbler && m_account->scrobble() ) + if ( m_account.isNull() ) + return; + + if ( !m_scrobbler && m_account.data()->scrobble() ) { // can simply create the scrobbler - lastfm::ws::Username = m_account->username(); - m_pw = m_account->password(); + lastfm::ws::Username = m_account.data()->username(); + m_pw = m_account.data()->password(); createScrobbler(); } - else if ( m_scrobbler && !m_account->scrobble() ) + else if ( m_scrobbler && !m_account.data()->scrobble() ) { delete m_scrobbler; m_scrobbler = 0; } - else if ( m_account->username() != lastfm::ws::Username || - m_account->password() != m_pw ) + else if ( m_account.data()->username() != lastfm::ws::Username || + m_account.data()->password() != m_pw ) { - lastfm::ws::Username = m_account->username(); - m_pw = m_account->password(); + lastfm::ws::Username = m_account.data()->username(); + m_pw = m_account.data()->password(); // credentials have changed, have to re-create scrobbler for them to take effect if ( m_scrobbler ) { @@ -740,12 +753,12 @@ void LastFmPlugin::onAuthenticated() { QNetworkReply* authJob = dynamic_cast( sender() ); - if ( !authJob ) + if ( !authJob || m_account.isNull() ) { tLog() << Q_FUNC_INFO << "Help! No longer got a last.fm auth job!"; return; } - + if ( authJob->error() == QNetworkReply::NoError ) { lastfm::XmlQuery lfm = lastfm::XmlQuery( authJob->readAll() ); @@ -753,16 +766,16 @@ LastFmPlugin::onAuthenticated() if ( lfm.children( "error" ).size() > 0 ) { tLog() << "Error from authenticating with Last.fm service:" << lfm.text(); - m_account->setSessionKey( QByteArray() ); + m_account.data()->setSessionKey( QByteArray() ); } else { lastfm::ws::SessionKey = lfm[ "session" ][ "key" ].text(); - m_account->setSessionKey( lastfm::ws::SessionKey.toLatin1() ); + m_account.data()->setSessionKey( lastfm::ws::SessionKey.toLatin1() ); // qDebug() << "Got session key from last.fm"; - if ( m_account->scrobble() ) + if ( m_account.data()->scrobble() ) m_scrobbler = new lastfm::Audioscrobbler( "thk" ); } } @@ -778,7 +791,10 @@ LastFmPlugin::onAuthenticated() void LastFmPlugin::createScrobbler() { - if ( m_account->sessionKey().isEmpty() ) // no session key, so get one + if ( m_account.isNull() ) + return; + + if ( m_account.data()->sessionKey().isEmpty() ) // no session key, so get one { qDebug() << "LastFmPlugin::createScrobbler Session key is empty"; QString authToken = TomahawkUtils::md5( ( lastfm::ws::Username.toLower() + TomahawkUtils::md5( m_pw.toUtf8() ) ).toUtf8() ); @@ -794,7 +810,7 @@ LastFmPlugin::createScrobbler() else { qDebug() << "LastFmPlugin::createScrobbler Already have session key"; - lastfm::ws::SessionKey = m_account->sessionKey(); + lastfm::ws::SessionKey = m_account.data()->sessionKey(); m_scrobbler = new lastfm::Audioscrobbler( "thk" ); } diff --git a/src/accounts/lastfm/lastfmplugin.h b/src/accounts/lastfm/lastfmplugin.h index 76d490a37..088bf4199 100644 --- a/src/accounts/lastfm/lastfmplugin.h +++ b/src/accounts/lastfm/lastfmplugin.h @@ -49,6 +49,7 @@ public: virtual ~LastFmPlugin(); public slots: + void init(); void settingsChanged(); void onAuthenticated(); @@ -79,7 +80,7 @@ private: void dataError( Tomahawk::InfoSystem::InfoRequestData requestData ); - Accounts::LastFmAccount* m_account; + QWeakPointer< Accounts::LastFmAccount > m_account; QList parseTrackList( QNetworkReply * reply ); lastfm::MutableTrack m_track; 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/CMakeLists.txt b/src/accounts/twitter/CMakeLists.txt index 253bd4e03..62bcf83b6 100644 --- a/src/accounts/twitter/CMakeLists.txt +++ b/src/accounts/twitter/CMakeLists.txt @@ -8,6 +8,7 @@ add_definitions( -DACCOUNTDLLEXPORT_PRO ) set( twitterAccountSources twitteraccount.cpp + twitterinfoplugin.cpp twitterconfigwidget.cpp tomahawkoauthtwitter.cpp sip/twittersip.cpp @@ -15,6 +16,7 @@ set( twitterAccountSources set( twitterAccountHeaders twitteraccount.h + twitterinfoplugin.h twitterconfigwidget.h tomahawkoauthtwitter.h sip/twittersip.h diff --git a/src/accounts/twitter/twitteraccount.cpp b/src/accounts/twitter/twitteraccount.cpp index 92eaab161..da1fb2467 100644 --- a/src/accounts/twitter/twitteraccount.cpp +++ b/src/accounts/twitter/twitteraccount.cpp @@ -21,6 +21,7 @@ #include "twitteraccount.h" #include "twitterconfigwidget.h" #include "accounts/twitter/tomahawkoauthtwitter.h" +#include "libtomahawk/infosystem/infosystem.h" #include "sip/SipPlugin.h" @@ -47,9 +48,10 @@ TwitterAccountFactory::createAccount( const QString& accountId ) TwitterAccount::TwitterAccount( const QString &accountId ) : Account( accountId ) , m_isAuthenticated( false ) + , m_isAuthenticating( false ) { setAccountServiceName( "Twitter" ); - setTypes( AccountTypes( InfoType | SipType ) ); + setTypes( AccountTypes( StatusPushType | SipType ) ); qDebug() << "Got cached peers:" << configuration() << configuration()[ "cachedpeers" ]; @@ -99,19 +101,57 @@ TwitterAccount::sipPlugin() } +Tomahawk::InfoSystem::InfoPluginPtr +TwitterAccount::infoPlugin() +{ + if ( m_twitterInfoPlugin.isNull() ) + m_twitterInfoPlugin = QWeakPointer< Tomahawk::InfoSystem::TwitterInfoPlugin >( new Tomahawk::InfoSystem::TwitterInfoPlugin( this ) ); + + 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() ) { - qDebug() << "TwitterSipPlugin has empty Twitter credentials; not connecting"; + tDebug() << Q_FUNC_INFO << "TwitterSipPlugin has empty Twitter credentials; not connecting"; return; } 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 & ) ) ); credVerifier->verify(); @@ -122,10 +162,17 @@ TwitterAccount::authenticate() void TwitterAccount::deauthenticate() { - if ( sipPlugin() ) + tDebug() << Q_FUNC_INFO; + + if ( m_twitterSipPlugin ) sipPlugin()->disconnectPlugin(); + if ( m_twitterInfoPlugin ) + Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( m_twitterInfoPlugin.data() ); + m_isAuthenticated = false; + m_isAuthenticating = false; + emit nowDeauthenticated(); } @@ -139,7 +186,7 @@ TwitterAccount::refreshTwitterAuth() delete m_twitterAuth.data(); Q_ASSERT( TomahawkUtils::nam() != 0 ); - qDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam(); + tDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam(); m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) ); if( m_twitterAuth.isNull() ) @@ -155,6 +202,7 @@ TwitterAccount::refreshTwitterAuth() void TwitterAccount::connectAuthVerifyReply( const QTweetUser &user ) { + m_isAuthenticating = false; if ( user.id() == 0 ) { qDebug() << "TwitterAccount could not authenticate to Twitter"; @@ -174,6 +222,8 @@ TwitterAccount::connectAuthVerifyReply( const QTweetUser &user ) emit nowAuthenticated( m_twitterAuth, user ); } } + + QPixmap TwitterAccount::icon() const { return QPixmap( ":/twitter-icon.png" ); diff --git a/src/accounts/twitter/twitteraccount.h b/src/accounts/twitter/twitteraccount.h index 16dcf6242..2ec8e4079 100644 --- a/src/accounts/twitter/twitteraccount.h +++ b/src/accounts/twitter/twitteraccount.h @@ -25,6 +25,7 @@ #include "tomahawkoauthtwitter.h" #include "sip/twittersip.h" +#include "twitterinfoplugin.h" #include "accounts/accountdllmacro.h" #include "accounts/Account.h" @@ -49,7 +50,7 @@ public: QString factoryId() const { return "twitteraccount"; } QString description() const { return tr( "Connect to your Twitter followers." ); } QPixmap icon() const { return QPixmap( ":/twitter-icon.png" ); } - AccountTypes types() const { return AccountTypes( SipType ); }; + AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); }; Account* createAccount( const QString& pluginId = QString() ); }; @@ -69,7 +70,7 @@ public: ConnectionState connectionState() const; - Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; } + Tomahawk::InfoSystem::InfoPluginPtr infoPlugin(); SipPlugin* sipPlugin(); QWidget* configurationWidget() { return m_configWidget.data(); } @@ -83,15 +84,18 @@ 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; + QWeakPointer< Tomahawk::InfoSystem::TwitterInfoPlugin > m_twitterInfoPlugin; // for settings access friend class TwitterConfigWidget; diff --git a/src/accounts/twitter/twitterinfoplugin.cpp b/src/accounts/twitter/twitterinfoplugin.cpp new file mode 100644 index 000000000..1de65a9ef --- /dev/null +++ b/src/accounts/twitter/twitterinfoplugin.cpp @@ -0,0 +1,174 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012, Dominik Schmidt + * Copyright 2012, Jeff Mitchell + * + * 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 "twitterinfoplugin.h" + +#include "accounts/twitter/twitteraccount.h" + +#include +#include + +#include "globalactionmanager.h" +#include "utils/logger.h" + +namespace Tomahawk +{ + +namespace InfoSystem +{ + +TwitterInfoPlugin::TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account ) + : m_account( account ) +{ + m_supportedPushTypes << InfoLove; +} + + +void +TwitterInfoPlugin::init() +{ + if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() && thread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ) + { + tDebug() << "Failure: move to the worker thread before running init"; + return; + } + + QVariantHash credentials = m_account->credentials(); + if ( credentials[ "oauthtoken" ].toString().isEmpty() || credentials[ "oauthtokensecret" ].toString().isEmpty() ) + { + tDebug() << "TwitterInfoPlugin has empty Twitter credentials; not connecting"; + return; + } + + if ( refreshTwitterAuth() ) + { + QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this ); + connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) ); + credVerifier->verify(); + } +} + + +TwitterInfoPlugin::~TwitterInfoPlugin() +{ + tDebug() << Q_FUNC_INFO; +} + + +bool +TwitterInfoPlugin::refreshTwitterAuth() +{ + tDebug() << Q_FUNC_INFO << " begin" << this; + if( !m_twitterAuth.isNull() ) + delete m_twitterAuth.data(); + + Q_ASSERT( TomahawkUtils::nam() != 0 ); + tDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam() << this; + m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) ); + + if( m_twitterAuth.isNull() ) + return false; + + m_twitterAuth.data()->setOAuthToken( m_account->credentials()[ "oauthtoken" ].toString().toLatin1() ); + m_twitterAuth.data()->setOAuthTokenSecret( m_account->credentials()[ "oauthtokensecret" ].toString().toLatin1() ); + + return true; +} + + +void +TwitterInfoPlugin::connectAuthVerifyReply( const QTweetUser &user ) +{ + if ( user.id() == 0 ) + { + tDebug() << "TwitterInfoPlugin could not authenticate to Twitter" << this; + deleteLater(); + return; + } + else + { + tDebug() << "TwitterInfoPlugin successfully authenticated to Twitter" << this; + return; + } +} + + +void +TwitterInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) +{ + tDebug() << Q_FUNC_INFO; + if ( !isValid() ) + { + tDebug() << Q_FUNC_INFO << "Plugin not valid, deleting and returning"; + deleteLater(); + return; + } + + Tomahawk::InfoSystem::PushInfoPair pushInfoPair = pushData.infoPair; + + if ( !pushInfoPair.second.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) + { + tDebug() << Q_FUNC_INFO << "Cannot convert input into an info string hash"; + return; + } + + Tomahawk::InfoSystem::InfoStringHash info = pushInfoPair.second.value< Tomahawk::InfoSystem::InfoStringHash >(); + + QString msg = tr( "Listening to \"%1\" by %2 and loving it! %3" ) + .arg( info[ "title" ] ) + .arg( info[ "artist" ] ) + .arg( pushInfoPair.first.contains( "shorturl" ) ? + pushInfoPair.first[ "shorturl" ].toUrl().toString() : + GlobalActionManager::instance()->openLink( info[ "title" ], info[ "artist" ], info[ "album" ] ).toString() ); + + 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 ); +} + + +void +TwitterInfoPlugin::postLovedStatusUpdateReply( const QTweetStatus& status ) +{ + if ( status.id() == 0 ) + tDebug() << Q_FUNC_INFO << "Failed to post loved status"; + else + tDebug() << Q_FUNC_INFO << "Successfully posted loved status"; +} + + +void +TwitterInfoPlugin::postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg ) +{ + tDebug() << Q_FUNC_INFO << "Error posting love message, error code is " << code << ", error message is " << errorMsg; +} + + +bool +TwitterInfoPlugin::isValid() const +{ + return !m_twitterAuth.isNull(); +} + +} + +} \ No newline at end of file diff --git a/src/accounts/twitter/twitterinfoplugin.h b/src/accounts/twitter/twitterinfoplugin.h new file mode 100644 index 000000000..77242754d --- /dev/null +++ b/src/accounts/twitter/twitterinfoplugin.h @@ -0,0 +1,80 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012, Dominik Schmidt + * Copyright 2012, Jeff Mitchell + * + * 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 TWITTERINFOPLUGIN_H +#define TWITTERINFOPLUGIN_H + +#include "infosystem/infosystem.h" +#include "accounts/twitter/tomahawkoauthtwitter.h" + +#include +#include +#include + +namespace Tomahawk { + + namespace Accounts { + class TwitterAccount; + } + + namespace InfoSystem { + + class TwitterInfoPlugin : public InfoPlugin + { + Q_OBJECT + + public: + TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account ); + virtual ~TwitterInfoPlugin(); + + public slots: + void init(); + void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) + { + Q_UNUSED( criteria ); + Q_UNUSED( requestData ); + } + + protected slots: + void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ); + void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) + { + Q_UNUSED( requestData ); + } + + private slots: + void connectAuthVerifyReply( const QTweetUser &user ); + void postLovedStatusUpdateReply( const QTweetStatus& status ); + void postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg ); + + private: + bool refreshTwitterAuth(); + bool isValid() const; + + Tomahawk::Accounts::TwitterAccount* m_account; + QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth; + }; + + } + +} + +#endif // TWITTERINFOPLUGIN_H + +struct A; diff --git a/src/accounts/xmpp/XmppInfoPlugin.cpp b/src/accounts/xmpp/XmppInfoPlugin.cpp index 728ba4cf5..b1d822a68 100644 --- a/src/accounts/xmpp/XmppInfoPlugin.cpp +++ b/src/accounts/xmpp/XmppInfoPlugin.cpp @@ -1,6 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright 2012, Dominik Schmidt + * Copyright 2012, Jeff Mitchell * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,31 +24,18 @@ #include "sip/xmppsip.h" #include "utils/logger.h" -#include -#include -#include - -#include // remove now playing status after PAUSE_TIMEOUT seconds -static const int PAUSE_TIMEOUT = 60; +static const int PAUSE_TIMEOUT = 10; -Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin(XmppSipPlugin* sipPlugin) +Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin( XmppSipPlugin* sipPlugin ) : m_sipPlugin( sipPlugin ) - , m_pubSubManager( 0 ) , m_pauseTimer( this ) { Q_ASSERT( sipPlugin->m_client ); m_supportedPushTypes << InfoNowPlaying << InfoNowPaused << InfoNowResumed << InfoNowStopped; - m_pubSubManager = new Jreen::PubSub::Manager( sipPlugin->m_client ); - m_pubSubManager->addEntityType< Jreen::Tune >(); - - // Clear status - Jreen::Tune::Ptr tune( new Jreen::Tune() ); - m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); - m_pauseTimer.setSingleShot( true ); connect( &m_pauseTimer, SIGNAL( timeout() ), this, SLOT( audioStopped() ) ); @@ -56,24 +44,28 @@ Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin(XmppSipPlugin* sipPlugin) Tomahawk::InfoSystem::XmppInfoPlugin::~XmppInfoPlugin() { - //Note: the next two lines don't currently work, because the deletion wipes out internally posted events, need to talk to euro about a fix - Jreen::Tune::Ptr tune( new Jreen::Tune() ); - m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); - m_pubSubManager->deleteLater(); +} + + +void +Tomahawk::InfoSystem::XmppInfoPlugin::init() +{ + if ( QThread::currentThread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ) + { + QMetaObject::invokeMethod( this, "init", Qt::QueuedConnection ); + return; + } + + if ( m_sipPlugin.isNull() ) + return; + + connect( this, SIGNAL( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), m_sipPlugin.data(), SLOT( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), Qt::QueuedConnection ); } void Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) { - tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full(); - - if( m_sipPlugin->m_account->configuration().value("publishtracks").toBool() == false ) - { - tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full() << "Not publishing now playing info (disabled in account config)"; - return; - } - switch ( pushData.type ) { case InfoNowPlaying: @@ -108,8 +100,7 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem:: QVariantMap map = pushInfoPair.second.toMap(); if ( map.contains( "private" ) && map[ "private" ] == TomahawkSettings::FullyPrivate ) { - Jreen::Tune::Ptr tune( new Jreen::Tune() ); - m_pubSubManager->publishItems( QList() << tune, Jreen::JID() ); + emit publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() ); return; } @@ -120,42 +111,25 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem:: } Tomahawk::InfoSystem::InfoStringHash info = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >(); - tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full() << info; - - Jreen::Tune::Ptr tune( new Jreen::Tune() ); - tune->setTitle( info.value( "title" ) ); - tune->setArtist( info.value( "artist" ) ); - tune->setLength( info.value("duration").toInt() ); - tune->setTrack( info.value("albumpos") ); + QUrl url; if ( pushInfoPair.first.contains( "shorturl" ) ) - tune->setUri( pushInfoPair.first[ "shorturl" ].toUrl() ); + url = pushInfoPair.first[ "shorturl" ].toUrl(); else - tune->setUri( GlobalActionManager::instance()->openLink( info.value( "title" ), info.value( "artist" ), info.value( "album" ) ) ); + url = GlobalActionManager::instance()->openLink( info.value( "title" ), info.value( "artist" ), info.value( "album" ) ); - tDebug() << Q_FUNC_INFO << "Setting URI of " << tune->uri().toString(); - //TODO: provide a rating once available in Tomahawk - tune->setRating( 10 ); - - //TODO: it would be nice to set Spotify, Dilandau etc here, but not the jabber ids of friends - tune->setSource( "Tomahawk" ); - - m_pubSubManager->publishItems( QList() << tune, Jreen::JID() ); + emit publishTune( url, info ); } void Tomahawk::InfoSystem::XmppInfoPlugin::audioPaused() { - tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full(); } void Tomahawk::InfoSystem::XmppInfoPlugin::audioStopped() { - tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full(); - - Jreen::Tune::Ptr tune( new Jreen::Tune() ); - m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); + emit publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() ); } diff --git a/src/accounts/xmpp/XmppInfoPlugin.h b/src/accounts/xmpp/XmppInfoPlugin.h index 223167524..c15f1571f 100644 --- a/src/accounts/xmpp/XmppInfoPlugin.h +++ b/src/accounts/xmpp/XmppInfoPlugin.h @@ -1,6 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright 2012, Dominik Schmidt + * Copyright 2012, Jeff Mitchell * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,12 +24,6 @@ #include -namespace Jreen { - namespace PubSub { - class Manager; - } -} - class XmppSipPlugin; namespace Tomahawk { @@ -43,7 +38,11 @@ namespace Tomahawk { XmppInfoPlugin(XmppSipPlugin* parent); virtual ~XmppInfoPlugin(); + signals: + void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo ); + public slots: + void init(); void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ); protected slots: @@ -56,8 +55,7 @@ namespace Tomahawk { void audioPaused(); private: - XmppSipPlugin* m_sipPlugin; - Jreen::PubSub::Manager* m_pubSubManager; + QWeakPointer< XmppSipPlugin > m_sipPlugin; QTimer m_pauseTimer; }; diff --git a/src/accounts/xmpp/sip/xmppsip.cpp b/src/accounts/xmpp/sip/xmppsip.cpp index 10fb265b4..a36d3fb1e 100644 --- a/src/accounts/xmpp/sip/xmppsip.cpp +++ b/src/accounts/xmpp/sip/xmppsip.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -86,11 +87,11 @@ 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 ) , m_xmlConsole( 0 ) + , m_pubSubManager( 0 ) #endif { Jreen::Logger::addHandler( JreenMessageHandler ); @@ -161,11 +162,22 @@ XmppSipPlugin::XmppSipPlugin( Account *account ) #ifndef ENABLE_HEADLESS connect(m_avatarManager, SIGNAL(newAvatar(QString)), SLOT(onNewAvatar(QString))); #endif + + m_pubSubManager = new Jreen::PubSub::Manager( m_client ); + m_pubSubManager->addEntityType< Jreen::Tune >(); + + // Clear status + Jreen::Tune::Ptr tune( new Jreen::Tune() ); + m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); + } XmppSipPlugin::~XmppSipPlugin() { - delete m_infoPlugin; + //Note: the next two lines don't currently work, because the deletion wipes out internally posted events, need to talk to euro about a fix + Jreen::Tune::Ptr tune( new Jreen::Tune() ); + m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); + delete m_pubSubManager; delete m_avatarManager; delete m_roster; #ifndef ENABLE_HEADLESS @@ -175,10 +187,13 @@ XmppSipPlugin::~XmppSipPlugin() } -InfoSystem::InfoPlugin* +InfoSystem::InfoPluginPtr XmppSipPlugin::infoPlugin() { - return m_infoPlugin; + if ( m_infoPlugin.isNull() ) + m_infoPlugin = QWeakPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) ); + + return InfoSystem::InfoPluginPtr( m_infoPlugin.data() ); } @@ -241,6 +256,8 @@ XmppSipPlugin::disconnectPlugin() m_peers.clear(); + publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() ); + m_client->disconnectFromServer( true ); m_state = Account::Disconnecting; emit stateChanged( m_state ); @@ -272,10 +289,11 @@ XmppSipPlugin::onConnect() m_roster->load(); // load XmppInfoPlugin - if( !m_infoPlugin ) + if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() ) { - m_infoPlugin = new Tomahawk::InfoSystem::XmppInfoPlugin( this ); - InfoSystem::InfoSystem::instance()->addInfoPlugin( m_infoPlugin ); + infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() ); + Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() ); + QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection ); } //FIXME: this implementation is totally broken atm, so it's disabled to avoid harm :P @@ -340,6 +358,9 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason ) { handlePeerStatus(peer, Jreen::Presence::Unavailable); } + + if ( !m_infoPlugin.isNull() ) + Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() ); } @@ -509,6 +530,41 @@ XmppSipPlugin::showAddFriendDialog() } +void +XmppSipPlugin::publishTune( const QUrl& url, const InfoSystem::InfoStringHash& trackInfo ) +{ + if( m_account->configuration().value("publishtracks").toBool() == false ) + { + tDebug() << Q_FUNC_INFO << m_client->jid().full() << "Not publishing now playing info (disabled in account config)"; + return; + } + + if ( trackInfo.isEmpty() ) + { + Jreen::Tune::Ptr tune( new Jreen::Tune() ); + m_pubSubManager->publishItems(QList() << tune, Jreen::JID()); + } + + Jreen::Tune::Ptr tune( new Jreen::Tune() ); + + tune->setTitle( trackInfo.value( "title" ) ); + tune->setArtist( trackInfo.value( "artist" ) ); + tune->setLength( trackInfo.value("duration").toInt() ); + tune->setTrack( trackInfo.value("albumpos") ); + + //TODO: provide a rating once available in Tomahawk + tune->setRating( 10 ); + + //TODO: it would be nice to set Spotify, Dilandau etc here, but not the jabber ids of friends + tune->setSource( "Tomahawk" ); + + tune->setUri( url ); + tDebug() << Q_FUNC_INFO << "Setting URI of " << tune->uri().toString(); + + m_pubSubManager->publishItems( QList() << tune, Jreen::JID() ); +} + + QString XmppSipPlugin::defaultSuffix() const { diff --git a/src/accounts/xmpp/sip/xmppsip.h b/src/accounts/xmpp/sip/xmppsip.h index 33b7b61dd..1e570928d 100644 --- a/src/accounts/xmpp/sip/xmppsip.h +++ b/src/accounts/xmpp/sip/xmppsip.h @@ -42,6 +42,7 @@ #include #include #include +#include #ifndef ENABLE_HEADLESS #include @@ -67,7 +68,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(); @@ -92,6 +93,7 @@ public slots: void broadcastMsg( const QString &msg ); virtual void addContact( const QString &jid, const QString& msg = QString() ); void showAddFriendDialog(); + void publishTune( const QUrl &url, const Tomahawk::InfoSystem::InfoStringHash &trackInfo ); protected: virtual QString defaultSuffix() const; @@ -131,7 +133,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 @@ -147,6 +149,7 @@ private: #endif enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard, RequestVersion, RequestedVersion }; AvatarManager *m_avatarManager; + Jreen::PubSub::Manager* m_pubSubManager; }; #endif 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 8529d9e11..7b8d215c6 100644 --- a/src/accounts/xmpp/xmppaccount.h +++ b/src/accounts/xmpp/xmppaccount.h @@ -51,7 +51,7 @@ public: QString description() const { return tr( "Log on to your Jabber/XMPP account to connect to your friends" ); } QString factoryId() const { return "xmppaccount"; } QPixmap icon() const { return QPixmap( ":/xmpp-icon.png" ); } - AccountTypes types() const { return AccountTypes( SipType ); }; + AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); }; Account* createAccount( const QString& pluginId = QString() ); }; @@ -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.cpp b/src/libtomahawk/accounts/Account.cpp index e8a293c2e..b43196f33 100644 --- a/src/libtomahawk/accounts/Account.cpp +++ b/src/libtomahawk/accounts/Account.cpp @@ -37,6 +37,8 @@ accountTypeToString( AccountType type ) case InfoType: case StatusPushType: return QObject::tr( "Status Updaters" ); + case NoType: + return QString(); } return QString(); 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 eb1f7b43d..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 @@ -297,9 +318,6 @@ AccountManager::addAccount( Account* account ) if ( account->types() & Accounts::StatusPushType ) m_accountsByAccountType[ Accounts::StatusPushType ].append( account ); - if ( account->infoPlugin() ) - InfoSystem::InfoSystem::instance()->addInfoPlugin( account->infoPlugin() ); - emit added( account ); } @@ -370,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..cd2bc6041 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -327,8 +327,8 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty onNowPlayingInfoReady( type ); else { - _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); - m_currentTrack->album()->cover( QSize( 0, 0 ) ); + NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); + m_currentTrack->album()->cover( QSize( 0, 0 ), true ); } #endif } @@ -337,14 +337,11 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty void AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) { - tDebug( LOGVERBOSE ) << Q_FUNC_INFO; + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << type; if ( m_currentTrack.isNull() || m_currentTrack->track().isNull() || m_currentTrack->artist().isNull() ) return; - - if ( !m_currentTrack->album().isNull() && sender() && m_currentTrack->album().data() != sender() ) - return; QVariantMap playInfo; @@ -353,26 +350,29 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) #ifndef ENABLE_HEADLESS QImage cover; cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage(); - playInfo["cover"] = cover; - - QTemporaryFile coverTempFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + m_currentTrack->artist()->name() + "_" + m_currentTrack->album()->name() + "_tomahawk_cover.png" ) ); - if ( !coverTempFile.open() ) + if ( !cover.isNull() ) { - tDebug() << "WARNING: could not write temporary file for cover art!"; - } + playInfo["cover"] = cover; - // Finally, save the image to the new temp file - if ( cover.save( &coverTempFile, "PNG" ) ) - { - tDebug( LOGVERBOSE ) << "Saving cover image to:" << QFileInfo( coverTempFile ).absoluteFilePath(); - coverTempFile.close(); - playInfo["coveruri"] = QFileInfo( coverTempFile ).absoluteFilePath(); + QTemporaryFile* coverTempFile = new QTemporaryFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + m_currentTrack->artist()->name() + "_" + m_currentTrack->album()->name() + "_tomahawk_cover.png" ) ); + if ( !coverTempFile->open() ) + tDebug() << Q_FUNC_INFO << "WARNING: could not write temporary file for cover art!"; + else + { + // Finally, save the image to the new temp file + coverTempFile->setAutoRemove( false ); + if ( cover.save( coverTempFile, "PNG" ) ) + { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Saving cover image to:" << QFileInfo( *coverTempFile ).absoluteFilePath(); + playInfo["coveruri"] = QFileInfo( *coverTempFile ).absoluteFilePath(); + } + else + tDebug() << Q_FUNC_INFO << "failed to save cover image!"; + } + delete coverTempFile; } else - { - tDebug() << Q_FUNC_INFO << "failed to save cover image!"; - coverTempFile.close(); - } + tDebug() << Q_FUNC_INFO << "Cover from album is null!"; #endif } @@ -388,6 +388,7 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) Tomahawk::InfoSystem::InfoPushData pushData ( s_aeInfoIdentifier, type, playInfo, Tomahawk::InfoSystem::PushShortUrlFlag ); + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "pushing data with type " << type; Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); } diff --git a/src/libtomahawk/globalactionmanager.cpp b/src/libtomahawk/globalactionmanager.cpp index e42c2f953..7c8a5404e 100644 --- a/src/libtomahawk/globalactionmanager.cpp +++ b/src/libtomahawk/globalactionmanager.cpp @@ -125,6 +125,7 @@ GlobalActionManager::openLink( const QString& title, const QString& artist, cons void GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj ) { + tDebug() << Q_FUNC_INFO << "callbackObj is valid: " << ( callbackObj.isValid() ? "true" : "false" ); if ( QThread::currentThread() != thread() ) { qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO; @@ -136,7 +137,7 @@ GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj ) request.setUrl( url ); QNetworkReply *reply = TomahawkUtils::nam()->get( request ); - if ( !callbackObj.isValid() ) + if ( callbackObj.isValid() ) reply->setProperty( "callbackobj", callbackObj ); connect( reply, SIGNAL( finished() ), SLOT( shortenLinkRequestFinished() ) ); connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), SLOT( shortenLinkRequestError( QNetworkReply::NetworkError ) ) ); @@ -1013,7 +1014,7 @@ GlobalActionManager::shortenLinkRequestFinished() } QVariant callbackObj; - if ( reply->property( "callbackobj" ).canConvert< QVariant >() && reply->property( "callbackobj" ).isValid() ) + if ( reply->property( "callbackobj" ).isValid() ) callbackObj = reply->property( "callbackobj" ); // Check for the redirect attribute, as this should be the shortened link diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp index 4cc973270..5c252f820 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp @@ -49,9 +49,9 @@ using namespace Tomahawk::InfoSystem; - FdoNotifyPlugin::FdoNotifyPlugin() : InfoPlugin() + , m_nowPlayingId( 0 ) { qDebug() << Q_FUNC_INFO; m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped; @@ -119,6 +119,7 @@ FdoNotifyPlugin::notifyUser( const QString &messageText ) void FdoNotifyPlugin::nowPlaying( const QVariant &input ) { + tDebug( LOGVERBOSE ) << Q_FUNC_INFO; if ( !input.canConvert< QVariantMap >() ) return; @@ -135,23 +136,29 @@ FdoNotifyPlugin::nowPlaying( const QVariant &input ) .arg( hash[ "title" ] ) .arg( hash[ "artist" ] ) .arg( hash[ "album" ].isEmpty() ? QString() : QString( " %1" ).arg( tr( "on \"%1\"" ).arg( hash[ "album" ] ) ) ); - + + tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText; + QDBusMessage message = QDBusMessage::createMethodCall( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "Notify" ); QList arguments; arguments << QString( "Tomahawk" ); //app_name - arguments << quint32( 0 ); //notification_id + arguments << m_nowPlayingId; //notification_id arguments << QString(); //app_icon arguments << QString( "Tomahawk" ); //summary arguments << messageText; //body arguments << QStringList(); //actions QVariantMap dict; dict["desktop-entry"] = QString( "tomahawk" ); - if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() ) - dict[ "image_data" ] = ImageConverter::variantForImage( map[ "cover" ].value< QImage >() ); + if ( map.contains( "coveruri" ) && map[ "coveruri" ].canConvert< QString >() ) + dict[ "image_data" ] = ImageConverter::variantForImage( QImage( map[ "coveruri" ].toString(), "PNG" ) ); else dict[ "image_data" ] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) ); arguments << dict; //hints arguments << qint32( -1 ); //expire_timeout message.setArguments( arguments ); - QDBusConnection::sessionBus().send( message ); + + const QDBusMessage &reply = QDBusConnection::sessionBus().call( message ); + const QVariantList &list = reply.arguments(); + if ( list.count() > 0 ) + m_nowPlayingId = list.at( 0 ).toInt(); } diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h index c12621ff3..bba7bc304 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h +++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h @@ -54,6 +54,8 @@ private: void notifyUser( const QString &messageText ); void nowPlaying( const QVariant &input ); + + quint32 m_nowPlayingId; }; } diff --git a/src/libtomahawk/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp index c1f6c020b..9db1bfe80 100644 --- a/src/libtomahawk/infosystem/infosystem.cpp +++ b/src/libtomahawk/infosystem/infosystem.cpp @@ -137,7 +137,7 @@ InfoSystem::init() bool InfoSystem::getInfo( const InfoRequestData &requestData ) { - qDebug() << Q_FUNC_INFO; + //qDebug() << Q_FUNC_INFO; if ( !m_inited || !m_infoSystemWorkerThreadController->worker() ) { init(); @@ -210,15 +210,66 @@ 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 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::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(), "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, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) ); + QMetaObject::invokeMethod( this, "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) ); return; } - QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) ); + + 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 ) ); +} + + +QWeakPointer< QThread > +InfoSystem::workerThread() const +{ + if ( m_infoSystemWorkerThreadController->isRunning() && m_infoSystemWorkerThreadController->worker() ) + return QWeakPointer< QThread >( m_infoSystemWorkerThreadController->worker()->thread() ); + + return QWeakPointer< QThread >(); } diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index 9f0d8a811..c59b6d62e 100644 --- a/src/libtomahawk/infosystem/infosystem.h +++ b/src/libtomahawk/infosystem/infosystem.h @@ -282,9 +282,12 @@ public: bool pushInfo( InfoPushData pushData ); bool pushInfo( const QString &caller, const InfoTypeMap &input, const PushInfoFlags pushFlags ); + QWeakPointer< QThread > workerThread() const; + 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 ); @@ -307,7 +310,6 @@ private: } - inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash ) { QCryptographicHash md5( QCryptographicHash::Md5 ); @@ -329,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 ); @@ -337,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/infosystemcache.cpp b/src/libtomahawk/infosystem/infosystemcache.cpp index ac626ecd0..5a2503046 100644 --- a/src/libtomahawk/infosystem/infosystemcache.cpp +++ b/src/libtomahawk/infosystem/infosystemcache.cpp @@ -159,7 +159,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri if ( !fileLocationHash.isEmpty() ) { //We already know of some values, so no need to re-read the directory again as it's already happened - qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash empty"; + //qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash empty"; notInCache( sendingObj, criteria, requestData ); return; } @@ -169,7 +169,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri if ( !dir.exists() ) { //Dir doesn't exist so clearly not in cache - qDebug() << Q_FUNC_INFO << "notInCache -- dir doesn't exist"; + //qDebug() << Q_FUNC_INFO << "notInCache -- dir doesn't exist"; notInCache( sendingObj, criteria, requestData ); return; } @@ -186,7 +186,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri if ( !fileLocationHash.contains( criteriaHashVal ) ) { //Still didn't find it? It's really not in the cache then - qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash doesn't contain criteria val"; + //qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash doesn't contain criteria val"; notInCache( sendingObj, criteria, requestData ); return; } @@ -250,7 +250,7 @@ InfoSystemCache::notInCache( QObject *receiver, Tomahawk::InfoSystem::InfoString void InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output ) { - qDebug() << Q_FUNC_INFO; + //qDebug() << Q_FUNC_INFO; const QString criteriaHashVal = criteriaMd5( criteria ); const QString criteriaHashValWithType = criteriaMd5( criteria, type ); const QString cacheDir = m_cacheBaseDir + QString::number( (int)type ); diff --git a/src/libtomahawk/infosystem/infosystemworker.cpp b/src/libtomahawk/infosystem/infosystemworker.cpp index be7fb4f2b..a59bdd4ad 100644 --- a/src/libtomahawk/infosystem/infosystemworker.cpp +++ b/src/libtomahawk/infosystem/infosystemworker.cpp @@ -82,36 +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 ) { - InfoPluginPtr weakptr( plugin ); - m_plugins.append( weakptr ); - registerInfoTypes( weakptr, weakptr.data()->supportedGetTypes(), weakptr.data()->supportedPushTypes() ); + tDebug() << Q_FUNC_INFO << plugin; + foreach ( InfoPluginPtr ptr, m_plugins ) + { + 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; + } + + 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 ) ), @@ -119,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 ) ), @@ -135,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 ) { @@ -145,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 { @@ -234,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/libtomahawk/query.cpp b/src/libtomahawk/query.cpp index 0702cad40..2b9cabc86 100644 --- a/src/libtomahawk/query.cpp +++ b/src/libtomahawk/query.cpp @@ -588,9 +588,9 @@ Query::setLoved( bool loved ) trackInfo["album"] = album(); Tomahawk::InfoSystem::InfoPushData pushData ( id(), - Tomahawk::InfoSystem::InfoLove, + ( loved ? Tomahawk::InfoSystem::InfoLove : Tomahawk::InfoSystem::InfoUnLove ), QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ), - Tomahawk::InfoSystem::PushNoFlag ); + Tomahawk::InfoSystem::PushShortUrlFlag ); Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); 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();