Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
69635022
Commit
69635022
authored
Mar 16, 2006
by
Eric Wong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merge with mpd/trunk up to r3925
git-svn-id:
https://svn.musicpd.org/mpd/trunk@3926
09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent
d7e846bd
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1165 additions
and
318 deletions
+1165
-318
configure.ac
configure.ac
+33
-13
libOggFLAC.m4
m4/libOggFLAC.m4
+104
-0
Makefile.am
src/Makefile.am
+7
-2
decode.c
src/decode.c
+54
-15
directory.c
src/directory.c
+5
-5
inputPlugin.c
src/inputPlugin.c
+22
-8
inputPlugin.h
src/inputPlugin.h
+26
-3
_flac_common.c
src/inputPlugins/_flac_common.c
+195
-0
_flac_common.h
src/inputPlugins/_flac_common.h
+77
-0
_ogg_common.c
src/inputPlugins/_ogg_common.c
+65
-0
_ogg_common.h
src/inputPlugins/_ogg_common.h
+35
-0
aac_plugin.c
src/inputPlugins/aac_plugin.c
+2
-0
audiofile_plugin.c
src/inputPlugins/audiofile_plugin.c
+2
-0
flac_plugin.c
src/inputPlugins/flac_plugin.c
+12
-206
mod_plugin.c
src/inputPlugins/mod_plugin.c
+2
-0
mp3_plugin.c
src/inputPlugins/mp3_plugin.c
+2
-0
mp4_plugin.c
src/inputPlugins/mp4_plugin.c
+2
-0
mpc_plugin.c
src/inputPlugins/mpc_plugin.c
+2
-0
oggflac_plugin.c
src/inputPlugins/oggflac_plugin.c
+426
-0
oggvorbis_plugin.c
src/inputPlugins/oggvorbis_plugin.c
+58
-52
inputStream_http.c
src/inputStream_http.c
+14
-0
ls.c
src/ls.c
+4
-4
ls.h
src/ls.h
+2
-2
song.c
src/song.c
+13
-7
tag.c
src/tag.c
+1
-1
No files found.
configure.ac
View file @
69635022
...
...
@@ -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_ogg
vorbis
= 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_ogg
vorbis
= xyes && test x$use_tremor != xyes; then
XIPH_PATH_OGG(MPD_LIBS="$MPD_LIBS $OGG_LIBS" MPD_CFLAGS="$MPD_CFLAGS $OGG_CFLAGS",enable_ogg
vorbis
=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_ogg
vorbis
=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_ogg
vorbis
= 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_ogg
vorbis
=no)
fi
if test x$enable_ogg = xyes; then
if test x$enable_ogg
vorbis
= 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_ogg
vorbis
= 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 v
orbis support])
if test x$enable_ogg
vorbis
= xyes; then
AC_DEFINE(HAVE_OGG
VORBIS,1,[Define for Ogg V
orbis 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_ogg
vorbis
= 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
...
...
m4/libOggFLAC.m4
0 → 100644
View file @
69635022
# Configure paths for libOggFLAC
# "Inspired" by ogg.m4
dnl AM_PATH_LIBOGGFLAC([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Test for libOggFLAC, and define LIBOGGFLAC_CFLAGS and LIBOGGFLAC_LIBS
dnl
AC_DEFUN([AM_PATH_LIBOGGFLAC],
[dnl
dnl Get the cflags and libraries
dnl
AC_ARG_WITH(libOggFLAC,[ --with-libOggFLAC=PFX Prefix where libOggFLAC is installed (optional)], libOggFLAC_prefix="$withval", libOggFLAC_prefix="")
AC_ARG_WITH(libOggFLAC-libraries,[ --with-libOggFLAC-libraries=DIR Directory where libOggFLAC library is installed (optional)], libOggFLAC_libraries="$withval", libOggFLAC_libraries="")
AC_ARG_WITH(libOggFLAC-includes,[ --with-libOggFLAC-includes=DIR Directory where libOggFLAC header files are installed (optional)], libOggFLAC_includes="$withval", libOggFLAC_includes="")
AC_ARG_ENABLE(libOggFLACtest, [ --disable-libOggFLACtest Do not try to compile and run a test libOggFLAC program],, enable_libOggFLACtest=yes)
if test "x$libOggFLAC_libraries" != "x" ; then
LIBOGGFLAC_LIBS="-L$libOggFLAC_libraries"
elif test "x$libOggFLAC_prefix" != "x" ; then
LIBOGGFLAC_LIBS="-L$libOggFLAC_prefix/lib"
elif test "x$prefix" != "xNONE" ; then
LIBOGGFLAC_LIBS="-L$libdir"
fi
LIBOGGFLAC_LIBS="$LIBOGGFLAC_LIBS -lOggFLAC -lFLAC -lm"
if test "x$libOggFLAC_includes" != "x" ; then
LIBOGGFLAC_CFLAGS="-I$libOggFLAC_includes"
elif test "x$libOggFLAC_prefix" != "x" ; then
LIBOGGFLAC_CFLAGS="-I$libOggFLAC_prefix/include"
elif test "$prefix" != "xNONE"; then
LIBOGGFLAC_CFLAGS="-I$prefix/include"
fi
AC_MSG_CHECKING(for libOggFLAC)
no_libOggFLAC=""
if test "x$enable_libOggFLACtest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_CXXFLAGS="$CXXFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $LIBOGGFLAC_CFLAGS"
CXXFLAGS="$CXXFLAGS $LIBOGGFLAC_CFLAGS"
LIBS="$LIBS $LIBOGGFLAC_LIBS"
dnl
dnl Now check if the installed libOggFLAC is sufficiently new.
dnl
rm -f conf.libOggFLACtest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <OggFLAC/stream_decoder.h>
int main ()
{
system("touch conf.libOggFLACtest");
return 0;
}
],, no_libOggFLAC=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
if test "x$no_libOggFLAC" = "x" ; then
AC_MSG_RESULT(yes)
ifelse([$1], , :, [$1])
else
AC_MSG_RESULT(no)
if test -f conf.libOggFLACtest ; then
:
else
echo "*** Could not run libOggFLAC test program, checking why..."
CFLAGS="$CFLAGS $LIBOGGFLAC_CFLAGS"
LIBS="$LIBS $LIBOGGFLAC_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <OggFLAC/stream_decoder.h>
], [ return 0; ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding libOggFLAC or finding the wrong"
echo "*** version of libOggFLAC. If it is not finding libOggFLAC, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means libOggFLAC was incorrectly installed"
echo "*** or that you have moved libOggFLAC since it was installed. In the latter case, you"
echo "*** may want to edit the libOggFLAC-config script: $LIBOGGFLAC_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
LIBOGGFLAC_CFLAGS=""
LIBOGGFLAC_LIBS=""
ifelse([$2], , :, [$2])
fi
AC_SUBST(LIBOGGFLAC_CFLAGS)
AC_SUBST(LIBOGGFLAC_LIBS)
rm -f conf.libOggFLACtest
])
src/Makefile.am
View file @
69635022
...
...
@@ -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
\
...
...
src/decode.c
View file @
69635022
...
...
@@ -322,35 +322,74 @@ 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
);
break
;
}
/* 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
);
break
;
}
}
/* 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
)
{
ret
=
plugin
->
streamDecodeFunc
(
cb
,
dc
,
&
inStream
);
/* we already know our mp3Plugin supports streams, no
* need to check for stream{Types,DecodeFunc} */
if
((
plugin
=
getInputPluginFromName
(
"mp3"
)))
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
))
{
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
);
ret
=
plugin
->
streamDecodeFunc
(
cb
,
dc
,
&
inStream
);
break
;
}
else
if
(
plugin
->
fileDecodeFunc
)
{
closeInputStream
(
&
inStream
);
ret
=
plugin
->
fileDecodeFunc
(
cb
,
dc
,
path
);
ret
=
plugin
->
fileDecodeFunc
(
cb
,
dc
,
path
);
}
}
}
...
...
src/directory.c
View file @
69635022
...
...
@@ -323,7 +323,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
;
...
...
@@ -414,7 +414,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
;
}
...
...
@@ -550,7 +550,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
;
...
...
@@ -573,7 +573,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
&&
...
...
@@ -765,7 +765,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
);
...
...
src/inputPlugin.c
View file @
69635022
...
...
@@ -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
ogg
vorbis
Plugin
;
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
);
...
...
src/inputPlugin.h
View file @
69635022
...
...
@@ -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
);
...
...
src/inputPlugins/_flac_common.c
0 → 100644
View file @
69635022
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* Common data structures and functions used by FLAC and OggFLAC
* (c) 2005 by Eric Wong <normalperson@yhbt.net>
*
* 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"
#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
#include "_flac_common.h"
#include "../log.h"
#include "../tag.h"
#include "../inputStream.h"
#include "../outputBuffer.h"
#include "../decode.h"
#include "../replayGain.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <FLAC/format.h>
#include <FLAC/metadata.h>
void
init_FlacData
(
FlacData
*
data
,
OutputBuffer
*
cb
,
DecoderControl
*
dc
,
InputStream
*
inStream
)
{
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
;
data
->
tag
=
NULL
;
}
static
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
)
{
size_t
pos
=
strlen
(
cmnt
)
+
1
;
/* 1 is for '=' */
int
len
=
block
->
data
.
vorbis_comment
.
comments
[
offset
].
length
-
pos
;
if
(
len
>
0
)
{
unsigned
char
tmp
;
unsigned
char
*
dup
=
&
(
block
->
data
.
vorbis_comment
.
comments
[
offset
].
entry
[
pos
]);
tmp
=
dup
[
len
];
dup
[
len
]
=
'\0'
;
*
fl
=
atof
((
char
*
)
dup
);
dup
[
len
]
=
tmp
;
return
1
;
}
}
return
0
;
}
/* replaygain stuff by AliasMrJones */
static
void
flacParseReplayGain
(
const
FLAC__StreamMetadata
*
block
,
FlacData
*
data
)
{
unsigned
int
found
=
0
;
if
(
data
->
replayGainInfo
)
freeReplayGainInfo
(
data
->
replayGainInfo
);
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
;
}
}
/* tracknumber is used in VCs, MPD uses "track" ..., all the other
* tag names match */
static
const
char
*
VORBIS_COMMENT_TRACK_KEY
=
"tracknumber"
;
static
unsigned
int
commentMatchesAddToTag
(
const
FLAC__StreamMetadata_VorbisComment_Entry
*
entry
,
unsigned
int
itemType
,
MpdTag
**
tag
)
{
const
char
*
str
=
(
itemType
==
TAG_ITEM_TRACK
)
?
VORBIS_COMMENT_TRACK_KEY
:
mpdTagItemKeys
[
itemType
];
size_t
slen
=
strlen
(
str
);
int
vlen
=
entry
->
length
-
slen
-
1
;
if
((
vlen
>
0
)
&&
(
0
==
strncasecmp
(
str
,(
char
*
)
entry
->
entry
,
slen
))
&&
(
*
(
entry
->
entry
+
slen
)
==
'='
))
{
if
(
!*
tag
)
*
tag
=
newMpdTag
();
addItemToMpdTagWithLen
(
*
tag
,
itemType
,
(
char
*
)(
entry
->
entry
+
slen
+
1
),
vlen
);
return
1
;
}
return
0
;
}
MpdTag
*
copyVorbisCommentBlockToMpdTag
(
const
FLAC__StreamMetadata
*
block
,
MpdTag
*
tag
)
{
unsigned
int
i
,
j
;
FLAC__StreamMetadata_VorbisComment_Entry
*
comments
;
comments
=
block
->
data
.
vorbis_comment
.
comments
;
for
(
i
=
block
->
data
.
vorbis_comment
.
num_comments
;
i
!=
0
;
--
i
)
{
for
(
j
=
TAG_NUM_OF_ITEM_TYPES
;
j
--
;
)
{
if
(
commentMatchesAddToTag
(
comments
,
j
,
&
tag
))
break
;
}
comments
++
;
}
return
tag
;
}
void
flac_metadata_common_cb
(
const
FLAC__StreamMetadata
*
block
,
FlacData
*
data
)
{
DecoderControl
*
dc
=
data
->
dc
;
const
FLAC__StreamMetadata_StreamInfo
*
si
=
&
(
block
->
data
.
stream_info
);
switch
(
block
->
type
)
{
case
FLAC__METADATA_TYPE_STREAMINFO
:
dc
->
audioFormat
.
bits
=
si
->
bits_per_sample
;
dc
->
audioFormat
.
sampleRate
=
si
->
sample_rate
;
dc
->
audioFormat
.
channels
=
si
->
channels
;
dc
->
totalTime
=
((
float
)
si
->
total_samples
)
/
(
si
->
sample_rate
);
getOutputAudioFormat
(
&
(
dc
->
audioFormat
),
&
(
data
->
cb
->
audioFormat
));
break
;
case
FLAC__METADATA_TYPE_VORBIS_COMMENT
:
flacParseReplayGain
(
block
,
data
);
default:
break
;
}
}
void
flac_error_common_cb
(
const
char
*
plugin
,
const
FLAC__StreamDecoderErrorStatus
status
,
FlacData
*
data
)
{
if
(
data
->
dc
->
stop
)
return
;
switch
(
status
)
{
case
FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC
:
ERROR
(
"%s lost sync
\n
"
,
plugin
);
break
;
case
FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER
:
ERROR
(
"bad %s header
\n
"
,
plugin
);
break
;
case
FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH
:
ERROR
(
"%s crc mismatch
\n
"
,
plugin
);
break
;
default:
ERROR
(
"unknown %s error
\n
"
,
plugin
);
}
}
#endif
/* HAVE_FLAC || HAVE_OGGFLAC */
src/inputPlugins/_flac_common.h
0 → 100644
View file @
69635022
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* Common data structures and functions used by FLAC and OggFLAC
* (c) 2005 by Eric Wong <normalperson@yhbt.net>
*
* 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
*/
#ifndef _FLAC_COMMON_H
#define _FLAC_COMMON_H
#include "../inputPlugin.h"
#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
#include "../tag.h"
#include "../inputStream.h"
#include "../outputBuffer.h"
#include "../decode.h"
#include <FLAC/seekable_stream_decoder.h>
#include <FLAC/metadata.h>
#define FLAC_CHUNK_SIZE 4080
typedef
struct
{
unsigned
char
chunk
[
FLAC_CHUNK_SIZE
];
int
chunk_length
;
float
time
;
int
bitRate
;
FLAC__uint64
position
;
OutputBuffer
*
cb
;
DecoderControl
*
dc
;
InputStream
*
inStream
;
ReplayGainInfo
*
replayGainInfo
;
MpdTag
*
tag
;
}
FlacData
;
/* initializes a given FlacData struct */
void
init_FlacData
(
FlacData
*
data
,
OutputBuffer
*
cb
,
DecoderControl
*
dc
,
InputStream
*
inStream
);
void
flac_metadata_common_cb
(
const
FLAC__StreamMetadata
*
block
,
FlacData
*
data
);
void
flac_error_common_cb
(
const
char
*
plugin
,
FLAC__StreamDecoderErrorStatus
status
,
FlacData
*
data
);
MpdTag
*
copyVorbisCommentBlockToMpdTag
(
const
FLAC__StreamMetadata
*
block
,
MpdTag
*
tag
);
static
inline
int
flacSendChunk
(
FlacData
*
data
)
{
if
(
sendDataToOutputBuffer
(
data
->
cb
,
NULL
,
data
->
dc
,
1
,
data
->
chunk
,
data
->
chunk_length
,
data
->
time
,
data
->
bitRate
,
data
->
replayGainInfo
)
==
OUTPUT_BUFFER_DC_STOP
)
return
-
1
;
return
0
;
}
#endif
/* HAVE_FLAC || HAVE_OGGFLAC */
#endif
/* _FLAC_COMMON_H */
src/inputPlugins/_ogg_common.c
0 → 100644
View file @
69635022
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
* (c) 2005 by Eric Wong <normalperson@yhbt.net>
*
* 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"
#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS)
#include "../utils.h"
#include "_ogg_common.h"
#include <string.h>
ogg_stream_type
ogg_stream_type_detect
(
InputStream
*
inStream
)
{
/* oggflac detection based on code in ogg123 and this post
* http://lists.xiph.org/pipermail/flac/2004-December/000393.html
* ogg123 trunk still doesn't have this patch as of June 2005 */
unsigned
char
buf
[
41
];
size_t
r
,
to_read
=
41
;
seekInputStream
(
inStream
,
0
,
SEEK_SET
);
while
(
to_read
)
{
r
=
readFromInputStream
(
inStream
,
buf
,
1
,
to_read
);
if
(
r
<
0
)
break
;
to_read
-=
r
;
if
(
!
r
&&
!
inputStreamAtEOF
(
inStream
))
my_usleep
(
10000
);
else
break
;
}
seekInputStream
(
inStream
,
0
,
SEEK_SET
);
if
(
r
>=
32
&&
memcmp
(
buf
,
"OggS"
,
4
)
==
0
&&
(
(
memcmp
(
buf
+
29
,
"FLAC"
,
4
)
==
0
&&
memcmp
(
buf
+
37
,
"fLaC"
,
4
)
==
0
)
||
(
memcmp
(
buf
+
28
,
"FLAC"
,
4
)
==
0
)
||
(
memcmp
(
buf
+
28
,
"fLaC"
,
4
)
==
0
)))
{
return
FLAC
;
}
return
VORBIS
;
}
#endif
/* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
src/inputPlugins/_ogg_common.h
0 → 100644
View file @
69635022
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
* (c) 2005 by Eric Wong <normalperson@yhbt.net>
*
* 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
*/
#ifndef _OGG_COMMON_H
#define _OGG_COMMON_H
#include "../inputPlugin.h"
#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS)
typedef
enum
_ogg_stream_type
{
VORBIS
,
FLAC
}
ogg_stream_type
;
ogg_stream_type
ogg_stream_type_detect
(
InputStream
*
inStream
);
#endif
/* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
#endif
/* _OGG_COMMON_H */
src/inputPlugins/aac_plugin.c
View file @
69635022
...
...
@@ -420,6 +420,7 @@ InputPlugin aacPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
aac_decode
,
aacTagDup
,
INPUT_PLUGIN_STREAM_FILE
,
...
...
@@ -437,6 +438,7 @@ InputPlugin aacPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
,
...
...
src/inputPlugins/audiofile_plugin.c
View file @
69635022
...
...
@@ -163,6 +163,7 @@ InputPlugin audiofilePlugin =
NULL
,
NULL
,
NULL
,
NULL
,
audiofile_decode
,
audiofileTagDup
,
INPUT_PLUGIN_STREAM_FILE
,
...
...
@@ -180,6 +181,7 @@ InputPlugin audiofilePlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
...
...
src/inputPlugins/flac_plugin.c
View file @
69635022
...
...
@@ -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
;
fail:
if
(
data
.
replayGainInfo
)
freeReplayGainInfo
(
data
.
replayGainInfo
);
closeInputStream
(
inStream
);
if
(
flacDec
)
FLAC__seekable_stream_decoder_delete
(
flacDec
);
closeInputStream
(
inStream
);
return
ret
;
}
...
...
@@ -252,33 +230,15 @@ FLAC__SeekableStreamDecoderLengthStatus flacLength(
FLAC__bool
flacEOF
(
const
FLAC__SeekableStreamDecoder
*
flacDec
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
switch
(
inputStreamAtEOF
(
data
->
inStream
))
{
case
1
:
if
(
inputStreamAtEOF
(
data
->
inStream
)
==
1
)
return
true
;
default:
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
,
...
...
@@ -447,79 +324,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
;
...
...
@@ -597,6 +401,7 @@ InputPlugin flacPlugin =
"flac"
,
NULL
,
NULL
,
NULL
,
flac_decode
,
NULL
,
flacTagDup
,
...
...
@@ -605,7 +410,7 @@ InputPlugin flacPlugin =
flac_mime_types
};
#else
#else
/* !HAVE_FLAC */
InputPlugin
flacPlugin
=
{
...
...
@@ -615,9 +420,10 @@ InputPlugin flacPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
,
};
#endif
#endif
/* HAVE_FLAC */
src/inputPlugins/mod_plugin.c
View file @
69635022
...
...
@@ -259,6 +259,7 @@ InputPlugin modPlugin =
NULL
,
mod_finishMikMod
,
NULL
,
NULL
,
mod_decode
,
modTagDup
,
INPUT_PLUGIN_STREAM_FILE
,
...
...
@@ -276,6 +277,7 @@ InputPlugin modPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
...
...
src/inputPlugins/mp3_plugin.c
View file @
69635022
...
...
@@ -820,6 +820,7 @@ InputPlugin mp3Plugin =
"mp3"
,
NULL
,
NULL
,
NULL
,
mp3_decode
,
NULL
,
mp3_tagDup
,
...
...
@@ -837,6 +838,7 @@ InputPlugin mp3Plugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
...
...
src/inputPlugins/mp4_plugin.c
View file @
69635022
...
...
@@ -431,6 +431,7 @@ InputPlugin mp4Plugin =
NULL
,
NULL
,
NULL
,
NULL
,
mp4_decode
,
mp4TagDup
,
INPUT_PLUGIN_STREAM_FILE
,
...
...
@@ -448,6 +449,7 @@ InputPlugin mp4Plugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
...
...
src/inputPlugins/mpc_plugin.c
View file @
69635022
...
...
@@ -336,6 +336,7 @@ InputPlugin mpcPlugin =
"mpc"
,
NULL
,
NULL
,
NULL
,
mpc_decode
,
NULL
,
mpcTagDup
,
...
...
@@ -354,6 +355,7 @@ InputPlugin mpcPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
...
...
src/inputPlugins/oggflac_plugin.c
0 → 100644
View file @
69635022
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* OggFLAC support (half-stolen from flac_plugin.c :))
* (c) 2005 by Eric Wong <normalperson@yhbt.net>
*
* 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_OGGFLAC
#include "_flac_common.h"
#include "_ogg_common.h"
#include "../utils.h"
#include "../log.h"
#include "../pcm_utils.h"
#include "../inputStream.h"
#include "../outputBuffer.h"
#include "../replayGain.h"
#include "../audio.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <OggFLAC/seekable_stream_decoder.h>
#include <FLAC/metadata.h>
static
void
oggflac_cleanup
(
InputStream
*
inStream
,
FlacData
*
data
,
OggFLAC__SeekableStreamDecoder
*
decoder
)
{
if
(
data
->
replayGainInfo
)
freeReplayGainInfo
(
data
->
replayGainInfo
);
if
(
decoder
)
OggFLAC__seekable_stream_decoder_delete
(
decoder
);
closeInputStream
(
inStream
);
}
static
OggFLAC__SeekableStreamDecoderReadStatus
of_read_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
FLAC__byte
buf
[],
unsigned
*
bytes
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
size_t
r
;
while
(
1
)
{
r
=
readFromInputStream
(
data
->
inStream
,(
void
*
)
buf
,
1
,
*
bytes
);
if
(
r
==
0
&&
!
inputStreamAtEOF
(
data
->
inStream
)
&&
!
data
->
dc
->
stop
)
my_usleep
(
10000
);
else
break
;
}
*
bytes
=
r
;
if
(
r
==
0
&&
!
inputStreamAtEOF
(
data
->
inStream
)
&&
!
data
->
dc
->
stop
)
return
OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
;
return
OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
;
}
static
OggFLAC__SeekableStreamDecoderSeekStatus
of_seek_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
FLAC__uint64
offset
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
if
(
seekInputStream
(
data
->
inStream
,
offset
,
SEEK_SET
)
<
0
)
{
return
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
;
}
return
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
;
}
static
OggFLAC__SeekableStreamDecoderTellStatus
of_tell_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
FLAC__uint64
*
offset
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
*
offset
=
(
long
)(
data
->
inStream
->
offset
);
return
OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
;
}
static
OggFLAC__SeekableStreamDecoderLengthStatus
of_length_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
FLAC__uint64
*
length
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
*
length
=
(
size_t
)(
data
->
inStream
->
size
);
return
OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
;
}
static
FLAC__bool
of_EOF_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
void
*
fdata
)
{
FlacData
*
data
=
(
FlacData
*
)
fdata
;
if
(
inputStreamAtEOF
(
data
->
inStream
)
==
1
)
return
true
;
return
false
;
}
static
void
of_error_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
FLAC__StreamDecoderErrorStatus
status
,
void
*
fdata
)
{
flac_error_common_cb
(
"oggflac"
,
status
,(
FlacData
*
)
fdata
);
}
static
void
oggflacPrintErroredState
(
OggFLAC__SeekableStreamDecoderState
state
)
{
switch
(
state
)
{
case
OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR
:
ERROR
(
"oggflac allocation error
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR
:
ERROR
(
"oggflac read error
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR
:
ERROR
(
"oggflac seek error
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
:
ERROR
(
"oggflac seekable stream error
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED
:
ERROR
(
"oggflac decoder already initialized
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK
:
ERROR
(
"invalid oggflac callback
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED
:
ERROR
(
"oggflac decoder uninitialized
\n
"
);
break
;
case
OggFLAC__SEEKABLE_STREAM_DECODER_OK
:
case
OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING
:
case
OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
:
break
;
}
}
static
FLAC__StreamDecoderWriteStatus
oggflacWrite
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
const
FLAC__Frame
*
frame
,
const
FLAC__int32
*
const
buf
[],
void
*
vdata
)
{
FlacData
*
data
=
(
FlacData
*
)
vdata
;
FLAC__uint32
samples
=
frame
->
header
.
blocksize
;
FLAC__uint16
u16
;
unsigned
char
*
uc
;
int
c_samp
,
c_chan
,
d_samp
;
int
i
;
float
timeChange
;
const
int
bytesPerSample
=
data
->
dc
->
audioFormat
.
bits
/
8
;
timeChange
=
((
float
)
samples
)
/
frame
->
header
.
sample_rate
;
data
->
time
+=
timeChange
;
/* ogg123 uses a complicated method of calculating bitrate
* with averaging which I'm not too fond of.
* (waste of memory/CPU cycles, especially given this is _lossless_)
* a get_decode_position() is not available in OggFLAC, either
*
* this does not give an accurate bitrate:
* (bytes_last_read was set in the read callback)
data->bitRate = ((8.0 * data->bytes_last_read *
frame->header.sample_rate)
/((float)samples * 1000)) + 0.5;
*/
for
(
c_samp
=
d_samp
=
0
;
c_samp
<
frame
->
header
.
blocksize
;
c_samp
++
)
{
for
(
c_chan
=
0
;
c_chan
<
frame
->
header
.
channels
;
c_chan
++
,
d_samp
++
)
{
u16
=
buf
[
c_chan
][
c_samp
];
uc
=
(
unsigned
char
*
)
&
u16
;
for
(
i
=
0
;
i
<
(
data
->
dc
->
audioFormat
.
bits
/
8
);
i
++
)
{
if
(
data
->
chunk_length
>=
FLAC_CHUNK_SIZE
)
{
if
(
flacSendChunk
(
data
)
<
0
)
{
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
data
->
chunk_length
=
0
;
if
(
data
->
dc
->
seek
)
{
return
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
}
}
data
->
chunk
[
data
->
chunk_length
++
]
=
*
(
uc
++
);
}
}
}
return
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
}
/* used by TagDup */
static
void
of_metadata_dup_cb
(
const
OggFLAC__SeekableStreamDecoder
*
decoder
,
const
FLAC__StreamMetadata
*
block
,
void
*
vdata
)
{
FlacData
*
data
=
(
FlacData
*
)
vdata
;
switch
(
block
->
type
)
{
case
FLAC__METADATA_TYPE_STREAMINFO
:
if
(
!
data
->
tag
)
data
->
tag
=
newMpdTag
();
data
->
tag
->
time
=
((
float
)
block
->
data
.
stream_info
.
total_samples
)
/
block
->
data
.
stream_info
.
sample_rate
+
0
.
5
;
return
;
case
FLAC__METADATA_TYPE_VORBIS_COMMENT
:
copyVorbisCommentBlockToMpdTag
(
block
,
data
->
tag
);
default:
break
;
}
}
/* used by decode */
static
void
of_metadata_decode_cb
(
const
OggFLAC__SeekableStreamDecoder
*
dec
,
const
FLAC__StreamMetadata
*
block
,
void
*
vdata
)
{
flac_metadata_common_cb
(
block
,
(
FlacData
*
)
vdata
);
}
static
OggFLAC__SeekableStreamDecoder
*
full_decoder_init_and_read_metadata
(
FlacData
*
data
,
unsigned
int
metadata_only
)
{
OggFLAC__SeekableStreamDecoder
*
decoder
=
NULL
;
unsigned
int
s
=
1
;
if
(
!
(
decoder
=
OggFLAC__seekable_stream_decoder_new
()))
return
NULL
;
if
(
metadata_only
)
{
s
&=
OggFLAC__seekable_stream_decoder_set_metadata_callback
(
decoder
,
of_metadata_dup_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_metadata_respond
(
decoder
,
FLAC__METADATA_TYPE_STREAMINFO
);
}
else
{
s
&=
OggFLAC__seekable_stream_decoder_set_metadata_callback
(
decoder
,
of_metadata_decode_cb
);
}
s
&=
OggFLAC__seekable_stream_decoder_set_read_callback
(
decoder
,
of_read_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_seek_callback
(
decoder
,
of_seek_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_tell_callback
(
decoder
,
of_tell_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_length_callback
(
decoder
,
of_length_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_eof_callback
(
decoder
,
of_EOF_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_write_callback
(
decoder
,
oggflacWrite
);
s
&=
OggFLAC__seekable_stream_decoder_set_metadata_respond
(
decoder
,
FLAC__METADATA_TYPE_VORBIS_COMMENT
);
s
&=
OggFLAC__seekable_stream_decoder_set_error_callback
(
decoder
,
of_error_cb
);
s
&=
OggFLAC__seekable_stream_decoder_set_client_data
(
decoder
,
(
void
*
)
data
);
if
(
!
s
)
{
ERROR
(
"oggflac problem before init()
\n
"
);
goto
fail
;
}
if
(
OggFLAC__seekable_stream_decoder_init
(
decoder
)
!=
OggFLAC__SEEKABLE_STREAM_DECODER_OK
)
{
ERROR
(
"oggflac problem doing init()
\n
"
);
goto
fail
;
}
if
(
!
OggFLAC__seekable_stream_decoder_process_until_end_of_metadata
(
decoder
))
{
ERROR
(
"oggflac problem reading metadata
\n
"
);
goto
fail
;
}
return
decoder
;
fail:
oggflacPrintErroredState
(
OggFLAC__seekable_stream_decoder_get_state
(
decoder
));
OggFLAC__seekable_stream_decoder_delete
(
decoder
);
return
NULL
;
}
/* public functions: */
static
MpdTag
*
oggflac_TagDup
(
char
*
file
)
{
InputStream
inStream
;
OggFLAC__SeekableStreamDecoder
*
decoder
;
FlacData
data
;
if
(
openInputStream
(
&
inStream
,
file
)
<
0
)
return
NULL
;
if
(
ogg_stream_type_detect
(
&
inStream
)
!=
FLAC
)
{
closeInputStream
(
&
inStream
);
return
NULL
;
}
init_FlacData
(
&
data
,
NULL
,
NULL
,
&
inStream
);
/* errors here won't matter,
* data.tag will be set or unset, that's all we care about */
decoder
=
full_decoder_init_and_read_metadata
(
&
data
,
1
);
oggflac_cleanup
(
&
inStream
,
&
data
,
decoder
);
return
data
.
tag
;
}
static
unsigned
int
oggflac_try_decode
(
InputStream
*
inStream
)
{
return
(
ogg_stream_type_detect
(
inStream
)
==
FLAC
)
?
1
:
0
;
}
static
int
oggflac_decode
(
OutputBuffer
*
cb
,
DecoderControl
*
dc
,
InputStream
*
inStream
)
{
OggFLAC__SeekableStreamDecoder
*
decoder
=
NULL
;
FlacData
data
;
int
ret
=
0
;
init_FlacData
(
&
data
,
cb
,
dc
,
inStream
);
if
(
!
(
decoder
=
full_decoder_init_and_read_metadata
(
&
data
,
0
))){
ret
=
-
1
;
goto
fail
;
}
dc
->
state
=
DECODE_STATE_DECODE
;
while
(
1
)
{
OggFLAC__seekable_stream_decoder_process_single
(
decoder
);
if
(
OggFLAC__seekable_stream_decoder_get_state
(
decoder
)
!=
OggFLAC__SEEKABLE_STREAM_DECODER_OK
)
{
break
;
}
if
(
dc
->
seek
)
{
FLAC__uint64
sampleToSeek
=
dc
->
seekWhere
*
dc
->
audioFormat
.
sampleRate
+
0
.
5
;
if
(
OggFLAC__seekable_stream_decoder_seek_absolute
(
decoder
,
sampleToSeek
))
{
clearOutputBuffer
(
cb
);
data
.
time
=
((
float
)
sampleToSeek
)
/
dc
->
audioFormat
.
sampleRate
;
data
.
position
=
0
;
}
else
dc
->
seekError
=
1
;
dc
->
seek
=
0
;
}
}
if
(
!
dc
->
stop
)
{
oggflacPrintErroredState
(
OggFLAC__seekable_stream_decoder_get_state
(
decoder
));
OggFLAC__seekable_stream_decoder_finish
(
decoder
);
}
/* send last little bit */
if
(
data
.
chunk_length
>
0
&&
!
dc
->
stop
)
{
flacSendChunk
(
&
data
);
flushOutputBuffer
(
data
.
cb
);
}
dc
->
state
=
DECODE_STATE_STOP
;
dc
->
stop
=
0
;
fail:
oggflac_cleanup
(
inStream
,
&
data
,
decoder
);
return
ret
;
}
static
char
*
oggflac_Suffixes
[]
=
{
"ogg"
,
NULL
};
static
char
*
oggflac_mime_types
[]
=
{
"application/ogg"
,
NULL
};
InputPlugin
oggflacPlugin
=
{
"oggflac"
,
NULL
,
NULL
,
oggflac_try_decode
,
oggflac_decode
,
NULL
,
oggflac_TagDup
,
INPUT_PLUGIN_STREAM_URL
|
INPUT_PLUGIN_STREAM_FILE
,
oggflac_Suffixes
,
oggflac_mime_types
};
#else
/* !HAVE_FLAC */
InputPlugin
oggflacPlugin
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
,
};
#endif
/* HAVE_OGGFLAC */
src/inputPlugins/ogg_plugin.c
→
src/inputPlugins/ogg
vorbis
_plugin.c
View file @
69635022
...
...
@@ -16,9 +16,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* TODO 'ogg' should probably be replaced with 'oggvorbis' in all instances */
#include "../inputPlugin.h"
#ifdef HAVE_OGG
#ifdef HAVE_OGGVORBIS
#include "_ogg_common.h"
#include "../utils.h"
#include "../audio.h"
...
...
@@ -99,7 +103,7 @@ long ogg_tell_cb(void * vdata) {
return
(
long
)(
data
->
inStream
->
offset
);
}
char
*
ogg_parseComment
(
char
*
comment
,
char
*
needle
)
{
static
inline
char
*
ogg_parseComment
(
char
*
comment
,
char
*
needle
)
{
int
len
=
strlen
(
needle
);
if
(
strncasecmp
(
comment
,
needle
,
len
)
==
0
&&
*
(
comment
+
len
)
==
'='
)
{
...
...
@@ -150,48 +154,40 @@ void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
}
}
MpdTag
*
oggCommentsParse
(
char
**
comments
)
{
MpdTag
*
ret
=
NULL
;
char
*
temp
;
static
const
char
*
VORBIS_COMMENT_TRACK_KEY
=
"tracknumber"
;
while
(
*
comments
)
{
if
((
temp
=
ogg_parseComment
(
*
comments
,
"artist"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_ARTIST
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"title"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_TITLE
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"album"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_ALBUM
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"tracknumber"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_TRACK
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"genre"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_GENRE
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"date"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_DATE
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"composer"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_COMPOSER
,
temp
);
}
else
if
((
temp
=
ogg_parseComment
(
*
comments
,
"performer"
)))
{
if
(
!
ret
)
ret
=
newMpdTag
();
addItemToMpdTag
(
ret
,
TAG_ITEM_PERFORMER
,
temp
);
static
inline
unsigned
int
ogg_parseCommentAddToTag
(
char
*
comment
,
unsigned
int
itemType
,
MpdTag
**
tag
)
{
const
char
*
needle
=
(
itemType
==
TAG_ITEM_TRACK
)
?
VORBIS_COMMENT_TRACK_KEY
:
mpdTagItemKeys
[
itemType
];
unsigned
int
len
=
strlen
(
needle
);
if
(
strncasecmp
(
comment
,
needle
,
len
)
==
0
&&
*
(
comment
+
len
)
==
'='
)
{
if
(
!*
tag
)
*
tag
=
newMpdTag
();
addItemToMpdTag
(
*
tag
,
itemType
,
comment
+
len
+
1
);
return
1
;
}
return
0
;
}
static
MpdTag
*
oggCommentsParse
(
char
**
comments
)
{
MpdTag
*
tag
=
NULL
;
while
(
*
comments
)
{
unsigned
int
j
;
for
(
j
=
TAG_NUM_OF_ITEM_TYPES
;
j
--
;
)
{
if
(
ogg_parseCommentAddToTag
(
*
comments
,
j
,
&
tag
))
break
;
}
comments
++
;
}
return
ret
;
return
tag
;
}
void
putOggCommentsIntoOutputBuffer
(
OutputBuffer
*
cb
,
char
*
streamName
,
...
...
@@ -220,7 +216,9 @@ void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
freeMpdTag
(
tag
);
}
int
ogg_decode
(
OutputBuffer
*
cb
,
DecoderControl
*
dc
,
InputStream
*
inStream
)
/* public */
int
oggvorbis_decode
(
OutputBuffer
*
cb
,
DecoderControl
*
dc
,
InputStream
*
inStream
)
{
OggVorbis_File
vf
;
ov_callbacks
callbacks
;
...
...
@@ -360,7 +358,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
return
0
;
}
MpdTag
*
oggTagDup
(
char
*
file
)
{
MpdTag
*
ogg
vorbis_
TagDup
(
char
*
file
)
{
MpdTag
*
ret
=
NULL
;
FILE
*
fp
;
OggVorbis_File
vf
;
...
...
@@ -386,25 +384,32 @@ MpdTag * oggTagDup(char * file) {
return
ret
;
}
char
*
oggSuffixes
[]
=
{
"ogg"
,
NULL
};
char
*
oggMimeTypes
[]
=
{
"application/ogg"
,
NULL
};
static
unsigned
int
oggvorbis_try_decode
(
InputStream
*
inStream
)
{
return
(
ogg_stream_type_detect
(
inStream
)
==
VORBIS
)
?
1
:
0
;
}
InputPlugin
oggPlugin
=
static
char
*
oggvorbis_Suffixes
[]
=
{
"ogg"
,
NULL
};
static
char
*
oggvorbis_MimeTypes
[]
=
{
"application/ogg"
,
NULL
};
InputPlugin
oggvorbisPlugin
=
{
"ogg
"
,
"oggvorbis
"
,
NULL
,
NULL
,
ogg_decode
,
oggvorbis_try_decode
,
oggvorbis_decode
,
NULL
,
ogg
TagDup
,
oggvorbis_
TagDup
,
INPUT_PLUGIN_STREAM_URL
|
INPUT_PLUGIN_STREAM_FILE
,
ogg
Suffixes
,
ogg
MimeTypes
oggvorbis_
Suffixes
,
oggvorbis_
MimeTypes
};
#else
#else
/* !HAVE_OGGVORBIS */
InputPlugin
ogg
Plugin
=
InputPlugin
ogg
vorbisPlugin
=
{
NULL
,
NULL
,
...
...
@@ -412,9 +417,10 @@ InputPlugin oggPlugin =
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
NULL
,
};
#endif
#endif
/* HAVE_OGGVORBIS */
src/inputStream_http.c
View file @
69635022
...
...
@@ -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
;
}
...
...
src/ls.c
View file @
69635022
...
...
@@ -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
);
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
;
}
...
...
src/ls.h
View file @
69635022
...
...
@@ -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
);
...
...
src/song.c
View file @
69635022
...
...
@@ -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
;
}
...
...
src/tag.c
View file @
69635022
...
...
@@ -34,7 +34,7 @@
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#ifdef HAVE_OGG
#ifdef HAVE_OGG
VORBIS
#include <vorbis/vorbisfile.h>
#endif
#ifdef HAVE_FLAC
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment