--- mpd-0.12.1/src/inputPlugins/_flac_common.h.orig 2007-01-01 20:16:07.000000000 +0000 +++ mpd-0.12.1/src/inputPlugins/_flac_common.h 2007-01-01 21:10:31.000000000 +0000 @@ -30,7 +30,114 @@ #include "../inputStream.h" #include "../outputBuffer.h" #include "../decode.h" -#include +#include +#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 +# include +# define flac_decoder FLAC__SeekableStreamDecoder +# define flac_new(x) FLAC__seekable_stream_decoder_new(x) + +# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) (0) + +# define flac_get_decode_position(x,y) \ + FLAC__seekable_stream_decoder_get_decode_position(x,y) +# define flac_get_state(x) FLAC__seekable_stream_decoder_get_state(x) +# define flac_process_single(x) FLAC__seekable_stream_decoder_process_single(x) +# define flac_process_metadata(x) \ + FLAC__seekable_stream_decoder_process_until_end_of_metadata(x) +# define flac_seek_absolute(x,y) \ + FLAC__seekable_stream_decoder_seek_absolute(x,y) +# define flac_finish(x) FLAC__seekable_stream_decoder_finish(x) +# define flac_delete(x) FLAC__seekable_stream_decoder_delete(x) + +# define flac_decoder_eof FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM + +# define flac_read_status FLAC__SeekableStreamDecoderReadStatus +# define flac_read_status_continue \ + FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK +# define flac_read_status_eof FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK +# define flac_read_status_abort \ + FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR + +# define flac_seek_status FLAC__SeekableStreamDecoderSeekStatus +# define flac_seek_status_ok FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK +# define flac_seek_status_error FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR + +# define flac_tell_status FLAC__SeekableStreamDecoderTellStatus +# define flac_tell_status_ok FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK +# define flac_tell_status_error \ + FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR +# define flac_tell_status_unsupported \ + FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR + +# define flac_length_status FLAC__SeekableStreamDecoderLengthStatus +# define flac_length_status_ok FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK +# define flac_length_status_error \ + FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR +# define flac_length_status_unsupported \ + FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR + +# ifdef HAVE_OGGFLAC +# include +# endif +#else /* FLAC_API_VERSION_CURRENT >= 7 */ + + /* OggFLAC support is handled by our flac_plugin already, and + * thus we *can* always have it if libFLAC was compiled with it */ +# ifndef HAVE_OGGFLAC +# define HAVE_OGGFLAC 1 +# endif +# include "_ogg_common.h" +# undef HAVE_OGGFLAC /* we don't need this defined anymore */ + +# include +# define flac_decoder FLAC__StreamDecoder +# define flac_new(x) FLAC__stream_decoder_new(x) + +# define flac_init(a,b,c,d,e,f,g,h,i,j) \ + (FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \ + == FLAC__STREAM_DECODER_INIT_STATUS_OK) +# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) \ + (FLAC__stream_decoder_init_ogg_stream(a,b,c,d,e,f,g,h,i,j) \ + == FLAC__STREAM_DECODER_INIT_STATUS_OK) + +# define flac_get_decode_position(x,y) \ + FLAC__stream_decoder_get_decode_position(x,y) +# define flac_get_state(x) FLAC__stream_decoder_get_state(x) +# define flac_process_single(x) FLAC__stream_decoder_process_single(x) +# define flac_process_metadata(x) \ + FLAC__stream_decoder_process_until_end_of_metadata(x) +# define flac_seek_absolute(x,y) FLAC__stream_decoder_seek_absolute(x,y) +# define flac_finish(x) FLAC__stream_decoder_finish(x) +# define flac_delete(x) FLAC__stream_decoder_delete(x) + +# define flac_decoder_eof FLAC__STREAM_DECODER_END_OF_STREAM + +# define flac_read_status FLAC__StreamDecoderReadStatus +# define flac_read_status_continue \ + FLAC__STREAM_DECODER_READ_STATUS_CONTINUE +# define flac_read_status_eof FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM +# define flac_read_status_abort FLAC__STREAM_DECODER_READ_STATUS_ABORT + +# define flac_seek_status FLAC__StreamDecoderSeekStatus +# define flac_seek_status_ok FLAC__STREAM_DECODER_SEEK_STATUS_OK +# define flac_seek_status_error FLAC__STREAM_DECODER_SEEK_STATUS_ERROR +# define flac_seek_status_unsupported \ + FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED + +# define flac_tell_status FLAC__StreamDecoderTellStatus +# define flac_tell_status_ok FLAC__STREAM_DECODER_TELL_STATUS_OK +# define flac_tell_status_error FLAC__STREAM_DECODER_TELL_STATUS_ERROR +# define flac_tell_status_unsupported \ + FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED + +# define flac_length_status FLAC__StreamDecoderLengthStatus +# define flac_length_status_ok FLAC__STREAM_DECODER_LENGTH_STATUS_OK +# define flac_length_status_error FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR +# define flac_length_status_unsupported \ + FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED + +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ + #include #define FLAC_CHUNK_SIZE 4080 --- mpd-0.12.1/src/inputPlugins/flac_plugin.c.orig 2007-01-01 20:17:35.000000000 +0000 +++ mpd-0.12.1/src/inputPlugins/flac_plugin.c 2007-01-01 21:08:32.000000000 +0000 @@ -16,12 +16,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../inputPlugin.h" +#include "_flac_common.h" #ifdef HAVE_FLAC -#include "_flac_common.h" - #include "../utils.h" #include "../log.h" #include "../pcm_utils.h" @@ -33,166 +31,14 @@ #include #include #include -#include -#include +#include -/* this code is based on flac123, from flac-tools */ +/* this code was based on flac123, from flac-tools */ -static void flacError(const FLAC__SeekableStreamDecoder *, - FLAC__StreamDecoderErrorStatus, void *); -static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state); -static void flacMetadata(const FLAC__SeekableStreamDecoder *, - const FLAC__StreamMetadata *, void *); -static FLAC__StreamDecoderWriteStatus flacWrite(const - FLAC__SeekableStreamDecoder *, - const FLAC__Frame *, - const FLAC__int32 * const buf[], - void *); -static FLAC__SeekableStreamDecoderReadStatus flacRead(const - FLAC__SeekableStreamDecoder - *, FLAC__byte buf[], - unsigned *, void *); -static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const - FLAC__SeekableStreamDecoder - *, FLAC__uint64, void *); -static FLAC__SeekableStreamDecoderTellStatus flacTell(const - FLAC__SeekableStreamDecoder - *, FLAC__uint64 *, - void *); -static FLAC__SeekableStreamDecoderLengthStatus flacLength(const - FLAC__SeekableStreamDecoder - *, FLAC__uint64 *, - void *); -static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *); - -static int flac_decode(OutputBuffer * cb, DecoderControl * dc, - InputStream * inStream) -{ - FLAC__SeekableStreamDecoder *flacDec = NULL; - FlacData data; - int status = 1; - int ret = 0; - - init_FlacData(&data, cb, dc, inStream); - - if (!(flacDec = FLAC__seekable_stream_decoder_new())) { - ret = -1; - goto fail; - } - /*status&=FLAC__file_decoder_set_md5_checking(flacDec,1); */ - status &= FLAC__seekable_stream_decoder_set_read_callback(flacDec, - flacRead); - status &= FLAC__seekable_stream_decoder_set_seek_callback(flacDec, - flacSeek); - status &= FLAC__seekable_stream_decoder_set_tell_callback(flacDec, - flacTell); - status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec, - flacLength); - status &= - FLAC__seekable_stream_decoder_set_eof_callback(flacDec, flacEOF); - status &= - FLAC__seekable_stream_decoder_set_write_callback(flacDec, - flacWrite); - status &= - FLAC__seekable_stream_decoder_set_metadata_callback(flacDec, - flacMetadata); - status &= - FLAC__seekable_stream_decoder_set_metadata_respond(flacDec, - FLAC__METADATA_TYPE_VORBIS_COMMENT); - status &= - FLAC__seekable_stream_decoder_set_error_callback(flacDec, - flacError); - status &= - FLAC__seekable_stream_decoder_set_client_data(flacDec, - (void *)&data); - if (!status) { - ERROR("flac problem before init()\n"); - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state - (flacDec)); - ret = -1; - goto fail; - } - - if (FLAC__seekable_stream_decoder_init(flacDec) != - FLAC__SEEKABLE_STREAM_DECODER_OK) { - ERROR("flac problem doing init()\n"); - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state - (flacDec)); - ret = -1; - goto fail; - } - - if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata - (flacDec)) { - ERROR("flac problem reading metadata\n"); - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state - (flacDec)); - ret = -1; - goto fail; - } - - dc->state = DECODE_STATE_DECODE; - - while (1) { - FLAC__seekable_stream_decoder_process_single(flacDec); - if (FLAC__seekable_stream_decoder_get_state(flacDec) != - FLAC__SEEKABLE_STREAM_DECODER_OK) { - break; - } - if (dc->seek) { - FLAC__uint64 sampleToSeek = dc->seekWhere * - dc->audioFormat.sampleRate + 0.5; - if (FLAC__seekable_stream_decoder_seek_absolute(flacDec, - sampleToSeek)) - { - clearOutputBuffer(cb); - data.time = ((float)sampleToSeek) / - dc->audioFormat.sampleRate; - data.position = 0; - } else - dc->seekError = 1; - dc->seek = 0; - } - } - /* I don't think we need this bit here! -shank */ - /*FLAC__file_decoder_process_until_end_of_file(flacDec); */ - if (!dc->stop) { - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state - (flacDec)); - FLAC__seekable_stream_decoder_finish(flacDec); - } - /* send last little bit */ - if (data.chunk_length > 0 && !dc->stop) { - flacSendChunk(&data); - flushOutputBuffer(data.cb); - } - - /*if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } */ - - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - -fail: - if (data.replayGainInfo) - freeReplayGainInfo(data.replayGainInfo); - - if (flacDec) - FLAC__seekable_stream_decoder_delete(flacDec); - - closeInputStream(inStream); - - return ret; -} - -static FLAC__SeekableStreamDecoderReadStatus flacRead(const - FLAC__SeekableStreamDecoder - * flacDec, - FLAC__byte buf[], - unsigned *bytes, - void *fdata) +static flac_read_status flacRead(const flac_decoder * flacDec, + FLAC__byte buf[], + unsigned *bytes, + void *fdata) { FlacData *data = (FlacData *) fdata; size_t r; @@ -207,55 +53,51 @@ } *bytes = r; - if (*bytes == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; - - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + if (r == 0 && !data->dc->stop) { + if (inputStreamAtEOF(data->inStream)) + return flac_read_status_eof; + else + return flac_read_status_abort; + } + return flac_read_status_continue; } -static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const - FLAC__SeekableStreamDecoder - * flacDec, - FLAC__uint64 offset, - void *fdata) +static flac_seek_status flacSeek(const flac_decoder * flacDec, + FLAC__uint64 offset, + void *fdata) { FlacData *data = (FlacData *) fdata; if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return flac_seek_status_error; } - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + return flac_tell_status_ok; } -static FLAC__SeekableStreamDecoderTellStatus flacTell(const - FLAC__SeekableStreamDecoder - * flacDec, - FLAC__uint64 * offset, - void *fdata) +static flac_tell_status flacTell(const flac_decoder * flacDec, + FLAC__uint64 * offset, + void *fdata) { FlacData *data = (FlacData *) fdata; *offset = (long)(data->inStream->offset); - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + return flac_tell_status_ok; } -static FLAC__SeekableStreamDecoderLengthStatus flacLength(const - FLAC__SeekableStreamDecoder - * flacDec, - FLAC__uint64 * length, - void *fdata) +static flac_length_status flacLength(const flac_decoder * flacDec, + FLAC__uint64 * length, + void *fdata) { FlacData *data = (FlacData *) fdata; *length = (size_t) (data->inStream->size); - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + return flac_length_status_ok; } -static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, - void *fdata) +static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata) { FlacData *data = (FlacData *) fdata; @@ -264,52 +106,112 @@ return false; } -static void flacError(const FLAC__SeekableStreamDecoder * dec, +static void flacError(const flac_decoder *dec, FLAC__StreamDecoderErrorStatus status, void *fdata) { flac_error_common_cb("flac", status, (FlacData *) 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: - ERROR("flac allocation error\n"); + str = "allocation error"; break; case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: - ERROR("flac read error\n"); + str = "read error"; break; case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: - ERROR("flac seek error\n"); + str = "seek error"; break; case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: - ERROR("flac seekable stream error\n"); + str = "seekable stream error"; break; case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: - ERROR("flac decoder already initialized\n"); + str = "decoder already initialized"; break; case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: - ERROR("invalid flac callback\n"); + str = "invalid callback"; break; case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: - ERROR("flac decoder uninitialized\n"); + str = "decoder uninitialized"; + } + ERROR("flac %s\n", str); +} + +static int flac_init(FLAC__SeekableStreamDecoder *dec, + FLAC__SeekableStreamDecoderReadCallback read_cb, + FLAC__SeekableStreamDecoderSeekCallback seek_cb, + FLAC__SeekableStreamDecoderTellCallback tell_cb, + FLAC__SeekableStreamDecoderLengthCallback length_cb, + FLAC__SeekableStreamDecoderEofCallback eof_cb, + FLAC__SeekableStreamDecoderWriteCallback write_cb, + FLAC__SeekableStreamDecoderMetadataCallback metadata_cb, + FLAC__SeekableStreamDecoderErrorCallback error_cb, + void *data) +{ + int s = 1; + s &= FLAC__seekable_stream_decoder_set_read_callback(dec, read_cb); + s &= FLAC__seekable_stream_decoder_set_seek_callback(dec, seek_cb); + s &= FLAC__seekable_stream_decoder_set_tell_callback(dec, tell_cb); + s &= FLAC__seekable_stream_decoder_set_length_callback(dec, length_cb); + s &= FLAC__seekable_stream_decoder_set_eof_callback(dec, eof_cb); + s &= FLAC__seekable_stream_decoder_set_write_callback(dec, write_cb); + s &= FLAC__seekable_stream_decoder_set_metadata_callback(dec, + metadata_cb); + s &= FLAC__seekable_stream_decoder_set_metadata_respond(dec, + FLAC__METADATA_TYPE_VORBIS_COMMENT); + s &= FLAC__seekable_stream_decoder_set_error_callback(dec, error_cb); + s &= FLAC__seekable_stream_decoder_set_client_data(dec, data); + if (!s || (FLAC__seekable_stream_decoder_init(dec) != + FLAC__SEEKABLE_STREAM_DECODER_OK)) + return 0; + return 1; +} +#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: + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + 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__SEEKABLE_STREAM_DECODER_OK: - case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: - case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: + 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"; } + ERROR("flac %s\n", str); } +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ -static void flacMetadata(const FLAC__SeekableStreamDecoder * dec, +static void flacMetadata(const flac_decoder * dec, const FLAC__StreamMetadata * block, void *vdata) { flac_metadata_common_cb(block, (FlacData *) vdata); } -static FLAC__StreamDecoderWriteStatus flacWrite(const - FLAC__SeekableStreamDecoder * - dec, const FLAC__Frame * frame, +static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, + const FLAC__Frame * frame, const FLAC__int32 * const buf[], void *vdata) { @@ -325,7 +227,7 @@ timeChange = ((float)samples) / frame->header.sample_rate; data->time += timeChange; - FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition); + flac_get_decode_position(dec, &newPosition); if (data->position) { data->bitRate = ((newPosition - data->position) * 8.0 / timeChange) @@ -438,12 +340,174 @@ return ret; } +static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc, + InputStream * inStream, int is_ogg) +{ + flac_decoder *flacDec; + FlacData data; + const char *err = NULL; + + if (!(flacDec = flac_new())) + return -1; + init_FlacData(&data, cb, dc, inStream); + if (is_ogg) { + if (!flac_ogg_init(flacDec, flacRead, flacSeek, flacTell, + flacLength, flacEOF, flacWrite, flacMetadata, + flacError, (void *)&data)) { + err = "doing Ogg init()"; + goto fail; + } + } else { + if (!flac_init(flacDec, flacRead, flacSeek, flacTell, + flacLength, flacEOF, flacWrite, flacMetadata, + flacError, (void *)&data)) { + err = "doing init()"; + goto fail; + } + if (!flac_process_metadata(flacDec)) { + err = "problem reading metadata"; + goto fail; + } + } + + dc->state = DECODE_STATE_DECODE; + + while (1) { + if (!flac_process_single(flacDec)) + break; + if (flac_get_state(flacDec) == flac_decoder_eof) + break; + if (dc->seek) { + FLAC__uint64 sampleToSeek = dc->seekWhere * + dc->audioFormat.sampleRate + 0.5; + if (flac_seek_absolute(flacDec, sampleToSeek)) { + clearOutputBuffer(cb); + data.time = ((float)sampleToSeek) / + dc->audioFormat.sampleRate; + data.position = 0; + } else + dc->seekError = 1; + dc->seek = 0; + } + } + if (!dc->stop) { + flacPrintErroredState(flac_get_state(flacDec)); + flac_finish(flacDec); + } + /* send last little bit */ + if (data.chunk_length > 0 && !dc->stop) { + flacSendChunk(&data); + flushOutputBuffer(data.cb); + } + + /*if(dc->seek) { + dc->seekError = 1; + dc->seek = 0; + } */ + + dc->state = DECODE_STATE_STOP; + dc->stop = 0; + +fail: + if (data.replayGainInfo) + freeReplayGainInfo(data.replayGainInfo); + + if (flacDec) + flac_delete(flacDec); + + closeInputStream(inStream); + + if (err) { + ERROR("flac %s\n", err); + return -1; + } + return 0; +} + +static int flac_decode(OutputBuffer * cb, DecoderControl * dc, + InputStream * inStream) +{ + return flac_decode_internal(cb, dc, inStream, 0); +} + +#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 +# define flac_plugin_init NULL +#else /* FLAC_API_VERSION_CURRENT >= 7 */ +/* some of this stuff is duplicated from oggflac_plugin.c */ +extern InputPlugin oggflacPlugin; + +static MpdTag *oggflac_tag_dup(char *file) +{ + MpdTag *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; + it = FLAC__metadata_iterator_new(); + FLAC__metadata_iterator_init(it, chain); + do { + if (!(block = FLAC__metadata_iterator_get_block(it))) + break; + if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + ret = copyVorbisCommentBlockToMpdTag(block, ret); + } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) { + if (!ret) + ret = newMpdTag(); + ret->time = ((float)block->data.stream_info. + total_samples) / + block->data.stream_info.sample_rate + 0.5; + } + } while (FLAC__metadata_iterator_next(it)); + FLAC__metadata_iterator_delete(it); +out: + FLAC__metadata_chain_delete(chain); + return ret; +} + +static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc, + InputStream * inStream) +{ + return flac_decode_internal(cb, dc, inStream, 1); +} + +static unsigned int oggflac_try_decode(InputStream * inStream) +{ + return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0; +} + +static char *oggflac_suffixes[] = { "ogg", NULL }; +static char *oggflac_mime_types[] = { "application/ogg", NULL }; + +static int flac_plugin_init(void) +{ + if (!FLAC_API_SUPPORTS_OGG_FLAC) { + DEBUG("libFLAC does not support OggFLAC\n"); + return 1; + } + DEBUG("libFLAC supports OggFLAC, initializing OggFLAC support\n"); + assert(oggflacPlugin.name == NULL); + oggflacPlugin.name = "oggflac"; + oggflacPlugin.tryDecodeFunc = oggflac_try_decode; + oggflacPlugin.streamDecodeFunc = oggflac_decode; + oggflacPlugin.tagDupFunc = oggflac_tag_dup; + oggflacPlugin.streamTypes = INPUT_PLUGIN_STREAM_URL | + INPUT_PLUGIN_STREAM_FILE; + oggflacPlugin.suffixes = oggflac_suffixes; + oggflacPlugin.mimeTypes = oggflac_mime_types; + loadInputPlugin(&oggflacPlugin); + return 1; +} + +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ + static char *flacSuffixes[] = { "flac", NULL }; static char *flac_mime_types[] = { "application/x-flac", NULL }; InputPlugin flacPlugin = { "flac", - NULL, + flac_plugin_init, NULL, NULL, flac_decode,