mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-20 07:49:42 +01:00
Parse Grooveshark playlists on drag & drop
not much error handling yet, but it works ;)
This commit is contained in:
parent
52cb7cebd9
commit
e989bc1652
@ -101,6 +101,7 @@ set( libGuiSources
|
||||
utils/m3uloader.cpp
|
||||
utils/itunesparser.cpp
|
||||
utils/rdioparser.cpp
|
||||
utils/groovesharkparser.cpp
|
||||
utils/shortenedlinkparser.cpp
|
||||
utils/stylehelper.cpp
|
||||
utils/dropjobnotifier.cpp
|
||||
@ -218,6 +219,7 @@ set( libGuiHeaders
|
||||
utils/m3uloader.h
|
||||
utils/itunesparser.h
|
||||
utils/rdioparser.h
|
||||
utils/groovesharkparser.h
|
||||
utils/shortenedlinkparser.h
|
||||
utils/dropjobnotifier.h
|
||||
utils/tomahawkutilsgui.h
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "utils/spotifyparser.h"
|
||||
#include "utils/itunesparser.h"
|
||||
#include "utils/rdioparser.h"
|
||||
#include "utils/groovesharkparser.h"
|
||||
#include "utils/m3uloader.h"
|
||||
#include "utils/shortenedlinkparser.h"
|
||||
#include "utils/logger.h"
|
||||
@ -120,6 +121,9 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
// Not the most elegant
|
||||
if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
|
||||
return true;
|
||||
|
||||
if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( acceptedType.testFlag( Track ) )
|
||||
@ -188,6 +192,9 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
|
||||
|
||||
if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) )
|
||||
return true;
|
||||
|
||||
if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) )
|
||||
return true;
|
||||
|
||||
if ( ShortenedLinkParser::handlesUrl( url ) )
|
||||
return true;
|
||||
@ -555,6 +562,27 @@ DropJob::handleRdioUrls( const QString& urlsRaw )
|
||||
rdio->parse( urls );
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::handleGroovesharkUrls ( const QString& urlsRaw )
|
||||
{
|
||||
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||
tDebug() << "Got Grooveshark urls!" << urls;
|
||||
|
||||
if ( dropAction() == Default )
|
||||
setDropAction( Create );
|
||||
|
||||
GroovesharkParser* groove = new GroovesharkParser( urls, dropAction() == Create, this );
|
||||
connect( groove, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
|
||||
if ( dropAction() == Append )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Asking for grooveshark contents from" << urls;
|
||||
connect( groove, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
m_queryCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DropJob::handleAllUrls( const QString& urls )
|
||||
@ -569,6 +597,8 @@ DropJob::handleAllUrls( const QString& urls )
|
||||
handleSpotifyUrls( urls );
|
||||
else if ( urls.contains( "rdio.com" ) )
|
||||
handleRdioUrls( urls );
|
||||
else if ( urls.contains( "grooveshark.com" ) )
|
||||
handleGroovesharkUrls( urls );
|
||||
else
|
||||
handleTrackUrls ( urls );
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ public:
|
||||
void handleM3u( const QString& urls );
|
||||
void handleSpotifyUrls( const QString& urls );
|
||||
void handleRdioUrls( const QString& urls );
|
||||
void handleGroovesharkUrls( const QString& urls );
|
||||
|
||||
static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; }
|
||||
static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
|
||||
|
258
src/libtomahawk/utils/groovesharkparser.cpp
Normal file
258
src/libtomahawk/utils/groovesharkparser.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Stefan Derkits <stefan@derkits.at>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "groovesharkparser.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "query.h"
|
||||
#include "sourcelist.h"
|
||||
#include "dropjob.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "dropjobnotifier.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
QPixmap* GroovesharkParser::s_pixmap = 0;
|
||||
|
||||
const char* enApiSecret = "erCj5s0Vebyqtc9Aduyotc1CLListJ9HfO2os5hBeew=";
|
||||
|
||||
GroovesharkParser::GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist, QObject* parent )
|
||||
: QObject ( parent )
|
||||
, m_limit ( 40 )
|
||||
, m_trackMode( true )
|
||||
, m_createNewPlaylist( createNewPlaylist )
|
||||
, m_browseJob( 0 )
|
||||
{
|
||||
foreach ( const QString& url, trackUrls )
|
||||
lookupUrl( url );
|
||||
}
|
||||
|
||||
GroovesharkParser::~GroovesharkParser()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::lookupUrl( const QString& link )
|
||||
{
|
||||
if( link.contains( "playlist" ) )
|
||||
{
|
||||
if( !m_createNewPlaylist )
|
||||
m_trackMode = true;
|
||||
else
|
||||
m_trackMode = false;
|
||||
|
||||
lookupGroovesharkPlaylist( link );
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw )
|
||||
{
|
||||
tLog() << "Parsing Grooveshark Playlist URI:" << linkRaw;
|
||||
QString browseUri = linkRaw;
|
||||
|
||||
QStringList urlParts = linkRaw.split("/");
|
||||
bool ok;
|
||||
int playlistID = urlParts.last().toInt(&ok, 10);
|
||||
if (!ok)
|
||||
{
|
||||
tDebug() << "incorrect grooveshark url";
|
||||
return;
|
||||
}
|
||||
|
||||
m_title = urlParts.at(urlParts.size()-2);
|
||||
|
||||
tDebug() << "should get playlist " << playlistID;
|
||||
|
||||
DropJob::DropType type;
|
||||
|
||||
if ( browseUri.contains( "playlist" ) )
|
||||
type = DropJob::Playlist;
|
||||
|
||||
QString base_url("http://api.grooveshark.com/ws3.php?sig=");
|
||||
|
||||
QByteArray data = QString("{\"method\":\"getPlaylistSongs\",\"parameters\":{\"playlistID\":\"%1\"},\"header\":{\"wsKey\":\"tomahawkplayer\"}}").arg(playlistID).toLocal8Bit();
|
||||
|
||||
QByteArray magic = QByteArray::fromBase64( enApiSecret );
|
||||
|
||||
QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
|
||||
int length = magic.length(), n2 = wand.length();
|
||||
for ( int i=0; i<length; i++ ) magic[i] = magic[i] ^ wand[i%n2];
|
||||
|
||||
QCA::SymmetricKey key( magic );
|
||||
|
||||
tDebug() << "key size: " << key.size();
|
||||
|
||||
QCA::MessageAuthenticationCode hmac(QString("hmac(md5)"),key);
|
||||
tDebug() << "created hmac object";
|
||||
QCA::SecureArray secdata( data );
|
||||
tDebug() << "before creating hmac";
|
||||
hmac.update(secdata);
|
||||
QCA::SecureArray resultArray = hmac.final();
|
||||
|
||||
QString hash = QCA::arrayToHex(resultArray.toByteArray());
|
||||
QUrl url = QUrl(base_url + hash);
|
||||
|
||||
tDebug() << "Looking up URL..." << url.toString();
|
||||
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->post( QNetworkRequest( url ), data );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( groovesharkLookupFinished() ) );
|
||||
|
||||
//m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", type, reply );
|
||||
//JobStatusView::instance()->model()->addJob( m_browseJob );
|
||||
|
||||
m_queries.insert( reply );
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::groovesharkLookupFinished()
|
||||
{
|
||||
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
|
||||
Q_ASSERT( r );
|
||||
|
||||
m_queries.remove( r );
|
||||
r->deleteLater();
|
||||
|
||||
if ( r->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
bool ok;
|
||||
QVariantMap res = p.parse( r, &ok ).toMap();
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
tLog() << "Failed to parse json from Grooveshark browse item :" << p.errorString() << "On line" << p.errorLine();
|
||||
checkTrackFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
//tDebug() << "parsed grooveshark result into a map " << res;
|
||||
//tDebug() << "results " << res.value("result") << " which is of type " << res.value("result").type();
|
||||
QVariantList list = res.value("result").toMap().value("songs").toList();
|
||||
foreach (const QVariant& var, list)
|
||||
{
|
||||
QVariantMap trackResult = var.toMap();
|
||||
//tDebug() << map;
|
||||
|
||||
QString title, artist, album;
|
||||
|
||||
title = trackResult.value( "SongName", QString() ).toString();
|
||||
artist = trackResult.value( "ArtistName", QString() ).toString();
|
||||
album = trackResult.value( "AlbumName", QString() ).toString();
|
||||
|
||||
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
|
||||
{
|
||||
tLog() << "Didn't get an artist and track name from spotify, not enough to build a query on. Aborting" << title << artist << album;
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode );
|
||||
m_tracks << q;
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
tLog() << "Error in network request to grooveshark for track decoding:" << r->errorString();
|
||||
}
|
||||
|
||||
if ( m_trackMode )
|
||||
checkTrackFinished();
|
||||
else
|
||||
checkBrowseFinished();
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::checkBrowseFinished()
|
||||
{
|
||||
tDebug() << "Checking for grooveshark batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist;
|
||||
if ( m_queries.isEmpty() ) // we're done
|
||||
{
|
||||
if ( m_browseJob )
|
||||
m_browseJob->setFinished();
|
||||
|
||||
if( m_createNewPlaylist && !m_tracks.isEmpty() )
|
||||
{
|
||||
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
|
||||
uuid(),
|
||||
m_title,
|
||||
m_info,
|
||||
m_creator,
|
||||
false,
|
||||
m_tracks );
|
||||
connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
emit tracks( m_tracks );
|
||||
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::checkTrackFinished()
|
||||
{
|
||||
tDebug() << "Checking for grooveshark batch track job finished" << m_queries.isEmpty();
|
||||
if ( m_queries.isEmpty() ) // we're done
|
||||
{
|
||||
if ( m_browseJob )
|
||||
m_browseJob->setFinished();
|
||||
|
||||
emit tracks( m_tracks );
|
||||
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::playlistCreated()
|
||||
{
|
||||
|
||||
ViewManager::instance()->show( m_playlist );
|
||||
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
GroovesharkParser::pixmap() const
|
||||
{
|
||||
if ( !s_pixmap )
|
||||
s_pixmap = new QPixmap( RESPATH "images/spotify-logo.png" );
|
||||
|
||||
return *s_pixmap;
|
||||
}
|
81
src/libtomahawk/utils/groovesharkparser.h
Normal file
81
src/libtomahawk/utils/groovesharkparser.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Stefan Derkits <stefan@derkits.at>
|
||||
*
|
||||
* 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 GROOVESHARKPARSER_H
|
||||
#define GROOVESHARKPARSER_H
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "typedefs.h"
|
||||
#include "query.h"
|
||||
#include "jobview/JobStatusItem.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
/**
|
||||
* Small class to parse grooveshark links into query_ptrs
|
||||
*
|
||||
* Connect to the signals to get the results
|
||||
*/
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DropJobNotifier;
|
||||
|
||||
class DLLEXPORT GroovesharkParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 );
|
||||
virtual ~GroovesharkParser();
|
||||
signals:
|
||||
void track( const Tomahawk::query_ptr& track );
|
||||
void tracks( const QList< Tomahawk::query_ptr > tracks );
|
||||
void playlist( const Tomahawk::query_ptr& playlist );
|
||||
|
||||
private slots:
|
||||
void groovesharkLookupFinished();
|
||||
|
||||
void playlistCreated();
|
||||
private:
|
||||
QPixmap pixmap() const;
|
||||
|
||||
void lookupUrl( const QString& url );
|
||||
void lookupGroovesharkPlaylist( const QString& playlist );
|
||||
void checkTrackFinished();
|
||||
void checkBrowseFinished();
|
||||
int m_limit;
|
||||
bool m_trackMode;
|
||||
bool m_createNewPlaylist;
|
||||
QList< query_ptr > m_tracks;
|
||||
QSet< QNetworkReply* > m_queries;
|
||||
QString m_title, m_info, m_creator;
|
||||
Tomahawk::playlist_ptr m_playlist;
|
||||
DropJobNotifier* m_browseJob;
|
||||
|
||||
static QPixmap* s_pixmap;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GROOVESHARKPARSER_H
|
Loading…
x
Reference in New Issue
Block a user