db/simple: add an AudioFormat to each Song
This commit is contained in:
parent
c05bca6f2c
commit
72b6c09a73
|
@ -1932,6 +1932,9 @@ test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \
|
|||
src/db/Selection.cxx \
|
||||
src/db/PlaylistVector.cxx \
|
||||
src/db/DatabaseLock.cxx \
|
||||
src/AudioFormat.cxx \
|
||||
src/AudioParser.cxx \
|
||||
src/pcm/SampleFormat.cxx \
|
||||
src/SongSave.cxx \
|
||||
src/DetachedSong.cxx \
|
||||
src/TagSave.cxx \
|
||||
|
|
2
NEWS
2
NEWS
|
@ -5,6 +5,8 @@ ver 0.21 (not yet released)
|
|||
- "outputs" prints the plugin name
|
||||
- "outputset" sets runtime attributes
|
||||
- close connection when client sends HTTP request
|
||||
* database
|
||||
- simple: scan audio formats
|
||||
* player
|
||||
- "one-shot" single mode
|
||||
* input
|
||||
|
|
|
@ -256,6 +256,17 @@
|
|||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<varname>Format</varname>: the audio format of the song
|
||||
(or an approximation to a format supported by MPD and the
|
||||
decoder plugin being used). When playing this file, the
|
||||
<varname>audio</varname> value in the <link
|
||||
linkend="command_status"><command>status</command></link>
|
||||
response should be the same.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<varname>Last-Modified</varname>: the time stamp of the
|
||||
|
|
|
@ -92,6 +92,9 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept
|
|||
if (!IsNegative(song.mtime))
|
||||
time_print(r, "Last-Modified", song.mtime);
|
||||
|
||||
if (song.audio_format.IsDefined())
|
||||
r.Format("Format: %s\n", ToString(song.audio_format).c_str());
|
||||
|
||||
tag_print(r, song.tag);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "SongSave.hxx"
|
||||
#include "AudioParser.hxx"
|
||||
#include "db/plugins/simple/Song.hxx"
|
||||
#include "DetachedSong.hxx"
|
||||
#include "TagSave.hxx"
|
||||
|
@ -28,6 +29,8 @@
|
|||
#include "tag/Tag.hxx"
|
||||
#include "tag/Builder.hxx"
|
||||
#include "util/ChronoUtil.hxx"
|
||||
#include "util/StringAPI.hxx"
|
||||
#include "util/StringBuffer.hxx"
|
||||
#include "util/StringStrip.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
#include "util/NumberParser.hxx"
|
||||
|
@ -56,6 +59,9 @@ song_save(BufferedOutputStream &os, const Song &song)
|
|||
|
||||
tag_save(os, song.tag);
|
||||
|
||||
if (song.audio_format.IsDefined())
|
||||
os.Format("Format: %s\n", ToString(song.audio_format).c_str());
|
||||
|
||||
if (!IsNegative(song.mtime))
|
||||
os.Format(SONG_MTIME ": %li\n",
|
||||
(long)std::chrono::system_clock::to_time_t(song.mtime));
|
||||
|
@ -78,7 +84,8 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
|||
}
|
||||
|
||||
std::unique_ptr<DetachedSong>
|
||||
song_load(TextFile &file, const char *uri)
|
||||
song_load(TextFile &file, const char *uri,
|
||||
AudioFormat *audio_format_r)
|
||||
{
|
||||
auto song = std::make_unique<DetachedSong>(uri);
|
||||
|
||||
|
@ -100,6 +107,15 @@ song_load(TextFile &file, const char *uri)
|
|||
tag.AddItem(type, value);
|
||||
} else if (strcmp(line, "Time") == 0) {
|
||||
tag.SetDuration(SignedSongTime::FromS(ParseDouble(value)));
|
||||
} else if (StringIsEqual(line, "Format")) {
|
||||
if (audio_format_r != nullptr) {
|
||||
try {
|
||||
*audio_format_r =
|
||||
ParseAudioFormat(value, false);
|
||||
} catch (...) {
|
||||
/* ignore parser errors */
|
||||
}
|
||||
}
|
||||
} else if (strcmp(line, "Playlist") == 0) {
|
||||
tag.SetHasPlaylist(strcmp(value, "yes") == 0);
|
||||
} else if (strcmp(line, SONG_MTIME) == 0) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define SONG_BEGIN "song_begin: "
|
||||
|
||||
struct Song;
|
||||
struct AudioFormat;
|
||||
class DetachedSong;
|
||||
class BufferedOutputStream;
|
||||
class TextFile;
|
||||
|
@ -42,6 +43,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song);
|
|||
* Throws #std::runtime_error on error.
|
||||
*/
|
||||
std::unique_ptr<DetachedSong>
|
||||
song_load(TextFile &file, const char *uri);
|
||||
song_load(TextFile &file, const char *uri,
|
||||
AudioFormat *audio_format_r=nullptr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,19 +77,23 @@ Song::UpdateFile(Storage &storage) noexcept
|
|||
return false;
|
||||
|
||||
TagBuilder tag_builder;
|
||||
auto new_audio_format = AudioFormat::Undefined();
|
||||
|
||||
const auto path_fs = storage.MapFS(relative_uri.c_str());
|
||||
if (path_fs.IsNull()) {
|
||||
const auto absolute_uri =
|
||||
storage.MapUTF8(relative_uri.c_str());
|
||||
if (!tag_stream_scan(absolute_uri.c_str(), tag_builder))
|
||||
if (!tag_stream_scan(absolute_uri.c_str(), tag_builder,
|
||||
&new_audio_format))
|
||||
return false;
|
||||
} else {
|
||||
if (!ScanFileTagsWithGeneric(path_fs, tag_builder))
|
||||
if (!ScanFileTagsWithGeneric(path_fs, tag_builder,
|
||||
&new_audio_format))
|
||||
return false;
|
||||
}
|
||||
|
||||
mtime = info.mtime;
|
||||
audio_format = new_audio_format;
|
||||
tag_builder.Commit(tag);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define MPD_LIGHT_SONG_HXX
|
||||
|
||||
#include "Chrono.hxx"
|
||||
#include "AudioFormat.hxx"
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -78,6 +79,12 @@ struct LightSong {
|
|||
*/
|
||||
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();
|
||||
|
||||
LightSong(const char *_uri, const Tag &_tag) noexcept
|
||||
:uri(_uri), tag(_tag) {}
|
||||
|
||||
|
|
|
@ -161,10 +161,15 @@ directory_load(TextFile &file, Directory &directory)
|
|||
if (directory.FindSong(name) != nullptr)
|
||||
throw FormatRuntimeError("Duplicate song '%s'", name);
|
||||
|
||||
auto song = song_load(file, name);
|
||||
auto audio_format = AudioFormat::Undefined();
|
||||
auto detached_song = song_load(file, name,
|
||||
&audio_format);
|
||||
|
||||
directory.AddSong(Song::NewFrom(std::move(*song),
|
||||
directory));
|
||||
auto song = Song::NewFrom(std::move(*detached_song),
|
||||
directory);
|
||||
song->audio_format = audio_format;
|
||||
|
||||
directory.AddSong(song);
|
||||
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
||||
const char *name = p;
|
||||
playlist_metadata_load(file, directory.playlists, name);
|
||||
|
|
|
@ -104,5 +104,6 @@ Song::Export() const noexcept
|
|||
dest.mtime = mtime;
|
||||
dest.start_time = start_time;
|
||||
dest.end_time = end_time;
|
||||
dest.audio_format = audio_format;
|
||||
return dest;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "check.h"
|
||||
#include "Chrono.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "AudioFormat.hxx"
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
@ -88,6 +89,12 @@ struct Song {
|
|||
*/
|
||||
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();
|
||||
|
||||
/**
|
||||
* The file name.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue