diff options
Diffstat (limited to 'src/decoder/wavpack_decoder_plugin.c')
-rw-r--r-- | src/decoder/wavpack_decoder_plugin.c | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/src/decoder/wavpack_decoder_plugin.c b/src/decoder/wavpack_decoder_plugin.c index 61026842b..ae85b0e27 100644 --- a/src/decoder/wavpack_decoder_plugin.c +++ b/src/decoder/wavpack_decoder_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,8 @@ #include "audio_check.h" #include "path.h" #include "utils.h" +#include "tag_table.h" +#include "tag_handler.h" #include <wavpack/wavpack.h> #include <glib.h> @@ -36,10 +38,7 @@ #define ERRORLEN 80 -static struct { - const char *name; - enum tag_type type; -} tagtypes[] = { +static const struct tag_table wavpack_tags[] = { { "artist", TAG_ARTIST }, { "album", TAG_ALBUM }, { "title", TAG_TITLE }, @@ -51,6 +50,7 @@ static struct { { "performer", TAG_PERFORMER }, { "comment", TAG_COMMENT }, { "disc", TAG_DISC }, + { NULL, TAG_NUM_OF_ITEM_TYPES } }; /** A pointer type for format converter function. */ @@ -111,12 +111,11 @@ static void format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer, uint32_t count) { - int32_t *dst = buffer; - float *src = buffer; - assert_static(sizeof(*dst) <= sizeof(*src)); + float *p = buffer; while (count--) { - *dst++ = (int32_t)(*src++ + 0.5f); + *p /= (1 << 23); + ++p; } } @@ -127,7 +126,7 @@ static enum sample_format wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) { if (is_float) - return SAMPLE_FORMAT_S24_P32; + return SAMPLE_FORMAT_FLOAT; switch (bytes_per_sample) { case 1: @@ -273,17 +272,41 @@ wavpack_replaygain(struct replay_gain_info *replay_gain_info, return found; } +static void +wavpack_scan_tag_item(WavpackContext *wpc, const char *name, + enum tag_type type, + const struct tag_handler *handler, void *handler_ctx) +{ + char buffer[1024]; + int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer)); + if (len <= 0 || (unsigned)len >= sizeof(buffer)) + return; + + tag_handler_invoke_tag(handler, handler_ctx, type, buffer); + +} + +static void +wavpack_scan_pair(WavpackContext *wpc, const char *name, + const struct tag_handler *handler, void *handler_ctx) +{ + char buffer[8192]; + int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer)); + if (len <= 0 || (unsigned)len >= sizeof(buffer)) + return; + + tag_handler_invoke_pair(handler, handler_ctx, name, buffer); +} + /* * 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; wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0); if (wpc == NULL) { @@ -291,40 +314,34 @@ 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); - - allocated_size = 0; - s = NULL; - - for (unsigned i = 0; i < G_N_ELEMENTS(tagtypes); ++i) { - size = WavpackGetTagItem(wpc, tagtypes[i].name, NULL, 0); - if (size > 0) { - ++size; /* EOS */ - - if (s == NULL) { - s = g_malloc(size); - allocated_size = size; - } else if (size > allocated_size) { - char *t = (char *)g_realloc(s, size); - allocated_size = size; - s = t; - } + tag_handler_invoke_duration(handler, handler_ctx, + WavpackGetNumSamples(wpc) / + WavpackGetSampleRate(wpc)); - WavpackGetTagItem(wpc, tagtypes[i].name, s, size); - tag_add_item(tag, tagtypes[i].type, s); + for (const struct tag_table *i = wavpack_tags; i->name != NULL; ++i) + wavpack_scan_tag_item(wpc, i->name, i->type, + handler, handler_ctx); + + if (handler->pair != NULL) { + char name[64]; + + for (int i = 0, n = WavpackGetNumTagItems(wpc); + i < n; ++i) { + int len = WavpackGetTagItemIndexed(wpc, i, name, + sizeof(name)); + if (len <= 0 || (unsigned)len >= sizeof(name)) + continue; + + wavpack_scan_pair(wpc, name, handler, handler_ctx); } } - g_free(s); - WavpackCloseFile(wpc); - return tag; + return true; } /* @@ -390,13 +407,15 @@ wavpack_input_get_pos(void *id) static int wavpack_input_set_pos_abs(void *id, uint32_t pos) { - return input_stream_seek(wpin(id)->is, pos, SEEK_SET, NULL) ? 0 : -1; + return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, NULL) + ? 0 : -1; } static int wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) { - return input_stream_seek(wpin(id)->is, delta, mode, NULL) ? 0 : -1; + return input_stream_lock_seek(wpin(id)->is, delta, mode, NULL) + ? 0 : -1; } static int @@ -447,6 +466,7 @@ wavpack_input_init(struct wavpack_input *isp, struct decoder *decoder, static struct input_stream * wavpack_open_wvc(struct decoder *decoder, const char *uri, + GMutex *mutex, GCond *cond, struct wavpack_input *wpi) { struct input_stream *is_wvc; @@ -462,7 +482,7 @@ wavpack_open_wvc(struct decoder *decoder, const char *uri, return false; wvc_url = g_strconcat(uri, "c", NULL); - is_wvc = input_stream_open(wvc_url, NULL); + is_wvc = input_stream_open(wvc_url, mutex, cond, NULL); g_free(wvc_url); if (is_wvc == NULL) @@ -499,7 +519,8 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is) struct wavpack_input isp, isp_wvc; bool can_seek = is->seekable; - is_wvc = wavpack_open_wvc(decoder, is->uri, &isp_wvc); + is_wvc = wavpack_open_wvc(decoder, is->uri, is->mutex, is->cond, + &isp_wvc); if (is_wvc != NULL) { open_flags |= OPEN_WVC; can_seek &= is_wvc->seekable; @@ -573,7 +594,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 }; |