From c4a9e3790f489ac70af60fe8cd1c16230979bc76 Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Tue, 4 May 2004 23:39:02 +0000 Subject: flac uses abstracted inputStream stuff git-svn-id: https://svn.musicpd.org/mpd/trunk@905 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/flac_decode.c | 195 +++++++++++++++++++++++++++++++++++++++++------------- src/inputStream.c | 4 ++ src/inputStream.h | 1 + 3 files changed, 154 insertions(+), 46 deletions(-) diff --git a/src/flac_decode.c b/src/flac_decode.c index 45ccb27b6..9760bcb11 100644 --- a/src/flac_decode.c +++ b/src/flac_decode.c @@ -23,11 +23,12 @@ #include "utils.h" #include "log.h" #include "pcm_utils.h" +#include "inputStream.h" #include #include #include -#include +#include #include typedef struct { @@ -39,21 +40,35 @@ typedef struct { Buffer * cb; AudioFormat * af; DecoderControl * dc; - char * file; + char * file; + InputStream inStream; } FlacData; /* this code is based on flac123, from flac-tools */ int flacSendChunk(FlacData * data); -void flacError(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *); -void flacPrintErroredState(FLAC__FileDecoderState state, char * file); -void flacMetadata(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *); -FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const buf[], void *); +void flacError(const FLAC__SeekableStreamDecoder *, + FLAC__StreamDecoderErrorStatus, void *); +void flacPrintErroredState(FLAC__SeekableStreamDecoderState state, char * file); +void flacMetadata(const FLAC__SeekableStreamDecoder *, + const FLAC__StreamMetadata *, void *); +FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *, + const FLAC__Frame *, const FLAC__int32 * const buf[], void *); +FLAC__SeekableStreamDecoderReadStatus flacRead( + const FLAC__SeekableStreamDecoder *, FLAC__byte buf[], + unsigned *, void *); +FLAC__SeekableStreamDecoderSeekStatus flacSeek( + const FLAC__SeekableStreamDecoder *, FLAC__uint64, void *); +FLAC__SeekableStreamDecoderTellStatus flacTell( + const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *); +FLAC__SeekableStreamDecoderLengthStatus flacLength( + const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *); +FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *); void flacPlayFile(char *file, Buffer * cb, AudioFormat * af, DecoderControl *dc) { - FLAC__FileDecoder * flacDec; + FLAC__SeekableStreamDecoder * flacDec; FlacData data; int status = 1; @@ -64,39 +79,59 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af, data.cb = cb; data.af = af; data.dc = dc; - data.file = file; + data.file = file; + + if(openInputStreamFromFile(&(data.inStream),file)<0) { + ERROR("unable to open flac: %s\n",file); + return; + } - if(!(flacDec = FLAC__file_decoder_new())) return; + if(!(flacDec = FLAC__seekable_stream_decoder_new())) return; /*status&=FLAC__file_decoder_set_md5_checking(flacDec,1);*/ - status&=FLAC__file_decoder_set_filename(flacDec,file); - status&=FLAC__file_decoder_set_write_callback(flacDec,flacWrite); - status&=FLAC__file_decoder_set_metadata_callback(flacDec,flacMetadata); - status&=FLAC__file_decoder_set_error_callback(flacDec,flacError); - status&=FLAC__file_decoder_set_client_data(flacDec, (void *)&data); + 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_error_callback(flacDec, + flacError); + status&=FLAC__seekable_stream_decoder_set_client_data(flacDec, + (void *)&data); if(!status) { ERROR("flac problem before init(): %s\n",file); - flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file); - FLAC__file_decoder_delete(flacDec); + flacPrintErroredState( + FLAC__seekable_stream_decoder_get_state(flacDec),file); + FLAC__seekable_stream_decoder_delete(flacDec); return; } - if(FLAC__file_decoder_init(flacDec)!= + if(FLAC__seekable_stream_decoder_init(flacDec)!= FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) { ERROR("flac problem doing init(): %s\n",file); - flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file); - FLAC__file_decoder_delete(flacDec); + flacPrintErroredState( + FLAC__seekable_stream_decoder_get_state(flacDec),file); + FLAC__seekable_stream_decoder_delete(flacDec); return; } - if(!FLAC__file_decoder_process_until_end_of_metadata(flacDec)) { + if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDec)) { ERROR("flac problem reading metadata: %s\n",file); - flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file); - FLAC__file_decoder_delete(flacDec); + flacPrintErroredState( + FLAC__seekable_stream_decoder_get_state(flacDec),file); + FLAC__seekable_stream_decoder_delete(flacDec); return; } while(1) { - FLAC__file_decoder_process_single(flacDec); - if(FLAC__file_decoder_get_state(flacDec)!= - FLAC__FILE_DECODER_OK) + FLAC__seekable_stream_decoder_process_single(flacDec); + if(FLAC__seekable_stream_decoder_get_state(flacDec)!= + FLAC__SEEKABLE_STREAM_DECODER_OK) { break; } @@ -105,7 +140,7 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af, af->sampleRate+0.5; cb->end = cb->begin; cb->wrap = 0; - if(FLAC__file_decoder_seek_absolute(flacDec, + if(FLAC__seekable_stream_decoder_seek_absolute(flacDec, sampleToSeek)) { data.time = ((float)sampleToSeek)/ @@ -118,16 +153,76 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af, /* I don't think we need this bit here! -shank */ /*FLAC__file_decoder_process_until_end_of_file(flacDec);*/ if(!dc->stop) { - flacPrintErroredState(FLAC__file_decoder_get_state(flacDec), - file); - FLAC__file_decoder_finish(flacDec); + flacPrintErroredState( + FLAC__seekable_stream_decoder_get_state(flacDec),file); + FLAC__seekable_stream_decoder_finish(flacDec); } - FLAC__file_decoder_delete(flacDec); + FLAC__seekable_stream_decoder_delete(flacDec); /* send last little bit */ if(data.chunk_length>0 && !dc->stop) flacSendChunk(&data); } -void flacError(const FLAC__FileDecoder *dec, FLAC__StreamDecoderErrorStatus status, void *fdata) { +FLAC__SeekableStreamDecoderReadStatus flacRead( + const FLAC__SeekableStreamDecoder * flacDec, FLAC__byte buf[], + unsigned * bytes, void * fdata) { + FlacData * data = (FlacData *) fdata; + + *bytes = readFromInputStream(&(data->inStream),(void *)buf,1,*bytes); + + if(*bytes==0) return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; +} + +FLAC__SeekableStreamDecoderSeekStatus flacSeek( + const FLAC__SeekableStreamDecoder * 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__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; +} + +FLAC__SeekableStreamDecoderTellStatus flacTell( + const FLAC__SeekableStreamDecoder * flacDec, + FLAC__uint64 * offset, void * fdata) +{ + FlacData * data = (FlacData *) fdata; + + *offset = data->inStream.offset; + + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; +} + +FLAC__SeekableStreamDecoderLengthStatus flacLength( + const FLAC__SeekableStreamDecoder * flacDec, + FLAC__uint64 * length, void * fdata) +{ + FlacData * data = (FlacData *) fdata; + + *length = data->inStream.size; + + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; +} + +FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) { + FlacData * data = (FlacData *) fdata; + + switch(inputStreamAtEOF(&(data->inStream))) { + case 1: + return true; + default: + return false; + } +} + +void flacError(const FLAC__SeekableStreamDecoder *dec, + FLAC__StreamDecoderErrorStatus status, void *fdata) +{ FlacData * data = (FlacData *) fdata; if(data->dc->stop) return; @@ -146,36 +241,41 @@ void flacError(const FLAC__FileDecoder *dec, FLAC__StreamDecoderErrorStatus stat } } -void flacPrintErroredState(FLAC__FileDecoderState state, char * file) { +void flacPrintErroredState(FLAC__SeekableStreamDecoderState state, + char * file) +{ switch(state) { - case FLAC__FILE_DECODER_ERROR_OPENING_FILE: - ERROR("error opening flac: %s\n",file); - break; - case FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR: + case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: ERROR("flac allocation error\n"); break; - case FLAC__FILE_DECODER_SEEK_ERROR: + case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: + ERROR("flac read error: %s\n",file); + break; + case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: ERROR("flac seek error: %s\n",file); break; - case FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR: + case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: ERROR("flac seekable stream error: %s\n",file); break; - case FLAC__FILE_DECODER_ALREADY_INITIALIZED: + case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: ERROR("flac decoder already initilaized: %s\n",file); break; - case FLAC__FILE_DECODER_INVALID_CALLBACK: + case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: ERROR("invalid flac callback\n"); break; - case FLAC__FILE_DECODER_UNINITIALIZED: + case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: ERROR("flac decoder uninitialized: %s\n",file); break; - case FLAC__FILE_DECODER_OK: - case FLAC__FILE_DECODER_END_OF_FILE: + case FLAC__SEEKABLE_STREAM_DECODER_OK: + case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: + case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: break; } } -void flacMetadata(const FLAC__FileDecoder *dec, const FLAC__StreamMetadata *meta, void *data) { +void flacMetadata(const FLAC__SeekableStreamDecoder *dec, + const FLAC__StreamMetadata *meta, void *data) +{ } int flacSendChunk(FlacData * data) { @@ -203,7 +303,10 @@ int flacSendChunk(FlacData * data) { return 0; } -FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *dec, const FLAC__Frame *frame, const FLAC__int32 * const buf[], void * vdata) { +FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec, + const FLAC__Frame *frame, const FLAC__int32 * const buf[], + void * vdata) +{ FlacData * data = (FlacData *)vdata; FLAC__uint32 samples = frame->header.blocksize; FLAC__uint16 u16; @@ -216,7 +319,7 @@ FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *dec, const FLA timeChange = ((float)samples)/frame->header.sample_rate; data->time+= timeChange; - FLAC__file_decoder_get_decode_position(dec,&newPosition); + FLAC__seekable_stream_decoder_get_decode_position(dec,&newPosition); if(data->position) { data->bitRate = ((newPosition-data->position)*8.0/timeChange) /1000+0.5; diff --git a/src/inputStream.c b/src/inputStream.c index 9168e6aeb..bddde9aad 100644 --- a/src/inputStream.c +++ b/src/inputStream.c @@ -71,3 +71,7 @@ int closeInputStream(InputStream * inStream) { return 0; } + +int inputStreamAtEOF(InputStream * inStream) { + return feof(inStream->fp); +} diff --git a/src/inputStream.h b/src/inputStream.h index 8998e3ac1..d8ed90d36 100644 --- a/src/inputStream.h +++ b/src/inputStream.h @@ -34,6 +34,7 @@ typedef struct _InputStream { int openInputStreamFromFile(InputStream * inStream, char * filename); int seekInputStream(InputStream * inStream, long offset, int whence); int closeInputStream(InputStream * inStream); +int inputStreamAtEOF(InputStream * inStream); size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size, size_t nmemb); -- cgit v1.2.3