From c729f16dcdd37dd7a528ef8cb531f2e72aea12d6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 18 Feb 2021 21:59:47 +0100 Subject: [PATCH] song/DetachedSong: copy the AudioFormat from LightSong Enables the "Format" row in "playlistinfo" responses. https://github.com/MusicPlayerDaemon/MPD/issues/1094 --- NEWS | 1 + src/SongPrint.cxx | 3 +++ src/SongSave.cxx | 15 ++++++--------- src/SongSave.hxx | 3 +-- src/SongUpdate.cxx | 9 +++++++-- src/db/plugins/simple/DirectorySave.cxx | 5 +---- src/db/plugins/simple/Song.cxx | 1 + src/playlist/PlaylistSong.cxx | 3 +++ src/song/DetachedSong.cxx | 3 ++- src/song/DetachedSong.hxx | 15 +++++++++++++++ 10 files changed, 40 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index cccbc603a..55cd628da 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.23 (not yet released) * protocol - new command "getvol" + - show the audio format in "playlistinfo" * output - snapcast: new plugin diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx index 5ad300081..d6e18e77a 100644 --- a/src/SongPrint.cxx +++ b/src/SongPrint.cxx @@ -111,6 +111,9 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept if (!IsNegative(song.GetLastModified())) time_print(r, "Last-Modified", song.GetLastModified()); + if (const auto &f = song.GetAudioFormat(); f.IsDefined()) + r.Format("Format: %s\n", ToString(f).c_str()); + tag_print_values(r, song.GetTag()); const auto duration = song.GetDuration(); diff --git a/src/SongSave.cxx b/src/SongSave.cxx index 5c18948eb..af207c55f 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -86,8 +86,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song) DetachedSong song_load(TextFile &file, const char *uri, - std::string *target_r, - AudioFormat *audio_format_r) + std::string *target_r) { DetachedSong song(uri); @@ -113,13 +112,11 @@ song_load(TextFile &file, const char *uri, if (target_r != nullptr) *target_r = value; } else if (StringIsEqual(line, "Format")) { - if (audio_format_r != nullptr) { - try { - *audio_format_r = - ParseAudioFormat(value, false); - } catch (...) { - /* ignore parser errors */ - } + try { + song.SetAudioFormat(ParseAudioFormat(value, + false)); + } catch (...) { + /* ignore parser errors */ } } else if (StringIsEqual(line, "Playlist")) { tag.SetHasPlaylist(StringIsEqual(value, "yes")); diff --git a/src/SongSave.hxx b/src/SongSave.hxx index d6353f1a5..4aa9be870 100644 --- a/src/SongSave.hxx +++ b/src/SongSave.hxx @@ -44,7 +44,6 @@ song_save(BufferedOutputStream &os, const DetachedSong &song); */ DetachedSong song_load(TextFile &file, const char *uri, - std::string *target_r=nullptr, - AudioFormat *audio_format_r=nullptr); + std::string *target_r=nullptr); #endif diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx index fab7d9717..4b61d0a7b 100644 --- a/src/SongUpdate.cxx +++ b/src/SongUpdate.cxx @@ -153,9 +153,10 @@ DetachedSong::LoadFile(Path path) return false; TagBuilder tag_builder; + auto new_audio_format = AudioFormat::Undefined(); try { - if (!ScanFileTagsWithGeneric(path, tag_builder)) + if (!ScanFileTagsWithGeneric(path, tag_builder, &new_audio_format)) return false; } catch (...) { // TODO: log or propagate I/O errors? @@ -163,6 +164,7 @@ DetachedSong::LoadFile(Path path) } mtime = fi.GetModificationTime(); + audio_format = new_audio_format; tag_builder.Commit(tag); return true; } @@ -177,9 +179,11 @@ DetachedSong::Update() return LoadFile(path_fs); } else if (IsRemote()) { TagBuilder tag_builder; + auto new_audio_format = AudioFormat::Undefined(); try { - if (!tag_stream_scan(uri.c_str(), tag_builder)) + if (!tag_stream_scan(uri.c_str(), tag_builder, + &new_audio_format)) return false; } catch (...) { // TODO: log or propagate I/O errors? @@ -187,6 +191,7 @@ DetachedSong::Update() } mtime = std::chrono::system_clock::time_point::min(); + audio_format = new_audio_format; tag_builder.Commit(tag); return true; } else diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx index 71e9caaeb..adcd15f84 100644 --- a/src/db/plugins/simple/DirectorySave.cxx +++ b/src/db/plugins/simple/DirectorySave.cxx @@ -168,15 +168,12 @@ directory_load(TextFile &file, Directory &directory) throw FormatRuntimeError("Duplicate song '%s'", name); std::string target; - auto audio_format = AudioFormat::Undefined(); auto detached_song = song_load(file, name, - &target, - &audio_format); + &target); auto song = std::make_unique(std::move(detached_song), directory); song->target = std::move(target); - song->audio_format = audio_format; directory.AddSong(std::move(song)); } else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) { diff --git a/src/db/plugins/simple/Song.cxx b/src/db/plugins/simple/Song.cxx index 8db47d03f..162a2732f 100644 --- a/src/db/plugins/simple/Song.cxx +++ b/src/db/plugins/simple/Song.cxx @@ -34,6 +34,7 @@ Song::Song(DetachedSong &&other, Directory &_parent) noexcept mtime(other.GetLastModified()), start_time(other.GetStartTime()), end_time(other.GetEndTime()), + audio_format(other.GetAudioFormat()), filename(other.GetURI()) { } diff --git a/src/playlist/PlaylistSong.cxx b/src/playlist/PlaylistSong.cxx index e03d580db..3cecbaeab 100644 --- a/src/playlist/PlaylistSong.cxx +++ b/src/playlist/PlaylistSong.cxx @@ -47,6 +47,9 @@ merge_song_metadata(DetachedSong &add, const DetachedSong &base) noexcept if (add.GetEndTime().IsZero()) { add.SetEndTime(base.GetEndTime()); } + + if (!add.GetAudioFormat().IsDefined()) + add.SetAudioFormat(base.GetAudioFormat()); } static bool diff --git a/src/song/DetachedSong.cxx b/src/song/DetachedSong.cxx index b63391bf5..e79595d75 100644 --- a/src/song/DetachedSong.cxx +++ b/src/song/DetachedSong.cxx @@ -28,7 +28,8 @@ DetachedSong::DetachedSong(const LightSong &other) noexcept tag(other.tag), mtime(other.mtime), start_time(other.start_time), - end_time(other.end_time) {} + end_time(other.end_time), + audio_format(other.audio_format) {} DetachedSong::operator LightSong() const noexcept { diff --git a/src/song/DetachedSong.hxx b/src/song/DetachedSong.hxx index 2400334d9..63203526b 100644 --- a/src/song/DetachedSong.hxx +++ b/src/song/DetachedSong.hxx @@ -21,6 +21,7 @@ #define MPD_DETACHED_SONG_HXX #include "tag/Tag.hxx" +#include "pcm/AudioFormat.hxx" #include "Chrono.hxx" #include "util/Compiler.h" @@ -79,6 +80,12 @@ class DetachedSong { */ SongTime end_time = SongTime::zero(); + /** + * The audio format of the song, if given by the decoder + * plugin. May be undefined if unknown. + */ + AudioFormat audio_format = AudioFormat::Undefined(); + public: explicit DetachedSong(const char *_uri) noexcept :uri(_uri) {} @@ -231,6 +238,14 @@ public: gcc_pure SignedSongTime GetDuration() const noexcept; + const AudioFormat &GetAudioFormat() const noexcept { + return audio_format; + } + + void SetAudioFormat(const AudioFormat &src) noexcept { + audio_format = src; + } + /** * Update the #tag and #mtime. *