From 5fdb804a500c91c206dd75327c920a1fc75dcc9f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 4 Sep 2019 10:19:01 +0200 Subject: [PATCH] db/simple/Song: add attribute "target" Will be used for Song objects representing tracks inside a CUE file. --- src/SongSave.cxx | 7 +++++++ src/SongSave.hxx | 1 + src/db/plugins/simple/DirectorySave.cxx | 3 +++ src/db/plugins/simple/Song.cxx | 2 ++ src/db/plugins/simple/Song.hxx | 9 +++++++++ 5 files changed, 22 insertions(+) diff --git a/src/SongSave.cxx b/src/SongSave.cxx index ce761e544..11c2ebcaf 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -53,6 +53,9 @@ song_save(BufferedOutputStream &os, const Song &song) { os.Format(SONG_BEGIN "%s\n", song.filename.c_str()); + if (!song.target.empty()) + os.Format("Target: %s\n", song.target.c_str()); + range_save(os, song.start_time.ToMS(), song.end_time.ToMS()); tag_save(os, song.tag); @@ -83,6 +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) { DetachedSong song(uri); @@ -105,6 +109,9 @@ song_load(TextFile &file, const char *uri, tag.AddItem(type, value); } else if (StringIsEqual(line, "Time")) { tag.SetDuration(SignedSongTime::FromS(ParseDouble(value))); + } else if (StringIsEqual(line, "Target")) { + if (target_r != nullptr) + *target_r = value; } else if (StringIsEqual(line, "Format")) { if (audio_format_r != nullptr) { try { diff --git a/src/SongSave.hxx b/src/SongSave.hxx index 579ec6f30..ab3105229 100644 --- a/src/SongSave.hxx +++ b/src/SongSave.hxx @@ -44,6 +44,7 @@ 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); #endif diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx index 783dcc3f0..1dedba063 100644 --- a/src/db/plugins/simple/DirectorySave.cxx +++ b/src/db/plugins/simple/DirectorySave.cxx @@ -161,12 +161,15 @@ directory_load(TextFile &file, Directory &directory) if (directory.FindSong(name) != nullptr) throw FormatRuntimeError("Duplicate song '%s'", name); + std::string target; auto audio_format = AudioFormat::Undefined(); auto detached_song = song_load(file, name, + &target, &audio_format); 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)); diff --git a/src/db/plugins/simple/Song.cxx b/src/db/plugins/simple/Song.cxx index e71a885e0..f9ac734ae 100644 --- a/src/db/plugins/simple/Song.cxx +++ b/src/db/plugins/simple/Song.cxx @@ -51,6 +51,8 @@ Song::Export() const noexcept LightSong dest(filename.c_str(), tag); if (!parent.IsRoot()) dest.directory = parent.GetPath(); + if (!target.empty()) + dest.real_uri = target.c_str(); dest.mtime = mtime; dest.start_time = start_time; dest.end_time = end_time; diff --git a/src/db/plugins/simple/Song.hxx b/src/db/plugins/simple/Song.hxx index 17443fd45..9525de6f8 100644 --- a/src/db/plugins/simple/Song.hxx +++ b/src/db/plugins/simple/Song.hxx @@ -93,6 +93,15 @@ struct Song { */ std::string filename; + /** + * If non-empty, then this object does not describe a file + * within the `music_directory`, but some sort of symbolic + * link pointing to this value. It can be an absolute URI + * (i.e. with URI scheme) or a URI relative to this object + * (which may begin with one or more "../"). + */ + std::string target; + template Song(F &&_filename, Directory &_parent) noexcept :parent(_parent), filename(std::forward(_filename)) {}