Adding WavPack support. Patch courtesy Kodest.
git-svn-id: https://svn.musicpd.org/mpd/trunk@6651 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
df32eed2cc
commit
db47ab163a
3
AUTHORS
3
AUTHORS
|
@ -24,6 +24,9 @@ Qball Cow <qballcow@gmail.com>
|
||||||
Patrik Weiskircher <pat@icore.at>
|
Patrik Weiskircher <pat@icore.at>
|
||||||
Stored playlist commands
|
Stored playlist commands
|
||||||
|
|
||||||
|
Kodest <kodest at gmail dot com>
|
||||||
|
WavPack support
|
||||||
|
|
||||||
Former Developers
|
Former Developers
|
||||||
-----------------
|
-----------------
|
||||||
tw-nym
|
tw-nym
|
||||||
|
|
|
@ -9,6 +9,7 @@ ver 0.14.0 (????/??/??)
|
||||||
* Make the shout output block while trying to connect instead of failing
|
* Make the shout output block while trying to connect instead of failing
|
||||||
* New timeout parameter for shout outputs to define a connection timeout
|
* New timeout parameter for shout outputs to define a connection timeout
|
||||||
* New FIFO audio output
|
* New FIFO audio output
|
||||||
|
* Support for WavPack files
|
||||||
|
|
||||||
ver 0.13.0 (2007/5/28)
|
ver 0.13.0 (2007/5/28)
|
||||||
* New JACK audio output
|
* New JACK audio output
|
||||||
|
|
17
configure.ac
17
configure.ac
|
@ -79,6 +79,7 @@ AC_ARG_ENABLE(aac,[ --disable-aac disable AAC support (default: enabl
|
||||||
AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support, disables wave support (default: enable)],[enable_audiofile=$enableval],[enable_audiofile=yes])
|
AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support, disables wave support (default: enable)],[enable_audiofile=$enableval],[enable_audiofile=yes])
|
||||||
AC_ARG_ENABLE(mod,[ --enable-mod enable MOD support (default: disable],[enable_mod=$enableval],[enable_mod=yes])
|
AC_ARG_ENABLE(mod,[ --enable-mod enable MOD support (default: disable],[enable_mod=$enableval],[enable_mod=yes])
|
||||||
AC_ARG_ENABLE(mpc,[ --disable-mpc disable musepack (MPC) support (default: enable)],[enable_mpc=$enableval],[enable_mpc=yes])
|
AC_ARG_ENABLE(mpc,[ --disable-mpc disable musepack (MPC) support (default: enable)],[enable_mpc=$enableval],[enable_mpc=yes])
|
||||||
|
AC_ARG_ENABLE(wavpack,[ --disable-wavpack disable wavpack support (default: enable)],[enable_wavpack=$enableval],[enable_wavpack=yes])
|
||||||
AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support (default: enable)],[enable_id3=$enableval],[enable_id3=yes])
|
AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support (default: enable)],[enable_id3=$enableval],[enable_id3=yes])
|
||||||
AC_ARG_ENABLE(lsr,[ --disable-lsr disable libsamplerate support (default: enable)],[enable_lsr=$enableval],[enable_lsr=yes])
|
AC_ARG_ENABLE(lsr,[ --disable-lsr disable libsamplerate support (default: enable)],[enable_lsr=$enableval],[enable_lsr=yes])
|
||||||
|
|
||||||
|
@ -182,7 +183,8 @@ if test x$enable_oss = xyes; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test x$enable_pulse = xyes || test x$enable_jack = xyes ||
|
if test x$enable_pulse = xyes || test x$enable_jack = xyes ||
|
||||||
test x$enable_lsr = xyes || test x$with_zeroconf != xno; then
|
test x$enable_lsr = xyes || test x$with_zeroconf != xno ||
|
||||||
|
test x$enable_wavpack = xyes; then
|
||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -368,6 +370,12 @@ if test x$enable_mpc = xyes; then
|
||||||
CPPFLAGS=$oldcppflags
|
CPPFLAGS=$oldcppflags
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test x$enable_wavpack = xyes; then
|
||||||
|
PKG_CHECK_MODULES([WAVPACK], [wavpack],
|
||||||
|
[enable_wavpack=yes;AC_DEFINE([HAVE_WAVPACK], 1, [Define to enable WavPack support])] MPD_LIBS="$MPD_LIBS $WAVPACK_LIBS" MPD_CFLAGS="$MPD_CFLAGS $WAVPACK_CFLAGS",
|
||||||
|
[enable_wavpack=no;AC_MSG_WARN([WavPack not found -- disabling])])
|
||||||
|
fi
|
||||||
|
|
||||||
MP4FF_SUBDIR=""
|
MP4FF_SUBDIR=""
|
||||||
|
|
||||||
if test x$enable_aac = xyes; then
|
if test x$enable_aac = xyes; then
|
||||||
|
@ -764,6 +772,12 @@ else
|
||||||
echo " Musepack (MPC) support ........disabled"
|
echo " Musepack (MPC) support ........disabled"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test x$enable_wavpack = xyes; then
|
||||||
|
echo " WavPack support ...............enabled"
|
||||||
|
else
|
||||||
|
echo " WavPack support ...............disabled"
|
||||||
|
fi
|
||||||
|
|
||||||
if test x$enable_mod = xyes; then
|
if test x$enable_mod = xyes; then
|
||||||
echo " MOD support ...................enabled"
|
echo " MOD support ...................enabled"
|
||||||
else
|
else
|
||||||
|
@ -778,6 +792,7 @@ if
|
||||||
test x$enable_audiofile = xno &&
|
test x$enable_audiofile = xno &&
|
||||||
test x$enable_aac = xno &&
|
test x$enable_aac = xno &&
|
||||||
test x$enable_mpc = xno &&
|
test x$enable_mpc = xno &&
|
||||||
|
test x$enable_wavpack = xno &&
|
||||||
test x$enable_mod = xno; then
|
test x$enable_mod = xno; then
|
||||||
AC_MSG_ERROR([No input plugins supported!])
|
AC_MSG_ERROR([No input plugins supported!])
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -24,7 +24,8 @@ mpd_inputPlugins = \
|
||||||
inputPlugins/mod_plugin.c \
|
inputPlugins/mod_plugin.c \
|
||||||
inputPlugins/mp3_plugin.c \
|
inputPlugins/mp3_plugin.c \
|
||||||
inputPlugins/mp4_plugin.c \
|
inputPlugins/mp4_plugin.c \
|
||||||
inputPlugins/mpc_plugin.c
|
inputPlugins/mpc_plugin.c \
|
||||||
|
inputPlugins/wavpack_plugin.c
|
||||||
|
|
||||||
|
|
||||||
mpd_headers = \
|
mpd_headers = \
|
||||||
|
|
|
@ -150,6 +150,7 @@ void initInputPlugins(void)
|
||||||
loadInputPlugin(&mp4Plugin);
|
loadInputPlugin(&mp4Plugin);
|
||||||
loadInputPlugin(&aacPlugin);
|
loadInputPlugin(&aacPlugin);
|
||||||
loadInputPlugin(&mpcPlugin);
|
loadInputPlugin(&mpcPlugin);
|
||||||
|
loadInputPlugin(&wavpackPlugin);
|
||||||
loadInputPlugin(&modPlugin);
|
loadInputPlugin(&modPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ extern InputPlugin audiofilePlugin;
|
||||||
extern InputPlugin mp4Plugin;
|
extern InputPlugin mp4Plugin;
|
||||||
extern InputPlugin aacPlugin;
|
extern InputPlugin aacPlugin;
|
||||||
extern InputPlugin mpcPlugin;
|
extern InputPlugin mpcPlugin;
|
||||||
|
extern InputPlugin wavpackPlugin;
|
||||||
extern InputPlugin modPlugin;
|
extern InputPlugin modPlugin;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,422 @@
|
||||||
|
/* the Music Player Daemon (MPD)
|
||||||
|
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
|
||||||
|
* This project's homepage is: http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* WavPack support added by Kodest <kodest at gmail dot com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../inputPlugin.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WAVPACK
|
||||||
|
|
||||||
|
#include "../utils.h"
|
||||||
|
#include "../audio.h"
|
||||||
|
#include "../log.h"
|
||||||
|
#include "../pcm_utils.h"
|
||||||
|
#include "../playerData.h"
|
||||||
|
#include "../outputBuffer.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <wavpack/wavpack.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define ERRORLEN 80
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *name;
|
||||||
|
int type;
|
||||||
|
} tagtypes[] = {
|
||||||
|
{ "artist", TAG_ITEM_ARTIST },
|
||||||
|
{ "album", TAG_ITEM_ALBUM },
|
||||||
|
{ "title", TAG_ITEM_TITLE },
|
||||||
|
{ "track", TAG_ITEM_TRACK },
|
||||||
|
{ "name", TAG_ITEM_NAME },
|
||||||
|
{ "genre", TAG_ITEM_GENRE },
|
||||||
|
{ "date", TAG_ITEM_DATE },
|
||||||
|
{ "composer", TAG_ITEM_COMPOSER },
|
||||||
|
{ "performer", TAG_ITEM_PERFORMER },
|
||||||
|
{ "comment", TAG_ITEM_COMMENT },
|
||||||
|
{ "disc", TAG_ITEM_DISC },
|
||||||
|
{ 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
|
||||||
|
* wavpack.com. Modifications were required because mpd only handles
|
||||||
|
* max 16 bit samples.
|
||||||
|
*/
|
||||||
|
static void format_samples_int(int Bps, void *buffer, uint32_t samcnt)
|
||||||
|
{
|
||||||
|
int32_t temp;
|
||||||
|
uchar *dst = (uchar *)buffer;
|
||||||
|
int32_t *src = (int32_t *)buffer;
|
||||||
|
|
||||||
|
switch (Bps) {
|
||||||
|
case 1:
|
||||||
|
while (samcnt--)
|
||||||
|
*dst++ = *src++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
while (samcnt--) {
|
||||||
|
*dst++ = (uchar)(temp = *src++);
|
||||||
|
*dst++ = (uchar)(temp >> 8);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* downscale to 16 bits */
|
||||||
|
while (samcnt--) {
|
||||||
|
temp = *src++;
|
||||||
|
*dst++ = (uchar)(temp >> 8);
|
||||||
|
*dst++ = (uchar)(temp >> 16);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
/* downscale to 16 bits */
|
||||||
|
while (samcnt--) {
|
||||||
|
temp = *src++;
|
||||||
|
*dst++ = (uchar)(temp >> 16);
|
||||||
|
*dst++ = (uchar)(temp >> 24);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function converts floating point sample data to 16 bit integer.
|
||||||
|
*/
|
||||||
|
static void format_samples_float(int Bps, void *buffer, uint32_t samcnt)
|
||||||
|
{
|
||||||
|
int16_t *dst = (int16_t *)buffer;
|
||||||
|
float *src = (float *)buffer;
|
||||||
|
|
||||||
|
while (samcnt--) {
|
||||||
|
*dst++ = (int16_t)(*src++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This does the main decoding thing.
|
||||||
|
* Requires an already opened WavpackContext.
|
||||||
|
*/
|
||||||
|
static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc,
|
||||||
|
WavpackContext *wpc, int canseek)
|
||||||
|
{
|
||||||
|
void (*format_samples)(int Bps, void *buffer, uint32_t samcnt);
|
||||||
|
char chunk[CHUNK_SIZE];
|
||||||
|
float time;
|
||||||
|
int samplesreq, samplesgot;
|
||||||
|
int allsamples;
|
||||||
|
int position, outsamplesize;
|
||||||
|
int Bps;
|
||||||
|
|
||||||
|
dc->audioFormat.sampleRate = WavpackGetSampleRate(wpc);
|
||||||
|
dc->audioFormat.channels = WavpackGetReducedChannels(wpc);
|
||||||
|
dc->audioFormat.bits = WavpackGetBitsPerSample(wpc);
|
||||||
|
|
||||||
|
if (dc->audioFormat.bits > 16)
|
||||||
|
dc->audioFormat.bits = 16;
|
||||||
|
|
||||||
|
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT)
|
||||||
|
format_samples = format_samples_float;
|
||||||
|
else
|
||||||
|
format_samples = format_samples_int;
|
||||||
|
|
||||||
|
allsamples = WavpackGetNumSamples(wpc);
|
||||||
|
Bps = WavpackGetBytesPerSample(wpc);
|
||||||
|
|
||||||
|
outsamplesize = Bps;
|
||||||
|
if (outsamplesize > 2)
|
||||||
|
outsamplesize = 2;
|
||||||
|
outsamplesize *= dc->audioFormat.channels;
|
||||||
|
|
||||||
|
samplesreq = sizeof(chunk) / (4 * dc->audioFormat.channels);
|
||||||
|
|
||||||
|
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
|
||||||
|
|
||||||
|
dc->totalTime = (float)allsamples / dc->audioFormat.sampleRate;
|
||||||
|
dc->state = DECODE_STATE_DECODE;
|
||||||
|
|
||||||
|
position = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (dc->seek) {
|
||||||
|
if (canseek) {
|
||||||
|
int where;
|
||||||
|
|
||||||
|
clearOutputBuffer(cb);
|
||||||
|
|
||||||
|
where = dc->seekWhere *
|
||||||
|
dc->audioFormat.sampleRate;
|
||||||
|
if (WavpackSeekSample(wpc, where))
|
||||||
|
position = where;
|
||||||
|
else
|
||||||
|
dc->seekError = 1;
|
||||||
|
} else {
|
||||||
|
dc->seekError = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc->seek = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dc->stop)
|
||||||
|
break;
|
||||||
|
|
||||||
|
samplesgot = WavpackUnpackSamples(wpc,
|
||||||
|
(int32_t *)chunk, samplesreq);
|
||||||
|
if (samplesgot > 0) {
|
||||||
|
int bitrate = (int)(WavpackGetInstantBitrate(wpc) /
|
||||||
|
1000 + 0.5);
|
||||||
|
position += samplesgot;
|
||||||
|
time = (float)position / dc->audioFormat.sampleRate;
|
||||||
|
|
||||||
|
format_samples(Bps, chunk,
|
||||||
|
samplesgot * dc->audioFormat.channels);
|
||||||
|
|
||||||
|
sendDataToOutputBuffer(cb, NULL, dc, 0, chunk,
|
||||||
|
samplesgot * outsamplesize,
|
||||||
|
time, bitrate, NULL);
|
||||||
|
}
|
||||||
|
} while (samplesgot == samplesreq);
|
||||||
|
|
||||||
|
flushOutputBuffer(cb);
|
||||||
|
|
||||||
|
dc->state = DECODE_STATE_STOP;
|
||||||
|
dc->stop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads metainfo from the specified file.
|
||||||
|
*/
|
||||||
|
static MpdTag *wavpack_tagdup(char *fname)
|
||||||
|
{
|
||||||
|
WavpackContext *wpc;
|
||||||
|
MpdTag *tag;
|
||||||
|
char error[ERRORLEN];
|
||||||
|
char *s;
|
||||||
|
int ssize;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0);
|
||||||
|
if (wpc == NULL) {
|
||||||
|
ERROR("failed to open WavPack file \"%s\": %s\n", fname, error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = newMpdTag();
|
||||||
|
if (tag == NULL) {
|
||||||
|
ERROR("failed to newMpdTag()\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag->time =
|
||||||
|
(float)WavpackGetNumSamples(wpc) / WavpackGetSampleRate(wpc);
|
||||||
|
|
||||||
|
ssize = 0;
|
||||||
|
s = NULL;
|
||||||
|
|
||||||
|
for (i = 0; tagtypes[i].name != NULL; ++i) {
|
||||||
|
j = WavpackGetTagItem(wpc, tagtypes[i].name, NULL, 0);
|
||||||
|
if (j > 0) {
|
||||||
|
++j;
|
||||||
|
|
||||||
|
if (s == NULL) {
|
||||||
|
s = xmalloc(j);
|
||||||
|
if (s == NULL) break;
|
||||||
|
ssize = j;
|
||||||
|
} else if (j > ssize) {
|
||||||
|
char *t = (char *)xrealloc(s, j);
|
||||||
|
if (t == NULL) break;
|
||||||
|
ssize = j;
|
||||||
|
s = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
WavpackGetTagItem(wpc, tagtypes[i].name, s, j);
|
||||||
|
addItemToMpdTag(tag, tagtypes[i].type, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != NULL)
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
WavpackCloseFile(wpc);
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mpd InputStream <=> WavpackStreamReader wrapper callbacks
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int32_t read_bytes(void *id, void *data, int32_t bcount)
|
||||||
|
{
|
||||||
|
uint8_t *buf = (uint8_t *)data;
|
||||||
|
int32_t i = 0;
|
||||||
|
|
||||||
|
if (last_byte != EOF) {
|
||||||
|
*buf++ = last_byte;
|
||||||
|
last_byte = EOF;
|
||||||
|
--bcount;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return i + readFromInputStream((InputStream *)id, buf, 1, bcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_pos(void *id)
|
||||||
|
{
|
||||||
|
return ((InputStream *)id)->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_pos_abs(void *id, uint32_t pos)
|
||||||
|
{
|
||||||
|
return seekInputStream((InputStream *)id, pos, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_pos_rel(void *id, int32_t delta, int mode)
|
||||||
|
{
|
||||||
|
return seekInputStream((InputStream *)id, delta, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push_back_byte(void *id, int c)
|
||||||
|
{
|
||||||
|
last_byte = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_length(void *id)
|
||||||
|
{
|
||||||
|
return ((InputStream *)id)->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int can_seek(void *id)
|
||||||
|
{
|
||||||
|
return (seekInputStream((InputStream *)id, 0, SEEK_SET) != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static WavpackStreamReader mpd_is_reader = {
|
||||||
|
.read_bytes = read_bytes,
|
||||||
|
.get_pos = get_pos,
|
||||||
|
.set_pos_abs = set_pos_abs,
|
||||||
|
.set_pos_rel = set_pos_rel,
|
||||||
|
.push_back_byte = push_back_byte,
|
||||||
|
.get_length = get_length,
|
||||||
|
.can_seek = can_seek,
|
||||||
|
.write_bytes = NULL /* no need to write edited tags */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tries to decode the specified stream, and gives true if managed to do it.
|
||||||
|
*/
|
||||||
|
static unsigned int wavpack_trydecode(InputStream *is)
|
||||||
|
{
|
||||||
|
char error[ERRORLEN];
|
||||||
|
WavpackContext *wpc;
|
||||||
|
|
||||||
|
wpc = WavpackOpenFileInputEx(&mpd_is_reader, (void *)is, NULL, error,
|
||||||
|
OPEN_STREAMING, 0);
|
||||||
|
if (wpc == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
WavpackCloseFile(wpc);
|
||||||
|
/* Seek it back in order to play from the first byte. */
|
||||||
|
seekInputStream(is, 0, SEEK_SET);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes a stream.
|
||||||
|
* We cannot handle wvc files this way, use the wavpack_filedecode for that.
|
||||||
|
*/
|
||||||
|
static int wavpack_streamdecode(OutputBuffer *cb, DecoderControl *dc,
|
||||||
|
InputStream *is)
|
||||||
|
{
|
||||||
|
char error[ERRORLEN];
|
||||||
|
WavpackContext *wpc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wavpack_streamdecode is unable to use wvc :-(
|
||||||
|
* If we know the original stream url, we would find out the wvc url...
|
||||||
|
* This would require InputStream to store that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wpc = WavpackOpenFileInputEx(&mpd_is_reader, (void *)is, NULL, error,
|
||||||
|
OPEN_2CH_MAX | OPEN_NORMALIZE, 15);
|
||||||
|
if (wpc == NULL) {
|
||||||
|
ERROR("failed to open WavPack stream: %s\n", error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wavpack_decode(cb, dc, wpc, can_seek(is));
|
||||||
|
|
||||||
|
WavpackCloseFile(wpc);
|
||||||
|
closeInputStream(is); /* calling side doesn't do this in mpd 0.13.0 */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes a file. This has the goods on wavpack_streamdecode that this
|
||||||
|
* can handle wvc files.
|
||||||
|
*/
|
||||||
|
static int wavpack_filedecode(OutputBuffer *cb, DecoderControl *dc, char *fname)
|
||||||
|
{
|
||||||
|
char error[ERRORLEN];
|
||||||
|
WavpackContext *wpc;
|
||||||
|
|
||||||
|
wpc = WavpackOpenFileInput(fname, error,
|
||||||
|
OPEN_WVC | OPEN_2CH_MAX | OPEN_NORMALIZE,
|
||||||
|
15);
|
||||||
|
if (wpc == NULL) {
|
||||||
|
ERROR("failed to open WavPack file \"%s\": %s\n", fname, error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wavpack_decode(cb, dc, wpc, 1);
|
||||||
|
|
||||||
|
WavpackCloseFile(wpc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *wavpackSuffixes[] = { "wv", NULL };
|
||||||
|
static char *wavpackMimeTypes[] = { "audio/x-wavpack", NULL };
|
||||||
|
|
||||||
|
InputPlugin wavpackPlugin = {
|
||||||
|
"wavpack",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
wavpack_trydecode,
|
||||||
|
wavpack_streamdecode,
|
||||||
|
wavpack_filedecode, /* provides more functionality! (wvc) */
|
||||||
|
wavpack_tagdup,
|
||||||
|
INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL,
|
||||||
|
wavpackSuffixes,
|
||||||
|
wavpackMimeTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
#else /* !HAVE_WAVPACK */
|
||||||
|
|
||||||
|
InputPlugin wavpackPlugin;
|
||||||
|
|
||||||
|
#endif /* !HAVE_WAVPACK */
|
Loading…
Reference in New Issue