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

Implement New Releases info plugin

Heavily based off existing charts info plugin, refactoring and consolidating
can be done later.
This commit is contained in:
Casey Link 2012-04-10 18:11:58 -05:00
parent 066c387ae9
commit 69d1450b5c
5 changed files with 452 additions and 3 deletions

View File

@ -251,6 +251,7 @@ set( libSources
infosystem/infoplugins/generic/echonestplugin.cpp
infosystem/infoplugins/generic/chartsplugin.cpp
infosystem/infoplugins/generic/newreleasesplugin.cpp
infosystem/infoplugins/generic/spotifyPlugin.cpp
infosystem/infoplugins/generic/hypemPlugin.cpp
infosystem/infoplugins/generic/musixmatchplugin.cpp

View File

@ -0,0 +1,343 @@
#include "newreleasesplugin.h"
#include <QtCore/QDir>
#include <QtCore/QSettings>
#include <QtNetwork/QNetworkConfiguration>
#include <QtNetwork/QNetworkReply>
#include "album.h"
#include "chartsplugin_data_p.h"
#include "typedefs.h"
#include "audio/audioengine.h"
#include "tomahawksettings.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include <qjson/parser.h>
#include <qjson/serializer.h>
#define CHART_URL "http://charts.tomahawk-player.org/"
//#define CHART_URL "http://localhost:8080/"
using namespace Tomahawk::InfoSystem;
NewReleasesPlugin::NewReleasesPlugin()
: InfoPlugin()
, m_nrFetchJobs ( 0 )
{
m_nrVersion = "0";
m_supportedGetTypes << InfoNewReleaseCapabilities << InfoNewRelease;
}
NewReleasesPlugin::~NewReleasesPlugin()
{
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO;
}
void NewReleasesPlugin::dataError ( InfoRequestData requestData )
{
emit info ( requestData, QVariant() );
return;
}
void NewReleasesPlugin::getInfo ( InfoRequestData requestData )
{
//qDebug() << Q_FUNC_INFO << requestData.caller;
//qDebug() << Q_FUNC_INFO << requestData.customData;
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
bool foundSource = false;
switch ( requestData.type ) {
case InfoNewRelease:
/// We need something to check if the request is actually ment to go to this plugin
if ( !hash.contains ( "nr_source" ) ) {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
dataError ( requestData );
break;
} else {
foreach ( QString resource, m_nrSources ) {
if ( resource == hash["nr_source"] ) {
foundSource = true;
}
}
if ( !foundSource ) {
dataError ( requestData );
break;
}
}
fetchNRFromCache ( requestData );
break;
case InfoNewReleaseCapabilities:
fetchNRCapabilitiesFromCache ( requestData );
break;
default:
dataError ( requestData );
}
}
void NewReleasesPlugin::fetchNRFromCache ( InfoRequestData requestData )
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) {
dataError ( requestData );
return;
}
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
Tomahawk::InfoSystem::InfoStringHash criteria;
/// Each request needs to contain both a id and source
if ( !hash.contains ( "nr_id" ) && !hash.contains ( "nr_source" ) ) {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
dataError ( requestData );
return;
}
/// Set the criterias for current chart
criteria["nr_id"] = hash["nr_id"];
criteria["nr_source"] = hash["nr_source"];
emit getCachedInfo ( criteria, 86400000, requestData );
}
void NewReleasesPlugin::fetchNRCapabilitiesFromCache ( InfoRequestData requestData )
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
dataError ( requestData );
return;
}
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoNewReleaseCapabilities" ] = "newreleasesplugin";
criteria[ "InfoNewReleaseVersion" ] = m_nrVersion;
emit getCachedInfo ( criteria, 864000000, requestData );
}
void NewReleasesPlugin::notInCacheSlot ( InfoStringHash criteria, InfoRequestData requestData )
{
switch ( requestData.type ) {
case InfoNewRelease: {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoNewRelease not in cache! Fetching...";
fetchNR ( requestData, criteria["nr_source"], criteria["nr_id"] );
return;
}
case InfoNewReleaseCapabilities: {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
fetchNRSourcesList();
m_cachedRequests.append ( requestData );
return;
}
default: {
tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
emit info ( requestData, QVariant() );
return;
}
}
}
void NewReleasesPlugin::fetchNRSourcesList()
{
QUrl url = QUrl ( QString ( CHART_URL "newreleases" ) );
QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
tDebug() << "fetching:" << url;
connect ( reply, SIGNAL ( finished() ), SLOT ( nrSourcesList() ) );
}
void NewReleasesPlugin::nrSourcesList()
{
tDebug ( LOGVERBOSE ) << "Got newreleases sources list";
QNetworkReply* reply = qobject_cast<QNetworkReply*> ( sender() );
if ( reply->error() == QNetworkReply::NoError ) {
QJson::Parser p;
bool ok;
const QVariantMap res = p.parse ( reply, &ok ).toMap();
const QVariantList sources = res.value ( "sources" ).toList();
if ( !ok ) {
tLog() << "Failed to parse sources" << p.errorString() << "On line" << p.errorLine();
return;
}
m_nrSources.clear();
foreach ( const QVariant &source, sources ) {
m_nrSources << source.toString();
}
fetchAllNRSources();
}
}
void NewReleasesPlugin::fetchAllNRSources()
{
if ( !m_nrSources.isEmpty() && m_allNRsMap.isEmpty() ) {
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoNewRelease fetching source data";
foreach ( QString source, m_nrSources ) {
QUrl url = QUrl ( QString ( CHART_URL "newreleases/%1" ).arg ( source ) );
QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
reply->setProperty ( "nr_source", source );
tDebug() << "fetching:" << url;
connect ( reply, SIGNAL ( finished() ), SLOT ( nrList() ) );
m_nrFetchJobs++;
}
}
}
void NewReleasesPlugin::fetchNR ( InfoRequestData requestData, const QString& source, const QString& nr_id )
{
/// Fetch the chart, we need source and id
QUrl url = QUrl ( QString ( CHART_URL "newreleases/%1/%2" ).arg ( source ).arg ( nr_id ) );
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "fetching: " << url;
QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
reply->setProperty ( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData > ( requestData ) );
connect ( reply, SIGNAL ( finished() ), SLOT ( nrReturned() ) );
}
void NewReleasesPlugin::nrList()
{
tDebug ( LOGVERBOSE ) << "Got newreleases list result";
QNetworkReply* reply = qobject_cast<QNetworkReply*> ( sender() );
if ( reply->error() == QNetworkReply::NoError ) {
QJson::Parser p;
bool ok;
const QVariantMap res = p.parse ( reply, &ok ).toMap();
if ( !ok ) {
tLog() << "Failed to parse resources" << p.errorString() << "On line" << p.errorLine();
return;
}
/// Got types, append!
const QString source = reply->property ( "nr_source" ).toString();
// We'll populate newreleases with the data from the server
QVariantMap newreleases;
QString nrName;
// Building:
// [Source] - New Release
QList< InfoStringHash > albumNRs;
foreach ( const QVariant &nrObj, res.values() ) {
if ( !nrObj.toMap().isEmpty() ) {
const QVariantMap nrMap = nrObj.toMap();
const QString type = nrMap.value ( "type" ).toString();
InfoStringHash nr;
nr["id"] = nrMap.value ( "id" ).toString();
nr["label"] = nrMap.value ( "name" ).toString();
nr["date"] = nrMap.value ( "date" ).toString();
if ( type == "Album" ) {
nr[ "type" ] = "album";
albumNRs.append ( nr );
} else {
tLog() << "Unknown newrelease type " << type;
continue;
}
}
}
if ( !albumNRs.isEmpty() )
newreleases.insert ( tr ( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > > ( albumNRs ) );
/// @note For displaying purposes, upper the first letter
/// @note Remeber to lower it when fetching this!
nrName = source;
nrName[0] = nrName[0].toUpper();
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING newrelease TO NRS:" << nrName;
QVariantMap defaultMap = m_allNRsMap.value ( "defaults" ).value< QVariantMap >();
m_allNRsMap.insert ( nrName, QVariant::fromValue< QVariantMap > ( newreleases ) );
} else {
tLog() << "Error fetching charts:" << reply->errorString();
}
m_nrFetchJobs--;
if ( !m_cachedRequests.isEmpty() && m_nrFetchJobs == 0 ) {
foreach ( InfoRequestData request, m_cachedRequests ) {
emit info ( request, m_allNRsMap );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoNewReleaseCapabilities" ] = "newreleasesplugin";
criteria[ "InfoNewReleaseVersion" ] = m_nrVersion;
emit updateCache ( criteria, 864000000, request.type, m_allNRsMap );
}
m_cachedRequests.clear();
}
}
void NewReleasesPlugin::nrReturned()
{
/// Chart request returned something! Woho
QNetworkReply* reply = qobject_cast<QNetworkReply*> ( sender() );
QVariantMap returnedData;
if ( reply->error() == QNetworkReply::NoError ) {
QJson::Parser p;
bool ok;
QVariantMap res = p.parse ( reply, &ok ).toMap();
if ( !ok ) {
tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
return;
}
/// SO we have a result, parse it!
QVariantList albumList = res.value ( "list" ).toList();
QList< Tomahawk::InfoSystem::InfoStringHash > newreleases;
foreach( const QVariant & albumObj, albumList ) {
QVariantMap albumMap = albumObj.toMap();
if(!albumMap.isEmpty()) {
const QString album = albumMap.value("album").toString();
const QString artist = albumMap.value("artist").toString();
const QString date = albumMap.value("date").toString();
Tomahawk::InfoSystem::InfoStringHash pair;
pair["artist"] = artist;
pair["album"] = album;
newreleases.append( pair );
}
}
tDebug() << "NewReleasesPlugin:" << "\tgot " << newreleases.size() << " albums";
returnedData[ "albums" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( newreleases );
returnedData[ "type" ] = "albums";
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( requestData, returnedData );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "nr_id" ] = origData[ "nr_id" ];
criteria[ "nr_source" ] = origData[ "nr_source" ];
emit updateCache( criteria, 86400000, requestData.type, returnedData );
} else
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Network error in fetching newrelease:" << reply->url().toString();
}

View File

@ -0,0 +1,100 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2012, Casey Link <unnamedrambler@gmail.com>
*
* 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 NEWRELEASESPLUGIN_H
#define NEWRELEASESPLUGIN_H
#include "infosystem/infosystem.h"
#include "infosystem/infosystemworker.h"
#include <QtNetwork/QNetworkReply>
#include <QtCore/QObject>
class QNetworkReply;
namespace Tomahawk
{
namespace InfoSystem
{
class NewReleasesPlugin : public InfoPlugin
{
Q_OBJECT
public:
NewReleasesPlugin();
virtual ~NewReleasesPlugin();
protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
{
Q_UNUSED( pushData );
}
/**
* Parses a QNetworkReply of a list of newreleases sources.
*/
void nrSourcesList();
/**
* Parses a QNetworkReply of a list of newreleases from a particular source
*/
void nrList();
/**
* Parses a QNetworkReply for the newreleases data for a particular newrelease
*/
void nrReturned();
private:
/**
* Fetch list of newlreeases sources (e.g., rovi)
* Populates the m_nrSources member.
*/
void fetchNRSourcesList();
/**
* Requests newrelease list for each source in m_chartSources
*/
void fetchAllNRSources();
/**
* Fetches a specific newrelease from a particular source.
* Updates the cache.
*/
void fetchNR( Tomahawk::InfoSystem::InfoRequestData requestData, const QString& source, const QString& nr_id );
void fetchNRFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchNRCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
QStringList m_nrSources;
QString m_nrVersion;
QList< InfoStringHash > m_newreleases;
//ChartType m_chartType;
QVariantMap m_allNRsMap;
uint m_nrFetchJobs;
QList< InfoRequestData > m_cachedRequests;
QHash< QString, QString > m_cachedCountries;
QWeakPointer< QNetworkAccessManager > m_nam;
};
}
}
#endif // NEWRELEASESPLUGIN_H

View File

@ -112,6 +112,9 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
*/
InfoChart = 51,
InfoNewReleaseCapabilities = 52,
InfoNewRelease = 53,
InfoMiscTopHotttness = 60,
InfoMiscTopTerms = 61,
@ -195,7 +198,7 @@ struct InfoPushData {
, pushFlags( pflags )
, infoPair( Tomahawk::InfoSystem::PushInfoPair( QVariantMap(), QVariant() ) )
{}
};

View File

@ -28,6 +28,7 @@
#include "infoplugins/generic/echonestplugin.h"
#include "infoplugins/generic/musixmatchplugin.h"
#include "infoplugins/generic/chartsplugin.h"
#include "infoplugins/generic/newreleasesplugin.h"
#include "infoplugins/generic/spotifyPlugin.h"
#include "infoplugins/generic/musicbrainzPlugin.h"
#include "infoplugins/generic/hypemPlugin.h"
@ -86,6 +87,7 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) );
addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) );
addInfoPlugin( InfoPluginPtr( new ChartsPlugin() ) );
addInfoPlugin( InfoPluginPtr( new NewReleasesPlugin() ) );
addInfoPlugin( InfoPluginPtr( new RoviPlugin() ) );
addInfoPlugin( InfoPluginPtr( new SpotifyPlugin() ) );
addInfoPlugin( InfoPluginPtr( new hypemPlugin() ) );
@ -274,7 +276,7 @@ void
InfoSystemWorker::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
{
tDebug() << Q_FUNC_INFO << "type is " << pushData.type;
if ( pushData.pushFlags != PushNoFlag )
{
if ( pushData.pushFlags & PushShortUrlFlag )
@ -334,7 +336,7 @@ InfoSystemWorker::shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callback
m_shortLinksWaiting--;
if ( !m_shortLinksWaiting )
disconnect( GlobalActionManager::instance(), SIGNAL( shortLinkReady( QUrl, QUrl, QVariant ) ) );
if ( !callbackObj.isValid() )
{
tDebug() << Q_FUNC_INFO << "callback object was not valid, cannot continue";