diff --git a/data/images/grooveshark.png b/data/images/grooveshark.png new file mode 100644 index 000000000..d7cd43b33 Binary files /dev/null and b/data/images/grooveshark.png differ diff --git a/resources.qrc b/resources.qrc index 8b9160c9b..bd779ef74 100644 --- a/resources.qrc +++ b/resources.qrc @@ -133,6 +133,7 @@ data/images/headphones-bigger.png data/images/no-album-no-case.png data/images/rdio.png + data/images/grooveshark.png data/sql/dbmigrate-27_to_28.sql data/images/process-stop.png diff --git a/src/libtomahawk/utils/groovesharkparser.cpp b/src/libtomahawk/utils/groovesharkparser.cpp index ec088cc08..d8353dfb9 100644 --- a/src/libtomahawk/utils/groovesharkparser.cpp +++ b/src/libtomahawk/utils/groovesharkparser.cpp @@ -39,6 +39,10 @@ #include #include +#include +#include +#include + using namespace Tomahawk; QPixmap* GroovesharkParser::s_pixmap = 0; @@ -72,15 +76,17 @@ GroovesharkParser::~GroovesharkParser() void GroovesharkParser::lookupUrl( const QString& link ) { - if( link.contains( "playlist" ) ) + if ( link.contains( "playlist" ) ) { - if( !m_createNewPlaylist ) + if ( !m_createNewPlaylist ) m_trackMode = true; else m_trackMode = false; lookupGroovesharkPlaylist( link ); } + else if ( link.contains( "grooveshark.com/s/" ) || link.contains( "grooveshark.com/#/s/" ) ) + lookupGroovesharkTrack( link ); else return; @@ -97,7 +103,7 @@ GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw ) tDebug() << "no fragment, setting fragment to path"; urlFragment = QUrl(linkRaw).path(); } - + tDebug() << urlFragment; int paramStartingPostition = urlFragment.indexOf( "?" ); @@ -108,22 +114,22 @@ GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw ) bool ok; QStringList urlParts = urlFragment.split( "/", QString::SkipEmptyParts ); - + tDebug() << urlParts; - + int playlistID = urlParts.at( 2 ).toInt( &ok, 10 ); if (!ok) { tDebug() << "incorrect grooveshark url"; return; } - - - + + + m_title = urlParts.at( 1 ); - + tDebug() << "should get playlist " << playlistID; - + DropJob::DropType type; type = DropJob::Playlist; @@ -153,6 +159,53 @@ GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw ) m_queries.insert( reply ); } + +void +GroovesharkParser::lookupGroovesharkTrack( const QString& track ) +{ + tLog() << "Parsing Grooveshark Track Page:" << track; + + QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( track ) ) ); + connect( reply, SIGNAL( finished() ), this, SLOT( trackPageFetchFinished() ) ); + + m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", DropJob::Track, reply ); + JobStatusView::instance()->model()->addJob( m_browseJob ); + + m_queries << reply; +} + + +void +GroovesharkParser::trackPageFetchFinished() +{ + QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); + Q_ASSERT( r ); + + m_queries.remove( r ); + r->deleteLater(); + + QWebPage page; + page.settings()->setAttribute( QWebSettings::JavascriptEnabled, false ); + page.settings()->setAttribute( QWebSettings::PluginsEnabled, false ); + page.settings()->setAttribute( QWebSettings::JavaEnabled, false ); + page.settings()->setAttribute( QWebSettings::AutoLoadImages, false ); + page.mainFrame()->setHtml( QString::fromUtf8( r->readAll() ) ); + QWebElement title = page.mainFrame()->findFirstElement("span[itemprop='name']"); + QWebElement artist = page.mainFrame()->findFirstElement("noscript span[itemprop='byArtist']"); + QWebElement album = page.mainFrame()->findFirstElement("noscript span[itemprop='inAlbum']"); + + if ( !title.toPlainText().isEmpty() && !artist.toPlainText().isEmpty() ) + { + tDebug() << "Got track info from grooveshark, enough to create a query:" << title.toPlainText() << artist.toPlainText() << album.toPlainText(); + + Tomahawk::query_ptr q = Tomahawk::Query::get( artist.toPlainText(), title.toPlainText(), album.toPlainText(), uuid(), true ); + m_tracks << q; + } + + checkTrackFinished(); +} + + void GroovesharkParser::groovesharkLookupFinished() { @@ -179,7 +232,7 @@ GroovesharkParser::groovesharkLookupFinished() foreach (const QVariant& var, list) { QVariantMap trackResult = var.toMap(); - + QString title, artist, album; title = trackResult.value( "SongName", QString() ).toString(); @@ -195,7 +248,7 @@ GroovesharkParser::groovesharkLookupFinished() Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode ); m_tracks << q; } - + } else { @@ -231,7 +284,7 @@ GroovesharkParser::checkPlaylistFinished() return; } - + emit tracks( m_tracks ); deleteLater(); diff --git a/src/libtomahawk/utils/groovesharkparser.h b/src/libtomahawk/utils/groovesharkparser.h index a387ed928..af04dac3d 100644 --- a/src/libtomahawk/utils/groovesharkparser.h +++ b/src/libtomahawk/utils/groovesharkparser.h @@ -42,7 +42,7 @@ class QNetworkReply; namespace Tomahawk { - + class DropJobNotifier; class DLLEXPORT GroovesharkParser : public QObject @@ -58,6 +58,7 @@ signals: private slots: void groovesharkLookupFinished(); + void trackPageFetchFinished(); void playlistCreated(); private: @@ -65,6 +66,8 @@ private: void lookupUrl( const QString& url ); void lookupGroovesharkPlaylist( const QString& playlist ); + void lookupGroovesharkTrack( const QString& track ); + void checkTrackFinished(); void checkPlaylistFinished(); int m_limit; @@ -79,7 +82,7 @@ private: QCA::SymmetricKey m_apiKey; static QPixmap* s_pixmap; - + }; } diff --git a/src/libtomahawk/utils/shortenedlinkparser.cpp b/src/libtomahawk/utils/shortenedlinkparser.cpp index f11646607..e28b1a1d3 100644 --- a/src/libtomahawk/utils/shortenedlinkparser.cpp +++ b/src/libtomahawk/utils/shortenedlinkparser.cpp @@ -21,6 +21,7 @@ #include "utils/logger.h" #include "utils/tomahawkutils.h" +#include "dropjobnotifier.h" #include "query.h" #include "jobview/ErrorStatusMessage.h" #include "jobview/JobStatusModel.h" @@ -33,6 +34,7 @@ using namespace Tomahawk; +QPixmap* ShortenedLinkParser::s_pixmap = 0; ShortenedLinkParser::ShortenedLinkParser ( const QStringList& urls, QObject* parent ) : QObject( parent ) @@ -61,6 +63,8 @@ ShortenedLinkParser::handlesUrl( const QString& url ) url.contains( "itun.es" ) || url.contains( "tinyurl.com" ) || url.contains( "tinysong.com" ) || + url.contains( "grooveshark.com/s/~/" ) || // These redirect to the 'real' grooveshark track url + url.contains( "grooveshark.com/#/s/~/" ) || url.contains( "rd.io" ) ); } @@ -68,11 +72,18 @@ void ShortenedLinkParser::lookupUrl ( const QString& url ) { tDebug() << "Looking up..." << url; + QString cleaned = url; + if ( cleaned.contains( "/#/s/" ) ) + cleaned.replace( "/#", "" ); - QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( url ) ) ); + QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( cleaned ) ) ); connect( reply, SIGNAL( finished() ), this, SLOT( lookupFinished() ) ); m_queries.insert( reply ); + + m_expandJob = new DropJobNotifier( pixmap(), "shortened", DropJob::Track, reply ); + JobStatusView::instance()->model()->addJob( m_expandJob ); + } void @@ -95,7 +106,7 @@ ShortenedLinkParser::lookupFinished() else { tLog() << "Got a redirected url:" << r->url().toString(); - m_links << r->url().toString(); + m_links << r->url().toString(); m_queries.remove( r ); r->deleteLater(); checkFinished(); @@ -114,3 +125,13 @@ ShortenedLinkParser::checkFinished() deleteLater(); } } + + +QPixmap +ShortenedLinkParser::pixmap() +{ + if ( !s_pixmap ) + s_pixmap = new QPixmap( RESPATH "images/add.png" ); + + return *s_pixmap; +} diff --git a/src/libtomahawk/utils/shortenedlinkparser.h b/src/libtomahawk/utils/shortenedlinkparser.h index 4fd358749..8c503acd3 100644 --- a/src/libtomahawk/utils/shortenedlinkparser.h +++ b/src/libtomahawk/utils/shortenedlinkparser.h @@ -26,12 +26,15 @@ #include #include #include +#include class QNetworkReply; namespace Tomahawk { +class DropJobNotifier; + /** * Small class to parse whitelisted shortened links into the redirected urls * @@ -58,8 +61,13 @@ private: void lookupUrl( const QString& url ); void checkFinished(); + static QPixmap pixmap(); + QStringList m_links; QSet< QNetworkReply* > m_queries; + DropJobNotifier* m_expandJob; + + static QPixmap* s_pixmap; }; }