From 9fb351a139a56fc7b1ece549894f8fc31fa887cd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 30 Jul 2014 20:58:14 +0200 Subject: *Save, *State: use the OutputStream API instead of FILE* --- src/PlaylistDatabase.cxx | 11 +++--- src/PlaylistDatabase.hxx | 5 ++- src/SongSave.cxx | 31 +++++++++-------- src/SongSave.hxx | 7 ++-- src/StateFile.cxx | 32 ++++++++++++------ src/StateFile.hxx | 5 +++ src/TagSave.cxx | 10 +++--- src/TagSave.hxx | 5 ++- src/db/plugins/simple/DatabaseSave.cxx | 17 +++++----- src/db/plugins/simple/DatabaseSave.hxx | 5 ++- src/db/plugins/simple/DirectorySave.cxx | 23 +++++++------ src/db/plugins/simple/DirectorySave.hxx | 5 ++- src/db/plugins/simple/SimpleDatabasePlugin.cxx | 20 +++++------ src/mixer/Volume.cxx | 6 ++-- src/mixer/Volume.hxx | 6 ++-- src/output/OutputState.cxx | 7 ++-- src/output/OutputState.hxx | 6 ++-- src/queue/PlaylistState.cxx | 47 +++++++++++++------------- src/queue/PlaylistState.hxx | 5 ++- src/queue/QueueSave.cxx | 22 ++++++------ src/queue/QueueSave.hxx | 5 ++- test/dump_playlist.cxx | 11 ++++++ test/run_input.cxx | 11 ++++++ 23 files changed, 169 insertions(+), 133 deletions(-) diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx index 81aeae2cd..336a6d0e0 100644 --- a/src/PlaylistDatabase.cxx +++ b/src/PlaylistDatabase.cxx @@ -21,6 +21,7 @@ #include "PlaylistDatabase.hxx" #include "db/PlaylistVector.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "util/StringUtil.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -31,13 +32,13 @@ static constexpr Domain playlist_database_domain("playlist_database"); void -playlist_vector_save(FILE *fp, const PlaylistVector &pv) +playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv) { for (const PlaylistInfo &pi : pv) - fprintf(fp, PLAYLIST_META_BEGIN "%s\n" - "mtime: %li\n" - "playlist_end\n", - pi.name.c_str(), (long)pi.mtime); + os.Format(PLAYLIST_META_BEGIN "%s\n" + "mtime: %li\n" + "playlist_end\n", + pi.name.c_str(), (long)pi.mtime); } bool diff --git a/src/PlaylistDatabase.hxx b/src/PlaylistDatabase.hxx index 48de64efa..17f82f64b 100644 --- a/src/PlaylistDatabase.hxx +++ b/src/PlaylistDatabase.hxx @@ -22,16 +22,15 @@ #include "check.h" -#include - #define PLAYLIST_META_BEGIN "playlist_begin: " class PlaylistVector; +class BufferedOutputStream; class TextFile; class Error; void -playlist_vector_save(FILE *fp, const PlaylistVector &pv); +playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv); bool playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, diff --git a/src/SongSave.cxx b/src/SongSave.cxx index d6c1dbdd7..02a7861e5 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -23,6 +23,7 @@ #include "DetachedSong.hxx" #include "TagSave.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "tag/Tag.hxx" #include "tag/TagBuilder.hxx" #include "util/StringUtil.hxx" @@ -38,38 +39,38 @@ static constexpr Domain song_save_domain("song_save"); static void -range_save(FILE *file, unsigned start_ms, unsigned end_ms) +range_save(BufferedOutputStream &os, unsigned start_ms, unsigned end_ms) { if (end_ms > 0) - fprintf(file, "Range: %u-%u\n", start_ms, end_ms); + os.Format("Range: %u-%u\n", start_ms, end_ms); else if (start_ms > 0) - fprintf(file, "Range: %u-\n", start_ms); + os.Format("Range: %u-\n", start_ms); } void -song_save(FILE *fp, const Song &song) +song_save(BufferedOutputStream &os, const Song &song) { - fprintf(fp, SONG_BEGIN "%s\n", song.uri); + os.Format(SONG_BEGIN "%s\n", song.uri); - range_save(fp, song.start_ms, song.end_ms); + range_save(os, song.start_ms, song.end_ms); - tag_save(fp, song.tag); + tag_save(os, song.tag); - fprintf(fp, SONG_MTIME ": %li\n", (long)song.mtime); - fprintf(fp, SONG_END "\n"); + os.Format(SONG_MTIME ": %li\n", (long)song.mtime); + os.Format(SONG_END "\n"); } void -song_save(FILE *fp, const DetachedSong &song) +song_save(BufferedOutputStream &os, const DetachedSong &song) { - fprintf(fp, SONG_BEGIN "%s\n", song.GetURI()); + os.Format(SONG_BEGIN "%s\n", song.GetURI()); - range_save(fp, song.GetStartMS(), song.GetEndMS()); + range_save(os, song.GetStartMS(), song.GetEndMS()); - tag_save(fp, song.GetTag()); + tag_save(os, song.GetTag()); - fprintf(fp, SONG_MTIME ": %li\n", (long)song.GetLastModified()); - fprintf(fp, SONG_END "\n"); + os.Format(SONG_MTIME ": %li\n", (long)song.GetLastModified()); + os.Format(SONG_END "\n"); } DetachedSong * diff --git a/src/SongSave.hxx b/src/SongSave.hxx index 2a0edb49d..28c217249 100644 --- a/src/SongSave.hxx +++ b/src/SongSave.hxx @@ -20,21 +20,20 @@ #ifndef MPD_SONG_SAVE_HXX #define MPD_SONG_SAVE_HXX -#include - #define SONG_BEGIN "song_begin: " struct Song; struct Directory; class DetachedSong; +class BufferedOutputStream; class TextFile; class Error; void -song_save(FILE *fp, const Song &song); +song_save(BufferedOutputStream &os, const Song &song); void -song_save(FILE *fp, const DetachedSong &song); +song_save(BufferedOutputStream &os, const DetachedSong &song); /** * Loads a song from the input file. Reading stops after the diff --git a/src/StateFile.cxx b/src/StateFile.cxx index 0e558f298..e8df1ec0a 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -22,6 +22,8 @@ #include "output/OutputState.hxx" #include "queue/PlaylistState.hxx" #include "fs/TextFile.hxx" +#include "fs/output/FileOutputStream.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "Partition.hxx" #include "Instance.hxx" #include "mixer/Volume.hxx" @@ -62,25 +64,35 @@ StateFile::IsModified() const partition.pc); } +inline void +StateFile::Write(BufferedOutputStream &os) +{ + save_sw_volume_state(os); + audio_output_state_save(os, partition.outputs); + playlist_state_save(os, partition.playlist, partition.pc); +} + +inline bool +StateFile::Write(OutputStream &os, Error &error) +{ + BufferedOutputStream bos(os); + Write(bos); + return bos.Flush(error); +} + void StateFile::Write() { FormatDebug(state_file_domain, "Saving state file %s", path_utf8.c_str()); - FILE *fp = FOpen(path, FOpenMode::WriteText); - if (gcc_unlikely(!fp)) { - FormatErrno(state_file_domain, "failed to create %s", - path_utf8.c_str()); + Error error; + FileOutputStream fos(path, error); + if (!fos.IsDefined() || !Write(fos, error) || !fos.Commit(error)) { + LogError(error); return; } - save_sw_volume_state(fp); - audio_output_state_save(fp, partition.outputs); - playlist_state_save(fp, partition.playlist, partition.pc); - - fclose(fp); - RememberVersions(); } diff --git a/src/StateFile.hxx b/src/StateFile.hxx index e35797b95..609651c92 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -27,6 +27,8 @@ #include struct Partition; +class OutputStream; +class BufferedOutputStream; class StateFile final : private TimeoutMonitor { AllocatedPath path; @@ -53,6 +55,9 @@ public: void CheckModified(); private: + bool Write(OutputStream &os, Error &error); + void Write(BufferedOutputStream &os); + /** * Save the current state versions for use with IsModified(). */ diff --git a/src/TagSave.cxx b/src/TagSave.cxx index 7666287af..6ec562ec5 100644 --- a/src/TagSave.cxx +++ b/src/TagSave.cxx @@ -20,19 +20,19 @@ #include "config.h" #include "TagSave.hxx" #include "tag/Tag.hxx" +#include "fs/output/BufferedOutputStream.hxx" #define SONG_TIME "Time: " void -tag_save(FILE *file, const Tag &tag) +tag_save(BufferedOutputStream &os, const Tag &tag) { if (tag.time >= 0) - fprintf(file, SONG_TIME "%i\n", tag.time); + os.Format(SONG_TIME "%i\n", tag.time); if (tag.has_playlist) - fprintf(file, "Playlist: yes\n"); + os.Format("Playlist: yes\n"); for (const auto &i : tag) - fprintf(file, "%s: %s\n", - tag_item_names[i.type], i.value); + os.Format("%s: %s\n", tag_item_names[i.type], i.value); } diff --git a/src/TagSave.hxx b/src/TagSave.hxx index d209c0a16..fd4b91f98 100644 --- a/src/TagSave.hxx +++ b/src/TagSave.hxx @@ -20,11 +20,10 @@ #ifndef MPD_TAG_SAVE_HXX #define MPD_TAG_SAVE_HXX -#include - struct Tag; +class BufferedOutputStream; void -tag_save(FILE *file, const Tag &tag); +tag_save(BufferedOutputStream &os, const Tag &tag); #endif diff --git a/src/db/plugins/simple/DatabaseSave.cxx b/src/db/plugins/simple/DatabaseSave.cxx index 62034a0b8..e10d79d60 100644 --- a/src/db/plugins/simple/DatabaseSave.cxx +++ b/src/db/plugins/simple/DatabaseSave.cxx @@ -23,6 +23,7 @@ #include "db/DatabaseError.hxx" #include "Directory.hxx" #include "DirectorySave.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "fs/TextFile.hxx" #include "tag/Tag.hxx" #include "tag/TagSettings.h" @@ -49,20 +50,20 @@ static constexpr unsigned DB_FORMAT = 2; static constexpr unsigned OLDEST_DB_FORMAT = 1; void -db_save_internal(FILE *fp, const Directory &music_root) +db_save_internal(BufferedOutputStream &os, const Directory &music_root) { - fprintf(fp, "%s\n", DIRECTORY_INFO_BEGIN); - fprintf(fp, DB_FORMAT_PREFIX "%u\n", DB_FORMAT); - fprintf(fp, "%s%s\n", DIRECTORY_MPD_VERSION, VERSION); - fprintf(fp, "%s%s\n", DIRECTORY_FS_CHARSET, GetFSCharset()); + os.Format("%s\n", DIRECTORY_INFO_BEGIN); + os.Format(DB_FORMAT_PREFIX "%u\n", DB_FORMAT); + os.Format("%s%s\n", DIRECTORY_MPD_VERSION, VERSION); + os.Format("%s%s\n", DIRECTORY_FS_CHARSET, GetFSCharset()); for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) if (!ignore_tag_items[i]) - fprintf(fp, DB_TAG_PREFIX "%s\n", tag_item_names[i]); + os.Format(DB_TAG_PREFIX "%s\n", tag_item_names[i]); - fprintf(fp, "%s\n", DIRECTORY_INFO_END); + os.Format("%s\n", DIRECTORY_INFO_END); - directory_save(fp, music_root); + directory_save(os, music_root); } bool diff --git a/src/db/plugins/simple/DatabaseSave.hxx b/src/db/plugins/simple/DatabaseSave.hxx index 3bd3377ae..bb7f57115 100644 --- a/src/db/plugins/simple/DatabaseSave.hxx +++ b/src/db/plugins/simple/DatabaseSave.hxx @@ -20,14 +20,13 @@ #ifndef MPD_DATABASE_SAVE_HXX #define MPD_DATABASE_SAVE_HXX -#include - struct Directory; +class BufferedOutputStream; class TextFile; class Error; void -db_save_internal(FILE *file, const Directory &root); +db_save_internal(BufferedOutputStream &os, const Directory &root); bool db_load_internal(TextFile &file, Directory &root, Error &error); diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx index 9d3ebbac2..7e7cbc3ba 100644 --- a/src/db/plugins/simple/DirectorySave.cxx +++ b/src/db/plugins/simple/DirectorySave.cxx @@ -25,6 +25,7 @@ #include "DetachedSong.hxx" #include "PlaylistDatabase.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "util/StringUtil.hxx" #include "util/NumberParser.hxx" #include "util/Error.hxx" @@ -70,37 +71,37 @@ ParseTypeString(const char *type) } void -directory_save(FILE *fp, const Directory &directory) +directory_save(BufferedOutputStream &os, const Directory &directory) { if (!directory.IsRoot()) { const char *type = DeviceToTypeString(directory.device); if (type != nullptr) - fprintf(fp, DIRECTORY_TYPE "%s\n", type); + os.Format(DIRECTORY_TYPE "%s\n", type); if (directory.mtime != 0) - fprintf(fp, DIRECTORY_MTIME "%lu\n", - (unsigned long)directory.mtime); + os.Format(DIRECTORY_MTIME "%lu\n", + (unsigned long)directory.mtime); - fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, directory.GetPath()); + os.Format("%s%s\n", DIRECTORY_BEGIN, directory.GetPath()); } for (const auto &child : directory.children) { - fprintf(fp, DIRECTORY_DIR "%s\n", child.GetName()); + os.Format(DIRECTORY_DIR "%s\n", child.GetName()); if (!child.IsMount()) - directory_save(fp, child); + directory_save(os, child); - if (ferror(fp)) + if (!os.Check()) return; } for (const auto &song : directory.songs) - song_save(fp, song); + song_save(os, song); - playlist_vector_save(fp, directory.playlists); + playlist_vector_save(os, directory.playlists); if (!directory.IsRoot()) - fprintf(fp, DIRECTORY_END "%s\n", directory.GetPath()); + os.Format(DIRECTORY_END "%s\n", directory.GetPath()); } static bool diff --git a/src/db/plugins/simple/DirectorySave.hxx b/src/db/plugins/simple/DirectorySave.hxx index 07e9e158b..f464f9946 100644 --- a/src/db/plugins/simple/DirectorySave.hxx +++ b/src/db/plugins/simple/DirectorySave.hxx @@ -20,14 +20,13 @@ #ifndef MPD_DIRECTORY_SAVE_HXX #define MPD_DIRECTORY_SAVE_HXX -#include - struct Directory; class TextFile; +class BufferedOutputStream; class Error; void -directory_save(FILE *fp, const Directory &directory); +directory_save(BufferedOutputStream &os, const Directory &directory); bool directory_load(TextFile &file, Directory &directory, Error &error); diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx index 97d3e52df..fe712b90b 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx @@ -32,6 +32,8 @@ #include "db/DatabaseLock.hxx" #include "db/DatabaseError.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" +#include "fs/output/FileOutputStream.hxx" #include "config/ConfigData.hxx" #include "fs/FileSystem.hxx" #include "util/CharUtil.hxx" @@ -366,22 +368,16 @@ SimpleDatabase::Save(Error &error) LogDebug(simple_db_domain, "writing DB"); - FILE *fp = FOpen(path, FOpenMode::WriteText); - if (!fp) { - error.FormatErrno("unable to write to db file \"%s\"", - path_utf8.c_str()); + FileOutputStream fos(path, error); + if (!fos.IsDefined()) return false; - } - db_save_internal(fp, *root); + BufferedOutputStream bos(fos); - if (ferror(fp)) { - error.SetErrno("Failed to write to database file"); - fclose(fp); - return false; - } + db_save_internal(bos, *root); - fclose(fp); + if (!bos.Flush(error) || !fos.Commit(error)) + return false; struct stat st; if (StatFile(path, st)) diff --git a/src/mixer/Volume.cxx b/src/mixer/Volume.cxx index 596b3c12a..86ebbf422 100644 --- a/src/mixer/Volume.cxx +++ b/src/mixer/Volume.cxx @@ -24,6 +24,7 @@ #include "util/StringUtil.hxx" #include "util/Domain.hxx" #include "system/PeriodClock.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "Log.hxx" #include @@ -110,9 +111,10 @@ read_sw_volume_state(const char *line, MultipleOutputs &outputs) return true; } -void save_sw_volume_state(FILE *fp) +void +save_sw_volume_state(BufferedOutputStream &os) { - fprintf(fp, SW_VOLUME_STATE "%u\n", volume_software_set); + os.Format(SW_VOLUME_STATE "%u\n", volume_software_set); } unsigned diff --git a/src/mixer/Volume.hxx b/src/mixer/Volume.hxx index a02c21a21..d787a6415 100644 --- a/src/mixer/Volume.hxx +++ b/src/mixer/Volume.hxx @@ -22,9 +22,8 @@ #include "Compiler.h" -#include - class MultipleOutputs; +class BufferedOutputStream; void InvalidateHardwareVolume(); @@ -39,7 +38,8 @@ volume_level_change(MultipleOutputs &outputs, unsigned volume); bool read_sw_volume_state(const char *line, MultipleOutputs &outputs); -void save_sw_volume_state(FILE *fp); +void +save_sw_volume_state(BufferedOutputStream &os); /** * Generates a hash number for the current state of the software diff --git a/src/output/OutputState.cxx b/src/output/OutputState.cxx index 7f3a8da7b..0c1424404 100644 --- a/src/output/OutputState.cxx +++ b/src/output/OutputState.cxx @@ -28,6 +28,7 @@ #include "Internal.hxx" #include "Domain.hxx" #include "Log.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "util/StringUtil.hxx" #include @@ -38,13 +39,13 @@ unsigned audio_output_state_version; void -audio_output_state_save(FILE *fp, const MultipleOutputs &outputs) +audio_output_state_save(BufferedOutputStream &os, + const MultipleOutputs &outputs) { for (unsigned i = 0, n = outputs.Size(); i != n; ++i) { const AudioOutput &ao = outputs.Get(i); - fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n", - ao.enabled, ao.name); + os.Format(AUDIO_DEVICE_STATE "%d:%s\n", ao.enabled, ao.name); } } diff --git a/src/output/OutputState.hxx b/src/output/OutputState.hxx index 32f4bbcce..47f8429d5 100644 --- a/src/output/OutputState.hxx +++ b/src/output/OutputState.hxx @@ -25,15 +25,15 @@ #ifndef MPD_OUTPUT_STATE_HXX #define MPD_OUTPUT_STATE_HXX -#include - class MultipleOutputs; +class BufferedOutputStream; bool audio_output_state_read(const char *line, MultipleOutputs &outputs); void -audio_output_state_save(FILE *fp, const MultipleOutputs &outputs); +audio_output_state_save(BufferedOutputStream &os, + const MultipleOutputs &outputs); /** * Generates a version number for the current state of the audio diff --git a/src/queue/PlaylistState.cxx b/src/queue/PlaylistState.cxx index f5c798e3e..56adb2a9b 100644 --- a/src/queue/PlaylistState.cxx +++ b/src/queue/PlaylistState.cxx @@ -28,6 +28,7 @@ #include "Playlist.hxx" #include "queue/QueueSave.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "PlayerControl.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" @@ -59,47 +60,45 @@ #define PLAYLIST_BUFFER_SIZE 2*MPD_PATH_MAX void -playlist_state_save(FILE *fp, const struct playlist &playlist, +playlist_state_save(BufferedOutputStream &os, const struct playlist &playlist, PlayerControl &pc) { const auto player_status = pc.GetStatus(); - fputs(PLAYLIST_STATE_FILE_STATE, fp); + os.Write(PLAYLIST_STATE_FILE_STATE); if (playlist.playing) { switch (player_status.state) { case PlayerState::PAUSE: - fputs(PLAYLIST_STATE_FILE_STATE_PAUSE "\n", fp); + os.Write(PLAYLIST_STATE_FILE_STATE_PAUSE "\n"); break; default: - fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp); + os.Write(PLAYLIST_STATE_FILE_STATE_PLAY "\n"); } - fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", - playlist.queue.OrderToPosition(playlist.current)); - fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n", - (int)player_status.elapsed_time); + os.Format(PLAYLIST_STATE_FILE_CURRENT "%i\n", + playlist.queue.OrderToPosition(playlist.current)); + os.Format(PLAYLIST_STATE_FILE_TIME "%i\n", + (int)player_status.elapsed_time); } else { - fputs(PLAYLIST_STATE_FILE_STATE_STOP "\n", fp); + os.Write(PLAYLIST_STATE_FILE_STATE_STOP "\n"); if (playlist.current >= 0) - fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", + os.Format(PLAYLIST_STATE_FILE_CURRENT "%i\n", playlist.queue.OrderToPosition(playlist.current)); } - fprintf(fp, PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist.queue.random); - fprintf(fp, PLAYLIST_STATE_FILE_REPEAT "%i\n", playlist.queue.repeat); - fprintf(fp, PLAYLIST_STATE_FILE_SINGLE "%i\n", playlist.queue.single); - fprintf(fp, PLAYLIST_STATE_FILE_CONSUME "%i\n", - playlist.queue.consume); - fprintf(fp, PLAYLIST_STATE_FILE_CROSSFADE "%i\n", - (int)pc.GetCrossFade()); - fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDB "%f\n", - pc.GetMixRampDb()); - fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDELAY "%f\n", - pc.GetMixRampDelay()); - fputs(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "\n", fp); - queue_save(fp, playlist.queue); - fputs(PLAYLIST_STATE_FILE_PLAYLIST_END "\n", fp); + os.Format(PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist.queue.random); + os.Format(PLAYLIST_STATE_FILE_REPEAT "%i\n", playlist.queue.repeat); + os.Format(PLAYLIST_STATE_FILE_SINGLE "%i\n", playlist.queue.single); + os.Format(PLAYLIST_STATE_FILE_CONSUME "%i\n", playlist.queue.consume); + os.Format(PLAYLIST_STATE_FILE_CROSSFADE "%i\n", + (int)pc.GetCrossFade()); + os.Format(PLAYLIST_STATE_FILE_MIXRAMPDB "%f\n", pc.GetMixRampDb()); + os.Format(PLAYLIST_STATE_FILE_MIXRAMPDELAY "%f\n", + pc.GetMixRampDelay()); + os.Write(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "\n"); + queue_save(os, playlist.queue); + os.Write(PLAYLIST_STATE_FILE_PLAYLIST_END "\n"); } static void diff --git a/src/queue/PlaylistState.hxx b/src/queue/PlaylistState.hxx index 8d3f88ae2..3211b1178 100644 --- a/src/queue/PlaylistState.hxx +++ b/src/queue/PlaylistState.hxx @@ -25,15 +25,14 @@ #ifndef MPD_PLAYLIST_STATE_HXX #define MPD_PLAYLIST_STATE_HXX -#include - struct playlist; struct PlayerControl; class TextFile; +class BufferedOutputStream; class SongLoader; void -playlist_state_save(FILE *fp, const playlist &playlist, +playlist_state_save(BufferedOutputStream &os, const playlist &playlist, PlayerControl &pc); bool diff --git a/src/queue/QueueSave.cxx b/src/queue/QueueSave.cxx index 5f47a0fac..eca906421 100644 --- a/src/queue/QueueSave.cxx +++ b/src/queue/QueueSave.cxx @@ -26,6 +26,7 @@ #include "SongLoader.hxx" #include "playlist/PlaylistSong.hxx" #include "fs/TextFile.hxx" +#include "fs/output/BufferedOutputStream.hxx" #include "util/StringUtil.hxx" #include "util/Error.hxx" #include "fs/Traits.hxx" @@ -36,40 +37,41 @@ #define PRIO_LABEL "Prio: " static void -queue_save_database_song(FILE *fp, int idx, const DetachedSong &song) +queue_save_database_song(BufferedOutputStream &os, + int idx, const DetachedSong &song) { - fprintf(fp, "%i:%s\n", idx, song.GetURI()); + os.Format("%i:%s\n", idx, song.GetURI()); } static void -queue_save_full_song(FILE *fp, const DetachedSong &song) +queue_save_full_song(BufferedOutputStream &os, const DetachedSong &song) { - song_save(fp, song); + song_save(os, song); } static void -queue_save_song(FILE *fp, int idx, const DetachedSong &song) +queue_save_song(BufferedOutputStream &os, int idx, const DetachedSong &song) { if (song.IsInDatabase() && song.GetStartMS() == 0 && song.GetEndMS() == 0) /* use the brief format (just the URI) for "full" database songs */ - queue_save_database_song(fp, idx, song); + queue_save_database_song(os, idx, song); else /* use the long format (URI, range, tags) for the rest, so all metadata survives a MPD restart */ - queue_save_full_song(fp, song); + queue_save_full_song(os, song); } void -queue_save(FILE *fp, const Queue &queue) +queue_save(BufferedOutputStream &os, const Queue &queue) { for (unsigned i = 0; i < queue.GetLength(); i++) { uint8_t prio = queue.GetPriorityAtPosition(i); if (prio != 0) - fprintf(fp, PRIO_LABEL "%u\n", prio); + os.Format(PRIO_LABEL "%u\n", prio); - queue_save_song(fp, i, queue.Get(i)); + queue_save_song(os, i, queue.Get(i)); } } diff --git a/src/queue/QueueSave.hxx b/src/queue/QueueSave.hxx index 470823a24..3fb4dc1a6 100644 --- a/src/queue/QueueSave.hxx +++ b/src/queue/QueueSave.hxx @@ -25,14 +25,13 @@ #ifndef MPD_QUEUE_SAVE_HXX #define MPD_QUEUE_SAVE_HXX -#include - struct Queue; +class BufferedOutputStream; class TextFile; class SongLoader; void -queue_save(FILE *fp, const Queue &queue); +queue_save(BufferedOutputStream &os, const Queue &queue); /** * Loads one song from the state file and appends it to the queue. diff --git a/test/dump_playlist.cxx b/test/dump_playlist.cxx index 5928c8eb4..1d497535c 100644 --- a/test/dump_playlist.cxx +++ b/test/dump_playlist.cxx @@ -29,6 +29,8 @@ #include "playlist/PlaylistRegistry.hxx" #include "playlist/PlaylistPlugin.hxx" #include "fs/Path.hxx" +#include "fs/output/BufferedOutputStream.hxx" +#include "fs/output/StdioOutputStream.hxx" #include "util/Error.hxx" #include "thread/Cond.hxx" #include "Log.hxx" @@ -40,6 +42,15 @@ #include #include +static void +tag_save(FILE *file, const Tag &tag) +{ + StdioOutputStream sos(file); + BufferedOutputStream bos(sos); + tag_save(bos, tag); + bos.Flush(); +} + int main(int argc, char **argv) { const char *uri; diff --git a/test/run_input.cxx b/test/run_input.cxx index 130d0f031..f53711cc9 100644 --- a/test/run_input.cxx +++ b/test/run_input.cxx @@ -28,6 +28,8 @@ #include "util/Error.hxx" #include "thread/Cond.hxx" #include "Log.hxx" +#include "fs/output/BufferedOutputStream.hxx" +#include "fs/output/StdioOutputStream.hxx" #ifdef ENABLE_ARCHIVE #include "archive/ArchiveList.hxx" @@ -40,6 +42,15 @@ #include #include +static void +tag_save(FILE *file, const Tag &tag) +{ + StdioOutputStream sos(file); + BufferedOutputStream bos(sos); + tag_save(bos, tag); + bos.Flush(); +} + static int dump_input_stream(InputStream *is) { -- cgit v1.2.3