aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2005-12-05 03:53:56 +0000
committerEric Wong <normalperson@yhbt.net>2005-12-05 03:53:56 +0000
commit7a7886a193d4d2ecdf092bbd18e37739f2430be5 (patch)
tree9d5cf3b78e50803ec9d26d1ef6b2a36561d6fb34
parent3af3a551dfbd3299287b88980370de9dc98308fc (diff)
downloadmpd-7a7886a193d4d2ecdf092bbd18e37739f2430be5.tar.gz
mpd-7a7886a193d4d2ecdf092bbd18e37739f2430be5.tar.xz
mpd-7a7886a193d4d2ecdf092bbd18e37739f2430be5.zip
OggFLAC support
git-svn-id: https://svn.musicpd.org/mpd/branches/oggflac@3720 09075e82-0dd4-0310-85a5-a0d7c8717e4f
-rw-r--r--configure.ac46
-rw-r--r--src/Makefile.am9
-rw-r--r--src/decode.c73
-rw-r--r--src/directory.c10
-rw-r--r--src/inputPlugin.c30
-rw-r--r--src/inputPlugin.h29
-rw-r--r--src/inputPlugins/aac_plugin.c2
-rw-r--r--src/inputPlugins/audiofile_plugin.c2
-rw-r--r--src/inputPlugins/flac_plugin.c262
-rw-r--r--src/inputPlugins/mod_plugin.c2
-rw-r--r--src/inputPlugins/mp3_plugin.c2
-rw-r--r--src/inputPlugins/mp4_plugin.c2
-rw-r--r--src/inputPlugins/mpc_plugin.c2
-rw-r--r--src/inputStream_http.c14
-rw-r--r--src/ls.c10
-rw-r--r--src/ls.h4
-rw-r--r--src/song.c20
-rw-r--r--src/tag.c2
18 files changed, 228 insertions, 293 deletions
diff --git a/configure.ac b/configure.ac
index 264fcc707..e9af7e634 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,8 @@ AC_ARG_ENABLE(sun,[ --disable-sun disable sun support (default: enable)],[e
AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enable)],[enable_oss=$enableval],[enable_oss=yes])
AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA support (default: enable)],[enable_alsa=$enableval],[enable_alsa=yes])
AC_ARG_ENABLE(mvp,[ --enable-mvp enable support for Hauppauge Media MVP (default: disable)],[enable_mvp=$enableval],[enable_mvp=no])
-AC_ARG_ENABLE(ogg,[ --disable-ogg disable ogg support (default: enable)],[enable_ogg=$enableval],[enable_ogg=yes])
+AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (default: enable)],[enable_oggvorbis=$enableval],enable_oggvorbis=yes)
+AC_ARG_ENABLE(oggflac,[ --disable-oggflac disable OggFLAC support (default: enable)],[enable_oggflac=$enableval],enable_oggflac=yes)
AC_ARG_ENABLE(flac,[ --disable-flac disable flac support (default: enable)],[enable_flac=$enableval],[enable_flac=yes])
AC_ARG_ENABLE(mp3,[ --disable-mp3 disable mp3 support (default: enable)],[enable_mp3=$enableval],[enable_mp3=yes])
AC_ARG_ENABLE(aac,[ --disable-aac disable AAC support (default: enable)],[enable_aac=$enableval],[enable_aac=yes])
@@ -120,7 +121,7 @@ case $host in
enable_osx=yes ;;
esac
-if test x$enable_ogg = xno; then
+if test x$enable_oggvorbis = xno; then
AC_MSG_WARN("disabling shout streaming support because vorbis encoder was not found")
enable_shout=no
elif test x$use_tremor = xyes; then
@@ -439,8 +440,8 @@ int main() {
CPPFLAGS=$oldcppflags
fi
-if test x$enable_ogg = xyes && test x$use_tremor != xyes; then
- XIPH_PATH_OGG(MPD_LIBS="$MPD_LIBS $OGG_LIBS" MPD_CFLAGS="$MPD_CFLAGS $OGG_CFLAGS",enable_ogg=no)
+if test x$enable_oggvorbis = xyes && test x$use_tremor != xyes; then
+ XIPH_PATH_OGG(MPD_LIBS="$MPD_LIBS $OGG_LIBS" MPD_CFLAGS="$MPD_CFLAGS $OGG_CFLAGS",enable_oggvorbis=no)
fi
if test x$use_tremor = xyes; then
@@ -463,20 +464,20 @@ if test x$use_tremor = xyes; then
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $TREMOR_CFLAGS"
LIBS="$LIBS $TREMOR_LIBS"
- AC_CHECK_LIB(vorbisidec,ov_read,,enable_ogg=no;AC_MSG_WARN([vorbisidec lib needed for ogg support with tremor -- disabling ogg support]))
+ AC_CHECK_LIB(vorbisidec,ov_read,,enable_oggvorbis=no;AC_MSG_WARN([vorbisidec lib needed for ogg support with tremor -- disabling ogg support]))
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
-if test x$enable_ogg = xyes; then
+if test x$enable_oggvorbis = xyes; then
if test x$use_tremor = xyes; then
VORBIS_LIBS="$TREMOR_LIBS"
VORBIS_CFLAGS="$TREMOR_CFLAGS"
else
enable_vorbistest=no
- XIPH_PATH_VORBIS(,enable_ogg=no)
+ XIPH_PATH_VORBIS(,enable_oggvorbis=no)
fi
- if test x$enable_ogg = xyes; then
+ if test x$enable_oggvorbis = xyes; then
dnl
dnl Vorbis Test
@@ -526,21 +527,21 @@ int main ()
return 0;
}
-], AC_MSG_RESULT(yes), AC_MSG_RESULT(no); enable_ogg=no,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+], AC_MSG_RESULT(yes), AC_MSG_RESULT(no) enable_oggvorbis=no,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
dnl
dnl End of Vorbis Test
dnl
- if test x$enable_ogg = xyes; then
+ if test x$enable_oggvorbis = xyes; then
MPD_LIBS="$MPD_LIBS $VORBIS_LIBS $VORBISFILE_LIBS $VORBISENC_LIBS"
MPD_CFLAGS="$MPD_CFLAGS $VORBIS_CFLAGS $VORBISFILE_CFLAGS $VORBISENC_CFLAGS"
fi
fi
-if test x$enable_ogg = xyes; then
- AC_DEFINE(HAVE_OGG,1,[Define for ogg vorbis support])
+if test x$enable_oggvorbis = xyes; then
+ AC_DEFINE(HAVE_OGGVORBIS,1,[Define for Ogg Vorbis support])
fi
if test x$use_tremor = xyes; then
@@ -553,6 +554,7 @@ if test x$enable_flac = xyes; then
AM_PATH_LIBFLAC(MPD_LIBS="$MPD_LIBS $LIBFLAC_LIBS" MPD_CFLAGS="$MPD_CFLAGS $LIBFLAC_CFLAGS",enable_flac=no)
fi
+
if test x$enable_flac = xyes; then
oldcflags="$CFLAGS"
oldlibs="$LIBS"
@@ -573,6 +575,18 @@ if test x$enable_flac = xyes; then
AC_DEFINE(HAVE_FLAC,1,[Define for FLAC support])
fi
+
+if test x$enable_oggflac = xyes; then
+ oldmpdcflags="$MPD_CFLAGS"
+ oldmpdlibs="$MPD_LIBS"
+ AM_PATH_LIBOGGFLAC(MPD_LIBS="$MPD_LIBS $LIBOGGFLAC_LIBS" MPD_CFLAGS="$MPD_CFLAGS $LIBOGGFLAC_CFLAGS",enable_oggflac=no)
+fi
+
+if test x$enable_oggflac = xyes; then
+ AC_DEFINE(HAVE_OGGFLAC,1,[Define for OggFLAC support])
+fi
+
+
if test x$enable_audiofile = xyes; then
AM_PATH_AUDIOFILE(0.1.7, MPD_LIBS="$MPD_LIBS $AUDIOFILE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AUDIOFILE_CFLAGS",
[enable_audiofile=no;AC_MSG_WARN(You need audiofile -- disabling audiofile support)])
@@ -675,7 +689,7 @@ else
echo " mp3 support ...................disabled"
fi
-if test x$enable_ogg = xyes; then
+if test x$enable_oggvorbis = xyes; then
echo " Ogg Vorbis support ............enabled"
if test x$use_tremor = xyes; then
echo " using tremor.................yes"
@@ -692,6 +706,12 @@ else
echo " FLAC support ..................disabled"
fi
+if test x$enable_oggflac = xyes; then
+ echo " OggFLAC support ...............enabled"
+else
+ echo " OggFLAC support ...............disabled"
+fi
+
if test x$enable_audiofile = xyes; then
echo " Wave file support .............enabled"
else
diff --git a/src/Makefile.am b/src/Makefile.am
index b861f1b65..9197c3d69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,14 +10,17 @@ mpd_audioOutputs = \
audioOutputs/audioOutput_shout.c
mpd_inputPlugins = \
+ inputPlugins/_flac_common.c \
+ inputPlugins/_ogg_common.c \
+ inputPlugins/oggflac_plugin.c \
+ inputPlugins/oggvorbis_plugin.c \
inputPlugins/aac_plugin.c \
inputPlugins/audiofile_plugin.c \
inputPlugins/flac_plugin.c \
inputPlugins/mod_plugin.c \
inputPlugins/mp3_plugin.c \
inputPlugins/mp4_plugin.c \
- inputPlugins/mpc_plugin.c \
- inputPlugins/ogg_plugin.c
+ inputPlugins/mpc_plugin.c
mpd_headers = \
@@ -32,6 +35,8 @@ mpd_headers = \
decode.h \
directory.h \
inputPlugin.h \
+ inputPlugins/_flac_common.h \
+ inputPlugins/_ogg_common.h \
inputStream.h \
inputStream_file.h \
inputStream_http.h \
diff --git a/src/decode.c b/src/decode.c
index 34904a4c9..1c78065b4 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -319,37 +319,72 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
ret = DECODE_ERROR_UNKTYPE;
if(isRemoteUrl(dc->utf8url)) {
+ unsigned int next = 0;
cb->acceptMetadata = 1;
- plugin = getInputPluginFromMimeType(inStream.mime);
+
+ /* first we try mime types: */
+ while(ret && (plugin = getInputPluginFromMimeType(
+ inStream.mime, next++))) {
+ if (!plugin->streamDecodeFunc)
+ continue;
+ if (!(plugin->streamTypes & INPUT_PLUGIN_STREAM_URL))
+ continue;
+ if(plugin->tryDecodeFunc && !plugin->tryDecodeFunc(
+ &inStream))
+ continue;
+ ret = plugin->streamDecodeFunc(cb, dc, &inStream);
+ }
+
+ /* if that fails, try suffix matching the URL: */
if(plugin == NULL) {
- plugin = getInputPluginFromSuffix(
- getSuffix(dc->utf8url));
+ char * s = getSuffix(dc->utf8url);
+ next = 0;
+ while(ret && (plugin = getInputPluginFromSuffix(
+ s, next++))) {
+ if (!plugin->streamDecodeFunc)
+ continue;
+ if(!(plugin->streamTypes &
+ INPUT_PLUGIN_STREAM_URL))
+ continue;
+ if(plugin->tryDecodeFunc &&
+ !plugin->tryDecodeFunc(
+ &inStream))
+ continue;
+ ret = plugin->streamDecodeFunc(
+ cb, dc, &inStream);
+ }
}
+ /* fallback to mp3: */
/* this is needed for bastard streams that don't have a suffix
or set the mimeType */
if(plugin == NULL) {
plugin = getInputPluginFromName("mp3");
- }
- if(plugin && (plugin->streamTypes & INPUT_PLUGIN_STREAM_URL) &&
- plugin->streamDecodeFunc)
- {
+ /* we already know our mp3Plugin supports streams, no
+ * need to check for stream{Types,DecodeFunc} */
ret = plugin->streamDecodeFunc(cb, dc, &inStream);
}
}
else {
+ unsigned int next = 0;
+ char * s = getSuffix(dc->utf8url);
cb->acceptMetadata = 0;
- plugin = getInputPluginFromSuffix(getSuffix(dc->utf8url));
- if(plugin && (plugin->streamTypes & INPUT_PLUGIN_STREAM_FILE))
- {
- if(plugin->streamDecodeFunc) {
- ret = plugin->streamDecodeFunc(cb, dc,
- &inStream);
- }
- else if(plugin->fileDecodeFunc) {
- closeInputStream(&inStream);
- ret = plugin->fileDecodeFunc(cb, dc, path);
- }
- }
+ while (ret && (plugin = getInputPluginFromSuffix(s, next++))) {
+ if(!plugin->streamTypes & INPUT_PLUGIN_STREAM_FILE)
+ continue;
+ if(plugin->tryDecodeFunc && !plugin->tryDecodeFunc(
+ &inStream))
+ continue;
+
+ if(plugin->streamDecodeFunc) {
+ ret = plugin->streamDecodeFunc(
+ cb, dc, &inStream);
+ }
+ else if(plugin->fileDecodeFunc) {
+ closeInputStream(&inStream);
+ ret = plugin->fileDecodeFunc(
+ cb, dc, path);
+ }
+ }
}
if(ret<0 || ret == DECODE_ERROR_UNKTYPE) {
diff --git a/src/directory.c b/src/directory.c
index a07336dcb..4d1858a8a 100644
--- a/src/directory.c
+++ b/src/directory.c
@@ -322,7 +322,7 @@ int updateInDirectory(Directory * directory, char * shortname, char * name) {
if(myStat(name, &st)) return -1;
- if(S_ISREG(st.st_mode) && hasMusicSuffix(name)) {
+ if(S_ISREG(st.st_mode) && hasMusicSuffix(name, 0)) {
if(0==findInList(directory->songs,shortname,&song)) {
addToDirectory(directory, shortname, name);
return DIRECTORY_RETURN_UPDATE;
@@ -413,7 +413,7 @@ int removeDeletedFromDirectory(Directory * directory, DIR * dir) {
while(node) {
tmpNode = node->nextNode;
if(findInList(entList,node->key,(void **)&name)) {
- if(!isMusic(name,NULL)) {
+ if(!isMusic(name,NULL,0)) {
removeSongFromDirectory(directory,node->key);
ret = 1;
}
@@ -549,7 +549,7 @@ int updatePath(char * utf8path) {
parentDirectory->parent,
parentDirectory->stat->inode,
parentDirectory->stat->device) &&
- song && isMusic(getSongUrl(song), &mtime))
+ song && isMusic(getSongUrl(song), &mtime, 0))
{
free(path);
if(song->mtime==mtime) return 0;
@@ -572,7 +572,7 @@ int updatePath(char * utf8path) {
* Also, if by chance a directory was replaced by a file of the same
* name or vice versa, we need to add it to the db
*/
- if(isDir(path) || isMusic(path,NULL)) {
+ if(isDir(path) || isMusic(path,NULL,0)) {
parentDirectory = addParentPathToDB(path,&shortname);
if(!parentDirectory || (
!parentDirectory->stat &&
@@ -764,7 +764,7 @@ int addToDirectory(Directory * directory, char * shortname, char * name) {
return -1;
}
- if(S_ISREG(st.st_mode) && hasMusicSuffix(name)) {
+ if(S_ISREG(st.st_mode) && hasMusicSuffix(name, 0)) {
Song * song;
song = addSongToList(directory->songs, shortname, name,
SONG_TYPE_FILE, directory);
diff --git a/src/inputPlugin.c b/src/inputPlugin.c
index 2fe20f5fc..5c08b265f 100644
--- a/src/inputPlugin.c
+++ b/src/inputPlugin.c
@@ -49,15 +49,23 @@ static int stringFoundInStringArray(char ** array, char * suffix) {
return 0;
}
-InputPlugin * getInputPluginFromSuffix(char * suffix) {
- ListNode * node = inputPlugin_list->firstNode;
- InputPlugin * plugin = NULL;
+InputPlugin * getInputPluginFromSuffix(char * suffix, unsigned int next) {
+ static ListNode * pos = NULL;
+ ListNode * node;
+ InputPlugin * plugin;
if(suffix == NULL) return NULL;
+
+ if (next) {
+ if (pos) node = pos;
+ else return NULL;
+ } else
+ node = inputPlugin_list->firstNode;
while(node != NULL) {
plugin = node->data;
if(stringFoundInStringArray(plugin->suffixes, suffix)) {
+ pos = node->nextNode;
return plugin;
}
node = node->nextNode;
@@ -66,15 +74,19 @@ InputPlugin * getInputPluginFromSuffix(char * suffix) {
return NULL;
}
-InputPlugin * getInputPluginFromMimeType(char * mimeType) {
- ListNode * node = inputPlugin_list->firstNode;
- InputPlugin * plugin = NULL;
+InputPlugin * getInputPluginFromMimeType(char * mimeType, unsigned int next) {
+ static ListNode * pos = NULL;
+ ListNode * node;
+ InputPlugin * plugin;
if(mimeType == NULL) return NULL;
+
+ node = (next && pos) ? pos : inputPlugin_list->firstNode;
while(node != NULL) {
plugin = node->data;
if(stringFoundInStringArray(plugin->mimeTypes, mimeType)) {
+ pos = node->nextNode;
return plugin;
}
node = node->nextNode;
@@ -109,8 +121,9 @@ void printAllInputPluginSuffixes(FILE * fp) {
}
extern InputPlugin mp3Plugin;
-extern InputPlugin oggPlugin;
+extern InputPlugin oggvorbisPlugin;
extern InputPlugin flacPlugin;
+extern InputPlugin oggflacPlugin;
extern InputPlugin audiofilePlugin;
extern InputPlugin mp4Plugin;
extern InputPlugin mpcPlugin;
@@ -122,7 +135,8 @@ void initInputPlugins() {
/* load plugins here */
loadInputPlugin(&mp3Plugin);
- loadInputPlugin(&oggPlugin);
+ loadInputPlugin(&oggvorbisPlugin);
+ loadInputPlugin(&oggflacPlugin);
loadInputPlugin(&flacPlugin);
loadInputPlugin(&audiofilePlugin);
loadInputPlugin(&mp4Plugin);
diff --git a/src/inputPlugin.h b/src/inputPlugin.h
index dc2e2219e..78268a7f3 100644
--- a/src/inputPlugin.h
+++ b/src/inputPlugin.h
@@ -25,30 +25,53 @@
#include "outputBuffer.h"
#include "tag.h"
+/* valid values for streamTypes in the InputPlugin struct: */
#define INPUT_PLUGIN_STREAM_FILE 0x01
#define INPUT_PLUGIN_STREAM_URL 0x02
+/* optional, set this to NULL if the InputPlugin doesn't have/need one
+ * this must return < 0 if there is an error and >= 0 otherwise */
typedef int (* InputPlugin_initFunc) ();
+/* optional, set this to NULL if the InputPlugin doesn't have/need one */
typedef void (* InputPlugin_finishFunc) ();
+/* boolean return value, returns 1 if the InputStream is decodable by
+ * the InputPlugin, 0 if not */
+typedef unsigned int (* InputPlugin_tryDecodeFunc) (InputStream *);
+
+/* this will be used to decode InputStreams, and is recommended for files
+ * and networked (HTTP) connections.
+ *
+ * returns -1 on error, 0 on success */
typedef int (* InputPlugin_streamDecodeFunc) (OutputBuffer *, DecoderControl *,
InputStream *);
+/* use this if and only if your InputPlugin can only be passed a filename or
+ * handle as input, and will not allow callbacks to be set (like Ogg-Vorbis
+ * and FLAC libraries allow)
+ *
+ * returns -1 on error, 0 on success */
typedef int (* InputPlugin_fileDecodeFunc) (OutputBuffer *, DecoderControl *,
char * path);
-/* file should be the full path! */
+/* file should be the full path! Returns NULL if a tag cannot be found
+ * or read */
typedef MpdTag * (* InputPlugin_tagDupFunc) (char * file);
typedef struct _InputPlugin {
char * name;
InputPlugin_initFunc initFunc;
InputPlugin_finishFunc finishFunc;
+ InputPlugin_tryDecodeFunc tryDecodeFunc;
InputPlugin_streamDecodeFunc streamDecodeFunc;
InputPlugin_fileDecodeFunc fileDecodeFunc;
InputPlugin_tagDupFunc tagDupFunc;
+
+ /* one or more of the INPUT_PLUGIN_STREAM_* values OR'd together */
unsigned char streamTypes;
+
+ /* last element in these arrays must always be a NULL: */
char ** suffixes;
char ** mimeTypes;
} InputPlugin;
@@ -59,9 +82,9 @@ void unloadInputPlugin(InputPlugin * inputPlugin);
/* interface for using plugins */
-InputPlugin * getInputPluginFromSuffix(char * suffix);
+InputPlugin * getInputPluginFromSuffix(char * suffix, unsigned int next);
-InputPlugin * getInputPluginFromMimeType(char * mimeType);
+InputPlugin * getInputPluginFromMimeType(char * mimeType, unsigned int next);
InputPlugin * getInputPluginFromName(char * name);
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index e368f3089..3fb5f4742 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -418,6 +418,7 @@ InputPlugin aacPlugin =
{
"aac",
NULL,
+ NULL,
NULL,
NULL,
aac_decode,
@@ -435,6 +436,7 @@ InputPlugin aacPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
0,
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index adc279b60..d212eaf47 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -163,6 +163,7 @@ InputPlugin audiofilePlugin =
NULL,
NULL,
NULL,
+ NULL,
audiofile_decode,
audiofileTagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -176,6 +177,7 @@ InputPlugin audiofilePlugin =
{
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c
index 6be7f43b3..10a12f853 100644
--- a/src/inputPlugins/flac_plugin.c
+++ b/src/inputPlugins/flac_plugin.c
@@ -20,6 +20,8 @@
#ifdef HAVE_FLAC
+#include "_flac_common.h"
+
#include "../utils.h"
#include "../log.h"
#include "../pcm_utils.h"
@@ -34,22 +36,8 @@
#include <FLAC/seekable_stream_decoder.h>
#include <FLAC/metadata.h>
-typedef struct {
-#define FLAC_CHUNK_SIZE 4080
- unsigned char chunk[FLAC_CHUNK_SIZE];
- int chunk_length;
- float time;
- int bitRate;
- FLAC__uint64 position;
- OutputBuffer * cb;
- DecoderControl * dc;
- InputStream * inStream;
- ReplayGainInfo * replayGainInfo;
-} FlacData;
-
/* this code is based on flac123, from flac-tools */
-int flacSendChunk(FlacData * data);
void flacError(const FLAC__SeekableStreamDecoder *,
FLAC__StreamDecoderErrorStatus, void *);
void flacPrintErroredState(FLAC__SeekableStreamDecoderState state);
@@ -75,14 +63,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
int status = 1;
int ret =0;
- data.chunk_length = 0;
- data.time = 0;
- data.position = 0;
- data.bitRate = 0;
- data.cb = cb;
- data.dc = dc;
- data.inStream = inStream;
- data.replayGainInfo = NULL;
+ init_FlacData(&data, cb, dc, inStream);
if(!(flacDec = FLAC__seekable_stream_decoder_new())) {
ret = -1;
@@ -176,19 +157,16 @@ int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
dc->seek = 0;
} */
- if(dc->stop) {
- dc->state = DECODE_STATE_STOP;
- dc->stop = 0;
- }
- else dc->state = DECODE_STATE_STOP;
+ dc->state = DECODE_STATE_STOP;
+ dc->stop = 0;
fail:
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo);
- closeInputStream(inStream);
-
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
+ closeInputStream(inStream);
+
return ret;
}
@@ -250,35 +228,17 @@ FLAC__SeekableStreamDecoderLengthStatus flacLength(
}
FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) {
- FlacData * data = (FlacData *) fdata;
-
- switch(inputStreamAtEOF(data->inStream)) {
- case 1:
+ FlacData * data = (FlacData *) fdata;
+
+ if (inputStreamAtEOF(data->inStream) == 1)
return true;
- default:
- return false;
- }
+ return false;
}
void flacError(const FLAC__SeekableStreamDecoder *dec,
FLAC__StreamDecoderErrorStatus status, void *fdata)
{
- FlacData * data = (FlacData *) fdata;
- if(data->dc->stop) return;
-
- switch(status) {
- case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
- ERROR("flac lost sync\n");
- break;
- case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
- ERROR("bad header\n");
- break;
- case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
- ERROR("crc mismatch\n");
- break;
- default:
- ERROR("unknown flac error\n");
- }
+ flac_error_common_cb("flac",status,(FlacData *) fdata);
}
void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
@@ -312,93 +272,10 @@ void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
}
}
-int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, char * cmnt,
- float * fl)
-{
- int offset = FLAC__metadata_object_vorbiscomment_find_entry_from(
- block,0,cmnt);
-
- if(offset >= 0) {
- int pos = strlen(cmnt)+1; /* 1 is for '=' */
- int len = block->data.vorbis_comment.comments[offset].length
- -pos;
- if(len > 0) {
- char * dup = malloc(len+1);
- memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
- dup[len] = '\0';
- *fl = atof(dup);
- free(dup);
- return 1;
- }
- }
-
- return 0;
-}
-
-/* replaygain stuff by AliasMrJones */
-void flacParseReplayGain(const FLAC__StreamMetadata *block, FlacData * data) {
- int found = 0;
-
- if(NULL != data->replayGainInfo) {
- freeReplayGainInfo(data->replayGainInfo);
- data->replayGainInfo = NULL;
- }
-
- data->replayGainInfo = newReplayGainInfo();
-
- found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
- &data->replayGainInfo->albumGain);
- found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
- &data->replayGainInfo->albumPeak);
- found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
- &data->replayGainInfo->trackGain);
- found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak",
- &data->replayGainInfo->trackPeak);
-
- if(!found) {
- freeReplayGainInfo(data->replayGainInfo);
- data->replayGainInfo = NULL;
- }
-}
-
void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
const FLAC__StreamMetadata *block, void *vdata)
{
- FlacData * data = (FlacData *)vdata;
-
- switch(block->type) {
- case FLAC__METADATA_TYPE_STREAMINFO:
- data->dc->audioFormat.bits =
- block->data.stream_info.bits_per_sample;
- data->dc->audioFormat.sampleRate =
- block->data.stream_info.sample_rate;
- data->dc->audioFormat.channels =
- block->data.stream_info.channels;
- data->dc->totalTime =
- ((float)block->data.stream_info.total_samples)/
- data->dc->audioFormat.sampleRate;
- getOutputAudioFormat(&(data->dc->audioFormat),
- &(data->cb->audioFormat));
- break;
- case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- flacParseReplayGain(block,data);
- default:
- break;
- }
-}
-
-int flacSendChunk(FlacData * data) {
- switch(sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
- data->chunk_length, data->time, data->bitRate,
- data->replayGainInfo))
- {
- case OUTPUT_BUFFER_DC_STOP:
- return -1;
- default:
- return 0;
- }
-
- return 0;
+ flac_metadata_common_cb(block, (FlacData *)vdata);
}
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
@@ -429,12 +306,12 @@ FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
memcpy(data->chunk+data->chunk_length,
&buf[c_chan][c_samp]+4-bytesPerSample,
bytesPerSample);
- data->chunk_length+=bytesPerSample;
#else
memcpy(data->chunk+data->chunk_length,
&buf[c_chan][c_samp], bytesPerSample);
- data->chunk_length+=bytesPerSample;
#endif
+ data->chunk_length+=bytesPerSample;
+
if(FLAC_CHUNK_SIZE-data->chunk_length < bytesPerSample)
{
if(flacSendChunk(data)<0) {
@@ -451,79 +328,6 @@ FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
-static int commentMatchesAddToTag(
- char * str,
- FLAC__StreamMetadata_VorbisComment_Entry * entry,
- int itemType,
- MpdTag ** tag)
-{
- int slen = strlen(str);
- int vlen = entry->length - slen;
-
- if( vlen <= 0 ) return 0;
-
- if( 0 == strncasecmp(str, entry->entry, slen) ) {
- if(*tag == NULL) *tag = newMpdTag();
- addItemToMpdTagWithLen(*tag, itemType,
- entry->entry+slen, vlen);
- return 1;
- }
-
- return 0;
-}
-
-
-static MpdTag * copyVorbisCommentBlockToMpdTag(FLAC__StreamMetadata * block,
- MpdTag * tag)
-{
- int i;
-
- for(i = 0; i < block->data.vorbis_comment.num_comments; i++) {
- if(commentMatchesAddToTag(
- "artist=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_ARTIST,
- &tag));
- else if(commentMatchesAddToTag(
- "title=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_TITLE,
- &tag));
- else if(commentMatchesAddToTag(
- "album=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_ALBUM,
- &tag));
- else if(commentMatchesAddToTag(
- "tracknumber=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_TRACK,
- &tag));
- else if(commentMatchesAddToTag(
- "genre=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_GENRE,
- &tag));
- else if(commentMatchesAddToTag(
- "date=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_DATE,
- &tag));
- else if(commentMatchesAddToTag(
- "composer=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_COMPOSER,
- &tag));
- else if(commentMatchesAddToTag(
- "performer=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_PERFORMER,
- &tag));
- }
-
- return tag;
-}
-
MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
MpdTag * ret = NULL;
FLAC__Metadata_SimpleIterator * it;
@@ -598,30 +402,32 @@ char * flac_mime_types[] = {"application/x-flac", NULL};
InputPlugin flacPlugin =
{
- "flac",
- NULL,
+ "flac",
NULL,
- flac_decode,
NULL,
- flacTagDup,
- INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
- flacSuffixes,
- flac_mime_types
+ NULL,
+ flac_decode,
+ NULL,
+ flacTagDup,
+ INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
+ flacSuffixes,
+ flac_mime_types
};
-#else
+#else /* !HAVE_FLAC */
InputPlugin flacPlugin =
-{
- NULL,
- NULL,
- NULL,
- NULL,
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
NULL,
NULL,
- 0,
- NULL,
- NULL,
};
-#endif
+#endif /* HAVE_FLAC */
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index 547f4af4a..8b5a245a0 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -259,6 +259,7 @@ InputPlugin modPlugin =
NULL,
mod_finishMikMod,
NULL,
+ NULL,
mod_decode,
modTagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -273,6 +274,7 @@ InputPlugin modPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index 8799e1c87..dd7ceb767 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -771,6 +771,7 @@ InputPlugin mp3Plugin =
"mp3",
NULL,
NULL,
+ NULL,
mp3_decode,
NULL,
mp3_tagDup,
@@ -788,6 +789,7 @@ InputPlugin mp3Plugin =
NULL,
NULL,
NULL,
+ NULL,
0,
NULL,
NULL
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index a1af848c5..e41c054c0 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -431,6 +431,7 @@ InputPlugin mp4Plugin =
NULL,
NULL,
NULL,
+ NULL,
mp4_decode,
mp4TagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -447,6 +448,7 @@ InputPlugin mp4Plugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
0,
NULL,
diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c
index 335c5c368..01a165c44 100644
--- a/src/inputPlugins/mpc_plugin.c
+++ b/src/inputPlugins/mpc_plugin.c
@@ -336,6 +336,7 @@ InputPlugin mpcPlugin =
"mpc",
NULL,
NULL,
+ NULL,
mpc_decode,
NULL,
mpcTagDup,
@@ -351,6 +352,7 @@ InputPlugin mpcPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputStream_http.c b/src/inputStream_http.c
index dbb6d82d3..d3303eb87 100644
--- a/src/inputStream_http.c
+++ b/src/inputStream_http.c
@@ -708,6 +708,20 @@ int inputStream_httpOpen(InputStream * inStream, char * url) {
}
int inputStream_httpSeek(InputStream * inStream, long offset, int whence) {
+ /* hack to reopen an HTTP stream if we're trying to seek to
+ * the beginning */
+ if ((whence == SEEK_SET) && (offset == 0)) {
+ InputStreamHTTPData * data;
+
+ data = (InputStreamHTTPData*)inStream->data;
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_REOPEN;
+ data->buflen = 0;
+ inStream->offset = 0;
+ return 0;
+ }
+
+ /* otherwise, we don't know how to seek in HTTP yet */
return -1;
}
diff --git a/src/ls.c b/src/ls.c
index 762ddd672..f913ff2d3 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -262,12 +262,12 @@ int isDir(char * utf8name) {
return 0;
}
-InputPlugin * hasMusicSuffix(char * utf8file) {
+InputPlugin * hasMusicSuffix(char * utf8file, unsigned int next) {
InputPlugin * ret = NULL;
char * s = getSuffix(utf8file);
- if(s) {
- ret = getInputPluginFromSuffix(s);
+ if(s) {
+ ret = getInputPluginFromSuffix(s, next);
}
else {
DEBUG("hasMusicSuffix: The file: %s has no valid suffix\n",utf8file);
@@ -276,9 +276,9 @@ InputPlugin * hasMusicSuffix(char * utf8file) {
return ret;
}
-InputPlugin * isMusic(char * utf8file, time_t * mtime) {
+InputPlugin * isMusic(char * utf8file, time_t * mtime, unsigned int next) {
if(isFile(utf8file,mtime)) {
- InputPlugin * plugin = hasMusicSuffix(utf8file);
+ InputPlugin * plugin = hasMusicSuffix(utf8file, next);
if (plugin != NULL)
return plugin;
}
diff --git a/src/ls.h b/src/ls.h
index dd8dddd9c..97406c062 100644
--- a/src/ls.h
+++ b/src/ls.h
@@ -45,9 +45,9 @@ int isDir(char * utf8name);
int isPlaylist(char * utf8file);
-InputPlugin * hasMusicSuffix(char * utf8file);
+InputPlugin * hasMusicSuffix(char * utf8file, unsigned int next);
-InputPlugin * isMusic(char * utf8file, time_t * mtime);
+InputPlugin * isMusic(char * utf8file, time_t * mtime, unsigned int next);
char * dupAndStripPlaylistSuffix(char * file);
diff --git a/src/song.c b/src/song.c
index 9a2c8d67d..07a7e04fb 100644
--- a/src/song.c
+++ b/src/song.c
@@ -64,9 +64,12 @@ Song * newSong(char * url, int type, Directory * parentDir) {
if(song->type == SONG_TYPE_FILE) {
InputPlugin * plugin;
- if((plugin = isMusic(getSongUrl(song), &(song->mtime)))) {
- song->tag = plugin->tagDupFunc(
- rmp2amp(utf8ToFsCharset(getSongUrl(song))));
+ unsigned int next = 0;
+ char * song_url = getSongUrl(song);
+ char * abs_path = rmp2amp(utf8ToFsCharset(song_url));
+ while(!song->tag && (plugin = isMusic(song_url,
+ &(song->mtime), next++))) {
+ song->tag = plugin->tagDupFunc(abs_path);
}
if(!song->tag || song->tag->time<0) {
freeSong(song);
@@ -100,7 +103,7 @@ Song * addSongToList(SongList * list, char * url, char * utf8path,
switch(songType) {
case SONG_TYPE_FILE:
- if(isMusic(utf8path, NULL)) {
+ if(isMusic(utf8path, NULL, 0)) {
song = newSong(url, songType, parentDirectory);
}
break;
@@ -278,14 +281,17 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) {
int updateSongInfo(Song * song) {
if(song->type == SONG_TYPE_FILE) {
InputPlugin * plugin;
+ unsigned int next = 0;
+ char * song_url = getSongUrl(song);
+ char * abs_path = rmp2amp(song_url);
if(song->tag) freeMpdTag(song->tag);
song->tag = NULL;
- if((plugin = isMusic(getSongUrl(song),&(song->mtime)))) {
- song->tag = plugin->tagDupFunc(
- rmp2amp(getSongUrl(song)));
+ while(!song->tag && (plugin = isMusic(song_url,
+ &(song->mtime), next++))) {
+ song->tag = plugin->tagDupFunc(abs_path);
}
if(!song->tag || song->tag->time<0) return -1;
}
diff --git a/src/tag.c b/src/tag.c
index b1239f56d..0fa232345 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -34,7 +34,7 @@
#include <stdio.h>
#include <assert.h>
#include <errno.h>
-#ifdef HAVE_OGG
+#ifdef HAVE_OGGVORBIS
#include <vorbis/vorbisfile.h>
#endif
#ifdef HAVE_FLAC