diff options
Diffstat (limited to '')
-rw-r--r-- | src/decoder/FLACDecoderPlugin.cxx (renamed from src/decoder/flac_decoder_plugin.c) | 292 |
1 files changed, 96 insertions, 196 deletions
diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/FLACDecoderPlugin.cxx index fb0b3502d..dbe7f207f 100644 --- a/src/decoder/flac_decoder_plugin.c +++ b/src/decoder/FLACDecoderPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2012 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,13 +18,13 @@ */ #include "config.h" /* must be first for large file support */ -#include "_flac_common.h" -#include "flac_compat.h" -#include "flac_metadata.h" +#include "FLACDecoderPlugin.h" +#include "FLACCommon.hxx" +#include "FLACMetaData.hxx" -#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 -#include "_ogg_common.h" -#endif +extern "C" { +#include "ogg_codec.h" +} #include <glib.h> @@ -34,114 +34,10 @@ #include <sys/stat.h> #include <sys/types.h> -/* this code was based on flac123, from flac-tools */ - -static FLAC__StreamDecoderReadStatus -flac_read_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, - FLAC__byte buf[], flac_read_status_size_t *bytes, - void *fdata) -{ - struct flac_data *data = fdata; - size_t r; - - r = decoder_read(data->decoder, data->input_stream, - (void *)buf, *bytes); - *bytes = r; - - if (r == 0) { - if (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE || - input_stream_lock_eof(data->input_stream)) - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - else - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - } - - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; -} - -static FLAC__StreamDecoderSeekStatus -flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, - FLAC__uint64 offset, void *fdata) -{ - struct flac_data *data = (struct flac_data *) fdata; - - if (!data->input_stream->seekable) - return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - - 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; -} - -static FLAC__StreamDecoderTellStatus -flac_tell_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, - FLAC__uint64 * offset, void *fdata) -{ - struct flac_data *data = (struct flac_data *) fdata; - - if (!data->input_stream->seekable) - return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; - - *offset = (long)(data->input_stream->offset); - - return FLAC__STREAM_DECODER_TELL_STATUS_OK; -} - -static FLAC__StreamDecoderLengthStatus -flac_length_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, - FLAC__uint64 * length, void *fdata) -{ - struct flac_data *data = (struct flac_data *) fdata; - - if (data->input_stream->size < 0) - return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; - - *length = (size_t) (data->input_stream->size); - - return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; -} - -static FLAC__bool -flac_eof_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, void *fdata) -{ - struct flac_data *data = (struct flac_data *) fdata; - - return (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE && - decoder_get_command(data->decoder) != DECODE_COMMAND_SEEK) || - 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(status, (struct flac_data *) fdata); -} - #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 -static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) -{ - 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: - case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: - case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: - case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: - case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: - case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: - case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: - break; - } +#error libFLAC is too old +#endif - g_warning("%s\n", FLAC__SeekableStreamDecoderStateString[state]); -} -#else /* FLAC_API_VERSION_CURRENT >= 7 */ static void flacPrintErroredState(FLAC__StreamDecoderState state) { switch (state) { @@ -162,7 +58,6 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state) g_warning("%s\n", FLAC__StreamDecoderStateString[state]); } -#endif /* FLAC_API_VERSION_CURRENT >= 7 */ static void flacMetadata(G_GNUC_UNUSED const FLAC__StreamDecoder * dec, const FLAC__StreamMetadata * block, void *vdata) @@ -195,7 +90,30 @@ static bool flac_scan_file(const char *file, const struct tag_handler *handler, void *handler_ctx) { - return flac_scan_file2(file, NULL, handler, handler_ctx); + FLACMetadataChain chain; + if (!chain.Read(file)) { + g_debug("Failed to read FLAC tags: %s", + chain.GetStatusString()); + return false; + } + + chain.Scan(handler, handler_ctx); + return true; +} + +static bool +flac_scan_stream(struct input_stream *is, + const struct tag_handler *handler, void *handler_ctx) +{ + FLACMetadataChain chain; + if (!chain.Read(is)) { + g_debug("Failed to read FLAC tags: %s", + chain.GetStatusString()); + return false; + } + + chain.Scan(handler, handler_ctx); + return true; } /** @@ -205,15 +123,13 @@ static FLAC__StreamDecoder * flac_decoder_new(void) { FLAC__StreamDecoder *sd = FLAC__stream_decoder_new(); - if (sd == NULL) { + if (sd == nullptr) { g_warning("FLAC__stream_decoder_new() failed"); - return NULL; + return nullptr; } -#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 if(!FLAC__stream_decoder_set_metadata_respond(sd, FLAC__METADATA_TYPE_VORBIS_COMMENT)) g_debug("FLAC__stream_decoder_set_metadata_respond() has failed"); -#endif return sd; } @@ -259,7 +175,7 @@ flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec, data->first_frame = t_start; while (true) { - if (data->tag != NULL && !tag_is_empty(data->tag)) { + if (data->tag != nullptr && !tag_is_empty(data->tag)) { cmd = decoder_tag(data->decoder, data->input_stream, data->tag); tag_free(data->tag); @@ -300,34 +216,30 @@ flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *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, + FLACInput::Read, + FLACInput::Seek, + FLACInput::Tell, + FLACInput::Length, + FLACInput::Eof, flac_write_cb, flacMetadata, - flac_error_cb, + FLACInput::Error, 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, + FLACInput::Read, + FLACInput::Seek, + FLACInput::Tell, + FLACInput::Length, + FLACInput::Eof, + flac_write_cb, flacMetadata, - flac_error_cb, + FLACInput::Error, data); } @@ -345,28 +257,23 @@ flac_decode_internal(struct decoder * decoder, bool is_ogg) { FLAC__StreamDecoder *flac_dec; - struct flac_data data; flac_dec = flac_decoder_new(); - if (flac_dec == NULL) + if (flac_dec == nullptr) return; - flac_data_init(&data, decoder, input_stream); + struct flac_data data(decoder, input_stream); data.tag = tag_new(); 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 g_warning("%s", FLAC__StreamDecoderInitStatusString[status]); -#endif 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; @@ -374,8 +281,6 @@ flac_decode_internal(struct decoder * decoder, flac_decoder_loop(&data, flac_dec, 0, 0); - flac_data_deinit(&data); - FLAC__stream_decoder_finish(flac_dec); FLAC__stream_decoder_delete(flac_dec); } @@ -386,101 +291,96 @@ flac_decode(struct decoder * decoder, struct input_stream *input_stream) flac_decode_internal(decoder, input_stream, false); } -#ifndef HAVE_OGGFLAC - static bool oggflac_init(G_GNUC_UNUSED const struct config_param *param) { -#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 return !!FLAC_API_SUPPORTS_OGG_FLAC; -#else - /* disable oggflac when libflac is too old */ - return false; -#endif } -#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 - static bool oggflac_scan_file(const char *file, const struct tag_handler *handler, void *handler_ctx) { - 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); + FLACMetadataChain chain; + if (!chain.ReadOgg(file)) { + g_debug("Failed to read OggFLAC tags: %s", + chain.GetStatusString()); return false; } - it = FLAC__metadata_iterator_new(); - FLAC__metadata_iterator_init(it, chain); - - do { - if (!(block = FLAC__metadata_iterator_get_block(it))) - break; + chain.Scan(handler, handler_ctx); + return true; +} - flac_scan_metadata(NULL, block, - handler, handler_ctx); - } while (FLAC__metadata_iterator_next(it)); - FLAC__metadata_iterator_delete(it); +static bool +oggflac_scan_stream(struct input_stream *is, + const struct tag_handler *handler, void *handler_ctx) +{ + FLACMetadataChain chain; + if (!chain.ReadOgg(is)) { + g_debug("Failed to read OggFLAC tags: %s", + chain.GetStatusString()); + return false; + } - FLAC__metadata_chain_delete(chain); + chain.Scan(handler, handler_ctx); return true; } static void oggflac_decode(struct decoder *decoder, struct input_stream *input_stream) { - if (ogg_stream_type_detect(input_stream) != FLAC) + if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_FLAC) return; - /* rewind the stream, because ogg_stream_type_detect() has + /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); + input_stream_lock_seek(input_stream, 0, SEEK_SET, nullptr); flac_decode_internal(decoder, input_stream, true); } -static const char *const oggflac_suffixes[] = { "ogg", "oga", NULL }; +static const char *const oggflac_suffixes[] = { "ogg", "oga", nullptr }; static const char *const oggflac_mime_types[] = { "application/ogg", "application/x-ogg", "audio/ogg", "audio/x-flac+ogg", "audio/x-ogg", - NULL + nullptr }; -#endif /* FLAC_API_VERSION_CURRENT >= 7 */ - const struct decoder_plugin oggflac_decoder_plugin = { - .name = "oggflac", - .init = oggflac_init, -#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 - .stream_decode = oggflac_decode, - .scan_file = oggflac_scan_file, - .suffixes = oggflac_suffixes, - .mime_types = oggflac_mime_types -#endif + "oggflac", + oggflac_init, + nullptr, + oggflac_decode, + nullptr, + oggflac_scan_file, + oggflac_scan_stream, + nullptr, + oggflac_suffixes, + oggflac_mime_types, }; -#endif /* HAVE_OGGFLAC */ - -static const char *const flac_suffixes[] = { "flac", NULL }; +static const char *const flac_suffixes[] = { "flac", nullptr }; static const char *const flac_mime_types[] = { "application/flac", "application/x-flac", "audio/flac", "audio/x-flac", - NULL + nullptr }; const struct decoder_plugin flac_decoder_plugin = { - .name = "flac", - .stream_decode = flac_decode, - .scan_file = flac_scan_file, - .suffixes = flac_suffixes, - .mime_types = flac_mime_types, + "flac", + nullptr, + nullptr, + flac_decode, + nullptr, + flac_scan_file, + flac_scan_stream, + nullptr, + flac_suffixes, + flac_mime_types, }; |