Commit 258ecb76 authored by Max Kellermann's avatar Max Kellermann

PlaylistFile: add class PlaylistFileEditor

parent 6f595e9a
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include "config/Defaults.hxx" #include "config/Defaults.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include "fs/Limits.hxx" #include "fs/Limits.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/Traits.hxx" #include "fs/Traits.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "fs/FileInfo.hxx" #include "fs/FileInfo.hxx"
...@@ -173,11 +172,8 @@ ListPlaylistFiles() ...@@ -173,11 +172,8 @@ ListPlaylistFiles()
} }
static void static void
SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path) SavePlaylistFile(Path path_fs, const PlaylistFileContents &contents)
{ {
assert(utf8path != nullptr);
const auto path_fs = spl_map_to_fs(utf8path);
assert(!path_fs.IsNull()); assert(!path_fs.IsNull());
FileOutputStream fos(path_fs); FileOutputStream fos(path_fs);
...@@ -191,12 +187,11 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path) ...@@ -191,12 +187,11 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path)
fos.Commit(); fos.Commit();
} }
PlaylistFileContents static PlaylistFileContents
LoadPlaylistFile(const char *utf8path) LoadPlaylistFile(Path path_fs)
try { try {
PlaylistFileContents contents; PlaylistFileContents contents;
const auto path_fs = spl_map_to_fs(utf8path);
assert(!path_fs.IsNull()); assert(!path_fs.IsNull());
TextFile file(path_fs); TextFile file(path_fs);
...@@ -251,16 +246,31 @@ try { ...@@ -251,16 +246,31 @@ try {
throw; throw;
} }
void static PlaylistFileContents
spl_move_index(const char *utf8path, unsigned src, unsigned dest) MaybeLoadPlaylistFile(Path path_fs, PlaylistFileEditor::LoadMode load_mode)
{ try {
if (src == dest) if (load_mode == PlaylistFileEditor::LoadMode::NO)
/* this doesn't check whether the playlist exists, but return {};
what the hell.. */
return;
auto contents = LoadPlaylistFile(utf8path); return LoadPlaylistFile(path_fs);
} catch (const PlaylistError &error) {
if (error.GetCode() == PlaylistResult::NO_SUCH_LIST &&
load_mode == PlaylistFileEditor::LoadMode::TRY)
return {};
throw;
}
PlaylistFileEditor::PlaylistFileEditor(const char *name_utf8,
LoadMode load_mode)
:path(spl_map_to_fs(name_utf8)),
contents(MaybeLoadPlaylistFile(path, load_mode))
{
}
void
PlaylistFileEditor::MoveIndex(unsigned src, unsigned dest)
{
if (src >= contents.size() || dest >= contents.size()) if (src >= contents.size() || dest >= contents.size())
throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range"); throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range");
...@@ -270,13 +280,38 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest) ...@@ -270,13 +280,38 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest)
const auto dest_i = std::next(contents.begin(), dest); const auto dest_i = std::next(contents.begin(), dest);
contents.insert(dest_i, std::move(value)); contents.insert(dest_i, std::move(value));
}
SavePlaylistFile(contents, utf8path); void
PlaylistFileEditor::RemoveIndex(unsigned i)
{
if (i >= contents.size())
throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range");
contents.erase(std::next(contents.begin(), i));
}
void
PlaylistFileEditor::Save()
{
SavePlaylistFile(path, contents);
idle_add(IDLE_STORED_PLAYLIST); idle_add(IDLE_STORED_PLAYLIST);
} }
void void
spl_move_index(const char *utf8path, unsigned src, unsigned dest)
{
if (src == dest)
/* this doesn't check whether the playlist exists, but
what the hell.. */
return;
PlaylistFileEditor editor(utf8path, PlaylistFileEditor::LoadMode::YES);
editor.MoveIndex(src, dest);
editor.Save();
}
void
spl_clear(const char *utf8path) spl_clear(const char *utf8path)
{ {
const auto path_fs = spl_map_to_fs(utf8path); const auto path_fs = spl_map_to_fs(utf8path);
...@@ -317,15 +352,9 @@ spl_delete(const char *name_utf8) ...@@ -317,15 +352,9 @@ spl_delete(const char *name_utf8)
void void
spl_remove_index(const char *utf8path, unsigned pos) spl_remove_index(const char *utf8path, unsigned pos)
{ {
auto contents = LoadPlaylistFile(utf8path); PlaylistFileEditor editor(utf8path, PlaylistFileEditor::LoadMode::YES);
editor.RemoveIndex(pos);
if (pos >= contents.size()) editor.Save();
throw PlaylistError(PlaylistResult::BAD_RANGE, "Bad range");
contents.erase(std::next(contents.begin(), pos));
SavePlaylistFile(contents, utf8path);
idle_add(IDLE_STORED_PLAYLIST);
} }
void void
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef MPD_PLAYLIST_FILE_HXX #ifndef MPD_PLAYLIST_FILE_HXX
#define MPD_PLAYLIST_FILE_HXX #define MPD_PLAYLIST_FILE_HXX
#include "fs/AllocatedPath.hxx"
#include <vector> #include <vector>
#include <string> #include <string>
...@@ -27,12 +29,37 @@ struct ConfigData; ...@@ -27,12 +29,37 @@ struct ConfigData;
class DetachedSong; class DetachedSong;
class SongLoader; class SongLoader;
class PlaylistVector; class PlaylistVector;
class AllocatedPath;
typedef std::vector<std::string> PlaylistFileContents; typedef std::vector<std::string> PlaylistFileContents;
extern bool playlist_saveAbsolutePaths; extern bool playlist_saveAbsolutePaths;
class PlaylistFileEditor {
const AllocatedPath path;
PlaylistFileContents contents;
public:
enum class LoadMode {
NO,
YES,
TRY,
};
/**
* Throws on error.
*/
explicit PlaylistFileEditor(const char *name_utf8, LoadMode load_mode);
void MoveIndex(unsigned src, unsigned dest);
void RemoveIndex(unsigned i);
void Save();
private:
void Load();
};
/** /**
* Perform some global initialization, e.g. load configuration values. * Perform some global initialization, e.g. load configuration values.
*/ */
...@@ -55,9 +82,6 @@ spl_map_to_fs(const char *name_utf8); ...@@ -55,9 +82,6 @@ spl_map_to_fs(const char *name_utf8);
PlaylistVector PlaylistVector
ListPlaylistFiles(); ListPlaylistFiles();
PlaylistFileContents
LoadPlaylistFile(const char *utf8path);
void void
spl_move_index(const char *utf8path, unsigned src, unsigned dest); spl_move_index(const char *utf8path, unsigned src, unsigned dest);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment