tag/Handler: convert to class with virtual methods

This commit is contained in:
Max Kellermann
2018-07-05 19:07:05 +02:00
parent 09d4176210
commit 3d3a1232b1
49 changed files with 414 additions and 496 deletions

@@ -83,16 +83,14 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
static void
adplug_scan_tag(TagType type, const std::string &value,
const TagHandler &handler, void *handler_ctx) noexcept
TagHandler &handler) noexcept
{
if (!value.empty())
tag_handler_invoke_tag(handler, handler_ctx,
type, value.c_str());
handler.OnTag(type, value.c_str());
}
static bool
adplug_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
adplug_scan_file(Path path_fs, TagHandler &handler) noexcept
{
CEmuopl opl(sample_rate, true, true);
opl.init();
@@ -101,16 +99,15 @@ adplug_scan_file(Path path_fs,
if (player == nullptr)
return false;
tag_handler_invoke_duration(handler, handler_ctx,
SongTime::FromMS(player->songlength()));
handler.OnDuration(SongTime::FromMS(player->songlength()));
if (handler.tag != nullptr) {
if (handler.WantTag()) {
adplug_scan_tag(TAG_TITLE, player->gettitle(),
handler, handler_ctx);
handler);
adplug_scan_tag(TAG_ARTIST, player->getauthor(),
handler, handler_ctx);
handler);
adplug_scan_tag(TAG_COMMENT, player->getdesc(),
handler, handler_ctx);
handler);
}
delete player;

@@ -256,14 +256,13 @@ audiofile_get_duration(InputStream &is) noexcept
}
static bool
audiofile_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
audiofile_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
const auto duration = audiofile_get_duration(is);
if (duration.IsNegative())
return false;
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
handler.OnDuration(SongTime(duration));
return true;
}

@@ -115,9 +115,8 @@ dsdlib_valid_freq(uint32_t samplefreq) noexcept
#ifdef ENABLE_ID3TAG
void
dsdlib_tag_id3(InputStream &is,
const TagHandler &handler,
void *handler_ctx, offset_type tagoffset)
dsdlib_tag_id3(InputStream &is, TagHandler &handler,
offset_type tagoffset)
{
if (tagoffset == 0 || !is.KnownSize())
return;
@@ -150,7 +149,7 @@ dsdlib_tag_id3(InputStream &is,
if (id3_tag == nullptr)
return;
scan_id3_tag(id3_tag, handler, handler_ctx);
scan_id3_tag(id3_tag, handler);
id3_tag_delete(id3_tag);
return;

@@ -26,7 +26,7 @@
#include <stdint.h>
struct TagHandler;
class TagHandler;
class DecoderClient;
class InputStream;
@@ -79,8 +79,7 @@ dsdlib_valid_freq(uint32_t samplefreq) noexcept;
* DSF and DSDIFF files are imported
*/
void
dsdlib_tag_id3(InputStream &is,
const TagHandler &handler,
void *handler_ctx, offset_type tagoffset);
dsdlib_tag_id3(InputStream &is, TagHandler &handler,
offset_type tagoffset);
#endif

@@ -186,8 +186,8 @@ dsdiff_read_prop(DecoderClient *client, InputStream &is,
static void
dsdiff_handle_native_tag(InputStream &is,
const TagHandler &handler,
void *handler_ctx, offset_type tagoffset,
TagHandler &handler,
offset_type tagoffset,
TagType type)
{
if (!dsdlib_skip_to(nullptr, is, tagoffset))
@@ -212,7 +212,7 @@ dsdiff_handle_native_tag(InputStream &is,
return;
string[length] = '\0';
tag_handler_invoke_tag(handler, handler_ctx, type, label);
handler.OnTag(type, label);
return;
}
@@ -228,8 +228,7 @@ static bool
dsdiff_read_metadata_extra(DecoderClient *client, InputStream &is,
DsdiffMetaData *metadata,
DsdiffChunkHeader *chunk_header,
const TagHandler &handler,
void *handler_ctx)
TagHandler &handler)
{
/* skip from DSD data to next chunk header */
@@ -286,17 +285,17 @@ dsdiff_read_metadata_extra(DecoderClient *client, InputStream &is,
if (id3_offset != 0) {
/* a ID3 tag has preference over the other tags, do not process
other tags if we have one */
dsdlib_tag_id3(is, handler, handler_ctx, id3_offset);
dsdlib_tag_id3(is, handler, id3_offset);
return true;
}
#endif
if (artist_offset != 0)
dsdiff_handle_native_tag(is, handler, handler_ctx,
dsdiff_handle_native_tag(is, handler,
artist_offset, TAG_ARTIST);
if (title_offset != 0)
dsdiff_handle_native_tag(is, handler, handler_ctx,
dsdiff_handle_native_tag(is, handler,
title_offset, TAG_TITLE);
return true;
}
@@ -449,9 +448,7 @@ dsdiff_stream_decode(DecoderClient &client, InputStream &is)
}
static bool
dsdiff_scan_stream(InputStream &is,
gcc_unused const TagHandler &handler,
gcc_unused void *handler_ctx) noexcept
dsdiff_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
DsdiffMetaData metadata;
DsdiffChunkHeader chunk_header;
@@ -469,11 +466,11 @@ dsdiff_scan_stream(InputStream &is,
uint64_t n_frames = metadata.chunk_size / metadata.channels;
auto songtime = SongTime::FromScale<uint64_t>(n_frames,
sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, songtime);
handler.OnDuration(songtime);
/* Read additional metadata and created tags if available */
dsdiff_read_metadata_extra(nullptr, is, &metadata, &chunk_header,
handler, handler_ctx);
handler);
return true;
}

@@ -325,9 +325,7 @@ dsf_stream_decode(DecoderClient &client, InputStream &is)
}
static bool
dsf_scan_stream(InputStream &is,
gcc_unused const TagHandler &handler,
gcc_unused void *handler_ctx) noexcept
dsf_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
/* check DSF metadata */
DsfMetaData metadata;
@@ -342,11 +340,11 @@ dsf_scan_stream(InputStream &is,
const auto n_blocks = metadata.n_blocks;
auto songtime = SongTime::FromScale<uint64_t>(n_blocks * DSF_BLOCK_SIZE,
sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, songtime);
handler.OnDuration(songtime);
#ifdef ENABLE_ID3TAG
/* Add available tags from the ID3 tag */
dsdlib_tag_id3(is, handler, handler_ctx, metadata.id3_offset);
dsdlib_tag_id3(is, handler, metadata.id3_offset);
#endif
return true;
}

@@ -414,16 +414,14 @@ faad_stream_decode(DecoderClient &client, InputStream &is)
}
static bool
faad_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
faad_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
auto result = faad_get_file_time(is);
if (!result.first)
return false;
if (!result.second.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx,
SongTime(result.second));
handler.OnDuration(SongTime(result.second));
return true;
}

@@ -572,21 +572,20 @@ FfmpegParseMetaData(DecoderClient &client,
}
static void
FfmpegScanMetadata(const AVStream &stream,
const TagHandler &handler, void *handler_ctx)
FfmpegScanMetadata(const AVStream &stream, TagHandler &handler) noexcept
{
FfmpegScanDictionary(stream.metadata, handler, handler_ctx);
FfmpegScanDictionary(stream.metadata, handler);
}
static void
FfmpegScanMetadata(const AVFormatContext &format_context, int audio_stream,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
assert(audio_stream >= 0);
FfmpegScanDictionary(format_context.metadata, handler, handler_ctx);
FfmpegScanDictionary(format_context.metadata, handler);
FfmpegScanMetadata(*format_context.streams[audio_stream],
handler, handler_ctx);
handler);
}
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
@@ -595,8 +594,8 @@ static void
FfmpegScanTag(const AVFormatContext &format_context, int audio_stream,
TagBuilder &tag)
{
FfmpegScanMetadata(format_context, audio_stream,
full_tag_handler, &tag);
FullTagHandler h(tag);
FfmpegScanMetadata(format_context, audio_stream, h);
}
/**
@@ -828,7 +827,7 @@ ffmpeg_decode(DecoderClient &client, InputStream &input)
static bool
FfmpegScanStream(AVFormatContext &format_context,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
const int find_result =
avformat_find_stream_info(&format_context, nullptr);
@@ -841,22 +840,19 @@ FfmpegScanStream(AVFormatContext &format_context,
const AVStream &stream = *format_context.streams[audio_stream];
if (stream.duration != (int64_t)AV_NOPTS_VALUE)
tag_handler_invoke_duration(handler, handler_ctx,
FromFfmpegTime(stream.duration,
stream.time_base));
handler.OnDuration(FromFfmpegTime(stream.duration,
stream.time_base));
else if (format_context.duration != (int64_t)AV_NOPTS_VALUE)
tag_handler_invoke_duration(handler, handler_ctx,
FromFfmpegTime(format_context.duration,
AV_TIME_BASE_Q));
handler.OnDuration(FromFfmpegTime(format_context.duration,
AV_TIME_BASE_Q));
FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);
FfmpegScanMetadata(format_context, audio_stream, handler);
return true;
}
static bool
ffmpeg_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
ffmpeg_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
AVInputFormat *input_format = ffmpeg_probe(nullptr, is);
if (input_format == nullptr)
@@ -877,7 +873,7 @@ ffmpeg_scan_stream(InputStream &is,
avformat_close_input(&f);
};
return FfmpegScanStream(*f, handler, handler_ctx);
return FfmpegScanStream(*f, handler);
}
/**

@@ -43,46 +43,42 @@ static constexpr struct tag_table ffmpeg_tags[] = {
static void
FfmpegScanTag(TagType type,
AVDictionary *m, const char *name,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
AVDictionaryEntry *mt = nullptr;
while ((mt = av_dict_get(m, name, mt, 0)) != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
type, mt->value);
handler.OnTag(type, mt->value);
}
static void
FfmpegScanPairs(AVDictionary *dict,
const TagHandler &handler, void *handler_ctx)
FfmpegScanPairs(AVDictionary *dict, TagHandler &handler) noexcept
{
AVDictionaryEntry *i = nullptr;
while ((i = av_dict_get(dict, "", i, AV_DICT_IGNORE_SUFFIX)) != nullptr)
tag_handler_invoke_pair(handler, handler_ctx,
i->key, i->value);
handler.OnPair(i->key, i->value);
}
void
FfmpegScanDictionary(AVDictionary *dict,
const TagHandler &handler, void *handler_ctx)
FfmpegScanDictionary(AVDictionary *dict, TagHandler &handler) noexcept
{
if (handler.tag != nullptr) {
if (handler.WantTag()) {
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
FfmpegScanTag(TagType(i), dict, tag_item_names[i],
handler, handler_ctx);
handler);
for (const struct tag_table *i = ffmpeg_tags;
i->name != nullptr; ++i)
FfmpegScanTag(i->type, dict, i->name,
handler, handler_ctx);
handler);
for (const struct tag_table *i = musicbrainz_txxx_tags;
i->name != nullptr; ++i)
FfmpegScanTag(i->type, dict, i->name,
handler, handler_ctx);
handler);
}
if (handler.pair != nullptr)
FfmpegScanPairs(dict, handler, handler_ctx);
if (handler.WantPair())
FfmpegScanPairs(dict, handler);
}

@@ -21,10 +21,9 @@
#define MPD_FFMPEG_METADATA_HXX
struct AVDictionary;
struct TagHandler;
class TagHandler;
void
FfmpegScanDictionary(AVDictionary *dict,
const TagHandler &handler, void *handler_ctx);
FfmpegScanDictionary(AVDictionary *dict, TagHandler &handler) noexcept;
#endif

@@ -69,8 +69,7 @@ flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
}
static bool
flac_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
flac_scan_file(Path path_fs, TagHandler &handler) noexcept
{
FlacMetadataChain chain;
if (!chain.Read(NarrowPath(path_fs))) {
@@ -80,13 +79,12 @@ flac_scan_file(Path path_fs,
return false;
}
chain.Scan(handler, handler_ctx);
chain.Scan(handler);
return true;
}
static bool
flac_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
flac_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
FlacMetadataChain chain;
if (!chain.Read(is)) {
@@ -96,7 +94,7 @@ flac_scan_stream(InputStream &is,
return false;
}
chain.Scan(handler, handler_ctx);
chain.Scan(handler);
return true;
}
@@ -315,8 +313,7 @@ oggflac_init(gcc_unused const ConfigBlock &block)
}
static bool
oggflac_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
oggflac_scan_file(Path path_fs, TagHandler &handler) noexcept
{
FlacMetadataChain chain;
if (!chain.ReadOgg(NarrowPath(path_fs))) {
@@ -326,13 +323,12 @@ oggflac_scan_file(Path path_fs,
return false;
}
chain.Scan(handler, handler_ctx);
chain.Scan(handler);
return true;
}
static bool
oggflac_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
oggflac_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
FlacMetadataChain chain;
if (!chain.ReadOgg(is)) {
@@ -342,7 +338,7 @@ oggflac_scan_stream(InputStream &is,
return false;
}
chain.Scan(handler, handler_ctx);
chain.Scan(handler);
return true;
}

@@ -79,11 +79,11 @@ flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
static bool
flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
const char *name, TagType tag_type,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
const char *value = flac_comment_value(entry, name);
if (value != nullptr) {
tag_handler_invoke_tag(handler, handler_ctx, tag_type, value);
handler.OnTag(tag_type, value);
return true;
}
@@ -92,36 +92,33 @@ flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
static void
flac_scan_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
if (handler.pair != nullptr) {
if (handler.WantPair()) {
const char *comment = (const char *)entry->entry;
const DivideString split(comment, '=');
if (split.IsDefined() && !split.empty())
tag_handler_invoke_pair(handler, handler_ctx,
split.GetFirst(),
split.GetSecond());
handler.OnPair(split.GetFirst(), split.GetSecond());
}
for (const struct tag_table *i = xiph_tags; i->name != nullptr; ++i)
if (flac_copy_comment(entry, i->name, i->type,
handler, handler_ctx))
if (flac_copy_comment(entry, i->name, i->type, handler))
return;
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
if (flac_copy_comment(entry,
tag_item_names[i], (TagType)i,
handler, handler_ctx))
handler))
return;
}
static void
flac_scan_comments(const FLAC__StreamMetadata_VorbisComment *comment,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
for (unsigned i = 0; i < comment->num_comments; ++i)
flac_scan_comment(&comment->comments[i],
handler, handler_ctx);
handler);
}
gcc_pure
@@ -136,18 +133,17 @@ flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) noexcept
void
flac_scan_metadata(const FLAC__StreamMetadata *block,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
switch (block->type) {
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
flac_scan_comments(&block->data.vorbis_comment,
handler, handler_ctx);
handler);
break;
case FLAC__METADATA_TYPE_STREAMINFO:
if (block->data.stream_info.sample_rate > 0)
tag_handler_invoke_duration(handler, handler_ctx,
flac_duration(&block->data.stream_info));
handler.OnDuration(flac_duration(&block->data.stream_info));
break;
default:
@@ -159,12 +155,13 @@ Tag
flac_vorbis_comments_to_tag(const FLAC__StreamMetadata_VorbisComment *comment)
{
TagBuilder tag_builder;
flac_scan_comments(comment, add_tag_handler, &tag_builder);
AddTagHandler h(tag_builder);
flac_scan_comments(comment, h);
return tag_builder.Commit();
}
void
FlacMetadataChain::Scan(const TagHandler &handler, void *handler_ctx)
FlacMetadataChain::Scan(TagHandler &handler) noexcept
{
FLACMetadataIterator iterator(*this);
@@ -173,6 +170,6 @@ FlacMetadataChain::Scan(const TagHandler &handler, void *handler_ctx)
if (block == nullptr)
break;
flac_scan_metadata(block, handler, handler_ctx);
flac_scan_metadata(block, handler);
} while (iterator.Next());
}

@@ -25,7 +25,7 @@
#include <FLAC/metadata.h>
struct TagHandler;
class TagHandler;
class MixRampInfo;
class FlacMetadataChain {
@@ -82,7 +82,7 @@ public:
return FLAC__Metadata_ChainStatusString[GetStatus()];
}
void Scan(const TagHandler &handler, void *handler_ctx);
void Scan(TagHandler &handler) noexcept;
};
class FLACMetadataIterator {
@@ -126,6 +126,6 @@ flac_vorbis_comments_to_tag(const FLAC__StreamMetadata_VorbisComment *comment);
void
flac_scan_metadata(const FLAC__StreamMetadata *block,
const TagHandler &handler, void *handler_ctx);
TagHandler &handler) noexcept;
#endif

@@ -193,8 +193,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
static bool
fluidsynth_scan_file(Path path_fs,
gcc_unused const TagHandler &handler,
gcc_unused void *handler_ctx) noexcept
gcc_unused TagHandler &handler) noexcept
{
return fluid_is_midifile(path_fs.c_str());
}

@@ -215,15 +215,13 @@ gme_file_decode(DecoderClient &client, Path path_fs)
static void
ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
if (info.play_length > 0)
tag_handler_invoke_duration(handler, handler_ctx,
SongTime::FromMS(info.play_length));
handler.OnDuration(SongTime::FromMS(info.play_length));
if (track_count > 1)
tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK,
StringFormat<16>("%u", song_num + 1));
handler.OnTag(TAG_TRACK, StringFormat<16>("%u", song_num + 1));
if (info.song != nullptr) {
if (track_count > 1) {
@@ -232,33 +230,26 @@ ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count,
StringFormat<1024>("%s (%u/%d)",
info.song, song_num + 1,
track_count);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
handler.OnTag(TAG_TITLE, tag_title);
} else
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, info.song);
handler.OnTag(TAG_TITLE, info.song);
}
if (info.author != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
TAG_ARTIST, info.author);
handler.OnTag(TAG_ARTIST, info.author);
if (info.game != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
TAG_ALBUM, info.game);
handler.OnTag(TAG_ALBUM, info.game);
if (info.comment != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
TAG_COMMENT, info.comment);
handler.OnTag(TAG_COMMENT, info.comment);
if (info.copyright != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
TAG_DATE, info.copyright);
handler.OnTag(TAG_DATE, info.copyright);
}
static bool
ScanMusicEmu(Music_Emu *emu, unsigned song_num,
const TagHandler &handler, void *handler_ctx)
ScanMusicEmu(Music_Emu *emu, unsigned song_num, TagHandler &handler) noexcept
{
gme_info_t *ti;
const char *gme_err = gme_track_info(emu, &ti, song_num);
@@ -271,14 +262,12 @@ ScanMusicEmu(Music_Emu *emu, unsigned song_num,
AtScopeExit(ti) { gme_free_info(ti); };
ScanGmeInfo(*ti, song_num, gme_track_count(emu),
handler, handler_ctx);
ScanGmeInfo(*ti, song_num, gme_track_count(emu), handler);
return true;
}
static bool
gme_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
gme_scan_file(Path path_fs, TagHandler &handler) noexcept
{
const auto container = ParseContainerPath(path_fs);
@@ -289,7 +278,7 @@ gme_scan_file(Path path_fs,
AtScopeExit(emu) { gme_delete(emu); };
return ScanMusicEmu(emu, container.track, handler, handler_ctx);
return ScanMusicEmu(emu, container.track, handler);
}
static std::forward_list<DetachedSong>
@@ -316,8 +305,8 @@ gme_container_scan(Path path_fs)
auto tail = list.before_begin();
for (unsigned i = 0; i < num_songs; ++i) {
ScanMusicEmu(emu, i,
add_tag_handler, &tag_builder);
AddTagHandler h(tag_builder);
ScanMusicEmu(emu, i, h);
const auto track_name =
StringFormat<64>(SUBTUNE_PREFIX "%03u.%s", i+1,

@@ -1062,16 +1062,14 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
}
static bool
mad_decoder_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
mad_decoder_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
const auto result = mad_decoder_total_file_time(is);
if (!result.first)
return false;
if (!result.second.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx,
SongTime(result.second));
handler.OnDuration(SongTime(result.second));
return true;
}

@@ -185,8 +185,7 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
}
static bool
mikmod_decoder_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
mikmod_decoder_scan_file(Path path_fs, TagHandler &handler) noexcept
{
/* deconstify the path because libmikmod wants a non-const
string pointer */
@@ -204,8 +203,7 @@ mikmod_decoder_scan_file(Path path_fs,
char *title = Player_LoadTitle(path2);
if (title != nullptr) {
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, title);
handler.OnTag(TAG_TITLE, title);
#if (LIBMIKMOD_VERSION >= 0x030200)
MikMod_free(title);
#else

@@ -175,20 +175,17 @@ mod_decode(DecoderClient &client, InputStream &is)
}
static bool
modplug_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
modplug_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
ModPlugFile *f = LoadModPlugFile(nullptr, is);
if (f == nullptr)
return false;
tag_handler_invoke_duration(handler, handler_ctx,
SongTime::FromMS(ModPlug_GetLength(f)));
handler.OnDuration(SongTime::FromMS(ModPlug_GetLength(f)));
const char *title = ModPlug_GetName(f);
if (title != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, title);
handler.OnTag(TAG_TITLE, title);
ModPlug_Unload(f);

@@ -257,14 +257,13 @@ mpcdec_get_file_duration(InputStream &is)
}
static bool
mpcdec_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
mpcdec_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
const auto duration = mpcdec_get_file_duration(is);
if (duration.IsNegative())
return false;
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
handler.OnDuration(SongTime(duration));
return true;
}

@@ -279,8 +279,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
}
static bool
mpd_mpg123_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
mpd_mpg123_scan_file(Path path_fs, TagHandler &handler) noexcept
{
int error;
mpg123_handle *const handle = mpg123_new(nullptr, &error);
@@ -316,7 +315,7 @@ mpd_mpg123_scan_file(Path path_fs,
SongTime::FromScale<uint64_t>(num_samples,
audio_format.sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, duration);
handler.OnDuration(duration);
return true;
}

@@ -207,10 +207,9 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
rgi.Clear();
TagBuilder tag_builder;
AddTagHandler h(tag_builder);
if (ScanOpusTags(packet.packet, packet.bytes,
&rgi,
add_tag_handler, &tag_builder) &&
if (ScanOpusTags(packet.packet, packet.bytes, &rgi, h) &&
!tag_builder.empty()) {
client.SubmitReplayGain(&rgi);
@@ -314,7 +313,7 @@ ReadAndParseOpusHead(OggSyncState &sync, OggStreamState &stream,
static bool
ReadAndVisitOpusTags(OggSyncState &sync, OggStreamState &stream,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler)
{
ogg_packet packet;
@@ -322,12 +321,12 @@ ReadAndVisitOpusTags(OggSyncState &sync, OggStreamState &stream,
IsOpusTags(packet) &&
ScanOpusTags(packet.packet, packet.bytes,
nullptr,
handler, handler_ctx);
handler);
}
static void
VisitOpusDuration(InputStream &is, OggSyncState &sync, OggStreamState &stream,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler)
{
ogg_packet packet;
@@ -335,13 +334,12 @@ VisitOpusDuration(InputStream &is, OggSyncState &sync, OggStreamState &stream,
const auto duration =
SongTime::FromScale<uint64_t>(packet.granulepos,
opus_sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, duration);
handler.OnDuration(duration);
}
}
static bool
mpd_opus_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
mpd_opus_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
InputStreamReader reader(is);
OggSyncState oy(reader);
@@ -354,10 +352,10 @@ mpd_opus_scan_stream(InputStream &is,
unsigned channels;
if (!ReadAndParseOpusHead(oy, os, channels) ||
!ReadAndVisitOpusTags(oy, os, handler, handler_ctx))
!ReadAndVisitOpusTags(oy, os, handler))
return false;
VisitOpusDuration(is, oy, os, handler, handler_ctx);
VisitOpusDuration(is, oy, os, handler);
return true;
}

@@ -43,7 +43,7 @@ ParseOpusTagName(const char *name) noexcept
static void
ScanOneOpusTag(const char *name, const char *value,
ReplayGainInfo *rgi,
const TagHandler &handler, void *ctx)
TagHandler &handler) noexcept
{
if (rgi != nullptr && strcmp(name, "R128_TRACK_GAIN") == 0) {
/* R128_TRACK_GAIN is a Q7.8 fixed point number in
@@ -63,25 +63,25 @@ ScanOneOpusTag(const char *name, const char *value,
rgi->album.gain = double(l) / 256.;
}
tag_handler_invoke_pair(handler, ctx, name, value);
handler.OnPair(name, value);
if (handler.tag != nullptr) {
if (handler.WantTag()) {
TagType t = ParseOpusTagName(name);
if (t != TAG_NUM_OF_ITEM_TYPES)
tag_handler_invoke_tag(handler, ctx, t, value);
handler.OnTag(t, value);
}
}
bool
ScanOpusTags(const void *data, size_t size,
ReplayGainInfo *rgi,
const TagHandler &handler, void *ctx)
TagHandler &handler) noexcept
{
OpusReader r(data, size);
if (!r.Expect("OpusTags", 8))
return false;
if (handler.pair == nullptr && handler.tag == nullptr)
if (!handler.WantPair() && !handler.WantTag())
return true;
if (!r.SkipString())
@@ -100,7 +100,7 @@ ScanOpusTags(const void *data, size_t size,
if (eq != nullptr && eq > p) {
*eq = 0;
ScanOneOpusTag(p, eq + 1, rgi, handler, ctx);
ScanOneOpusTag(p, eq + 1, rgi, handler);
}
delete[] p;

@@ -25,11 +25,11 @@
#include <stddef.h>
struct ReplayGainInfo;
struct TagHandler;
class TagHandler;
bool
ScanOpusTags(const void *data, size_t size,
ReplayGainInfo *rgi,
const TagHandler &handler, void *ctx);
TagHandler &handler) noexcept;
#endif

@@ -405,7 +405,7 @@ GetInfoString(const SidTuneInfo &info, unsigned i) noexcept
static void
ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
/* title */
const char *title = GetInfoString(info, 0);
@@ -416,31 +416,26 @@ ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks,
const auto tag_title =
StringFormat<1024>("%s (%u/%u)",
title, track, n_tracks);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
handler.OnTag(TAG_TITLE, tag_title);
} else
tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, title);
handler.OnTag(TAG_TITLE, title);
/* artist */
const char *artist = GetInfoString(info, 1);
if (artist != nullptr)
tag_handler_invoke_tag(handler, handler_ctx, TAG_ARTIST,
artist);
handler.OnTag(TAG_ARTIST, artist);
/* date */
const char *date = GetInfoString(info, 2);
if (date != nullptr)
tag_handler_invoke_tag(handler, handler_ctx, TAG_DATE,
date);
handler.OnTag(TAG_DATE, date);
/* track */
tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK,
StringFormat<16>("%u", track));
handler.OnTag(TAG_TRACK, StringFormat<16>("%u", track));
}
static bool
sidplay_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
sidplay_scan_file(Path path_fs, TagHandler &handler) noexcept
{
const auto container = ParseContainerPath(path_fs);
const unsigned song_num = container.track;
@@ -463,13 +458,12 @@ sidplay_scan_file(Path path_fs,
const unsigned n_tracks = info.songs;
#endif
ScanSidTuneInfo(info, song_num, n_tracks, handler, handler_ctx);
ScanSidTuneInfo(info, song_num, n_tracks, handler);
/* time */
const auto duration = get_song_length(tune);
if (!duration.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx,
SongTime(duration));
handler.OnDuration(SongTime(duration));
return true;
}
@@ -506,8 +500,8 @@ sidplay_container_scan(Path path_fs)
for (unsigned i = 1; i <= n_tracks; ++i) {
tune.selectSong(i);
ScanSidTuneInfo(info, i, n_tracks,
add_tag_handler, &tag_builder);
AddTagHandler h(tag_builder);
ScanSidTuneInfo(info, i, n_tracks, h);
char track_name[32];
/* Construct container/tune path names, eg.

@@ -240,11 +240,11 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
static void
sndfile_handle_tag(SNDFILE *sf, int str, TagType tag,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
const char *value = sf_get_string(sf, str);
if (value != nullptr)
tag_handler_invoke_tag(handler, handler_ctx, tag, value);
handler.OnTag(tag, value);
}
static constexpr struct {
@@ -261,8 +261,7 @@ static constexpr struct {
};
static bool
sndfile_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
sndfile_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
SF_INFO info;
@@ -280,11 +279,10 @@ sndfile_scan_stream(InputStream &is,
return false;
}
tag_handler_invoke_duration(handler, handler_ctx,
sndfile_duration(info));
handler.OnDuration(sndfile_duration(info));
for (auto i : sndfile_tags)
sndfile_handle_tag(sf, i.str, i.tag, handler, handler_ctx);
sndfile_handle_tag(sf, i.str, i.tag, handler);
sf_close(sf);

@@ -348,7 +348,7 @@ static void
VisitVorbisDuration(InputStream &is,
OggSyncState &sync, OggStreamState &stream,
unsigned sample_rate,
const TagHandler &handler, void *handler_ctx)
TagHandler &handler) noexcept
{
ogg_packet packet;
@@ -358,12 +358,11 @@ VisitVorbisDuration(InputStream &is,
const auto duration =
SongTime::FromScale<uint64_t>(packet.granulepos,
sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, duration);
handler.OnDuration(duration);
}
static bool
vorbis_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
vorbis_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
/* initialize libogg */
@@ -397,12 +396,11 @@ vorbis_scan_stream(InputStream &is,
/* visit the Vorbis comments we just read */
vorbis_comments_scan(vc.user_comments,
handler, handler_ctx);
vorbis_comments_scan(vc.user_comments, handler);
/* check the song duration by locating the e_o_s packet */
VisitVorbisDuration(is, sync, stream, vi.rate, handler, handler_ctx);
VisitVorbisDuration(is, sync, stream, vi.rate, handler);
return true;
}

@@ -578,8 +578,7 @@ wavpack_filedecode(DecoderClient &client, Path path_fs)
* Reads metainfo from the specified file.
*/
static bool
wavpack_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
wavpack_scan_file(Path path_fs, TagHandler &handler) noexcept
{
WavpackContext *wpc;
@@ -595,14 +594,13 @@ wavpack_scan_file(Path path_fs,
const auto duration = GetDuration(wpc);
if (!duration.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
handler.OnDuration(SongTime(duration));
return true;
}
static bool
wavpack_scan_stream(InputStream &is,
const TagHandler &handler, void *handler_ctx) noexcept
wavpack_scan_stream(InputStream &is, TagHandler &handler) noexcept
{
WavpackInput isp(nullptr, is);
@@ -620,7 +618,7 @@ wavpack_scan_stream(InputStream &is,
const auto duration = GetDuration(wpc);
if (!duration.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
handler.OnDuration(SongTime(duration));
return true;
}

@@ -126,8 +126,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
}
static bool
wildmidi_scan_file(Path path_fs,
const TagHandler &handler, void *handler_ctx) noexcept
wildmidi_scan_file(Path path_fs, TagHandler &handler) noexcept
{
midi *wm = WildMidi_Open(path_fs.c_str());
if (wm == nullptr)
@@ -142,7 +141,7 @@ wildmidi_scan_file(Path path_fs,
const auto duration =
SongTime::FromScale<uint64_t>(info->approx_total_samples,
WILDMIDI_SAMPLE_RATE);
tag_handler_invoke_duration(handler, handler_ctx, duration);
handler.OnDuration(duration);
WildMidi_Close(wm);