decoder/DecoderPlugin: container_scan() returns forward_list<string>

This commit is contained in:
Max Kellermann 2016-11-22 09:33:52 +01:00
parent 114fcee2ae
commit 0abee77e62
5 changed files with 55 additions and 39 deletions

2
NEWS
View File

@ -21,9 +21,11 @@ ver 0.20 (not yet released)
- ffmpeg: support ReplayGain and MixRamp - ffmpeg: support ReplayGain and MixRamp
- ffmpeg: support stream tags - ffmpeg: support stream tags
- gme: add option "accuracy" - gme: add option "accuracy"
- gme: faster scanning
- mad: reduce memory usage while scanning tags - mad: reduce memory usage while scanning tags
- mpcdec: read the bit rate - mpcdec: read the bit rate
- pcm: support audio/L16 (RFC 2586) and audio/x-mpd-float - pcm: support audio/L16 (RFC 2586) and audio/x-mpd-float
- sidplay: faster scanning
* playlist * playlist
- cue: don't skip pregap - cue: don't skip pregap
- embcue: fix last track - embcue: fix last track

View File

@ -96,10 +96,14 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
return false; return false;
} }
AllocatedString<> vtrack = nullptr; const auto v = plugin.container_scan(pathname);
unsigned int tnum = 0; if (v.empty()) {
editor.LockDeleteDirectory(contdir);
return false;
}
TagBuilder tag_builder; TagBuilder tag_builder;
while ((vtrack = plugin.container_scan(pathname, ++tnum)) != nullptr) { for (const auto &vtrack : v) {
Song *song = Song::NewFile(vtrack.c_str(), *contdir); Song *song = Song::NewFile(vtrack.c_str(), *contdir);
// shouldn't be necessary but it's there.. // shouldn't be necessary but it's there..
@ -126,9 +130,5 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
directory.GetPath(), vtrack.c_str()); directory.GetPath(), vtrack.c_str());
} }
if (tnum == 1) { return true;
editor.LockDeleteDirectory(contdir);
return false;
} else
return true;
} }

View File

@ -22,11 +22,13 @@
#include "Compiler.h" #include "Compiler.h"
#include <forward_list>
#include <string>
struct ConfigBlock; struct ConfigBlock;
class InputStream; class InputStream;
struct TagHandler; struct TagHandler;
class Path; class Path;
template<typename T> class AllocatedString;
class DecoderClient; class DecoderClient;
struct DecoderPlugin { struct DecoderPlugin {
@ -85,14 +87,13 @@ struct DecoderPlugin {
/** /**
* @brief Return a "virtual" filename for subtracks in * @brief Return a "virtual" filename for subtracks in
* container formats like flac * container formats like flac
* @param const char* pathname full pathname for the file on fs * @param path_fs full pathname for the file on fs
* @param const unsigned int tnum track number
* *
* @return nullptr if there are no multiple files * @return an empty list if there are no multiple files
* a filename for every single track according to tnum (param 2) * 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
*/ */
AllocatedString<char> (*container_scan)(Path path_fs, unsigned tnum); std::forward_list<std::string> (*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;

View File

@ -27,16 +27,16 @@
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "util/ScopeExit.hxx" #include "util/ScopeExit.hxx"
#include "util/FormatString.hxx" #include "util/FormatString.hxx"
#include "util/AllocatedString.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <gme/gme.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <gme/gme.h>
#define SUBTUNE_PREFIX "tune_" #define SUBTUNE_PREFIX "tune_"
@ -103,29 +103,36 @@ ParseContainerPath(Path path_fs)
return { path_fs.GetDirectoryName(), track - 1 }; return { path_fs.GetDirectoryName(), track - 1 };
} }
static AllocatedString<> static std::forward_list<std::string>
gme_container_scan(Path path_fs, const unsigned int tnum) gme_container_scan(Path path_fs)
{ {
std::forward_list<std::string> 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,
GME_SAMPLE_RATE); GME_SAMPLE_RATE);
if (gme_err != nullptr) { if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err); LogWarning(gme_domain, gme_err);
return nullptr; return list;
} }
const unsigned num_songs = gme_track_count(emu); const unsigned num_songs = gme_track_count(emu);
gme_delete(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 nullptr; return list;
const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
if (tnum <= num_songs){
return FormatString(SUBTUNE_PREFIX "%03u.%s", auto tail = list.before_begin();
tnum, subtune_suffix); for (unsigned i = 1; i < num_songs; ++i) {
} else char track_name[64];
return nullptr; snprintf(track_name, sizeof(track_name),
"%03u.%s", i, subtune_suffix);
tail = list.emplace_after(tail, track_name);
}
return list;
} }
static void static void

View File

@ -25,14 +25,11 @@
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "util/Macros.hxx" #include "util/Macros.hxx"
#include "util/FormatString.hxx" #include "util/FormatString.hxx"
#include "util/AllocatedString.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "system/ByteOrder.hxx" #include "system/ByteOrder.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <string.h>
#ifdef HAVE_SIDPLAYFP #ifdef HAVE_SIDPLAYFP
#include <sidplayfp/sidplayfp.h> #include <sidplayfp/sidplayfp.h>
#include <sidplayfp/SidInfo.h> #include <sidplayfp/SidInfo.h>
@ -49,6 +46,9 @@
#include <sidplay/utils/SidDatabase.h> #include <sidplay/utils/SidDatabase.h>
#endif #endif
#include <string.h>
#include <stdio.h>
#define SUBTUNE_PREFIX "tune_" #define SUBTUNE_PREFIX "tune_"
static constexpr Domain sidplay_domain("sidplay"); static constexpr Domain sidplay_domain("sidplay");
@ -476,12 +476,14 @@ sidplay_scan_file(Path path_fs,
return true; return true;
} }
static AllocatedString<> static std::forward_list<std::string>
sidplay_container_scan(Path path_fs, const unsigned int tnum) sidplay_container_scan(Path path_fs)
{ {
std::forward_list<std::string> list;
SidTune tune(path_fs.c_str(), nullptr, true); SidTune tune(path_fs.c_str(), nullptr, true);
if (!tune.getStatus()) if (!tune.getStatus())
return nullptr; return list;
#ifdef HAVE_SIDPLAYFP #ifdef HAVE_SIDPLAYFP
const SidTuneInfo &info = *tune.getInfo(); 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 /* Don't treat sids containing a single tune
as containers */ as containers */
if(!all_files_are_containers && n_tracks < 2) if(!all_files_are_containers && n_tracks < 2)
return nullptr; return list;
/* Construct container/tune path names, eg. auto tail = list.before_begin();
Delta.sid/tune_001.sid */ for (unsigned i = 1; i < n_tracks; ++i) {
if (tnum <= n_tracks) { char track_name[32];
return FormatString(SUBTUNE_PREFIX "%03u.sid", tnum); /* Construct container/tune path names, eg.
} else Delta.sid/tune_001.sid */
return nullptr; sprintf(track_name, SUBTUNE_PREFIX "%03u.sid", i);
tail = list.emplace_after(tail, track_name);
}
return list;
} }
static const char *const sidplay_suffixes[] = { static const char *const sidplay_suffixes[] = {