From 0abee77e62636cceec966bda77696b16ab1ed96b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 22 Nov 2016 09:33:52 +0100 Subject: [PATCH] decoder/DecoderPlugin: container_scan() returns forward_list --- NEWS | 2 ++ src/db/update/Container.cxx | 16 +++++----- src/decoder/DecoderPlugin.hxx | 13 ++++---- src/decoder/plugins/GmeDecoderPlugin.cxx | 31 +++++++++++-------- src/decoder/plugins/SidplayDecoderPlugin.cxx | 32 ++++++++++++-------- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/NEWS b/NEWS index 6a6a90018..6dafc9241 100644 --- a/NEWS +++ b/NEWS @@ -21,9 +21,11 @@ ver 0.20 (not yet released) - ffmpeg: support ReplayGain and MixRamp - ffmpeg: support stream tags - gme: add option "accuracy" + - gme: faster scanning - mad: reduce memory usage while scanning tags - mpcdec: read the bit rate - pcm: support audio/L16 (RFC 2586) and audio/x-mpd-float + - sidplay: faster scanning * playlist - cue: don't skip pregap - embcue: fix last track diff --git a/src/db/update/Container.cxx b/src/db/update/Container.cxx index 01f2edfa0..28bb7e5f1 100644 --- a/src/db/update/Container.cxx +++ b/src/db/update/Container.cxx @@ -96,10 +96,14 @@ UpdateWalk::UpdateContainerFile(Directory &directory, return false; } - AllocatedString<> vtrack = nullptr; - unsigned int tnum = 0; + const auto v = plugin.container_scan(pathname); + if (v.empty()) { + editor.LockDeleteDirectory(contdir); + return false; + } + TagBuilder tag_builder; - while ((vtrack = plugin.container_scan(pathname, ++tnum)) != nullptr) { + for (const auto &vtrack : v) { Song *song = Song::NewFile(vtrack.c_str(), *contdir); // shouldn't be necessary but it's there.. @@ -126,9 +130,5 @@ UpdateWalk::UpdateContainerFile(Directory &directory, directory.GetPath(), vtrack.c_str()); } - if (tnum == 1) { - editor.LockDeleteDirectory(contdir); - return false; - } else - return true; + return true; } diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx index c83944b5f..ec24a115f 100644 --- a/src/decoder/DecoderPlugin.hxx +++ b/src/decoder/DecoderPlugin.hxx @@ -22,11 +22,13 @@ #include "Compiler.h" +#include +#include + struct ConfigBlock; class InputStream; struct TagHandler; class Path; -template class AllocatedString; class DecoderClient; struct DecoderPlugin { @@ -85,14 +87,13 @@ struct DecoderPlugin { /** * @brief Return a "virtual" filename for subtracks in * container formats like flac - * @param const char* pathname full pathname for the file on fs - * @param const unsigned int tnum track number + * @param path_fs full pathname for the file on fs * - * @return nullptr if there are no multiple files - * a filename for every single track according to tnum (param 2) + * @return an empty list if there are no multiple files + * a filename for every single track; * do not include full pathname here, just the "virtual" file */ - AllocatedString (*container_scan)(Path path_fs, unsigned tnum); + 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 dd7d58a73..508949ad8 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -27,16 +27,16 @@ #include "fs/AllocatedPath.hxx" #include "util/ScopeExit.hxx" #include "util/FormatString.hxx" -#include "util/AllocatedString.hxx" #include "util/UriUtil.hxx" #include "util/Domain.hxx" #include "Log.hxx" +#include + #include #include #include - -#include +#include #define SUBTUNE_PREFIX "tune_" @@ -103,29 +103,36 @@ ParseContainerPath(Path path_fs) return { path_fs.GetDirectoryName(), track - 1 }; } -static AllocatedString<> -gme_container_scan(Path path_fs, const unsigned int tnum) +static std::forward_list +gme_container_scan(Path path_fs) { + std::forward_list list; + Music_Emu *emu; const char *gme_err = gme_open_file(path_fs.c_str(), &emu, GME_SAMPLE_RATE); if (gme_err != nullptr) { LogWarning(gme_domain, gme_err); - return nullptr; + return list; } 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 nullptr; + return list; const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); - if (tnum <= num_songs){ - return FormatString(SUBTUNE_PREFIX "%03u.%s", - tnum, subtune_suffix); - } else - return nullptr; + + auto tail = list.before_begin(); + for (unsigned i = 1; i < num_songs; ++i) { + char track_name[64]; + snprintf(track_name, sizeof(track_name), + "%03u.%s", i, subtune_suffix); + tail = list.emplace_after(tail, track_name); + } + + return list; } static void diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx index b3b122ac3..42a4d595f 100644 --- a/src/decoder/plugins/SidplayDecoderPlugin.cxx +++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx @@ -25,14 +25,11 @@ #include "fs/AllocatedPath.hxx" #include "util/Macros.hxx" #include "util/FormatString.hxx" -#include "util/AllocatedString.hxx" #include "util/Domain.hxx" #include "system/ByteOrder.hxx" #include "system/FatalError.hxx" #include "Log.hxx" -#include - #ifdef HAVE_SIDPLAYFP #include #include @@ -49,6 +46,9 @@ #include #endif +#include +#include + #define SUBTUNE_PREFIX "tune_" static constexpr Domain sidplay_domain("sidplay"); @@ -476,12 +476,14 @@ sidplay_scan_file(Path path_fs, return true; } -static AllocatedString<> -sidplay_container_scan(Path path_fs, const unsigned int tnum) +static std::forward_list +sidplay_container_scan(Path path_fs) { + std::forward_list list; + SidTune tune(path_fs.c_str(), nullptr, true); if (!tune.getStatus()) - return nullptr; + return list; #ifdef HAVE_SIDPLAYFP const SidTuneInfo &info = *tune.getInfo(); @@ -494,14 +496,18 @@ sidplay_container_scan(Path path_fs, const unsigned int tnum) /* Don't treat sids containing a single tune as containers */ if(!all_files_are_containers && n_tracks < 2) - return nullptr; + return list; - /* Construct container/tune path names, eg. - Delta.sid/tune_001.sid */ - if (tnum <= n_tracks) { - return FormatString(SUBTUNE_PREFIX "%03u.sid", tnum); - } else - return nullptr; + auto tail = list.before_begin(); + for (unsigned i = 1; i < n_tracks; ++i) { + 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); + } + + return list; } static const char *const sidplay_suffixes[] = {