File indexing completed on 2025-02-23 04:27:30

0001 /***************************************************************************************
0002 * Copyright (c) 2009 Nathan Sala <sala.nathan@gmail.com>                               *
0003 * Copyright (c) 2009 Oleksandr Khayrullin <saniokh@gmail.com>                          *
0004 * Copyright (c) 2009-2010 Joffrey Clavel <jclavel@clabert.info>                        *
0005 *                                                                                      *
0006 * This program is free software; you can redistribute it and/or modify it under        *
0007 * the terms of the GNU General Public License as published by the Free Software        *
0008 * Foundation; either version 2 of the License, or (at your option) any later           *
0009 * version.                                                                             *
0010 *                                                                                      *
0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0014 *                                                                                      *
0015 * You should have received a copy of the GNU General Public License along with         *
0016 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0017 ****************************************************************************************/
0018 
0019 #define DEBUG_PREFIX "SimilarArtistsEngine"
0020 
0021 #include "SimilarArtistsEngine.h"
0022 
0023 #include "EngineController.h"
0024 #include "core/meta/Meta.h"
0025 #include "core/support/Amarok.h"
0026 #include "core/support/Debug.h"
0027 
0028 #include <QTimer>
0029 #include <QXmlStreamReader>
0030 
0031 AMAROK_EXPORT_DATAENGINE( similarArtists, SimilarArtistsEngine )
0032 
0033 using namespace Context;
0034 
0035 SimilarArtistsEngine::SimilarArtistsEngine( QObject *parent, const QList<QVariant>& /*args*/ )
0036     : DataEngine( parent )
0037     , m_maxArtists( 5 )
0038 {
0039 }
0040 
0041 SimilarArtistsEngine::~SimilarArtistsEngine()
0042 {
0043 }
0044 
0045 void
0046 SimilarArtistsEngine::init()
0047 {
0048     EngineController *engine = The::engineController();
0049     connect( engine, SIGNAL(trackChanged(Meta::TrackPtr)), SLOT(update()) );
0050     connect( engine, SIGNAL(trackMetadataChanged(Meta::TrackPtr)), SLOT(update()) );
0051 }
0052 
0053 bool
0054 SimilarArtistsEngine::sourceRequestEvent( const QString &name )
0055 {
0056     if( !name.startsWith( "similarArtists" ) )
0057         return false;
0058 
0059     bool force( false );
0060     QStringList tokens = name.split( QLatin1Char(':'), Qt::SkipEmptyParts );
0061     if( tokens.contains( QLatin1String("forceUpdate") ) )
0062         force = true;
0063 
0064     if( tokens.contains( QLatin1String("artist") ) )
0065         return update( m_artist );
0066     else
0067         return update( force );
0068 }
0069 
0070 bool
0071 SimilarArtistsEngine::update( bool force )
0072 {
0073     QString newArtist;
0074 
0075     Meta::TrackPtr track = The::engineController()->currentTrack();
0076     if( track )
0077     {
0078         if( Meta::ArtistPtr artistPtr = track->artist() )
0079             newArtist = artistPtr->name();
0080     }
0081 
0082     if( newArtist.isEmpty() )
0083     {
0084         m_artist.clear();
0085         removeAllData( "similarArtists" );
0086         return false;
0087     }
0088     else   //valid artist
0089     {
0090         // wee make a request only if the artist is different
0091         if( force || (newArtist != m_artist) )
0092         {
0093             // if the artist has changed
0094             m_artist = newArtist;
0095             similarArtistsRequest( m_artist );
0096             return true;
0097         }
0098     }
0099     return false;
0100 }
0101 
0102 bool
0103 SimilarArtistsEngine::update( const QString &name )
0104 {
0105     if( name.isEmpty() )
0106         return false;
0107 
0108     m_artist = name;
0109     similarArtistsRequest( m_artist );
0110     return true;
0111 }
0112 
0113 void
0114 SimilarArtistsEngine::similarArtistsRequest( const QString &artistName )
0115 {
0116     // we generate the url for the demand on the lastFM Api
0117     QUrl url;
0118     url.setScheme( "http" );
0119     url.setHost( "ws.audioscrobbler.com" );
0120     url.setPath( "/2.0/" );
0121     url.addQueryItem( "method", "artist.getSimilar" );
0122     url.addQueryItem( "api_key", Amarok::lastfmApiKey() );
0123     url.addQueryItem( "artist", artistName );
0124     url.addQueryItem( "limit",  QString::number( m_maxArtists ) );
0125 
0126     The::networkAccessManager()->getData( url, this,
0127          SLOT(parseSimilarArtists(QUrl,QByteArray,NetworkAccessManagerProxy::Error)) );
0128 }
0129 
0130 void
0131 SimilarArtistsEngine::parseSimilarArtists( const QUrl &url, consr QByteArray &data,
0132                                            NetworkAccessManagerProxy::Error e )
0133 {
0134     if( e.code != QNetworkReply::NoError )
0135     {
0136         removeAllData( "similarArtists" );
0137         warning() << "Failed to parse similar artists xml:" << url << e.description;
0138         return;
0139     }
0140 
0141     if( data.isEmpty() )
0142         return;
0143 
0144     QXmlStreamReader xml( data );
0145     SimilarArtist::List saList = SimilarArtist::listFromXml( xml );
0146     debug() << "Found" << saList.size() << "similar artists to" << m_artist;
0147     Plasma::DataEngine::Data eData;
0148     eData[ "artist"  ] = m_artist;
0149     eData[ "similar" ] = QVariant::fromValue( saList );
0150     setData( "similarArtists", eData );
0151 }
0152 
0153 int
0154 SimilarArtistsEngine::maximumArtists() const
0155 {
0156     return m_maxArtists;
0157 }
0158 
0159 void
0160 SimilarArtistsEngine::setMaximumArtists( int number )
0161 {
0162     m_maxArtists = number;
0163 }
0164 
0165 QString
0166 SimilarArtistsEngine::artist() const
0167 {
0168     return m_artist;
0169 }
0170 
0171 void
0172 SimilarArtistsEngine::setArtist( const QString &name )
0173 {
0174     m_artist = name;
0175 }
0176 
0177 #include "SimilarArtistsEngine.moc"