decoder/DecoderPlugin: container_scan() returns forward_list<DetachedSong>
Speed up container_scan() again, by eliminating the need to call scan_file() for each item.
This commit is contained in:
parent
72c96052b4
commit
95e2bec215
@ -1894,6 +1894,7 @@ test_run_decoder_LDADD = \
|
|||||||
test_run_decoder_SOURCES = test/run_decoder.cxx \
|
test_run_decoder_SOURCES = test/run_decoder.cxx \
|
||||||
test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \
|
test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \
|
||||||
test/ScopeIOThread.hxx \
|
test/ScopeIOThread.hxx \
|
||||||
|
src/DetachedSong.cxx \
|
||||||
src/Log.cxx src/LogBackend.cxx \
|
src/Log.cxx src/LogBackend.cxx \
|
||||||
src/IOThread.cxx \
|
src/IOThread.cxx \
|
||||||
src/ReplayGainInfo.cxx
|
src/ReplayGainInfo.cxx
|
||||||
@ -1915,6 +1916,7 @@ test_read_tags_LDADD = \
|
|||||||
test_read_tags_SOURCES = test/read_tags.cxx \
|
test_read_tags_SOURCES = test/read_tags.cxx \
|
||||||
test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \
|
test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \
|
||||||
test/ScopeIOThread.hxx \
|
test/ScopeIOThread.hxx \
|
||||||
|
src/DetachedSong.cxx \
|
||||||
src/Log.cxx src/LogBackend.cxx \
|
src/Log.cxx src/LogBackend.cxx \
|
||||||
src/IOThread.cxx \
|
src/IOThread.cxx \
|
||||||
src/ReplayGainInfo.cxx
|
src/ReplayGainInfo.cxx
|
||||||
@ -1946,6 +1948,8 @@ test_ContainerScan_LDADD = \
|
|||||||
libsystem.a \
|
libsystem.a \
|
||||||
libutil.a
|
libutil.a
|
||||||
test_ContainerScan_SOURCES = test/ContainerScan.cxx \
|
test_ContainerScan_SOURCES = test/ContainerScan.cxx \
|
||||||
|
src/DetachedSong.cxx \
|
||||||
|
src/SongSave.cxx src/TagSave.cxx \
|
||||||
src/Log.cxx src/LogBackend.cxx \
|
src/Log.cxx src/LogBackend.cxx \
|
||||||
src/ReplayGainInfo.cxx \
|
src/ReplayGainInfo.cxx \
|
||||||
$(DECODER_SRC)
|
$(DECODER_SRC)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "config.h" /* must be first for large file support */
|
#include "config.h" /* must be first for large file support */
|
||||||
#include "Walk.hxx"
|
#include "Walk.hxx"
|
||||||
#include "UpdateDomain.hxx"
|
#include "UpdateDomain.hxx"
|
||||||
|
#include "DetachedSong.hxx"
|
||||||
#include "db/DatabaseLock.hxx"
|
#include "db/DatabaseLock.hxx"
|
||||||
#include "db/plugins/simple/Directory.hxx"
|
#include "db/plugins/simple/Directory.hxx"
|
||||||
#include "db/plugins/simple/Song.hxx"
|
#include "db/plugins/simple/Song.hxx"
|
||||||
@ -28,8 +29,6 @@
|
|||||||
#include "decoder/DecoderList.hxx"
|
#include "decoder/DecoderList.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "storage/FileInfo.hxx"
|
#include "storage/FileInfo.hxx"
|
||||||
#include "tag/TagHandler.hxx"
|
|
||||||
#include "tag/TagBuilder.hxx"
|
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "util/AllocatedString.hxx"
|
#include "util/AllocatedString.hxx"
|
||||||
|
|
||||||
@ -97,34 +96,21 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auto v = plugin.container_scan(pathname);
|
auto v = plugin.container_scan(pathname);
|
||||||
if (v.empty()) {
|
if (v.empty()) {
|
||||||
editor.LockDeleteDirectory(contdir);
|
editor.LockDeleteDirectory(contdir);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagBuilder tag_builder;
|
for (auto &vtrack : v) {
|
||||||
for (const auto &vtrack : v) {
|
Song *song = Song::NewFrom(std::move(vtrack),
|
||||||
Song *song = Song::NewFile(vtrack.c_str(), *contdir);
|
*contdir);
|
||||||
|
|
||||||
// shouldn't be necessary but it's there..
|
// shouldn't be necessary but it's there..
|
||||||
song->mtime = info.mtime;
|
song->mtime = info.mtime;
|
||||||
|
|
||||||
try {
|
FormatDefault(update_domain, "added %s/%s",
|
||||||
const auto vtrack_fs =
|
contdir->GetPath(), song->uri);
|
||||||
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);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const ScopeDatabaseLock protect;
|
const ScopeDatabaseLock protect;
|
||||||
@ -132,9 +118,6 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
|
|||||||
}
|
}
|
||||||
|
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
||||||
FormatDefault(update_domain, "added %s/%s",
|
|
||||||
directory.GetPath(), vtrack.c_str());
|
|
||||||
}
|
}
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
editor.LockDeleteDirectory(contdir);
|
editor.LockDeleteDirectory(contdir);
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class InputStream;
|
class InputStream;
|
||||||
struct TagHandler;
|
struct TagHandler;
|
||||||
class Path;
|
class Path;
|
||||||
class DecoderClient;
|
class DecoderClient;
|
||||||
|
class DetachedSong;
|
||||||
|
|
||||||
struct DecoderPlugin {
|
struct DecoderPlugin {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -93,7 +93,7 @@ struct DecoderPlugin {
|
|||||||
* a filename for every single track;
|
* a filename for every single track;
|
||||||
* do not include full pathname here, just the "virtual" file
|
* do not include full pathname here, just the "virtual" file
|
||||||
*/
|
*/
|
||||||
std::forward_list<std::string> (*container_scan)(Path path_fs);
|
std::forward_list<DetachedSong> (*container_scan)(Path path_fs);
|
||||||
|
|
||||||
/* last element in these arrays must always be a nullptr: */
|
/* last element in these arrays must always be a nullptr: */
|
||||||
const char *const*suffixes;
|
const char *const*suffixes;
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
#include "../DecoderAPI.hxx"
|
#include "../DecoderAPI.hxx"
|
||||||
#include "config/Block.cxx"
|
#include "config/Block.cxx"
|
||||||
#include "CheckAudioFormat.hxx"
|
#include "CheckAudioFormat.hxx"
|
||||||
|
#include "DetachedSong.hxx"
|
||||||
#include "tag/TagHandler.hxx"
|
#include "tag/TagHandler.hxx"
|
||||||
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
@ -266,10 +268,10 @@ gme_scan_file(Path path_fs,
|
|||||||
return ScanMusicEmu(emu, container.track, handler, handler_ctx);
|
return ScanMusicEmu(emu, container.track, handler, handler_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::forward_list<std::string>
|
static std::forward_list<DetachedSong>
|
||||||
gme_container_scan(Path path_fs)
|
gme_container_scan(Path path_fs)
|
||||||
{
|
{
|
||||||
std::forward_list<std::string> list;
|
std::forward_list<DetachedSong> list;
|
||||||
|
|
||||||
Music_Emu *emu;
|
Music_Emu *emu;
|
||||||
const char *gme_err = gme_open_file(path_fs.c_str(), &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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AtScopeExit(emu) { gme_delete(emu); };
|
||||||
|
|
||||||
const unsigned num_songs = gme_track_count(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 it only contains a single tune, don't treat as container */
|
||||||
if (num_songs < 2)
|
if (num_songs < 2)
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
|
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
|
||||||
|
|
||||||
|
TagBuilder tag_builder;
|
||||||
|
|
||||||
auto tail = list.before_begin();
|
auto tail = list.before_begin();
|
||||||
for (unsigned i = 1; i <= num_songs; ++i) {
|
for (unsigned i = 1; i <= num_songs; ++i) {
|
||||||
|
ScanMusicEmu(emu, i,
|
||||||
|
add_tag_handler, &tag_builder);
|
||||||
|
|
||||||
char track_name[64];
|
char track_name[64];
|
||||||
snprintf(track_name, sizeof(track_name),
|
snprintf(track_name, sizeof(track_name),
|
||||||
SUBTUNE_PREFIX "%03u.%s", i, subtune_suffix);
|
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;
|
return list;
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include "SidplayDecoderPlugin.hxx"
|
#include "SidplayDecoderPlugin.hxx"
|
||||||
#include "../DecoderAPI.hxx"
|
#include "../DecoderAPI.hxx"
|
||||||
#include "tag/TagHandler.hxx"
|
#include "tag/TagHandler.hxx"
|
||||||
|
#include "tag/TagBuilder.hxx"
|
||||||
|
#include "DetachedSong.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "util/Macros.hxx"
|
#include "util/Macros.hxx"
|
||||||
@ -467,12 +469,16 @@ sidplay_scan_file(Path path_fs,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::forward_list<std::string>
|
static std::forward_list<DetachedSong>
|
||||||
sidplay_container_scan(Path path_fs)
|
sidplay_container_scan(Path path_fs)
|
||||||
{
|
{
|
||||||
std::forward_list<std::string> list;
|
std::forward_list<DetachedSong> 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())
|
if (!tune.getStatus())
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
@ -489,13 +495,21 @@ sidplay_container_scan(Path path_fs)
|
|||||||
if(!all_files_are_containers && n_tracks < 2)
|
if(!all_files_are_containers && n_tracks < 2)
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
|
TagBuilder tag_builder;
|
||||||
|
|
||||||
auto tail = list.before_begin();
|
auto tail = list.before_begin();
|
||||||
for (unsigned i = 1; i <= n_tracks; ++i) {
|
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];
|
char track_name[32];
|
||||||
/* Construct container/tune path names, eg.
|
/* Construct container/tune path names, eg.
|
||||||
Delta.sid/tune_001.sid */
|
Delta.sid/tune_001.sid */
|
||||||
sprintf(track_name, SUBTUNE_PREFIX "%03u.sid", i);
|
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;
|
return list;
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
#include "DetachedSong.hxx"
|
||||||
|
#include "SongSave.hxx"
|
||||||
#include "decoder/DecoderList.hxx"
|
#include "decoder/DecoderList.hxx"
|
||||||
#include "decoder/DecoderPlugin.hxx"
|
#include "decoder/DecoderPlugin.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
@ -84,7 +86,7 @@ try {
|
|||||||
BufferedOutputStream bos(sos);
|
BufferedOutputStream bos(sos);
|
||||||
|
|
||||||
for (const auto &song : v)
|
for (const auto &song : v)
|
||||||
bos.Format("%s\n", song.c_str());
|
song_save(bos, song);
|
||||||
|
|
||||||
bos.Flush();
|
bos.Flush();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user