1
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
3
* Copyright 2012, Casey Link <unnamedrambler@gmail.com>
4
* Copyright 2011-2012, Hugo Lindstrƶm <hugolm84@gmail.com>
5
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
6
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
8
* Tomahawk is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
13
* Tomahawk is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
22
#include "ChartsPlugin.h"
26
#include <QNetworkConfiguration>
27
#include <QNetworkReply>
31
#include "CountryUtils.h"
33
#include "audio/AudioEngine.h"
34
#include "TomahawkSettings.h"
35
#include "utils/TomahawkUtils.h"
36
#include "utils/Logger.h"
37
#include "utils/TomahawkCache.h"
40
#define CHART_URL "http://charts.tomahawk-player.org/"
41
//#define CHART_URL "http://localhost:8080/"
42
#include <qjson/parser.h>
43
#include <qjson/serializer.h>
51
ChartsPlugin::ChartsPlugin()
53
, m_chartsFetchJobs( 0 )
55
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << QThread::currentThread();
56
/// If you add resource, update version aswell
57
m_chartVersion = "2.6";
58
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
62
ChartsPlugin::~ChartsPlugin()
64
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << QThread::currentThread();
71
QVariant data = TomahawkUtils::Cache::instance()->getData( "ChartsPlugin", "chart_sources" );
72
if ( data.canConvert< QList< Tomahawk::InfoSystem::InfoStringHash > >() )
74
const QList< Tomahawk::InfoSystem::InfoStringHash > sourceList = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
75
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, sourceList )
78
qlonglong maxAge = getMaxAge( QString( sourceHash[ "chart_expires" ] ).toLongLong( &ok ) );
79
if ( !ok || maxAge <= 0 )
81
// This source has expired.
82
m_refetchSource << sourceHash[ "chart_source" ];
84
m_chartResources << sourceHash;
89
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Migrating";
90
m_refetchSource << "ALL";
93
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "total sources" << m_chartResources.size() << m_chartResources;
95
if( m_chartResources.size() == 0 || m_refetchSource.size() != 0 )
97
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Will refetch on next request. Empty or Invalid CACHE" << m_chartResources.size() << m_refetchSource;
104
ChartsPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
106
emit info( requestData, QVariant() );
112
ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
114
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
115
bool foundSource = false;
117
switch ( requestData.type )
120
/// We need something to check if the request is actually ment to go to this plugin
121
if ( !hash.contains( "chart_source" ) )
123
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
124
dataError( requestData );
129
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, m_chartResources )
131
if ( sourceHash[ "chart_source" ] == hash[ "chart_source" ] )
139
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "no such source" << hash["chart_source"] << "(" << m_chartResources.size() << " total sources)";
140
dataError( requestData );
145
fetchChartFromCache( requestData );
148
case InfoChartCapabilities:
149
fetchChartCapabilitiesFromCache( requestData );
152
dataError( requestData );
158
ChartsPlugin::fetchChartFromCache( Tomahawk::InfoSystem::InfoRequestData requestData )
160
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
162
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
163
dataError( requestData );
167
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
168
Tomahawk::InfoSystem::InfoStringHash criteria;
170
/// Each request needs to contain both a id, source and expires param
171
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) && !hash.contains( "chart_expires" ) )
173
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
174
dataError( requestData );
178
/// Set the criterias for current chart
179
criteria[ "chart_id" ] = hash[ "chart_id" ];
180
criteria[ "chart_source" ] = hash[ "chart_source" ];
181
criteria[ "chart_expires" ] = hash[ "chart_expires" ];
182
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Checking cache for " << hash["chart_id"] << " from " << hash["chart_source"];
185
const qlonglong maxAge = getMaxAge( QString( hash[ "chart_expires" ] ).toLongLong( &ok ) );
187
if ( !ok || maxAge <= 0 )
189
emit notInCacheSlot( criteria, requestData );
193
emit getCachedInfo( criteria, maxAge, requestData );
199
ChartsPlugin::fetchChartCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData )
201
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
203
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
204
dataError( requestData );
208
Tomahawk::InfoSystem::InfoStringHash criteria;
209
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
210
criteria[ "InfoChartVersion" ] = m_chartVersion;
212
Tomahawk::InfoSystem::InfoStringHash inputData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
214
/// @todo: Only fetch this source, and update charts map
215
if( inputData.contains( "chart_refetch" ) )
217
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Chart source needs to be refetched!" << inputData[ "chart_refetch" ];
218
m_refetchSource << inputData[ "chart_refetch" ];
221
/// Someone requested capabilities, but init() told us someone was out of date
222
/// Next fetch will fetch those that are invalid
224
if ( m_refetchSource.size() != 0 )
226
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Some sources need to refetch!" << m_refetchSource;
227
emit notInCacheSlot( criteria, requestData );
231
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Checking cache for " << "InfoChartCapabilities" << m_chartVersion;
232
emit getCachedInfo( criteria, 172800000 /* 2 days */, requestData );
237
ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
239
switch ( requestData.type )
243
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
244
fetchChart( requestData, criteria["chart_source"], criteria["chart_id"] );
248
case InfoChartCapabilities:
250
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
251
fetchChartSourcesList( false );
252
m_cachedRequests.append( requestData );
258
tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
259
emit info( requestData, QVariant() );
267
ChartsPlugin::fetchChartSourcesList( bool fetchOnlySourceList )
269
QUrl url = QUrl( QString ( CHART_URL "charts" ) );
270
url.addQueryItem( "version", TomahawkUtils::appFriendlyVersion() );
272
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
273
reply->setProperty( "only_source_list", fetchOnlySourceList );
275
connect( reply, SIGNAL( finished() ), SLOT( chartSourcesList() ) );
280
ChartsPlugin::chartSourcesList()
282
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got chart sources list";
283
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
285
if ( reply->error() == QNetworkReply::NoError )
289
const QVariantMap res = p.parse( reply, &ok ).toMap();
290
const QVariantList sources = res.value( "sources" ).toList();
294
tLog() << Q_FUNC_INFO << "Failed to parse sources" << p.errorString() << "On line" << p.errorLine();
298
/// This will re/fetch all sources
299
/// @todo: Fetch only requested source
300
m_chartResources.clear();
302
foreach ( const QVariant &rsource, sources )
304
/// Each item has an expiration, on next request for cache, it will be checked */
305
const QString source = rsource.toString();
307
/// Twisted backend Uppers first header letter, and lowers the rest
308
QString tmpSource = source + "expires";
309
tmpSource[0] = tmpSource[0].toUpper();
311
const QString headerExpiration = reply->rawHeader( QString( tmpSource ).toLocal8Bit() );
312
const qlonglong maxAge = getMaxAge( headerExpiration.toLocal8Bit() );
313
const qlonglong expires = headerExpiration.toLongLong(&ok);
314
Tomahawk::InfoSystem::InfoStringHash source_expire;
318
source_expire[ "chart_source" ] = source;
319
source_expire[ "chart_expires" ] = QString::number(expires);
320
m_chartResources << source_expire;
325
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "MaxAge for " << source << " is 0. Fetching all";
326
reply->setProperty( "only_source_list", false );
332
/// We can store the source list for how long as we want
333
/// In init, we check expiration for each source, and refetch if invalid
334
/// 2 days seems fair enough though
335
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "storing sources in cache" << m_chartResources;
336
TomahawkUtils::Cache::instance()->putData( "ChartsPlugin", 172800000 /* 2 days */, "chart_sources", QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > > ( m_chartResources ) );
338
if( !reply->property( "only_source_list" ).toBool() )
340
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Fetching all sources!";
341
fetchAllChartSources();
345
tDebug() << Q_FUNC_INFO << "Encountered error fetching chart sources list";
351
ChartsPlugin::fetchAllChartSources()
353
if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
355
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoNewRelease fetching source data";
356
foreach ( const Tomahawk::InfoSystem::InfoStringHash source, m_chartResources )
358
QUrl url = QUrl( QString( CHART_URL "charts/%1" ).arg( source[ "chart_source" ] ) );
359
url.addQueryItem( "version", TomahawkUtils::appFriendlyVersion() );
361
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
362
reply->setProperty( "chart_source", source[ "chart_source" ] );
364
tDebug() << Q_FUNC_INFO << "fetching:" << url;
365
connect( reply, SIGNAL( finished() ), SLOT( chartsList() ) );
374
ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData, const QString& source, const QString& chart_id )
376
/// Fetch the chart, we need source and id
377
QUrl url = QUrl ( QString ( CHART_URL "charts/%1/%2" ).arg( source ).arg( chart_id ) );
378
url.addQueryItem( "version", TomahawkUtils::appFriendlyVersion() );
380
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "fetching: " << url;
382
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
383
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
385
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
390
ChartsPlugin::chartsList()
392
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got chart list result";
393
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
395
if ( reply->error() == QNetworkReply::NoError )
399
const QVariantMap res = p.parse( reply, &ok ).toMap();
403
tLog() << "Failed to parse resources" << p.errorString() << "On line" << p.errorLine();
408
/// Got types, append!
409
const QString source = reply->property("chart_source").toString();
410
const qlonglong expires = QString( reply->rawHeader( QString( "Expires" ).toLocal8Bit() ) ).toLongLong( &ok );
414
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Failed to parse expire headers!";
415
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << reply->url();
416
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << reply->rawHeaderPairs();
419
// We'll populate charts with the data from the server
422
QStringList defaultChain;
423
if ( source == "wearehunted" || source == "itunes" || source == "hotnewhiphop" )
425
// Some charts can have an extra param, itunes has geo, WAH has emerging/mainstream
426
// Itunes has geographic-area based charts. So we build a breadcrumb of
427
// ITunes - Country - Albums - Top Chart Type
428
// - Tracks - Top Chart Type
429
// WeAreHunted has Mainstream/Emerging
430
// WeAreHunted - Type - Artists - Chart Type
431
// - Tracks - Chart Type
432
QHash< QString, QVariantMap > extraType;
433
QStringList processed;
434
foreach ( const QVariant& chartObj, res.values() )
436
if ( !chartObj.toMap().isEmpty() )
438
const QVariantMap chart = chartObj.toMap();
439
const QString id = chart.value( "id" ).toString();
440
const QString geo = chart.value( "geo" ).toString();
441
QString name = chart.value( "genre" ).toString();
442
const QString type = QString( chart.value( "type" ).toString() + "s" );
443
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
446
// Japan charts contains multiple duplicates, all which are linked
447
// back to ONE specific id. So we only parse the first
448
// Should/Could be fixed in the chartserver when its less fragile
449
if ( geo == "jp" && type == "Tracks" )
451
if ( processed.contains( name ) )
457
if ( !geo.isEmpty() )
459
if ( !m_cachedCountries.contains( geo ) )
461
extra = Tomahawk::CountryUtils::fullCountryFromCode( geo );
463
for ( int i = 1; i < extra.size(); i++ )
465
if ( extra.at( i ).isUpper() )
467
extra.insert( i, " " );
471
m_cachedCountries[ geo ] = extra;
474
extra = m_cachedCountries[ geo ];
477
extra = chart.value( "extra" ).toString();
479
if ( source == "hotnewhiphop" )
480
name = chart.value( "name" ).toString();
482
if ( name.isEmpty() ) // not a specific chart, an all chart
483
name = tr( "Top Overall" );
488
c[ "type" ] = "album";
490
c[ "default" ] = "true";
492
/// If this item has expired, set it to 0.
493
c[ "expires" ] = ( ok ? QString::number (expires ) : QString::number( 0 ) );
495
QList< Tomahawk::InfoSystem::InfoStringHash > extraTypeData = extraType[ extra ][ type ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
496
extraTypeData.append( c );
497
extraType[ extra ][ type ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( extraTypeData );
501
defaultChain.clear();
502
defaultChain.append( extra );
503
defaultChain.append( type );
504
defaultChain.append( name );
507
foreach ( const QString& c, extraType.keys() )
509
charts[ c ] = extraType[ c ];
511
if ( source == "itunes" )
513
chartName = "iTunes";
515
else if ( source == "soundcloudwall" )
517
chartName = "SoundCloudWall";
519
else if ( source == "wearehunted" )
521
chartName = "WeAreHunted";
523
else if ( source == "hotnewhiphop" )
525
chartName = "HotNewHiphop";
532
// [Source] - Album - Chart Type
533
// [Source] - Track - Chart Type
534
QList< InfoStringHash > albumCharts;
535
QList< InfoStringHash > trackCharts;
536
QList< InfoStringHash > artistCharts;
538
foreach ( const QVariant& chartObj, res.values() )
540
if ( !chartObj.toMap().isEmpty() )
542
const QVariantMap chart = chartObj.toMap();
543
const QString type = chart.value( "type" ).toString();
544
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
547
c[ "id" ] = chart.value( "id" ).toString();
548
c[ "expires" ] = ( ok ? QString::number( expires ) : QString::number( 0 ) );
549
if ( chart.value( "genre").isValid() )
550
c[ "label" ] = chart.value( "genre" ).toString();
552
c[ "label" ] = chart.value( "name" ).toString();
555
c[ "default" ] = "true";
557
if ( type == "Album" )
559
c[ "type" ] = "album";
560
albumCharts.append( c );
562
else if ( type == "Track" )
564
c[ "type" ] = "tracks";
565
trackCharts.append( c );
567
else if ( type == "Artist" )
569
c[ "type" ] = "artists";
570
artistCharts.append( c );
575
defaultChain.clear();
576
defaultChain.append( type + "s" ); //UGLY but it's plural to the user, see below
577
defaultChain.append( c[ "label" ] );
581
if ( !artistCharts.isEmpty() )
582
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( artistCharts ) );
583
if ( !albumCharts.isEmpty() )
584
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( albumCharts ) );
585
if ( !trackCharts.isEmpty() )
586
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( trackCharts ) );
588
/// @note For displaying purposes, upper the first letter
589
/// @note Remeber to lower it when fetching this!
591
chartName[0] = chartName[0].toUpper();
595
/// Add the possible charts and its types to breadcrumb
596
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Adding to charts:" << chartName;
597
QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >();
598
defaultMap[ source ] = defaultChain;
599
m_allChartsMap[ "defaults" ] = defaultMap;
600
m_allChartsMap[ "defaultSource" ] = "itunes";
601
m_allChartsMap.insert( chartName , QVariant::fromValue< QVariantMap >( charts ) );
605
tLog() << "Error fetching charts:" << reply->errorString();
609
if ( !m_cachedRequests.isEmpty() && m_chartsFetchJobs == 0 )
611
foreach ( InfoRequestData request, m_cachedRequests )
613
emit info( request, m_allChartsMap );
615
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Updating cache with" << m_allChartsMap.size() << "charts";
616
Tomahawk::InfoSystem::InfoStringHash criteria;
617
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
618
criteria[ "InfoChartVersion" ] = m_chartVersion;
620
/// We can cache it the lot for 2 days, it will be checked on next request
621
emit updateCache( criteria, 172800000 /* 2 days */, request.type,m_allChartsMap );
623
m_cachedRequests.clear();
629
ChartsPlugin::chartReturned()
631
/// Chart request returned something! Woho
632
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
633
QVariantMap returnedData;
635
if ( reply->error() == QNetworkReply::NoError )
639
QVariantMap res = p.parse( reply, &ok ).toMap();
643
tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
647
const qlonglong maxAge = getMaxAge( reply->rawHeader( QString( "Expires" ).toLocal8Bit() ) );
648
const qlonglong expires = QString( reply->rawHeader( QString( "Expires" ).toLocal8Bit() ) ).toLongLong( &ok );
650
/// SO we have a result, parse it!
651
QVariantList chartResponse = res.value( "list" ).toList();
652
QList< Tomahawk::InfoSystem::InfoStringHash > top_tracks;
653
QList< Tomahawk::InfoSystem::InfoStringHash > top_albums;
654
QStringList top_artists;
656
/// Deside what type, we need to handle it differently
657
/// @todo: We allready know the type, append it to breadcrumb hash
659
if ( res.value( "type" ).toString() == "Album" )
660
setChartType( Album );
661
else if ( res.value( "type" ).toString() == "Track" )
662
setChartType( Track );
663
else if ( res.value( "type" ).toString() == "Artist" )
664
setChartType( Artist );
666
setChartType( None );
668
foreach ( const QVariant& chartR, chartResponse )
670
QString title, artist, album, streamUrl;
671
QVariantMap chartMap = chartR.toMap();
673
if ( !chartMap.isEmpty() )
675
title = chartMap.value( "track" ).toString();
676
album = chartMap.value( "album" ).toString();
677
artist = chartMap.value( "artist" ).toString();
678
streamUrl = chartMap.value( "stream_url" ).toString();
679
/// Maybe we can use rank later on, to display something nice
680
/// rank = chartMap.value( "rank" ).toString();
682
if ( chartType() == Album )
684
if ( album.isEmpty() && artist.isEmpty() ) // don't have enough...
686
tDebug( LOGVERBOSE ) << "Didn't get an artist and album name from chart, not enough to build a query on. Aborting" << title << album << artist;
690
Tomahawk::InfoSystem::InfoStringHash pair;
691
pair["artist"] = artist;
692
pair["album"] = album;
693
top_albums.append( pair );
696
else if ( chartType() == Track )
698
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
700
tDebug( LOGVERBOSE ) << "Didn't get an artist and track name from charts, not enough to build a query on. Aborting" << title << artist << album;
704
Tomahawk::InfoSystem::InfoStringHash pair;
705
pair["artist"] = artist;
706
pair["track"] = title;
707
pair["streamUrl"] = streamUrl;
708
top_tracks.append( pair );
711
else if ( chartType() == Artist )
713
if ( artist.isEmpty() ) // don't have enough...
715
tDebug( LOGVERBOSE ) << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist;
719
top_artists.append( artist );
725
if ( chartType() == Artist )
727
tDebug( LOGVERBOSE ) << "ChartsPlugin:" << "got" << top_artists.size() << "artists";
728
returnedData[ "artists" ] = QVariant::fromValue< QStringList >( top_artists );
729
returnedData[ "type" ] = "artists";
731
else if ( chartType() == Track )
733
tDebug( LOGVERBOSE ) << "ChartsPlugin:" << "got" << top_tracks.size() << "tracks";
734
returnedData[ "tracks" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_tracks );
735
returnedData[ "type" ] = "tracks";
737
else if ( chartType() == Album )
739
tDebug( LOGVERBOSE ) << "ChartsPlugin:" << "got" << top_albums.size() << "albums";
740
returnedData[ "albums" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_albums );
741
returnedData[ "type" ] = "albums";
744
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
746
emit info( requestData, returnedData );
748
Tomahawk::InfoSystem::InfoStringHash criteria;
749
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
750
criteria[ "chart_id" ] = origData[ "chart_id" ];
751
criteria[ "chart_source" ] = origData[ "chart_source" ];
752
criteria[ "chart_expires" ] = ( ok ? QString::number( expires ) : QString::number( 0 ) );
754
/// If the item has expired, cache it for one hour and try and refetch later
755
emit updateCache( criteria, (maxAge == 0 ? 3600000 /* One hour */ : maxAge), requestData.type, returnedData );
759
tDebug() << Q_FUNC_INFO << "Network error in fetching chart:" << reply->url().toString();
760
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
761
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
762
returnedData[ "chart_error" ] = "Invalid ID";
763
returnedData[ "chart_source" ] = origData[ "chart_source" ];
764
returnedData[ "chart_id" ] = origData[ "chart_id" ];
765
emit info( requestData, returnedData );
770
ChartsPlugin::getMaxAge( const QByteArray &rawHeader ) const
773
qlonglong expires = QString( rawHeader ).toLongLong( &ok );
776
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got rawheader " << QString( rawHeader ) << ":" << expires;
777
return getMaxAge( expires );
783
ChartsPlugin::getMaxAge( const qlonglong expires ) const
785
qlonglong currentEpoch = QDateTime::currentMSecsSinceEpoch()/1000;
786
qlonglong expiresInSeconds = expires-currentEpoch;
788
if ( expiresInSeconds > 0 )
790
return ( qlonglong )expiresInSeconds*1000;
799
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::ChartsPlugin )