diff options
Diffstat (limited to 'src/playlist')
-rw-r--r-- | src/playlist/MemorySongEnumerator.cxx | 32 | ||||
-rw-r--r-- | src/playlist/MemorySongEnumerator.hxx | 38 | ||||
-rw-r--r-- | src/playlist/PlaylistAny.cxx | 69 | ||||
-rw-r--r-- | src/playlist/PlaylistAny.hxx | 41 | ||||
-rw-r--r-- | src/playlist/PlaylistMapper.cxx | 102 | ||||
-rw-r--r-- | src/playlist/PlaylistMapper.hxx | 40 | ||||
-rw-r--r-- | src/playlist/PlaylistPlugin.hxx | 109 | ||||
-rw-r--r-- | src/playlist/PlaylistQueue.cxx | 90 | ||||
-rw-r--r-- | src/playlist/PlaylistQueue.hxx | 59 | ||||
-rw-r--r-- | src/playlist/PlaylistRegistry.cxx | 335 | ||||
-rw-r--r-- | src/playlist/PlaylistRegistry.hxx | 83 | ||||
-rw-r--r-- | src/playlist/PlaylistSong.cxx | 131 | ||||
-rw-r--r-- | src/playlist/PlaylistSong.hxx | 37 | ||||
-rw-r--r-- | src/playlist/Print.cxx | 71 | ||||
-rw-r--r-- | src/playlist/Print.hxx | 36 | ||||
-rw-r--r-- | src/playlist/SongEnumerator.hxx | 41 | ||||
-rw-r--r-- | src/playlist/plugins/AsxPlaylistPlugin.cxx (renamed from src/playlist/AsxPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/AsxPlaylistPlugin.hxx (renamed from src/playlist/AsxPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/CuePlaylistPlugin.cxx (renamed from src/playlist/CuePlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/CuePlaylistPlugin.hxx (renamed from src/playlist/CuePlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/DespotifyPlaylistPlugin.cxx (renamed from src/playlist/DespotifyPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/DespotifyPlaylistPlugin.hxx (renamed from src/playlist/DespotifyPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx (renamed from src/playlist/EmbeddedCuePlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx (renamed from src/playlist/EmbeddedCuePlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/ExtM3uPlaylistPlugin.cxx (renamed from src/playlist/ExtM3uPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/ExtM3uPlaylistPlugin.hxx (renamed from src/playlist/ExtM3uPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/M3uPlaylistPlugin.cxx (renamed from src/playlist/M3uPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/M3uPlaylistPlugin.hxx (renamed from src/playlist/M3uPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/PlsPlaylistPlugin.cxx (renamed from src/playlist/PlsPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/PlsPlaylistPlugin.hxx (renamed from src/playlist/PlsPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/RssPlaylistPlugin.cxx (renamed from src/playlist/RssPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/RssPlaylistPlugin.hxx (renamed from src/playlist/RssPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/SoundCloudPlaylistPlugin.cxx (renamed from src/playlist/SoundCloudPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/SoundCloudPlaylistPlugin.hxx (renamed from src/playlist/SoundCloudPlaylistPlugin.hxx) | 0 | ||||
-rw-r--r-- | src/playlist/plugins/XspfPlaylistPlugin.cxx (renamed from src/playlist/XspfPlaylistPlugin.cxx) | 4 | ||||
-rw-r--r-- | src/playlist/plugins/XspfPlaylistPlugin.hxx (renamed from src/playlist/XspfPlaylistPlugin.hxx) | 0 |
36 files changed, 1334 insertions, 20 deletions
diff --git a/src/playlist/MemorySongEnumerator.cxx b/src/playlist/MemorySongEnumerator.cxx new file mode 100644 index 000000000..c3127c2bf --- /dev/null +++ b/src/playlist/MemorySongEnumerator.cxx @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "MemorySongEnumerator.hxx" + +DetachedSong * +MemorySongEnumerator::NextSong() +{ + if (songs.empty()) + return nullptr; + + auto result = new DetachedSong(std::move(songs.front())); + songs.pop_front(); + return result; +} diff --git a/src/playlist/MemorySongEnumerator.hxx b/src/playlist/MemorySongEnumerator.hxx new file mode 100644 index 000000000..e87a4f6dd --- /dev/null +++ b/src/playlist/MemorySongEnumerator.hxx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2014 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_MEMORY_PLAYLIST_PROVIDER_HXX +#define MPD_MEMORY_PLAYLIST_PROVIDER_HXX + +#include "SongEnumerator.hxx" +#include "DetachedSong.hxx" + +#include <forward_list> + +class MemorySongEnumerator final : public SongEnumerator { + std::forward_list<DetachedSong> songs; + +public: + MemorySongEnumerator(std::forward_list<DetachedSong> &&_songs) + :songs(std::move(_songs)) {} + + virtual DetachedSong *NextSong() override; +}; + +#endif diff --git a/src/playlist/PlaylistAny.cxx b/src/playlist/PlaylistAny.cxx new file mode 100644 index 000000000..8d748cada --- /dev/null +++ b/src/playlist/PlaylistAny.cxx @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "PlaylistAny.hxx" +#include "PlaylistMapper.hxx" +#include "PlaylistRegistry.hxx" +#include "util/UriUtil.hxx" +#include "util/Error.hxx" +#include "InputStream.hxx" +#include "Log.hxx" + +#include <assert.h> + +static SongEnumerator * +playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + assert(uri_has_scheme(uri)); + + SongEnumerator *playlist = playlist_list_open_uri(uri, mutex, cond); + if (playlist != nullptr) { + *is_r = nullptr; + return playlist; + } + + Error error; + InputStream *is = InputStream::OpenReady(uri, mutex, cond, error); + if (is == nullptr) { + if (error.IsDefined()) + FormatError(error, "Failed to open %s", uri); + + return nullptr; + } + + playlist = playlist_list_open_stream(*is, uri); + if (playlist == nullptr) { + is->Close(); + return nullptr; + } + + *is_r = is; + return playlist; +} + +SongEnumerator * +playlist_open_any(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + return uri_has_scheme(uri) + ? playlist_open_remote(uri, mutex, cond, is_r) + : playlist_mapper_open(uri, mutex, cond, is_r); +} diff --git a/src/playlist/PlaylistAny.hxx b/src/playlist/PlaylistAny.hxx new file mode 100644 index 000000000..c472afb31 --- /dev/null +++ b/src/playlist/PlaylistAny.hxx @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST_ANY_HXX +#define MPD_PLAYLIST_ANY_HXX + +class Mutex; +class Cond; +class SongEnumerator; +struct InputStream; + +/** + * Opens a playlist from the specified URI, which can be either an + * absolute remote URI (with a scheme) or a relative path to the + * music orplaylist directory. + * + * @param is_r on success, an input_stream object may be returned + * here, which must be closed after the playlist_provider object is + * freed + */ +SongEnumerator * +playlist_open_any(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r); + +#endif diff --git a/src/playlist/PlaylistMapper.cxx b/src/playlist/PlaylistMapper.cxx new file mode 100644 index 000000000..0df0bc61f --- /dev/null +++ b/src/playlist/PlaylistMapper.cxx @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "PlaylistMapper.hxx" +#include "PlaylistFile.hxx" +#include "PlaylistRegistry.hxx" +#include "Mapper.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/UriUtil.hxx" + +#include <assert.h> + +static SongEnumerator * +playlist_open_path(const char *path_fs, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + auto playlist = playlist_list_open_uri(path_fs, mutex, cond); + if (playlist != nullptr) + *is_r = nullptr; + else + playlist = playlist_list_open_path(path_fs, mutex, cond, is_r); + + return playlist; +} + +/** + * Load a playlist from the configured playlist directory. + */ +static SongEnumerator * +playlist_open_in_playlist_dir(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + assert(spl_valid_name(uri)); + + const auto &playlist_directory_fs = map_spl_path(); + if (playlist_directory_fs.IsNull()) + return nullptr; + + const auto uri_fs = AllocatedPath::FromUTF8(uri); + if (uri_fs.IsNull()) + return nullptr; + + const auto path_fs = + AllocatedPath::Build(playlist_directory_fs, uri_fs); + assert(!path_fs.IsNull()); + + return playlist_open_path(path_fs.c_str(), mutex, cond, is_r); +} + +/** + * Load a playlist from the configured music directory. + */ +static SongEnumerator * +playlist_open_in_music_dir(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + assert(uri_safe_local(uri)); + + const auto path = map_uri_fs(uri); + if (path.IsNull()) + return nullptr; + + return playlist_open_path(path.c_str(), mutex, cond, is_r); +} + +SongEnumerator * +playlist_mapper_open(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + if (spl_valid_name(uri)) { + auto playlist = playlist_open_in_playlist_dir(uri, mutex, cond, + is_r); + if (playlist != nullptr) + return playlist; + } + + if (uri_safe_local(uri)) { + auto playlist = playlist_open_in_music_dir(uri, mutex, cond, + is_r); + if (playlist != nullptr) + return playlist; + } + + return nullptr; +} diff --git a/src/playlist/PlaylistMapper.hxx b/src/playlist/PlaylistMapper.hxx new file mode 100644 index 000000000..a460cb124 --- /dev/null +++ b/src/playlist/PlaylistMapper.hxx @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST_MAPPER_HXX +#define MPD_PLAYLIST_MAPPER_HXX + +class Mutex; +class Cond; +class SongEnumerator; +struct InputStream; + +/** + * Opens a playlist from an URI relative to the playlist or music + * directory. + * + * @param is_r on success, an input_stream object may be returned + * here, which must be closed after the playlist_provider object is + * freed + */ +SongEnumerator * +playlist_mapper_open(const char *uri, Mutex &mutex, Cond &cond, + InputStream **is_r); + +#endif diff --git a/src/playlist/PlaylistPlugin.hxx b/src/playlist/PlaylistPlugin.hxx new file mode 100644 index 000000000..d3c44f1f4 --- /dev/null +++ b/src/playlist/PlaylistPlugin.hxx @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST_PLUGIN_HXX +#define MPD_PLAYLIST_PLUGIN_HXX + +struct config_param; +struct InputStream; +struct Tag; +class Mutex; +class Cond; +class SongEnumerator; + +struct playlist_plugin { + const char *name; + + /** + * Initialize the plugin. Optional method. + * + * @param param a configuration block for this plugin, or nullptr + * if none is configured + * @return true if the plugin was initialized successfully, + * false if the plugin is not available + */ + bool (*init)(const config_param ¶m); + + /** + * Deinitialize a plugin which was initialized successfully. + * Optional method. + */ + void (*finish)(void); + + /** + * Opens the playlist on the specified URI. This URI has + * either matched one of the schemes or one of the suffixes. + */ + 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. + */ + SongEnumerator *(*open_stream)(InputStream &is); + + const char *const*schemes; + const char *const*suffixes; + const char *const*mime_types; +}; + +/** + * Initialize a plugin. + * + * @param param a configuration block for this plugin, or nullptr if none + * is configured + * @return true if the plugin was initialized successfully, false if + * the plugin is not available + */ +static inline bool +playlist_plugin_init(const struct playlist_plugin *plugin, + const config_param ¶m) +{ + return plugin->init != nullptr + ? plugin->init(param) + : true; +} + +/** + * Deinitialize a plugin which was initialized successfully. + */ +static inline void +playlist_plugin_finish(const struct playlist_plugin *plugin) +{ + if (plugin->finish != nullptr) + plugin->finish(); +} + +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 SongEnumerator * +playlist_plugin_open_stream(const struct playlist_plugin *plugin, + InputStream &is) +{ + return plugin->open_stream(is); +} + +#endif diff --git a/src/playlist/PlaylistQueue.cxx b/src/playlist/PlaylistQueue.cxx new file mode 100644 index 000000000..0a45920e3 --- /dev/null +++ b/src/playlist/PlaylistQueue.cxx @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "PlaylistQueue.hxx" +#include "PlaylistAny.hxx" +#include "PlaylistSong.hxx" +#include "Playlist.hxx" +#include "InputStream.hxx" +#include "SongEnumerator.hxx" +#include "DetachedSong.hxx" +#include "thread/Cond.hxx" +#include "fs/Traits.hxx" + +PlaylistResult +playlist_load_into_queue(const char *uri, SongEnumerator &e, + unsigned start_index, unsigned end_index, + playlist &dest, PlayerControl &pc, + bool secure) +{ + const std::string base_uri = uri != nullptr + ? PathTraitsUTF8::GetParent(uri) + : std::string("."); + + DetachedSong *song; + for (unsigned i = 0; + i < end_index && (song = e.NextSong()) != nullptr; + ++i) { + if (i < start_index) { + /* skip songs before the start index */ + delete song; + continue; + } + + if (!playlist_check_translate_song(*song, base_uri.c_str(), + secure)) { + delete song; + continue; + } + + PlaylistResult result = dest.AppendSong(pc, std::move(*song)); + delete song; + if (result != PlaylistResult::SUCCESS) + return result; + } + + return PlaylistResult::SUCCESS; +} + +PlaylistResult +playlist_open_into_queue(const char *uri, + unsigned start_index, unsigned end_index, + playlist &dest, PlayerControl &pc, + bool secure) +{ + Mutex mutex; + Cond cond; + + InputStream *is; + auto playlist = playlist_open_any(uri, mutex, cond, &is); + if (playlist == nullptr) + return PlaylistResult::NO_SUCH_LIST; + + PlaylistResult result = + playlist_load_into_queue(uri, *playlist, + start_index, end_index, + dest, pc, secure); + delete playlist; + + if (is != nullptr) + is->Close(); + + return result; +} diff --git a/src/playlist/PlaylistQueue.hxx b/src/playlist/PlaylistQueue.hxx new file mode 100644 index 000000000..075191ced --- /dev/null +++ b/src/playlist/PlaylistQueue.hxx @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +/*! \file + * \brief Glue between playlist plugin and the play queue + */ + +#ifndef MPD_PLAYLIST_QUEUE_HXX +#define MPD_PLAYLIST_QUEUE_HXX + +#include "PlaylistError.hxx" + +class SongEnumerator; +struct playlist; +struct PlayerControl; + +/** + * Loads the contents of a playlist and append it to the specified + * play queue. + * + * @param uri the URI of the playlist, used to resolve relative song + * URIs + * @param start_index the index of the first song + * @param end_index the index of the last song (excluding) + */ +PlaylistResult +playlist_load_into_queue(const char *uri, SongEnumerator &e, + unsigned start_index, unsigned end_index, + playlist &dest, PlayerControl &pc, + bool secure); + +/** + * Opens a playlist with a playlist plugin and append to the specified + * play queue. + */ +PlaylistResult +playlist_open_into_queue(const char *uri, + unsigned start_index, unsigned end_index, + playlist &dest, PlayerControl &pc, + bool secure); + +#endif + diff --git a/src/playlist/PlaylistRegistry.cxx b/src/playlist/PlaylistRegistry.cxx new file mode 100644 index 000000000..94244f14c --- /dev/null +++ b/src/playlist/PlaylistRegistry.cxx @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "PlaylistRegistry.hxx" +#include "PlaylistPlugin.hxx" +#include "plugins/ExtM3uPlaylistPlugin.hxx" +#include "plugins/M3uPlaylistPlugin.hxx" +#include "plugins/XspfPlaylistPlugin.hxx" +#include "plugins/DespotifyPlaylistPlugin.hxx" +#include "plugins/SoundCloudPlaylistPlugin.hxx" +#include "plugins/PlsPlaylistPlugin.hxx" +#include "plugins/AsxPlaylistPlugin.hxx" +#include "plugins/RssPlaylistPlugin.hxx" +#include "plugins/CuePlaylistPlugin.hxx" +#include "plugins/EmbeddedCuePlaylistPlugin.hxx" +#include "InputStream.hxx" +#include "util/UriUtil.hxx" +#include "util/StringUtil.hxx" +#include "util/Error.hxx" +#include "util/Macros.hxx" +#include "ConfigGlobal.hxx" +#include "ConfigData.hxx" +#include "system/FatalError.hxx" +#include "Log.hxx" + +#include <assert.h> +#include <string.h> + +const struct playlist_plugin *const playlist_plugins[] = { + &extm3u_playlist_plugin, + &m3u_playlist_plugin, + &pls_playlist_plugin, +#ifdef HAVE_EXPAT + &xspf_playlist_plugin, + &asx_playlist_plugin, + &rss_playlist_plugin, +#endif +#ifdef ENABLE_DESPOTIFY + &despotify_playlist_plugin, +#endif +#ifdef ENABLE_SOUNDCLOUD + &soundcloud_playlist_plugin, +#endif + &cue_playlist_plugin, + &embcue_playlist_plugin, + nullptr +}; + +static constexpr unsigned n_playlist_plugins = + ARRAY_SIZE(playlist_plugins) - 1; + +/** which plugins have been initialized successfully? */ +static bool playlist_plugins_enabled[n_playlist_plugins]; + +#define playlist_plugins_for_each_enabled(plugin) \ + playlist_plugins_for_each(plugin) \ + if (playlist_plugins_enabled[playlist_plugin_iterator - playlist_plugins]) + +/** + * Find the "playlist" configuration block for the specified plugin. + * + * @param plugin_name the name of the playlist plugin + * @return the configuration block, or nullptr if none was configured + */ +static const struct config_param * +playlist_plugin_config(const char *plugin_name) +{ + const struct config_param *param = nullptr; + + assert(plugin_name != nullptr); + + while ((param = config_get_next_param(CONF_PLAYLIST_PLUGIN, param)) != nullptr) { + const char *name = param->GetBlockValue("name"); + if (name == nullptr) + FormatFatalError("playlist configuration without 'plugin' name in line %d", + param->line); + + if (strcmp(name, plugin_name) == 0) + return param; + } + + return nullptr; +} + +void +playlist_list_global_init(void) +{ + const config_param empty; + + for (unsigned i = 0; playlist_plugins[i] != nullptr; ++i) { + const struct playlist_plugin *plugin = playlist_plugins[i]; + const struct config_param *param = + playlist_plugin_config(plugin->name); + if (param == nullptr) + param = ∅ + else if (!param->GetBlockValue("enabled", true)) + /* the plugin is disabled in mpd.conf */ + continue; + + playlist_plugins_enabled[i] = + playlist_plugin_init(playlist_plugins[i], *param); + } +} + +void +playlist_list_global_finish(void) +{ + playlist_plugins_for_each_enabled(plugin) + playlist_plugin_finish(plugin); +} + +static SongEnumerator * +playlist_list_open_uri_scheme(const char *uri, Mutex &mutex, Cond &cond, + bool *tried) +{ + SongEnumerator *playlist = nullptr; + + assert(uri != nullptr); + + const auto scheme = uri_get_scheme(uri); + if (scheme.empty()) + return nullptr; + + for (unsigned i = 0; playlist_plugins[i] != nullptr; ++i) { + const struct playlist_plugin *plugin = playlist_plugins[i]; + + assert(!tried[i]); + + if (playlist_plugins_enabled[i] && plugin->open_uri != nullptr && + plugin->schemes != nullptr && + string_array_contains(plugin->schemes, scheme.c_str())) { + playlist = playlist_plugin_open_uri(plugin, uri, + mutex, cond); + if (playlist != nullptr) + break; + + tried[i] = true; + } + } + + return playlist; +} + +static SongEnumerator * +playlist_list_open_uri_suffix(const char *uri, Mutex &mutex, Cond &cond, + const bool *tried) +{ + const char *suffix; + SongEnumerator *playlist = nullptr; + + assert(uri != nullptr); + + suffix = uri_get_suffix(uri); + if (suffix == nullptr) + return nullptr; + + for (unsigned i = 0; playlist_plugins[i] != nullptr; ++i) { + const struct playlist_plugin *plugin = playlist_plugins[i]; + + if (playlist_plugins_enabled[i] && !tried[i] && + plugin->open_uri != nullptr && plugin->suffixes != nullptr && + string_array_contains(plugin->suffixes, suffix)) { + playlist = playlist_plugin_open_uri(plugin, uri, + mutex, cond); + if (playlist != nullptr) + break; + } + } + + return playlist; +} + +SongEnumerator * +playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond) +{ + /** this array tracks which plugins have already been tried by + playlist_list_open_uri_scheme() */ + bool tried[n_playlist_plugins]; + + assert(uri != nullptr); + + memset(tried, false, sizeof(tried)); + + auto playlist = playlist_list_open_uri_scheme(uri, mutex, cond, tried); + if (playlist == nullptr) + playlist = playlist_list_open_uri_suffix(uri, mutex, cond, + tried); + + return playlist; +} + +static SongEnumerator * +playlist_list_open_stream_mime2(InputStream &is, const char *mime) +{ + assert(mime != nullptr); + + playlist_plugins_for_each_enabled(plugin) { + if (plugin->open_stream != nullptr && + plugin->mime_types != nullptr && + string_array_contains(plugin->mime_types, mime)) { + /* rewind the stream, so each plugin gets a + fresh start */ + is.Rewind(IgnoreError()); + + auto playlist = playlist_plugin_open_stream(plugin, + is); + if (playlist != nullptr) + return playlist; + } + } + + return nullptr; +} + +static SongEnumerator * +playlist_list_open_stream_mime(InputStream &is, const char *full_mime) +{ + assert(full_mime != nullptr); + + const char *semicolon = strchr(full_mime, ';'); + if (semicolon == nullptr) + return playlist_list_open_stream_mime2(is, full_mime); + + if (semicolon == full_mime) + return nullptr; + + /* probe only the portion before the semicolon*/ + const std::string mime(full_mime, semicolon); + return playlist_list_open_stream_mime2(is, mime.c_str()); +} + +static SongEnumerator * +playlist_list_open_stream_suffix(InputStream &is, const char *suffix) +{ + assert(suffix != nullptr); + + playlist_plugins_for_each_enabled(plugin) { + if (plugin->open_stream != nullptr && + plugin->suffixes != nullptr && + string_array_contains(plugin->suffixes, suffix)) { + /* rewind the stream, so each plugin gets a + fresh start */ + is.Rewind(IgnoreError()); + + auto playlist = playlist_plugin_open_stream(plugin, is); + if (playlist != nullptr) + return playlist; + } + } + + return nullptr; +} + +SongEnumerator * +playlist_list_open_stream(InputStream &is, const char *uri) +{ + assert(is.ready); + + const char *const mime = is.GetMimeType(); + if (mime != nullptr) { + auto playlist = playlist_list_open_stream_mime(is, mime); + if (playlist != nullptr) + return playlist; + } + + const char *suffix = uri != nullptr ? uri_get_suffix(uri) : nullptr; + if (suffix != nullptr) { + auto playlist = playlist_list_open_stream_suffix(is, suffix); + if (playlist != nullptr) + return playlist; + } + + return nullptr; +} + +bool +playlist_suffix_supported(const char *suffix) +{ + assert(suffix != nullptr); + + playlist_plugins_for_each_enabled(plugin) { + if (plugin->suffixes != nullptr && + string_array_contains(plugin->suffixes, suffix)) + return true; + } + + return false; +} + +SongEnumerator * +playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, + InputStream **is_r) +{ + const char *suffix; + + assert(path_fs != nullptr); + + suffix = uri_get_suffix(path_fs); + if (suffix == nullptr || !playlist_suffix_supported(suffix)) + return nullptr; + + Error error; + InputStream *is = InputStream::OpenReady(path_fs, mutex, cond, error); + if (is == nullptr) { + if (error.IsDefined()) + LogError(error); + + return nullptr; + } + + auto playlist = playlist_list_open_stream_suffix(*is, suffix); + if (playlist != nullptr) + *is_r = is; + else + is->Close(); + + return playlist; +} diff --git a/src/playlist/PlaylistRegistry.hxx b/src/playlist/PlaylistRegistry.hxx new file mode 100644 index 000000000..0079fa68e --- /dev/null +++ b/src/playlist/PlaylistRegistry.hxx @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST_REGISTRY_HXX +#define MPD_PLAYLIST_REGISTRY_HXX + +class Mutex; +class Cond; +class SongEnumerator; +struct InputStream; + +extern const struct playlist_plugin *const playlist_plugins[]; + +#define playlist_plugins_for_each(plugin) \ + for (const struct playlist_plugin *plugin, \ + *const*playlist_plugin_iterator = &playlist_plugins[0]; \ + (plugin = *playlist_plugin_iterator) != nullptr; \ + ++playlist_plugin_iterator) + +/** + * Initializes all playlist plugins. + */ +void +playlist_list_global_init(void); + +/** + * Deinitializes all playlist plugins. + */ +void +playlist_list_global_finish(void); + +/** + * Opens a playlist by its URI. + */ +SongEnumerator * +playlist_list_open_uri(const char *uri, Mutex &mutex, Cond &cond); + +/** + * Opens a playlist from an input stream. + * + * @param is an #input_stream object which is open and ready + * @param uri optional URI which was used to open the stream; may be + * used to select the appropriate playlist plugin + */ +SongEnumerator * +playlist_list_open_stream(InputStream &is, const char *uri); + +/** + * Determines if there is a playlist plugin which can handle the + * specified file name suffix. + */ +bool +playlist_suffix_supported(const char *suffix); + +/** + * Opens a playlist from a local file. + * + * @param path_fs the path of the playlist file + * @param is_r on success, an input_stream object is returned here, + * which must be closed after the playlist_provider object is freed + * @return a playlist, or nullptr on error + */ +SongEnumerator * +playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, + InputStream **is_r); + +#endif diff --git a/src/playlist/PlaylistSong.cxx b/src/playlist/PlaylistSong.cxx new file mode 100644 index 000000000..bcbdc30be --- /dev/null +++ b/src/playlist/PlaylistSong.cxx @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "PlaylistSong.hxx" +#include "Mapper.hxx" +#include "DatabaseSong.hxx" +#include "ls.hxx" +#include "tag/Tag.hxx" +#include "tag/TagBuilder.hxx" +#include "fs/AllocatedPath.hxx" +#include "fs/Traits.hxx" +#include "util/UriUtil.hxx" +#include "util/Error.hxx" +#include "DetachedSong.hxx" + +#include <assert.h> +#include <string.h> + +static void +merge_song_metadata(DetachedSong &add, const DetachedSong &base) +{ + { + TagBuilder builder(add.GetTag()); + builder.Complement(base.GetTag()); + add.SetTag(builder.Commit()); + } + + add.SetLastModified(base.GetLastModified()); +} + +static void +apply_song_metadata(DetachedSong &dest, const DetachedSong &src) +{ + if (!src.GetTag().IsDefined() && + src.GetStartMS() == 0 && src.GetEndMS() == 0) + return; + + merge_song_metadata(dest, src); + + if (dest.GetTag().IsDefined() && dest.GetTag().time > 0 && + src.GetStartMS() > 0 && src.GetEndMS() == 0 && + src.GetStartMS() / 1000 < (unsigned)dest.GetTag().time) + /* the range is open-ended, and the playlist plugin + did not know the total length of the song file + (e.g. last track on a CUE file); fix it up here */ + dest.WritableTag().time = + dest.GetTag().time - src.GetStartMS() / 1000; +} + +static bool +playlist_check_load_song(DetachedSong &song) +{ + const char *const uri = song.GetURI(); + + if (uri_has_scheme(uri)) { + return true; + } else if (PathTraitsUTF8::IsAbsolute(uri)) { + DetachedSong tmp(uri); + if (!tmp.Update()) + return false; + + apply_song_metadata(song, tmp); + return true; + } else { + DetachedSong *tmp = DatabaseDetachSong(uri, IgnoreError()); + if (tmp == nullptr) + return false; + + apply_song_metadata(song, *tmp); + delete tmp; + return true; + } +} + +bool +playlist_check_translate_song(DetachedSong &song, const char *base_uri, + bool secure) +{ + const char *const uri = song.GetURI(); + + if (uri_has_scheme(uri)) + /* valid remote song? */ + return uri_supported_scheme(uri); + + if (base_uri != nullptr && strcmp(base_uri, ".") == 0) + /* PathTraitsUTF8::GetParent() returns "." when there + is no directory name in the given path; clear that + now, because it would break the database lookup + functions */ + base_uri = nullptr; + + if (PathTraitsUTF8::IsAbsolute(uri)) { + /* XXX fs_charset vs utf8? */ + const char *suffix = map_to_relative_path(uri); + assert(suffix != nullptr); + + if (suffix != uri) + song.SetURI(std::string(suffix)); + else if (!secure) + /* local files must be relative to the music + directory when "secure" is enabled */ + return false; + + base_uri = nullptr; + } + + if (base_uri != nullptr) { + song.SetURI(PathTraitsUTF8::Build(base_uri, uri)); + /* repeat the above checks */ + return playlist_check_translate_song(song, nullptr, secure); + } + + return playlist_check_load_song(song); +} diff --git a/src/playlist/PlaylistSong.hxx b/src/playlist/PlaylistSong.hxx new file mode 100644 index 000000000..2a47b28db --- /dev/null +++ b/src/playlist/PlaylistSong.hxx @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST_SONG_HXX +#define MPD_PLAYLIST_SONG_HXX + +class DetachedSong; + +/** + * Verifies the song, returns false if it is unsafe. Translate the + * song to a song within the database, if it is a local file. + * + * @param secure if true, then local files are only allowed if they + * are relative to base_uri + * @return true on success, false if the song should not be used + */ +bool +playlist_check_translate_song(DetachedSong &song, const char *base_uri, + bool secure); + +#endif diff --git a/src/playlist/Print.cxx b/src/playlist/Print.cxx new file mode 100644 index 000000000..7f13d5544 --- /dev/null +++ b/src/playlist/Print.cxx @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#include "config.h" +#include "Print.hxx" +#include "PlaylistAny.hxx" +#include "PlaylistSong.hxx" +#include "SongEnumerator.hxx" +#include "SongPrint.hxx" +#include "InputStream.hxx" +#include "DetachedSong.hxx" +#include "fs/Traits.hxx" +#include "thread/Cond.hxx" + +static void +playlist_provider_print(Client &client, const char *uri, + SongEnumerator &e, bool detail) +{ + const std::string base_uri = uri != nullptr + ? PathTraitsUTF8::GetParent(uri) + : std::string("."); + + DetachedSong *song; + while ((song = e.NextSong()) != nullptr) { + if (playlist_check_translate_song(*song, base_uri.c_str(), + false)) { + if (detail) + song_print_info(client, *song); + else + song_print_uri(client, *song); + } + + delete song; + } +} + +bool +playlist_file_print(Client &client, const char *uri, bool detail) +{ + Mutex mutex; + Cond cond; + + InputStream *is; + SongEnumerator *playlist = playlist_open_any(uri, mutex, cond, &is); + if (playlist == nullptr) + return false; + + playlist_provider_print(client, uri, *playlist, detail); + delete playlist; + + if (is != nullptr) + is->Close(); + + return true; +} diff --git a/src/playlist/Print.hxx b/src/playlist/Print.hxx new file mode 100644 index 000000000..c2fff5475 --- /dev/null +++ b/src/playlist/Print.hxx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003-2014 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_PLAYLIST__PRINT_HXX +#define MPD_PLAYLIST__PRINT_HXX + +class Client; + +/** + * Send the playlist file to the client. + * + * @param client the client which requested the playlist + * @param uri the URI of the playlist file in UTF-8 encoding + * @param detail true if all details should be printed + * @return true on success, false if the playlist does not exist + */ +bool +playlist_file_print(Client &client, const char *uri, bool detail); + +#endif diff --git a/src/playlist/SongEnumerator.hxx b/src/playlist/SongEnumerator.hxx new file mode 100644 index 000000000..75295add1 --- /dev/null +++ b/src/playlist/SongEnumerator.hxx @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2014 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 + +class DetachedSong; + +/** + * 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 DetachedSong *NextSong() = 0; +}; + +#endif diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/plugins/AsxPlaylistPlugin.cxx index 24eb26077..5434c8e85 100644 --- a/src/playlist/AsxPlaylistPlugin.cxx +++ b/src/playlist/plugins/AsxPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "AsxPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "tag/TagBuilder.hxx" #include "util/ASCII.hxx" #include "util/Error.hxx" diff --git a/src/playlist/AsxPlaylistPlugin.hxx b/src/playlist/plugins/AsxPlaylistPlugin.hxx index 63371be0f..63371be0f 100644 --- a/src/playlist/AsxPlaylistPlugin.hxx +++ b/src/playlist/plugins/AsxPlaylistPlugin.hxx diff --git a/src/playlist/CuePlaylistPlugin.cxx b/src/playlist/plugins/CuePlaylistPlugin.cxx index 505c0c5d8..d52d41c07 100644 --- a/src/playlist/CuePlaylistPlugin.cxx +++ b/src/playlist/plugins/CuePlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "CuePlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "SongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../SongEnumerator.hxx" #include "cue/CueParser.hxx" #include "TextInputStream.hxx" diff --git a/src/playlist/CuePlaylistPlugin.hxx b/src/playlist/plugins/CuePlaylistPlugin.hxx index 4d833bfc2..4d833bfc2 100644 --- a/src/playlist/CuePlaylistPlugin.hxx +++ b/src/playlist/plugins/CuePlaylistPlugin.hxx diff --git a/src/playlist/DespotifyPlaylistPlugin.cxx b/src/playlist/plugins/DespotifyPlaylistPlugin.cxx index 7d73a64bc..1e8de0130 100644 --- a/src/playlist/DespotifyPlaylistPlugin.cxx +++ b/src/playlist/plugins/DespotifyPlaylistPlugin.cxx @@ -20,8 +20,8 @@ #include "config.h" #include "DespotifyPlaylistPlugin.hxx" #include "DespotifyUtils.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "tag/Tag.hxx" #include "DetachedSong.hxx" #include "Log.hxx" diff --git a/src/playlist/DespotifyPlaylistPlugin.hxx b/src/playlist/plugins/DespotifyPlaylistPlugin.hxx index 6acfd40f4..6acfd40f4 100644 --- a/src/playlist/DespotifyPlaylistPlugin.hxx +++ b/src/playlist/plugins/DespotifyPlaylistPlugin.hxx diff --git a/src/playlist/EmbeddedCuePlaylistPlugin.cxx b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx index 4d9eb4b9b..53f3feda0 100644 --- a/src/playlist/EmbeddedCuePlaylistPlugin.cxx +++ b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx @@ -25,8 +25,8 @@ #include "config.h" #include "EmbeddedCuePlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "SongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../SongEnumerator.hxx" #include "tag/TagHandler.hxx" #include "tag/TagId3.hxx" #include "tag/ApeTag.hxx" diff --git a/src/playlist/EmbeddedCuePlaylistPlugin.hxx b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx index 5eedf3f13..5eedf3f13 100644 --- a/src/playlist/EmbeddedCuePlaylistPlugin.hxx +++ b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx diff --git a/src/playlist/ExtM3uPlaylistPlugin.cxx b/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx index 1a975c081..ac27fb136 100644 --- a/src/playlist/ExtM3uPlaylistPlugin.cxx +++ b/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "ExtM3uPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "SongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../SongEnumerator.hxx" #include "DetachedSong.hxx" #include "tag/Tag.hxx" #include "tag/TagBuilder.hxx" diff --git a/src/playlist/ExtM3uPlaylistPlugin.hxx b/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx index 5743ded43..5743ded43 100644 --- a/src/playlist/ExtM3uPlaylistPlugin.hxx +++ b/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx diff --git a/src/playlist/M3uPlaylistPlugin.cxx b/src/playlist/plugins/M3uPlaylistPlugin.cxx index fe7d8a17f..a87e3edc7 100644 --- a/src/playlist/M3uPlaylistPlugin.cxx +++ b/src/playlist/plugins/M3uPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "M3uPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "SongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../SongEnumerator.hxx" #include "DetachedSong.hxx" #include "util/StringUtil.hxx" #include "TextInputStream.hxx" diff --git a/src/playlist/M3uPlaylistPlugin.hxx b/src/playlist/plugins/M3uPlaylistPlugin.hxx index f1ad14069..f1ad14069 100644 --- a/src/playlist/M3uPlaylistPlugin.hxx +++ b/src/playlist/plugins/M3uPlaylistPlugin.hxx diff --git a/src/playlist/PlsPlaylistPlugin.cxx b/src/playlist/plugins/PlsPlaylistPlugin.cxx index 839098a73..0abd7172b 100644 --- a/src/playlist/PlsPlaylistPlugin.cxx +++ b/src/playlist/plugins/PlsPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "PlsPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "InputStream.hxx" #include "DetachedSong.hxx" #include "tag/TagBuilder.hxx" diff --git a/src/playlist/PlsPlaylistPlugin.hxx b/src/playlist/plugins/PlsPlaylistPlugin.hxx index 1a3f33873..1a3f33873 100644 --- a/src/playlist/PlsPlaylistPlugin.hxx +++ b/src/playlist/plugins/PlsPlaylistPlugin.hxx diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/plugins/RssPlaylistPlugin.cxx index 550a4630e..076d82f14 100644 --- a/src/playlist/RssPlaylistPlugin.cxx +++ b/src/playlist/plugins/RssPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "RssPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "tag/TagBuilder.hxx" #include "util/ASCII.hxx" #include "util/Error.hxx" diff --git a/src/playlist/RssPlaylistPlugin.hxx b/src/playlist/plugins/RssPlaylistPlugin.hxx index a00a5a898..a00a5a898 100644 --- a/src/playlist/RssPlaylistPlugin.hxx +++ b/src/playlist/plugins/RssPlaylistPlugin.hxx diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx index bf68acd3b..fac052d19 100644 --- a/src/playlist/SoundCloudPlaylistPlugin.cxx +++ b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "SoundCloudPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "ConfigData.hxx" #include "InputStream.hxx" #include "tag/TagBuilder.hxx" diff --git a/src/playlist/SoundCloudPlaylistPlugin.hxx b/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx index b355b477a..b355b477a 100644 --- a/src/playlist/SoundCloudPlaylistPlugin.hxx +++ b/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx diff --git a/src/playlist/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index e726ad338..12888b3bc 100644 --- a/src/playlist/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -19,8 +19,8 @@ #include "config.h" #include "XspfPlaylistPlugin.hxx" -#include "PlaylistPlugin.hxx" -#include "MemorySongEnumerator.hxx" +#include "../PlaylistPlugin.hxx" +#include "../MemorySongEnumerator.hxx" #include "DetachedSong.hxx" #include "InputStream.hxx" #include "tag/TagBuilder.hxx" diff --git a/src/playlist/XspfPlaylistPlugin.hxx b/src/playlist/plugins/XspfPlaylistPlugin.hxx index 6b08a6be6..6b08a6be6 100644 --- a/src/playlist/XspfPlaylistPlugin.hxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.hxx |