mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-17 19:37:09 +02:00
Merge branch 'master' into decltest
This commit is contained in:
@@ -225,6 +225,7 @@ ACLRegistryImpl::queueNextJob()
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ACLRegistryImpl::wipeEntries()
|
||||
{
|
||||
@@ -232,6 +233,7 @@ ACLRegistryImpl::wipeEntries()
|
||||
save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ACLRegistryImpl::load()
|
||||
{
|
||||
@@ -244,7 +246,6 @@ ACLRegistryImpl::load()
|
||||
tLog() << Q_FUNC_INFO << "entry is invalid";
|
||||
continue;
|
||||
}
|
||||
tLog() << Q_FUNC_INFO << "loading entry";
|
||||
ACLRegistry::User entryUser = entry.value< ACLRegistry::User >();
|
||||
if ( entryUser.knownAccountIds.empty() || entryUser.knownDbids.empty() )
|
||||
{
|
||||
|
@@ -194,6 +194,7 @@ set( libSources
|
||||
accounts/spotify/SpotifyAccount.cpp
|
||||
accounts/spotify/SpotifyAccountConfig.cpp
|
||||
accounts/spotify/SpotifyPlaylistUpdater.cpp
|
||||
accounts/spotify/SpotifyInfoPlugin.cpp
|
||||
|
||||
accounts/lastfm/LastFmAccount.cpp
|
||||
accounts/lastfm/LastFmConfig.cpp
|
||||
|
@@ -111,20 +111,21 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
if ( m_supportedActions & ActionPage && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "&Show Track Page" ) ), ActionPage );
|
||||
|
||||
if ( m_supportedActions & ActionEditMetadata && itemCount() == 1 ) {
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionEditMetadata && itemCount() == 1 )
|
||||
{
|
||||
if ( m_queries.first()->results().isEmpty() )
|
||||
return;
|
||||
|
||||
Tomahawk::result_ptr result = m_queries.first()->results().first();
|
||||
if ( result->collection() && result->collection()->source() &&
|
||||
result->collection()->source()->isLocal() ) {
|
||||
m_sigmap->setMapping( addAction( tr( "Properties") ), ActionEditMetadata );
|
||||
result->collection()->source()->isLocal() )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( tr( "Properties..." ) ), ActionEditMetadata );
|
||||
}
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionDelete )
|
||||
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
|
||||
|
||||
|
@@ -228,6 +228,7 @@ Query::addResults( const QList< Tomahawk::result_ptr >& newresults )
|
||||
|
||||
checkResults();
|
||||
emit resultsAdded( newresults );
|
||||
emit resultsChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -292,6 +293,7 @@ Query::removeResult( const Tomahawk::result_ptr& result )
|
||||
|
||||
emit resultsRemoved( result );
|
||||
checkResults();
|
||||
emit resultsChanged();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -207,6 +207,10 @@ Result::toQuery()
|
||||
if ( m_query.isNull() )
|
||||
{
|
||||
m_query = Tomahawk::Query::get( artist()->name(), track(), album()->name() );
|
||||
|
||||
if ( m_query.isNull() )
|
||||
return query_ptr();
|
||||
|
||||
m_query->setAlbumPos( albumpos() );
|
||||
m_query->setDiscNumber( discnumber() );
|
||||
m_query->setDuration( duration() );
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#include "Pipeline.h"
|
||||
#include "accounts/AccountManager.h"
|
||||
#include "utils/Closure.h"
|
||||
#include "SpotifyInfoPlugin.h"
|
||||
#include "infosystem/InfoSystem.h"
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#include "jobview/JobStatusView.h"
|
||||
@@ -80,6 +82,7 @@ SpotifyAccountFactory::icon() const
|
||||
SpotifyAccount::SpotifyAccount( const QString& accountId )
|
||||
: CustomAtticaAccount( accountId )
|
||||
, m_preventEnabling( false )
|
||||
, m_loggedIn( false )
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -106,6 +109,12 @@ SpotifyAccount::init()
|
||||
AtticaManager::instance()->registerCustomAccount( s_resolverId, this );
|
||||
qRegisterMetaType< Tomahawk::Accounts::SpotifyPlaylistInfo* >( "Tomahawk::Accounts::SpotifyPlaylist*" );
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
if ( !AtticaManager::instance()->resolversLoaded() )
|
||||
{
|
||||
// If we're still waiting to load, wait for the attica resolvers to come down the pipe
|
||||
@@ -195,17 +204,12 @@ SpotifyAccount::hookupResolver()
|
||||
connect( m_spotifyResolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
connect( m_spotifyResolver.data(), SIGNAL( customMessage( QString,QVariantMap ) ), this, SLOT( resolverMessage( QString, QVariantMap ) ) );
|
||||
|
||||
const bool hasMigrated = configuration().value( "hasMigrated" ).toBool();
|
||||
if ( !hasMigrated )
|
||||
{
|
||||
qDebug() << "Getting credentials from spotify resolver to migrate to in-app config";
|
||||
// Always get logged in status
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "getCredentials";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::killExistingResolvers()
|
||||
@@ -328,6 +332,18 @@ SpotifyAccount::connectionState() const
|
||||
}
|
||||
|
||||
|
||||
InfoSystem::InfoPluginPtr
|
||||
SpotifyAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QWeakPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::resolverInstalled(const QString& resolverId)
|
||||
{
|
||||
@@ -384,6 +400,13 @@ SpotifyAccount::setManualResolverPath( const QString &resolverPath )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SpotifyAccount::loggedIn() const
|
||||
{
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::hookupAfterDeletion( bool autoEnable )
|
||||
{
|
||||
@@ -515,6 +538,15 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
creds[ "highQuality" ] = msg.value( "highQuality" );
|
||||
setCredentials( creds );
|
||||
|
||||
m_loggedIn = msg.value( "loggedIn", false ).toBool();
|
||||
if ( m_loggedIn )
|
||||
{
|
||||
configurationWidget();
|
||||
|
||||
if ( !m_configWidget.isNull() )
|
||||
m_configWidget.data()->loginResponse( true, QString(), creds[ "username" ].toString() );
|
||||
}
|
||||
|
||||
qDebug() << "Set creds:" << creds.value( "username" ) << creds.value( "password" ) << msg.value( "username" ) << msg.value( "password" );
|
||||
|
||||
QVariantHash config = configuration();
|
||||
@@ -675,6 +707,8 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
|
||||
const bool success = msg.value( "success" ).toBool();
|
||||
|
||||
m_loggedIn = success;
|
||||
|
||||
if ( success )
|
||||
createActions();
|
||||
|
||||
@@ -682,7 +716,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
if ( m_configWidget.data() )
|
||||
{
|
||||
const QString message = msg.value( "message" ).toString();
|
||||
m_configWidget.data()->loginResponse( success, message );
|
||||
m_configWidget.data()->loginResponse( success, message, creds[ "username" ].toString() );
|
||||
}
|
||||
}
|
||||
else if ( msgType == "playlistDeleted" )
|
||||
@@ -695,6 +729,23 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
SpotifyPlaylistUpdater* updater = m_updaters.take( plid );
|
||||
updater->remove( false );
|
||||
}
|
||||
else if ( msgType == "status" )
|
||||
{
|
||||
const bool loggedIn = msg.value( "loggedIn" ).toBool();
|
||||
const QString username = msg.value( "username" ).toString();
|
||||
|
||||
qDebug() << "Got status message with login info:" << loggedIn << username;
|
||||
|
||||
if ( !loggedIn || username.isEmpty() || credentials().value( "username").toString() != username )
|
||||
m_loggedIn = false;
|
||||
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "status";
|
||||
msg[ "_status" ] = 1;
|
||||
sendMessage( msg );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -734,16 +785,17 @@ SpotifyAccount::icon() const
|
||||
QWidget*
|
||||
SpotifyAccount::configurationWidget()
|
||||
{
|
||||
if ( m_spotifyResolver.isNull() || !m_spotifyResolver.data()->running() )
|
||||
return 0;
|
||||
|
||||
if ( m_configWidget.isNull() )
|
||||
{
|
||||
m_configWidget = QWeakPointer< SpotifyAccountConfig >( new SpotifyAccountConfig( this ) );
|
||||
connect( m_configWidget.data(), SIGNAL( login( QString,QString ) ), this, SLOT( login( QString,QString ) ) );
|
||||
connect( m_configWidget.data(), SIGNAL( logout() ), this, SLOT( logout() ) );
|
||||
m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists );
|
||||
}
|
||||
|
||||
if ( m_spotifyResolver.isNull() || !m_spotifyResolver.data()->running() )
|
||||
return 0;
|
||||
|
||||
return static_cast< QWidget* >( m_configWidget.data() );
|
||||
}
|
||||
|
||||
@@ -823,7 +875,6 @@ SpotifyAccount::saveConfig()
|
||||
void
|
||||
SpotifyAccount::login( const QString& username, const QString& password )
|
||||
{
|
||||
// Send the result to the resolver
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "login";
|
||||
msg[ "username" ] = username;
|
||||
@@ -835,6 +886,15 @@ SpotifyAccount::login( const QString& username, const QString& password )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::logout()
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "logout";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::startPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
{
|
||||
|
@@ -35,6 +35,12 @@ class QTimer;
|
||||
class ScriptResolver;
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
class SpotifyInfoPlugin;
|
||||
}
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class SpotifyAccountConfig;
|
||||
@@ -89,7 +95,7 @@ public:
|
||||
virtual void deauthenticate();
|
||||
|
||||
virtual QWidget* aclWidget() { return 0; }
|
||||
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
|
||||
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
|
||||
virtual SipPlugin* sipPlugin() { return 0; }
|
||||
virtual bool preventEnabling() const { return m_preventEnabling; }
|
||||
|
||||
@@ -102,6 +108,8 @@ public:
|
||||
|
||||
void setManualResolverPath( const QString& resolverPath );
|
||||
|
||||
bool loggedIn() const;
|
||||
|
||||
public slots:
|
||||
void aboutToShow( QAction* action, const Tomahawk::playlist_ptr& playlist );
|
||||
void syncActionTriggered( bool );
|
||||
@@ -114,6 +122,8 @@ private slots:
|
||||
void resolverMessage( const QString& msgType, const QVariantMap& msg );
|
||||
|
||||
void login( const QString& username, const QString& password );
|
||||
void logout();
|
||||
|
||||
// SpotifyResolver message handlers, all take msgtype, msg as argument
|
||||
// void <here>( const QString& msgType, const QVariantMap& msg );
|
||||
void startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg );
|
||||
@@ -143,6 +153,7 @@ private:
|
||||
QWeakPointer<SpotifyAccountConfig> m_configWidget;
|
||||
QWeakPointer<QWidget> m_aboutWidget;
|
||||
QWeakPointer<ScriptResolver> m_spotifyResolver;
|
||||
QWeakPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
|
||||
QMap<QString, QPair<QObject*, QString> > m_qidToSlotMap;
|
||||
|
||||
@@ -152,7 +163,7 @@ private:
|
||||
|
||||
QHash< QString, playlist_ptr > m_waitingForCreateReply;
|
||||
|
||||
bool m_preventEnabling;
|
||||
bool m_preventEnabling, m_loggedIn;
|
||||
|
||||
SmartPointerList< QAction > m_customActions;
|
||||
friend class ::SpotifyPlaylistUpdater;
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QShowEvent>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
@@ -32,16 +33,18 @@ using namespace Accounts;
|
||||
SpotifyAccountConfig::SpotifyAccountConfig( SpotifyAccount *account )
|
||||
: QWidget( 0 )
|
||||
, m_ui( new Ui::SpotifyConfig )
|
||||
, m_loggedInUser( 0 )
|
||||
, m_account( account )
|
||||
, m_playlistsLoading( 0 )
|
||||
, m_loggedInManually( false )
|
||||
, m_isLoggedIn( false )
|
||||
{
|
||||
m_ui->setupUi( this );
|
||||
|
||||
connect( m_ui->loginButton, SIGNAL( clicked( bool ) ), this, SLOT( doLogin() ) );
|
||||
|
||||
connect( m_ui->usernameEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->passwordEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->usernameEdit, SIGNAL( textEdited( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->passwordEdit, SIGNAL( textEdited( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
loadFromConfig();
|
||||
|
||||
m_playlistsLoading = new AnimatedSpinner( m_ui->playlistList );
|
||||
@@ -61,10 +64,21 @@ SpotifyAccountConfig::showEvent( QShowEvent *event )
|
||||
void
|
||||
SpotifyAccountConfig::loadFromConfig()
|
||||
{
|
||||
m_ui->usernameEdit->setText( m_account->credentials().value( "username" ).toString() );
|
||||
const QString username = m_account->credentials().value( "username" ).toString();
|
||||
m_ui->usernameEdit->setText( username );
|
||||
m_ui->passwordEdit->setText( m_account->credentials().value( "password" ).toString() );
|
||||
m_ui->streamingCheckbox->setChecked( m_account->credentials().value( "highQuality" ).toBool() );
|
||||
m_ui->deleteOnUnsync->setChecked( m_account->deleteOnUnsync() );
|
||||
|
||||
if ( m_account->loggedIn() )
|
||||
{
|
||||
qDebug() << "Loading spotify config widget with logged in username:" << username;
|
||||
if ( !username.isEmpty() )
|
||||
m_verifiedUsername = username;
|
||||
showLoggedIn();
|
||||
}
|
||||
else
|
||||
showLoggedOut();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -131,6 +145,8 @@ SpotifyAccountConfig::setPlaylists( const QList<SpotifyPlaylistInfo *>& playlist
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::doLogin()
|
||||
{
|
||||
if ( !m_isLoggedIn )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Logging in..." ) );
|
||||
m_ui->loginButton->setEnabled( false );
|
||||
@@ -140,20 +156,34 @@ SpotifyAccountConfig::doLogin()
|
||||
|
||||
emit login( username(), password() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log out
|
||||
m_isLoggedIn = false;
|
||||
m_loggedInManually = true;
|
||||
m_verifiedUsername.clear();
|
||||
m_ui->playlistList->clear();
|
||||
emit logout();
|
||||
showLoggedOut();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::loginResponse( bool success, const QString& msg )
|
||||
SpotifyAccountConfig::loginResponse( bool success, const QString& msg, const QString& username )
|
||||
{
|
||||
if ( success )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Logged in!" ) );
|
||||
m_ui->loginButton->setEnabled( false );
|
||||
qDebug() << Q_FUNC_INFO << "Login response with username:" << username;
|
||||
m_verifiedUsername = username;
|
||||
m_isLoggedIn = true;
|
||||
showLoggedIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPlaylists( QList< SpotifyPlaylistInfo* >() );
|
||||
m_playlistsLoading->fadeOut();
|
||||
|
||||
m_ui->loginButton->setText( tr( "Failed: %1" ).arg( msg ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
@@ -162,9 +192,51 @@ SpotifyAccountConfig::loginResponse( bool success, const QString& msg )
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::resetLoginButton()
|
||||
SpotifyAccountConfig::showLoggedIn()
|
||||
{
|
||||
m_ui->passwordEdit->hide();
|
||||
m_ui->passwordLabel->hide();
|
||||
m_ui->usernameEdit->hide();
|
||||
m_ui->usernameLabel->hide();
|
||||
|
||||
if ( !m_loggedInUser )
|
||||
{
|
||||
m_loggedInUser = new QLabel( this );
|
||||
m_ui->verticalLayout->insertWidget( 1, m_loggedInUser, 0, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
qDebug() << "Showing logged in withuserame:" << m_verifiedUsername;
|
||||
m_loggedInUser->show();
|
||||
m_loggedInUser->setText( tr( "Logged in as %1" ).arg( m_verifiedUsername ) );
|
||||
|
||||
m_ui->loginButton->setText( tr( "Log Out" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::showLoggedOut()
|
||||
{
|
||||
m_ui->passwordEdit->show();
|
||||
m_ui->passwordLabel->show();
|
||||
m_ui->usernameEdit->show();
|
||||
m_ui->usernameLabel->show();
|
||||
|
||||
if ( m_loggedInUser )
|
||||
m_loggedInUser->hide();
|
||||
|
||||
m_ui->loginButton->setText( tr( "Log In" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::resetLoginButton()
|
||||
{
|
||||
if ( !m_isLoggedIn )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Log In" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <QVariantMap>
|
||||
#include <QTimer>
|
||||
|
||||
class QLabel;
|
||||
class AnimatedSpinner;
|
||||
class QShowEvent;
|
||||
|
||||
@@ -55,14 +56,13 @@ public:
|
||||
void loadFromConfig();
|
||||
void saveSettings();
|
||||
|
||||
void loginResponse( bool success, const QString& msg );
|
||||
void loginResponse( bool success, const QString& msg, const QString& username );
|
||||
|
||||
bool loggedInManually() const { return m_loggedInManually; }
|
||||
|
||||
signals:
|
||||
void login( const QString& username, const QString& pw );
|
||||
|
||||
public slots:
|
||||
// void verifyResult( const QString& msgType, const QVariantMap& msg );
|
||||
void logout();
|
||||
|
||||
protected:
|
||||
void showEvent( QShowEvent* event );
|
||||
@@ -72,10 +72,15 @@ private slots:
|
||||
void resetLoginButton();
|
||||
|
||||
private:
|
||||
void showLoggedIn();
|
||||
void showLoggedOut();
|
||||
|
||||
Ui::SpotifyConfig* m_ui;
|
||||
QLabel* m_loggedInUser;
|
||||
QString m_verifiedUsername;
|
||||
SpotifyAccount* m_account;
|
||||
AnimatedSpinner* m_playlistsLoading;
|
||||
bool m_loggedInManually;
|
||||
bool m_loggedInManually, m_isLoggedIn;
|
||||
};
|
||||
|
||||
}
|
||||
|
263
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp
Normal file
263
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SpotifyInfoPlugin.h"
|
||||
|
||||
#include "SpotifyAccount.h"
|
||||
#include "utils/Closure.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
|
||||
SpotifyInfoPlugin::SpotifyInfoPlugin( Accounts::SpotifyAccount* account )
|
||||
: InfoPlugin()
|
||||
, m_account( QWeakPointer< Accounts::SpotifyAccount >( account ) )
|
||||
{
|
||||
if ( !m_account.isNull() )
|
||||
m_supportedGetTypes << InfoAlbumSongs;
|
||||
}
|
||||
|
||||
|
||||
SpotifyInfoPlugin::~SpotifyInfoPlugin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::getInfo( InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "album" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria[ "album" ] = hash[ "album" ];
|
||||
if ( hash.contains( "artist" ) )
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
const QString album = criteria[ "album" ];
|
||||
const QString artist = criteria[ "artist" ];
|
||||
|
||||
if ( m_account.isNull() || !m_account.data()->loggedIn() )
|
||||
{
|
||||
// No running spotify account, use our webservice
|
||||
QUrl lookupUrl( "http://ws.spotify.com/search/1/album.json" );
|
||||
lookupUrl.addQueryItem( "q", QString( "%1 %2" ).arg( album ).arg( album ) );
|
||||
|
||||
QNetworkReply * reply = TomahawkUtils::nam()->get( QNetworkRequest( lookupUrl ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( albumIdLookupFinished( QNetworkReply*, Tomahawk::InfoSystem::InfoRequestData ) ), reply, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Running resolver, so do the lookup through that
|
||||
qDebug() << Q_FUNC_INFO << "Doing album lookup through spotify:" << album << artist;
|
||||
QVariantMap message;
|
||||
message[ "_msgtype" ] = "albumListing";
|
||||
message[ "artist" ] = artist;
|
||||
message[ "album" ] = album;
|
||||
|
||||
const QString qid = m_account.data()->sendMessage( message, this, "albumListingResult" );
|
||||
|
||||
m_waitingForResults[ qid ] = requestData;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumListingResult( const QString& msgType, const QVariantMap& msg )
|
||||
{
|
||||
Q_ASSERT( msg.contains( "qid" ) );
|
||||
Q_ASSERT( m_waitingForResults.contains( msg.value( "qid" ).toString() ) );
|
||||
|
||||
if ( !msg.contains( "qid" ) || !m_waitingForResults.contains( msg.value( "qid" ).toString() ) )
|
||||
return;
|
||||
|
||||
const InfoRequestData requestData = m_waitingForResults.take( msg.value( "qid" ).toString() );
|
||||
|
||||
QVariantList tracks = msg.value( "tracks" ).toList();
|
||||
QStringList trackNameList;
|
||||
|
||||
foreach ( const QVariant track, tracks )
|
||||
{
|
||||
const QVariantMap trackData = track.toMap();
|
||||
if ( trackData.contains( "track" ) && !trackData[ "track" ].toString().isEmpty() )
|
||||
trackNameList << trackData[ "track" ].toString();
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Successfully got album listing from spotify resolver";
|
||||
trackListResult( trackNameList, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumIdLookupFinished( QNetworkReply* reply, const InfoRequestData& requestData )
|
||||
{
|
||||
Q_ASSERT( reply );
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
const QVariantMap response = p.parse( reply ).toMap();
|
||||
if ( !response.contains( "albums" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantList albums = response.value( "albums" ).toList();
|
||||
if ( albums.isEmpty() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantMap album = albums.first().toMap();
|
||||
const QString id = album.value( "href" ).toString();
|
||||
if ( id.isEmpty() || !id.contains( "spotify:album" ) )
|
||||
{
|
||||
qDebug() << "Empty or malformed spotify album ID from json:" << id << response;
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Doing spotify album lookup via webservice with ID:" << id;
|
||||
|
||||
QUrl lookupUrl( QString( "http://spotikea.tomahawk-player.org/browse/%1" ).arg( id ) );
|
||||
|
||||
|
||||
QNetworkReply * reply = TomahawkUtils::nam()->get( QNetworkRequest( lookupUrl ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( albumContentsLookupFinished( QNetworkReply*, Tomahawk::InfoSystem::InfoRequestData ) ), reply, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Network Error retrieving ID from spotify metadata service:" << reply->error() << reply->errorString() << reply->url();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumContentsLookupFinished( QNetworkReply* reply, const InfoRequestData& requestData )
|
||||
{
|
||||
Q_ASSERT( reply );
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
const QVariantMap response = p.parse( reply ).toMap();
|
||||
|
||||
if ( !response.contains( "album" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantMap album = response.value( "album" ).toMap();
|
||||
if ( !album.contains( "result" ) || album.value( "result" ).toList().isEmpty() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantList albumTracks = album.value( "result" ).toList();
|
||||
QStringList trackNameList;
|
||||
|
||||
foreach ( const QVariant& track, albumTracks )
|
||||
{
|
||||
const QVariantMap trackMap = track.toMap();
|
||||
if ( trackMap.contains( "title" ) )
|
||||
trackNameList << trackMap.value( "title" ).toString();
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Successfully got album listing from spotikea service!";
|
||||
|
||||
if ( trackNameList.isEmpty() )
|
||||
dataError( requestData );
|
||||
else
|
||||
trackListResult( trackNameList, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Network Error retrieving ID from spotify metadata service:" << reply->error() << reply->errorString() << reply->url();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::dataError( InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::trackListResult( const QStringList& trackNameList, const InfoRequestData& requestData )
|
||||
{
|
||||
QVariantMap returnedData;
|
||||
returnedData["tracks"] = trackNameList;
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = requestData.input.value< InfoStringHash>()["artist"];
|
||||
criteria["album"] = requestData.input.value< InfoStringHash>()["album"];
|
||||
|
||||
emit updateCache( criteria, 0, requestData.type, returnedData );
|
||||
}
|
74
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h
Normal file
74
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SPOTIFYINFOPLUGIN_H
|
||||
#define SPOTIFYINFOPLUGIN_H
|
||||
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include <QWeakPointer>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
class SpotifyAccount;
|
||||
}
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class DLLEXPORT SpotifyInfoPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SpotifyInfoPlugin( Accounts::SpotifyAccount* account );
|
||||
virtual ~SpotifyInfoPlugin();
|
||||
|
||||
public slots:
|
||||
void albumListingResult( const QString& msgType, const QVariantMap& msg );
|
||||
|
||||
protected slots:
|
||||
virtual void init() {}
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData ) {}
|
||||
|
||||
private slots:
|
||||
void albumIdLookupFinished( QNetworkReply* reply, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
void albumContentsLookupFinished( QNetworkReply* reply, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
|
||||
private:
|
||||
void dataError( InfoRequestData );
|
||||
void trackListResult( const QStringList& trackNameList, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
|
||||
QHash< QString, InfoRequestData > m_waitingForResults;
|
||||
|
||||
QWeakPointer< Tomahawk::Accounts::SpotifyAccount > m_account;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SPOTIFYINFOPLUGIN_H
|
@@ -91,12 +91,6 @@ PlayableItem::PlayableItem( const Tomahawk::query_ptr& query, PlayableItem* pare
|
||||
connect( query.data(), SIGNAL( updated() ),
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
@@ -118,12 +112,6 @@ PlayableItem::PlayableItem( const Tomahawk::plentry_ptr& entry, PlayableItem* pa
|
||||
connect( m_query.data(), SIGNAL( updated() ),
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
|
@@ -255,11 +255,6 @@ ScriptResolver::handleMsg( const QByteArray& msg )
|
||||
setupConfWidget( m );
|
||||
return;
|
||||
}
|
||||
else if ( msgtype == "status" )
|
||||
{
|
||||
sendStatus();
|
||||
return;
|
||||
}
|
||||
else if ( msgtype == "results" )
|
||||
{
|
||||
const QString qid = m.value( "qid" ).toString();
|
||||
@@ -365,16 +360,6 @@ ScriptResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::sendStatus()
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "status";
|
||||
msg[ "_status" ] = 1;
|
||||
sendMessage( msg );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::doSetup( const QVariantMap& m )
|
||||
{
|
||||
@@ -387,6 +372,7 @@ ScriptResolver::doSetup( const QVariantMap& m )
|
||||
|
||||
m_ready = true;
|
||||
m_configSent = false;
|
||||
m_num_restarts = 0;
|
||||
|
||||
if ( !m_stopped )
|
||||
Tomahawk::Pipeline::instance()->addResolver( this );
|
||||
|
@@ -77,7 +77,6 @@ private:
|
||||
void sendMsg( const QByteArray& msg );
|
||||
void doSetup( const QVariantMap& m );
|
||||
void setupConfWidget( const QVariantMap& m );
|
||||
void sendStatus();
|
||||
|
||||
void startProcess();
|
||||
|
||||
|
@@ -51,6 +51,7 @@ PixmapDelegateFader::PixmapDelegateFader( const artist_ptr& artist, const QSize&
|
||||
{
|
||||
connect( m_artist.data(), SIGNAL( updated() ), SLOT( artistChanged() ) );
|
||||
connect( m_artist.data(), SIGNAL( coverChanged() ), SLOT( artistChanged() ) );
|
||||
|
||||
m_currentReference = m_artist->cover( size, forceLoad );
|
||||
}
|
||||
|
||||
@@ -67,6 +68,7 @@ PixmapDelegateFader::PixmapDelegateFader( const album_ptr& album, const QSize& s
|
||||
{
|
||||
connect( m_album.data(), SIGNAL( updated() ), SLOT( albumChanged() ) );
|
||||
connect( m_album.data(), SIGNAL( coverChanged() ), SLOT( albumChanged() ) );
|
||||
|
||||
m_currentReference = m_album->cover( size, forceLoad );
|
||||
}
|
||||
|
||||
@@ -82,8 +84,10 @@ PixmapDelegateFader::PixmapDelegateFader( const query_ptr& track, const QSize& s
|
||||
if ( !m_track.isNull() )
|
||||
{
|
||||
connect( m_track.data(), SIGNAL( updated() ), SLOT( trackChanged() ) );
|
||||
connect( m_track.data(), SIGNAL( coverChanged() ), SLOT( trackChanged() ) );
|
||||
m_currentReference = m_track->cover( size, forceLoad );
|
||||
connect( m_track.data(), SIGNAL( resultsChanged() ), SLOT( trackChanged() ) );
|
||||
connect( m_track->displayQuery().data(), SIGNAL( coverChanged() ), SLOT( trackChanged() ) );
|
||||
|
||||
m_currentReference = m_track->displayQuery()->cover( size, forceLoad );
|
||||
}
|
||||
|
||||
init();
|
||||
@@ -144,7 +148,7 @@ PixmapDelegateFader::setSize( const QSize& size )
|
||||
else if ( !m_artist.isNull() )
|
||||
m_currentReference = m_artist->cover( m_size );
|
||||
else if ( !m_track.isNull() )
|
||||
m_currentReference = m_track->cover( m_size );
|
||||
m_currentReference = m_track->displayQuery()->cover( m_size );
|
||||
}
|
||||
|
||||
emit repaintRequest();
|
||||
@@ -177,7 +181,8 @@ PixmapDelegateFader::trackChanged()
|
||||
if ( m_track.isNull() )
|
||||
return;
|
||||
|
||||
QMetaObject::invokeMethod( this, "setPixmap", Qt::QueuedConnection, Q_ARG( QPixmap, m_track->cover( m_size ) ) );
|
||||
connect( m_track->displayQuery().data(), SIGNAL( coverChanged() ), SLOT( trackChanged() ) );
|
||||
QMetaObject::invokeMethod( this, "setPixmap", Qt::QueuedConnection, Q_ARG( QPixmap, m_track->displayQuery()->cover( m_size ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user