From 44d9f62f34e0561d83ea32941f0ea1b529b1490d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Aug 2008 09:28:15 -0700 Subject: core rewrite (decode,player,outputBuffer,playlist) This is a huge refactoring of the core mpd process. The queueing/buffering mechanism is heavily reworked. The player.c code has been merged into outputBuffer (the actual ring buffering logic is handled by ringbuf.c); and decode.c actually handles decoding stuff. The end result is several hundreds of lines shorter, even though we still have a lot of DEBUG statements left in there for tracing and a lot of assertions, too. --- src/inputPlugins/_flac_common.c | 11 ++- src/inputPlugins/_flac_common.h | 16 ++-- src/inputPlugins/aac_plugin.c | 44 ++++------- src/inputPlugins/audiofile_plugin.c | 46 +++++------- src/inputPlugins/flac_plugin.c | 53 ++++++------- src/inputPlugins/mod_plugin.c | 30 +++----- src/inputPlugins/mp3_plugin.c | 146 +++++++++++++++++------------------- src/inputPlugins/mp4_plugin.c | 55 ++++++-------- src/inputPlugins/mpc_plugin.c | 59 ++++++--------- src/inputPlugins/oggflac_plugin.c | 55 +++++++------- src/inputPlugins/oggvorbis_plugin.c | 59 ++++++--------- src/inputPlugins/wavpack_plugin.c | 83 ++++++++------------ 12 files changed, 275 insertions(+), 382 deletions(-) (limited to 'src/inputPlugins') diff --git a/src/inputPlugins/_flac_common.c b/src/inputPlugins/_flac_common.c index cf23a5e8c..3401a8b4f 100644 --- a/src/inputPlugins/_flac_common.c +++ b/src/inputPlugins/_flac_common.c @@ -166,11 +166,10 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, switch (block->type) { case FLAC__METADATA_TYPE_STREAMINFO: - dc.audioFormat.bits = (mpd_sint8)si->bits_per_sample; - dc.audioFormat.sampleRate = si->sample_rate; - dc.audioFormat.channels = (mpd_sint8)si->channels; - dc.totalTime = ((float)si->total_samples) / (si->sample_rate); - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); + dc.audio_format.bits = (mpd_sint8)si->bits_per_sample; + dc.audio_format.sampleRate = si->sample_rate; + dc.audio_format.channels = (mpd_sint8)si->channels; + dc.total_time = ((float)si->total_samples) / (si->sample_rate); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: flacParseReplayGain(block, data); @@ -183,7 +182,7 @@ void flac_error_common_cb(const char *plugin, const FLAC__StreamDecoderErrorStatus status, FlacData * data) { - if (dc.stop) + if (dc_intr()) return; switch (status) { diff --git a/src/inputPlugins/_flac_common.h b/src/inputPlugins/_flac_common.h index 10c2f3d38..5c147a064 100644 --- a/src/inputPlugins/_flac_common.h +++ b/src/inputPlugins/_flac_common.h @@ -165,17 +165,13 @@ MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, MpdTag * tag); /* keep this inlined, this is just macro but prettier :) */ -static inline int flacSendChunk(FlacData * data) +static inline enum dc_action flacSendChunk(FlacData * data) { - if (ob_send(data->inStream, - 1, data->chunk, - data->chunk_length, data->time, - data->bitRate, - data->replayGainInfo) == - OUTPUT_BUFFER_DC_STOP) - return -1; - - return 0; + enum dc_action ret = ob_send(data->chunk, data->chunk_length, + data->time, data->bitRate, + data->replayGainInfo); + data->chunk_length = 0; + return ret; } #endif /* HAVE_FLAC || HAVE_OGGFLAC */ diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c index 6e53c6420..98329a4b3 100644 --- a/src/inputPlugins/aac_plugin.c +++ b/src/inputPlugins/aac_plugin.c @@ -339,9 +339,8 @@ static int aac_decode(char *path) return -1; } - dc.audioFormat.bits = 16; - - dc.totalTime = totalTime; + dc.audio_format.bits = 16; + dc.total_time = totalTime; file_time = 0.0; @@ -372,13 +371,8 @@ static int aac_decode(char *path) sampleRate = frameInfo.samplerate; #endif - if (dc.state != DECODE_STATE_DECODE) { - dc.audioFormat.channels = frameInfo.channels; - dc.audioFormat.sampleRate = sampleRate; - getOutputAudioFormat(&(dc.audioFormat), - &(ob.audioFormat)); - dc.state = DECODE_STATE_DECODE; - } + dc.audio_format.channels = frameInfo.channels; + dc.audio_format.sampleRate = sampleRate; advanceAacBuffer(&b, frameInfo.bytesconsumed); @@ -395,34 +389,24 @@ static int aac_decode(char *path) sampleBufferLen = sampleCount * 2; - ob_send(NULL, 0, sampleBuffer, - sampleBufferLen, file_time, - bitRate, NULL); - if (dc.seek) { - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); - } else if (dc.stop) { - eof = 1; + switch (ob_send(sampleBuffer, sampleBufferLen, + file_time, bitRate, NULL)) { + case DC_ACTION_NONE: break; + case DC_ACTION_SEEK: + /* + * this plugin doesn't support seek because nobody + * has bothered, yet... + */ + dc_action_seek_fail(DC_SEEK_ERROR); break; + default: eof = 1; } } - ob_flush(); - faacDecClose(decoder); if (b.buffer) free(b.buffer); - if (dc.state != DECODE_STATE_DECODE) - return -1; - - if (dc.seek) { - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); - } - return 0; } diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c index 558731dd3..8178972ff 100644 --- a/src/inputPlugins/audiofile_plugin.c +++ b/src/inputPlugins/audiofile_plugin.c @@ -67,42 +67,39 @@ static int audiofile_decode(char *path) afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); - dc.audioFormat.bits = (mpd_uint8)bits; - dc.audioFormat.sampleRate = + dc.audio_format.bits = (mpd_uint8)bits; + dc.audio_format.sampleRate = (unsigned int)afGetRate(af_fp, AF_DEFAULT_TRACK); - dc.audioFormat.channels = + dc.audio_format.channels = (mpd_uint8)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK); - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); - dc.totalTime = - ((float)frame_count / (float)dc.audioFormat.sampleRate); + dc.total_time = ((float)frame_count / + (float)dc.audio_format.sampleRate); - bitRate = (mpd_uint16)(st.st_size * 8.0 / dc.totalTime / 1000.0 + 0.5); + bitRate = (mpd_uint16)(st.st_size * 8.0 / dc.total_time / 1000.0 + 0.5); - if (dc.audioFormat.bits != 8 && dc.audioFormat.bits != 16) { + if (dc.audio_format.bits != 8 && dc.audio_format.bits != 16) { ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n", - path, dc.audioFormat.bits); + path, dc.audio_format.bits); afCloseFile(af_fp); return -1; } fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); - dc.state = DECODE_STATE_DECODE; { int ret, eof = 0, current = 0; char chunk[CHUNK_SIZE]; while (!eof) { - if (dc.seek) { - ob_clear(); - current = dc.seekWhere * - dc.audioFormat.sampleRate; + if (dc_seek()) { + dc_action_begin(); + current = dc.seek_where * + dc.audio_format.sampleRate; afSeekFrame(af_fp, AF_DEFAULT_TRACK, current); - dc.seek = 0; - decoder_wakeup_player(); + dc_action_end(); } ret = @@ -112,20 +109,15 @@ static int audiofile_decode(char *path) eof = 1; else { current += ret; - ob_send(NULL, - 1, - chunk, - ret * fs, - (float)current / - (float)dc.audioFormat. - sampleRate, bitRate, - NULL); - if (dc.stop) + ob_send(chunk, ret * fs, + (float)current / + (float)dc.audio_format.sampleRate, + bitRate, + NULL); + if (dc_intr()) break; } } - - ob_flush(); } afCloseFile(af_fp); diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c index 38131bac9..4a4ac627c 100644 --- a/src/inputPlugins/flac_plugin.c +++ b/src/inputPlugins/flac_plugin.c @@ -41,14 +41,14 @@ static flac_read_status flacRead(const flac_decoder * flacDec, while (1) { r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes); - if (r == 0 && !inputStreamAtEOF(data->inStream) && !dc.stop) - my_usleep(10000); + if (r == 0 && !inputStreamAtEOF(data->inStream) && !dc_intr()) + my_usleep(10000); /* FIXME */ else break; } *bytes = r; - if (r == 0 && !dc.stop) { + if (r == 0 && !dc_intr()) { if (inputStreamAtEOF(data->inStream)) return flac_read_status_eof; else @@ -247,7 +247,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, FLAC__uint32 samples = frame->header.blocksize; unsigned int c_samp; const unsigned int num_channels = frame->header.channels; - const unsigned int bytes_per_sample = (dc.audioFormat.bits / 8); + const unsigned int bytes_per_sample = (dc.audio_format.bits / 8); const unsigned int bytes_per_channel = bytes_per_sample * frame->header.channels; const unsigned int max_samples = FLAC_CHUNK_SIZE / bytes_per_channel; @@ -255,7 +255,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, float timeChange; FLAC__uint64 newPosition = 0; - assert(dc.audioFormat.bits > 0); + assert(dc.audio_format.bits > 0); timeChange = ((float)samples) / frame->header.sample_rate; data->time += timeChange; @@ -286,14 +286,12 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, c_samp, c_samp + num_samples); data->chunk_length = num_samples * bytes_per_channel; - if (flacSendChunk(data) < 0) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - data->chunk_length = 0; - if (dc.seek) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + switch (flacSendChunk(data)) { + case DC_ACTION_STOP: + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + case DC_ACTION_SEEK: + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + default: break; /* compilers are complainers */ } } @@ -419,36 +417,35 @@ static int flac_decode_internal(InputStream * inStream, int is_ogg) } } - 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 (dc_seek()) { + FLAC__uint64 sampleToSeek; + dc_action_begin(); + assert(dc.action == DC_ACTION_SEEK); + sampleToSeek = dc.seek_where * + dc.audio_format.sampleRate + 0.5; if (flac_seek_absolute(flacDec, sampleToSeek)) { - ob_clear(); data.time = ((float)sampleToSeek) / - dc.audioFormat.sampleRate; + dc.audio_format.sampleRate; data.position = 0; - } else - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); + data.chunk_length = 0; + } else { + dc.seek_where = DC_SEEK_ERROR; + } + dc_action_end(); } } - if (!dc.stop) { + if (!dc_intr()) { flacPrintErroredState(flac_get_state(flacDec)); flac_finish(flacDec); } /* send last little bit */ - if (data.chunk_length > 0 && !dc.stop) { + if (data.chunk_length > 0 && !dc_intr()) flacSendChunk(&data); - ob_flush(); - } fail: if (data.replayGainInfo) diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c index 23b16fa23..cfa7d6e3d 100644 --- a/src/inputPlugins/mod_plugin.c +++ b/src/inputPlugins/mod_plugin.c @@ -179,25 +179,20 @@ static int mod_decode(char *path) return -1; } - dc.totalTime = 0; - dc.audioFormat.bits = 16; - dc.audioFormat.sampleRate = 44100; - dc.audioFormat.channels = 2; - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); + dc.total_time = 0; + dc.audio_format.bits = 16; + dc.audio_format.sampleRate = 44100; + dc.audio_format.channels = 2; secPerByte = - 1.0 / ((dc.audioFormat.bits * dc.audioFormat.channels / 8.0) * - (float)dc.audioFormat.sampleRate); + 1.0 / ((dc.audio_format.bits * dc.audio_format.channels / 8.0) * + (float)dc.audio_format.sampleRate); - dc.state = DECODE_STATE_DECODE; while (1) { - if (dc.seek) { - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); - } + if (dc_seek()) + dc_action_seek_fail(DC_SEEK_ERROR); - if (dc.stop) + if (dc_intr()) break; if (!Player_Active()) @@ -205,13 +200,8 @@ static int mod_decode(char *path) ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE); total_time += ret * secPerByte; - ob_send(NULL, 0, - (char *)data->audio_buffer, ret, - total_time, 0, NULL); + ob_send((char *)data->audio_buffer, ret, total_time, 0, NULL); } - - ob_flush(); - mod_close(data); MikMod_Exit(); diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c index dcfc25cdc..10a914a91 100644 --- a/src/inputPlugins/mp3_plugin.c +++ b/src/inputPlugins/mp3_plugin.c @@ -314,10 +314,8 @@ static void mp3_parseId3Tag(mp3DecodeData * data, size_t tagsize, len = readFromInputStream(data->inStream, allocated + count, (size_t) 1, tagsize - count); - if (len <= 0 && inputStreamAtEOF(data->inStream)) { + if (len <= 0 && inputStreamAtEOF(data->inStream)) break; - } else if (len <= 0) - my_usleep(10000); else count += len; } @@ -689,13 +687,13 @@ static int decodeFirstFrame(mp3DecodeData * data, while (1) { while ((ret = decodeNextFrameHeader(data, tag, replayGainInfo)) == DECODE_CONT && - !dc.stop); - if (ret == DECODE_BREAK || dc.stop) return -1; + !dc_intr()); + if (ret == DECODE_BREAK || dc_intr()) return -1; if (ret == DECODE_SKIP) continue; while ((ret = decodeNextFrame(data)) == DECODE_CONT && - !dc.stop); - if (ret == DECODE_BREAK || dc.stop) return -1; + !dc_intr()); + if (ret == DECODE_BREAK || dc_intr()) return -1; if (ret == DECODE_OK) break; } @@ -813,6 +811,35 @@ static int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data, return 0; } +static float frame_time(mp3DecodeData * data, long j) +{ + return (((float)mad_timer_count(data->times[j], + MAD_UNITS_MILLISECONDS)) / 1000); +} + +static void mp3Read_seek(mp3DecodeData * data) +{ + long j = 0; + data->muteFrame = MUTEFRAME_SEEK; + + assert(pthread_equal(pthread_self(), dc.thread)); + assert(dc.action == DC_ACTION_SEEK); + + while (j < data->highestFrame && dc.seek_where > frame_time(data, j)) + j++; + if (j < data->highestFrame) { + dc_action_begin(); + if (seekMp3InputBuffer(data, data->frameOffset[j]) < 0) { + dc.seek_where = DC_SEEK_ERROR; + } else { + data->outputPtr = data->outputBuffer; + data->currentFrame = j; + } + data->muteFrame = 0; + dc_action_end(); + } +} + static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo) { int samplesPerFrame; @@ -821,6 +848,8 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo) int ret; int skip; + assert(pthread_equal(pthread_self(), dc.thread)); + if (data->currentFrame >= data->highestFrame) { mad_timer_add(&data->timer, (data->frame).header.duration); data->bitRate = (data->frame).header.bitrate; @@ -851,13 +880,13 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo) data->muteFrame = 0; break; case MUTEFRAME_SEEK: - if (dc.seekWhere <= data->elapsedTime) { + dc_action_begin(); + assert(dc.action == DC_ACTION_SEEK); + if (dc.seek_where <= data->elapsedTime) { data->outputPtr = data->outputBuffer; - ob_clear(); data->muteFrame = 0; - dc.seek = 0; - decoder_wakeup_player(); } + dc_action_end(); break; default: mad_synth_frame(&data->synth, &data->frame); @@ -928,53 +957,33 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo) } if (data->outputPtr >= data->outputBufferEnd) { - ret = ob_send(data->inStream, - data->inStream->seekable, - data->outputBuffer, - data->outputPtr - data->outputBuffer, - data->elapsedTime, - data->bitRate / 1000, - (replayGainInfo != NULL) ? *replayGainInfo : NULL); - if (ret == OUTPUT_BUFFER_DC_STOP) { + enum dc_action action = ob_send( + data->outputBuffer, + data->outputPtr - + data->outputBuffer, + data->elapsedTime, + data->bitRate / 1000, + replayGainInfo ? *replayGainInfo + : NULL); + + if (action == DC_ACTION_STOP) { data->flush = 0; return DECODE_BREAK; } - data->outputPtr = data->outputBuffer; - if (ret == OUTPUT_BUFFER_DC_SEEK) + if (action == DC_ACTION_SEEK) break; } } data->decodedFirstFrame = 1; - if (dc.seek && data->inStream->seekable) { - long j = 0; - data->muteFrame = MUTEFRAME_SEEK; - while (j < data->highestFrame && dc.seekWhere > - ((float)mad_timer_count(data->times[j], - MAD_UNITS_MILLISECONDS)) - / 1000) { - j++; - } - if (j < data->highestFrame) { - if (seekMp3InputBuffer(data, - data->frameOffset[j]) == - 0) { - data->outputPtr = data->outputBuffer; - ob_clear(); - data->currentFrame = j; - } else - dc.seekError = 1; - data->muteFrame = 0; - dc.seek = 0; - decoder_wakeup_player(); - } - } else if (dc.seek && !data->inStream->seekable) { - dc.seek = 0; - dc.seekError = 1; - decoder_wakeup_player(); + if (dc_seek()) { + if (data->inStream->seekable) + mp3Read_seek(data); + else + dc_action_seek_fail(DC_SEEK_ERROR); } } @@ -983,22 +992,22 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo) while ((ret = decodeNextFrameHeader(data, NULL, replayGainInfo)) == DECODE_CONT - && !dc.stop) ; - if (ret == DECODE_BREAK || dc.stop || dc.seek) + && dc_intr()) ; + if (ret == DECODE_BREAK || dc_intr() || dc_seek()) break; else if (ret == DECODE_SKIP) skip = 1; if (!data->muteFrame) { while ((ret = decodeNextFrame(data)) == DECODE_CONT && - !dc.stop && !dc.seek) ; - if (ret == DECODE_BREAK || dc.stop || dc.seek) + !dc_intr() && dc_seek()) ; + if (ret == DECODE_BREAK || dc_intr() || dc_seek()) break; } if (!skip && ret == DECODE_OK) break; } - if (dc.stop) + if (dc_intr()) return DECODE_BREAK; return ret; @@ -1018,9 +1027,8 @@ static int mp3_decode(InputStream * inStream) MpdTag *tag = NULL; ReplayGainInfo *replayGainInfo = NULL; - if (openMp3FromInputStream(inStream, &data, &tag, &replayGainInfo) < - 0) { - if (!dc.stop) { + if (openMp3FromInputStream(inStream, &data, &tag, &replayGainInfo) < 0) { + if (!dc_intr()) { ERROR ("Input does not appear to be a mp3 bit stream.\n"); return -1; @@ -1028,10 +1036,9 @@ static int mp3_decode(InputStream * inStream) return 0; } - initAudioFormatFromMp3DecodeData(&data, &(dc.audioFormat)); - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); + initAudioFormatFromMp3DecodeData(&data, &(dc.audio_format)); - dc.totalTime = data.totalTime; + dc.total_time = data.totalTime; if (inStream->metaTitle) { if (tag) @@ -1058,31 +1065,16 @@ static int mp3_decode(InputStream * inStream) freeMpdTag(tag); } - dc.state = DECODE_STATE_DECODE; - while (mp3Read(&data, &replayGainInfo) != DECODE_BREAK) ; - /* send last little bit if not dc.stop */ - if (!dc.stop && data.outputPtr != data.outputBuffer && data.flush) { - ob_send(NULL, - data.inStream->seekable, - data.outputBuffer, - data.outputPtr - data.outputBuffer, - data.elapsedTime, data.bitRate / 1000, - replayGainInfo); + /* send last little bit if not dc_intr() */ + if (!dc_intr() && data.outputPtr != data.outputBuffer && data.flush) { + ob_send(data.outputBuffer, data.outputPtr - data.outputBuffer, + data.elapsedTime, data.bitRate / 1000, replayGainInfo); } if (replayGainInfo) freeReplayGainInfo(replayGainInfo); - - if (dc.seek && data.muteFrame == MUTEFRAME_SEEK) { - ob_clear(); - dc.seek = 0; - decoder_wakeup_player(); - } - - ob_flush(); mp3DecodeDataFinalize(&data); - return 0; } diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c index 7f13ca344..bf200c534 100644 --- a/src/inputPlugins/mp4_plugin.c +++ b/src/inputPlugins/mp4_plugin.c @@ -145,7 +145,7 @@ static int mp4_decode(InputStream * inStream) #endif faacDecSetConfiguration(decoder, config); - dc.audioFormat.bits = 16; + dc.audio_format.bits = 16; mp4Buffer = NULL; mp4BufferSize = 0; @@ -160,8 +160,8 @@ static int mp4_decode(InputStream * inStream) return -1; } - dc.audioFormat.sampleRate = sampleRate; - dc.audioFormat.channels = channels; + dc.audio_format.sampleRate = sampleRate; + dc.audio_format.channels = channels; file_time = mp4ff_get_track_duration_use_offsets(mp4fh, track); scale = mp4ff_time_scale(mp4fh, track); @@ -175,7 +175,7 @@ static int mp4_decode(InputStream * inStream) free(mp4cb); return -1; } - dc.totalTime = ((float)file_time) / scale; + dc.total_time = ((float)file_time) / scale; numSamples = mp4ff_num_samples(mp4fh, track); @@ -184,13 +184,16 @@ static int mp4_decode(InputStream * inStream) seekTable = xmalloc(sizeof(float) * numSamples); for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) { - if (dc.seek) + if (!seeking && dc_seek()) { + dc_action_begin(); + assert(dc.action == DC_ACTION_SEEK); seeking = 1; + } if (seeking && seekTableEnd > 1 && - seekTable[seekTableEnd] >= dc.seekWhere) { + seekTable[seekTableEnd] >= dc.seek_where) { int i = 2; - while (seekTable[i] < dc.seekWhere) + while (seekTable[i] < dc.seek_where) i++; sampleId = i - 1; file_time = seekTable[sampleId]; @@ -212,15 +215,14 @@ static int mp4_decode(InputStream * inStream) dur -= offset; file_time += ((float)dur) / scale; - if (seeking && file_time > dc.seekWhere) + if (seeking && file_time > dc.seek_where) seekPositionFound = 1; if (seeking && seekPositionFound) { seekPositionFound = 0; - ob_clear(); seeking = 0; - dc.seek = 0; - decoder_wakeup_player(); + assert(dc.action == DC_ACTION_SEEK); + dc_action_end(); } if (seeking) @@ -247,17 +249,12 @@ static int mp4_decode(InputStream * inStream) break; } - if (dc.state != DECODE_STATE_DECODE) { - channels = frameInfo.channels; + channels = frameInfo.channels; #ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE - scale = frameInfo.samplerate; + scale = frameInfo.samplerate; #endif - dc.audioFormat.sampleRate = scale; - dc.audioFormat.channels = frameInfo.channels; - getOutputAudioFormat(&(dc.audioFormat), - &(ob.audioFormat)); - dc.state = DECODE_STATE_DECODE; - } + dc.audio_format.sampleRate = scale; + dc.audio_format.channels = frameInfo.channels; if (channels * (unsigned long)(dur + offset) > frameInfo.samples) { dur = frameInfo.samples / channels; @@ -277,10 +274,9 @@ static int mp4_decode(InputStream * inStream) sampleBuffer += offset * channels * 2; - ob_send(inStream, 1, sampleBuffer, - sampleBufferLen, file_time, - bitRate, NULL); - if (dc.stop) { + ob_send(sampleBuffer, sampleBufferLen, file_time, + bitRate, NULL); + if (dc_intr()) { eof = 1; break; } @@ -291,15 +287,10 @@ static int mp4_decode(InputStream * inStream) mp4ff_close(mp4fh); free(mp4cb); - if (dc.state != DECODE_STATE_DECODE) - return -1; - - if (dc.seek && seeking) { - ob_clear(); - dc.seek = 0; - decoder_wakeup_player(); + if (seeking) { + dc.seek_where = DC_SEEK_ERROR; + dc_action_end(); } - ob_flush(); return 0; } diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c index 1003f15d5..116e471ff 100644 --- a/src/inputPlugins/mpc_plugin.c +++ b/src/inputPlugins/mpc_plugin.c @@ -42,8 +42,8 @@ static mpc_int32_t mpc_read_cb(void *vdata, void *ptr, mpc_int32_t size) while (1) { ret = readFromInputStream(data->inStream, ptr, 1, size); - if (ret == 0 && !inputStreamAtEOF(data->inStream) && !dc.stop) - my_usleep(10000); + if (ret == 0 && !inputStreamAtEOF(data->inStream) && !dc_intr()) + my_usleep(10000); /* FIXME */ else break; } @@ -147,7 +147,7 @@ static int mpc_decode(InputStream * inStream) mpc_streaminfo_init(&info); if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) { - if (!dc.stop) { + if (!dc_intr()) { ERROR("Not a valid musepack stream\n"); return -1; } @@ -157,20 +157,18 @@ static int mpc_decode(InputStream * inStream) mpc_decoder_setup(&decoder, &reader); if (!mpc_decoder_initialize(&decoder, &info)) { - if (!dc.stop) { + if (!dc_intr()) { ERROR("Not a valid musepack stream\n"); return -1; } return 0; } - dc.totalTime = mpc_streaminfo_get_length(&info); + dc.total_time = mpc_streaminfo_get_length(&info); - dc.audioFormat.bits = 16; - dc.audioFormat.channels = info.channels; - dc.audioFormat.sampleRate = info.sample_freq; - - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); + dc.audio_format.bits = 16; + dc.audio_format.channels = info.channels; + dc.audio_format.sampleRate = info.sample_freq; replayGainInfo = newReplayGainInfo(); replayGainInfo->albumGain = info.gain_album * 0.01; @@ -178,19 +176,16 @@ static int mpc_decode(InputStream * inStream) replayGainInfo->trackGain = info.gain_title * 0.01; replayGainInfo->trackPeak = info.peak_title / 32767.0; - dc.state = DECODE_STATE_DECODE; - while (!eof) { - if (dc.seek) { - samplePos = dc.seekWhere * dc.audioFormat.sampleRate; + if (dc_seek()) { + dc_action_begin(); + samplePos = dc.seek_where * dc.audio_format.sampleRate; if (mpc_decoder_seek_sample(&decoder, samplePos)) { - ob_clear(); s16 = (mpd_sint16 *) chunk; chunkpos = 0; } else - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); + dc.seek_where = DC_SEEK_ERROR; + dc_action_end(); } vbrUpdateAcc = 0; @@ -198,7 +193,7 @@ static int mpc_decode(InputStream * inStream) ret = mpc_decoder_decode(&decoder, sample_buffer, &vbrUpdateAcc, &vbrUpdateBits); - if (ret <= 0 || dc.stop) { + if (ret <= 0 || dc_intr()) { eof = 1; break; } @@ -216,20 +211,17 @@ static int mpc_decode(InputStream * inStream) if (chunkpos >= MPC_CHUNK_SIZE) { total_time = ((float)samplePos) / - dc.audioFormat.sampleRate; + dc.audio_format.sampleRate; bitRate = vbrUpdateBits * - dc.audioFormat.sampleRate / 1152 / 1000; + dc.audio_format.sampleRate / 1152 / 1000; - ob_send(inStream, - inStream->seekable, - chunk, chunkpos, - total_time, - bitRate, replayGainInfo); + ob_send(chunk, chunkpos, total_time, + bitRate, replayGainInfo); chunkpos = 0; s16 = (mpd_sint16 *) chunk; - if (dc.stop) { + if (dc_intr()) { eof = 1; break; } @@ -237,19 +229,14 @@ static int mpc_decode(InputStream * inStream) } } - if (!dc.stop && chunkpos > 0) { - total_time = ((float)samplePos) / dc.audioFormat.sampleRate; + if (!dc_intr() && chunkpos > 0) { + total_time = ((float)samplePos) / dc.audio_format.sampleRate; bitRate = - vbrUpdateBits * dc.audioFormat.sampleRate / 1152 / 1000; + vbrUpdateBits * dc.audio_format.sampleRate / 1152 / 1000; - ob_send(NULL, inStream->seekable, - chunk, chunkpos, total_time, bitRate, - replayGainInfo); + ob_send(chunk, chunkpos, total_time, bitRate, replayGainInfo); } - - ob_flush(); - freeReplayGainInfo(replayGainInfo); return 0; diff --git a/src/inputPlugins/oggflac_plugin.c b/src/inputPlugins/oggflac_plugin.c index 379ff6466..6c5998afe 100644 --- a/src/inputPlugins/oggflac_plugin.c +++ b/src/inputPlugins/oggflac_plugin.c @@ -55,15 +55,14 @@ static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const while (1) { r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes); - if (r == 0 && !inputStreamAtEOF(data->inStream) && - !dc.stop) - my_usleep(10000); + if (r == 0 && !inputStreamAtEOF(data->inStream) && !dc_intr()) + my_usleep(10000); /* FIXME */ else break; } *bytes = r; - if (r == 0 && !inputStreamAtEOF(data->inStream) && !dc.stop) + if (r == 0 && !inputStreamAtEOF(data->inStream) && !dc_intr()) return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; @@ -193,16 +192,17 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(const c_chan++) { u16 = buf[c_chan][c_samp]; uc = (unsigned char *)&u16; - for (i = 0; i < (dc.audioFormat.bits / 8); i++) { + for (i = 0; i < (dc.audio_format.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 (dc.seek) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + /* FIXME: line wrapping */ + switch (flacSendChunk(data)) { + case DC_ACTION_STOP: + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + case DC_ACTION_SEEK: + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + default: + /* compilers are complainers */ + break; } } data->chunk[data->chunk_length++] = *(uc++); @@ -349,40 +349,39 @@ static int oggflac_decode(InputStream * inStream) goto fail; } - dc.state = DECODE_STATE_DECODE; - while (1) { OggFLAC__seekable_stream_decoder_process_single(decoder); if (OggFLAC__seekable_stream_decoder_get_state(decoder) != OggFLAC__SEEKABLE_STREAM_DECODER_OK) { break; } - if (dc.seek) { - FLAC__uint64 sampleToSeek = dc.seekWhere * - dc.audioFormat.sampleRate + 0.5; + if (dc_seek()) { + FLAC__uint64 sampleToSeek; + dc_action_begin(); + assert(dc.action == DC_ACTION_SEEK); + sampleToSeek = dc.seek_where * + dc.audio_format.sampleRate + 0.5; if (OggFLAC__seekable_stream_decoder_seek_absolute (decoder, sampleToSeek)) { - ob_clear(); data.time = ((float)sampleToSeek) / - dc.audioFormat.sampleRate; + dc.audio_format.sampleRate; data.position = 0; - } else - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); + data.chunk_length = 0; + } else { + dc.seek_where = DC_SEEK_ERROR; + } + dc_action_end(); } } - if (!dc.stop) { + if (!dc_intr()) { oggflacPrintErroredState (OggFLAC__seekable_stream_decoder_get_state(decoder)); OggFLAC__seekable_stream_decoder_finish(decoder); } /* send last little bit */ - if (data.chunk_length > 0 && !dc.stop) { + if (data.chunk_length > 0 && !dc_intr()) flacSendChunk(&data); - ob_flush(); - } fail: oggflac_cleanup(&data, decoder); diff --git a/src/inputPlugins/oggvorbis_plugin.c b/src/inputPlugins/oggvorbis_plugin.c index 16040b388..fcedda54a 100644 --- a/src/inputPlugins/oggvorbis_plugin.c +++ b/src/inputPlugins/oggvorbis_plugin.c @@ -66,8 +66,8 @@ static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata) while (1) { ret = readFromInputStream(data->inStream, ptr, size, nmemb); if (ret == 0 && !inputStreamAtEOF(data->inStream) && - !dc.stop) { - my_usleep(10000); + !dc_intr()) { + my_usleep(10000); /* FIXME */ } else break; } @@ -80,7 +80,7 @@ static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata) static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence) { const OggCallbackData *data = (const OggCallbackData *) vdata; - if (dc.stop) + if (dc_intr()) return -1; return seekInputStream(data->inStream, offset, whence); } @@ -240,7 +240,7 @@ static int oggvorbis_decode(InputStream * inStream) callbacks.close_func = ogg_close_cb; callbacks.tell_func = ogg_tell_cb; if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) { - if (!dc.stop) { + if (!dc_intr()) { switch (ret) { case OV_EREAD: errorStr = "read error"; @@ -267,20 +267,19 @@ static int oggvorbis_decode(InputStream * inStream) } return 0; } - dc.totalTime = ov_time_total(&vf, -1); - if (dc.totalTime < 0) - dc.totalTime = 0; - dc.audioFormat.bits = 16; + dc.total_time = ov_time_total(&vf, -1); + if (dc.total_time < 0) + dc.total_time = 0; + dc.audio_format.bits = 16; while (1) { - if (dc.seek) { - if (0 == ov_time_seek_page(&vf, dc.seekWhere)) { - ob_clear(); + if (dc_seek()) { + dc_action_begin(); + if (0 == ov_time_seek_page(&vf, dc.seek_where)) chunkpos = 0; - } else - dc.seekError = 1; - dc.seek = 0; - decoder_wakeup_player(); + else + dc.seek_where = DC_SEEK_ERROR; + dc_action_end(); } ret = ov_read(&vf, chunk + chunkpos, OGG_CHUNK_SIZE - chunkpos, @@ -288,13 +287,8 @@ static int oggvorbis_decode(InputStream * inStream) if (current_section != prev_section) { /*printf("new song!\n"); */ vorbis_info *vi = ov_info(&vf, -1); - dc.audioFormat.channels = vi->channels; - dc.audioFormat.sampleRate = vi->rate; - if (dc.state == DECODE_STATE_START) { - getOutputAudioFormat(&(dc.audioFormat), - &(ob.audioFormat)); - dc.state = DECODE_STATE_DECODE; - } + dc.audio_format.channels = vi->channels; + dc.audio_format.sampleRate = vi->rate; comments = ov_comment(&vf, -1)->user_comments; putOggCommentsIntoOutputBuffer(inStream->metaName, comments); @@ -316,23 +310,18 @@ static int oggvorbis_decode(InputStream * inStream) if ((test = ov_bitrate_instant(&vf)) > 0) { bitRate = test / 1000; } - ob_send(inStream, - inStream->seekable, - chunk, chunkpos, - ov_pcm_tell(&vf) / - dc.audioFormat.sampleRate, - bitRate, replayGainInfo); + ob_send(chunk, chunkpos, + ov_pcm_tell(&vf) / dc.audio_format.sampleRate, + bitRate, replayGainInfo); chunkpos = 0; - if (dc.stop) + if (dc_intr()) break; } } - if (!dc.stop && chunkpos > 0) { - ob_send(NULL, inStream->seekable, - chunk, chunkpos, - ov_time_tell(&vf), bitRate, - replayGainInfo); + if (!dc_intr() && chunkpos > 0) { + ob_send(chunk, chunkpos, ov_time_tell(&vf), bitRate, + replayGainInfo); } if (replayGainInfo) @@ -340,8 +329,6 @@ static int oggvorbis_decode(InputStream * inStream) ov_clear(&vf); - ob_flush(); - return 0; } diff --git a/src/inputPlugins/wavpack_plugin.c b/src/inputPlugins/wavpack_plugin.c index 7a7145141..ef02712d7 100644 --- a/src/inputPlugins/wavpack_plugin.c +++ b/src/inputPlugins/wavpack_plugin.c @@ -139,12 +139,12 @@ static void wavpack_decode(WavpackContext *wpc, int canseek, int position, outsamplesize; int Bps; - dc.audioFormat.sampleRate = WavpackGetSampleRate(wpc); - dc.audioFormat.channels = WavpackGetReducedChannels(wpc); - dc.audioFormat.bits = WavpackGetBitsPerSample(wpc); + dc.audio_format.sampleRate = WavpackGetSampleRate(wpc); + dc.audio_format.channels = WavpackGetReducedChannels(wpc); + dc.audio_format.bits = WavpackGetBitsPerSample(wpc); - if (dc.audioFormat.bits > 16) - dc.audioFormat.bits = 16; + if (dc.audio_format.bits > 16) + dc.audio_format.bits = 16; if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) format_samples = format_samples_float; @@ -162,40 +162,33 @@ static void wavpack_decode(WavpackContext *wpc, int canseek, outsamplesize = Bps; if (outsamplesize > 2) outsamplesize = 2; - outsamplesize *= dc.audioFormat.channels; + outsamplesize *= dc.audio_format.channels; - samplesreq = sizeof(chunk) / (4 * dc.audioFormat.channels); + samplesreq = sizeof(chunk) / (4 * dc.audio_format.channels); - getOutputAudioFormat(&(dc.audioFormat), &(ob.audioFormat)); - - dc.totalTime = (float)allsamples / dc.audioFormat.sampleRate; - dc.state = DECODE_STATE_DECODE; - dc.seekable = canseek; + dc.total_time = (float)allsamples / dc.audio_format.sampleRate; position = 0; do { - if (dc.seek) { + if (dc_seek()) { + dc_action_begin(); + assert(dc.action == DC_ACTION_SEEK); if (canseek) { int where; - - ob_clear(); - - where = dc.seekWhere * - dc.audioFormat.sampleRate; + where = dc.seek_where * + dc.audio_format.sampleRate; if (WavpackSeekSample(wpc, where)) position = where; else - dc.seekError = 1; + dc.seek_where = DC_SEEK_ERROR; } else { - dc.seekError = 1; + dc.seek_where = DC_SEEK_ERROR; } - - dc.seek = 0; - decoder_wakeup_player(); + dc_action_end(); } - if (dc.stop) + if (dc_intr()) break; samplesgot = WavpackUnpackSamples(wpc, @@ -205,19 +198,15 @@ static void wavpack_decode(WavpackContext *wpc, int canseek, 1000 + 0.5); position += samplesgot; file_time = (float)position / - dc.audioFormat.sampleRate; + dc.audio_format.sampleRate; format_samples(Bps, chunk, - samplesgot * dc.audioFormat.channels); + samplesgot * dc.audio_format.channels); - ob_send(NULL, 0, chunk, - samplesgot * outsamplesize, - file_time, bitrate, - replayGainInfo); + ob_send(chunk, samplesgot * outsamplesize, + file_time, bitrate, replayGainInfo); } } while (samplesgot == samplesreq); - - ob_flush(); } static char *wavpack_tag(WavpackContext *wpc, char *key) @@ -398,6 +387,7 @@ static int can_seek(void *id) return ((InputStreamPlus *)id)->is->seekable; } +/* FIXME: remove C99 initializers */ static WavpackStreamReader mpd_is_reader = { .read_bytes = read_bytes, .get_pos = get_pos, @@ -453,38 +443,27 @@ static int wavpack_streamdecode(InputStream *is) int canseek; /* Try to find wvc */ + /* wvc being the "correction" file to supplement the original .wv */ do { char tmp[MPD_PATH_MAX]; const char *utf8url; size_t len; err = 1; - /* - * As we use dc.utf8url, this function will be bad for - * single files. utf8url is not absolute file path :/ - */ - utf8url = get_song_url(tmp, dc.current_song); - if (utf8url == NULL) { - break; - } - - len = strlen(utf8url); - if (!len) { + /* This is the only reader of dc.current_song */ + if (!(utf8url = get_song_url(tmp, dc.current_song))) break; - } - wvc_url = (char *)xmalloc(len + 2); /* +2: 'c' and EOS */ - if (wvc_url == NULL) { + if (!(len = strlen(utf8url))) break; - } + wvc_url = (char *)xmalloc(len + sizeof("c")); memcpy(wvc_url, utf8url, len); wvc_url[len] = 'c'; wvc_url[len + 1] = '\0'; - if (openInputStream(&is_wvc, wvc_url)) { + if (openInputStream(&is_wvc, wvc_url)) break; - } /* * And we try to buffer in order to get know @@ -500,17 +479,17 @@ static int wavpack_streamdecode(InputStream *is) break; } + /* FIXME: replace with future "peek" function */ if (bufferInputStream(&is_wvc) >= 0) { err = 0; break; } - if (dc.stop) { + if (dc_intr()) break; - } /* Save some CPU */ - my_usleep(1000); + my_usleep(1000); /* FIXME: remove */ } if (err) { closeInputStream(&is_wvc); -- cgit v1.2.3