PageRenderTime 226ms CodeModel.GetById 81ms app.highlight 80ms RepoModel.GetById 60ms app.codeStats 1ms

/src/libtomahawk/infosystem/infoplugins/generic/hypemPlugin.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 395 lines | 286 code | 81 blank | 28 comment | 38 complexity | 4e340216bf3e13bc3c06a79f2503a95c MD5 | raw file
  1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2 *
  3 *   Copyright 2010-2011, Hugo Lindstr??m <hugolm84@gmail.com>
  4 *
  5 *   Tomahawk is free software: you can redistribute it and/or modify
  6 *   it under the terms of the GNU General Public License as published by
  7 *   the Free Software Foundation, either version 3 of the License, or
  8 *   (at your option) any later version.
  9 *
 10 *   Tomahawk is distributed in the hope that it will be useful,
 11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 13 *   GNU General Public License for more details.
 14 *
 15 *   You should have received a copy of the GNU General Public License
 16 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 17 */
 18
 19#include "hypemPlugin.h"
 20
 21#include <QDir>
 22#include <QSettings>
 23#include <QCryptographicHash>
 24#include <QNetworkConfiguration>
 25#include <QNetworkReply>
 26
 27#include "album.h"
 28#include "typedefs.h"
 29#include "tomahawksettings.h"
 30#include "utils/tomahawkutils.h"
 31#include "utils/logger.h"
 32
 33#define HYPEM_URL "http://hypem.com/playlist/"
 34#define HYPEM_END_URL "json/1/data.js"
 35#include <qjson/parser.h>
 36#include <qjson/serializer.h>
 37
 38using namespace Tomahawk::InfoSystem;
 39
 40
 41hypemPlugin::hypemPlugin()
 42    : InfoPlugin()
 43    , m_chartsFetchJobs( 0 )
 44{
 45
 46    m_supportedGetTypes << InfoChart << InfoChartCapabilities;
 47    m_types << "Artists" << "Tracks" << "Recent by Tag";
 48
 49    m_trackTypes    << "Last 3 Days"
 50                    << "Last Week"
 51                    << "No Remixes"
 52                    << "On Twitter";
 53
 54    m_byTagTypes    << "Dance"
 55                    << "Experimental"
 56                    << "Electronic"
 57                    << "Funk"
 58                    << "Hip-hop"
 59                    << "Indie"
 60                    << "Instrumental"
 61                    << "Post-punk"
 62                    << "Rock"
 63                    << "Singer-songwriter"
 64                    << "Alternative"
 65                    << "Pop"
 66                    << "Female"
 67                    << "Vocalist"
 68                    << "Folk"
 69                    << "Electro"
 70                    << "Lo-fi"
 71                    << "Psychedelic"
 72                    << "Rap"
 73                    << "British"
 74                    << "Ambient"
 75                    << "Dubstep"
 76                    << "House"
 77                    << "Chillwave"
 78                    << "Dreampop"
 79                    << "Shoegaze"
 80                    << "Chillout"
 81                    << "Soul"
 82                    << "French"
 83                    << "Acoustic"
 84                    << "Canadian"
 85                    << "60s"
 86                    << "80s"
 87                    << "Techno"
 88                    << "Punk"
 89                    << "New wave";
 90    chartTypes();
 91
 92}
 93
 94
 95
 96
 97hypemPlugin::~hypemPlugin()
 98{
 99    qDebug() << Q_FUNC_INFO;
100}
101
102
103void
104hypemPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
105{
106    emit info( requestData, QVariant() );
107    return;
108}
109
110
111void
112hypemPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
113{
114    qDebug() << Q_FUNC_INFO << requestData.caller;
115    qDebug() << Q_FUNC_INFO << requestData.customData;
116
117    InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
118
119
120    switch ( requestData.type )
121    {
122
123        case InfoChart:
124            if ( !hash.contains( "chart_source" ) || hash["chart_source"].toLower() != "hype machine" )
125            {
126                dataError( requestData );
127                break;
128            }
129            qDebug() << Q_FUNC_INFO << "InfoCHart req for" << hash["chart_source"];
130            fetchChart( requestData );
131            break;
132
133        case InfoChartCapabilities:
134            fetchChartCapabilities( requestData );
135            break;
136        default:
137            dataError( requestData );
138    }
139}
140
141void
142hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
143{
144
145    if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
146    {
147        dataError( requestData );
148        return;
149    }
150
151    InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
152    Tomahawk::InfoSystem::InfoStringHash criteria;
153
154    /// Each request needs to contain both a id and source
155    if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
156    {
157        dataError( requestData );
158        return;
159
160    }
161    /// Set the criterias for current chart
162    criteria["chart_id"] = hash["chart_id"];
163    criteria["chart_source"] = hash["chart_source"];
164    /// @todo
165    /// set cache time based on wether requested type is 3day, lastweek or recent.
166    emit getCachedInfo( criteria, 86400000, requestData );
167}
168
169void
170hypemPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
171{
172    if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
173    {
174        dataError( requestData );
175        return;
176    }
177
178    Tomahawk::InfoSystem::InfoStringHash criteria;
179    emit getCachedInfo( criteria, 0, requestData );
180}
181
182void
183hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
184{
185    switch ( requestData.type )
186    {
187        case InfoChart:
188        {
189            /// Fetch the chart, we need source and id
190            tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
191            QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) );
192            qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
193
194            QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
195            reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
196            connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
197            return;
198
199
200        }
201
202        case InfoChartCapabilities:
203        {
204            tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
205            if ( m_chartsFetchJobs > 0 )
206            {
207                qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
208                m_cachedRequests.append( requestData );
209                return;
210            }
211
212            emit info( requestData, m_allChartsMap );
213            return;
214        }
215
216        default:
217        {
218            tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
219            emit info( requestData, QVariant() );
220            return;
221        }
222    }
223}
224
225
226void
227hypemPlugin::chartTypes()
228{
229    /// Get possible chart type for specifichypemPlugin: InfoChart types returned chart source
230    tDebug() << Q_FUNC_INFO << "Got hypem types";
231
232    QVariantMap charts;
233
234    foreach(QVariant types, m_types )
235    {
236        QList< InfoStringHash > chart_types;
237        QList< InfoStringHash > pop_charts;
238        InfoStringHash c;
239
240        if(types.toString() != "Artists")
241        {
242
243            if(types.toString() == "Tracks")
244            {
245
246                foreach(QVariant trackType, m_trackTypes)
247                {
248                    QString typeId;
249                    if(trackType.toString() == "Last 3 Days")
250                        typeId = "popular/3day";
251
252                    if(trackType.toString() == "Last Week")
253                        typeId = "popular/lastweek";
254
255                    if(trackType.toString() == "No Remixes")
256                        typeId = "popular/noremix";
257
258                    if(trackType.toString() == "On Twitter")
259                        typeId = "popular/twitter";
260
261                    c[ "id" ] = typeId;
262                    c[ "label" ] = trackType.toString();
263                    c[ "type" ] = "tracks";
264                    pop_charts.append( c );
265                }
266
267                chart_types.append( pop_charts );
268
269            }
270            else if(types.toString() == "Recent by Tag")
271            {
272                foreach(QVariant tagTypes, m_byTagTypes)
273                {
274
275                    c[ "id" ] = "tags/" + tagTypes.toString().toLower();
276                    c[ "label" ] = tagTypes.toString();
277                    c[ "type" ] = tagTypes.toString();
278                    chart_types.append( c );
279                }
280
281            }
282
283        }else
284        {
285            InfoStringHash c;
286            c[ "id" ] = "popular/artists";
287            c[ "label" ] = "Most Recent";
288            c[ "type" ] = "artists";
289            chart_types.append( c );
290        }
291
292        charts.insert( types.toString(), QVariant::fromValue<QList< InfoStringHash > >( chart_types ) );
293    }
294
295
296    m_allChartsMap.insert( "Hype Machine", QVariant::fromValue<QVariantMap>( charts ) );
297    qDebug() << "hypemPlugin:Chartstype: " << m_allChartsMap;
298
299
300}
301
302void
303hypemPlugin::chartReturned()
304{
305
306    /// Chart request returned something! Woho
307    QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
308    QString url = reply->url().toString();
309    QVariantMap returnedData;
310    if ( reply->error() == QNetworkReply::NoError )
311    {
312        QJson::Parser p;
313        bool ok;
314        QVariantMap res = p.parse( reply, &ok ).toMap();
315
316        if ( !ok )
317        {
318            tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
319            return;
320        }
321
322        /// SO we have a result, parse it!
323        QList< InfoStringHash > top_tracks;
324        QStringList top_artists;
325
326        if( url.contains( "artists" ) )
327            setChartType( Artist );
328        else
329            setChartType( Track );
330
331        foreach(QVariant result, res )
332        {
333            QString title, artist;
334            QVariantMap chartMap = result.toMap();
335
336            if ( !chartMap.isEmpty() )
337            {
338
339                title = chartMap.value( "title" ).toString();
340                artist = chartMap.value( "artist" ).toString();
341
342                if( chartType() == Track )
343                {
344                    InfoStringHash pair;
345                    pair["artist"] = artist;
346                    pair["track"] = title;
347                    top_tracks << pair;
348
349                    qDebug() << "HypemChart type is track";
350                }
351
352
353                if( chartType() == Artist )
354                {
355
356                    top_artists << artist;
357                    qDebug() << "HypemChart type is artist";
358
359                }
360            }
361        }
362
363        if( chartType() == Track )
364        {
365            tDebug() << "HypemPlugin:" << "\tgot " << top_tracks.size() << " tracks";
366            returnedData["tracks"] = QVariant::fromValue( top_tracks );
367            returnedData["type"] = "tracks";
368        }
369
370
371
372        if( chartType() == Artist )
373        {
374            tDebug() << "HypemPlugin:" << "\tgot " << top_artists.size() << " artists";
375            returnedData["artists"] = top_artists;
376            returnedData["type"] = "artists";
377        }
378
379        Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
380
381
382        emit info( requestData, returnedData );
383        // update cache
384        Tomahawk::InfoSystem::InfoStringHash criteria;
385        Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
386        criteria[ "chart_id" ] = origData[ "chart_id" ];
387        criteria[ "chart_source" ] = origData[ "chart_source" ];
388        /// @todo
389        /// set cache time based on wether requested type is 3day, lastweek or recent.
390        emit updateCache( criteria, 86400000, requestData.type, returnedData );
391    }
392    else
393        qDebug() << "Network error in fetching chart:" << reply->url().toString();
394
395}