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:
		| @@ -36,6 +36,8 @@ | ||||
| #  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) | ||||
| @@ -78,18 +80,26 @@ | ||||
| #    include <OggFLAC/seekable_stream_decoder.h> | ||||
| #  endif | ||||
| #else /* FLAC_API_VERSION_CURRENT >= 7 */ | ||||
|    /* OggFLAC support is handled by our flac_plugin already */ | ||||
| #  ifdef HAVE_OGGFLAC | ||||
| #    undef HAVE_OGGFLAC | ||||
|  | ||||
|    /* 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 <FLAC/stream_decoder.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_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) | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| /* this code was based on flac123, from flac-tools */ | ||||
|  | ||||
| @@ -339,30 +340,34 @@ static MpdTag *flacTagDup(char *file) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int flac_decode(OutputBuffer * cb, DecoderControl * dc, | ||||
| 		       InputStream * inStream) | ||||
| static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc, | ||||
|                                InputStream * inStream, int is_ogg) | ||||
| { | ||||
| 	flac_decoder *flacDec; | ||||
| 	FlacData data; | ||||
| 	int ret = 0; | ||||
| 	const char *err = NULL; | ||||
|  | ||||
| 	if (!(flacDec = flac_new())) | ||||
| 		return -1; | ||||
| 	init_FlacData(&data, cb, dc, inStream); | ||||
| 	if (!flac_init(flacDec, flacRead, flacSeek, flacTell, flacLength, | ||||
| 	               flacEOF, flacWrite, flacMetadata, flacError, | ||||
| 		       (void *)&data)) { | ||||
| 		ERROR("flac problem doing init()\n"); | ||||
| 		flacPrintErroredState(flac_get_state(flacDec)); | ||||
| 		ret = -1; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	if (!flac_process_metadata(flacDec)) { | ||||
| 		ERROR("flac problem reading metadata\n"); | ||||
| 		flacPrintErroredState(flac_get_state(flacDec)); | ||||
| 		ret = -1; | ||||
| 		goto fail; | ||||
| 	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; | ||||
| @@ -412,15 +417,97 @@ fail: | ||||
|  | ||||
| 	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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Eric Wong
					Eric Wong