1
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
3
* Copyright 2012, Hugo Lindstrƶm <hugolm84@gmail.com>
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.
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.
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/>.
19
#include "SoundcloudParser.h"
21
#include <QtNetwork/QNetworkAccessManager>
23
#include <qjson/parser.h>
26
#include "SourceList.h"
27
#include "DropJobNotifier.h"
28
#include "ViewManager.h"
29
#include "jobview/JobStatusView.h"
30
#include "jobview/JobStatusModel.h"
31
#include "jobview/ErrorStatusMessage.h"
32
#include "utils/NetworkReply.h"
33
#include "utils/TomahawkUtilsGui.h"
34
#include "utils/Logger.h"
36
using namespace Tomahawk;
39
SoundcloudParser::SoundcloudParser( const QStringList& Urls, bool createNewPlaylist, QObject* parent )
43
, m_createNewPlaylist( createNewPlaylist )
45
, m_type( DropJob::All )
49
foreach ( const QString& url, Urls )
54
SoundcloudParser::SoundcloudParser( const QString& Url, bool createNewPlaylist, QObject* parent )
58
, m_createNewPlaylist( createNewPlaylist )
60
, m_type( DropJob::All )
67
SoundcloudParser::~SoundcloudParser()
73
SoundcloudParser::lookupUrl( const QString& link )
75
tDebug() << "Looking up URL..." << link;
77
if ( link.contains( "/likes" ) )
79
qDebug() << Q_FUNC_INFO << "Requesting likes";
80
url.replace( "/likes", "" );
83
QUrl scLink( QString( "http://api.soundcloud.com/resolve.json?client_id=TiNg2DRYhBnp01DA3zNag&url=" ) + url );
85
NetworkReply* reply = new NetworkReply( TomahawkUtils::nam()->get( QNetworkRequest( scLink ) ) );
86
connect( reply, SIGNAL( finished() ), SLOT( soundcloudLookupFinished() ) );
88
m_browseJob = new DropJobNotifier( pixmap(), "Soundcloud", DropJob::All, reply );
89
JobStatusView::instance()->model()->addJob( m_browseJob );
91
m_queries.insert( reply );
96
SoundcloudParser::parseTrack( const QVariantMap& res )
98
QString title, artist;
99
title = res.value( "title", QString() ).toString();
100
artist = res.value( "user" ).toMap().value( "username", QString() ).toString();
101
bool streamable = res.value( "streamable" ).toBool();
103
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
105
tLog() << "Didn't get an artist and track name from Soundcloud, not enough to build a query on. Aborting" << title << artist;
111
JobStatusView::instance()->model()->addJob(
112
new ErrorStatusMessage( tr( "Track '%1' by %2 is not streamable." ).arg( title ).arg( artist ), 5 ) );
113
tLog() << "Track is not streamble, aborting." << res.value( "uri" ).toString();
117
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, QString(), uuid(), m_trackMode );
121
QUrl url = QUrl::fromUserInput( res.value( "stream_url" ).toString() );
122
url.addQueryItem( "client_id", "TiNg2DRYhBnp01DA3zNag" );
123
tLog() << "Setting resulthint to " << res.value( "stream_url" ) << url.toString();
124
q->setResultHint( url.toString() );
125
q->setSaveHTTPResultHint( true );
132
SoundcloudParser::soundcloudLookupFinished()
134
NetworkReply* r = qobject_cast< NetworkReply* >( sender() );
136
m_queries.remove( r );
139
if ( r->reply()->error() == QNetworkReply::NoError )
143
QVariantMap res = p.parse( r->reply(), &ok ).toMap();
146
tLog() << "Failed to parse json from Soundcloud browse item:" << p.errorString() << "On line" << p.errorLine();
150
if( res.value( "kind" ).toString() == "playlist" )
151
m_type = DropJob::Playlist;
152
if( res.value( "kind" ).toString() == "track" )
153
m_type = DropJob::Track;
154
if( res.value( "kind" ).toString() == "user" )
159
url = QUrl( QString( res.value( "uri" ).toString() + "/favorites.json?client_id=TiNg2DRYhBnp01DA3zNag" ) );
163
url = QUrl( QString( res.value( "uri" ).toString() + "/tracks.json?client_id=TiNg2DRYhBnp01DA3zNag" ) );
166
NetworkReply* reply = new NetworkReply( TomahawkUtils::nam()->get( QNetworkRequest( QUrl( url ) ) ) );
168
if ( m_createNewPlaylist )
171
connect( reply, SIGNAL( finished() ), SLOT( soundcloudArtistLookupFinished() ) );
175
if ( m_type == DropJob::Track )
179
else if ( m_type == DropJob::Playlist )
181
QString title, user, desc;
182
title = res.value( "title" ).toString();
183
desc = res.value( "description" ).toString();
184
user = res.value( "user" ).toMap().value( "username" ).toString();
186
QVariantList tracks = res.value( "tracks" ).toList();
188
foreach( const QVariant& track, tracks )
189
parseTrack( track.toMap() );
191
if ( m_createNewPlaylist )
193
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
201
connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) );
207
if ( m_single && !m_tracks.isEmpty() )
208
emit track( m_tracks.first() );
209
else if ( !m_single && !m_tracks.isEmpty() )
210
emit tracks( m_tracks );
217
SoundcloudParser::playlistCreated()
219
ViewManager::instance()->show( m_playlist );
226
SoundcloudParser::soundcloudArtistLookupFinished()
228
NetworkReply* r = qobject_cast< NetworkReply* >( sender() );
233
if ( r->reply()->error() == QNetworkReply::NoError )
237
QVariantList res = p.parse( r->reply(), &ok ).toList();
239
foreach( const QVariant& track, res )
240
parseTrack( track.toMap() );
242
if ( m_createNewPlaylist )
244
const QString user = m_userData.value( "full_name" ).toString();
245
const QString title = user + "'s " + ( m_getLikes ? "Favorites" : "Tracks" );
246
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
254
connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) );
258
if ( m_single && !m_tracks.isEmpty() )
259
emit track( m_tracks.first() );
260
else if ( !m_single && !m_tracks.isEmpty() )
261
emit tracks( m_tracks );
270
SoundcloudParser::pixmap() const
272
return TomahawkUtils::defaultPixmap( TomahawkUtils::SoundcloudIcon );