diff --git a/Makefile.am b/Makefile.am index b71cb0e41..b73efecb0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1894,6 +1894,7 @@ test_run_decoder_LDADD = \ test_run_decoder_SOURCES = test/run_decoder.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx \ + src/DetachedSong.cxx \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ src/ReplayGainInfo.cxx @@ -1915,6 +1916,7 @@ test_read_tags_LDADD = \ test_read_tags_SOURCES = test/read_tags.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx \ + src/DetachedSong.cxx \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ src/ReplayGainInfo.cxx @@ -1946,6 +1948,8 @@ test_ContainerScan_LDADD = \ libsystem.a \ libutil.a test_ContainerScan_SOURCES = test/ContainerScan.cxx \ + src/DetachedSong.cxx \ + src/SongSave.cxx src/TagSave.cxx \ src/Log.cxx src/LogBackend.cxx \ src/ReplayGainInfo.cxx \ $(DECODER_SRC) diff --git a/src/db/update/Container.cxx b/src/db/update/Container.cxx index c56ed1eb8..b21c4adb4 100644 --- a/src/db/update/Container.cxx +++ b/src/db/update/Container.cxx @@ -20,6 +20,7 @@ #include "config.h" /* must be first for large file support */ #include "Walk.hxx" #include "UpdateDomain.hxx" +#include "DetachedSong.hxx" #include "db/DatabaseLock.hxx" #include "db/plugins/simple/Directory.hxx" #include "db/plugins/simple/Song.hxx" @@ -28,8 +29,6 @@ #include "decoder/DecoderList.hxx" #include "fs/AllocatedPath.hxx" #include "storage/FileInfo.hxx" -#include "tag/TagHandler.hxx" -#include "tag/TagBuilder.hxx" #include "Log.hxx" #include "util/AllocatedString.hxx" @@ -97,34 +96,21 @@ UpdateWalk::UpdateContainerFile(Directory &directory, } try { - const auto v = plugin.container_scan(pathname); + auto v = plugin.container_scan(pathname); if (v.empty()) { editor.LockDeleteDirectory(contdir); return false; } - TagBuilder tag_builder; - for (const auto &vtrack : v) { - Song *song = Song::NewFile(vtrack.c_str(), *contdir); + for (auto &vtrack : v) { + Song *song = Song::NewFrom(std::move(vtrack), + *contdir); // shouldn't be necessary but it's there.. song->mtime = info.mtime; - try { - const auto vtrack_fs = - AllocatedPath::FromUTF8Throw(vtrack.c_str()); - - const auto child_path_fs = AllocatedPath::Build(pathname, - vtrack_fs); - plugin.ScanFile(child_path_fs, - add_tag_handler, &tag_builder); - } catch (const std::runtime_error &e) { - song->Free(); - LogError(e); - continue; - } - - tag_builder.Commit(song->tag); + FormatDefault(update_domain, "added %s/%s", + contdir->GetPath(), song->uri); { const ScopeDatabaseLock protect; @@ -132,9 +118,6 @@ UpdateWalk::UpdateContainerFile(Directory &directory, } modified = true; - - FormatDefault(update_domain, "added %s/%s", - directory.GetPath(), vtrack.c_str()); } } catch (const std::runtime_error &e) { editor.LockDeleteDirectory(contdir); diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx index ec24a115f..d36bb4002 100644 --- a/src/decoder/DecoderPlugin.hxx +++ b/src/decoder/DecoderPlugin.hxx @@ -23,13 +23,13 @@ #include "Compiler.h" #include -#include struct ConfigBlock; class InputStream; struct TagHandler; class Path; class DecoderClient; +class DetachedSong; struct DecoderPlugin { const char *name; @@ -93,7 +93,7 @@ struct DecoderPlugin { * a filename for every single track; * do not include full pathname here, just the "virtual" file */ - std::forward_list (*container_scan)(Path path_fs); + std::forward_list (*container_scan)(Path path_fs); /* last element in these arrays must always be a nullptr: */ const char *const*suffixes; diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index f3813d475..cd58bc06a 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -22,7 +22,9 @@ #include "../DecoderAPI.hxx" #include "config/Block.cxx" #include "CheckAudioFormat.hxx" +#include "DetachedSong.hxx" #include "tag/TagHandler.hxx" +#include "tag/TagBuilder.hxx" #include "fs/Path.hxx" #include "fs/AllocatedPath.hxx" #include "util/ScopeExit.hxx" @@ -266,10 +268,10 @@ gme_scan_file(Path path_fs, return ScanMusicEmu(emu, container.track, handler, handler_ctx); } -static std::forward_list +static std::forward_list gme_container_scan(Path path_fs) { - std::forward_list list; + std::forward_list list; Music_Emu *emu; const char *gme_err = gme_open_file(path_fs.c_str(), &emu, @@ -279,20 +281,27 @@ gme_container_scan(Path path_fs) return list; } + AtScopeExit(emu) { gme_delete(emu); }; + const unsigned num_songs = gme_track_count(emu); - gme_delete(emu); /* if it only contains a single tune, don't treat as container */ if (num_songs < 2) return list; const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); + TagBuilder tag_builder; + auto tail = list.before_begin(); for (unsigned i = 1; i <= num_songs; ++i) { + ScanMusicEmu(emu, i, + add_tag_handler, &tag_builder); + char track_name[64]; snprintf(track_name, sizeof(track_name), SUBTUNE_PREFIX "%03u.%s", i, subtune_suffix); - tail = list.emplace_after(tail, track_name); + tail = list.emplace_after(tail, track_name, + tag_builder.Commit()); } return list; diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx index 151a73914..b7edd9a95 100644 --- a/src/decoder/plugins/SidplayDecoderPlugin.cxx +++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx @@ -21,6 +21,8 @@ #include "SidplayDecoderPlugin.hxx" #include "../DecoderAPI.hxx" #include "tag/TagHandler.hxx" +#include "tag/TagBuilder.hxx" +#include "DetachedSong.hxx" #include "fs/Path.hxx" #include "fs/AllocatedPath.hxx" #include "util/Macros.hxx" @@ -467,12 +469,16 @@ sidplay_scan_file(Path path_fs, return true; } -static std::forward_list +static std::forward_list sidplay_container_scan(Path path_fs) { - std::forward_list list; + std::forward_list list; - SidTune tune(path_fs.c_str(), nullptr, true); +#ifdef HAVE_SIDPLAYFP + SidTune tune(path_fs.c_str()); +#else + SidTuneMod tune(path_fs.c_str()); +#endif if (!tune.getStatus()) return list; @@ -489,13 +495,21 @@ sidplay_container_scan(Path path_fs) if(!all_files_are_containers && n_tracks < 2) return list; + TagBuilder tag_builder; + auto tail = list.before_begin(); for (unsigned i = 1; i <= n_tracks; ++i) { + tune.selectSong(i); + + ScanSidTuneInfo(info, i, n_tracks, + add_tag_handler, &tag_builder); + char track_name[32]; /* Construct container/tune path names, eg. Delta.sid/tune_001.sid */ sprintf(track_name, SUBTUNE_PREFIX "%03u.sid", i); - tail = list.emplace_after(tail, track_name); + tail = list.emplace_after(tail, track_name, + tag_builder.Commit()); } return list; diff --git a/test/ContainerScan.cxx b/test/ContainerScan.cxx index 7ec55c0fe..40ec29276 100644 --- a/test/ContainerScan.cxx +++ b/test/ContainerScan.cxx @@ -19,6 +19,8 @@ #include "config.h" #include "Log.hxx" +#include "DetachedSong.hxx" +#include "SongSave.hxx" #include "decoder/DecoderList.hxx" #include "decoder/DecoderPlugin.hxx" #include "fs/Path.hxx" @@ -84,7 +86,7 @@ try { BufferedOutputStream bos(sos); for (const auto &song : v) - bos.Format("%s\n", song.c_str()); + song_save(bos, song); bos.Flush();