From 2b2ecf81329a243f0421bbcc1008312d8d482a99 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Sun, 7 Jul 2013 02:03:12 +0200 Subject: [PATCH] Add (lazy) loading for Playlists from JSResolvers --- src/libtomahawk/CMakeLists.txt | 1 + src/libtomahawk/Typedefs.h | 2 + src/libtomahawk/playlist/PlaylistTemplate.cpp | 55 +++++++++++++ src/libtomahawk/playlist/PlaylistTemplate.h | 57 +++++++++++++ src/libtomahawk/playlist/PlaylistTemplate_p.h | 70 ++++++++++++++++ .../resolvers/JSResolverHelper.cpp | 81 ++++++++++++++++--- src/libtomahawk/resolvers/JSResolverHelper.h | 2 + src/tomahawk/TomahawkApp.cpp | 11 ++- 8 files changed, 266 insertions(+), 13 deletions(-) create mode 100644 src/libtomahawk/playlist/PlaylistTemplate.cpp create mode 100644 src/libtomahawk/playlist/PlaylistTemplate.h create mode 100644 src/libtomahawk/playlist/PlaylistTemplate_p.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index cc3d896ab..82c6a5ea5 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -322,6 +322,7 @@ list(APPEND libSources network/ConnectionManager.cpp playlist/PlaylistUpdaterInterface.cpp + playlist/PlaylistTemplate.cpp playlist/dynamic/DynamicPlaylist.cpp playlist/dynamic/GeneratorFactory.cpp playlist/dynamic/GeneratorInterface.cpp diff --git a/src/libtomahawk/Typedefs.h b/src/libtomahawk/Typedefs.h index f3a1f9043..94c44818f 100644 --- a/src/libtomahawk/Typedefs.h +++ b/src/libtomahawk/Typedefs.h @@ -43,6 +43,7 @@ namespace Tomahawk class Playlist; class PlaylistEntry; class PlaylistInterface; + class PlaylistTemplate; class DynamicPlaylist; class Query; class Result; @@ -58,6 +59,7 @@ namespace Tomahawk typedef QSharedPointer playlist_ptr; typedef QSharedPointer plentry_ptr; typedef QSharedPointer playlistinterface_ptr; + typedef QSharedPointer playlisttemplate_ptr; typedef QSharedPointer dynplaylist_ptr; typedef QSharedPointer query_ptr; typedef QWeakPointer query_wptr; diff --git a/src/libtomahawk/playlist/PlaylistTemplate.cpp b/src/libtomahawk/playlist/PlaylistTemplate.cpp new file mode 100644 index 000000000..f698b8c6b --- /dev/null +++ b/src/libtomahawk/playlist/PlaylistTemplate.cpp @@ -0,0 +1,55 @@ +/* === 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 "PlaylistTemplate_p.h" + +#include "Source.h" + +Tomahawk::PlaylistTemplate::PlaylistTemplate(const Tomahawk::source_ptr& author, const QString &guid, const QString &title, const QString &info, const QString &creator, bool shared, const QList &queries) + : QObject( 0 ) + , d_ptr( new PlaylistTemplatePrivate( this, author, guid, title, info, creator, shared, queries ) ) +{ +} + + +Tomahawk::PlaylistTemplate::~PlaylistTemplate() +{ + tLog() << Q_FUNC_INFO; + delete d_ptr; +} + + +Tomahawk::playlist_ptr +Tomahawk::PlaylistTemplate::get() +{ + Q_D( PlaylistTemplate ); + + if ( d->playlist.isNull() ) + { + // First try to load the playlist if already exists + d->playlist = Playlist::get( d->guid ); + } + + if ( d->playlist.isNull() ) + { + // This playlist does not exist yet, so create it. + d->playlist = Playlist::create( d->author, d->guid, d->title, d->info, d->creator, d->shared, d->queries ); + } + + return d->playlist; +} diff --git a/src/libtomahawk/playlist/PlaylistTemplate.h b/src/libtomahawk/playlist/PlaylistTemplate.h new file mode 100644 index 000000000..20663f881 --- /dev/null +++ b/src/libtomahawk/playlist/PlaylistTemplate.h @@ -0,0 +1,57 @@ +/* === 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 PLAYLISTTEMPLATE_H +#define PLAYLISTTEMPLATE_H + +#include "DllMacro.h" +#include "Typedefs.h" + +namespace Tomahawk +{ + +class PlaylistTemplatePrivate; + +class DLLEXPORT PlaylistTemplate : public QObject +{ + Q_OBJECT +public: + explicit PlaylistTemplate( const source_ptr& author, + const QString& guid, + const QString& title, + const QString& info, + const QString& creator, + bool shared, + const QList& queries = QList()); + virtual ~PlaylistTemplate(); + + /** + * Create or get the playlist for this template. + */ + Tomahawk::playlist_ptr get(); + +protected: + PlaylistTemplatePrivate* d_ptr; + +private: + Q_DECLARE_PRIVATE( PlaylistTemplate ) +}; + +} + +#endif // PLAYLISTTEMPLATE_H diff --git a/src/libtomahawk/playlist/PlaylistTemplate_p.h b/src/libtomahawk/playlist/PlaylistTemplate_p.h new file mode 100644 index 000000000..66b0e5c82 --- /dev/null +++ b/src/libtomahawk/playlist/PlaylistTemplate_p.h @@ -0,0 +1,70 @@ +/* === 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 PLAYLISTTEMPLATE_P_H +#define PLAYLISTTEMPLATE_P_H + +#include "playlist/PlaylistTemplate.h" + +#include "Playlist.h" +#include "utils/Logger.h" + +namespace Tomahawk +{ + +class PlaylistTemplatePrivate +{ +public: + PlaylistTemplatePrivate( PlaylistTemplate* q, + const source_ptr& _author, + const QString& _guid, + const QString& _title, + const QString& _info, + const QString& _creator, + bool _shared, + const QList& _queries ) + : q_ptr( q ) + , author( _author ) + , guid( _guid ) + , title( _title ) + , info( _info ) + , creator( _creator ) + , shared( _shared ) + , queries( _queries ) + { + } + + Q_DECLARE_PUBLIC( PlaylistTemplate ) + PlaylistTemplate* q_ptr; + +private: + source_ptr author; + QString guid; + QString title; + QString info; + QString creator; + bool shared; + QList queries; + playlist_ptr playlist; +}; + +} + +Q_DECLARE_METATYPE( QSharedPointer< Tomahawk::PlaylistTemplate > ) + +#endif // PLAYLISTTEMPLATE_P_H diff --git a/src/libtomahawk/resolvers/JSResolverHelper.cpp b/src/libtomahawk/resolvers/JSResolverHelper.cpp index e9adfa998..c8907b581 100644 --- a/src/libtomahawk/resolvers/JSResolverHelper.cpp +++ b/src/libtomahawk/resolvers/JSResolverHelper.cpp @@ -21,13 +21,18 @@ #include "JSResolverHelper.h" +#include "database/Database.h" +#include "database/DatabaseImpl.h" +#include "playlist/PlaylistTemplate.h" #include "resolvers/ScriptEngine.h" #include "network/Servent.h" #include "utils/Logger.h" + #include "config.h" #include "JSResolver_p.h" #include "Pipeline.h" #include "Result.h" +#include "SourceList.h" #include #include @@ -35,6 +40,8 @@ #include #include +using namespace Tomahawk; + JSResolverHelper::JSResolverHelper( const QString& scriptPath, JSResolver* parent ) : QObject( parent ) , m_urlCallbackIsAsync( false ) @@ -215,31 +222,81 @@ JSResolverHelper::addAlbumTrackResults( const QVariantMap& results ) } +query_ptr +JSResolverHelper::parseTrack( const QVariantMap& track ) +{ + QString title = track.value( "title" ).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 JSResolverHelper::addUrlResult( const QString& url, const QVariantMap& result ) { QString type = result.value( "type" ).toString(); if ( type == "track" ) { - QString title = result.value( "title" ).toString(); - QString artist = result.value( "artist" ).toString(); - QString album = result.value( "album" ).toString(); - tLog( LOGVERBOSE ) << m_resolver->name() << "Got track for url" << url << title << artist << album; - if ( title.isEmpty() || artist.isEmpty() ) + Tomahawk::query_ptr query = parseTrack( result ); + if ( query.isNull() ) { // A valid track result shoud have non-empty title and artist. tLog() << Q_FUNC_INFO << m_resolver->name() << "Got empty track information for " << url; emit m_resolver->informationFound( url, QSharedPointer() ); } - - Tomahawk::query_ptr query = Tomahawk::Query::get( artist, title, album ); - QString resultHint = result.value( "hint" ).toString(); - if ( !resultHint.isEmpty() ) + else { - query->setResultHint( resultHint ); - query->setSaveHTTPResultHint( true ); + emit m_resolver->informationFound( url, query.objectCast() ); } - emit m_resolver->informationFound( url, query.objectCast() ); + } + else if ( type == "playlist" ) + { + QString guid = result.value( "guid" ).toString(); + Q_ASSERT( !guid.isEmpty() ); + // Append nodeid to guid to make it globally unique. + guid += Tomahawk::Database::instance()->impl()->dbid(); + + // Do we already have this playlist loaded? + { + playlist_ptr playlist = Playlist::get( guid ); + if ( !playlist.isNull() ) + { + emit m_resolver->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 << m_resolver->name() << "Got playlist for " << url; + playlisttemplate_ptr pltemplate( new PlaylistTemplate( source, guid, title, info, creator, false, queries ) ); + emit m_resolver->informationFound( url, pltemplate.objectCast() ); } else { diff --git a/src/libtomahawk/resolvers/JSResolverHelper.h b/src/libtomahawk/resolvers/JSResolverHelper.h index 1f476606d..188d43f76 100644 --- a/src/libtomahawk/resolvers/JSResolverHelper.h +++ b/src/libtomahawk/resolvers/JSResolverHelper.h @@ -75,7 +75,9 @@ public slots: void reportCapabilities( const QVariant& capabilities ); private: + Tomahawk::query_ptr parseTrack( const QVariantMap& track ); void returnStreamUrl( const QString& streamUrl, boost::function< void( QSharedPointer< QIODevice >& ) > callback ); + QString m_scriptPath, m_urlCallback; QHash< QString, boost::function< void( QSharedPointer< QIODevice >& ) > > m_streamCallbacks; bool m_urlCallbackIsAsync; diff --git a/src/tomahawk/TomahawkApp.cpp b/src/tomahawk/TomahawkApp.cpp index 6a0ce86fd..88a7e3ea3 100644 --- a/src/tomahawk/TomahawkApp.cpp +++ b/src/tomahawk/TomahawkApp.cpp @@ -55,11 +55,12 @@ #include "accounts/spotify/SpotifyAccount.h" #include "accounts/spotify/SpotifyPlaylistUpdater.h" #include "accounts/AccountManager.h" +#include "audio/AudioEngine.h" #include "database/Database.h" #include "database/DatabaseCollection.h" #include "database/DatabaseCommand_CollectionStats.h" #include "database/DatabaseResolver.h" -#include "audio/AudioEngine.h" +#include "playlist/PlaylistTemplate.h" #include "jobview/ErrorStatusMessage.h" #include "jobview/JobStatusModel.h" #include "jobview/JobStatusView.h" @@ -401,6 +402,7 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< Tomahawk::dyncontrol_ptr >("Tomahawk::dyncontrol_ptr"); qRegisterMetaType< Tomahawk::playlist_ptr >("Tomahawk::playlist_ptr"); qRegisterMetaType< Tomahawk::playlistinterface_ptr >("Tomahawk::playlistinterface_ptr"); + qRegisterMetaType< Tomahawk::playlisttemplate_ptr >("Tomahawk::playlisttemplate_ptr"); qRegisterMetaType< Tomahawk::dynplaylist_ptr >("Tomahawk::dynplaylist_ptr"); qRegisterMetaType< Tomahawk::geninterface_ptr >("Tomahawk::geninterface_ptr"); qRegisterMetaType< Tomahawk::PlaybackLog >("Tomahawk::PlaybackLog"); @@ -750,6 +752,13 @@ TomahawkApp::informationForUrl( const QString& url, const QSharedPointer(); + if ( !pltemplate.isNull() ) + { + ViewManager::instance()->show( pltemplate->get() ); + return; + } + // Try to interpret as Track/Query Tomahawk::query_ptr query = information.objectCast(); if ( !query.isNull() )