From 2bda4966fce2411ca9bf3d80aef9d08a2e58b998 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Thu, 28 Jul 2011 17:33:58 +0200 Subject: [PATCH] Basic working use of resolvers for XSPF playlists. --- src/CMakeLists.txt | 2 ++ src/playlistparsers/parserbase.cpp | 4 +++ src/playlistparsers/xspfparser.cpp | 6 ++-- src/resolvers/libraryresolver.cpp | 1 + src/resolvers/songresolver.cpp | 51 ++++++++++++++++++++++++++++++ src/resolvers/songresolver.h | 37 ++++++++++++++++++++++ 6 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/resolvers/songresolver.cpp create mode 100644 src/resolvers/songresolver.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2431e875..dd5e4127a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -191,6 +191,7 @@ set(SOURCES playlistparsers/xspfparser.cpp resolvers/libraryresolver.cpp + resolvers/songresolver.cpp smartplaylists/generator.cpp smartplaylists/generatorinserter.cpp @@ -402,6 +403,7 @@ set(HEADERS resolvers/libraryresolver.h resolvers/resolver.h + resolvers/songresolver.h smartplaylists/generator.h smartplaylists/generatorinserter.h diff --git a/src/playlistparsers/parserbase.cpp b/src/playlistparsers/parserbase.cpp index 613e6be57..49c9b20e5 100644 --- a/src/playlistparsers/parserbase.cpp +++ b/src/playlistparsers/parserbase.cpp @@ -19,6 +19,7 @@ #include "library/librarybackend.h" #include "library/libraryquery.h" #include "library/sqlrow.h" +#include "resolvers/songresolver.h" #include @@ -31,6 +32,9 @@ ParserBase::ParserBase(LibraryBackendInterface* library, QObject *parent) void ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning, const QDir& dir, Song* song) const { if (filename_or_url.isEmpty()) { + // Try and resolve from various sources. + SongResolver resolver(library_); + resolver.ResolveSong(song); return; } diff --git a/src/playlistparsers/xspfparser.cpp b/src/playlistparsers/xspfparser.cpp index 468fff829..660be3e3e 100644 --- a/src/playlistparsers/xspfparser.cpp +++ b/src/playlistparsers/xspfparser.cpp @@ -90,13 +90,13 @@ Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const { } return_song: - Song song = LoadSong(location, 0, dir); - - // Override metadata with what was in the playlist + Song song; song.set_title(title); song.set_artist(artist); song.set_album(album); song.set_length_nanosec(nanosec); + LoadSong(location, 0, dir, &song); + return song; } diff --git a/src/resolvers/libraryresolver.cpp b/src/resolvers/libraryresolver.cpp index fa8d2bedb..6269fb590 100644 --- a/src/resolvers/libraryresolver.cpp +++ b/src/resolvers/libraryresolver.cpp @@ -22,6 +22,7 @@ int LibraryResolver::ResolveSong(const Song& song) { LibraryQuery* query = new LibraryQuery; query->AddWhere("artist", song.artist()); query->AddWhere("title", song.title()); + query->SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec); QFuture future = QtConcurrent::run( backend_, &LibraryBackendInterface::ExecQuery, query); diff --git a/src/resolvers/songresolver.cpp b/src/resolvers/songresolver.cpp new file mode 100644 index 000000000..eea1ca3c7 --- /dev/null +++ b/src/resolvers/songresolver.cpp @@ -0,0 +1,51 @@ +#include "songresolver.h" + +#include "core/logging.h" +#include "core/song.h" +#include "internet/internetmodel.h" +#include "internet/spotifyservice.h" +#include "libraryresolver.h" +#include "spotifyresolver.h" + +SongResolver::SongResolver(LibraryBackendInterface* library, QObject* parent) + : QObject(parent), + song_(NULL), + resolvers_finished_(0), + resolved_(false) { + // Register in the other they should be checked. + RegisterResolver(new LibraryResolver(library)); + RegisterResolver(new SpotifyResolver(InternetModel::Service()->server())); +} + +SongResolver::~SongResolver() { + qDeleteAll(resolvers_); + resolvers_.clear(); +} + +void SongResolver::RegisterResolver(Resolver* resolver) { + resolvers_ << resolver; + connect(resolver, SIGNAL(ResolveFinished(int, SongList)), SLOT(ResolveFinished(int, SongList))); +} + +bool SongResolver::ResolveSong(Song* song) { + song_ = song; + foreach (Resolver* resolver, resolvers_) { + resolver->ResolveSong(*song); + } + loop_.exec(); + return resolved_; +} + +void SongResolver::ResolveFinished(int, SongList resolved_songs) { + ++resolvers_finished_; + if (resolvers_finished_ == resolvers_.size()) { + loop_.quit(); + } + + if (!resolved_songs.isEmpty()) { + *song_ = resolved_songs.first(); + qLog(Debug) << "Resolved song:" << song_->title() << "from:" << sender()->metaObject()->className(); + resolved_ = true; + loop_.quit(); + } +} diff --git a/src/resolvers/songresolver.h b/src/resolvers/songresolver.h new file mode 100644 index 000000000..dbecf4185 --- /dev/null +++ b/src/resolvers/songresolver.h @@ -0,0 +1,37 @@ +#ifndef SONGRESOLVER_H +#define SONGRESOLVER_H + +#include +#include +#include + +#include "core/song.h" + +class LibraryBackendInterface; +class Resolver; + +class SongResolver : public QObject { + Q_OBJECT + public: + SongResolver(LibraryBackendInterface* library, QObject* parent = 0); + virtual ~SongResolver(); + + // Blocking + bool ResolveSong(Song* song); + + private slots: + void ResolveFinished(int, SongList resolved_songs); + + private: + void RegisterResolver(Resolver* resolver); + + QList resolvers_; + Song* song_; + + QEventLoop loop_; + + int resolvers_finished_; + bool resolved_; +}; + +#endif