Commit ad0d350f authored by Laszlo Ashin's avatar Laszlo Ashin Committed by Eric Wong

WavPack improvements

This patch does the following: -enables WVC support for streams as well, -improves MPD inputStream <=> WavPack stream connector, -fixes two compile warnings (which were caused by MPD API change). Mantis #1660 <http://musicpd.org/mantis/view.php?id=1660> git-svn-id: https://svn.musicpd.org/mpd/trunk@7210 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 99468b85
...@@ -52,9 +52,6 @@ static struct { ...@@ -52,9 +52,6 @@ static struct {
{ NULL, 0 } { NULL, 0 }
}; };
/* workaround for at least the last push_back_byte */
static int last_byte = EOF;
/* /*
* This function has been borrowed from the tiny player found on * This function has been borrowed from the tiny player found on
* wavpack.com. Modifications were required because mpd only handles * wavpack.com. Modifications were required because mpd only handles
...@@ -153,7 +150,12 @@ static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc, ...@@ -153,7 +150,12 @@ static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc,
format_samples = format_samples_float; format_samples = format_samples_float;
else else
format_samples = format_samples_int; format_samples = format_samples_int;
/*
if ((WavpackGetMode(wpc) & MODE_WVC) == MODE_WVC)
ERROR("decoding WITH wvc!!!\n");
else
ERROR("decoding without wvc\n");
*/
allsamples = WavpackGetNumSamples(wpc); allsamples = WavpackGetNumSamples(wpc);
Bps = WavpackGetBytesPerSample(wpc); Bps = WavpackGetBytesPerSample(wpc);
...@@ -168,6 +170,7 @@ static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc, ...@@ -168,6 +170,7 @@ static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc,
dc->totalTime = (float)allsamples / dc->audioFormat.sampleRate; dc->totalTime = (float)allsamples / dc->audioFormat.sampleRate;
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
dc->seekable = canseek;
position = 0; position = 0;
...@@ -339,49 +342,57 @@ static MpdTag *wavpack_tagdup(char *fname) ...@@ -339,49 +342,57 @@ static MpdTag *wavpack_tagdup(char *fname)
* mpd InputStream <=> WavpackStreamReader wrapper callbacks * mpd InputStream <=> WavpackStreamReader wrapper callbacks
*/ */
/* This struct is needed for per-stream last_byte storage. */
typedef struct {
InputStream *is;
/* Needed for push_back_byte() */
int last_byte;
} InputStreamPlus;
static int32_t read_bytes(void *id, void *data, int32_t bcount) static int32_t read_bytes(void *id, void *data, int32_t bcount)
{ {
InputStreamPlus *isp = (InputStreamPlus *)id;
uint8_t *buf = (uint8_t *)data; uint8_t *buf = (uint8_t *)data;
int32_t i = 0; int32_t i = 0;
if (last_byte != EOF) { if (isp->last_byte != EOF) {
*buf++ = last_byte; *buf++ = isp->last_byte;
last_byte = EOF; isp->last_byte = EOF;
--bcount; --bcount;
++i; ++i;
} }
return i + readFromInputStream((InputStream *)id, buf, 1, bcount); return i + readFromInputStream(isp->is, buf, 1, bcount);
} }
static uint32_t get_pos(void *id) static uint32_t get_pos(void *id)
{ {
return ((InputStream *)id)->offset; return ((InputStreamPlus *)id)->is->offset;
} }
static int set_pos_abs(void *id, uint32_t pos) static int set_pos_abs(void *id, uint32_t pos)
{ {
return seekInputStream((InputStream *)id, pos, SEEK_SET); return seekInputStream(((InputStreamPlus *)id)->is, pos, SEEK_SET);
} }
static int set_pos_rel(void *id, int32_t delta, int mode) static int set_pos_rel(void *id, int32_t delta, int mode)
{ {
return seekInputStream((InputStream *)id, delta, mode); return seekInputStream(((InputStreamPlus *)id)->is, delta, mode);
} }
static int push_back_byte(void *id, int c) static int push_back_byte(void *id, int c)
{ {
last_byte = c; ((InputStreamPlus *)id)->last_byte = c;
return 1; return 1;
} }
static uint32_t get_length(void *id) static uint32_t get_length(void *id)
{ {
return ((InputStream *)id)->size; return ((InputStreamPlus *)id)->is->size;
} }
static int can_seek(void *id) static int can_seek(void *id)
{ {
return (seekInputStream((InputStream *)id, 0, SEEK_SET) != -1); return ((InputStreamPlus *)id)->is->seekable;
} }
static WavpackStreamReader mpd_is_reader = { static WavpackStreamReader mpd_is_reader = {
...@@ -395,6 +406,13 @@ static WavpackStreamReader mpd_is_reader = { ...@@ -395,6 +406,13 @@ static WavpackStreamReader mpd_is_reader = {
.write_bytes = NULL /* no need to write edited tags */ .write_bytes = NULL /* no need to write edited tags */
}; };
static void
initInputStreamPlus(InputStreamPlus *isp, InputStream *is)
{
isp->is = is;
isp->last_byte = EOF;
}
/* /*
* Tries to decode the specified stream, and gives true if managed to do it. * Tries to decode the specified stream, and gives true if managed to do it.
*/ */
...@@ -402,8 +420,10 @@ static unsigned int wavpack_trydecode(InputStream *is) ...@@ -402,8 +420,10 @@ static unsigned int wavpack_trydecode(InputStream *is)
{ {
char error[ERRORLEN]; char error[ERRORLEN];
WavpackContext *wpc; WavpackContext *wpc;
InputStreamPlus isp;
wpc = WavpackOpenFileInputEx(&mpd_is_reader, (void *)is, NULL, error, initInputStreamPlus(&isp, is);
wpc = WavpackOpenFileInputEx(&mpd_is_reader, &isp, NULL, error,
OPEN_STREAMING, 0); OPEN_STREAMING, 0);
if (wpc == NULL) if (wpc == NULL)
return 0; return 0;
...@@ -417,37 +437,118 @@ static unsigned int wavpack_trydecode(InputStream *is) ...@@ -417,37 +437,118 @@ static unsigned int wavpack_trydecode(InputStream *is)
/* /*
* Decodes a stream. * Decodes a stream.
* We cannot handle wvc files this way, use the wavpack_filedecode for that.
*/ */
static int wavpack_streamdecode(OutputBuffer *cb, DecoderControl *dc, static int wavpack_streamdecode(OutputBuffer *cb, DecoderControl *dc,
InputStream *is) InputStream *is)
{ {
char error[ERRORLEN]; char error[ERRORLEN];
WavpackContext *wpc; 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 */
do {
size_t len;
err = 1;
/*
* As we use dc->utf8url, this function will be bad for
* single files. utf8url is not absolute file path :/
*/
if (dc->utf8url == NULL) {
break;
}
/* len = strlen(dc->utf8url);
* wavpack_streamdecode is unable to use wvc :-( if (!len) {
* If we know the original stream url, we would find out the wvc url... break;
* This would require InputStream to store that. }
*/
wvc_url = (char *)malloc(len + 2); /* +2: 'c' and EOS */
if (wvc_url == NULL) {
break;
}
strncpy(wvc_url, dc->utf8url, len);
wvc_url[len] = 'c';
wvc_url[len + 1] = '\0';
if (openInputStream(&is_wvc, wvc_url)) {
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;
}
if (bufferInputStream(&is_wvc) >= 0) {
err = 0;
break;
}
if (dc->stop) {
break;
}
/* Save some CPU */
my_usleep(1000);
}
if (err) {
closeInputStream(&is_wvc);
break;
}
open_flags |= OPEN_WVC;
} while (0);
canseek = can_seek(&isp);
if (wvc_url != NULL) {
if (err) {
free(wvc_url);
wvc_url = NULL;
} else {
initInputStreamPlus(&isp_wvc, &is_wvc);
}
}
initInputStreamPlus(&isp, is);
wpc = WavpackOpenFileInputEx(&mpd_is_reader, &isp, &isp_wvc, error,
open_flags, 15);
wpc = WavpackOpenFileInputEx(&mpd_is_reader, (void *)is, NULL, error,
OPEN_2CH_MAX | OPEN_NORMALIZE, 15);
if (wpc == NULL) { if (wpc == NULL) {
ERROR("failed to open WavPack stream: %s\n", error); ERROR("failed to open WavPack stream: %s\n", error);
return -1; return -1;
} }
wavpack_decode(cb, dc, wpc, can_seek(is), NULL); wavpack_decode(cb, dc, wpc, canseek, NULL);
WavpackCloseFile(wpc); WavpackCloseFile(wpc);
if (wvc_url != NULL) {
closeInputStream(&is_wvc);
free(wvc_url);
}
closeInputStream(is);
return 0; return 0;
} }
/* /*
* Decodes a file. This has the goods on wavpack_streamdecode that this * Decodes a file.
* can handle wvc files.
*/ */
static int wavpack_filedecode(OutputBuffer *cb, DecoderControl *dc, char *fname) static int wavpack_filedecode(OutputBuffer *cb, DecoderControl *dc, char *fname)
{ {
...@@ -475,8 +576,8 @@ static int wavpack_filedecode(OutputBuffer *cb, DecoderControl *dc, char *fname) ...@@ -475,8 +576,8 @@ static int wavpack_filedecode(OutputBuffer *cb, DecoderControl *dc, char *fname)
return 0; return 0;
} }
static char *wavpackSuffixes[] = { "wv", NULL }; static char const *wavpackSuffixes[] = { "wv", NULL };
static char *wavpackMimeTypes[] = { "audio/x-wavpack", NULL }; static char const *wavpackMimeTypes[] = { "audio/x-wavpack", NULL };
InputPlugin wavpackPlugin = { InputPlugin wavpackPlugin = {
"wavpack", "wavpack",
...@@ -484,7 +585,7 @@ InputPlugin wavpackPlugin = { ...@@ -484,7 +585,7 @@ InputPlugin wavpackPlugin = {
NULL, NULL,
wavpack_trydecode, wavpack_trydecode,
wavpack_streamdecode, wavpack_streamdecode,
wavpack_filedecode, /* provides more functionality! (wvc) */ wavpack_filedecode,
wavpack_tagdup, wavpack_tagdup,
INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL, INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL,
wavpackSuffixes, wavpackSuffixes,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment