diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 209c721a7..9ab439ce9 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -113,6 +113,7 @@ set( libSources infosystem/infoplugins/generic/chartsplugin.cpp infosystem/infoplugins/generic/musixmatchplugin.cpp infosystem/infoplugins/generic/musicbrainzPlugin.cpp + infosystem/infoplugins/generic/RoviPlugin.cpp playlist/treemodel.cpp playlist/treeproxymodel.cpp @@ -342,6 +343,7 @@ set( libHeaders infosystem/infoplugins/generic/chartsplugin.h infosystem/infoplugins/generic/musixmatchplugin.h infosystem/infoplugins/generic/musicbrainzPlugin.h + infosystem/infoplugins/generic/RoviPlugin.h network/bufferiodevice.h network/msgprocessor.h diff --git a/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.cpp new file mode 100644 index 000000000..d4ce5950a --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.cpp @@ -0,0 +1,193 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 "RoviPlugin.h" + +#include "utils/logger.h" + +#include +#include +#include + +using namespace Tomahawk::InfoSystem; + +static QString +md5( const QByteArray& src ) +{ + QByteArray const digest = QCryptographicHash::hash( src, QCryptographicHash::Md5 ); + return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' ); +} + +RoviPlugin::RoviPlugin() + : InfoPlugin() +{ + m_supportedGetTypes << InfoAlbumSongs; + + /* + * Your API Key is 7jxr9zggt45h6rg2n4ss3mrj + * Your secret is XUnYutaAW6 + */ + m_apiKey = "7jxr9zggt45h6rg2n4ss3mrj"; + m_secret = "XUnYutaAW6"; +} + +RoviPlugin::~RoviPlugin() +{ + +} + + + +void +RoviPlugin::namChangedSlot( QNetworkAccessManager* nam ) +{ + if ( !nam ) + return; + + m_nam = nam; +} + + +void +RoviPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) +{ + if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) + { + emit info( requestId, requestData, QVariant() ); + return; + } + InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >(); + if ( !hash.contains( "artist" ) || !hash.contains( "album" ) ) + { + emit info( requestId, requestData, QVariant() ); + return; + } + + Tomahawk::InfoSystem::InfoStringHash criteria; + criteria["album"] = hash["album"]; + + emit getCachedInfo( requestId, criteria, 2419200000, requestData ); +} + +void +RoviPlugin::notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) +{ + switch ( requestData.type ) + { + case InfoAlbumSongs: + { + QUrl baseUrl = QUrl( "http://api.rovicorp.com/data/v1/album/tracks" ); + baseUrl.addQueryItem( "album", criteria[ "album" ] ); + + QNetworkReply* reply = makeRequest( baseUrl ); + + reply->setProperty( "requestId", requestId ); + reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); + connect( reply, SIGNAL( finished() ), this, SLOT( albumLookupFinished() ) ); + connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( albumLookupError( QNetworkReply::NetworkError ) ) ); + break; + } + default: + { + Q_ASSERT( false ); + break; + } + } +} + +void +RoviPlugin::albumLookupError( QNetworkReply::NetworkError error ) +{ + if ( error == QNetworkReply::NoError ) + return; + + QNetworkReply* reply = qobject_cast( sender() ); + Q_ASSERT( reply ); + + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + int requestId = reply->property( "requestId" ).toUInt(); + + emit info( requestId, requestData, QVariant() ); + +} + +void +RoviPlugin::albumLookupFinished() +{ + QNetworkReply* reply = qobject_cast( sender() ); + Q_ASSERT( reply ); + + if ( reply->error() != QNetworkReply::NoError ) + return; + + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + int requestId = reply->property( "requestId" ).toUInt(); + + QByteArray data = reply->readAll(); + qDebug() << "data:" << data; + QJson::Parser p; + bool ok; + QVariantMap result = p.parse( data, &ok ).toMap(); + + if ( !ok || result.isEmpty() || !result.contains( "tracks" ) ) + { + tLog() << "Error parsing JSON from Rovi!" << p.errorString() << result; + emit info( requestId, requestData, QVariant() ); + } + + tDebug() << "Got Rovi results:" << result[ "tracks" ]; + QVariantList tracks = result[ "tracks" ].toList(); + QStringList trackNameList; + foreach ( const QVariant& track, tracks ) + { + const QVariantMap trackData = track.toMap(); + if ( trackData.contains( "title" ) ) + trackNameList << trackData[ "title" ].toString(); + } + tDebug() << "FOUND TRACK LIST FROM ROVI:" << trackNameList; + + QVariantMap returnedData; + returnedData["tracks"] = trackNameList; + + emit info( requestId, requestData, returnedData ); + + Tomahawk::InfoSystem::InfoStringHash criteria; + criteria["artist"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["artist"]; + + emit updateCache( criteria, 0, requestData.type, returnedData ); +} + + +QNetworkReply* +RoviPlugin::makeRequest( QUrl url ) +{ + url.addQueryItem( "apikey", m_apiKey ); + url.addEncodedQueryItem( "sig", generateSig() ); + + qDebug() << "url:" << url.toString(); + return m_nam->get( QNetworkRequest( url ) ); +} + + +QByteArray +RoviPlugin::generateSig() const +{ + QByteArray raw = m_apiKey + m_secret + QString::number( QDateTime::currentMSecsSinceEpoch() / 1000 ).toLatin1(); + return md5( raw ).toLatin1(); + +} diff --git a/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.h b/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.h new file mode 100644 index 000000000..0bc2e9e8c --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.h @@ -0,0 +1,67 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 ROVIPLUGIN_H +#define ROVIPLUGIN_H + +#include "infosystem/infosystem.h" + +#include + +class QNetworkAccessManager; + +namespace Tomahawk +{ + +namespace InfoSystem +{ + +class RoviPlugin : public InfoPlugin +{ + Q_OBJECT +public: + RoviPlugin(); + virtual ~RoviPlugin(); + +protected: + virtual void namChangedSlot( QNetworkAccessManager* nam ); + virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ); + + virtual void pushInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant ) + {} + + virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); + +private slots: + void albumLookupFinished(); + void albumLookupError( QNetworkReply::NetworkError ); +private: + QNetworkReply* makeRequest( QUrl url ); + QByteArray generateSig() const; + + QNetworkAccessManager* m_nam; + + QByteArray m_apiKey; + QByteArray m_secret; +}; + +} + +} + +#endif // ROVIPLUGIN_H diff --git a/src/libtomahawk/infosystem/infosystemworker.cpp b/src/libtomahawk/infosystem/infosystemworker.cpp index 9ae11951c..965a21581 100644 --- a/src/libtomahawk/infosystem/infosystemworker.cpp +++ b/src/libtomahawk/infosystem/infosystemworker.cpp @@ -40,6 +40,7 @@ #endif #include "lastfm/NetworkAccessManager" +#include "infoplugins/generic/RoviPlugin.h" namespace Tomahawk { @@ -92,7 +93,9 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac InfoPluginPtr sptr( new ChartsPlugin() ); m_plugins.append( sptr ); registerInfoTypes( sptr, sptr.data()->supportedGetTypes(), sptr.data()->supportedPushTypes() ); - + InfoPluginPtr roviptr( new RoviPlugin() ); + m_plugins.append( roviptr ); + registerInfoTypes( roviptr, roviptr.data()->supportedGetTypes(), roviptr.data()->supportedPushTypes() ); #ifdef Q_WS_MAC InfoPluginPtr admptr( new AdiumPlugin() ); @@ -105,7 +108,7 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac registerInfoTypes( fdonotifyptr, fdonotifyptr.data()->supportedGetTypes(), fdonotifyptr.data()->supportedPushTypes() ); InfoPluginPtr mprisptr( new MprisPlugin() ); m_plugins.append( mprisptr ); - registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() ); + registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() ); #endif Q_FOREACH( InfoPluginPtr plugin, m_plugins ) diff --git a/src/libtomahawk/playlist/treemodel.cpp b/src/libtomahawk/playlist/treemodel.cpp index 8dd336ea5..14cc9e06f 100644 --- a/src/libtomahawk/playlist/treemodel.cpp +++ b/src/libtomahawk/playlist/treemodel.cpp @@ -629,12 +629,13 @@ TreeModel::addTracks( const album_ptr& album, const QModelIndex& parent ) artistInfo["artist"] = album->artist()->name(); artistInfo["album"] = album->name(); + m_receivedInfoData.remove( artistInfo ); Tomahawk::InfoSystem::InfoRequestData requestData; requestData.caller = m_infoId; requestData.customData["rows"] = QVariant( rows ); requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo ); requestData.type = Tomahawk::InfoSystem::InfoAlbumSongs; - Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData, 0, true ); } else Q_ASSERT( false ); @@ -845,6 +846,10 @@ TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QV case Tomahawk::InfoSystem::InfoAlbumSongs: { + if ( m_receivedInfoData.contains( requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >() ) ) + break; + m_receivedInfoData.insert( requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >() ); + QVariantMap returnedData = output.value< QVariantMap >(); QStringList tracks = returnedData[ "tracks" ].toStringList(); QList ql; diff --git a/src/libtomahawk/playlist/treemodel.h b/src/libtomahawk/playlist/treemodel.h index af4aa6bf0..0c22511cc 100644 --- a/src/libtomahawk/playlist/treemodel.h +++ b/src/libtomahawk/playlist/treemodel.h @@ -171,6 +171,7 @@ private: Tomahawk::collection_ptr m_collection; QHash m_coverHash; + QSet m_receivedInfoData; }; #endif // ALBUMMODEL_H