From 8929f88e6d78d538d943e80b66fcf21706e53974 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 5 Sep 2013 09:37:54 +0200 Subject: [PATCH] PlaylistPlugin: add interface SongEnumerator Replaces struct playlist_provider. --- Makefile.am | 4 +- ...tProvider.cxx => MemorySongEnumerator.cxx} | 45 ++----------------- ...tProvider.hxx => MemorySongEnumerator.hxx} | 11 +++-- src/PlaylistAny.cxx | 7 ++- src/PlaylistAny.hxx | 4 +- src/PlaylistMapper.cxx | 24 +++++----- src/PlaylistMapper.hxx | 3 +- src/PlaylistPlugin.hxx | 42 +++-------------- src/PlaylistPrint.cxx | 12 ++--- src/PlaylistQueue.cxx | 13 +++--- src/PlaylistQueue.hxx | 4 +- src/PlaylistRegistry.cxx | 42 +++++++---------- src/PlaylistRegistry.hxx | 8 ++-- src/SongEnumerator.hxx | 41 +++++++++++++++++ src/playlist/AsxPlaylistPlugin.cxx | 11 +++-- src/playlist/CuePlaylistPlugin.cxx | 43 ++++++------------ src/playlist/DespotifyPlaylistPlugin.cxx | 9 ++-- src/playlist/EmbeddedCuePlaylistPlugin.cxx | 38 +++++----------- src/playlist/ExtM3uPlaylistPlugin.cxx | 40 +++++++---------- src/playlist/LastFMPlaylistPlugin.cxx | 42 ++++++----------- src/playlist/M3uPlaylistPlugin.cxx | 32 +++++-------- src/playlist/PlsPlaylistPlugin.cxx | 9 ++-- src/playlist/RssPlaylistPlugin.cxx | 11 +++-- src/playlist/SoundCloudPlaylistPlugin.cxx | 9 ++-- src/playlist/XspfPlaylistPlugin.cxx | 11 +++-- test/dump_playlist.cxx | 8 ++-- 26 files changed, 206 insertions(+), 317 deletions(-) rename src/{playlist/MemoryPlaylistProvider.cxx => MemorySongEnumerator.cxx} (52%) rename src/{playlist/MemoryPlaylistProvider.hxx => MemorySongEnumerator.hxx} (82%) create mode 100644 src/SongEnumerator.hxx diff --git a/Makefile.am b/Makefile.am index 862acac05..6def54a3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -917,8 +917,8 @@ endif libplaylist_plugins_a_SOURCES = \ src/PlaylistPlugin.hxx \ - src/playlist/MemoryPlaylistProvider.cxx \ - src/playlist/MemoryPlaylistProvider.hxx \ + src/SongEnumerator.hxx \ + src/MemorySongEnumerator.cxx src/MemorySongEnumerator.hxx \ src/playlist/ExtM3uPlaylistPlugin.cxx \ src/playlist/ExtM3uPlaylistPlugin.hxx \ src/playlist/M3uPlaylistPlugin.cxx \ diff --git a/src/playlist/MemoryPlaylistProvider.cxx b/src/MemorySongEnumerator.cxx similarity index 52% rename from src/playlist/MemoryPlaylistProvider.cxx rename to src/MemorySongEnumerator.cxx index c2b6d9312..7c9d05daa 100644 --- a/src/playlist/MemoryPlaylistProvider.cxx +++ b/src/MemorySongEnumerator.cxx @@ -18,50 +18,13 @@ */ #include "config.h" -#include "MemoryPlaylistProvider.hxx" -#include "Song.hxx" +#include "MemorySongEnumerator.hxx" -static void -memory_playlist_close(struct playlist_provider *_playlist) -{ - MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist; - - delete playlist; -} - -static Song * -memory_playlist_read(struct playlist_provider *_playlist) -{ - MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist; - - return playlist->Read(); -} - -static constexpr struct playlist_plugin memory_playlist_plugin = { - nullptr, - - nullptr, - nullptr, - nullptr, - nullptr, - memory_playlist_close, - memory_playlist_read, - - nullptr, - nullptr, - nullptr, -}; - -MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list &&_songs) - :songs(std::move(_songs)) { - playlist_provider_init(this, &memory_playlist_plugin); -} - -inline Song * -MemoryPlaylistProvider::Read() +Song * +MemorySongEnumerator::NextSong() { if (songs.empty()) - return NULL; + return nullptr; auto result = songs.front().Steal(); songs.pop_front(); diff --git a/src/playlist/MemoryPlaylistProvider.hxx b/src/MemorySongEnumerator.hxx similarity index 82% rename from src/playlist/MemoryPlaylistProvider.hxx rename to src/MemorySongEnumerator.hxx index efbc46fe1..46086a064 100644 --- a/src/playlist/MemoryPlaylistProvider.hxx +++ b/src/MemorySongEnumerator.hxx @@ -20,20 +20,19 @@ #ifndef MPD_MEMORY_PLAYLIST_PROVIDER_HXX #define MPD_MEMORY_PLAYLIST_PROVIDER_HXX -#include "PlaylistPlugin.hxx" +#include "SongEnumerator.hxx" #include "SongPointer.hxx" #include -struct Song; - -class MemoryPlaylistProvider : public playlist_provider { +class MemorySongEnumerator final : public SongEnumerator { std::forward_list songs; public: - MemoryPlaylistProvider(std::forward_list &&_songs); + MemorySongEnumerator(std::forward_list &&_songs) + :songs(std::move(_songs)) {} - Song *Read(); + virtual Song *NextSong() override; }; #endif diff --git a/src/PlaylistAny.cxx b/src/PlaylistAny.cxx index e84d055bd..95f65dca5 100644 --- a/src/PlaylistAny.cxx +++ b/src/PlaylistAny.cxx @@ -27,14 +27,13 @@ #include -static struct playlist_provider * +static SongEnumerator * playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r) { assert(uri_has_scheme(uri)); - struct playlist_provider *playlist = - playlist_list_open_uri(uri, mutex, cond); + SongEnumerator *playlist = playlist_list_open_uri(uri, mutex, cond); if (playlist != NULL) { *is_r = NULL; return playlist; @@ -60,7 +59,7 @@ playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond, return playlist; } -struct playlist_provider * +SongEnumerator * playlist_open_any(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r) { diff --git a/src/PlaylistAny.hxx b/src/PlaylistAny.hxx index d69087b3f..951fa1099 100644 --- a/src/PlaylistAny.hxx +++ b/src/PlaylistAny.hxx @@ -23,7 +23,7 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" -struct playlist_provider; +class SongEnumerator; struct input_stream; /** @@ -35,7 +35,7 @@ struct input_stream; * here, which must be closed after the playlist_provider object is * freed */ -struct playlist_provider * +SongEnumerator * playlist_open_any(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r); diff --git a/src/PlaylistMapper.cxx b/src/PlaylistMapper.cxx index 08131106d..559154a4e 100644 --- a/src/PlaylistMapper.cxx +++ b/src/PlaylistMapper.cxx @@ -27,13 +27,11 @@ #include -static struct playlist_provider * +static SongEnumerator * playlist_open_path(const char *path_fs, Mutex &mutex, Cond &cond, struct input_stream **is_r) { - struct playlist_provider *playlist; - - playlist = playlist_list_open_uri(path_fs, mutex, cond); + auto playlist = playlist_list_open_uri(path_fs, mutex, cond); if (playlist != NULL) *is_r = NULL; else @@ -45,7 +43,7 @@ playlist_open_path(const char *path_fs, Mutex &mutex, Cond &cond, /** * Load a playlist from the configured playlist directory. */ -static struct playlist_provider * +static SongEnumerator * playlist_open_in_playlist_dir(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r) { @@ -59,8 +57,7 @@ playlist_open_in_playlist_dir(const char *uri, Mutex &mutex, Cond &cond, path_fs = g_build_filename(playlist_directory_fs.c_str(), uri, NULL); - struct playlist_provider *playlist = - playlist_open_path(path_fs, mutex, cond, is_r); + auto playlist = playlist_open_path(path_fs, mutex, cond, is_r); g_free(path_fs); return playlist; @@ -69,7 +66,7 @@ playlist_open_in_playlist_dir(const char *uri, Mutex &mutex, Cond &cond, /** * Load a playlist from the configured music directory. */ -static struct playlist_provider * +static SongEnumerator * playlist_open_in_music_dir(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r) { @@ -82,21 +79,20 @@ playlist_open_in_music_dir(const char *uri, Mutex &mutex, Cond &cond, return playlist_open_path(path.c_str(), mutex, cond, is_r); } -struct playlist_provider * +SongEnumerator * playlist_mapper_open(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r) { - struct playlist_provider *playlist; - if (spl_valid_name(uri)) { - playlist = playlist_open_in_playlist_dir(uri, mutex, cond, - is_r); + auto playlist = playlist_open_in_playlist_dir(uri, mutex, cond, + is_r); if (playlist != NULL) return playlist; } if (uri_safe_local(uri)) { - playlist = playlist_open_in_music_dir(uri, mutex, cond, is_r); + auto playlist = playlist_open_in_music_dir(uri, mutex, cond, + is_r); if (playlist != NULL) return playlist; } diff --git a/src/PlaylistMapper.hxx b/src/PlaylistMapper.hxx index abfdb5481..b966e6c39 100644 --- a/src/PlaylistMapper.hxx +++ b/src/PlaylistMapper.hxx @@ -23,6 +23,7 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" +class SongEnumerator; struct input_stream; /** @@ -33,7 +34,7 @@ struct input_stream; * here, which must be closed after the playlist_provider object is * freed */ -struct playlist_provider * +SongEnumerator * playlist_mapper_open(const char *uri, Mutex &mutex, Cond &cond, struct input_stream **is_r); diff --git a/src/PlaylistPlugin.hxx b/src/PlaylistPlugin.hxx index f89fd9ce0..ce380d886 100644 --- a/src/PlaylistPlugin.hxx +++ b/src/PlaylistPlugin.hxx @@ -26,21 +26,7 @@ struct config_param; struct input_stream; struct Tag; -struct Song; - -/** - * An object which provides the contents of a playlist. - */ -struct playlist_provider { - const struct playlist_plugin *plugin; -}; - -static inline void -playlist_provider_init(struct playlist_provider *playlist, - const struct playlist_plugin *plugin) -{ - playlist->plugin = plugin; -} +class SongEnumerator; struct playlist_plugin { const char *name; @@ -65,19 +51,15 @@ struct playlist_plugin { * Opens the playlist on the specified URI. This URI has * either matched one of the schemes or one of the suffixes. */ - struct playlist_provider *(*open_uri)(const char *uri, - Mutex &mutex, Cond &cond); + SongEnumerator *(*open_uri)(const char *uri, + Mutex &mutex, Cond &cond); /** * Opens the playlist in the specified input stream. It has * either matched one of the suffixes or one of the MIME * types. */ - struct playlist_provider *(*open_stream)(struct input_stream *is); - - void (*close)(struct playlist_provider *playlist); - - Song *(*read)(struct playlist_provider *playlist); + SongEnumerator *(*open_stream)(struct input_stream *is); const char *const*schemes; const char *const*suffixes; @@ -111,30 +93,18 @@ playlist_plugin_finish(const struct playlist_plugin *plugin) plugin->finish(); } -static inline struct playlist_provider * +static inline SongEnumerator * playlist_plugin_open_uri(const struct playlist_plugin *plugin, const char *uri, Mutex &mutex, Cond &cond) { return plugin->open_uri(uri, mutex, cond); } -static inline struct playlist_provider * +static inline SongEnumerator * playlist_plugin_open_stream(const struct playlist_plugin *plugin, struct input_stream *is) { return plugin->open_stream(is); } -static inline void -playlist_plugin_close(struct playlist_provider *playlist) -{ - playlist->plugin->close(playlist); -} - -static inline Song * -playlist_plugin_read(struct playlist_provider *playlist) -{ - return playlist->plugin->read(playlist); -} - #endif diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx index f95061ca5..012f9600b 100644 --- a/src/PlaylistPrint.cxx +++ b/src/PlaylistPrint.cxx @@ -26,6 +26,7 @@ #include "PlaylistRegistry.hxx" #include "PlaylistPlugin.hxx" #include "QueuePrint.hxx" +#include "SongEnumerator.hxx" #include "SongPrint.hxx" #include "DatabaseGlue.hxx" #include "DatabasePlugin.hxx" @@ -145,12 +146,12 @@ spl_print(Client *client, const char *name_utf8, bool detail, static void playlist_provider_print(Client *client, const char *uri, - struct playlist_provider *playlist, bool detail) + SongEnumerator &e, bool detail) { Song *song; char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL; - while ((song = playlist_plugin_read(playlist)) != NULL) { + while ((song = e.NextSong()) != nullptr) { song = playlist_check_translate_song(song, base_uri, false); if (song == NULL) continue; @@ -173,13 +174,12 @@ playlist_file_print(Client *client, const char *uri, bool detail) Cond cond; struct input_stream *is; - struct playlist_provider *playlist = - playlist_open_any(uri, mutex, cond, &is); + SongEnumerator *playlist = playlist_open_any(uri, mutex, cond, &is); if (playlist == NULL) return false; - playlist_provider_print(client, uri, playlist, detail); - playlist_plugin_close(playlist); + playlist_provider_print(client, uri, *playlist, detail); + delete playlist; if (is != NULL) is->Close(); diff --git a/src/PlaylistQueue.cxx b/src/PlaylistQueue.cxx index af68176fe..901ee578d 100644 --- a/src/PlaylistQueue.cxx +++ b/src/PlaylistQueue.cxx @@ -24,10 +24,11 @@ #include "PlaylistSong.hxx" #include "Playlist.hxx" #include "InputStream.hxx" +#include "SongEnumerator.hxx" #include "Song.hxx" enum playlist_result -playlist_load_into_queue(const char *uri, struct playlist_provider *source, +playlist_load_into_queue(const char *uri, SongEnumerator &e, unsigned start_index, unsigned end_index, struct playlist *dest, struct player_control *pc, bool secure) @@ -37,7 +38,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source, char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL; for (unsigned i = 0; - i < end_index && (song = playlist_plugin_read(source)) != NULL; + i < end_index && (song = e.NextSong()) != NULL; ++i) { if (i < start_index) { /* skip songs before the start index */ @@ -72,15 +73,15 @@ playlist_open_into_queue(const char *uri, Cond cond; struct input_stream *is; - struct playlist_provider *playlist = - playlist_open_any(uri, mutex, cond, &is); + auto playlist = playlist_open_any(uri, mutex, cond, &is); if (playlist == NULL) return PLAYLIST_RESULT_NO_SUCH_LIST; enum playlist_result result = - playlist_load_into_queue(uri, playlist, start_index, end_index, + playlist_load_into_queue(uri, *playlist, + start_index, end_index, dest, pc, secure); - playlist_plugin_close(playlist); + delete playlist; if (is != NULL) is->Close(); diff --git a/src/PlaylistQueue.hxx b/src/PlaylistQueue.hxx index 5a5cc641d..71768ecb4 100644 --- a/src/PlaylistQueue.hxx +++ b/src/PlaylistQueue.hxx @@ -26,7 +26,7 @@ #include "PlaylistError.hxx" -struct playlist_provider; +class SongEnumerator; struct playlist; struct player_control; @@ -40,7 +40,7 @@ struct player_control; * @param end_index the index of the last song (excluding) */ enum playlist_result -playlist_load_into_queue(const char *uri, struct playlist_provider *source, +playlist_load_into_queue(const char *uri, SongEnumerator &e, unsigned start_index, unsigned end_index, struct playlist *dest, struct player_control *pc, bool secure); diff --git a/src/PlaylistRegistry.cxx b/src/PlaylistRegistry.cxx index 375e51d83..88628e455 100644 --- a/src/PlaylistRegistry.cxx +++ b/src/PlaylistRegistry.cxx @@ -124,12 +124,12 @@ playlist_list_global_finish(void) playlist_plugin_finish(plugin); } -static struct playlist_provider * +static SongEnumerator * playlist_list_open_uri_scheme(const char *uri, Mutex &mutex, Cond &cond, bool *tried) { char *scheme; - struct playlist_provider *playlist = NULL; + SongEnumerator *playlist = nullptr; assert(uri != NULL); @@ -158,12 +158,12 @@ playlist_list_open_uri_scheme(const char *uri, Mutex &mutex, Cond &cond, return playlist; } -static struct playlist_provider * +static SongEnumerator * playlist_list_open_uri_suffix(const char *uri, Mutex &mutex, Cond &cond, const bool *tried) { const char *suffix; - struct playlist_provider *playlist = NULL; + SongEnumerator *playlist = nullptr; assert(uri != NULL); @@ -187,10 +187,9 @@ playlist_list_open_uri_suffix(const char *uri, Mutex &mutex, Cond &cond, return playlist; } -struct playlist_provider * +SongEnumerator * playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond) { - struct playlist_provider *playlist; /** this array tracks which plugins have already been tried by playlist_list_open_uri_scheme() */ bool tried[G_N_ELEMENTS(playlist_plugins) - 1]; @@ -199,7 +198,7 @@ playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond) memset(tried, false, sizeof(tried)); - playlist = playlist_list_open_uri_scheme(uri, mutex, cond, tried); + auto playlist = playlist_list_open_uri_scheme(uri, mutex, cond, tried); if (playlist == NULL) playlist = playlist_list_open_uri_suffix(uri, mutex, cond, tried); @@ -207,11 +206,9 @@ playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond) return playlist; } -static struct playlist_provider * +static SongEnumerator * playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) { - struct playlist_provider *playlist; - assert(is != NULL); assert(mime != NULL); @@ -223,7 +220,7 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) fresh start */ is->Seek(0, SEEK_SET, IgnoreError()); - playlist = playlist_plugin_open_stream(plugin, is); + auto playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) return playlist; } @@ -232,7 +229,7 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) return NULL; } -static struct playlist_provider * +static SongEnumerator * playlist_list_open_stream_mime(struct input_stream *is, const char *full_mime) { assert(full_mime != NULL); @@ -246,17 +243,14 @@ playlist_list_open_stream_mime(struct input_stream *is, const char *full_mime) /* probe only the portion before the semicolon*/ char *mime = g_strndup(full_mime, semicolon - full_mime); - struct playlist_provider *playlist = - playlist_list_open_stream_mime2(is, mime); + auto playlist = playlist_list_open_stream_mime2(is, mime); g_free(mime); return playlist; } -static struct playlist_provider * +static SongEnumerator * playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) { - struct playlist_provider *playlist; - assert(is != NULL); assert(suffix != NULL); @@ -268,7 +262,7 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) fresh start */ is->Seek(0, SEEK_SET, IgnoreError()); - playlist = playlist_plugin_open_stream(plugin, is); + auto playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) return playlist; } @@ -277,24 +271,23 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) return NULL; } -struct playlist_provider * +SongEnumerator * playlist_list_open_stream(struct input_stream *is, const char *uri) { const char *suffix; - struct playlist_provider *playlist; is->LockWaitReady(); const char *const mime = is->GetMimeType(); if (mime != NULL) { - playlist = playlist_list_open_stream_mime(is, mime); + auto playlist = playlist_list_open_stream_mime(is, mime); if (playlist != NULL) return playlist; } suffix = uri != NULL ? uri_get_suffix(uri) : NULL; if (suffix != NULL) { - playlist = playlist_list_open_stream_suffix(is, suffix); + auto playlist = playlist_list_open_stream_suffix(is, suffix); if (playlist != NULL) return playlist; } @@ -316,12 +309,11 @@ playlist_suffix_supported(const char *suffix) return false; } -struct playlist_provider * +SongEnumerator * playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, struct input_stream **is_r) { const char *suffix; - struct playlist_provider *playlist; assert(path_fs != NULL); @@ -340,7 +332,7 @@ playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, is->LockWaitReady(); - playlist = playlist_list_open_stream_suffix(is, suffix); + auto playlist = playlist_list_open_stream_suffix(is, suffix); if (playlist != NULL) *is_r = is; else diff --git a/src/PlaylistRegistry.hxx b/src/PlaylistRegistry.hxx index 7c34c1565..350987012 100644 --- a/src/PlaylistRegistry.hxx +++ b/src/PlaylistRegistry.hxx @@ -23,7 +23,7 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" -struct playlist_provider; +class SongEnumerator; struct input_stream; extern const struct playlist_plugin *const playlist_plugins[]; @@ -49,7 +49,7 @@ playlist_list_global_finish(void); /** * Opens a playlist by its URI. */ -struct playlist_provider * +SongEnumerator * playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond); /** @@ -59,7 +59,7 @@ playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond); * @param uri optional URI which was used to open the stream; may be * used to select the appropriate playlist plugin */ -struct playlist_provider * +SongEnumerator * playlist_list_open_stream(struct input_stream *is, const char *uri); /** @@ -77,7 +77,7 @@ playlist_suffix_supported(const char *suffix); * which must be closed after the playlist_provider object is freed * @return a playlist, or NULL on error */ -struct playlist_provider * +SongEnumerator * playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, struct input_stream **is_r); diff --git a/src/SongEnumerator.hxx b/src/SongEnumerator.hxx new file mode 100644 index 000000000..0e268a31a --- /dev/null +++ b/src/SongEnumerator.hxx @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SONG_ENUMERATOR_HXX +#define MPD_SONG_ENUMERATOR_HXX + +struct Song; + +/** + * An object which provides serial access to a number of #Song + * objects. It is used to enumerate the contents of a playlist file. + */ +class SongEnumerator { +public: + virtual ~SongEnumerator() {} + + /** + * Obtain the next song. The caller is responsible for + * freeing the returned #Song object. Returns nullptr if + * there are no more songs. + */ + virtual Song *NextSong() = 0; +}; + +#endif diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/AsxPlaylistPlugin.cxx index c0fc15e07..6920ec268 100644 --- a/src/playlist/AsxPlaylistPlugin.cxx +++ b/src/playlist/AsxPlaylistPlugin.cxx @@ -19,7 +19,8 @@ #include "config.h" #include "AsxPlaylistPlugin.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "InputStream.hxx" #include "Song.hxx" #include "Tag.hxx" @@ -201,7 +202,7 @@ asx_parser_destroy(gpointer data) * */ -static struct playlist_provider * +static SongEnumerator * asx_open_stream(struct input_stream *is) { AsxParser parser; @@ -249,8 +250,8 @@ asx_open_stream(struct input_stream *is) } parser.songs.reverse(); - MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(std::move(parser.songs)); + MemorySongEnumerator *playlist = + new MemorySongEnumerator(std::move(parser.songs)); g_markup_parse_context_free(context); @@ -274,8 +275,6 @@ const struct playlist_plugin asx_playlist_plugin = { nullptr, nullptr, asx_open_stream, - nullptr, - nullptr, nullptr, asx_suffixes, diff --git a/src/playlist/CuePlaylistPlugin.cxx b/src/playlist/CuePlaylistPlugin.cxx index aa84b1c4a..1c1433a6a 100644 --- a/src/playlist/CuePlaylistPlugin.cxx +++ b/src/playlist/CuePlaylistPlugin.cxx @@ -20,67 +20,54 @@ #include "config.h" #include "CuePlaylistPlugin.hxx" #include "PlaylistPlugin.hxx" +#include "SongEnumerator.hxx" #include "Tag.hxx" #include "Song.hxx" #include "cue/CueParser.hxx" #include "TextInputStream.hxx" -#include #include #include #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "cue" -struct CuePlaylist { - struct playlist_provider base; - +class CuePlaylist final : public SongEnumerator { struct input_stream *is; TextInputStream tis; CueParser parser; + public: CuePlaylist(struct input_stream *_is) :is(_is), tis(is) { - playlist_provider_init(&base, &cue_playlist_plugin); } - ~CuePlaylist() { - } + virtual Song *NextSong() override; }; -static struct playlist_provider * +static SongEnumerator * cue_playlist_open_stream(struct input_stream *is) { - CuePlaylist *playlist = new CuePlaylist(is); - return &playlist->base; + return new CuePlaylist(is); } -static void -cue_playlist_close(struct playlist_provider *_playlist) +Song * +CuePlaylist::NextSong() { - CuePlaylist *playlist = (CuePlaylist *)_playlist; - delete playlist; -} - -static Song * -cue_playlist_read(struct playlist_provider *_playlist) -{ - CuePlaylist *playlist = (CuePlaylist *)_playlist; - - Song *song = playlist->parser.Get(); + Song *song = parser.Get(); if (song != NULL) return song; std::string line; - while (playlist->tis.ReadLine(line)) { - playlist->parser.Feed(line.c_str()); - song = playlist->parser.Get(); + while (tis.ReadLine(line)) { + parser.Feed(line.c_str()); + song = parser.Get(); if (song != NULL) return song; } - playlist->parser.Finish(); - return playlist->parser.Get(); + parser.Finish(); + return parser.Get(); } static const char *const cue_playlist_suffixes[] = { @@ -100,8 +87,6 @@ const struct playlist_plugin cue_playlist_plugin = { nullptr, nullptr, cue_playlist_open_stream, - cue_playlist_close, - cue_playlist_read, nullptr, cue_playlist_suffixes, diff --git a/src/playlist/DespotifyPlaylistPlugin.cxx b/src/playlist/DespotifyPlaylistPlugin.cxx index 5759a10c0..3e6527ea7 100644 --- a/src/playlist/DespotifyPlaylistPlugin.cxx +++ b/src/playlist/DespotifyPlaylistPlugin.cxx @@ -20,7 +20,8 @@ #include "config.h" #include "DespotifyPlaylistPlugin.hxx" #include "DespotifyUtils.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "Tag.hxx" #include "Song.hxx" @@ -86,7 +87,7 @@ parse_playlist(struct despotify_session *session, return true; } -static struct playlist_provider * +static SongEnumerator * despotify_playlist_open_uri(const char *url, gcc_unused Mutex &mutex, gcc_unused Cond &cond) { @@ -122,7 +123,7 @@ despotify_playlist_open_uri(const char *url, return nullptr; songs.reverse(); - return new MemoryPlaylistProvider(std::move(songs)); + return new MemorySongEnumerator(std::move(songs)); } static const char *const despotify_schemes[] = { @@ -137,8 +138,6 @@ const struct playlist_plugin despotify_playlist_plugin = { nullptr, despotify_playlist_open_uri, nullptr, - nullptr, - nullptr, despotify_schemes, nullptr, diff --git a/src/playlist/EmbeddedCuePlaylistPlugin.cxx b/src/playlist/EmbeddedCuePlaylistPlugin.cxx index 237bccdd5..8c5309ac1 100644 --- a/src/playlist/EmbeddedCuePlaylistPlugin.cxx +++ b/src/playlist/EmbeddedCuePlaylistPlugin.cxx @@ -26,6 +26,7 @@ #include "config.h" #include "EmbeddedCuePlaylistPlugin.hxx" #include "PlaylistPlugin.hxx" +#include "SongEnumerator.hxx" #include "Tag.hxx" #include "TagHandler.hxx" #include "tag/TagId3.hxx" @@ -41,9 +42,8 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "cue" -struct EmbeddedCuePlaylist { - struct playlist_provider base; - +class EmbeddedCuePlaylist final : public SongEnumerator { +public: /** * This is an override for the CUE's "FILE". An embedded CUE * sheet must always point to the song file it is contained @@ -63,18 +63,18 @@ struct EmbeddedCuePlaylist { CueParser *parser; +public: EmbeddedCuePlaylist() :filename(nullptr), cuesheet(nullptr), parser(nullptr) { - playlist_provider_init(&base, &embcue_playlist_plugin); } - ~EmbeddedCuePlaylist() { + virtual ~EmbeddedCuePlaylist() { delete parser; g_free(cuesheet); g_free(filename); } - Song *Read(); + virtual Song *NextSong() override; }; static void @@ -93,7 +93,7 @@ static const struct tag_handler embcue_tag_handler = { embcue_tag_pair, }; -static struct playlist_provider * +static SongEnumerator * embcue_playlist_open_uri(const char *uri, gcc_unused Mutex &mutex, gcc_unused Cond &cond) @@ -122,19 +122,11 @@ embcue_playlist_open_uri(const char *uri, playlist->next = playlist->cuesheet; playlist->parser = new CueParser(); - return &playlist->base; + return playlist; } -static void -embcue_playlist_close(struct playlist_provider *_playlist) -{ - EmbeddedCuePlaylist *playlist = (EmbeddedCuePlaylist *)_playlist; - - delete playlist; -} - -inline Song * -EmbeddedCuePlaylist::Read() +Song * +EmbeddedCuePlaylist::NextSong() { Song *song = parser->Get(); if (song != NULL) @@ -165,14 +157,6 @@ EmbeddedCuePlaylist::Read() return song; } -static Song * -embcue_playlist_read(struct playlist_provider *_playlist) -{ - EmbeddedCuePlaylist *playlist = (EmbeddedCuePlaylist *)_playlist; - - return playlist->Read(); -} - static const char *const embcue_playlist_suffixes[] = { /* a few codecs that are known to be supported; there are probably many more */ @@ -192,8 +176,6 @@ const struct playlist_plugin embcue_playlist_plugin = { nullptr, embcue_playlist_open_uri, nullptr, - embcue_playlist_close, - embcue_playlist_read, embcue_playlist_suffixes, nullptr, diff --git a/src/playlist/ExtM3uPlaylistPlugin.cxx b/src/playlist/ExtM3uPlaylistPlugin.cxx index 440dcd432..ff3fcbd7e 100644 --- a/src/playlist/ExtM3uPlaylistPlugin.cxx +++ b/src/playlist/ExtM3uPlaylistPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "ExtM3uPlaylistPlugin.hxx" #include "PlaylistPlugin.hxx" +#include "SongEnumerator.hxx" #include "Song.hxx" #include "Tag.hxx" #include "util/StringUtil.hxx" @@ -30,40 +31,36 @@ #include #include -struct ExtM3uPlaylist { - struct playlist_provider base; - +class ExtM3uPlaylist final : public SongEnumerator { TextInputStream tis; +public: ExtM3uPlaylist(input_stream *is) :tis(is) { - playlist_provider_init(&base, &extm3u_playlist_plugin); } + + bool CheckFirstLine() { + std::string line; + return tis.ReadLine(line) && + strcmp(line.c_str(), "#EXTM3U") == 0; + } + + virtual Song *NextSong() override; }; -static struct playlist_provider * +static SongEnumerator * extm3u_open_stream(struct input_stream *is) { ExtM3uPlaylist *playlist = new ExtM3uPlaylist(is); - std::string line; - if (!playlist->tis.ReadLine(line) - || strcmp(line.c_str(), "#EXTM3U") != 0) { + if (!playlist->CheckFirstLine()) { /* no EXTM3U header: fall back to the plain m3u plugin */ delete playlist; return NULL; } - return &playlist->base; -} - -static void -extm3u_close(struct playlist_provider *_playlist) -{ - ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist; - - delete playlist; + return playlist; } /** @@ -106,17 +103,16 @@ extm3u_parse_tag(const char *line) return tag; } -static Song * -extm3u_read(struct playlist_provider *_playlist) +Song * +ExtM3uPlaylist::NextSong() { - ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist; Tag *tag = NULL; std::string line; const char *line_s; Song *song; do { - if (!playlist->tis.ReadLine(line)) { + if (!tis.ReadLine(line)) { delete tag; return NULL; } @@ -155,8 +151,6 @@ const struct playlist_plugin extm3u_playlist_plugin = { nullptr, nullptr, extm3u_open_stream, - extm3u_close, - extm3u_read, nullptr, extm3u_suffixes, diff --git a/src/playlist/LastFMPlaylistPlugin.cxx b/src/playlist/LastFMPlaylistPlugin.cxx index a727a21a4..2cc538e1e 100644 --- a/src/playlist/LastFMPlaylistPlugin.cxx +++ b/src/playlist/LastFMPlaylistPlugin.cxx @@ -21,6 +21,7 @@ #include "LastFMPlaylistPlugin.hxx" #include "PlaylistPlugin.hxx" #include "PlaylistRegistry.hxx" +#include "SongEnumerator.hxx" #include "ConfigData.hxx" #include "Song.hxx" #include "InputStream.hxx" @@ -31,22 +32,24 @@ #include #include -struct LastfmPlaylist { - struct playlist_provider base; - +class LastfmPlaylist final : public SongEnumerator { struct input_stream *is; - struct playlist_provider *xspf; + SongEnumerator *const xspf; - LastfmPlaylist(input_stream *_is, playlist_provider *_xspf) +public: + LastfmPlaylist(input_stream *_is, SongEnumerator *_xspf) :is(_is), xspf(_xspf) { - playlist_provider_init(&base, &lastfm_playlist_plugin); } - ~LastfmPlaylist() { - playlist_plugin_close(xspf); + virtual ~LastfmPlaylist() { + delete xspf; is->Close(); } + + virtual Song *NextSong() override { + return xspf->NextSong(); + } }; static struct { @@ -161,7 +164,7 @@ lastfm_find(const char *response, const char *name) } } -static struct playlist_provider * +static SongEnumerator * lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) { char *p, *q, *response, *session; @@ -256,24 +259,7 @@ lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) /* create the playlist object */ - const auto playlist = new LastfmPlaylist(is, xspf); - return &playlist->base; -} - -static void -lastfm_close(struct playlist_provider *_playlist) -{ - LastfmPlaylist *playlist = (LastfmPlaylist *)_playlist; - - delete playlist; -} - -static Song * -lastfm_read(struct playlist_provider *_playlist) -{ - LastfmPlaylist *playlist = (LastfmPlaylist *)_playlist; - - return playlist_plugin_read(playlist->xspf); + return new LastfmPlaylist(is, xspf); } static const char *const lastfm_schemes[] = { @@ -288,8 +274,6 @@ const struct playlist_plugin lastfm_playlist_plugin = { lastfm_finish, lastfm_open_uri, nullptr, - lastfm_close, - lastfm_read, lastfm_schemes, nullptr, diff --git a/src/playlist/M3uPlaylistPlugin.cxx b/src/playlist/M3uPlaylistPlugin.cxx index d9f1e4737..8854be8d7 100644 --- a/src/playlist/M3uPlaylistPlugin.cxx +++ b/src/playlist/M3uPlaylistPlugin.cxx @@ -20,47 +20,37 @@ #include "config.h" #include "M3uPlaylistPlugin.hxx" #include "PlaylistPlugin.hxx" +#include "SongEnumerator.hxx" #include "Song.hxx" #include "TextInputStream.hxx" #include -struct M3uPlaylist { - struct playlist_provider base; - +class M3uPlaylist final : public SongEnumerator { TextInputStream tis; +public: M3uPlaylist(input_stream *is) :tis(is) { - playlist_provider_init(&base, &m3u_playlist_plugin); } + + virtual Song *NextSong() override; }; -static struct playlist_provider * +static SongEnumerator * m3u_open_stream(struct input_stream *is) { - M3uPlaylist *playlist = new M3uPlaylist(is); - - return &playlist->base; + return new M3uPlaylist(is); } -static void -m3u_close(struct playlist_provider *_playlist) +Song * +M3uPlaylist::NextSong() { - M3uPlaylist *playlist = (M3uPlaylist *)_playlist; - - delete playlist; -} - -static Song * -m3u_read(struct playlist_provider *_playlist) -{ - M3uPlaylist *playlist = (M3uPlaylist *)_playlist; std::string line; const char *line_s; do { - if (!playlist->tis.ReadLine(line)) + if (!tis.ReadLine(line)) return NULL; line_s = line.c_str(); @@ -89,8 +79,6 @@ const struct playlist_plugin m3u_playlist_plugin = { nullptr, nullptr, m3u_open_stream, - m3u_close, - m3u_read, nullptr, m3u_suffixes, diff --git a/src/playlist/PlsPlaylistPlugin.cxx b/src/playlist/PlsPlaylistPlugin.cxx index 4a0fde45f..946fe9c55 100644 --- a/src/playlist/PlsPlaylistPlugin.cxx +++ b/src/playlist/PlsPlaylistPlugin.cxx @@ -19,7 +19,8 @@ #include "config.h" #include "PlsPlaylistPlugin.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "InputStream.hxx" #include "Song.hxx" #include "Tag.hxx" @@ -101,7 +102,7 @@ pls_parser(GKeyFile *keyfile, std::forward_list &songs) } -static struct playlist_provider * +static SongEnumerator * pls_open_stream(struct input_stream *is) { GError *error = NULL; @@ -150,7 +151,7 @@ pls_open_stream(struct input_stream *is) g_key_file_free(keyfile); songs.reverse(); - return new MemoryPlaylistProvider(std::move(songs)); + return new MemorySongEnumerator(std::move(songs)); } static const char *const pls_suffixes[] = { @@ -170,8 +171,6 @@ const struct playlist_plugin pls_playlist_plugin = { nullptr, nullptr, pls_open_stream, - nullptr, - nullptr, nullptr, pls_suffixes, diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/RssPlaylistPlugin.cxx index c045b4df2..97c0d806b 100644 --- a/src/playlist/RssPlaylistPlugin.cxx +++ b/src/playlist/RssPlaylistPlugin.cxx @@ -19,7 +19,8 @@ #include "config.h" #include "RssPlaylistPlugin.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "InputStream.hxx" #include "Song.hxx" #include "Tag.hxx" @@ -198,7 +199,7 @@ rss_parser_destroy(gpointer data) * */ -static struct playlist_provider * +static SongEnumerator * rss_open_stream(struct input_stream *is) { RssParser parser; @@ -246,8 +247,8 @@ rss_open_stream(struct input_stream *is) } parser.songs.reverse(); - MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(std::move(parser.songs)); + MemorySongEnumerator *playlist = + new MemorySongEnumerator(std::move(parser.songs)); g_markup_parse_context_free(context); @@ -272,8 +273,6 @@ const struct playlist_plugin rss_playlist_plugin = { nullptr, nullptr, rss_open_stream, - nullptr, - nullptr, nullptr, rss_suffixes, diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx index 5679062cf..f822382fc 100644 --- a/src/playlist/SoundCloudPlaylistPlugin.cxx +++ b/src/playlist/SoundCloudPlaylistPlugin.cxx @@ -19,7 +19,8 @@ #include "config.h" #include "SoundCloudPlaylistPlugin.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "ConfigData.hxx" #include "InputStream.hxx" #include "Song.hxx" @@ -315,7 +316,7 @@ soundcloud_parse_json(const char *url, yajl_handle hand, * soundcloud://url/ */ -static struct playlist_provider * +static SongEnumerator * soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) { char *s, *p; @@ -389,7 +390,7 @@ soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) return NULL; data.songs.reverse(); - return new MemoryPlaylistProvider(std::move(data.songs)); + return new MemorySongEnumerator(std::move(data.songs)); } static const char *const soundcloud_schemes[] = { @@ -404,8 +405,6 @@ const struct playlist_plugin soundcloud_playlist_plugin = { soundcloud_finish, soundcloud_open_uri, nullptr, - nullptr, - nullptr, soundcloud_schemes, nullptr, diff --git a/src/playlist/XspfPlaylistPlugin.cxx b/src/playlist/XspfPlaylistPlugin.cxx index 667f484b2..002a03f8a 100644 --- a/src/playlist/XspfPlaylistPlugin.cxx +++ b/src/playlist/XspfPlaylistPlugin.cxx @@ -19,7 +19,8 @@ #include "config.h" #include "XspfPlaylistPlugin.hxx" -#include "MemoryPlaylistProvider.hxx" +#include "PlaylistPlugin.hxx" +#include "MemorySongEnumerator.hxx" #include "InputStream.hxx" #include "Tag.hxx" #include "util/Error.hxx" @@ -217,7 +218,7 @@ xspf_parser_destroy(gpointer data) * */ -static struct playlist_provider * +static SongEnumerator * xspf_open_stream(struct input_stream *is) { XspfParser parser; @@ -265,8 +266,8 @@ xspf_open_stream(struct input_stream *is) } parser.songs.reverse(); - MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(std::move(parser.songs)); + MemorySongEnumerator *playlist = + new MemorySongEnumerator(std::move(parser.songs)); g_markup_parse_context_free(context); @@ -290,8 +291,6 @@ const struct playlist_plugin xspf_playlist_plugin = { nullptr, nullptr, xspf_open_stream, - nullptr, - nullptr, nullptr, xspf_suffixes, diff --git a/test/dump_playlist.cxx b/test/dump_playlist.cxx index c42a2c52b..45719fab0 100644 --- a/test/dump_playlist.cxx +++ b/test/dump_playlist.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "TagSave.hxx" #include "Song.hxx" +#include "SongEnumerator.hxx" #include "Directory.hxx" #include "InputStream.hxx" #include "ConfigGlobal.hxx" @@ -141,7 +142,6 @@ int main(int argc, char **argv) { const char *uri; struct input_stream *is = NULL; - struct playlist_provider *playlist; Song *song; if (argc != 3) { @@ -186,7 +186,7 @@ int main(int argc, char **argv) Mutex mutex; Cond cond; - playlist = playlist_list_open_uri(uri, mutex, cond); + auto playlist = playlist_list_open_uri(uri, mutex, cond); if (playlist == NULL) { /* open the stream and wait until it becomes ready */ @@ -213,7 +213,7 @@ int main(int argc, char **argv) /* dump the playlist */ - while ((song = playlist_plugin_read(playlist)) != NULL) { + while ((song = playlist->NextSong()) != NULL) { g_print("%s\n", song->uri); if (song->end_ms > 0) @@ -235,7 +235,7 @@ int main(int argc, char **argv) /* deinitialize everything */ - playlist_plugin_close(playlist); + delete playlist; if (is != NULL) is->Close();