1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-20 07:49:42 +01:00

Merge branch 'spotifyAccount'

This commit is contained in:
Leo Franchi 2012-03-09 22:41:29 -05:00
commit 5c0507323c
17 changed files with 347 additions and 12 deletions

View File

@ -456,7 +456,7 @@ AtticaManager::payloadFetched()
if ( reply->property( "createAccount" ).toBool() )
{
// Do the install / add to tomahawk
Tomahawk::Accounts::Account* resolver = Tomahawk::Accounts::ResolverAccountFactory::createFromPath( resolverPath, true );
Tomahawk::Accounts::Account* resolver = Tomahawk::Accounts::ResolverAccountFactory::createFromPath( resolverPath, "resolveraccount", true );
Tomahawk::Accounts::AccountManager::instance()->addAccount( resolver );
TomahawkSettings::instance()->addAccount( resolver->accountId() );
}

View File

@ -184,6 +184,7 @@ set( libSources
accounts/ResolverAccount.cpp
accounts/LastFmAccount.cpp
accounts/LastFmConfig.cpp
accounts/SpotifyAccount.cpp
sip/SipPlugin.cpp
sip/SipHandler.cpp

View File

@ -58,7 +58,6 @@ Account::Account( const QString& accountId )
Account::~Account()
{
sync();
}

View File

@ -180,6 +180,10 @@ public:
virtual AccountTypes types() const = 0;
virtual Account* createAccount( const QString& accountId = QString() ) = 0;
/// If this resolver type accepts this path on disk (For general and special resolver accounts)
virtual bool acceptsPath( const QString& ) const { return false; }
virtual Account* createFromPath( const QString& ) { return 0; }
};
};

View File

@ -22,6 +22,7 @@
#include "sourcelist.h"
#include "ResolverAccount.h"
#include "LastFmAccount.h"
#include "SpotifyAccount.h"
#include <QtCore/QLibrary>
#include <QtCore/QDir>
@ -59,9 +60,14 @@ AccountManager::AccountManager( QObject *parent )
// We include the resolver factory manually, not in a plugin
ResolverAccountFactory* f = new ResolverAccountFactory();
m_accountFactories[ f->factoryId() ] = f;
registerAccountFactoryForFilesystem( f );
LastFmAccountFactory* l = new LastFmAccountFactory();
m_accountFactories[ l->factoryId() ] = l;
SpotifyAccountFactory* s = new SpotifyAccountFactory;
m_accountFactories[ s->factoryId() ] = s;
registerAccountFactoryForFilesystem( s );
}
@ -331,6 +337,30 @@ AccountManager::removeAccount( Account* account )
}
Account*
AccountManager::accountFromPath( const QString& accountPath )
{
foreach ( AccountFactory* factory, m_factoriesForFilesytem )
{
if ( factory->acceptsPath( accountPath ) )
{
return factory->createFromPath( accountPath );
}
}
Q_ASSERT_X( false, "Shouldn't have had no account factory accepting a path.. at least ResolverAccount!!", "");
return 0;
}
void
AccountManager::registerAccountFactoryForFilesystem( AccountFactory* factory )
{
m_factoriesForFilesytem.prepend( factory );
}
void
AccountManager::hookupAccount( Account* account ) const
{

View File

@ -61,6 +61,21 @@ public:
QList< Account* > accounts() const { return m_accounts; };
QList< Account* > accounts( Tomahawk::Accounts::AccountType type ) const { return m_accountsByAccountType[ type ]; }
/**
* Returns a new Account for a certain path on disk. This will go through all on-disk resolver account providers
* to find the most specific account that matches this.
*
* The fallback is ResolverAccount, which handles our generic external script resolvers.
*/
Account* accountFromPath( const QString& path );
/**
* Registers an account factory as being able to "handle" resolvers on disk. When accountFromPath is called
* AccountManager will go through all registered account factories in order until it finds one that can handle the path.
* This is searched in LIFO order.
*/
void registerAccountFactoryForFilesystem( AccountFactory* factory );
public slots:
void connectAll();
void disconnectAll();
@ -97,6 +112,7 @@ private:
QHash< AccountType, QList< Account* > > m_accountsByAccountType;
QHash< QString, AccountFactory* > m_accountFactories;
QList< AccountFactory* > m_factoriesForFilesytem;
static AccountManager* s_instance;
};

View File

@ -311,7 +311,7 @@ AccountModel::data( const QModelIndex& index, int role ) const
case Qt::DecorationRole:
return acct->icon();
case DescriptionRole:
return node->type == AccountModelNode::ManualResolverType ? QString() : node->factory->description();
return node->factory ? node->factory->description() : QString();
case Qt::CheckStateRole:
return acct->enabled() ? Qt::Checked : Qt::Unchecked;
case AccountData:
@ -597,7 +597,6 @@ void
AccountModel::accountStateChanged( Account* account , Account::ConnectionState )
{
// Find the factory this belongs up, and update
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
for ( int i = 0; i < m_accounts.size(); i++ )
{
AccountModelNode* n = m_accounts.at( i );

View File

@ -118,6 +118,7 @@ struct AccountModelNode {
{
init();
resolverAccount = ra;
factory = AccountManager::instance()->factoryForAccount( ra );
}
explicit AccountModelNode( Account* account ) : type( CustomAccountType )

View File

@ -83,6 +83,13 @@ LastFmAccount::~LastFmAccount()
void
LastFmAccount::authenticate()
{
if ( !AtticaManager::instance()->resolversLoaded() )
{
// If we're still waiting to load, wait for the attica resolvers to come down the pipe
connect( AtticaManager::instance(), SIGNAL(resolversLoaded(Attica::Content::List)), this, SLOT( atticaLoaded( Attica::Content::List ) ), Qt::UniqueConnection );
return;
}
const Attica::Content res = AtticaManager::instance()->resolverForId( "lastfm" );
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
@ -106,6 +113,14 @@ LastFmAccount::authenticate()
}
void
LastFmAccount::atticaLoaded( Attica::Content::List )
{
disconnect( AtticaManager::instance(), SIGNAL( resolversLoaded( Attica::Content::List ) ), this, SLOT( atticaLoaded( Attica::Content::List ) ) );
authenticate();
}
void
LastFmAccount::deauthenticate()
{

View File

@ -94,6 +94,8 @@ public:
Attica::Content atticaContent() const;
private slots:
void atticaLoaded( Attica::Content::List );
void resolverInstalled( const QString& resolverId );
void resolverChanged();

View File

@ -46,16 +46,23 @@ ResolverAccountFactory::createAccount( const QString& accountId )
Account*
ResolverAccountFactory::createFromPath( const QString& path, bool isAttica )
ResolverAccountFactory::createFromPath( const QString& path )
{
return createFromPath( path, factoryId(), false );
}
Account*
ResolverAccountFactory::createFromPath( const QString& path, const QString& factory, bool isAttica )
{
qDebug() << "Creating ResolverAccount from path:" << path << "is attica" << isAttica;
if ( isAttica )
{
QFileInfo info( path );
return new AtticaResolverAccount( generateId( "resolveraccount" ), path, info.baseName() );
return new AtticaResolverAccount( generateId( factory ), path, info.baseName() );
}
else
return new ResolverAccount( generateId( "resolveraccount" ), path );
return new ResolverAccount( generateId( factory ), path );
}

View File

@ -35,7 +35,7 @@ public:
ResolverAccountFactory() {}
virtual ~ResolverAccountFactory() {}
virtual Account* createAccount(const QString& accountId = QString());
virtual Account* createAccount( const QString& accountId = QString() );
virtual QString factoryId() const { return "resolveraccount"; }
virtual QString description() const { return QString(); }
virtual QString prettyName() const { return QString(); } // Internal, not displayed
@ -44,7 +44,11 @@ public:
// Used to create a new resolver from a script on disk, either chosen by
// the user, or installed from synchrotron
static Account* createFromPath( const QString& path, bool isAttica );
virtual bool acceptsPath( const QString& path ) const { return true; } // This is the catch-all filesystem account
virtual Account* createFromPath( const QString& path );
// Internal use
static Account* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
};
/**

View File

@ -0,0 +1,148 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 "SpotifyAccount.h"
#include "playlist.h"
#include "utils/tomahawkutils.h"
#include "PlaylistUpdaterInterface.h"
#include "sourcelist.h"
#include <QPixmap>
using namespace Tomahawk;
using namespace Accounts;
static QPixmap* s_icon = 0;
Account*
SpotifyAccountFactory::createAccount( const QString& accountId )
{
return new SpotifyAccount( accountId );
}
bool
SpotifyAccountFactory::acceptsPath( const QString& path ) const
{
QFileInfo info( path );
return info.baseName().startsWith( "spotify_" );
}
Account*
SpotifyAccountFactory::createFromPath( const QString& path )
{
return new SpotifyAccount( generateId( factoryId() ), path );
}
QPixmap
SpotifyAccountFactory::icon() const
{
if ( !s_icon )
s_icon = new QPixmap( RESPATH "images/spotify-logo.png" );
return *s_icon;
}
SpotifyAccount::SpotifyAccount( const QString& accountId )
: ResolverAccount( accountId )
{
}
SpotifyAccount::SpotifyAccount( const QString& accountId, const QString& path )
: ResolverAccount( accountId, path )
{
}
QPixmap
SpotifyAccount::icon() const
{
if ( !s_icon )
s_icon = new QPixmap( RESPATH "images/spotify-logo.png" );
return *s_icon;
}
void
SpotifyAccount::addPlaylist( const QString &qid, const QString& title, QList< Tomahawk::query_ptr > tracks )
{
Sync sync;
sync.id_ = qid;
int index = m_syncPlaylists.indexOf( sync );
if( !m_syncPlaylists.contains( sync ) )
{
qDebug() << Q_FUNC_INFO << "Adding playlist to sync" << qid;
playlist_ptr pl;
pl = Tomahawk::Playlist::create( SourceList::instance()->getLocal(),
uuid(),
title,
QString(),
QString(),
false,
tracks );
sync.playlist = pl;
sync.uuid = pl->guid();
m_syncPlaylists.append( sync );
}
else
{
qDebug() << Q_FUNC_INFO << "Found playlist";
if ( index != -1 && !tracks.isEmpty())
{
qDebug() << Q_FUNC_INFO << "Got pl" << m_syncPlaylists[ index ].playlist->guid();
QList< query_ptr > currTracks;
foreach ( const plentry_ptr ple, m_syncPlaylists[ index ].playlist->entries() )
currTracks << ple->query();
qDebug() << Q_FUNC_INFO << "tracks" << currTracks;
bool changed = false;
QList< query_ptr > mergedTracks = TomahawkUtils::mergePlaylistChanges( currTracks, tracks, changed );
if ( changed )
{
QList<Tomahawk::plentry_ptr> el = m_syncPlaylists[ index ].playlist->entriesFromQueries( mergedTracks, true );
m_syncPlaylists[ index ].playlist->createNewRevision( uuid(), m_syncPlaylists[ index ].playlist->currentrevision(), el );
}
}
}
}
bool operator==( SpotifyAccount::Sync one, SpotifyAccount::Sync two )
{
if( one.id_ == two.id_ )
return true;
return false;
}

View File

@ -0,0 +1,88 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 SpotifyAccount_H
#define SpotifyAccount_H
#include "playlist.h"
#include "utils/tomahawkutils.h"
#include "sourcelist.h"
#include "ResolverAccount.h"
class QTimer;
namespace Tomahawk {
class ExternalResolverGui;
namespace Accounts {
class SpotifyAccountFactory : public AccountFactory
{
Q_OBJECT
public:
SpotifyAccountFactory() {}
virtual Account* createAccount( const QString& accountId = QString() );
virtual QString description() const { return tr( "Play music from and sync your playlists with Spotify" ); }
virtual QString factoryId() const { return "spotifyaccount"; }
virtual QString prettyName() const { return "Spotify"; }
virtual bool acceptsPath( const QString& path ) const;
virtual Account* createFromPath( const QString& path );
virtual AccountTypes types() const { return AccountTypes( ResolverType ); }
virtual bool allowUserCreation() const { return false; }
virtual QPixmap icon() const;
virtual bool isUnique() const { return true; }
};
class SpotifyAccount : public ResolverAccount
{
Q_OBJECT
public:
SpotifyAccount( const QString& accountId );
SpotifyAccount( const QString& accountId, const QString& path );
virtual ~SpotifyAccount() {}
virtual QPixmap icon() const;
virtual QWidget* aclWidget() { return 0; }
virtual InfoSystem::InfoPlugin* infoPlugin() { return 0; }
virtual SipPlugin* sipPlugin() { return 0; }
void addPlaylist( const QString &qid, const QString& title, QList< Tomahawk::query_ptr > tracks );
struct Sync {
QString id_;
QString uuid;
Tomahawk::playlist_ptr playlist;
};
private:
QList<Sync> m_syncPlaylists;
int m_sCount;
};
}
}
#endif // SpotifyAccount_H

View File

@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, 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
@ -228,7 +229,7 @@ ScriptResolver::handleMsg( const QByteArray& msg )
return;
}
if ( msgtype == "results" )
else if ( msgtype == "results" )
{
const QString qid = m.value( "qid" ).toString();
QList< Tomahawk::result_ptr > results;
@ -265,6 +266,25 @@ ScriptResolver::handleMsg( const QByteArray& msg )
Tomahawk::Pipeline::instance()->reportResults( qid, results );
}
else if ( msgtype == "playlist" )
{
QList< Tomahawk::query_ptr > tracks;
const QString qid = m.value( "qid" ).toString();
const QString title = m.value( "identifier" ).toString();
const QVariantList reslist = m.value( "playlist" ).toList();
if( !reslist.isEmpty() )
{
foreach( const QVariant& rv, reslist )
{
QVariantMap m = rv.toMap();
qDebug() << "Found playlist result:" << m;
Tomahawk::query_ptr q = Tomahawk::Query::get( m.value( "artist" ).toString() , m.value( "track" ).toString() , QString(), uuid(), false );
tracks << q;
}
}
}
}

View File

@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, 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
@ -27,7 +28,6 @@
#include "query.h"
#include "ExternalResolverGui.h"
#include "dllmacro.h"
class QWidget;

View File

@ -396,7 +396,8 @@ SettingsDialog::installFromFile()
if( !resolver.isEmpty() )
{
Account* acct = ResolverAccountFactory::createFromPath( resolver, false );
Account* acct = AccountManager::instance()->accountFromPath( resolver );
AccountManager::instance()->addAccount( acct );
TomahawkSettings::instance()->addAccount( acct->accountId() );
AccountManager::instance()->enableAccount( acct );