song/DetachedSong: copy the AudioFormat from LightSong
Enables the "Format" row in "playlistinfo" responses. https://github.com/MusicPlayerDaemon/MPD/issues/1094
This commit is contained in:
parent
81d0c04ed4
commit
c729f16dcd
1
NEWS
1
NEWS
@ -1,6 +1,7 @@
|
|||||||
ver 0.23 (not yet released)
|
ver 0.23 (not yet released)
|
||||||
* protocol
|
* protocol
|
||||||
- new command "getvol"
|
- new command "getvol"
|
||||||
|
- show the audio format in "playlistinfo"
|
||||||
* output
|
* output
|
||||||
- snapcast: new plugin
|
- snapcast: new plugin
|
||||||
|
|
||||||
|
@ -111,6 +111,9 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept
|
|||||||
if (!IsNegative(song.GetLastModified()))
|
if (!IsNegative(song.GetLastModified()))
|
||||||
time_print(r, "Last-Modified", 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());
|
tag_print_values(r, song.GetTag());
|
||||||
|
|
||||||
const auto duration = song.GetDuration();
|
const auto duration = song.GetDuration();
|
||||||
|
@ -86,8 +86,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
|||||||
|
|
||||||
DetachedSong
|
DetachedSong
|
||||||
song_load(TextFile &file, const char *uri,
|
song_load(TextFile &file, const char *uri,
|
||||||
std::string *target_r,
|
std::string *target_r)
|
||||||
AudioFormat *audio_format_r)
|
|
||||||
{
|
{
|
||||||
DetachedSong song(uri);
|
DetachedSong song(uri);
|
||||||
|
|
||||||
@ -113,13 +112,11 @@ song_load(TextFile &file, const char *uri,
|
|||||||
if (target_r != nullptr)
|
if (target_r != nullptr)
|
||||||
*target_r = value;
|
*target_r = value;
|
||||||
} else if (StringIsEqual(line, "Format")) {
|
} else if (StringIsEqual(line, "Format")) {
|
||||||
if (audio_format_r != nullptr) {
|
try {
|
||||||
try {
|
song.SetAudioFormat(ParseAudioFormat(value,
|
||||||
*audio_format_r =
|
false));
|
||||||
ParseAudioFormat(value, false);
|
} catch (...) {
|
||||||
} catch (...) {
|
/* ignore parser errors */
|
||||||
/* ignore parser errors */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (StringIsEqual(line, "Playlist")) {
|
} else if (StringIsEqual(line, "Playlist")) {
|
||||||
tag.SetHasPlaylist(StringIsEqual(value, "yes"));
|
tag.SetHasPlaylist(StringIsEqual(value, "yes"));
|
||||||
|
@ -44,7 +44,6 @@ song_save(BufferedOutputStream &os, const DetachedSong &song);
|
|||||||
*/
|
*/
|
||||||
DetachedSong
|
DetachedSong
|
||||||
song_load(TextFile &file, const char *uri,
|
song_load(TextFile &file, const char *uri,
|
||||||
std::string *target_r=nullptr,
|
std::string *target_r=nullptr);
|
||||||
AudioFormat *audio_format_r=nullptr);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -153,9 +153,10 @@ DetachedSong::LoadFile(Path path)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
TagBuilder tag_builder;
|
TagBuilder tag_builder;
|
||||||
|
auto new_audio_format = AudioFormat::Undefined();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!ScanFileTagsWithGeneric(path, tag_builder))
|
if (!ScanFileTagsWithGeneric(path, tag_builder, &new_audio_format))
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// TODO: log or propagate I/O errors?
|
// TODO: log or propagate I/O errors?
|
||||||
@ -163,6 +164,7 @@ DetachedSong::LoadFile(Path path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mtime = fi.GetModificationTime();
|
mtime = fi.GetModificationTime();
|
||||||
|
audio_format = new_audio_format;
|
||||||
tag_builder.Commit(tag);
|
tag_builder.Commit(tag);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -177,9 +179,11 @@ DetachedSong::Update()
|
|||||||
return LoadFile(path_fs);
|
return LoadFile(path_fs);
|
||||||
} else if (IsRemote()) {
|
} else if (IsRemote()) {
|
||||||
TagBuilder tag_builder;
|
TagBuilder tag_builder;
|
||||||
|
auto new_audio_format = AudioFormat::Undefined();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!tag_stream_scan(uri.c_str(), tag_builder))
|
if (!tag_stream_scan(uri.c_str(), tag_builder,
|
||||||
|
&new_audio_format))
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// TODO: log or propagate I/O errors?
|
// TODO: log or propagate I/O errors?
|
||||||
@ -187,6 +191,7 @@ DetachedSong::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mtime = std::chrono::system_clock::time_point::min();
|
mtime = std::chrono::system_clock::time_point::min();
|
||||||
|
audio_format = new_audio_format;
|
||||||
tag_builder.Commit(tag);
|
tag_builder.Commit(tag);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
|
@ -168,15 +168,12 @@ directory_load(TextFile &file, Directory &directory)
|
|||||||
throw FormatRuntimeError("Duplicate song '%s'", name);
|
throw FormatRuntimeError("Duplicate song '%s'", name);
|
||||||
|
|
||||||
std::string target;
|
std::string target;
|
||||||
auto audio_format = AudioFormat::Undefined();
|
|
||||||
auto detached_song = song_load(file, name,
|
auto detached_song = song_load(file, name,
|
||||||
&target,
|
&target);
|
||||||
&audio_format);
|
|
||||||
|
|
||||||
auto song = std::make_unique<Song>(std::move(detached_song),
|
auto song = std::make_unique<Song>(std::move(detached_song),
|
||||||
directory);
|
directory);
|
||||||
song->target = std::move(target);
|
song->target = std::move(target);
|
||||||
song->audio_format = audio_format;
|
|
||||||
|
|
||||||
directory.AddSong(std::move(song));
|
directory.AddSong(std::move(song));
|
||||||
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
||||||
|
@ -34,6 +34,7 @@ Song::Song(DetachedSong &&other, Directory &_parent) noexcept
|
|||||||
mtime(other.GetLastModified()),
|
mtime(other.GetLastModified()),
|
||||||
start_time(other.GetStartTime()),
|
start_time(other.GetStartTime()),
|
||||||
end_time(other.GetEndTime()),
|
end_time(other.GetEndTime()),
|
||||||
|
audio_format(other.GetAudioFormat()),
|
||||||
filename(other.GetURI())
|
filename(other.GetURI())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ merge_song_metadata(DetachedSong &add, const DetachedSong &base) noexcept
|
|||||||
if (add.GetEndTime().IsZero()) {
|
if (add.GetEndTime().IsZero()) {
|
||||||
add.SetEndTime(base.GetEndTime());
|
add.SetEndTime(base.GetEndTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!add.GetAudioFormat().IsDefined())
|
||||||
|
add.SetAudioFormat(base.GetAudioFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -28,7 +28,8 @@ DetachedSong::DetachedSong(const LightSong &other) noexcept
|
|||||||
tag(other.tag),
|
tag(other.tag),
|
||||||
mtime(other.mtime),
|
mtime(other.mtime),
|
||||||
start_time(other.start_time),
|
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
|
DetachedSong::operator LightSong() const noexcept
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define MPD_DETACHED_SONG_HXX
|
#define MPD_DETACHED_SONG_HXX
|
||||||
|
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
|
#include "pcm/AudioFormat.hxx"
|
||||||
#include "Chrono.hxx"
|
#include "Chrono.hxx"
|
||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
@ -79,6 +80,12 @@ class DetachedSong {
|
|||||||
*/
|
*/
|
||||||
SongTime end_time = SongTime::zero();
|
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:
|
public:
|
||||||
explicit DetachedSong(const char *_uri) noexcept
|
explicit DetachedSong(const char *_uri) noexcept
|
||||||
:uri(_uri) {}
|
:uri(_uri) {}
|
||||||
@ -231,6 +238,14 @@ public:
|
|||||||
gcc_pure
|
gcc_pure
|
||||||
SignedSongTime GetDuration() const noexcept;
|
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.
|
* Update the #tag and #mtime.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user