aboutsummaryrefslogtreecommitdiff
path: root/src/decoder
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-02-11 19:12:02 +0100
committerMax Kellermann <max@duempel.org>2012-02-11 17:04:29 +0100
commit5d73215a8dad922c8e383f3837f3ec9e26503389 (patch)
tree8fc4b96d93a907054a05d3250f97bf4f68c6df85 /src/decoder
parentb7356bc526dbbd6fa00d40caff2addec10ae7c7e (diff)
decoder_plugin: scan tags with callback table
Pass a callback table to scan_file() and scan_stream(), instead of returning a tag object.
Diffstat (limited to 'src/decoder')
-rw-r--r--src/decoder/audiofile_decoder_plugin.c17
-rw-r--r--src/decoder/dsdiff_decoder_plugin.c14
-rw-r--r--src/decoder/faad_decoder_plugin.c16
-rw-r--r--src/decoder/ffmpeg_decoder_plugin.c31
-rw-r--r--src/decoder/ffmpeg_metadata.c20
-rw-r--r--src/decoder/ffmpeg_metadata.h5
-rw-r--r--src/decoder/flac_decoder_plugin.c30
-rw-r--r--src/decoder/flac_metadata.c78
-rw-r--r--src/decoder/flac_metadata.h10
-rw-r--r--src/decoder/gme_decoder_plugin.c39
-rw-r--r--src/decoder/mad_decoder_plugin.c16
-rw-r--r--src/decoder/modplug_decoder_plugin.c28
-rw-r--r--src/decoder/mpcdec_decoder_plugin.c16
-rw-r--r--src/decoder/mpg123_decoder_plugin.c24
-rw-r--r--src/decoder/sidplay_decoder_plugin.cxx26
-rw-r--r--src/decoder/sndfile_decoder_plugin.c28
-rw-r--r--src/decoder/vorbis_comments.c35
-rw-r--r--src/decoder/vorbis_comments.h5
-rw-r--r--src/decoder/vorbis_decoder_plugin.c21
-rw-r--r--src/decoder/wavpack_decoder_plugin.c22
-rw-r--r--src/decoder/wildmidi_decoder_plugin.c18
21 files changed, 286 insertions, 213 deletions
diff --git a/src/decoder/audiofile_decoder_plugin.c b/src/decoder/audiofile_decoder_plugin.c
index 8d6236a5..7db7c751 100644
--- a/src/decoder/audiofile_decoder_plugin.c
+++ b/src/decoder/audiofile_decoder_plugin.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
+#include "tag_handler.h"
#include <audiofile.h>
#include <af_vfs.h>
@@ -222,20 +223,20 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
afCloseFile(af_fp);
}
-static struct tag *audiofile_tag_dup(const char *file)
+static bool
+audiofile_scan_file(const char *file,
+ const struct tag_handler *handler, void *handler_ctx)
{
- struct tag *ret = NULL;
int total_time = audiofile_get_duration(file);
- if (total_time >= 0) {
- ret = tag_new();
- ret->time = total_time;
- } else {
+ if (total_time < 0) {
g_debug("Failed to get total song time from: %s\n",
file);
+ return false;
}
- return ret;
+ tag_handler_invoke_duration(handler, handler_ctx, total_time);
+ return true;
}
static const char *const audiofile_suffixes[] = {
@@ -251,7 +252,7 @@ static const char *const audiofile_mime_types[] = {
const struct decoder_plugin audiofile_decoder_plugin = {
.name = "audiofile",
.stream_decode = audiofile_stream_decode,
- .tag_dup = audiofile_tag_dup,
+ .scan_file = audiofile_scan_file,
.suffixes = audiofile_suffixes,
.mime_types = audiofile_mime_types,
};
diff --git a/src/decoder/dsdiff_decoder_plugin.c b/src/decoder/dsdiff_decoder_plugin.c
index 47b71d8c..391a5bf7 100644
--- a/src/decoder/dsdiff_decoder_plugin.c
+++ b/src/decoder/dsdiff_decoder_plugin.c
@@ -433,8 +433,10 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
dsd2pcm_destroy(dsd2pcm[i]);
}
-static struct tag *
-dsdiff_stream_tag(struct input_stream *is)
+static bool
+dsdiff_scan_stream(struct input_stream *is,
+ G_GNUC_UNUSED const struct tag_handler *handler,
+ G_GNUC_UNUSED void *handler_ctx)
{
struct dsdiff_metadata metadata = {
.sample_rate = 0,
@@ -443,17 +445,17 @@ dsdiff_stream_tag(struct input_stream *is)
struct dsdiff_chunk_header chunk_header;
if (!dsdiff_read_metadata(NULL, is, &metadata, &chunk_header))
- return NULL;
+ return false;
struct audio_format audio_format;
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
SAMPLE_FORMAT_S24_P32,
metadata.channels, NULL))
/* refuse to parse files which we cannot play anyway */
- return NULL;
+ return false;
/* no total time estimate, no tags implemented yet */
- return tag_new();
+ return true;
}
static const char *const dsdiff_suffixes[] = {
@@ -470,7 +472,7 @@ const struct decoder_plugin dsdiff_decoder_plugin = {
.name = "dsdiff",
.init = dsdiff_init,
.stream_decode = dsdiff_stream_decode,
- .stream_tag = dsdiff_stream_tag,
+ .scan_stream = dsdiff_scan_stream,
.suffixes = dsdiff_suffixes,
.mime_types = dsdiff_mime_types,
};
diff --git a/src/decoder/faad_decoder_plugin.c b/src/decoder/faad_decoder_plugin.c
index 91aa5392..911f033b 100644
--- a/src/decoder/faad_decoder_plugin.c
+++ b/src/decoder/faad_decoder_plugin.c
@@ -21,6 +21,7 @@
#include "decoder_api.h"
#include "decoder_buffer.h"
#include "audio_check.h"
+#include "tag_handler.h"
#define AAC_MAX_CHANNELS 6
@@ -487,18 +488,17 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
faacDecClose(decoder);
}
-static struct tag *
-faad_stream_tag(struct input_stream *is)
+static bool
+faad_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
int file_time = faad_get_file_time(is);
- struct tag *tag;
if (file_time < 0)
- return NULL;
+ return false;
- tag = tag_new();
- tag->time = file_time;
- return tag;
+ tag_handler_invoke_duration(handler, handler_ctx, file_time);
+ return true;
}
static const char *const faad_suffixes[] = { "aac", NULL };
@@ -509,7 +509,7 @@ static const char *const faad_mime_types[] = {
const struct decoder_plugin faad_decoder_plugin = {
.name = "faad",
.stream_decode = faad_stream_decode,
- .stream_tag = faad_stream_tag,
+ .scan_stream = faad_scan_stream,
.suffixes = faad_suffixes,
.mime_types = faad_mime_types,
};
diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c
index 20d24f13..6ad10026 100644
--- a/src/decoder/ffmpeg_decoder_plugin.c
+++ b/src/decoder/ffmpeg_decoder_plugin.c
@@ -21,6 +21,7 @@
#include "decoder_api.h"
#include "audio_check.h"
#include "ffmpeg_metadata.h"
+#include "tag_handler.h"
#include <glib.h>
@@ -570,22 +571,23 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
}
//no tag reading in ffmpeg, check if playable
-static struct tag *
-ffmpeg_stream_tag(struct input_stream *is)
+static bool
+ffmpeg_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVInputFormat *input_format = ffmpeg_probe(NULL, is);
if (input_format == NULL)
- return NULL;
+ return false;
struct mpd_ffmpeg_stream *stream = mpd_ffmpeg_stream_open(NULL, is);
if (stream == NULL)
- return NULL;
+ return false;
AVFormatContext *f = NULL;
if (mpd_ffmpeg_open_input(&f, stream->io, is->uri,
input_format) != 0) {
mpd_ffmpeg_stream_close(stream);
- return NULL;
+ return false;
}
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,6,0)
@@ -601,23 +603,22 @@ ffmpeg_stream_tag(struct input_stream *is)
av_close_input_stream(f);
#endif
mpd_ffmpeg_stream_close(stream);
- return NULL;
+ return false;
}
- struct tag *tag = tag_new();
-
- tag->time = f->duration != (int64_t)AV_NOPTS_VALUE
- ? f->duration / AV_TIME_BASE
- : 0;
+ if (f->duration != (int64_t)AV_NOPTS_VALUE)
+ tag_handler_invoke_duration(handler, handler_ctx,
+ f->duration / AV_TIME_BASE);
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,101,0)
av_metadata_conv(f, NULL, f->iformat->metadata_conv);
#endif
- ffmpeg_copy_dictionary(tag, f->metadata);
+ ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
int idx = ffmpeg_find_audio_stream(f);
if (idx >= 0)
- ffmpeg_copy_dictionary(tag, f->streams[idx]->metadata);
+ ffmpeg_scan_dictionary(f->streams[idx]->metadata,
+ handler, handler_ctx);
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
avformat_close_input(&f);
@@ -626,7 +627,7 @@ ffmpeg_stream_tag(struct input_stream *is)
#endif
mpd_ffmpeg_stream_close(stream);
- return tag;
+ return true;
}
/**
@@ -745,7 +746,7 @@ const struct decoder_plugin ffmpeg_decoder_plugin = {
.name = "ffmpeg",
.init = ffmpeg_init,
.stream_decode = ffmpeg_decode,
- .stream_tag = ffmpeg_stream_tag,
+ .scan_stream = ffmpeg_scan_stream,
.suffixes = ffmpeg_suffixes,
.mime_types = ffmpeg_mime_types
};
diff --git a/src/decoder/ffmpeg_metadata.c b/src/decoder/ffmpeg_metadata.c
index d091afbc..5325c1ca 100644
--- a/src/decoder/ffmpeg_metadata.c
+++ b/src/decoder/ffmpeg_metadata.c
@@ -19,8 +19,8 @@
#include "config.h"
#include "ffmpeg_metadata.h"
-#include "tag.h"
#include "tag_table.h"
+#include "tag_handler.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "ffmpeg"
@@ -39,23 +39,27 @@ static const struct tag_table ffmpeg_tags[] = {
};
static void
-ffmpeg_copy_metadata(struct tag *tag, enum tag_type type,
- AVDictionary *m, const char *name)
+ffmpeg_copy_metadata(enum tag_type type,
+ AVDictionary *m, const char *name,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVDictionaryEntry *mt = NULL;
while ((mt = av_dict_get(m, name, mt, 0)) != NULL)
- tag_add_item(tag, type, mt->value);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ type, mt->value);
}
void
-ffmpeg_copy_dictionary(struct tag *tag, AVDictionary *dict)
+ffmpeg_scan_dictionary(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
{
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- ffmpeg_copy_metadata(tag, i,
- dict, tag_item_names[i]);
+ ffmpeg_copy_metadata(i, dict, tag_item_names[i],
+ handler, handler_ctx);
for (const struct tag_table *i = ffmpeg_tags;
i->name != NULL; ++i)
- ffmpeg_copy_metadata(tag, i->type, dict, i->name);
+ ffmpeg_copy_metadata(i->type, dict, i->name,
+ handler, handler_ctx);
}
diff --git a/src/decoder/ffmpeg_metadata.h b/src/decoder/ffmpeg_metadata.h
index fc10e1eb..60658f47 100644
--- a/src/decoder/ffmpeg_metadata.h
+++ b/src/decoder/ffmpeg_metadata.h
@@ -32,9 +32,10 @@
#define av_dict_get av_metadata_get
#endif
-struct tag;
+struct tag_handler;
void
-ffmpeg_copy_dictionary(struct tag *tag, AVDictionary *dict);
+ffmpeg_scan_dictionary(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx);
#endif
diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/flac_decoder_plugin.c
index 9dc1898d..fb0b3502 100644
--- a/src/decoder/flac_decoder_plugin.c
+++ b/src/decoder/flac_decoder_plugin.c
@@ -191,10 +191,11 @@ flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
return flac_common_write(data, frame, buf, nbytes);
}
-static struct tag *
-flac_tag_dup(const char *file)
+static bool
+flac_scan_file(const char *file,
+ const struct tag_handler *handler, void *handler_ctx)
{
- return flac_tag_load(file, NULL);
+ return flac_scan_file2(file, NULL, handler, handler_ctx);
}
/**
@@ -400,38 +401,33 @@ oggflac_init(G_GNUC_UNUSED const struct config_param *param)
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
-static struct tag *
-oggflac_tag_dup(const char *file)
+static bool
+oggflac_scan_file(const char *file,
+ const struct tag_handler *handler, void *handler_ctx)
{
- struct tag *ret = NULL;
FLAC__Metadata_Iterator *it;
FLAC__StreamMetadata *block;
FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
if (!(FLAC__metadata_chain_read_ogg(chain, file))) {
FLAC__metadata_chain_delete(chain);
- return NULL;
+ return false;
}
it = FLAC__metadata_iterator_new();
FLAC__metadata_iterator_init(it, chain);
- ret = tag_new();
do {
if (!(block = FLAC__metadata_iterator_get_block(it)))
break;
- flac_tag_apply_metadata(ret, NULL, block);
+ flac_scan_metadata(NULL, block,
+ handler, handler_ctx);
} while (FLAC__metadata_iterator_next(it));
FLAC__metadata_iterator_delete(it);
- if (!tag_is_defined(ret)) {
- tag_free(ret);
- ret = NULL;
- }
-
FLAC__metadata_chain_delete(chain);
- return ret;
+ return true;
}
static void
@@ -464,7 +460,7 @@ const struct decoder_plugin oggflac_decoder_plugin = {
.init = oggflac_init,
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
.stream_decode = oggflac_decode,
- .tag_dup = oggflac_tag_dup,
+ .scan_file = oggflac_scan_file,
.suffixes = oggflac_suffixes,
.mime_types = oggflac_mime_types
#endif
@@ -484,7 +480,7 @@ static const char *const flac_mime_types[] = {
const struct decoder_plugin flac_decoder_plugin = {
.name = "flac",
.stream_decode = flac_decode,
- .tag_dup = flac_tag_dup,
+ .scan_file = flac_scan_file,
.suffixes = flac_suffixes,
.mime_types = flac_mime_types,
};
diff --git a/src/decoder/flac_metadata.c b/src/decoder/flac_metadata.c
index 30dedda3..9e138ef9 100644
--- a/src/decoder/flac_metadata.c
+++ b/src/decoder/flac_metadata.c
@@ -21,6 +21,7 @@
#include "flac_metadata.h"
#include "replay_gain_info.h"
#include "tag.h"
+#include "tag_handler.h"
#include "tag_table.h"
#include <glib.h>
@@ -164,17 +165,19 @@ flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
* the comment value into the tag.
*/
static bool
-flac_copy_comment(struct tag *tag,
- const FLAC__StreamMetadata_VorbisComment_Entry *entry,
+flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
const char *name, enum tag_type tag_type,
- const char *char_tnum)
+ const char *char_tnum,
+ const struct tag_handler *handler, void *handler_ctx)
{
const char *value;
size_t value_length;
value = flac_comment_value(entry, name, char_tnum, &value_length);
if (value != NULL) {
- tag_add_item_n(tag, tag_type, value, value_length);
+ char *p = g_strndup(value, value_length);
+ tag_handler_invoke_tag(handler, handler_ctx, tag_type, p);
+ g_free(p);
return true;
}
@@ -189,42 +192,47 @@ static const struct tag_table flac_tags[] = {
};
static void
-flac_parse_comment(struct tag *tag, const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment_Entry *entry)
+flac_scan_comment(const char *char_tnum,
+ const FLAC__StreamMetadata_VorbisComment_Entry *entry,
+ const struct tag_handler *handler, void *handler_ctx)
{
- assert(tag != NULL);
-
for (const struct tag_table *i = flac_tags; i->name != NULL; ++i)
- if (flac_copy_comment(tag, entry, i->name, i->type, char_tnum))
+ if (flac_copy_comment(entry, i->name, i->type, char_tnum,
+ handler, handler_ctx))
return;
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- if (flac_copy_comment(tag, entry,
- tag_item_names[i], i, char_tnum))
+ if (flac_copy_comment(entry,
+ tag_item_names[i], i, char_tnum,
+ handler, handler_ctx))
return;
}
-void
-flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment *comment)
+static void
+flac_scan_comments(const char *char_tnum,
+ const FLAC__StreamMetadata_VorbisComment *comment,
+ const struct tag_handler *handler, void *handler_ctx)
{
for (unsigned i = 0; i < comment->num_comments; ++i)
- flac_parse_comment(tag, char_tnum, &comment->comments[i]);
+ flac_scan_comment(char_tnum, &comment->comments[i],
+ handler, handler_ctx);
}
void
-flac_tag_apply_metadata(struct tag *tag, const char *track,
- const FLAC__StreamMetadata *block)
+flac_scan_metadata(const char *track,
+ const FLAC__StreamMetadata *block,
+ const struct tag_handler *handler, void *handler_ctx)
{
switch (block->type) {
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- flac_vorbis_comments_to_tag(tag, track,
- &block->data.vorbis_comment);
+ flac_scan_comments(track, &block->data.vorbis_comment,
+ handler, handler_ctx);
break;
case FLAC__METADATA_TYPE_STREAMINFO:
if (block->data.stream_info.sample_rate > 0)
- tag->time = flac_duration(&block->data.stream_info);
+ tag_handler_invoke_duration(handler, handler_ctx,
+ flac_duration(&block->data.stream_info));
break;
default:
@@ -232,10 +240,18 @@ flac_tag_apply_metadata(struct tag *tag, const char *track,
}
}
-struct tag *
-flac_tag_load(const char *file, const char *char_tnum)
+void
+flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
+ const FLAC__StreamMetadata_VorbisComment *comment)
+{
+ flac_scan_comments(char_tnum, comment,
+ &add_tag_handler, tag);
+}
+
+bool
+flac_scan_file2(const char *file, const char *char_tnum,
+ const struct tag_handler *handler, void *handler_ctx)
{
- struct tag *tag;
FLAC__Metadata_SimpleIterator *it;
FLAC__StreamMetadata *block = NULL;
@@ -262,22 +278,30 @@ flac_tag_load(const char *file, const char *char_tnum)
g_debug("Reading '%s' metadata gave the following error: %s\n",
file, err);
FLAC__metadata_simple_iterator_delete(it);
- return NULL;
+ return false;
}
- tag = tag_new();
do {
block = FLAC__metadata_simple_iterator_get_block(it);
if (!block)
break;
- flac_tag_apply_metadata(tag, char_tnum, block);
+ flac_scan_metadata(char_tnum, block, handler, handler_ctx);
FLAC__metadata_object_delete(block);
} while (FLAC__metadata_simple_iterator_next(it));
FLAC__metadata_simple_iterator_delete(it);
- if (!tag_is_defined(tag)) {
+ return true;
+}
+
+struct tag *
+flac_tag_load(const char *file, const char *char_tnum)
+{
+ struct tag *tag = tag_new();
+
+ if (!flac_scan_file2(file, char_tnum, &add_tag_handler, tag) ||
+ tag_is_empty(tag)) {
tag_free(tag);
tag = NULL;
}
diff --git a/src/decoder/flac_metadata.h b/src/decoder/flac_metadata.h
index 01bc1924..3c463d5d 100644
--- a/src/decoder/flac_metadata.h
+++ b/src/decoder/flac_metadata.h
@@ -24,6 +24,7 @@
#include <stdbool.h>
#include <FLAC/metadata.h>
+struct tag_handler;
struct tag;
struct replay_gain_info;
@@ -49,8 +50,13 @@ flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
const FLAC__StreamMetadata_VorbisComment *comment);
void
-flac_tag_apply_metadata(struct tag *tag, const char *track,
- const FLAC__StreamMetadata *block);
+flac_scan_metadata(const char *track,
+ const FLAC__StreamMetadata *block,
+ const struct tag_handler *handler, void *handler_ctx);
+
+bool
+flac_scan_file2(const char *file, const char *char_tnum,
+ const struct tag_handler *handler, void *handler_ctx);
struct tag *
flac_tag_load(const char *file, const char *char_tnum);
diff --git a/src/decoder/gme_decoder_plugin.c b/src/decoder/gme_decoder_plugin.c
index 8fdc39fd..237a1deb 100644
--- a/src/decoder/gme_decoder_plugin.c
+++ b/src/decoder/gme_decoder_plugin.c
@@ -2,6 +2,7 @@
#include "../decoder_api.h"
#include "audio_check.h"
#include "uri.h"
+#include "tag_handler.h"
#include <glib.h>
#include <assert.h>
@@ -180,8 +181,9 @@ gme_file_decode(struct decoder *decoder, const char *path_fs)
gme_delete(emu);
}
-static struct tag *
-gme_tag_dup(const char *path_fs)
+static bool
+gme_scan_file(const char *path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
{
Music_Emu *emu;
gme_info_t *ti;
@@ -194,42 +196,49 @@ gme_tag_dup(const char *path_fs)
g_free(path_container);
if (gme_err != NULL) {
g_warning("%s", gme_err);
- return NULL;
+ return false;
}
if((gme_err = gme_track_info(emu, &ti, song_num)) != NULL){
g_warning("%s", gme_err);
gme_delete(emu);
- return NULL;
+ return false;
}
assert(ti != NULL);
- struct tag *tag = tag_new();
-
if(ti->length > 0)
- tag->time = ti->length / 1000;
+ tag_handler_invoke_duration(handler, handler_ctx,
+ ti->length / 100);
+
if(ti->song != NULL){
if(gme_track_count(emu) > 1){
/* start numbering subtunes from 1 */
char *tag_title=g_strdup_printf("%s (%d/%d)",
ti->song, song_num+1, gme_track_count(emu));
- tag_add_item(tag, TAG_TITLE, tag_title);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_TITLE, tag_title);
g_free(tag_title);
}else
- tag_add_item(tag, TAG_TITLE, ti->song);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_TITLE, ti->song);
}
if(ti->author != NULL)
- tag_add_item(tag, TAG_ARTIST, ti->author);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_ARTIST, ti->author);
if(ti->game != NULL)
- tag_add_item(tag, TAG_ALBUM, ti->game);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_ALBUM, ti->game);
if(ti->comment != NULL)
- tag_add_item(tag, TAG_COMMENT, ti->comment);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_COMMENT, ti->comment);
if(ti->copyright != NULL)
- tag_add_item(tag, TAG_DATE, ti->copyright);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_DATE, ti->copyright);
gme_free_info(ti);
gme_delete(emu);
- return tag;
+
+ return true;
}
static const char *const gme_suffixes[] = {
@@ -242,7 +251,7 @@ extern const struct decoder_plugin gme_decoder_plugin;
const struct decoder_plugin gme_decoder_plugin = {
.name = "gme",
.file_decode = gme_file_decode,
- .tag_dup = gme_tag_dup,
+ .scan_file = gme_scan_file,
.suffixes = gme_suffixes,
.container_scan = gme_container_scan,
};
diff --git a/src/decoder/mad_decoder_plugin.c b/src/decoder/mad_decoder_plugin.c
index 8bf3f654..a69284be 100644
--- a/src/decoder/mad_decoder_plugin.c
+++ b/src/decoder/mad_decoder_plugin.c
@@ -22,6 +22,7 @@
#include "conf.h"
#include "tag_id3.h"
#include "tag_rva2.h"
+#include "tag_handler.h"
#include "audio_check.h"
#include <assert.h>
@@ -1176,19 +1177,18 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
mp3_data_finish(&data);
}
-static struct tag *
-mad_decoder_stream_tag(struct input_stream *is)
+static bool
+mad_decoder_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
- struct tag *tag;
int total_time;
total_time = mad_decoder_total_file_time(is);
if (total_time < 0)
- return NULL;
+ return false;
- tag = tag_new();
- tag->time = total_time;
- return tag;
+ tag_handler_invoke_duration(handler, handler_ctx, total_time);
+ return true;
}
static const char *const mp3_suffixes[] = { "mp3", "mp2", NULL };
@@ -1198,7 +1198,7 @@ const struct decoder_plugin mad_decoder_plugin = {
.name = "mad",
.init = mp3_plugin_init,
.stream_decode = mp3_decode,
- .stream_tag = mad_decoder_stream_tag,
+ .scan_stream = mad_decoder_scan_stream,
.suffixes = mp3_suffixes,
.mime_types = mp3_mime_types
};
diff --git a/src/decoder/modplug_decoder_plugin.c b/src/decoder/modplug_decoder_plugin.c
index 9345dd24..21ee79e7 100644
--- a/src/decoder/modplug_decoder_plugin.c
+++ b/src/decoder/modplug_decoder_plugin.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
+#include "tag_handler.h"
#include <glib.h>
#include <modplug.h>
@@ -149,34 +150,33 @@ mod_decode(struct decoder *decoder, struct input_stream *is)
ModPlug_Unload(f);
}
-static struct tag *
-modplug_stream_tag(struct input_stream *is)
+static bool
+modplug_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
ModPlugFile *f;
- struct tag *ret = NULL;
GByteArray *bdatas;
- char *title;
bdatas = mod_loadfile(NULL, is);
if (!bdatas)
- return NULL;
+ return false;
f = ModPlug_Load(bdatas->data, bdatas->len);
g_byte_array_free(bdatas, TRUE);
if (f == NULL)
- return NULL;
+ return false;
- ret = tag_new();
- ret->time = ModPlug_GetLength(f) / 1000;
+ tag_handler_invoke_duration(handler, handler_ctx,
+ ModPlug_GetLength(f) / 1000);
- title = g_strdup(ModPlug_GetName(f));
- if (title)
- tag_add_item(ret, TAG_TITLE, title);
- g_free(title);
+ const char *title = ModPlug_GetName(f);
+ if (title != NULL)
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_TITLE, title);
ModPlug_Unload(f);
- return ret;
+ return true;
}
static const char *const mod_suffixes[] = {
@@ -189,6 +189,6 @@ static const char *const mod_suffixes[] = {
const struct decoder_plugin modplug_decoder_plugin = {
.name = "modplug",
.stream_decode = mod_decode,
- .stream_tag = modplug_stream_tag,
+ .scan_stream = modplug_scan_stream,
.suffixes = mod_suffixes,
};
diff --git a/src/decoder/mpcdec_decoder_plugin.c b/src/decoder/mpcdec_decoder_plugin.c
index 7864c079..d4768b35 100644
--- a/src/decoder/mpcdec_decoder_plugin.c
+++ b/src/decoder/mpcdec_decoder_plugin.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
+#include "tag_handler.h"
#ifdef MPC_IS_OLD_API
#include <mpcdec/mpcdec.h>
@@ -323,18 +324,17 @@ mpcdec_get_file_duration(struct input_stream *is)
return total_time;
}
-static struct tag *
-mpcdec_stream_tag(struct input_stream *is)
+static bool
+mpcdec_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
float total_time = mpcdec_get_file_duration(is);
- struct tag *tag;
if (total_time < 0)
- return NULL;
+ return false;
- tag = tag_new();
- tag->time = total_time;
- return tag;
+ tag_handler_invoke_duration(handler, handler_ctx, total_time);
+ return true;
}
static const char *const mpcdec_suffixes[] = { "mpc", NULL };
@@ -342,6 +342,6 @@ static const char *const mpcdec_suffixes[] = { "mpc", NULL };
const struct decoder_plugin mpcdec_decoder_plugin = {
.name = "mpcdec",
.stream_decode = mpcdec_decode,
- .stream_tag = mpcdec_stream_tag,
+ .scan_stream = mpcdec_scan_stream,
.suffixes = mpcdec_suffixes,
};
diff --git a/src/decoder/mpg123_decoder_plugin.c b/src/decoder/mpg123_decoder_plugin.c
index 224f3db2..657a9c88 100644
--- a/src/decoder/mpg123_decoder_plugin.c
+++ b/src/decoder/mpg123_decoder_plugin.c
@@ -20,6 +20,7 @@
#include "config.h" /* must be first for large file support */
#include "decoder_api.h"
#include "audio_check.h"
+#include "tag_handler.h"
#include <glib.h>
@@ -192,41 +193,40 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs)
mpg123_delete(handle);
}
-static struct tag *
-mpd_mpg123_tag_dup(const char *path_fs)
+static bool
+mpd_mpg123_scan_file(const char *path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
{
struct audio_format audio_format;
mpg123_handle *handle;
int error;
off_t num_samples;
- struct tag *tag;
handle = mpg123_new(NULL, &error);
if (handle == NULL) {
g_warning("mpg123_new() failed: %s",
mpg123_plain_strerror(error));
- return NULL;
+ return false;
}
if (!mpd_mpg123_open(handle, path_fs, &audio_format)) {
mpg123_delete(handle);
- return NULL;
+ return false;
}
num_samples = mpg123_length(handle);
if (num_samples <= 0) {
mpg123_delete(handle);
- return NULL;
+ return false;
}
- tag = tag_new();
-
- tag->time = num_samples / audio_format.sample_rate;
-
/* ID3 tag support not yet implemented */
mpg123_delete(handle);
- return tag;
+
+ tag_handler_invoke_duration(handler, handler_ctx,
+ num_samples / audio_format.sample_rate);
+ return true;
}
static const char *const mpg123_suffixes[] = {
@@ -240,6 +240,6 @@ const struct decoder_plugin mpg123_decoder_plugin = {
.finish = mpd_mpg123_finish,
.file_decode = mpd_mpg123_file_decode,
/* streaming not yet implemented */
- .tag_dup = mpd_mpg123_tag_dup,
+ .scan_file = mpd_mpg123_scan_file,
.suffixes = mpg123_suffixes,
};
diff --git a/src/decoder/sidplay_decoder_plugin.cxx b/src/decoder/sidplay_decoder_plugin.cxx
index 9aeec8b5..c4ef2049 100644
--- a/src/decoder/sidplay_decoder_plugin.cxx
+++ b/src/decoder/sidplay_decoder_plugin.cxx
@@ -21,6 +21,7 @@
extern "C" {
#include "../decoder_api.h"
+#include "tag_handler.h"
}
#include <errno.h>
@@ -336,8 +337,9 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs)
} while (cmd != DECODE_COMMAND_STOP);
}
-static struct tag *
-sidplay_tag_dup(const char *path_fs)
+static bool
+sidplay_scan_file(const char *path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
{
int song_num=get_song_num(path_fs);
char *path_container=get_container_name(path_fs);
@@ -345,10 +347,9 @@ sidplay_tag_dup(const char *path_fs)
SidTune tune(path_container, NULL, true);
g_free(path_container);
if (!tune)
- return NULL;
+ return false;
const SidTuneInfo &info = tune.getInfo();
- struct tag *tag = tag_new();
/* title */
const char *title;
@@ -360,25 +361,28 @@ sidplay_tag_dup(const char *path_fs)
if(info.songs>1) {
char *tag_title=g_strdup_printf("%s (%d/%d)",
title, song_num, info.songs);
- tag_add_item(tag, TAG_TITLE, tag_title);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_TITLE, tag_title);
g_free(tag_title);
} else
- tag_add_item(tag, TAG_TITLE, title);
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, title);
/* artist */
if (info.numberOfInfoStrings > 1 && info.infoString[1] != NULL)
- tag_add_item(tag, TAG_ARTIST, info.infoString[1]);
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_ARTIST,
+ info.infoString[1]);
/* track */
char *track=g_strdup_printf("%d", song_num);
- tag_add_item(tag, TAG_TRACK, track);
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
g_free(track);
/* time */
int song_len=get_song_length(path_fs);
- if(song_len!=-1) tag->time=song_len;
+ if (song_len >= 0)
+ tag_handler_invoke_duration(handler, handler_ctx, song_len);
- return tag;
+ return true;
}
static char *
@@ -421,7 +425,7 @@ const struct decoder_plugin sidplay_decoder_plugin = {
sidplay_finish,
NULL, /* stream_decode() */
sidplay_file_decode,
- sidplay_tag_dup,
+ sidplay_scan_file,
NULL, /* stream_tag() */
sidplay_container_scan,
sidplay_suffixes,
diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c
index 25952dfd..8dd98236 100644
--- a/src/decoder/sndfile_decoder_plugin.c
+++ b/src/decoder/sndfile_decoder_plugin.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
+#include "tag_handler.h"
#include <sndfile.h>
@@ -172,44 +173,47 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
sf_close(sf);
}
-static struct tag *
-sndfile_tag_dup(const char *path_fs)
+static bool
+sndfile_scan_file(const char *path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
{
SNDFILE *sf;
SF_INFO info;
- struct tag *tag;
const char *p;
info.format = 0;
sf = sf_open(path_fs, SFM_READ, &info);
if (sf == NULL)
- return NULL;
+ return false;
if (!audio_valid_sample_rate(info.samplerate)) {
sf_close(sf);
g_warning("Invalid sample rate in %s\n", path_fs);
- return NULL;
+ return false;
}
- tag = tag_new();
- tag->time = info.frames / info.samplerate;
+ tag_handler_invoke_duration(handler, handler_ctx,
+ info.frames / info.samplerate);
p = sf_get_string(sf, SF_STR_TITLE);
if (p != NULL)
- tag_add_item(tag, TAG_TITLE, p);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_TITLE, p);
p = sf_get_string(sf, SF_STR_ARTIST);
if (p != NULL)
- tag_add_item(tag, TAG_ARTIST, p);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_ARTIST, p);
p = sf_get_string(sf, SF_STR_DATE);
if (p != NULL)
- tag_add_item(tag, TAG_DATE, p);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ TAG_DATE, p);
sf_close(sf);
- return tag;
+ return true;
}
static const char *const sndfile_suffixes[] = {
@@ -245,7 +249,7 @@ static const char *const sndfile_mime_types[] = {
const struct decoder_plugin sndfile_decoder_plugin = {
.name = "sndfile",
.stream_decode = sndfile_stream_decode,
- .tag_dup = sndfile_tag_dup,
+ .scan_file = sndfile_scan_file,
.suffixes = sndfile_suffixes,
.mime_types = sndfile_mime_types,
};
diff --git a/src/decoder/vorbis_comments.c b/src/decoder/vorbis_comments.c
index 9145507d..e94ee3d0 100644
--- a/src/decoder/vorbis_comments.c
+++ b/src/decoder/vorbis_comments.c
@@ -21,6 +21,7 @@
#include "vorbis_comments.h"
#include "tag.h"
#include "tag_table.h"
+#include "tag_handler.h"
#include "replay_gain_info.h"
#include <glib.h>
@@ -79,14 +80,15 @@ vorbis_comments_to_replay_gain(struct replay_gain_info *rgi, char **comments)
* the comment value into the tag.
*/
static bool
-vorbis_copy_comment(struct tag *tag, const char *comment,
- const char *name, enum tag_type tag_type)
+vorbis_copy_comment(const char *comment,
+ const char *name, enum tag_type tag_type,
+ const struct tag_handler *handler, void *handler_ctx)
{
const char *value;
value = vorbis_comment_value(comment, name);
if (value != NULL) {
- tag_add_item(tag, tag_type, value);
+ tag_handler_invoke_tag(handler, handler_ctx, tag_type, value);
return true;
}
@@ -101,27 +103,36 @@ static const struct tag_table vorbis_tags[] = {
};
static void
-vorbis_parse_comment(struct tag *tag, const char *comment)
+vorbis_scan_comment(const char *comment,
+ const struct tag_handler *handler, void *handler_ctx)
{
- assert(tag != NULL);
-
for (const struct tag_table *i = vorbis_tags; i->name != NULL; ++i)
- if (vorbis_copy_comment(tag, comment, i->name, i->type))
+ if (vorbis_copy_comment(comment, i->name, i->type,
+ handler, handler_ctx))
return;
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- if (vorbis_copy_comment(tag, comment,
- tag_item_names[i], i))
+ if (vorbis_copy_comment(comment,
+ tag_item_names[i], i,
+ handler, handler_ctx))
return;
}
+void
+vorbis_comments_scan(char **comments,
+ const struct tag_handler *handler, void *handler_ctx)
+{
+ while (*comments)
+ vorbis_scan_comment(*comments++,
+ handler, handler_ctx);
+
+}
+
struct tag *
vorbis_comments_to_tag(char **comments)
{
struct tag *tag = tag_new();
-
- while (*comments)
- vorbis_parse_comment(tag, *comments++);
+ vorbis_comments_scan(comments, &add_tag_handler, tag);
if (tag_is_empty(tag)) {
tag_free(tag);
diff --git a/src/decoder/vorbis_comments.h b/src/decoder/vorbis_comments.h
index 5d2c65e4..c1509693 100644
--- a/src/decoder/vorbis_comments.h
+++ b/src/decoder/vorbis_comments.h
@@ -25,10 +25,15 @@
#include <stdbool.h>
struct replay_gain_info;
+struct tag_handler;
bool
vorbis_comments_to_replay_gain(struct replay_gain_info *rgi, char **comments);
+void
+vorbis_comments_scan(char **comments,
+ const struct tag_handler *handler, void *handler_ctx);
+
struct tag *
vorbis_comments_to_tag(char **comments);
diff --git a/src/decoder/vorbis_decoder_plugin.c b/src/decoder/vorbis_decoder_plugin.c
index f3469384..15cdc0ca 100644
--- a/src/decoder/vorbis_decoder_plugin.c
+++ b/src/decoder/vorbis_decoder_plugin.c
@@ -22,6 +22,7 @@
#include "_ogg_common.h"
#include "audio_check.h"
#include "uri.h"
+#include "tag_handler.h"
#ifndef HAVE_TREMOR
#define OV_EXCLUDE_STATIC_CALLBACKS
@@ -268,24 +269,24 @@ vorbis_stream_decode(struct decoder *decoder,
ov_clear(&vf);
}
-static struct tag *
-vorbis_stream_tag(struct input_stream *is)
+static bool
+vorbis_scan_stream(struct input_stream *is,
+ const struct tag_handler *handler, void *handler_ctx)
{
struct vorbis_input_stream vis;
OggVorbis_File vf;
if (!vorbis_is_open(&vis, &vf, NULL, is))
- return NULL;
+ return false;
- struct tag *tag = vorbis_comments_to_tag(ov_comment(&vf, -1)->user_comments);
+ tag_handler_invoke_duration(handler, handler_ctx,
+ (int)(ov_time_total(&vf, -1) + 0.5));
- if (tag == NULL)
- tag = tag_new();
- tag->time = (int)(ov_time_total(&vf, -1) + 0.5);
+ vorbis_comments_scan(ov_comment(&vf, -1)->user_comments,
+ handler, handler_ctx);
ov_clear(&vf);
-
- return tag;
+ return true;
}
static const char *const vorbis_suffixes[] = {
@@ -307,7 +308,7 @@ static const char *const vorbis_mime_types[] = {
const struct decoder_plugin vorbis_decoder_plugin = {
.name = "vorbis",
.stream_decode = vorbis_stream_decode,
- .stream_tag = vorbis_stream_tag,
+ .scan_stream = vorbis_scan_stream,
.suffixes = vorbis_suffixes,
.mime_types = vorbis_mime_types
};
diff --git a/src/decoder/wavpack_decoder_plugin.c b/src/decoder/wavpack_decoder_plugin.c
index 4945b75c..794b969c 100644
--- a/src/decoder/wavpack_decoder_plugin.c
+++ b/src/decoder/wavpack_decoder_plugin.c
@@ -22,6 +22,7 @@
#include "audio_check.h"
#include "path.h"
#include "utils.h"
+#include "tag_handler.h"
#include <wavpack/wavpack.h>
#include <glib.h>
@@ -275,11 +276,11 @@ wavpack_replaygain(struct replay_gain_info *replay_gain_info,
/*
* Reads metainfo from the specified file.
*/
-static struct tag *
-wavpack_tagdup(const char *fname)
+static bool
+wavpack_scan_file(const char *fname,
+ const struct tag_handler *handler, void *handler_ctx)
{
WavpackContext *wpc;
- struct tag *tag;
char error[ERRORLEN];
char *s;
int size, allocated_size;
@@ -290,12 +291,12 @@ wavpack_tagdup(const char *fname)
"failed to open WavPack file \"%s\": %s\n",
fname, error
);
- return NULL;
+ return false;
}
- tag = tag_new();
- tag->time = WavpackGetNumSamples(wpc);
- tag->time /= WavpackGetSampleRate(wpc);
+ tag_handler_invoke_duration(handler, handler_ctx,
+ WavpackGetNumSamples(wpc) /
+ WavpackGetSampleRate(wpc));
allocated_size = 0;
s = NULL;
@@ -315,7 +316,8 @@ wavpack_tagdup(const char *fname)
}
WavpackGetTagItem(wpc, tagtypes[i].name, s, size);
- tag_add_item(tag, tagtypes[i].type, s);
+ tag_handler_invoke_tag(handler, handler_ctx,
+ tagtypes[i].type, s);
}
}
@@ -323,7 +325,7 @@ wavpack_tagdup(const char *fname)
WavpackCloseFile(wpc);
- return tag;
+ return true;
}
/*
@@ -576,7 +578,7 @@ const struct decoder_plugin wavpack_decoder_plugin = {
.name = "wavpack",
.stream_decode = wavpack_streamdecode,
.file_decode = wavpack_filedecode,
- .tag_dup = wavpack_tagdup,
+ .scan_file = wavpack_scan_file,
.suffixes = wavpack_suffixes,
.mime_types = wavpack_mime_types
};
diff --git a/src/decoder/wildmidi_decoder_plugin.c b/src/decoder/wildmidi_decoder_plugin.c
index 5bc36b4e..a2224940 100644
--- a/src/decoder/wildmidi_decoder_plugin.c
+++ b/src/decoder/wildmidi_decoder_plugin.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
+#include "tag_handler.h"
#include <glib.h>
@@ -111,25 +112,26 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
WildMidi_Close(wm);
}
-static struct tag *
-wildmidi_tag_dup(const char *path_fs)
+static bool
+wildmidi_scan_file(const char *path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
{
midi *wm = WildMidi_Open(path_fs);
if (wm == NULL)
- return NULL;
+ return false;
const struct _WM_Info *info = WildMidi_GetInfo(wm);
if (info == NULL) {
WildMidi_Close(wm);
- return NULL;
+ return false;
}
- struct tag *tag = tag_new();
- tag->time = info->approx_total_samples / WILDMIDI_SAMPLE_RATE;
+ int duration = info->approx_total_samples / WILDMIDI_SAMPLE_RATE;
+ tag_handler_invoke_duration(handler, handler_ctx, duration);
WildMidi_Close(wm);
- return tag;
+ return true;
}
static const char *const wildmidi_suffixes[] = {
@@ -142,6 +144,6 @@ const struct decoder_plugin wildmidi_decoder_plugin = {
.init = wildmidi_init,
.finish = wildmidi_finish,
.file_decode = wildmidi_file_decode,
- .tag_dup = wildmidi_tag_dup,
+ .scan_file = wildmidi_scan_file,
.suffixes = wildmidi_suffixes,
};