diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index bc005f9156..c243feb884 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -126,6 +126,8 @@ set( libGuiSources utils/LinkGenerator.cpp utils/LinkGeneratorPlugin.cpp utils/TomaHkLinkGeneratorPlugin.cpp + utils/LinkParser.cpp + utils/LinkParserPlugin.cpp viewpages/SearchViewPage.cpp viewpages/SourceViewPage.cpp @@ -350,8 +352,6 @@ list(APPEND libSources resolvers/ScriptCommand_AllArtists.cpp resolvers/ScriptCommand_AllAlbums.cpp resolvers/ScriptCommand_AllTracks.cpp - resolvers/ScriptCommand_LookupUrl.cpp - resolvers/ScriptCommandQueue.cpp resolvers/ScriptPluginFactory.cpp # ScriptPlugins @@ -359,6 +359,8 @@ list(APPEND libSources resolvers/plugins/ScriptCollectionFactory.cpp resolvers/ScriptInfoPlugin.cpp resolvers/plugins/ScriptInfoPluginFactory.cpp + resolvers/plugins/ScriptLinkParserPlugin.cpp + resolvers/plugins/ScriptLinkParserPluginFactory.cpp sip/SipPlugin.cpp @@ -366,6 +368,7 @@ list(APPEND libSources sip/PeerInfo.cpp sip/SipStatusMessage.cpp + utils/UrlType.cpp utils/Cloudstream.cpp utils/Json.cpp utils/TomahawkUtils.cpp diff --git a/src/libtomahawk/DropJob.cpp b/src/libtomahawk/DropJob.cpp index c301bb6107..9c125e40aa 100644 --- a/src/libtomahawk/DropJob.cpp +++ b/src/libtomahawk/DropJob.cpp @@ -4,6 +4,7 @@ * Copyright 2011, Leo Franchi * Copyright 2011-2012, Jeff Mitchell * Copyright 2011-2012, Christian Muehlhaeuser + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +36,7 @@ #include "utils/Logger.h" #include "utils/TomahawkUtils.h" #include "utils/XspfLoader.h" +#include "utils/LinkParser.h" #include "Artist.h" #include "Album.h" @@ -172,12 +174,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) ) return true; - // Check Scriptresolvers - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) - { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypePlaylist ) ) - return true; - } + return Tomahawk::Utils::LinkParser::instance()->canParseUrl( url, Tomahawk::Utils::UrlTypePlaylist ); } if ( acceptedType.testFlag( Track ) ) @@ -198,12 +195,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType || url.contains( "playlists" ) ) ) ) return true; - // Check Scriptresolvers - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) - { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeTrack ) ) - return true; - } + return Tomahawk::Utils::LinkParser::instance()->canParseUrl( url, Tomahawk::Utils::UrlTypeTrack ); } if ( acceptedType.testFlag( Album ) ) @@ -215,12 +207,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType if ( url.contains( "rdio.com" ) && ( url.contains( "artist" ) && url.contains( "album" ) && !url.contains( "track" ) ) ) return true; - // Check Scriptresolvers - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) - { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeAlbum ) ) - return true; - } + return Tomahawk::Utils::LinkParser::instance()->canParseUrl( url, Tomahawk::Utils::UrlTypeAlbum ); } if ( acceptedType.testFlag( Artist ) ) @@ -232,12 +219,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType if ( url.contains( "rdio.com" ) && ( url.contains( "artist" ) && !url.contains( "album" ) && !url.contains( "track" ) ) ) return true; - // Check Scriptresolvers - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) - { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeArtist ) ) - return true; - } + return Tomahawk::Utils::LinkParser::instance()->canParseUrl( url, Tomahawk::Utils::UrlTypeArtist ); } // We whitelist certain url-shorteners since they do some link checking. Often playable (e.g. spotify) links hide behind them, @@ -303,15 +285,7 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data ) if ( ShortenedLinkParser::handlesUrl( url ) ) return true; - // Check Scriptresolvers - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) - { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypePlaylist ) ) - { - tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Accepting current drop as a playlist" << resolver->name(); - return true; - } - } + return Tomahawk::Utils::LinkParser::instance()->canParseUrl( url, Tomahawk::Utils::UrlTypePlaylist ); } @@ -761,16 +735,12 @@ DropJob::handleTrackUrls( const QString& urls ) foreach ( QString track, tracks ) { - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) + QList< QSharedPointer< Utils::LinkParserPlugin > > parserPlugins = Utils::LinkParser::instance()->parserPluginsForUrl( track, Utils::UrlTypeAny ); + if( !parserPlugins.isEmpty() ) { - if ( resolver->canParseUrl( track, ExternalResolver::UrlTypeAny ) ) - { - ScriptCommand_LookupUrl* cmd = new ScriptCommand_LookupUrl( resolver, track ); - connect( cmd, SIGNAL( information( QString, QSharedPointer ) ), this, SLOT( informationForUrl( QString, QSharedPointer ) ) ); - cmd->enqueue(); - m_queryCount++; - break; - } + Tomahawk::Utils::LinkParser::instance()->lookupUrl( track, parserPlugins ); + connect( Tomahawk::Utils::LinkParser::instance(), SIGNAL( informationFound( QString, QSharedPointer ) ), this, SLOT( informationForUrl( QString, QSharedPointer ) ) ); + m_queryCount++; } } } diff --git a/src/libtomahawk/GlobalActionManager.cpp b/src/libtomahawk/GlobalActionManager.cpp index d8131397ee..888a5c6c39 100644 --- a/src/libtomahawk/GlobalActionManager.cpp +++ b/src/libtomahawk/GlobalActionManager.cpp @@ -5,6 +5,7 @@ * Copyright (C) 2011-2014, Christian Muehlhaeuser * Copyright (C) 2013, Uwe L. Korn * Copyright (C) 2013, Teo Mrnjavac + * Copyright (C) 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,13 +36,13 @@ #include "playlist/TrackView.h" #include "playlist/PlayableModel.h" #include "resolvers/ExternalResolver.h" -#include "resolvers/ScriptCommand_LookupUrl.h" #include "utils/JspfLoader.h" #include "utils/Logger.h" #include "utils/SpotifyParser.h" #include "utils/XspfLoader.h" #include "utils/XspfGenerator.h" #include "viewpages/SearchViewPage.h" +#include "utils/LinkParser.h" #include "Pipeline.h" #include "TomahawkSettings.h" @@ -162,27 +163,12 @@ GlobalActionManager::openUrl( const QString& url ) else if ( url.contains( "open.spotify.com" ) || url.startsWith( "spotify:" ) ) return openSpotifyLink( url ); - // Can we parse the Url using a ScriptResolver? - bool canParse = false; - QList< QPointer< ExternalResolver > > possibleResolvers; - foreach ( QPointer resolver, Pipeline::instance()->scriptResolvers() ) + // Can we parse the Url using LinkParser? + QList< QSharedPointer< Utils::LinkParserPlugin > > parserPlugins = Utils::LinkParser::instance()->parserPluginsForUrl( url, Utils::UrlTypeAny ); + if( !parserPlugins.isEmpty() ) { - if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeAny ) ) - { - canParse = true; - possibleResolvers << resolver; - } - } - if ( canParse ) - { - m_queuedUrl = url; - foreach ( QPointer resolver, possibleResolvers ) - { - ScriptCommand_LookupUrl* cmd = new ScriptCommand_LookupUrl( resolver, url ); - connect( cmd, SIGNAL( information( QString, QSharedPointer ) ), this, SLOT( informationForUrl( QString, QSharedPointer ) ) ); - cmd->enqueue(); - } - + Tomahawk::Utils::LinkParser::instance()->lookupUrl( url, parserPlugins ); + connect( Tomahawk::Utils::LinkParser::instance(), SIGNAL( informationFound( QString, QSharedPointer ) ), this, SLOT( informationForUrl( QString, QSharedPointer ) ), Qt::UniqueConnection ); return true; } diff --git a/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp b/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp index 1306d4713b..f4bcc57d0f 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp +++ b/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp @@ -842,15 +842,28 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg const QString qid = msg.value( "qid" ).toString(); if ( m_qidToSlotMap.contains( qid ) ) { - QObject* receiver = m_qidToSlotMap[ qid ].first; + QPointer< QObject > receiver = m_qidToSlotMap[ qid ].first; QString slot = m_qidToSlotMap[ qid ].second; m_qidToSlotMap.remove( qid ); + QVariant extraData; if ( m_qidToExtraData.contains( qid ) ) extraData = m_qidToExtraData.take( qid ); - QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ), Q_ARG( QVariant, extraData ) ); + // FIXME: SpotifyParser is sometimes a dangling pointer, haven't found a real way to reproduce: happens sometimes when dropping a playlist url onto the sidebar + //Q_ASSERT( !receiver.isNull() ); + + if ( !receiver.isNull() ) + { + QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ), Q_ARG( QVariant, extraData ) ); + } + else + { + JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( + tr( "Spotify account could not finish action. Try again." ) + ) ); + } } else if ( msgType == "allPlaylists" ) { diff --git a/src/libtomahawk/accounts/spotify/SpotifyAccount.h b/src/libtomahawk/accounts/spotify/SpotifyAccount.h index 10da048b97..c488e688e8 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyAccount.h +++ b/src/libtomahawk/accounts/spotify/SpotifyAccount.h @@ -172,7 +172,7 @@ private slots: QPointer m_spotifyResolver; QPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin; - QMap > m_qidToSlotMap; + QMap, QString> > m_qidToSlotMap; QMap m_qidToExtraData; // List of synced spotify playlists in config UI diff --git a/src/libtomahawk/resolvers/ExternalResolver.h b/src/libtomahawk/resolvers/ExternalResolver.h index 71e786946c..01fd4f139e 100644 --- a/src/libtomahawk/resolvers/ExternalResolver.h +++ b/src/libtomahawk/resolvers/ExternalResolver.h @@ -3,6 +3,7 @@ * Copyright 2010-2011, Christian Muehlhaeuser * Copyright 2010-2011, Leo Franchi * Copyright 2013, Teo Mrnjavac + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +25,6 @@ #include "Source.h" #include "DllMacro.h" #include "Resolver.h" -#include "ScriptCommandQueue.h" -#include "ScriptCommand_LookupUrl.h" #include "Typedefs.h" #include @@ -45,7 +44,6 @@ class DLLEXPORT ExternalResolver : public Resolver { Q_OBJECT - friend class ScriptCommandQueue; friend class ScriptCommand_LookupUrl; public: @@ -61,26 +59,13 @@ Q_OBJECT Browsable = 0x1, // can be represented in one or more collection tree views PlaylistSync = 0x2, // can sync playlists AccountFactory = 0x4, // can configure multiple accounts at the same time - UrlLookup = 0x8 // can be queried for information on an Url }; Q_DECLARE_FLAGS( Capabilities, Capability ) Q_FLAGS( Capabilities ) - enum UrlType - { - UrlTypeAny = 0x00, - UrlTypePlaylist = 0x01, - UrlTypeTrack = 0x02, - UrlTypeAlbum = 0x04, - UrlTypeArtist = 0x08, - UrlTypeXspf = 0x10 - }; - Q_DECLARE_FLAGS( UrlTypes, UrlType ) - Q_FLAGS( UrlTypes ) - ExternalResolver( const QString& filePath ) - : m_commandQueue( new ScriptCommandQueue( this ) ) - { m_filePath = filePath; } + : m_filePath( filePath ) + {} QString filePath() const { return m_filePath; } virtual void setIcon( const QPixmap& ) {} @@ -92,12 +77,6 @@ Q_OBJECT virtual bool running() const = 0; virtual Capabilities capabilities() const = 0; - // UrlLookup, sync call - virtual bool canParseUrl( const QString& url, UrlType type ) = 0; - - virtual void enqueue( const QSharedPointer< ScriptCommand >& req ) - { m_commandQueue->enqueue( req ); } - public slots: virtual void start() = 0; virtual void stop() = 0; @@ -112,11 +91,6 @@ public slots: protected: void setFilePath( const QString& path ) { m_filePath = path; } - ScriptCommandQueue* m_commandQueue; - - // Should only be called by ScriptCommands - // UrlLookup - virtual void lookupUrl( const QString& url ) = 0; private: QString m_filePath; diff --git a/src/libtomahawk/resolvers/JSResolver.cpp b/src/libtomahawk/resolvers/JSResolver.cpp index 0faa71c8fd..47e6117bea 100644 --- a/src/libtomahawk/resolvers/JSResolver.cpp +++ b/src/libtomahawk/resolvers/JSResolver.cpp @@ -4,6 +4,7 @@ * Copyright 2010-2011, Leo Franchi * Copyright 2013, Teo Mrnjavac * Copyright 2013, Uwe L. Korn + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,10 +46,6 @@ #include "ScriptInfoPlugin.h" #include "JSAccount.h" #include "ScriptJob.h" - -// lookupUrl stuff -#include "playlist/PlaylistTemplate.h" -#include "playlist/XspfPlaylistTemplate.h" #include "database/Database.h" #include "database/DatabaseImpl.h" @@ -322,191 +319,6 @@ JSResolver::start() } -bool -JSResolver::canParseUrl( const QString& url, UrlType type ) -{ - Q_D( const JSResolver ); - - if ( d->capabilities.testFlag( UrlLookup ) ) - { - QVariantMap arguments; - arguments["url"] = url; - arguments["type"] = (int) type; - - return scriptObject()->syncInvoke( "canParseUrl", arguments ).toBool(); - } - else - { - // We cannot do URL lookup. - return false; - } -} - - -void -JSResolver::lookupUrl( const QString& url ) -{ - Q_D( const JSResolver ); - - - if ( !d->capabilities.testFlag( UrlLookup ) ) - { - emit informationFound( url, QSharedPointer() ); - return; - } - - QVariantMap arguments; - arguments["url"] = url; - Tomahawk::ScriptJob* job = scriptObject()->invoke( "lookupUrl", arguments ); - connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onLookupUrlRequestDone( QVariantMap ) ) ); - job->setProperty( "url", url ); - job->start(); -} - - -void -JSResolver::onLookupUrlRequestDone( const QVariantMap& result ) -{ - sender()->deleteLater(); - - QString url = sender()->property( "url" ).toString(); - - tLog() << "ON LOOKUP URL REQUEST DONE" << url << result; - - // It may seem a bit weird, but currently no slot should do anything - // more as we starting on a new URL and not task are waiting for it yet. - m_pendingUrl = QString(); - m_pendingAlbum = album_ptr(); - - UrlTypes type = (UrlTypes) result.value( "type" ).toInt(); - if ( type == UrlTypeArtist ) - { - QString name = result.value( "name" ).toString(); - Q_ASSERT( !name.isEmpty() ); - emit informationFound( url, Artist::get( name, true ).objectCast() ); - } - else if ( type == UrlTypeAlbum ) - { - QString name = result.value( "name" ).toString(); - QString artist = result.value( "artist" ).toString(); - album_ptr album = Album::get( Artist::get( artist, true ), name ); - m_pendingUrl = url; - m_pendingAlbum = album; - connect( album.data(), SIGNAL( tracksAdded( QList, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ), - SLOT( tracksAdded( QList, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) ); - if ( !album->tracks().isEmpty() ) - { - emit informationFound( url, album.objectCast() ); - } - } - else if ( type == UrlTypeTrack ) - { - Tomahawk::query_ptr query = parseTrack( result ); - if ( query.isNull() ) - { - // A valid track result shoud have non-empty title and artist. - tLog() << Q_FUNC_INFO << name() << "Got empty track information for " << url; - emit informationFound( url, QSharedPointer() ); - } - else - { - emit informationFound( url, query.objectCast() ); - } - } - else if ( type == UrlTypePlaylist ) - { - QString guid = result.value( "guid" ).toString(); - Q_ASSERT( !guid.isEmpty() ); - // Append nodeid to guid to make it globally unique. - guid += instanceUUID(); - - // Do we already have this playlist loaded? - { - playlist_ptr playlist = Playlist::get( guid ); - if ( !playlist.isNull() ) - { - emit informationFound( url, playlist.objectCast() ); - return; - } - } - - // Get all information to build a new playlist but do not build it until we know, - // if it is really handled as a playlist and not as a set of tracks. - Tomahawk::source_ptr source = SourceList::instance()->getLocal(); - const QString title = result.value( "title" ).toString(); - const QString info = result.value( "info" ).toString(); - const QString creator = result.value( "creator" ).toString(); - QList queries; - foreach( QVariant track, result.value( "tracks" ).toList() ) - { - query_ptr query = parseTrack( track.toMap() ); - if ( !query.isNull() ) - { - queries << query; - } - } - tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "Got playlist for " << url; - playlisttemplate_ptr pltemplate( new PlaylistTemplate( source, guid, title, info, creator, false, queries ) ); - emit informationFound( url, pltemplate.objectCast() ); - } - else if ( type == UrlTypeXspf ) - { - QString xspfUrl = result.value( "url" ).toString(); - Q_ASSERT( !xspfUrl.isEmpty() ); - QString guid = QString( "xspf-%1-%2" ).arg( xspfUrl.toUtf8().toBase64().constData() ).arg( instanceUUID() ); - - // Do we already have this playlist loaded? - { - playlist_ptr playlist = Playlist::get( guid ); - if ( !playlist.isNull() ) - { - emit informationFound( url, playlist.objectCast() ); - return; - } - } - - - // Get all information to build a new playlist but do not build it until we know, - // if it is really handled as a playlist and not as a set of tracks. - Tomahawk::source_ptr source = SourceList::instance()->getLocal(); - QSharedPointer pltemplate( new XspfPlaylistTemplate( xspfUrl, source, guid ) ); - NewClosure( pltemplate, SIGNAL( tracksLoaded( QList< Tomahawk::query_ptr > ) ), - this, SLOT( pltemplateTracksLoadedForUrl( QString, Tomahawk::playlisttemplate_ptr ) ), - url, pltemplate.objectCast() ); - tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "Got playlist for " << url; - pltemplate->load(); - } - else - { - tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "No usable information found for " << url; - emit informationFound( url, QSharedPointer() ); - } -} - - -query_ptr -JSResolver::parseTrack( const QVariantMap& track ) -{ - QString title = track.value( "track" ).toString(); - QString artist = track.value( "artist" ).toString(); - QString album = track.value( "album" ).toString(); - if ( title.isEmpty() || artist.isEmpty() ) - { - return query_ptr(); - } - - Tomahawk::query_ptr query = Tomahawk::Query::get( artist, title, album ); - QString resultHint = track.value( "hint" ).toString(); - if ( !resultHint.isEmpty() ) - { - query->setResultHint( resultHint ); - query->setSaveHTTPResultHint( true ); - } - - return query; -} - - void JSResolver::tracksAdded( const QList&, const ModelMode, const collection_ptr&) { @@ -520,14 +332,6 @@ JSResolver::tracksAdded( const QList&, const ModelMode, const collect } -void -JSResolver::pltemplateTracksLoadedForUrl( const QString& url, const playlisttemplate_ptr& pltemplate ) -{ - tLog() << Q_FUNC_INFO; - emit informationFound( url, pltemplate.objectCast() ); -} - - Tomahawk::ExternalResolver::ErrorState JSResolver::error() const { @@ -688,13 +492,6 @@ JSResolver::resolverUserConfig() } -QString -JSResolver::instanceUUID() -{ - return Tomahawk::Database::instance()->impl()->dbid(); -} - - ScriptJob* JSResolver::getStreamUrl( const result_ptr& result ) { diff --git a/src/libtomahawk/resolvers/JSResolver.h b/src/libtomahawk/resolvers/JSResolver.h index df6ea97e16..1db2a26d75 100644 --- a/src/libtomahawk/resolvers/JSResolver.h +++ b/src/libtomahawk/resolvers/JSResolver.h @@ -4,6 +4,7 @@ * Copyright 2010-2011, Leo Franchi * Copyright 2013, Teo Mrnjavac * Copyright 2013, Uwe L. Korn + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,8 +70,6 @@ friend class JSAccount; void setIcon( const QPixmap& icon ) override; - bool canParseUrl( const QString& url, UrlType type ) override; - QVariantMap loadDataFromWidgets(); ScriptAccount* scriptAccount() const; @@ -82,9 +81,6 @@ public slots: void stop() override; void start() override; - // For UrlLookup - void lookupUrl( const QString& url ) override; - signals: void stopped(); @@ -93,7 +89,6 @@ public slots: private slots: void onResolveRequestDone(const QVariantMap& data); - void onLookupUrlRequestDone(const QVariantMap& data); private: void init(); @@ -107,15 +102,11 @@ private slots: Q_DECLARE_PRIVATE( JSResolver ) QScopedPointer d_ptr; - -// TODO: move lookupUrl stuff to its own plugin type - QString instanceUUID(); - static Tomahawk::query_ptr parseTrack( const QVariantMap& track ); + // TODO: collection stuff, get rid of collection scriptcommands QString m_pendingUrl; Tomahawk::album_ptr m_pendingAlbum; private slots: void tracksAdded( const QList& tracks, const Tomahawk::ModelMode, const Tomahawk::collection_ptr& collection ); - void pltemplateTracksLoadedForUrl( const QString& url, const Tomahawk::playlisttemplate_ptr& pltemplate ); }; } // ns: Tomahawk diff --git a/src/libtomahawk/resolvers/ScriptAccount.cpp b/src/libtomahawk/resolvers/ScriptAccount.cpp index dd577c12ff..64fc5f70f7 100644 --- a/src/libtomahawk/resolvers/ScriptAccount.cpp +++ b/src/libtomahawk/resolvers/ScriptAccount.cpp @@ -1,7 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright (C) 2011 Leo Franchi - * Copyright (C) 2014 Dominik Schmidt + * Copyright (C) 2014-2016, Dominik Schmidt * Copyright (C) 2015, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "../utils/Logger.h" #include "../Typedefs.h" +#include "plugins/ScriptLinkParserPluginFactory.h" #include "plugins/ScriptCollectionFactory.h" #include "plugins/ScriptInfoPluginFactory.h" @@ -44,6 +45,7 @@ ScriptAccount::ScriptAccount( const QString& name ) : QObject() , m_name( name ) , m_stopped( true ) + , m_linkParserPluginFactory( new ScriptLinkParserPluginFactory() ) , m_collectionFactory( new ScriptCollectionFactory() ) , m_infoPluginFactory( new ScriptInfoPluginFactory() ) { @@ -52,6 +54,7 @@ ScriptAccount::ScriptAccount( const QString& name ) ScriptAccount::~ScriptAccount() { + delete m_linkParserPluginFactory; delete m_collectionFactory; delete m_infoPluginFactory; } @@ -62,6 +65,7 @@ ScriptAccount::start() { m_stopped = false; + m_linkParserPluginFactory->addAllPlugins(); m_collectionFactory->addAllPlugins(); m_infoPluginFactory->addAllPlugins(); } @@ -72,6 +76,7 @@ ScriptAccount::stop() { m_stopped = true; + m_linkParserPluginFactory->removeAllPlugins(); m_collectionFactory->removeAllPlugins(); m_infoPluginFactory->removeAllPlugins(); } @@ -193,7 +198,11 @@ ScriptAccount::unregisterScriptPlugin( const QString& type, const QString& objec return; } - if ( type == "collection" ) + if( type == "linkParser" ) + { + m_linkParserPluginFactory->unregisterPlugin( object ); + } + else if ( type == "collection" ) { m_collectionFactory->unregisterPlugin( object ); } @@ -231,6 +240,10 @@ ScriptAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr& ScriptLinkGeneratorPlugin* lgp = new ScriptLinkGeneratorPlugin( object ); Utils::LinkGenerator::instance()->addPlugin( lgp ); } + else if( type == "linkParser" ) + { + m_linkParserPluginFactory->registerPlugin( object, this ); + } else if ( type == "infoPlugin" ) { m_infoPluginFactory->registerPlugin( object, this ); diff --git a/src/libtomahawk/resolvers/ScriptAccount.h b/src/libtomahawk/resolvers/ScriptAccount.h index ef126a1e85..716e71f91a 100644 --- a/src/libtomahawk/resolvers/ScriptAccount.h +++ b/src/libtomahawk/resolvers/ScriptAccount.h @@ -1,7 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright (C) 2011 Leo Franchi - * Copyright (C) 2014 Dominik Schmidt + * Copyright (C) 2014-2016, Dominik Schmidt * Copyright (C) 2015, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -39,6 +39,7 @@ namespace Tomahawk { class ScriptObject; class ScriptJob; +class ScriptLinkParserPluginFactory; class ScriptCollectionFactory; class ScriptInfoPluginFactory; @@ -94,6 +95,7 @@ private slots: QHash< QString, scriptobject_ptr > m_objects; // port to QScopedPointer when pimple'd + ScriptLinkParserPluginFactory* m_linkParserPluginFactory; ScriptCollectionFactory* m_collectionFactory; ScriptInfoPluginFactory* m_infoPluginFactory; }; diff --git a/src/libtomahawk/resolvers/ScriptCommand.h b/src/libtomahawk/resolvers/ScriptCommand.h index 0c3df3a51e..49e89a2fc8 100644 --- a/src/libtomahawk/resolvers/ScriptCommand.h +++ b/src/libtomahawk/resolvers/ScriptCommand.h @@ -34,7 +34,6 @@ class ScriptCommand : public QObject virtual void done() = 0; protected: - friend class ScriptCommandQueue; virtual void exec() = 0; virtual void reportFailure() = 0; }; diff --git a/src/libtomahawk/resolvers/ScriptCommandQueue.cpp b/src/libtomahawk/resolvers/ScriptCommandQueue.cpp deleted file mode 100644 index fb02a30c52..0000000000 --- a/src/libtomahawk/resolvers/ScriptCommandQueue.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2013, Teo Mrnjavac - * - * 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 . - */ - -#include "ScriptCommandQueue.h" - -#include -#include - -using namespace Tomahawk; - -ScriptCommandQueue::ScriptCommandQueue( QObject* parent ) - : QObject( parent ) - , m_timer( new QTimer( this ) ) -{ - m_timer->setSingleShot( true ); -} - - -void -ScriptCommandQueue::enqueue( const QSharedPointer< ScriptCommand >& req ) -{ - QMutexLocker locker( &m_mutex ); - m_queue.append( req ); - locker.unlock(); - - if ( m_queue.count() == 1 ) - nextCommand(); -} - - -void -ScriptCommandQueue::nextCommand() -{ - if ( m_queue.isEmpty() ) - return; - - QSharedPointer< ScriptCommand > req = m_queue.first(); - - connect( req.data(), SIGNAL( done() ), - this, SLOT( onCommandDone() ) ); - connect( m_timer, SIGNAL( timeout() ), - this, SLOT( onTimeout() ) ); - - m_timer->start( 20000 ); - - req->exec(); -} - - -void -ScriptCommandQueue::onCommandDone() -{ - if ( m_queue.isEmpty() || !m_timer->isActive() ) //the timeout already happened or some other weird thing - return; //nothing to do here - - m_timer->stop(); - - QMutexLocker locker( &m_mutex ); - const QSharedPointer< ScriptCommand > req = m_queue.first(); - m_queue.removeAll( req ); - locker.unlock(); - - disconnect( req.data(), SIGNAL( done() ), - this, SLOT( onCommandDone() ) ); - disconnect( m_timer, SIGNAL( timeout() ), - this, SLOT( onTimeout() ) ); - - if ( !m_queue.isEmpty() ) - nextCommand(); -} - - -void -ScriptCommandQueue::onTimeout() -{ - m_timer->stop(); - - QMutexLocker locker( &m_mutex ); - const QSharedPointer< ScriptCommand > req = m_queue.first(); - m_queue.removeAll( req ); - locker.unlock(); - - req->reportFailure(); - - disconnect( req.data(), SIGNAL( done() ), - this, SLOT( onCommandDone() ) ); - disconnect( m_timer, SIGNAL( timeout() ), - this, SLOT( onTimeout() ) ); - - if ( !m_queue.isEmpty() ) - nextCommand(); -} diff --git a/src/libtomahawk/resolvers/ScriptCommandQueue.h b/src/libtomahawk/resolvers/ScriptCommandQueue.h deleted file mode 100644 index 8795ff7aa2..0000000000 --- a/src/libtomahawk/resolvers/ScriptCommandQueue.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2013, Teo Mrnjavac - * - * 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 . - */ - -#ifndef SCRIPTCOMMANDQUEUE_H -#define SCRIPTCOMMANDQUEUE_H - -#include "ScriptCommand.h" - -#include -#include -#include -#include -#include - -namespace Tomahawk -{ - -class ScriptCommandQueue : public QObject -{ - Q_OBJECT -public: - explicit ScriptCommandQueue( QObject* parent = 0 ); - virtual ~ScriptCommandQueue() {} - - void enqueue( const QSharedPointer< ScriptCommand >& req ); - -private slots: - void nextCommand(); - void onCommandDone(); - void onTimeout(); - -private: - QQueue< QSharedPointer< ScriptCommand > > m_queue; - QTimer* m_timer; - QMutex m_mutex; -}; - -} // ns: Tomahawk - -Q_DECLARE_METATYPE( QSharedPointer< Tomahawk::ScriptCommand > ) - -#endif // SCRIPTCOMMANDQUEUE_H diff --git a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.cpp b/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.cpp deleted file mode 100644 index 5e91cbe73b..0000000000 --- a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2013, Uwe L. Korn - * - * 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 . - */ - -#include "ScriptCommand_LookupUrl_p.h" - -#include "PlaylistEntry.h" - -using namespace Tomahawk; - -ScriptCommand_LookupUrl::ScriptCommand_LookupUrl( Tomahawk::ExternalResolver* resolver, const QString& url, QObject* parent ) - : ScriptCommand( parent ) - , d_ptr( new ScriptCommand_LookupUrlPrivate( this, resolver, url ) ) -{ -} - -ScriptCommand_LookupUrl::~ScriptCommand_LookupUrl() -{ - delete d_ptr; -} - - -void -ScriptCommand_LookupUrl::enqueue() -{ - Q_D( ScriptCommand_LookupUrl ); - d->resolver->enqueue( QSharedPointer< ScriptCommand >( this ) ); -} - - -void -ScriptCommand_LookupUrl::exec() -{ - Q_D( ScriptCommand_LookupUrl ); - connect( d->resolver, SIGNAL( informationFound( QString , QSharedPointer ) ), - this, SLOT( onResolverDone( QString, QSharedPointer ) ) ); - - d->resolver->lookupUrl( d->url ); -} - - -void -ScriptCommand_LookupUrl::reportFailure() -{ - Q_D( ScriptCommand_LookupUrl ); - emit information( d->url, QSharedPointer() ); - emit done(); -} - - -void -ScriptCommand_LookupUrl::onResolverDone( const QString& url, const QSharedPointer& _information ) -{ - Q_D( ScriptCommand_LookupUrl ); - - qDebug() << Q_FUNC_INFO << url << _information.isNull(); - if ( url != d->url ) - { - // This data is not for us, skip. - return; - } - emit information( d->url, _information ); - emit done(); -} diff --git a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.h b/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.h deleted file mode 100644 index 7f68e37a1e..0000000000 --- a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl.h +++ /dev/null @@ -1,64 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2013, Uwe L. Korn - * - * 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 . - */ - -#ifndef SCRIPTCOMMAND_LOOKUPURL_H -#define SCRIPTCOMMAND_LOOKUPURL_H - -#include "ScriptCommand.h" - -#include "DllMacro.h" -#include "Typedefs.h" - -#include - -namespace Tomahawk -{ - -class ScriptCommand_LookupUrlPrivate; -class ExternalResolver; - -class DLLEXPORT ScriptCommand_LookupUrl : public ScriptCommand -{ - Q_OBJECT -public: - explicit ScriptCommand_LookupUrl( Tomahawk::ExternalResolver* resolver, - const QString& url, - QObject* parent = nullptr ); - virtual ~ScriptCommand_LookupUrl(); - - void enqueue(); - -signals: - void information( const QString& url, const QSharedPointer& variant ); - void done(); - -protected: - void exec() override; - void reportFailure() override; - -private slots: - void onResolverDone( const QString& url, const QSharedPointer& information ); - -private: - Q_DECLARE_PRIVATE( ScriptCommand_LookupUrl ) - ScriptCommand_LookupUrlPrivate* d_ptr; -}; - -} // ns: Tomahawk - -#endif // SCRIPTCOMMAND_LOOKUPURL_H diff --git a/src/libtomahawk/resolvers/ScriptResolver.cpp b/src/libtomahawk/resolvers/ScriptResolver.cpp index c9ff97bfec..19b251868a 100644 --- a/src/libtomahawk/resolvers/ScriptResolver.cpp +++ b/src/libtomahawk/resolvers/ScriptResolver.cpp @@ -3,6 +3,7 @@ * Copyright 2010-2011, Christian Muehlhaeuser * Copyright 2010-2011, Leo Franchi * Copyright 2013, Teo Mrnjavac + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,6 +40,7 @@ #include #include #include +#include #ifdef Q_OS_WIN #include diff --git a/src/libtomahawk/resolvers/ScriptResolver.h b/src/libtomahawk/resolvers/ScriptResolver.h index 5fcd00f445..315008fd0c 100644 --- a/src/libtomahawk/resolvers/ScriptResolver.h +++ b/src/libtomahawk/resolvers/ScriptResolver.h @@ -3,6 +3,7 @@ * Copyright 2010-2011, Christian Muehlhaeuser * Copyright 2010-2011, Leo Franchi * Copyright 2013, Teo Mrnjavac + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,8 +64,6 @@ Q_OBJECT void sendMessage( const QVariantMap& map ); - bool canParseUrl( const QString&, UrlType ) Q_DECL_OVERRIDE { return false; } - signals: void terminated(); void customMessage( const QString& msgType, const QVariantMap& msg ); @@ -74,9 +73,6 @@ public slots: void resolve( const Tomahawk::query_ptr& query ) Q_DECL_OVERRIDE; void start() Q_DECL_OVERRIDE; - void lookupUrl( const QString& ) Q_DECL_OVERRIDE {} - - private slots: void readStderr(); void readStdout(); diff --git a/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.cpp b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.cpp new file mode 100644 index 0000000000..4effde38d8 --- /dev/null +++ b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.cpp @@ -0,0 +1,228 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2016, Dominik Schmidt + * + * 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 . + */ +#include "ScriptLinkParserPlugin_p.h" + +#include "../ScriptJob.h" +#include "../ScriptObject.h" +#include "../../utils/Logger.h" +#include "../ScriptAccount.h" + +#include "../../database/Database.h" +#include "../../database/DatabaseImpl.h" +#include "../../SourceList.h" +#include "../../Artist.h" +#include "../../Album.h" +#include "../../playlist/PlaylistTemplate.h" +#include "../../playlist/XspfPlaylistTemplate.h" + + +using namespace Tomahawk; + +ScriptLinkParserPlugin::ScriptLinkParserPlugin( const scriptobject_ptr& scriptObject, ScriptAccount* account ) + : Utils::LinkParserPlugin() + , ScriptPlugin( scriptObject ) + , d_ptr( new ScriptLinkParserPluginPrivate( this, scriptObject, account ) ) +{ +} + + +ScriptLinkParserPlugin::~ScriptLinkParserPlugin() +{ +} + + +bool +ScriptLinkParserPlugin::canParseUrl( const QString& url, Tomahawk::Utils::UrlType type ) const +{ + QVariantMap arguments; + arguments["url"] = url; + arguments["type"] = (int) type; + + return scriptObject()->syncInvoke( "canParseUrl", arguments ).toBool(); +} + + +void +ScriptLinkParserPlugin::lookupUrl( const QString& url ) const +{ + QVariantMap arguments; + arguments["url"] = url; + Tomahawk::ScriptJob* job = scriptObject()->invoke( "lookupUrl", arguments ); + connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onLookupUrlRequestDone( QVariantMap ) ) ); + job->setProperty( "url", url ); + job->start(); +} + + +void +ScriptLinkParserPlugin::onLookupUrlRequestDone( const QVariantMap& result ) +{ + Q_D( ScriptLinkParserPlugin ); + + sender()->deleteLater(); + + QString url = sender()->property( "url" ).toString(); + + tLog() << "ON LOOKUP URL REQUEST DONE" << url << result; + + // It may seem a bit weird, but currently no slot should do anything + // more as we starting on a new URL and not task are waiting for it yet. + d->pendingUrl = QString(); + d->pendingAlbum = album_ptr(); + + Utils::UrlType type = (Utils::UrlType) result.value( "type" ).toInt(); + if ( type == Utils::UrlTypeArtist ) + { + QString name = result.value( "name" ).toString(); + Q_ASSERT( !name.isEmpty() ); + emit informationFound( url, Artist::get( name, true ).objectCast() ); + } + else if ( type == Utils::UrlTypeAlbum ) + { + QString name = result.value( "name" ).toString(); + QString artist = result.value( "artist" ).toString(); + album_ptr album = Album::get( Artist::get( artist, true ), name ); + d->pendingUrl = url; + d->pendingAlbum = album; + connect( album.data(), SIGNAL( tracksAdded( QList, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ), + SLOT( tracksAdded( QList, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) ); + if ( !album->tracks().isEmpty() ) + { + emit informationFound( url, album.objectCast() ); + } + } + else if ( type == Utils::UrlTypeTrack ) + { + Tomahawk::query_ptr query = parseTrack( result ); + if ( query.isNull() ) + { + // A valid track result shoud have non-empty title and artist. + tLog() << Q_FUNC_INFO << d->scriptAccount->name() << "Got empty track information for " << url; + emit informationFound( url, QSharedPointer() ); + } + else + { + emit informationFound( url, query.objectCast() ); + } + } + else if ( type == Utils::UrlTypePlaylist ) + { + QString guid = result.value( "guid" ).toString(); + Q_ASSERT( !guid.isEmpty() ); + // Append nodeid to guid to make it globally unique. + guid += instanceUUID(); + + // Do we already have this playlist loaded? + { + playlist_ptr playlist = Playlist::get( guid ); + if ( !playlist.isNull() ) + { + emit informationFound( url, playlist.objectCast() ); + return; + } + } + + // Get all information to build a new playlist but do not build it until we know, + // if it is really handled as a playlist and not as a set of tracks. + Tomahawk::source_ptr source = SourceList::instance()->getLocal(); + const QString title = result.value( "title" ).toString(); + const QString info = result.value( "info" ).toString(); + const QString creator = result.value( "creator" ).toString(); + QList queries; + foreach( QVariant track, result.value( "tracks" ).toList() ) + { + query_ptr query = parseTrack( track.toMap() ); + if ( !query.isNull() ) + { + queries << query; + } + } + tLog( LOGVERBOSE ) << Q_FUNC_INFO << d->scriptAccount->name() << "Got playlist for " << url; + playlisttemplate_ptr pltemplate( new PlaylistTemplate( source, guid, title, info, creator, false, queries ) ); + emit informationFound( url, pltemplate.objectCast() ); + } + else if ( type == Utils::UrlTypeXspf ) + { + QString xspfUrl = result.value( "url" ).toString(); + Q_ASSERT( !xspfUrl.isEmpty() ); + QString guid = QString( "xspf-%1-%2" ).arg( xspfUrl.toUtf8().toBase64().constData() ).arg( instanceUUID() ); + + // Do we already have this playlist loaded? + { + playlist_ptr playlist = Playlist::get( guid ); + if ( !playlist.isNull() ) + { + emit informationFound( url, playlist.objectCast() ); + return; + } + } + + + // Get all information to build a new playlist but do not build it until we know, + // if it is really handled as a playlist and not as a set of tracks. + Tomahawk::source_ptr source = SourceList::instance()->getLocal(); + QSharedPointer pltemplate( new XspfPlaylistTemplate( xspfUrl, source, guid ) ); + NewClosure( pltemplate, SIGNAL( tracksLoaded( QList< Tomahawk::query_ptr > ) ), + this, SLOT( pltemplateTracksLoadedForUrl( QString, Tomahawk::playlisttemplate_ptr ) ), + url, pltemplate.objectCast() ); + tLog( LOGVERBOSE ) << Q_FUNC_INFO << d->scriptAccount->name() << "Got playlist for " << url; + pltemplate->load(); + } + else + { + tLog( LOGVERBOSE ) << Q_FUNC_INFO << d->scriptAccount->name() << "No usable information found for " << url; + emit informationFound( url, QSharedPointer() ); + } +} + +void +ScriptLinkParserPlugin::pltemplateTracksLoadedForUrl( const QString& url, const playlisttemplate_ptr& pltemplate ) +{ + tLog() << Q_FUNC_INFO; + emit informationFound( url, pltemplate.objectCast() ); +} + + +QString +ScriptLinkParserPlugin::instanceUUID() +{ + return Tomahawk::Database::instance()->impl()->dbid(); +} + + +Tomahawk::query_ptr +ScriptLinkParserPlugin::parseTrack( const QVariantMap& track ) +{ + QString title = track.value( "track" ).toString(); + QString artist = track.value( "artist" ).toString(); + QString album = track.value( "album" ).toString(); + if ( title.isEmpty() || artist.isEmpty() ) + { + return query_ptr(); + } + + Tomahawk::query_ptr query = Tomahawk::Query::get( artist, title, album ); + QString resultHint = track.value( "hint" ).toString(); + if ( !resultHint.isEmpty() ) + { + query->setResultHint( resultHint ); + query->setSaveHTTPResultHint( true ); + } + + return query; +} diff --git a/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.h b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.h new file mode 100644 index 0000000000..8d5dc67d33 --- /dev/null +++ b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin.h @@ -0,0 +1,61 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2016, Dominik Schmidt + * + * 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 . + */ + +#ifndef TOMAHAWK_SCRIPTLINKPARSERPLUGIN_H +#define TOMAHAWK_SCRIPTLINKPARSERPLUGIN_H + +#include "../../resolvers/ScriptPlugin.h" +#include "../../utils/LinkParserPlugin.h" + +#include + +#include "DllMacro.h" + +namespace Tomahawk +{ + +class ScriptObject; +class ScriptLinkParserPluginPrivate; + +class DLLEXPORT ScriptLinkParserPlugin : public Utils::LinkParserPlugin, public ScriptPlugin +{ +Q_OBJECT + +public: + ScriptLinkParserPlugin( const scriptobject_ptr& scriptObject, ScriptAccount* account ); + virtual ~ScriptLinkParserPlugin(); + + bool canParseUrl( const QString& url, Tomahawk::Utils::UrlType type ) const override; + void lookupUrl( const QString& url ) const override; + +private slots: + void onLookupUrlRequestDone( const QVariantMap& result ); + void pltemplateTracksLoadedForUrl( const QString& url, const playlisttemplate_ptr& pltemplate ); + +private: + QString instanceUUID(); + static Tomahawk::query_ptr parseTrack( const QVariantMap& track ); + +private: + Q_DECLARE_PRIVATE( ScriptLinkParserPlugin ) + QScopedPointer d_ptr; +}; + +}; // ns: Tomahawk + +#endif // TOMAHAWK_SCRIPTLINKPARSERPLUGIN_H diff --git a/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.cpp b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.cpp new file mode 100644 index 0000000000..fe06716e0c --- /dev/null +++ b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.cpp @@ -0,0 +1,39 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ +#include "ScriptLinkParserPluginFactory.h" + +#include "../ScriptAccount.h" +#include "../../utils/LinkParser.h" +#include "../../utils/LinkParserPlugin.h" + +using namespace Tomahawk; + +void ScriptLinkParserPluginFactory::addPlugin( const QSharedPointer & plugin ) const +{ + Tomahawk::Utils::LinkParser::instance()->addPlugin( plugin ); +} + +void ScriptLinkParserPluginFactory::removePlugin( const QSharedPointer< ScriptLinkParserPlugin >& plugin ) const +{ + Tomahawk::Utils::LinkParser::instance()->removePlugin( plugin ); +} + +QSharedPointer< ScriptLinkParserPlugin > ScriptLinkParserPluginFactory::createPlugin( const scriptobject_ptr& object, ScriptAccount* scriptAccount ) +{ + return QSharedPointer< ScriptLinkParserPlugin >( new ScriptLinkParserPlugin( object, scriptAccount ) ); +} diff --git a/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.h b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.h new file mode 100644 index 0000000000..0e3527a31d --- /dev/null +++ b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPluginFactory.h @@ -0,0 +1,41 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ + +#pragma once +#ifndef TOMAHAWK_SCRIPTLINKPARSERPLUGINFACTORY_H +#define TOMAHAWK_SCRIPTLINKPARSERPLUGINFACTORY_H + +#include "Typedefs.h" +#include "ScriptLinkParserPlugin.h" +#include "../ScriptPluginFactory.h" + + +namespace Tomahawk +{ +class ScriptAccount; + +class DLLEXPORT ScriptLinkParserPluginFactory : public ScriptPluginFactory< ScriptLinkParserPlugin > +{ + QSharedPointer< ScriptLinkParserPlugin > createPlugin( const scriptobject_ptr&, ScriptAccount* ) override; + void addPlugin( const QSharedPointer< ScriptLinkParserPlugin >& scriptPlugin ) const override; + void removePlugin( const QSharedPointer< ScriptLinkParserPlugin >& scriptPlugin ) const override; +}; + +} // ns: Tomahawk + +#endif // TOMAHAWK_SCRIPTLINKPARSERPLUGINFACTORY_H diff --git a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl_p.h b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin_p.h similarity index 55% rename from src/libtomahawk/resolvers/ScriptCommand_LookupUrl_p.h rename to src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin_p.h index a47f1f5d1a..b6708339a3 100644 --- a/src/libtomahawk/resolvers/ScriptCommand_LookupUrl_p.h +++ b/src/libtomahawk/resolvers/plugins/ScriptLinkParserPlugin_p.h @@ -1,6 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright 2013, Uwe L. Korn + * Copyright 2016, Dominik Schmidt * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,33 +17,33 @@ * along with Tomahawk. If not, see . */ -#ifndef SCRIPTCOMMAND_LOOKUPURL_P_H -#define SCRIPTCOMMAND_LOOKUPURL_P_H +#ifndef TOMAHAWK_SCRIPTLINKGENERATORPLUGIN_P_H +#define TOMAHAWK_SCRIPTLINKGENERATORPLUGIN_P_H -#include "ScriptCommand_LookupUrl.h" +#include "ScriptLinkParserPlugin.h" -#include "ExternalResolver.h" - -namespace Tomahawk +namespace Tomahawk { -class ScriptCommand_LookupUrlPrivate +class ScriptLinkParserPluginPrivate { public: - ScriptCommand_LookupUrlPrivate( ScriptCommand_LookupUrl* q, Tomahawk::ExternalResolver* _resolver, const QString& _url ) + ScriptLinkParserPluginPrivate( ScriptLinkParserPlugin* q, const scriptobject_ptr& scriptObject, ScriptAccount* scriptAccount ) : q_ptr ( q ) - , url( _url ) - , resolver( _resolver ) + , scriptObject( scriptObject ) + , scriptAccount( scriptAccount ) { } - ScriptCommand_LookupUrl* q_ptr; - Q_DECLARE_PUBLIC ( ScriptCommand_LookupUrl ) + ScriptLinkParserPlugin* q_ptr; + Q_DECLARE_PUBLIC ( ScriptLinkParserPlugin ) private: - QString url; - Tomahawk::ExternalResolver* resolver; + scriptobject_ptr scriptObject; + ScriptAccount* scriptAccount; + QString pendingUrl; + album_ptr pendingAlbum; }; } // ns: Tomahawk -#endif // SCRIPTCOMMAND_LOOKUPURL_P_H +#endif // TOMAHAWK_SCRIPTLINKGENERATORPLUGIN_P_H diff --git a/src/libtomahawk/utils/LinkParser.cpp b/src/libtomahawk/utils/LinkParser.cpp new file mode 100644 index 0000000000..439c7a2799 --- /dev/null +++ b/src/libtomahawk/utils/LinkParser.cpp @@ -0,0 +1,122 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016, Dominik Schmidt + * + * 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 2 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 . + */ + +#include "LinkParser.h" + +#include "TomahawkUtils.h" +#include "Logger.h" +#include "../resolvers/SyncScriptJob.h" + +using namespace Tomahawk; +using namespace Tomahawk::Utils; + +LinkParser* LinkParser::s_instance = 0; + + +LinkParser* +LinkParser::instance() +{ + if ( !s_instance ) + s_instance = new LinkParser; + + return s_instance; +} + + +LinkParser::LinkParser( QObject* parent ) + : QObject( parent ) +{ +} + + +LinkParser::~LinkParser() +{ +} + + +void LinkParser::addPlugin( const QSharedPointer< LinkParserPlugin >& plugin ) +{ + m_plugins.append( plugin ); + connect( plugin.data(), SIGNAL( informationFound( QString, QSharedPointer ) ), SLOT( onInformationFound( QString, QSharedPointer ) ) ); +} + + +void +LinkParser::removePlugin( const QSharedPointer< LinkParserPlugin >& plugin ) +{ + if ( !plugin.isNull() ) + { + disconnect( plugin.data(), 0, this, 0); + + } + + QMutableListIterator< QSharedPointer< LinkParserPlugin > > iter( m_plugins ); + while ( iter.hasNext() ) + { + QSharedPointer< LinkParserPlugin > ptr = iter.next(); + if ( ptr.data() == plugin.data() || ptr.isNull() ) + { + iter.remove(); + } + } +} + + +bool +LinkParser::canParseUrl( const QString& url, UrlType type ) const +{ + return !parserPluginsForUrl( url, type).isEmpty(); +} + + +QList< QSharedPointer< LinkParserPlugin > > +LinkParser::parserPluginsForUrl( const QString& url, Tomahawk::Utils::UrlType type ) const +{ + QList< QSharedPointer< LinkParserPlugin > > plugins; + + foreach ( const QSharedPointer< LinkParserPlugin >& plugin, m_plugins ) + { + if ( plugin->canParseUrl( url, type ) ) + { + plugins.append( plugin ); + } + } + + return plugins; +} + + +void +LinkParser::lookupUrl( const QString& url, const QList< QSharedPointer < LinkParserPlugin > >& parserPlugins ) const +{ + foreach ( const QSharedPointer< LinkParserPlugin >& plugin, parserPlugins ) + { + if ( !plugin.isNull() ) + { + plugin->lookupUrl( url ); + } + } +} + + +void +LinkParser::onInformationFound( const QString& url, const QSharedPointer& information ) +{ + tLog() << Q_FUNC_INFO << url; + emit informationFound( url, information ); +} diff --git a/src/libtomahawk/utils/LinkParser.h b/src/libtomahawk/utils/LinkParser.h new file mode 100644 index 0000000000..399bad9662 --- /dev/null +++ b/src/libtomahawk/utils/LinkParser.h @@ -0,0 +1,69 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2014 Dominik Schmidt + * + * 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 2 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 . + */ + +#pragma once +#ifndef TOMAHAWK_UTILS_LINKPARSER_H +#define TOMAHAWK_UTILS_LINKPARSER_H + +#include "../resolvers/ScriptJob.h" +#include "LinkParserPlugin.h" +#include "UrlType.h" + +#include "../DllMacro.h" +#include "../Typedefs.h" + +#include + +namespace Tomahawk { + +namespace Utils { + +class LinkParserPlugin; + +class DLLEXPORT LinkParser : public QObject +{ + Q_OBJECT +public: + static LinkParser* instance(); + virtual ~LinkParser(); + + void addPlugin( const QSharedPointer< LinkParserPlugin >& plugin ); + void removePlugin( const QSharedPointer< LinkParserPlugin >& plugin ); + + bool canParseUrl( const QString& url, UrlType type ) const; + QList< QSharedPointer < LinkParserPlugin > > parserPluginsForUrl( const QString& url, UrlType type ) const; + void lookupUrl( const QString& url, const QList< QSharedPointer < LinkParserPlugin > >& parserPlugins = QList< QSharedPointer < LinkParserPlugin > >() ) const; + +signals: + void informationFound( const QString& url, const QSharedPointer& information ); + +private slots: + void onInformationFound( const QString& url, const QSharedPointer& information ); + +private: + explicit LinkParser( QObject* parent = 0 ); + QList< QSharedPointer < LinkParserPlugin > > m_plugins; + + + static LinkParser* s_instance; +}; + +} // namespace Utils +} // namespace Tomahawk + +#endif // TOMAHAWK_UTILS_LINKPARSER_H diff --git a/src/libtomahawk/utils/LinkParserPlugin.cpp b/src/libtomahawk/utils/LinkParserPlugin.cpp new file mode 100644 index 0000000000..5fe87e2b41 --- /dev/null +++ b/src/libtomahawk/utils/LinkParserPlugin.cpp @@ -0,0 +1,24 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ +#include "LinkParserPlugin.h" + +#include "LinkParser.h" + +Tomahawk::Utils::LinkParserPlugin::~LinkParserPlugin() +{ +} diff --git a/src/libtomahawk/utils/LinkParserPlugin.h b/src/libtomahawk/utils/LinkParserPlugin.h new file mode 100644 index 0000000000..7d0eac4f6b --- /dev/null +++ b/src/libtomahawk/utils/LinkParserPlugin.h @@ -0,0 +1,50 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ + +#pragma once +#ifndef TOMAHAWK_UTILS_LINKPARSERPLUGIN_H +#define TOMAHAWK_UTILS_LINKPARSERPLUGIN_H + +#include "../DllMacro.h" +#include "../Typedefs.h" +#include "UrlType.h" + +namespace Tomahawk { + +class ScriptJob; + +namespace Utils { + +class DLLEXPORT LinkParserPlugin : public QObject +{ +Q_OBJECT + +public: + virtual ~LinkParserPlugin(); + + virtual bool canParseUrl( const QString& url, Tomahawk::Utils::UrlType type ) const = 0; + virtual void lookupUrl( const QString& url ) const = 0; + +signals: + void informationFound( const QString&, const QSharedPointer& ); +}; + +} // namespace Utils +} // namespace Tomahawk + +#endif // TOMAHAWK_UTILS_LINKPARSERPLUGIN_H diff --git a/src/libtomahawk/utils/UrlType.cpp b/src/libtomahawk/utils/UrlType.cpp new file mode 100644 index 0000000000..e2e3c32bbe --- /dev/null +++ b/src/libtomahawk/utils/UrlType.cpp @@ -0,0 +1,19 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ + +#include "UrlType.h" diff --git a/src/libtomahawk/utils/UrlType.h b/src/libtomahawk/utils/UrlType.h new file mode 100644 index 0000000000..d750b677ae --- /dev/null +++ b/src/libtomahawk/utils/UrlType.h @@ -0,0 +1,40 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright (C) 2016 Dominik Schmidt + * + * 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 2 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 . + */ + +#pragma once +#ifndef TOMAHAWK_UTILS_URLTYPE_H +#define TOMAHAWK_UTILS_URLTYPE_H + +namespace Tomahawk { + +namespace Utils { + +enum UrlType +{ + UrlTypeAny = 0x00, + UrlTypePlaylist = 0x01, + UrlTypeTrack = 0x02, + UrlTypeAlbum = 0x04, + UrlTypeArtist = 0x08, + UrlTypeXspf = 0x10 +}; + +} // namespace Utils +} // namespace Tomahawk + +#endif // TOMAHAWK_UTILS_URLTYPE_H