Add OggFLAC support when using the new 1.1.3 FLAC library

This means that when using libFLAC as a shared object,
OggFLAC support is dependent on the compile-time options of
the libFLAC library loaded.

git-svn-id: https://svn.musicpd.org/mpd/trunk@5112 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
Eric Wong 2006-12-04 04:45:50 +00:00
parent b152086ae4
commit 63dd4b4598
2 changed files with 119 additions and 22 deletions

View File

@ -36,6 +36,8 @@
# define flac_decoder FLAC__SeekableStreamDecoder # define flac_decoder FLAC__SeekableStreamDecoder
# define flac_new(x) FLAC__seekable_stream_decoder_new(x) # 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) \ # define flac_get_decode_position(x,y) \
FLAC__seekable_stream_decoder_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_get_state(x) FLAC__seekable_stream_decoder_get_state(x)
@ -78,18 +80,26 @@
# include <OggFLAC/seekable_stream_decoder.h> # include <OggFLAC/seekable_stream_decoder.h>
# endif # endif
#else /* FLAC_API_VERSION_CURRENT >= 7 */ #else /* FLAC_API_VERSION_CURRENT >= 7 */
/* OggFLAC support is handled by our flac_plugin already */
# ifdef HAVE_OGGFLAC /* OggFLAC support is handled by our flac_plugin already, and
# undef HAVE_OGGFLAC * thus we *can* always have it if libFLAC was compiled with it */
# ifndef HAVE_OGGFLAC
# define HAVE_OGGFLAC 1
# endif # endif
# include <FLAC/stream_decoder.h>
# include "_ogg_common.h" # include "_ogg_common.h"
# undef HAVE_OGGFLAC /* we don't need this defined anymore */
# include <FLAC/stream_decoder.h>
# define flac_decoder FLAC__StreamDecoder # define flac_decoder FLAC__StreamDecoder
# define flac_new(x) FLAC__stream_decoder_new(x) # define flac_new(x) FLAC__stream_decoder_new(x)
# define flac_init(a,b,c,d,e,f,g,h,i,j) \ # 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_stream(a,b,c,d,e,f,g,h,i,j) \
== FLAC__STREAM_DECODER_INIT_STATUS_OK) == 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) \ # define flac_get_decode_position(x,y) \
FLAC__stream_decoder_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_get_state(x) FLAC__stream_decoder_get_state(x)

View File

@ -31,6 +31,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
/* this code was based on flac123, from flac-tools */ /* this code was based on flac123, from flac-tools */
@ -339,31 +340,35 @@ static MpdTag *flacTagDup(char *file)
return ret; return ret;
} }
static int flac_decode(OutputBuffer * cb, DecoderControl * dc, static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream) InputStream * inStream, int is_ogg)
{ {
flac_decoder *flacDec; flac_decoder *flacDec;
FlacData data; FlacData data;
int ret = 0; const char *err = NULL;
if (!(flacDec = flac_new())) if (!(flacDec = flac_new()))
return -1; return -1;
init_FlacData(&data, cb, dc, inStream); init_FlacData(&data, cb, dc, inStream);
if (!flac_init(flacDec, flacRead, flacSeek, flacTell, flacLength, if (is_ogg) {
flacEOF, flacWrite, flacMetadata, flacError, if (!flac_ogg_init(flacDec, flacRead, flacSeek, flacTell,
(void *)&data)) { flacLength, flacEOF, flacWrite, flacMetadata,
ERROR("flac problem doing init()\n"); flacError, (void *)&data)) {
flacPrintErroredState(flac_get_state(flacDec)); err = "doing Ogg init()";
ret = -1;
goto fail; goto fail;
} }
} else {
if (!flac_process_metadata(flacDec)) { if (!flac_init(flacDec, flacRead, flacSeek, flacTell,
ERROR("flac problem reading metadata\n"); flacLength, flacEOF, flacWrite, flacMetadata,
flacPrintErroredState(flac_get_state(flacDec)); flacError, (void *)&data)) {
ret = -1; err = "doing init()";
goto fail; goto fail;
} }
if (!flac_process_metadata(flacDec)) {
err = "problem reading metadata";
goto fail;
}
}
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
@ -412,15 +417,97 @@ fail:
closeInputStream(inStream); 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; 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 *flacSuffixes[] = { "flac", NULL };
static char *flac_mime_types[] = { "application/x-flac", NULL }; static char *flac_mime_types[] = { "application/x-flac", NULL };
InputPlugin flacPlugin = { InputPlugin flacPlugin = {
"flac", "flac",
NULL, flac_plugin_init,
NULL, NULL,
NULL, NULL,
flac_decode, flac_decode,