aboutsummaryrefslogtreecommitdiffstats
path: root/src/inputPlugins
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/inputPlugins/_flac_common.c8
-rw-r--r--src/inputPlugins/_flac_common.h4
-rw-r--r--src/inputPlugins/_ogg_common.c1
-rw-r--r--src/inputPlugins/aac_plugin.c359
-rw-r--r--src/inputPlugins/audiofile_plugin.c57
-rw-r--r--src/inputPlugins/flac_plugin.c20
-rw-r--r--src/inputPlugins/mod_plugin.c3
-rw-r--r--src/inputPlugins/mp3_plugin.c212
-rw-r--r--src/inputPlugins/mp4_plugin.c21
-rw-r--r--src/inputPlugins/mpc_plugin.c6
-rw-r--r--src/inputPlugins/oggflac_plugin.c29
-rw-r--r--src/inputPlugins/oggvorbis_plugin.c63
-rw-r--r--src/inputPlugins/wavpack_plugin.c144
13 files changed, 509 insertions, 418 deletions
diff --git a/src/inputPlugins/_flac_common.c b/src/inputPlugins/_flac_common.c
index 3401a8b4f..6890c7c50 100644
--- a/src/inputPlugins/_flac_common.c
+++ b/src/inputPlugins/_flac_common.c
@@ -26,12 +26,6 @@
#include "_flac_common.h"
#include "../log.h"
-#include "../tag.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../decode.h"
-#include "../replayGain.h"
-#include "../os_compat.h"
#include <FLAC/format.h>
#include <FLAC/metadata.h>
@@ -180,7 +174,7 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
void flac_error_common_cb(const char *plugin,
const FLAC__StreamDecoderErrorStatus status,
- FlacData * data)
+ mpd_unused FlacData * data)
{
if (dc_intr())
return;
diff --git a/src/inputPlugins/_flac_common.h b/src/inputPlugins/_flac_common.h
index 5c147a064..6fe5bd744 100644
--- a/src/inputPlugins/_flac_common.h
+++ b/src/inputPlugins/_flac_common.h
@@ -26,10 +26,6 @@
#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
-#include "../tag.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../decode.h"
#include <FLAC/export.h>
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# include <FLAC/seekable_stream_decoder.h>
diff --git a/src/inputPlugins/_ogg_common.c b/src/inputPlugins/_ogg_common.c
index d24b2b47b..a7525c2de 100644
--- a/src/inputPlugins/_ogg_common.c
+++ b/src/inputPlugins/_ogg_common.c
@@ -28,7 +28,6 @@
(defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7)
#include "../utils.h"
-#include "../os_compat.h"
ogg_stream_type ogg_stream_type_detect(InputStream * inStream)
{
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index 98329a4b3..512e73e53 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -23,66 +23,65 @@
#define AAC_MAX_CHANNELS 6
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../os_compat.h"
#include <faad.h>
/* all code here is either based on or copied from FAAD2's frontend code */
typedef struct {
InputStream *inStream;
- long bytesIntoBuffer;
- long bytesConsumed;
- long fileOffset;
+ size_t bytesIntoBuffer;
+ size_t bytesConsumed;
+ off_t fileOffset;
unsigned char *buffer;
int atEof;
} AacBuffer;
+static void aac_buffer_shift(AacBuffer * b, size_t length)
+{
+ assert(length >= b->bytesConsumed);
+ assert(length <= b->bytesConsumed + b->bytesIntoBuffer);
+
+ memmove(b->buffer, b->buffer + length,
+ b->bytesConsumed + b->bytesIntoBuffer - length);
+
+ length -= b->bytesConsumed;
+ b->bytesConsumed = 0;
+ b->bytesIntoBuffer -= length;
+}
+
static void fillAacBuffer(AacBuffer * b)
{
- if (b->bytesConsumed > 0) {
- int bread;
+ size_t bread;
- if (b->bytesIntoBuffer) {
- memmove((void *)b->buffer, (void *)(b->buffer +
- b->bytesConsumed),
- b->bytesIntoBuffer);
- }
+ if (b->bytesIntoBuffer >= FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
+ /* buffer already full */
+ return;
- if (!b->atEof) {
- bread = readFromInputStream(b->inStream,
- (void *)(b->buffer +
- b->
- bytesIntoBuffer),
- 1, b->bytesConsumed);
- if (bread != b->bytesConsumed)
- b->atEof = 1;
- b->bytesIntoBuffer += bread;
- }
+ aac_buffer_shift(b, b->bytesConsumed);
- b->bytesConsumed = 0;
+ if (!b->atEof) {
+ size_t rest = FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS -
+ b->bytesIntoBuffer;
- if (b->bytesIntoBuffer > 3) {
- if (memcmp(b->buffer, "TAG", 3) == 0)
- b->bytesIntoBuffer = 0;
- }
- if (b->bytesIntoBuffer > 11) {
- if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) {
- b->bytesIntoBuffer = 0;
- }
- }
- if (b->bytesIntoBuffer > 8) {
- if (memcmp(b->buffer, "APETAGEX", 8) == 0) {
- b->bytesIntoBuffer = 0;
- }
- }
+ bread = readFromInputStream(b->inStream,
+ (void *)(b->buffer +
+ b->
+ bytesIntoBuffer),
+ 1, rest);
+ if (bread == 0 && inputStreamAtEOF(b->inStream))
+ b->atEof = 1;
+ b->bytesIntoBuffer += bread;
}
+
+ if ((b->bytesIntoBuffer > 3 && memcmp(b->buffer, "TAG", 3) == 0) ||
+ (b->bytesIntoBuffer > 11 &&
+ memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) ||
+ (b->bytesIntoBuffer > 8 && memcmp(b->buffer, "APETAGEX", 8) == 0))
+ b->bytesIntoBuffer = 0;
}
-static void advanceAacBuffer(AacBuffer * b, int bytes)
+static void advanceAacBuffer(AacBuffer * b, size_t bytes)
{
b->fileOffset += bytes;
b->bytesConsumed = bytes;
@@ -94,36 +93,76 @@ static int adtsSampleRates[] =
16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
-static int adtsParse(AacBuffer * b, float *length)
+/**
+ * Check whether the buffer head is an AAC frame, and return the frame
+ * length. Returns 0 if it is not a frame.
+ */
+static size_t adts_check_frame(AacBuffer * b)
+{
+ if (b->bytesIntoBuffer <= 7)
+ return 0;
+
+ /* check syncword */
+ if (!((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)))
+ return 0;
+
+ return (((unsigned int)b->buffer[3] & 0x3) << 11) |
+ (((unsigned int)b->buffer[4]) << 3) |
+ (b->buffer[5] >> 5);
+}
+
+/**
+ * Find the next AAC frame in the buffer. Returns 0 if no frame is
+ * found or if not enough data is available.
+ */
+static size_t adts_find_frame(AacBuffer * b)
{
- int frames, frameLength;
- int tFrameLength = 0;
+ const unsigned char *p;
+ size_t frame_length;
+
+ while ((p = memchr(b->buffer, 0xff, b->bytesIntoBuffer)) != NULL) {
+ /* discard data before 0xff */
+ if (p > b->buffer)
+ aac_buffer_shift(b, p - b->buffer);
+
+ if (b->bytesIntoBuffer <= 7)
+ /* not enough data yet */
+ return 0;
+
+ /* is it a frame? */
+ frame_length = adts_check_frame(b);
+ if (frame_length > 0)
+ /* yes, it is */
+ return frame_length;
+
+ /* it's just some random 0xff byte; discard and and
+ continue searching */
+ aac_buffer_shift(b, 1);
+ }
+
+ /* nothing at all; discard the whole buffer */
+ aac_buffer_shift(b, b->bytesIntoBuffer);
+ return 0;
+}
+
+static void adtsParse(AacBuffer * b, float *length)
+{
+ unsigned int frames, frameLength;
int sampleRate = 0;
- float framesPerSec, bytesPerFrame;
+ float framesPerSec;
/* Read all frames to ensure correct time and bitrate */
for (frames = 0;; frames++) {
fillAacBuffer(b);
- if (b->bytesIntoBuffer > 7) {
- /* check syncword */
- if (!((b->buffer[0] == 0xFF) &&
- ((b->buffer[1] & 0xF6) == 0xF0))) {
- break;
- }
-
+ frameLength = adts_find_frame(b);
+ if (frameLength > 0) {
if (frames == 0) {
sampleRate = adtsSampleRates[(b->
buffer[2] & 0x3c)
>> 2];
}
- frameLength = ((((unsigned int)b->buffer[3] & 0x3))
- << 11) | (((unsigned int)b->buffer[4])
- << 3) | (b->buffer[5] >> 5);
-
- tFrameLength += frameLength;
-
if (frameLength > b->bytesIntoBuffer)
break;
@@ -133,46 +172,34 @@ static int adtsParse(AacBuffer * b, float *length)
}
framesPerSec = (float)sampleRate / 1024.0;
- if (frames != 0) {
- bytesPerFrame = (float)tFrameLength / (float)(frames * 1000);
- } else
- bytesPerFrame = 0;
if (framesPerSec != 0)
*length = (float)frames / framesPerSec;
-
- return 1;
}
-static void initAacBuffer(InputStream * inStream, AacBuffer * b, float *length,
- size_t * retFileread, size_t * retTagsize)
+static void initAacBuffer(InputStream * inStream, AacBuffer * b)
{
- size_t fileread;
- size_t bread;
- size_t tagsize;
-
- if (length)
- *length = -1;
-
memset(b, 0, sizeof(AacBuffer));
b->inStream = inStream;
- fileread = inStream->size;
-
b->buffer = xmalloc(FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
memset(b->buffer, 0, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
+}
- bread = readFromInputStream(inStream, b->buffer, 1,
- FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
- b->bytesIntoBuffer = bread;
- b->bytesConsumed = 0;
- b->fileOffset = 0;
+static void aac_parse_header(AacBuffer * b, float *length)
+{
+ size_t fileread;
+ size_t tagsize;
- if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
- b->atEof = 1;
+ if (length)
+ *length = -1;
+
+ fileread = b->inStream->size;
+
+ fillAacBuffer(b);
tagsize = 0;
- if (!memcmp(b->buffer, "ID3", 3)) {
+ if (b->bytesIntoBuffer >= 10 && !memcmp(b->buffer, "ID3", 3)) {
tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) |
(b->buffer[8] << 7) | (b->buffer[9] << 0);
@@ -181,28 +208,19 @@ static void initAacBuffer(InputStream * inStream, AacBuffer * b, float *length,
fillAacBuffer(b);
}
- if (retFileread)
- *retFileread = fileread;
- if (retTagsize)
- *retTagsize = tagsize;
-
if (length == NULL)
return;
- if ((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
+ if (b->bytesIntoBuffer >= 2 &&
+ (b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
adtsParse(b, length);
seekInputStream(b->inStream, tagsize, SEEK_SET);
- bread = readFromInputStream(b->inStream, b->buffer, 1,
- FAAD_MIN_STREAMSIZE *
- AAC_MAX_CHANNELS);
- if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
- b->atEof = 1;
- else
- b->atEof = 0;
- b->bytesIntoBuffer = bread;
+ b->bytesIntoBuffer = 0;
b->bytesConsumed = 0;
b->fileOffset = tagsize;
+
+ fillAacBuffer(b);
} else if (memcmp(b->buffer, "ADIF", 4) == 0) {
int bitRate;
int skipSize = (b->buffer[4] & 0x80) ? 9 : 0;
@@ -231,7 +249,6 @@ static float getAacFloatTotalTime(char *file)
{
AacBuffer b;
float length;
- size_t fileread, tagsize;
faacDecHandle decoder;
faacDecConfigurationPtr config;
uint32_t sampleRate;
@@ -242,7 +259,8 @@ static float getAacFloatTotalTime(char *file)
if (openInputStream(&inStream, file) < 0)
return -1;
- initAacBuffer(&inStream, &b, &length, &fileread, &tagsize);
+ initAacBuffer(&inStream, &b);
+ aac_parse_header(&b, &length);
if (length < 0) {
decoder = faacDecOpen();
@@ -282,6 +300,132 @@ static int getAacTotalTime(char *file)
return file_time;
}
+static int aac_stream_decode(InputStream *inStream)
+{
+ float file_time;
+ float totalTime = 0;
+ faacDecHandle decoder;
+ faacDecFrameInfo frameInfo;
+ faacDecConfigurationPtr config;
+ long bread;
+ uint32_t sampleRate;
+ unsigned char channels;
+ unsigned int sampleCount;
+ char *sampleBuffer;
+ size_t sampleBufferLen;
+ mpd_uint16 bitRate = 0;
+ AacBuffer b;
+
+ initAacBuffer(inStream, &b);
+ aac_parse_header(&b, NULL);
+
+ decoder = faacDecOpen();
+
+ config = faacDecGetCurrentConfiguration(decoder);
+ config->outputFormat = FAAD_FMT_16BIT;
+#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
+ config->downMatrix = 1;
+#endif
+#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
+ config->dontUpSampleImplicitSBR = 0;
+#endif
+ faacDecSetConfiguration(decoder, config);
+
+ while (b.bytesIntoBuffer < FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS &&
+ !b.atEof && !dc_intr()) {
+ fillAacBuffer(&b);
+ adts_find_frame(&b);
+ fillAacBuffer(&b);
+ }
+
+#ifdef HAVE_FAAD_BUFLEN_FUNCS
+ bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
+ &sampleRate, &channels);
+#else
+ bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels);
+#endif
+ if (bread < 0) {
+ ERROR("Error not a AAC stream.\n");
+ faacDecClose(decoder);
+ if (b.buffer)
+ free(b.buffer);
+ return -1;
+ }
+
+ dc.audio_format.bits = 16;
+ dc.total_time = totalTime;
+
+ file_time = 0.0;
+
+ advanceAacBuffer(&b, bread);
+
+ while (1) {
+ fillAacBuffer(&b);
+ adts_find_frame(&b);
+ fillAacBuffer(&b);
+
+ if (b.bytesIntoBuffer == 0)
+ break;
+
+#ifdef HAVE_FAAD_BUFLEN_FUNCS
+ sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer,
+ b.bytesIntoBuffer);
+#else
+ sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer);
+#endif
+
+ if (frameInfo.error > 0) {
+ ERROR("error decoding AAC stream\n");
+ ERROR("faad2 error: %s\n",
+ faacDecGetErrorMessage(frameInfo.error));
+ break;
+ }
+#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
+ sampleRate = frameInfo.samplerate;
+#endif
+
+ dc.audio_format.channels = frameInfo.channels;
+ dc.audio_format.sampleRate = sampleRate;
+
+ advanceAacBuffer(&b, frameInfo.bytesconsumed);
+
+ sampleCount = (unsigned long)(frameInfo.samples);
+
+ if (sampleCount > 0) {
+ bitRate = frameInfo.bytesconsumed * 8.0 *
+ frameInfo.channels * sampleRate /
+ frameInfo.samples / 1000 + 0.5;
+ file_time +=
+ (float)(frameInfo.samples) / frameInfo.channels /
+ sampleRate;
+ }
+
+ sampleBufferLen = sampleCount * 2;
+
+ 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: goto out;
+ }
+ }
+out:
+
+ faacDecClose(decoder);
+ if (b.buffer)
+ free(b.buffer);
+
+ return 0;
+}
+
+
+
static int aac_decode(char *path)
{
float file_time;
@@ -292,7 +436,6 @@ static int aac_decode(char *path)
long bread;
uint32_t sampleRate;
unsigned char channels;
- int eof = 0;
unsigned int sampleCount;
char *sampleBuffer;
size_t sampleBufferLen;
@@ -309,7 +452,8 @@ static int aac_decode(char *path)
if (openInputStream(&inStream, path) < 0)
return -1;
- initAacBuffer(&inStream, &b, NULL, NULL, NULL);
+ initAacBuffer(&inStream, &b);
+ aac_parse_header(&b, NULL);
decoder = faacDecOpen();
@@ -346,13 +490,12 @@ static int aac_decode(char *path)
advanceAacBuffer(&b, bread);
- while (!eof) {
+ while (1) {
fillAacBuffer(&b);
- if (b.bytesIntoBuffer == 0) {
- eof = 1;
+ if (b.bytesIntoBuffer == 0)
break;
- }
+
#ifdef HAVE_FAAD_BUFLEN_FUNCS
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer,
b.bytesIntoBuffer);
@@ -364,7 +507,6 @@ static int aac_decode(char *path)
ERROR("error decoding AAC file: %s\n", path);
ERROR("faad2 error: %s\n",
faacDecGetErrorMessage(frameInfo.error));
- eof = 1;
break;
}
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
@@ -399,9 +541,10 @@ static int aac_decode(char *path)
*/
dc_action_seek_fail(DC_SEEK_ERROR);
break;
- default: eof = 1;
+ default: goto out;
}
}
+out:
faacDecClose(decoder);
if (b.buffer)
@@ -435,10 +578,10 @@ InputPlugin aacPlugin = {
NULL,
NULL,
NULL,
- NULL,
+ aac_stream_decode,
aac_decode,
aacTagDup,
- INPUT_PLUGIN_STREAM_FILE,
+ INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL,
aac_suffixes,
aac_mimeTypes
};
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index 114a87786..fcebf562b 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -22,11 +22,7 @@
#ifdef HAVE_AUDIOFILE
-#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../os_compat.h"
#include <audiofile.h>
@@ -51,6 +47,8 @@ static int audiofile_decode(char *path)
int bits;
mpd_uint16 bitRate;
struct stat st;
+ int ret, current = 0;
+ char chunk[CHUNK_SIZE];
if (stat(path, &st) < 0) {
ERROR("failed to stat: %s\n", path);
@@ -88,34 +86,29 @@ static int audiofile_decode(char *path)
fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
- {
- int ret, eof = 0, current = 0;
- char chunk[CHUNK_SIZE];
-
- while (!eof) {
- if (dc_seek()) {
- dc_action_begin();
- current = dc.seek_where *
- dc.audio_format.sampleRate;
- afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);
- dc_action_end();
- }
-
- ret =
- afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
- CHUNK_SIZE / fs);
- if (ret <= 0)
- eof = 1;
- else {
- current += ret;
- ob_send(chunk, ret * fs,
- (float)current /
- (float)dc.audio_format.sampleRate,
- bitRate,
- NULL);
- if (dc_intr())
- break;
- }
+ while (1) {
+ if (dc_seek()) {
+ dc_action_begin();
+ current = dc.seek_where *
+ dc.audio_format.sampleRate;
+ afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);
+ dc_action_end();
+ }
+
+ ret =
+ afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
+ CHUNK_SIZE / fs);
+ if (ret <= 0)
+ break;
+ else {
+ current += ret;
+ ob_send(chunk, ret * fs,
+ (float)current /
+ (float)dc.audio_format.sampleRate,
+ bitRate,
+ NULL);
+ if (dc_intr())
+ break;
}
}
afCloseFile(af_fp);
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c
index 4a4ac627c..de0648c90 100644
--- a/src/inputPlugins/flac_plugin.c
+++ b/src/inputPlugins/flac_plugin.c
@@ -22,16 +22,10 @@
#include "../utils.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../replayGain.h"
-#include "../audio.h"
-#include "../os_compat.h"
/* this code was based on flac123, from flac-tools */
-static flac_read_status flacRead(const flac_decoder * flacDec,
+static flac_read_status flacRead(mpd_unused const flac_decoder * flacDec,
FLAC__byte buf[],
flac_read_status_size_t *bytes,
void *fdata)
@@ -57,7 +51,7 @@ static flac_read_status flacRead(const flac_decoder * flacDec,
return flac_read_status_continue;
}
-static flac_seek_status flacSeek(const flac_decoder * flacDec,
+static flac_seek_status flacSeek(mpd_unused const flac_decoder * flacDec,
FLAC__uint64 offset,
void *fdata)
{
@@ -70,7 +64,7 @@ static flac_seek_status flacSeek(const flac_decoder * flacDec,
return flac_seek_status_ok;
}
-static flac_tell_status flacTell(const flac_decoder * flacDec,
+static flac_tell_status flacTell(mpd_unused const flac_decoder * flacDec,
FLAC__uint64 * offset,
void *fdata)
{
@@ -81,7 +75,7 @@ static flac_tell_status flacTell(const flac_decoder * flacDec,
return flac_tell_status_ok;
}
-static flac_length_status flacLength(const flac_decoder * flacDec,
+static flac_length_status flacLength(mpd_unused const flac_decoder * flacDec,
FLAC__uint64 * length,
void *fdata)
{
@@ -92,7 +86,7 @@ static flac_length_status flacLength(const flac_decoder * flacDec,
return flac_length_status_ok;
}
-static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata)
+static FLAC__bool flacEOF(mpd_unused const flac_decoder * flacDec, void *fdata)
{
FlacData *data = (FlacData *) fdata;
@@ -101,7 +95,7 @@ static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata)
return false;
}
-static void flacError(const flac_decoder *dec,
+static void flacError(mpd_unused const flac_decoder *dec,
FLAC__StreamDecoderErrorStatus status, void *fdata)
{
flac_error_common_cb("flac", status, (FlacData *) fdata);
@@ -199,7 +193,7 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state)
}
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
-static void flacMetadata(const flac_decoder * dec,
+static void flacMetadata(mpd_unused const flac_decoder * dec,
const FLAC__StreamMetadata * block, void *vdata)
{
flac_metadata_common_cb(block, (FlacData *) vdata);
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index 9f9da6273..df938f0ed 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -21,10 +21,7 @@
#ifdef HAVE_MIKMOD
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../os_compat.h"
#include <mikmod.h>
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index c36cab6f0..f1304f401 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -20,7 +20,6 @@
#ifdef HAVE_MAD
-#include "../pcm_utils.h"
#include <mad.h>
#ifdef HAVE_ID3TAG
@@ -29,23 +28,24 @@
#include "../log.h"
#include "../utils.h"
-#include "../replayGain.h"
-#include "../tag.h"
#include "../conf.h"
-#include "../os_compat.h"
-
#define FRAMES_CUSHION 2000
#define READ_BUFFER_SIZE 40960
-#define DECODE_SKIP -3
-#define DECODE_BREAK -2
-#define DECODE_CONT -1
-#define DECODE_OK 0
+enum mp3_action {
+ DECODE_SKIP = -3,
+ DECODE_BREAK = -2,
+ DECODE_CONT = -1,
+ DECODE_OK = 0
+};
-#define MUTEFRAME_SKIP 1
-#define MUTEFRAME_SEEK 2
+enum muteframe {
+ MUTEFRAME_NONE,
+ MUTEFRAME_SKIP,
+ MUTEFRAME_SEEK
+};
/* the number of samples of silence the decoder inserts at start */
#define DECODERDELAY 529
@@ -65,8 +65,8 @@ static unsigned long prng(unsigned long state)
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
-static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
- struct audio_dither *dither)
+static mpd_sint16 audio_linear_dither(unsigned int bits, mad_fixed_t sample,
+ struct audio_dither *dither)
{
unsigned int scalebits;
mad_fixed_t output, mask, rnd;
@@ -107,7 +107,29 @@ static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
dither->error[0] = sample - output;
- return output >> scalebits;
+ return (mpd_sint16)(output >> scalebits);
+}
+
+static unsigned dither_buffer(mpd_sint16 *dest0, const struct mad_synth *synth,
+ struct audio_dither *dither,
+ unsigned int start, unsigned int end,
+ unsigned int num_channels)
+{
+ mpd_sint16 *dest = dest0;
+ unsigned int i;
+
+ for (i = start; i < end; ++i) {
+ *dest++ = audio_linear_dither(16,
+ synth->pcm.samples[0][i],
+ dither);
+
+ if (num_channels == 2)
+ *dest++ = audio_linear_dither(16,
+ synth->pcm.samples[1][i],
+ dither);
+ }
+
+ return dest - dest0;
}
/* end of stolen stuff from mpg321 */
@@ -123,7 +145,7 @@ static int mp3_plugin_init(void)
/* decoder stuff is based on madlld */
-#define MP3_DATA_OUTPUT_BUFFER_SIZE 4096
+#define MP3_DATA_OUTPUT_BUFFER_SIZE 2048
typedef struct _mp3DecodeData {
struct mad_stream stream;
@@ -131,25 +153,22 @@ typedef struct _mp3DecodeData {
struct mad_synth synth;
mad_timer_t timer;
unsigned char readBuffer[READ_BUFFER_SIZE];
- char outputBuffer[MP3_DATA_OUTPUT_BUFFER_SIZE];
- char *outputPtr;
- char *outputBufferEnd;
+ mpd_sint16 outputBuffer[MP3_DATA_OUTPUT_BUFFER_SIZE];
float totalTime;
float elapsedTime;
- int muteFrame;
+ enum muteframe muteFrame;
long *frameOffset;
mad_timer_t *times;
- long highestFrame;
- long maxFrames;
- long currentFrame;
- int dropFramesAtStart;
- int dropFramesAtEnd;
- int dropSamplesAtStart;
- int dropSamplesAtEnd;
+ unsigned long highestFrame;
+ unsigned long maxFrames;
+ unsigned long currentFrame;
+ unsigned int dropFramesAtStart;
+ unsigned int dropFramesAtEnd;
+ unsigned int dropSamplesAtStart;
+ unsigned int dropSamplesAtEnd;
int foundXing;
int foundFirstFrame;
int decodedFirstFrame;
- int flush;
unsigned long bitRate;
InputStream *inStream;
struct audio_dither dither;
@@ -158,10 +177,7 @@ typedef struct _mp3DecodeData {
static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream)
{
- data->outputPtr = data->outputBuffer;
- data->outputBufferEnd =
- data->outputBuffer + MP3_DATA_OUTPUT_BUFFER_SIZE;
- data->muteFrame = 0;
+ data->muteFrame = MUTEFRAME_NONE;
data->highestFrame = 0;
data->maxFrames = 0;
data->frameOffset = NULL;
@@ -174,7 +190,6 @@ static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream)
data->foundXing = 0;
data->foundFirstFrame = 0;
data->decodedFirstFrame = 0;
- data->flush = 1;
data->inStream = inStream;
data->layer = 0;
memset(&(data->dither), 0, sizeof(struct audio_dither));
@@ -357,8 +372,9 @@ fail:
}
#endif
-static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag,
- ReplayGainInfo ** replayGainInfo)
+static enum mp3_action
+decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag,
+ ReplayGainInfo ** replayGainInfo)
{
enum mad_layer layer;
@@ -400,7 +416,6 @@ static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag,
ERROR("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
- data->flush = 0;
return DECODE_BREAK;
}
}
@@ -421,7 +436,8 @@ static int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag,
return DECODE_OK;
}
-static int decodeNextFrame(mp3DecodeData * data)
+static enum mp3_action
+decodeNextFrame(mp3DecodeData * data)
{
if ((data->stream).buffer == NULL
|| (data->stream).error == MAD_ERROR_BUFLEN) {
@@ -453,7 +469,6 @@ static int decodeNextFrame(mp3DecodeData * data)
ERROR("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
- data->flush = 0;
return DECODE_BREAK;
}
}
@@ -819,7 +834,7 @@ static float frame_time(mp3DecodeData * data, long j)
static void mp3Read_seek(mp3DecodeData * data)
{
- long j = 0;
+ unsigned long j = 0;
data->muteFrame = MUTEFRAME_SEEK;
assert(pthread_equal(pthread_self(), dc.thread));
@@ -829,22 +844,20 @@ static void mp3Read_seek(mp3DecodeData * data)
j++;
if (j < data->highestFrame) {
dc_action_begin();
- if (seekMp3InputBuffer(data, data->frameOffset[j]) < 0) {
+ if (seekMp3InputBuffer(data, data->frameOffset[j]) < 0)
dc.seek_where = DC_SEEK_ERROR;
- } else {
- data->outputPtr = data->outputBuffer;
+ else
data->currentFrame = j;
- }
- data->muteFrame = 0;
+ data->muteFrame = MUTEFRAME_NONE;
dc_action_end();
}
}
-static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
+static enum mp3_action
+mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
{
- int samplesPerFrame;
- int samplesLeft;
- int i;
+ unsigned int pcm_length, max_samples;
+ unsigned int i;
int ret;
int skip;
@@ -877,22 +890,21 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
switch (data->muteFrame) {
case MUTEFRAME_SKIP:
- data->muteFrame = 0;
+ data->muteFrame = MUTEFRAME_NONE;
break;
case MUTEFRAME_SEEK:
if (dc.seek_where <= data->elapsedTime) {
dc_action_begin();
assert(dc.action == DC_ACTION_SEEK);
- data->outputPtr = data->outputBuffer;
- data->muteFrame = 0;
+ data->muteFrame = MUTEFRAME_NONE;
dc_action_end();
}
break;
- default:
+ case MUTEFRAME_NONE:
mad_synth_frame(&data->synth, &data->frame);
if (!data->foundFirstFrame) {
- samplesPerFrame = (data->synth).pcm.length;
+ unsigned int samplesPerFrame = (data->synth).pcm.length;
data->dropFramesAtStart = data->dropSamplesAtStart / samplesPerFrame;
data->dropFramesAtEnd = data->dropSamplesAtEnd / samplesPerFrame;
data->dropSamplesAtStart = data->dropSamplesAtStart % samplesPerFrame;
@@ -924,60 +936,57 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
metadata_pipe_send(tag, data->elapsedTime);
}
- samplesLeft = (data->synth).pcm.length;
+ if (!data->decodedFirstFrame) {
+ i = data->dropSamplesAtStart;
+ data->decodedFirstFrame = 1;
+ } else
+ i = 0;
+
+ pcm_length = data->synth.pcm.length;
+ if (data->dropSamplesAtEnd &&
+ (data->currentFrame == data->maxFrames - data->dropFramesAtEnd)) {
+ if (data->dropSamplesAtEnd >= pcm_length)
+ pcm_length = 0;
+ else
+ pcm_length -= data->dropSamplesAtEnd;
+ }
- for (i = 0; i < (data->synth).pcm.length; i++) {
- mpd_sint16 *sample;
+ max_samples = sizeof(data->outputBuffer) /
+ (2 * MAD_NCHANNELS(&(data->frame).header));
- samplesLeft--;
+ while (i < pcm_length) {
+ enum dc_action action;
+ unsigned int num_samples = pcm_length - i;
- if (!data->decodedFirstFrame &&
- (i < data->dropSamplesAtStart)) {
- continue;
- } else if (data->dropSamplesAtEnd &&
- (data->currentFrame == (data->maxFrames - data->dropFramesAtEnd)) &&
- (samplesLeft < data->dropSamplesAtEnd)) {
- /* stop decoding, effectively dropping
- * all remaining samples */
- return DECODE_BREAK;
- }
+ if (num_samples > max_samples)
+ num_samples = max_samples;
+ i += num_samples;
- sample = (mpd_sint16 *) data->outputPtr;
- *sample = (mpd_sint16) audio_linear_dither(16,
- (data->synth).pcm.samples[0][i],
- &(data->dither));
- data->outputPtr += 2;
-
- if (MAD_NCHANNELS(&(data->frame).header) == 2) {
- sample = (mpd_sint16 *) data->outputPtr;
- *sample = (mpd_sint16) audio_linear_dither(16,
- (data->synth).pcm.samples[1][i],
- &(data->dither));
- data->outputPtr += 2;
- }
+ num_samples = dither_buffer(data->outputBuffer,
+ &data->synth, &data->dither,
+ i - num_samples, i,
+ MAD_NCHANNELS(
+ &(data->frame).header));
- if (data->outputPtr >= data->outputBufferEnd) {
- 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;
+ action = ob_send(data->outputBuffer,
+ 2 * num_samples,
+ data->elapsedTime,
+ data->bitRate / 1000,
+ replayGainInfo ? *replayGainInfo : NULL);
- if (action == DC_ACTION_SEEK)
- break;
- }
+ if (action == DC_ACTION_STOP)
+ return DECODE_BREAK;
+
+ if (action == DC_ACTION_SEEK)
+ break;
}
- data->decodedFirstFrame = 1;
+ if (data->dropSamplesAtEnd &&
+ (data->currentFrame ==
+ (data->maxFrames - data->dropFramesAtEnd)))
+ /* stop decoding, effectively dropping
+ * all remaining samples */
+ return DECODE_BREAK;
if (dc_seek()) {
if (data->inStream->seekable)
@@ -997,7 +1006,7 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
break;
else if (ret == DECODE_SKIP)
skip = 1;
- if (!data->muteFrame) {
+ if (data->muteFrame == MUTEFRAME_NONE) {
while ((ret = decodeNextFrame(data)) == DECODE_CONT &&
!dc_intr() && dc_seek()) ;
if (ret == DECODE_BREAK || dc_intr() || dc_seek())
@@ -1065,11 +1074,6 @@ static int mp3_decode(InputStream * inStream)
metadata_pipe_send(tag, 0);
while (mp3Read(&data, &replayGainInfo) != DECODE_BREAK) ;
- /* 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);
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index bf200c534..8e3d02354 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -21,13 +21,7 @@
#ifdef HAVE_FAAD
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../decode.h"
-#include "../os_compat.h"
#include "../mp4ff/mp4ff.h"
@@ -100,7 +94,6 @@ static int mp4_decode(InputStream * inStream)
unsigned char channels;
long sampleId;
long numSamples;
- int eof = 0;
long dur;
unsigned int sampleCount;
char *sampleBuffer;
@@ -183,7 +176,7 @@ static int mp4_decode(InputStream * inStream)
seekTable = xmalloc(sizeof(float) * numSamples);
- for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) {
+ for (sampleId = 0; sampleId < numSamples; sampleId++) {
if (!seeking && dc_seek()) {
dc_action_begin();
assert(dc.action == DC_ACTION_SEEK);
@@ -229,10 +222,9 @@ static int mp4_decode(InputStream * inStream)
continue;
if (mp4ff_read_sample(mp4fh, track, sampleId, &mp4Buffer,
- &mp4BufferSize) == 0) {
- eof = 1;
- continue;
- }
+ &mp4BufferSize) == 0)
+ break;
+
#ifdef HAVE_FAAD_BUFLEN_FUNCS
sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer,
mp4BufferSize);
@@ -245,7 +237,6 @@ static int mp4_decode(InputStream * inStream)
if (frameInfo.error > 0) {
ERROR("faad2 error: %s\n",
faacDecGetErrorMessage(frameInfo.error));
- eof = 1;
break;
}
@@ -276,10 +267,8 @@ static int mp4_decode(InputStream * inStream)
ob_send(sampleBuffer, sampleBufferLen, file_time,
bitRate, NULL);
- if (dc_intr()) {
- eof = 1;
+ if (dc_intr())
break;
- }
}
free(seekTable);
diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c
index 116e471ff..ea27d1dbf 100644
--- a/src/inputPlugins/mpc_plugin.c
+++ b/src/inputPlugins/mpc_plugin.c
@@ -21,13 +21,7 @@
#ifdef HAVE_MPCDEC
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../replayGain.h"
-#include "../os_compat.h"
#include <mpcdec/mpcdec.h>
diff --git a/src/inputPlugins/oggflac_plugin.c b/src/inputPlugins/oggflac_plugin.c
index 6c5998afe..4b3bb0a6b 100644
--- a/src/inputPlugins/oggflac_plugin.c
+++ b/src/inputPlugins/oggflac_plugin.c
@@ -27,12 +27,6 @@
#include "../utils.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../replayGain.h"
-#include "../audio.h"
-#include "../os_compat.h"
static void oggflac_cleanup(FlacData * data,
OggFLAC__SeekableStreamDecoder * decoder)
@@ -43,7 +37,7 @@ static void oggflac_cleanup(FlacData * data,
OggFLAC__seekable_stream_decoder_delete(decoder);
}
-static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const
+static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(mpd_unused const
OggFLAC__SeekableStreamDecoder
* decoder,
FLAC__byte buf[],
@@ -68,7 +62,7 @@ static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
}
-static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(const
+static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(mpd_unused const
OggFLAC__SeekableStreamDecoder
* decoder,
FLAC__uint64 offset,
@@ -83,7 +77,7 @@ static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(const
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
}
-static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(const
+static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(mpd_unused const
OggFLAC__SeekableStreamDecoder
* decoder,
FLAC__uint64 *
@@ -96,7 +90,7 @@ static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(const
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
}
-static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(const
+static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(mpd_unused const
OggFLAC__SeekableStreamDecoder
* decoder,
FLAC__uint64 *
@@ -110,7 +104,7 @@ static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(const
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
}
-static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
+static FLAC__bool of_EOF_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
void *fdata)
{
FlacData *data = (FlacData *) fdata;
@@ -120,7 +114,7 @@ static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
return false;
}
-static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder,
+static void of_error_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
FLAC__StreamDecoderErrorStatus status, void *fdata)
{
flac_error_common_cb("oggflac", status, (FlacData *) fdata);
@@ -157,7 +151,7 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
}
}
-static FLAC__StreamDecoderWriteStatus oggflacWrite(const
+static FLAC__StreamDecoderWriteStatus oggflacWrite(mpd_unused const
OggFLAC__SeekableStreamDecoder
* decoder,
const FLAC__Frame * frame,
@@ -214,7 +208,7 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(const
}
/* used by TagDup */
-static void of_metadata_dup_cb(const OggFLAC__SeekableStreamDecoder * decoder,
+static void of_metadata_dup_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
const FLAC__StreamMetadata * block, void *vdata)
{
FlacData *data = (FlacData *) vdata;
@@ -235,7 +229,7 @@ static void of_metadata_dup_cb(const OggFLAC__SeekableStreamDecoder * decoder,
}
/* used by decode */
-static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec,
+static void of_metadata_decode_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * dec,
const FLAC__StreamMetadata * block,
void *vdata)
{
@@ -333,6 +327,11 @@ static MpdTag *oggflac_TagDup(char *file)
static unsigned int oggflac_try_decode(InputStream * inStream)
{
+ if (!inStream->seekable)
+ /* we cannot seek after the detection, so don't bother
+ checking */
+ return 1;
+
return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0;
}
diff --git a/src/inputPlugins/oggvorbis_plugin.c b/src/inputPlugins/oggvorbis_plugin.c
index 70a0ce2d3..d14ae2bac 100644
--- a/src/inputPlugins/oggvorbis_plugin.c
+++ b/src/inputPlugins/oggvorbis_plugin.c
@@ -25,13 +25,7 @@
#include "_ogg_common.h"
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../inputStream.h"
-#include "../outputBuffer.h"
-#include "../replayGain.h"
-#include "../os_compat.h"
#ifndef HAVE_TREMOR
#include <vorbis/vorbisfile.h>
@@ -86,7 +80,7 @@ static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence)
}
/* TODO: check Ogg libraries API and see if we can just not have this func */
-static int ogg_close_cb(void *vdata)
+static int ogg_close_cb(mpd_unused void *vdata)
{
return 0;
}
@@ -246,32 +240,32 @@ 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_intr()) {
- switch (ret) {
- case OV_EREAD:
- errorStr = "read error";
- break;
- case OV_ENOTVORBIS:
- errorStr = "not vorbis stream";
- break;
- case OV_EVERSION:
- errorStr = "vorbis version mismatch";
- break;
- case OV_EBADHEADER:
- errorStr = "invalid vorbis header";
- break;
- case OV_EFAULT:
- errorStr = "internal logic error";
- break;
- default:
- errorStr = "unknown error";
- break;
- }
- ERROR("Error decoding Ogg Vorbis stream: %s\n",
- errorStr);
- return -1;
+ if (dc_intr())
+ return 0;
+
+ switch (ret) {
+ case OV_EREAD:
+ errorStr = "read error";
+ break;
+ case OV_ENOTVORBIS:
+ errorStr = "not vorbis stream";
+ break;
+ case OV_EVERSION:
+ errorStr = "vorbis version mismatch";
+ break;
+ case OV_EBADHEADER:
+ errorStr = "invalid vorbis header";
+ break;
+ case OV_EFAULT:
+ errorStr = "internal logic error";
+ break;
+ default:
+ errorStr = "unknown error";
+ break;
}
- return 0;
+
+ ERROR("Error decoding Ogg Vorbis stream: %s\n", errorStr);
+ return -1;
}
dc.total_time = ov_time_total(&vf, -1);
if (dc.total_time < 0)
@@ -368,6 +362,11 @@ static MpdTag *oggvorbis_TagDup(char *file)
static unsigned int oggvorbis_try_decode(InputStream * inStream)
{
+ if (!inStream->seekable)
+ /* we cannot seek after the detection, so don't bother
+ checking */
+ return 1;
+
return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0;
}
diff --git a/src/inputPlugins/wavpack_plugin.c b/src/inputPlugins/wavpack_plugin.c
index 2538be326..c7e024a41 100644
--- a/src/inputPlugins/wavpack_plugin.c
+++ b/src/inputPlugins/wavpack_plugin.c
@@ -23,11 +23,7 @@
#ifdef HAVE_WAVPACK
#include "../utils.h"
-#include "../audio.h"
#include "../log.h"
-#include "../pcm_utils.h"
-#include "../outputBuffer.h"
-#include "../os_compat.h"
#include "../path.h"
#include <wavpack/wavpack.h>
@@ -113,7 +109,8 @@ static void format_samples_int(int Bps, void *buffer, uint32_t samcnt)
/*
* This function converts floating point sample data to 16 bit integer.
*/
-static void format_samples_float(int Bps, void *buffer, uint32_t samcnt)
+static void format_samples_float(mpd_unused int Bps, void *buffer,
+ uint32_t samcnt)
{
int16_t *dst = (int16_t *)buffer;
float *src = (float *)buffer;
@@ -427,86 +424,80 @@ static unsigned int wavpack_trydecode(InputStream *is)
return 1;
}
-/*
- * Decodes a stream.
- */
-static int wavpack_streamdecode(InputStream *is)
+/* wvc being the "correction" file to supplement the original .wv */
+static int wavpack_open_wvc(InputStream *is_wvc)
{
- char error[ERRORLEN];
- WavpackContext *wpc;
- InputStream is_wvc;
- int open_flags = OPEN_2CH_MAX | OPEN_NORMALIZE /*| OPEN_STREAMING*/;
- char *wvc_url = NULL;
- int err;
- InputStreamPlus isp, isp_wvc;
- 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;
+ char wvc_url[MPD_PATH_MAX];
+ size_t len;
- /* This is the only reader of dc.current_song */
- if (!(utf8url = get_song_url(tmp, dc.current_song)))
- break;
+ /* This is the only reader of dc.current_song */
+ if (!get_song_url(wvc_url, dc.current_song))
+ return 0;
- if (!(len = strlen(utf8url)))
- break;
+ len = strlen(wvc_url);
+ if ((len + 2) >= MPD_PATH_MAX)
+ return 0;
- wvc_url = (char *)xmalloc(len + sizeof("c"));
- memcpy(wvc_url, utf8url, len);
- wvc_url[len] = 'c';
- wvc_url[len + 1] = '\0';
+ /* convert the original ".wv" path to a ".wvc" path */
+ assert(wvc_url[len - 3] == '.');
+ assert(wvc_url[len - 2] == 'w' || wvc_url[len - 2] == 'w');
+ assert(wvc_url[len - 1] == 'v' || wvc_url[len - 1] == 'V');
+ assert(wvc_url[len] == '\0');
- if (openInputStream(&is_wvc, wvc_url))
- break;
+ wvc_url[len] = 'c';
+ wvc_url[len + 1] = '\0';
- /*
- * And we try to buffer in order to get know
- * about a possible 404 error.
- */
- for (;;) {
- if (inputStreamAtEOF(&is_wvc)) {
- /*
- * EOF is reached even without
- * a single byte is read...
- * So, this is not good :/
- */
- break;
- }
-
- /* FIXME: replace with future "peek" function */
- if (bufferInputStream(&is_wvc) >= 0) {
- err = 0;
- break;
- }
+ if (openInputStream(is_wvc, wvc_url) < 0) {
+ /* lowercase 'c' didn't work, maybe uppercase... */
+ wvc_url[len] = 'C';
+ if (openInputStream(is_wvc, wvc_url) < 0)
+ return 0;
+ }
- if (dc_intr())
- break;
+ /*
+ * And we try to buffer in order to get know
+ * about a possible 404 error.
+ */
+ for (;;) {
+ if (inputStreamAtEOF(is_wvc))
+ /*
+ * EOF is reached even without
+ * a single byte is read...
+ * So, this is not good :/
+ */
+ break;
- /* Save some CPU */
- my_usleep(1000); /* FIXME: remove */
+ /* FIXME: replace with future "peek" function */
+ if (bufferInputStream(is_wvc) >= 0) {
+ DEBUG("wavpack: got wvc file: %s\n", wvc_url);
+ return 1; /* success */
}
- if (err) {
- closeInputStream(&is_wvc);
+
+ if (dc_intr())
break;
- }
+ /* Save some CPU */
+ my_usleep(1000); /* FIXME: remove */
+ }
- open_flags |= OPEN_WVC;
+ closeInputStream(is_wvc);
+ return 0;
+}
- } while (0);
- canseek = can_seek(&isp);
- if (wvc_url != NULL) {
- if (err) {
- free(wvc_url);
- wvc_url = NULL;
- } else {
- initInputStreamPlus(&isp_wvc, &is_wvc);
- }
+/*
+ * Decodes a stream.
+ */
+static int wavpack_streamdecode(InputStream *is)
+{
+ char error[ERRORLEN];
+ WavpackContext *wpc;
+ InputStream is_wvc;
+ int open_flags = OPEN_2CH_MAX | OPEN_NORMALIZE /*| OPEN_STREAMING*/;
+ InputStreamPlus isp, isp_wvc;
+
+ if (wavpack_open_wvc(&is_wvc)) {
+ initInputStreamPlus(&isp_wvc, &is_wvc);
+ open_flags |= OPEN_WVC;
}
initInputStreamPlus(&isp, is);
@@ -515,17 +506,16 @@ static int wavpack_streamdecode(InputStream *is)
if (wpc == NULL) {
ERROR("failed to open WavPack stream: %s\n", error);
+ if (open_flags & OPEN_WVC)
+ closeInputStream(&is_wvc);
return -1;
}
- wavpack_decode(wpc, canseek, NULL);
+ wavpack_decode(wpc, can_seek(&isp), NULL);
WavpackCloseFile(wpc);
- if (wvc_url != NULL) {
+ if (open_flags & OPEN_WVC)
closeInputStream(&is_wvc);
- free(wvc_url);
- }
- closeInputStream(is);
return 0;
}