diff options
Diffstat (limited to 'src/inputPlugins/flac_plugin.c')
-rw-r--r-- | src/inputPlugins/flac_plugin.c | 419 |
1 files changed, 231 insertions, 188 deletions
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c index ca3f196ce..737cdbcd4 100644 --- a/src/inputPlugins/flac_plugin.c +++ b/src/inputPlugins/flac_plugin.c @@ -39,211 +39,240 @@ /* this code is based on flac123, from flac-tools */ static void flacError(const FLAC__SeekableStreamDecoder *, - FLAC__StreamDecoderErrorStatus, void *); + 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 *); + 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) +static int flac_decode(OutputBuffer * cb, DecoderControl * dc, + InputStream * inStream) { - FLAC__SeekableStreamDecoder * flacDec = NULL; + FLAC__SeekableStreamDecoder *flacDec = NULL; FlacData data; int status = 1; - int ret =0; + 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) { + 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)); + flacPrintErroredState(FLAC__seekable_stream_decoder_get_state + (flacDec)); ret = -1; - goto fail; + goto fail; } - if(FLAC__seekable_stream_decoder_init(flacDec)!= - FLAC__SEEKABLE_STREAM_DECODER_OK) - { + 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; + flacPrintErroredState(FLAC__seekable_stream_decoder_get_state + (flacDec)); + ret = -1; + goto fail; } - if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDec)) { + 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)); + flacPrintErroredState(FLAC__seekable_stream_decoder_get_state + (flacDec)); ret = -1; - goto fail; + goto fail; } dc->state = DECODE_STATE_DECODE; - while(1) { + while (1) { FLAC__seekable_stream_decoder_process_single(flacDec); - if(FLAC__seekable_stream_decoder_get_state(flacDec)!= - FLAC__SEEKABLE_STREAM_DECODER_OK) - { + 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)) + 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; + clearOutputBuffer(cb); + data.time = ((float)sampleToSeek) / + dc->audioFormat.sampleRate; data.position = 0; - } - else dc->seekError = 1; + } 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__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) { + if (data.chunk_length > 0 && !dc->stop) { flacSendChunk(&data); flushOutputBuffer(data.cb); } /*if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } */ - + dc->seekError = 1; + dc->seek = 0; + } */ + dc->state = DECODE_STATE_STOP; dc->stop = 0; -fail: - if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo); + fail: + if (data.replayGainInfo) + freeReplayGainInfo(data.replayGainInfo); - if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec); + 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) { - FlacData * data = (FlacData *) fdata; +static FLAC__SeekableStreamDecoderReadStatus flacRead(const + FLAC__SeekableStreamDecoder + * flacDec, + FLAC__byte buf[], + unsigned *bytes, + void *fdata) +{ + FlacData *data = (FlacData *) fdata; size_t r; while (1) { - r = readFromInputStream(data->inStream,(void *)buf,1,*bytes); + r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes); if (r == 0 && !inputStreamAtEOF(data->inStream) && - !data->dc->stop) + !data->dc->stop) my_usleep(10000); else break; } *bytes = r; - - if (*bytes==0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) + + 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; + + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; } -static FLAC__SeekableStreamDecoderSeekStatus flacSeek( - const FLAC__SeekableStreamDecoder * flacDec, - FLAC__uint64 offset, void * fdata) +static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const + FLAC__SeekableStreamDecoder + * flacDec, + FLAC__uint64 offset, + void *fdata) { - FlacData * data = (FlacData *) fdata; + FlacData *data = (FlacData *) fdata; - if(seekInputStream(data->inStream,offset,SEEK_SET)<0) { - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; - } + if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + } - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; } -static FLAC__SeekableStreamDecoderTellStatus flacTell( - const FLAC__SeekableStreamDecoder * flacDec, - FLAC__uint64 * offset, void * fdata) +static FLAC__SeekableStreamDecoderTellStatus flacTell(const + FLAC__SeekableStreamDecoder + * flacDec, + FLAC__uint64 * offset, + void *fdata) { - FlacData * data = (FlacData *) fdata; + FlacData *data = (FlacData *) fdata; - *offset = (long)(data->inStream->offset); + *offset = (long)(data->inStream->offset); - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; } -static FLAC__SeekableStreamDecoderLengthStatus flacLength( - const FLAC__SeekableStreamDecoder * flacDec, - FLAC__uint64 * length, void * fdata) +static FLAC__SeekableStreamDecoderLengthStatus flacLength(const + FLAC__SeekableStreamDecoder + * flacDec, + FLAC__uint64 * length, + void *fdata) { - FlacData * data = (FlacData *) fdata; + FlacData *data = (FlacData *) fdata; - *length = (size_t)(data->inStream->size); + *length = (size_t) (data->inStream->size); - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; } -static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) { - FlacData * data = (FlacData *) fdata; - +static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, + void *fdata) +{ + FlacData *data = (FlacData *) fdata; + if (inputStreamAtEOF(data->inStream) == 1) - return true; + return true; return false; } -static void flacError(const FLAC__SeekableStreamDecoder *dec, - FLAC__StreamDecoderErrorStatus status, void *fdata) +static void flacError(const FLAC__SeekableStreamDecoder * dec, + FLAC__StreamDecoderErrorStatus status, void *fdata) { - flac_error_common_cb("flac",status,(FlacData *) fdata); + flac_error_common_cb("flac", status, (FlacData *) fdata); } static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) { - switch(state) { + switch (state) { case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: ERROR("flac allocation error\n"); break; @@ -272,48 +301,53 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) } } -static void flacMetadata(const FLAC__SeekableStreamDecoder *dec, - const FLAC__StreamMetadata *block, void *vdata) +static void flacMetadata(const FLAC__SeekableStreamDecoder * dec, + const FLAC__StreamMetadata * block, void *vdata) { - flac_metadata_common_cb(block, (FlacData *)vdata); + flac_metadata_common_cb(block, (FlacData *) vdata); } -static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec, - const FLAC__Frame *frame, const FLAC__int32 * const buf[], - void * vdata) +static FLAC__StreamDecoderWriteStatus flacWrite(const + FLAC__SeekableStreamDecoder * + dec, const FLAC__Frame * frame, + const FLAC__int32 * const buf[], + void *vdata) { - FlacData * data = (FlacData *)vdata; + FlacData *data = (FlacData *) vdata; FLAC__uint32 samples = frame->header.blocksize; FLAC__uint16 u16; - unsigned char * uc; + unsigned char *uc; int c_samp, c_chan, d_samp; int i; float timeChange; FLAC__uint64 newPosition = 0; - - timeChange = ((float)samples)/frame->header.sample_rate; - data->time+= timeChange; - - FLAC__seekable_stream_decoder_get_decode_position(dec,&newPosition); - if(data->position) { - data->bitRate = ((newPosition-data->position)*8.0/timeChange) - /1000+0.5; + + timeChange = ((float)samples) / frame->header.sample_rate; + data->time += timeChange; + + FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition); + if (data->position) { + data->bitRate = + ((newPosition - data->position) * 8.0 / timeChange) + / 1000 + 0.5; } data->position = newPosition; - for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { - for(c_chan = 0; c_chan < frame->header.channels; - c_chan++, d_samp++) { + for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { + for (c_chan = 0; c_chan < frame->header.channels; + c_chan++, d_samp++) { u16 = buf[c_chan][c_samp]; uc = (unsigned char *)&u16; - for(i=0;i<(data->dc->audioFormat.bits/8);i++) { - if(data->chunk_length>=FLAC_CHUNK_SIZE) { - if(flacSendChunk(data)<0) { - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) { + if (data->chunk_length >= FLAC_CHUNK_SIZE) { + if (flacSendChunk(data) < 0) { + return + FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } data->chunk_length = 0; - if(data->dc->seek) { - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + if (data->dc->seek) { + return + FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } } data->chunk[data->chunk_length++] = *(uc++); @@ -324,66 +358,77 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecode return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } -static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) { - MpdTag * ret = NULL; - FLAC__Metadata_SimpleIterator * it; - FLAC__StreamMetadata * block = NULL; +static MpdTag *flacMetadataDup(char *file, int *vorbisCommentFound) +{ + MpdTag *ret = NULL; + FLAC__Metadata_SimpleIterator *it; + FLAC__StreamMetadata *block = NULL; *vorbisCommentFound = 0; it = FLAC__metadata_simple_iterator_new(); - if(!FLAC__metadata_simple_iterator_init(it, file ,1,0)) { - switch(FLAC__metadata_simple_iterator_status(it)) { - case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: - DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n",file); - break; - case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: - DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n",file); - break; - case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: - DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n",file); - break; - default: - DEBUG("flacMetadataDup: Reading '%s' metadata failed\n",file); + if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) { + switch (FLAC__metadata_simple_iterator_status(it)) { + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: + DEBUG + ("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n", + file); + break; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: + DEBUG + ("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n", + file); + break; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: + DEBUG + ("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n", + file); + break; + default: + DEBUG("flacMetadataDup: Reading '%s' metadata failed\n", + file); } FLAC__metadata_simple_iterator_delete(it); return ret; } - + do { block = FLAC__metadata_simple_iterator_get_block(it); - if(!block) break; - if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + if (!block) + break; + if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { ret = copyVorbisCommentBlockToMpdTag(block, ret); - if(ret) *vorbisCommentFound = 1; - } - else if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { - if(!ret) ret = newMpdTag(); + if (ret) + *vorbisCommentFound = 1; + } 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; + total_samples) / + block->data.stream_info.sample_rate + 0.5; } FLAC__metadata_object_delete(block); - } while(FLAC__metadata_simple_iterator_next(it)); + } while (FLAC__metadata_simple_iterator_next(it)); FLAC__metadata_simple_iterator_delete(it); return ret; } -static MpdTag * flacTagDup(char * file) { - MpdTag * ret = NULL; +static MpdTag *flacTagDup(char *file) +{ + MpdTag *ret = NULL; int foundVorbisComment = 0; ret = flacMetadataDup(file, &foundVorbisComment); - if(!ret) { - DEBUG("flacTagDup: Failed to grab information from: %s\n", file); + if (!ret) { + DEBUG("flacTagDup: Failed to grab information from: %s\n", + file); return NULL; } - if(!foundVorbisComment) { - MpdTag * temp = id3Dup(file); - if(temp) { + if (!foundVorbisComment) { + MpdTag *temp = id3Dup(file); + if (temp) { temp->time = ret->time; freeMpdTag(ret); ret = temp; @@ -393,11 +438,10 @@ static MpdTag * flacTagDup(char * file) { return ret; } -static char * flacSuffixes[] = {"flac", NULL}; -static char * flac_mime_types[] = {"application/x-flac", NULL}; +static char *flacSuffixes[] = { "flac", NULL }; +static char *flac_mime_types[] = { "application/x-flac", NULL }; -InputPlugin flacPlugin = -{ +InputPlugin flacPlugin = { "flac", NULL, NULL, @@ -410,10 +454,9 @@ InputPlugin flacPlugin = flac_mime_types }; -#else /* !HAVE_FLAC */ +#else /* !HAVE_FLAC */ -InputPlugin flacPlugin = -{ +InputPlugin flacPlugin = { NULL, NULL, NULL, @@ -426,4 +469,4 @@ InputPlugin flacPlugin = NULL, }; -#endif /* HAVE_FLAC */ +#endif /* HAVE_FLAC */ |