diff options
Diffstat (limited to 'src/decoder/flac_decoder_plugin.c')
-rw-r--r-- | src/decoder/flac_decoder_plugin.c | 185 |
1 files changed, 87 insertions, 98 deletions
diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/flac_decoder_plugin.c index 9d980b79d..fb0b3502d 100644 --- a/src/decoder/flac_decoder_plugin.c +++ b/src/decoder/flac_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 @@ -50,7 +50,7 @@ flac_read_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, if (r == 0) { if (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE || - input_stream_eof(data->input_stream)) + input_stream_lock_eof(data->input_stream)) return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; else return FLAC__STREAM_DECODER_READ_STATUS_ABORT; @@ -68,7 +68,8 @@ flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, if (!data->input_stream->seekable) return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - if (!input_stream_seek(data->input_stream, offset, SEEK_SET, NULL)) + if (!input_stream_lock_seek(data->input_stream, offset, SEEK_SET, + NULL)) return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__STREAM_DECODER_SEEK_STATUS_OK; @@ -109,53 +110,40 @@ flac_eof_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, void *fdata) return (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE && decoder_get_command(data->decoder) != DECODE_COMMAND_SEEK) || - input_stream_eof(data->input_stream); + input_stream_lock_eof(data->input_stream); } static void flac_error_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, FLAC__StreamDecoderErrorStatus status, void *fdata) { - flac_error_common_cb("flac", status, (struct flac_data *) fdata); + flac_error_common_cb(status, (struct flac_data *) fdata); } #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) { - const char *str = ""; /* "" to silence compiler warning */ switch (state) { case FLAC__SEEKABLE_STREAM_DECODER_OK: case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: return; + case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: - str = "allocation error"; - break; case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: - str = "read error"; - break; case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: - str = "seek error"; - break; case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: - str = "seekable stream error"; - break; case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: - str = "decoder already initialized"; - break; case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: - str = "invalid callback"; - break; case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: - str = "decoder uninitialized"; + break; } - g_warning("%s\n", str); + g_warning("%s\n", FLAC__SeekableStreamDecoderStateString[state]); } #else /* FLAC_API_VERSION_CURRENT >= 7 */ static void flacPrintErroredState(FLAC__StreamDecoderState state) { - const char *str = ""; /* "" to silence compiler warning */ switch (state) { case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: case FLAC__STREAM_DECODER_READ_METADATA: @@ -163,23 +151,16 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state) case FLAC__STREAM_DECODER_READ_FRAME: case FLAC__STREAM_DECODER_END_OF_STREAM: return; + case FLAC__STREAM_DECODER_OGG_ERROR: - str = "error in the Ogg layer"; - break; case FLAC__STREAM_DECODER_SEEK_ERROR: - str = "seek error"; - break; case FLAC__STREAM_DECODER_ABORTED: - str = "decoder aborted by read"; - break; case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR: - str = "allocation error"; - break; case FLAC__STREAM_DECODER_UNINITIALIZED: - str = "decoder uninitialized"; + break; } - g_warning("%s\n", str); + g_warning("%s\n", FLAC__StreamDecoderStateString[state]); } #endif /* FLAC_API_VERSION_CURRENT >= 7 */ @@ -210,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); } /** @@ -305,17 +287,56 @@ flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec, /* end of this sub track */ break; - if (!FLAC__stream_decoder_process_single(flac_dec)) { - cmd = decoder_get_command(decoder); - if (cmd != DECODE_COMMAND_SEEK) - break; + if (!FLAC__stream_decoder_process_single(flac_dec) && + decoder_get_command(decoder) == DECODE_COMMAND_NONE) { + /* a failure that was not triggered by a + decoder command */ + flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec)); + break; } } +} - if (cmd != DECODE_COMMAND_STOP) { - flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec)); - FLAC__stream_decoder_finish(flac_dec); - } +static FLAC__StreamDecoderInitStatus +stream_init_oggflac(FLAC__StreamDecoder *flac_dec, struct flac_data *data) +{ +#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 + return FLAC__stream_decoder_init_ogg_stream(flac_dec, + flac_read_cb, + flac_seek_cb, + flac_tell_cb, + flac_length_cb, + flac_eof_cb, + flac_write_cb, + flacMetadata, + flac_error_cb, + data); +#else + (void)flac_dec; + (void)data; + + return FLAC__STREAM_DECODER_INIT_STATUS_ERROR; +#endif +} + +static FLAC__StreamDecoderInitStatus +stream_init_flac(FLAC__StreamDecoder *flac_dec, struct flac_data *data) +{ + return FLAC__stream_decoder_init_stream(flac_dec, + flac_read_cb, flac_seek_cb, + flac_tell_cb, flac_length_cb, + flac_eof_cb, flac_write_cb, + flacMetadata, + flac_error_cb, + data); +} + +static FLAC__StreamDecoderInitStatus +stream_init(FLAC__StreamDecoder *flac_dec, struct flac_data *data, bool is_ogg) +{ + return is_ogg + ? stream_init_oggflac(flac_dec, data) + : stream_init_flac(flac_dec, data); } static void @@ -325,7 +346,6 @@ flac_decode_internal(struct decoder * decoder, { FLAC__StreamDecoder *flac_dec; struct flac_data data; - const char *err = NULL; flac_dec = flac_decoder_new(); if (flac_dec == NULL) @@ -334,58 +354,30 @@ flac_decode_internal(struct decoder * decoder, flac_data_init(&data, decoder, input_stream); data.tag = tag_new(); - if (is_ogg) { + FLAC__StreamDecoderInitStatus status = + stream_init(flac_dec, &data, is_ogg); + if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + flac_data_deinit(&data); + FLAC__stream_decoder_delete(flac_dec); #if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 - FLAC__StreamDecoderInitStatus status = - FLAC__stream_decoder_init_ogg_stream(flac_dec, - flac_read_cb, - flac_seek_cb, - flac_tell_cb, - flac_length_cb, - flac_eof_cb, - flac_write_cb, - flacMetadata, - flac_error_cb, - (void *)&data); - if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { - err = "doing Ogg init()"; - goto fail; - } -#else - goto fail; + g_warning("%s", FLAC__StreamDecoderInitStatusString[status]); #endif - } else { - FLAC__StreamDecoderInitStatus status = - FLAC__stream_decoder_init_stream(flac_dec, - flac_read_cb, - flac_seek_cb, - flac_tell_cb, - flac_length_cb, - flac_eof_cb, - flac_write_cb, - flacMetadata, - flac_error_cb, - (void *)&data); - if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { - err = "doing init()"; - goto fail; - } + return; } if (!flac_decoder_initialize(&data, flac_dec, 0)) { flac_data_deinit(&data); + FLAC__stream_decoder_finish(flac_dec); FLAC__stream_decoder_delete(flac_dec); return; } flac_decoder_loop(&data, flac_dec, 0, 0); -fail: flac_data_deinit(&data); - FLAC__stream_decoder_delete(flac_dec); - if (err) - g_warning("%s\n", err); + FLAC__stream_decoder_finish(flac_dec); + FLAC__stream_decoder_delete(flac_dec); } static void @@ -409,36 +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))) - goto out; + if (!(FLAC__metadata_chain_read_ogg(chain, file))) { + FLAC__metadata_chain_delete(chain); + 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; - } - -out: FLAC__metadata_chain_delete(chain); - return ret; + return true; } static void @@ -449,7 +438,7 @@ oggflac_decode(struct decoder *decoder, struct input_stream *input_stream) /* rewind the stream, because ogg_stream_type_detect() has moved it */ - input_stream_seek(input_stream, 0, SEEK_SET, NULL); + input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); flac_decode_internal(decoder, input_stream, true); } @@ -471,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 @@ -491,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, }; |