diff options
author | Eric Wong <normalperson@yhbt.net> | 2005-12-05 03:53:56 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2005-12-05 03:53:56 +0000 |
commit | 7a7886a193d4d2ecdf092bbd18e37739f2430be5 (patch) | |
tree | 9d5cf3b78e50803ec9d26d1ef6b2a36561d6fb34 | |
parent | 3af3a551dfbd3299287b88980370de9dc98308fc (diff) | |
download | mpd-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.ac | 46 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/decode.c | 73 | ||||
-rw-r--r-- | src/directory.c | 10 | ||||
-rw-r--r-- | src/inputPlugin.c | 30 | ||||
-rw-r--r-- | src/inputPlugin.h | 29 | ||||
-rw-r--r-- | src/inputPlugins/aac_plugin.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/audiofile_plugin.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/flac_plugin.c | 262 | ||||
-rw-r--r-- | src/inputPlugins/mod_plugin.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/mp3_plugin.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/mp4_plugin.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/mpc_plugin.c | 2 | ||||
-rw-r--r-- | src/inputStream_http.c | 14 | ||||
-rw-r--r-- | src/ls.c | 10 | ||||
-rw-r--r-- | src/ls.h | 4 | ||||
-rw-r--r-- | src/song.c | 20 | ||||
-rw-r--r-- | src/tag.c | 2 |
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; } @@ -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; } @@ -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; } @@ -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 |