Commit 1e5f57f4 authored by Led's avatar Led

0.14-beta1

parent 1a029af0
...@@ -27,6 +27,9 @@ Patrik Weiskircher <pat@icore.at> ...@@ -27,6 +27,9 @@ Patrik Weiskircher <pat@icore.at>
Laszlo Ashin <kodest@gmail.com> Laszlo Ashin <kodest@gmail.com>
WavPack support WavPack support
Viliam Mateicka <viliam.mateicka@gmail.com>
FFmpeg support
Former Developers Former Developers
----------------- -----------------
tw-nym tw-nym
......
...@@ -39,8 +39,7 @@ host_triplet = @host@ ...@@ -39,8 +39,7 @@ host_triplet = @host@
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/configure AUTHORS COPYING INSTALL NEWS TODO \ $(top_srcdir)/configure AUTHORS COPYING INSTALL NEWS TODO \
compile config.guess config.sub depcomp install-sh ltmain.sh \ compile config.guess config.sub depcomp install-sh missing
missing
subdir = . subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
...@@ -178,6 +177,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@ ...@@ -178,6 +177,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@ HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@ HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@ HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@ HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@ HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@ ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
...@@ -235,6 +236,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@ ...@@ -235,6 +236,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@ VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@ WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@ ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@ acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
......
...@@ -84,29 +84,6 @@ do ...@@ -84,29 +84,6 @@ do
fi fi
done done
if test -n "$LIBTOOLIZE"
then
echo "LIBTOOLIZE=$LIBTOOLIZE in environment," \
"will not attempt to auto-detect"
else
printf "checking for libtoolize ... "
for x in libtoolize glibtoolize
do
($x --version < /dev/null > /dev/null 2>&1) > /dev/null 2>&1
if test $? -eq 0
then
echo $x
LIBTOOLIZE=$x
break
fi
done
fi
if test -z "$LIBTOOLIZE"
then
DIE="$DIE libtoolize(libtool)"
fi
if test -n "$DIE" if test -n "$DIE"
then then
echo "You must have the following installed to compile $package:" echo "You must have the following installed to compile $package:"
...@@ -148,9 +125,6 @@ $ACLOCAL $ACLOCAL_FLAGS || exit 1 ...@@ -148,9 +125,6 @@ $ACLOCAL $ACLOCAL_FLAGS || exit 1
echo " $AUTOHEADER" echo " $AUTOHEADER"
$AUTOHEADER || exit 1 $AUTOHEADER || exit 1
echo " $LIBTOOLIZE --automake"
$LIBTOOLIZE --automake || exit 1
echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS" echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1 $AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
/* Define if FAAD2 uses buflen in function calls */ /* Define if FAAD2 uses buflen in function calls */
#undef HAVE_FAAD_BUFLEN_FUNCS #undef HAVE_FAAD_BUFLEN_FUNCS
/* Define if faad.h uses the broken "unsigned long" pointers */
#undef HAVE_FAAD_LONG
/* Define for FFMPEG support */ /* Define for FFMPEG support */
#undef HAVE_FFMPEG #undef HAVE_FFMPEG
......
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.63 for mpd 0.14~alpha3. # Generated by GNU Autoconf 2.63 for mpd 0.14~beta1.
# #
# Report bugs to <musicpd-dev-team@lists.sourceforge.net>. # Report bugs to <musicpd-dev-team@lists.sourceforge.net>.
# #
...@@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} ...@@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='mpd' PACKAGE_NAME='mpd'
PACKAGE_TARNAME='mpd' PACKAGE_TARNAME='mpd'
PACKAGE_VERSION='0.14~alpha3' PACKAGE_VERSION='0.14~beta1'
PACKAGE_STRING='mpd 0.14~alpha3' PACKAGE_STRING='mpd 0.14~beta1'
PACKAGE_BUGREPORT='musicpd-dev-team@lists.sourceforge.net' PACKAGE_BUGREPORT='musicpd-dev-team@lists.sourceforge.net'
ac_unique_file="src/main.c" ac_unique_file="src/main.c"
...@@ -639,6 +639,9 @@ ac_includes_default="\ ...@@ -639,6 +639,9 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS ac_subst_vars='LTLIBOBJS
LIBOBJS LIBOBJS
HAVE_XMLTO_FALSE
HAVE_XMLTO_TRUE
XMLTO
HAVE_ZEROCONF_FALSE HAVE_ZEROCONF_FALSE
HAVE_ZEROCONF_TRUE HAVE_ZEROCONF_TRUE
AVAHI_LIBS AVAHI_LIBS
...@@ -1478,7 +1481,7 @@ if test "$ac_init_help" = "long"; then ...@@ -1478,7 +1481,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures mpd 0.14~alpha3 to adapt to many kinds of systems. \`configure' configures mpd 0.14~beta1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
...@@ -1548,7 +1551,7 @@ fi ...@@ -1548,7 +1551,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of mpd 0.14~alpha3:";; short | recursive ) echo "Configuration of mpd 0.14~beta1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
...@@ -1746,7 +1749,7 @@ fi ...@@ -1746,7 +1749,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
mpd configure 0.14~alpha3 mpd configure 0.14~beta1
generated by GNU Autoconf 2.63 generated by GNU Autoconf 2.63
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
...@@ -1760,7 +1763,7 @@ cat >config.log <<_ACEOF ...@@ -1760,7 +1763,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by mpd $as_me 0.14~alpha3, which was It was created by mpd $as_me 0.14~beta1, which was
generated by GNU Autoconf 2.63. Invocation command line was generated by GNU Autoconf 2.63. Invocation command line was
$ $0 $@ $ $0 $@
...@@ -2457,7 +2460,7 @@ fi ...@@ -2457,7 +2460,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='mpd' PACKAGE='mpd'
VERSION='0.14~alpha3' VERSION='0.14~beta1'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
...@@ -9989,6 +9992,71 @@ fi ...@@ -9989,6 +9992,71 @@ fi
if test x$enable_aac = xyes; then if test x$enable_aac = xyes; then
oldcflags=$CFLAGS
oldlibs=$LIBS
oldcppflags=$CPPFLAGS
CFLAGS="$CFLAGS $MPD_CFLAGS $FAAD_CFLAGS -Werror"
LIBS="$LIBS $MPD_LIBS $FAAD_LIBS"
CPPFLAGS=$CFLAGS
{ $as_echo "$as_me:$LINENO: checking for broken libfaad headers" >&5
$as_echo_n "checking for broken libfaad headers... " >&6; }
cat >conftest.$ac_ext <<_ACEOF
#include <faad.h>
#include <stddef.h>
#include <stdint.h>
int main() {
unsigned char channels;
uint32_t sample_rate;
faacDecInit2(NULL, NULL, 0, &sample_rate, &channels);
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
{ $as_echo "$as_me:$LINENO: result: correct" >&5
$as_echo "correct" >&6; }
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ $as_echo "$as_me:$LINENO: result: broken" >&5
$as_echo "broken" >&6; };
cat >>confdefs.h <<\_ACEOF
#define HAVE_FAAD_LONG 1
_ACEOF
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$oldcflags
LIBS=$oldlibs
CPPFLAGS=$oldcppflags
fi
if test x$enable_aac = xyes; then
enable_mp4=yes enable_mp4=yes
MP4FF_LIBS="-lmp4ff" MP4FF_LIBS="-lmp4ff"
...@@ -11678,6 +11746,70 @@ fi ...@@ -11678,6 +11746,70 @@ fi
{ $as_echo "$as_me:$LINENO: checking for xmlto (DocBook processing)" >&5
$as_echo_n "checking for xmlto (DocBook processing)... " >&6; }
# Extract the first word of "xmlto", so it can be a program name with args.
set dummy xmlto; ac_word=$2
{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_path_XMLTO+set}" = set; then
$as_echo_n "(cached) " >&6
else
case $XMLTO in
[\\/]* | ?:[\\/]*)
ac_cv_path_XMLTO="$XMLTO" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_XMLTO="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
XMLTO=$ac_cv_path_XMLTO
if test -n "$XMLTO"; then
{ $as_echo "$as_me:$LINENO: result: $XMLTO" >&5
$as_echo "$XMLTO" >&6; }
else
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$XMLTO != x; then
{ $as_echo "$as_me:$LINENO: result: $XMLTO" >&5
$as_echo "$XMLTO" >&6; }
else
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$XMLTO != x; then
HAVE_XMLTO_TRUE=
HAVE_XMLTO_FALSE='#'
else
HAVE_XMLTO_TRUE='#'
HAVE_XMLTO_FALSE=
fi
if test "x$ENABLE_WERROR" = xyes; then if test "x$ENABLE_WERROR" = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -Werror -pedantic-errors" MPD_CFLAGS="$MPD_CFLAGS -Werror -pedantic-errors"
fi fi
...@@ -12615,6 +12747,13 @@ $as_echo "$as_me: error: conditional \"HAVE_ZEROCONF\" was never defined. ...@@ -12615,6 +12747,13 @@ $as_echo "$as_me: error: conditional \"HAVE_ZEROCONF\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;} Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; } { (exit 1); exit 1; }; }
fi fi
if test -z "${HAVE_XMLTO_TRUE}" && test -z "${HAVE_XMLTO_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"HAVE_XMLTO\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
$as_echo "$as_me: error: conditional \"HAVE_XMLTO\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
: ${CONFIG_STATUS=./config.status} : ${CONFIG_STATUS=./config.status}
ac_write_fail=0 ac_write_fail=0
...@@ -12937,7 +13076,7 @@ exec 6>&1 ...@@ -12937,7 +13076,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by mpd $as_me 0.14~alpha3, which was This file was extended by mpd $as_me 0.14~beta1, which was
generated by GNU Autoconf 2.63. Invocation command line was generated by GNU Autoconf 2.63. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
...@@ -13000,7 +13139,7 @@ Report bugs to <bug-autoconf@gnu.org>." ...@@ -13000,7 +13139,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\ ac_cs_version="\\
mpd config.status 0.14~alpha3 mpd config.status 0.14~beta1
configured by $0, generated by GNU Autoconf 2.63, configured by $0, generated by GNU Autoconf 2.63,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
......
AC_PREREQ(2.60) AC_PREREQ(2.60)
AC_INIT(mpd, 0.14~alpha3, musicpd-dev-team@lists.sourceforge.net) AC_INIT(mpd, 0.14~beta1, musicpd-dev-team@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2]) AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
...@@ -623,6 +623,37 @@ fi ...@@ -623,6 +623,37 @@ fi
AM_CONDITIONAL(HAVE_FAAD, test x$enable_aac = xyes) AM_CONDITIONAL(HAVE_FAAD, test x$enable_aac = xyes)
if test x$enable_aac = xyes; then if test x$enable_aac = xyes; then
oldcflags=$CFLAGS
oldlibs=$LIBS
oldcppflags=$CPPFLAGS
CFLAGS="$CFLAGS $MPD_CFLAGS $FAAD_CFLAGS -Werror"
LIBS="$LIBS $MPD_LIBS $FAAD_LIBS"
CPPFLAGS=$CFLAGS
AC_MSG_CHECKING(for broken libfaad headers)
AC_COMPILE_IFELSE([
#include <faad.h>
#include <stddef.h>
#include <stdint.h>
int main() {
unsigned char channels;
uint32_t sample_rate;
faacDecInit2(NULL, NULL, 0, &sample_rate, &channels);
return 0;
}
],
[AC_MSG_RESULT(correct)],
[AC_MSG_RESULT(broken);
AC_DEFINE(HAVE_FAAD_LONG, 1, [Define if faad.h uses the broken "unsigned long" pointers])])
CFLAGS=$oldcflags
LIBS=$oldlibs
CPPFLAGS=$oldcppflags
fi
if test x$enable_aac = xyes; then
enable_mp4=yes enable_mp4=yes
MP4FF_LIBS="-lmp4ff" MP4FF_LIBS="-lmp4ff"
...@@ -822,6 +853,22 @@ AM_CONDITIONAL(HAVE_ZEROCONF, test x$with_zeroconf != xno) ...@@ -822,6 +853,22 @@ AM_CONDITIONAL(HAVE_ZEROCONF, test x$with_zeroconf != xno)
dnl dnl
dnl Documentation
dnl
AC_MSG_CHECKING([for xmlto (DocBook processing)])
AC_PATH_PROG(XMLTO, xmlto)
if test x$XMLTO != x; then
AC_SUBST(XMLTO)
AC_MSG_RESULT($XMLTO)
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(HAVE_XMLTO, test x$XMLTO != x)
dnl
dnl build options dnl build options
dnl dnl
......
DOCBOOK_FILES = protocol.xml
DOCBOOK_HTML = $(patsubst %.xml,%.html,$(DOCBOOK_FILES))
man_MANS = mpd.1 mpd.conf.5 man_MANS = mpd.1 mpd.conf.5
doc_DATA = COMMANDS mpdconf.example doc_DATA = mpdconf.example
EXTRA_DIST = $(man_MANS) $(doc_DATA) EXTRA_DIST = $(man_MANS) $(DOCBOOK_FILES) mpdconf.example
MOSTLYCLEANFILES = $(DOCBOOK_HTML)
if HAVE_XMLTO
doc_DATA += $(DOCBOOK_HTML)
$(DOCBOOK_HTML): %.html: %.xml
$(XMLTO) html-nochunks $<
endif
...@@ -36,6 +36,7 @@ PRE_UNINSTALL = : ...@@ -36,6 +36,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = : POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
@HAVE_XMLTO_TRUE@am__append_1 = $(DOCBOOK_HTML)
subdir = doc subdir = doc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
...@@ -158,6 +159,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@ ...@@ -158,6 +159,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@ HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@ HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@ HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@ HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@ HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@ ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
...@@ -215,6 +218,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@ ...@@ -215,6 +218,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@ VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@ WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@ ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@ acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
...@@ -259,9 +263,12 @@ sbindir = @sbindir@ ...@@ -259,9 +263,12 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@ sysconfdir = @sysconfdir@
target_alias = @target_alias@ target_alias = @target_alias@
DOCBOOK_FILES = protocol.xml
DOCBOOK_HTML = $(patsubst %.xml,%.html,$(DOCBOOK_FILES))
man_MANS = mpd.1 mpd.conf.5 man_MANS = mpd.1 mpd.conf.5
doc_DATA = COMMANDS mpdconf.example doc_DATA = mpdconf.example $(am__append_1)
EXTRA_DIST = $(man_MANS) $(doc_DATA) EXTRA_DIST = $(man_MANS) $(DOCBOOK_FILES) mpdconf.example
MOSTLYCLEANFILES = $(DOCBOOK_HTML)
all: all-am all: all-am
.SUFFIXES: .SUFFIXES:
...@@ -458,6 +465,7 @@ install-strip: ...@@ -458,6 +465,7 @@ install-strip:
`test -z '$(STRIP)' || \ `test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic: mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic: clean-generic:
...@@ -526,6 +534,9 @@ uninstall-man: uninstall-man1 uninstall-man5 ...@@ -526,6 +534,9 @@ uninstall-man: uninstall-man1 uninstall-man5
uninstall-docDATA uninstall-info-am uninstall-man \ uninstall-docDATA uninstall-info-am uninstall-man \
uninstall-man1 uninstall-man5 uninstall-man1 uninstall-man5
@HAVE_XMLTO_TRUE@$(DOCBOOK_HTML): %.html: %.xml
@HAVE_XMLTO_TRUE@ $(XMLTO) html-nochunks $<
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# Generated from ltversion.in.
# serial 3012 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.2.6])
m4_define([LT_PACKAGE_REVISION], [1.3012])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.2.6'
macro_revision='1.3012'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 4 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
...@@ -315,6 +315,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@ ...@@ -315,6 +315,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@ HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@ HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@ HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@ HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@ HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@ ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
...@@ -372,6 +374,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@ ...@@ -372,6 +374,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@ VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@ WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@ ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@ acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
......
...@@ -40,6 +40,17 @@ static inline bool audio_format_defined(const struct audio_format *af) ...@@ -40,6 +40,17 @@ static inline bool audio_format_defined(const struct audio_format *af)
return af->sample_rate != 0; return af->sample_rate != 0;
} }
/**
* Returns false if the format is not valid for playback with MPD.
* This function performs some basic validity checks.
*/
static inline bool audio_format_valid(const struct audio_format *af)
{
return af->sample_rate > 0 &&
(af->bits == 8 || af->bits == 16 || af->bits == 24) &&
af->channels >= 1;
}
static inline bool audio_format_equals(const struct audio_format *a, static inline bool audio_format_equals(const struct audio_format *a,
const struct audio_format *b) const struct audio_format *b)
{ {
......
...@@ -91,6 +91,9 @@ struct client { ...@@ -91,6 +91,9 @@ struct client {
/** idle flags pending on this client, to be sent as soon as /** idle flags pending on this client, to be sent as soon as
the client enters "idle" */ the client enters "idle" */
unsigned idle_flags; unsigned idle_flags;
/** idle flags that the client wants to receive */
unsigned idle_subscriptions;
}; };
static LIST_HEAD(clients); static LIST_HEAD(clients);
...@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...) ...@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...)
va_end(args); va_end(args);
} }
static const char *const idle_names[] = {
"database",
"stored_playlist",
"playlist",
"player",
"mixer",
"output",
"options",
};
/** /**
* Send "idle" response to this client. * Send "idle" response to this client.
*/ */
...@@ -783,6 +776,7 @@ static void ...@@ -783,6 +776,7 @@ static void
client_idle_notify(struct client *client) client_idle_notify(struct client *client)
{ {
unsigned flags, i; unsigned flags, i;
const char *const* idle_names;
assert(client->idle_waiting); assert(client->idle_waiting);
assert(client->idle_flags != 0); assert(client->idle_flags != 0);
...@@ -791,10 +785,9 @@ client_idle_notify(struct client *client) ...@@ -791,10 +785,9 @@ client_idle_notify(struct client *client)
client->idle_flags = 0; client->idle_flags = 0;
client->idle_waiting = false; client->idle_waiting = false;
for (i = 0; i < sizeof(idle_names) / sizeof(idle_names[0]); ++i) { idle_names = idle_get_names();
assert(idle_names[i] != NULL); for (i = 0; idle_names[i]; ++i) {
if (flags & (1 << i) & client->idle_subscriptions)
if (flags & (1 << i))
client_printf(client, "changed: %s\n", client_printf(client, "changed: %s\n",
idle_names[i]); idle_names[i]);
} }
...@@ -814,20 +807,22 @@ void client_manager_idle_add(unsigned flags) ...@@ -814,20 +807,22 @@ void client_manager_idle_add(unsigned flags)
continue; continue;
client->idle_flags |= flags; client->idle_flags |= flags;
if (client->idle_waiting) { if (client->idle_waiting
&& (client->idle_flags & client->idle_subscriptions)) {
client_idle_notify(client); client_idle_notify(client);
client_write_output(client); client_write_output(client);
} }
} }
} }
bool client_idle_wait(struct client *client) bool client_idle_wait(struct client *client, unsigned flags)
{ {
assert(!client->idle_waiting); assert(!client->idle_waiting);
client->idle_waiting = true; client->idle_waiting = true;
client->idle_subscriptions = flags;
if (client->idle_flags != 0) { if (client->idle_flags & client->idle_subscriptions) {
client_idle_notify(client); client_idle_notify(client);
return true; return true;
} else } else
......
...@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags); ...@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags);
* sent immediately and "true" is returned". If no, it puts the * sent immediately and "true" is returned". If no, it puts the
* client into waiting mode and returns false. * client into waiting mode and returns false.
*/ */
bool client_idle_wait(struct client *client); bool client_idle_wait(struct client *client, unsigned flags);
#endif #endif
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "tag_print.h" #include "tag_print.h"
#include "path.h" #include "path.h"
#include "os_compat.h" #include "os_compat.h"
#include "idle.h"
#define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_STATE "state"
...@@ -204,7 +205,7 @@ print_playlist_result(struct client *client, ...@@ -204,7 +205,7 @@ print_playlist_result(struct client *client,
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
case PLAYLIST_RESULT_ERRNO: case PLAYLIST_RESULT_ERRNO:
command_error(client, ACK_ERROR_SYSTEM, strerror(errno)); command_error(client, ACK_ERROR_SYSTEM, "%s", strerror(errno));
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
case PLAYLIST_RESULT_DENIED: case PLAYLIST_RESULT_DENIED:
...@@ -1253,8 +1254,28 @@ static enum command_return ...@@ -1253,8 +1254,28 @@ static enum command_return
handle_idle(struct client *client, handle_idle(struct client *client,
mpd_unused int argc, mpd_unused char *argv[]) mpd_unused int argc, mpd_unused char *argv[])
{ {
unsigned flags = 0, j;
int i;
const char *const* idle_names;
idle_names = idle_get_names();
for (i = 1; i < argc; ++i) {
if (!argv[i])
continue;
for (j = 0; idle_names[j]; ++j) {
if (!strcasecmp(argv[i], idle_names[j])) {
flags |= (1 << j);
}
}
}
/* No argument means that the client wants to receive everything */
if (flags == 0)
flags = ~0;
/* enable "idle" mode on this client */ /* enable "idle" mode on this client */
client_idle_wait(client); client_idle_wait(client, flags);
/* return value is "1" so the caller won't print "OK" */ /* return value is "1" so the caller won't print "OK" */
return 1; return 1;
...@@ -1280,7 +1301,7 @@ static const struct command commands[] = { ...@@ -1280,7 +1301,7 @@ static const struct command commands[] = {
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput }, { "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput }, { "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
{ "find", PERMISSION_READ, 2, -1, handle_find }, { "find", PERMISSION_READ, 2, -1, handle_find },
{ "idle", PERMISSION_READ, 0, 0, handle_idle }, { "idle", PERMISSION_READ, 0, -1, handle_idle },
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill }, { "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
{ "list", PERMISSION_READ, 1, -1, handle_list }, { "list", PERMISSION_READ, 1, -1, handle_list },
{ "listall", PERMISSION_READ, 0, 1, handle_listall }, { "listall", PERMISSION_READ, 0, 1, handle_listall },
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
*/ */
#include "_flac_common.h" #include "_flac_common.h"
#include "../log.h"
#include <FLAC/format.h> #include <FLAC/format.h>
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
...@@ -177,16 +176,16 @@ void flac_error_common_cb(const char *plugin, ...@@ -177,16 +176,16 @@ void flac_error_common_cb(const char *plugin,
switch (status) { switch (status) {
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
ERROR("%s lost sync\n", plugin); g_warning("%s lost sync\n", plugin);
break; break;
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER: case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
ERROR("bad %s header\n", plugin); g_warning("bad %s header\n", plugin);
break; break;
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH: case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
ERROR("%s crc mismatch\n", plugin); g_warning("%s crc mismatch\n", plugin);
break; break;
default: default:
ERROR("unknown %s error\n", plugin); g_warning("unknown %s error\n", plugin);
} }
} }
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
#include "../decoder_api.h" #include "../decoder_api.h"
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "flac"
#include <FLAC/export.h> #include <FLAC/export.h>
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# include <FLAC/seekable_stream_decoder.h> # include <FLAC/seekable_stream_decoder.h>
......
...@@ -20,11 +20,13 @@ ...@@ -20,11 +20,13 @@
#define AAC_MAX_CHANNELS 6 #define AAC_MAX_CHANNELS 6
#include "../utils.h"
#include "../log.h"
#include <assert.h> #include <assert.h>
#include <unistd.h>
#include <faad.h> #include <faad.h>
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "aac"
/* all code here is either based on or copied from FAAD2's frontend code */ /* all code here is either based on or copied from FAAD2's frontend code */
typedef struct { typedef struct {
...@@ -186,7 +188,7 @@ static void aac_parse_header(AacBuffer * b, float *length) ...@@ -186,7 +188,7 @@ static void aac_parse_header(AacBuffer * b, float *length)
if (length) if (length)
*length = -1; *length = -1;
fileread = b->inStream->size; fileread = b->inStream->size >= 0 ? b->inStream->size : 0;
fillAacBuffer(b); fillAacBuffer(b);
...@@ -252,6 +254,14 @@ static float getAacFloatTotalTime(const char *file) ...@@ -252,6 +254,14 @@ static float getAacFloatTotalTime(const char *file)
faacDecHandle decoder; faacDecHandle decoder;
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
uint32_t sample_rate; uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels; unsigned char channels;
struct input_stream inStream; struct input_stream inStream;
long bread; long bread;
...@@ -272,9 +282,9 @@ static float getAacFloatTotalTime(const char *file) ...@@ -272,9 +282,9 @@ static float getAacFloatTotalTime(const char *file)
fillAacBuffer(&b); fillAacBuffer(&b);
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer, bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sample_rate, &channels); sample_rate_r, &channels);
#else #else
bread = faacDecInit(decoder, b.buffer, &sample_rate, &channels); bread = faacDecInit(decoder, b.buffer, sample_rate_r, &channels);
#endif #endif
if (bread >= 0 && sample_rate > 0 && channels > 0) if (bread >= 0 && sample_rate > 0 && channels > 0)
length = 0; length = 0;
...@@ -282,8 +292,6 @@ static float getAacFloatTotalTime(const char *file) ...@@ -282,8 +292,6 @@ static float getAacFloatTotalTime(const char *file)
faacDecClose(decoder); faacDecClose(decoder);
} }
if (b.buffer)
free(b.buffer);
input_stream_close(&inStream); input_stream_close(&inStream);
return length; return length;
...@@ -310,6 +318,14 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream) ...@@ -310,6 +318,14 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
long bread; long bread;
uint32_t sample_rate; uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels; unsigned char channels;
unsigned int sampleCount; unsigned int sampleCount;
char *sampleBuffer; char *sampleBuffer;
...@@ -340,20 +356,17 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream) ...@@ -340,20 +356,17 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
fillAacBuffer(&b); fillAacBuffer(&b);
adts_find_frame(&b); adts_find_frame(&b);
fillAacBuffer(&b); fillAacBuffer(&b);
my_usleep(10000);
} }
#ifdef HAVE_FAAD_BUFLEN_FUNCS #ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer, bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sample_rate, &channels); sample_rate_r, &channels);
#else #else
bread = faacDecInit(decoder, b.buffer, &sample_rate, &channels); bread = faacDecInit(decoder, b.buffer, sample_rate_r, &channels);
#endif #endif
if (bread < 0) { if (bread < 0) {
ERROR("Error not a AAC stream.\n"); g_warning("Error not a AAC stream.\n");
faacDecClose(decoder); faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
return; return;
} }
...@@ -377,9 +390,8 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream) ...@@ -377,9 +390,8 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
#endif #endif
if (frameInfo.error > 0) { if (frameInfo.error > 0) {
ERROR("error decoding AAC stream\n"); g_warning("error decoding AAC stream: %s\n",
ERROR("faad2 error: %s\n", faacDecGetErrorMessage(frameInfo.error));
faacDecGetErrorMessage(frameInfo.error));
break; break;
} }
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE #ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
...@@ -393,6 +405,11 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream) ...@@ -393,6 +405,11 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
.sample_rate = sample_rate, .sample_rate = sample_rate,
}; };
if (!audio_format_valid(&audio_format)) {
g_warning("aac: invalid audio format\n");
break;
}
decoder_initialized(mpd_decoder, &audio_format, decoder_initialized(mpd_decoder, &audio_format,
false, totalTime); false, totalTime);
initialized = true; initialized = true;
...@@ -433,8 +450,8 @@ static struct tag *aacTagDup(const char *file) ...@@ -433,8 +450,8 @@ static struct tag *aacTagDup(const char *file)
ret = tag_new(); ret = tag_new();
ret->time = file_time; ret->time = file_time;
} else { } else {
DEBUG("aacTagDup: Failed to get total song time from: %s\n", g_debug("aacTagDup: Failed to get total song time from: %s\n",
file); file);
} }
return ret; return ret;
......
...@@ -19,10 +19,13 @@ ...@@ -19,10 +19,13 @@
*/ */
#include "../decoder_api.h" #include "../decoder_api.h"
#include "../log.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <audiofile.h> #include <audiofile.h>
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "audiofile"
/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */ /* pick 1020 since its devisible for 8,16,24, and 32-bit audio */
#define CHUNK_SIZE 1020 #define CHUNK_SIZE 1020
...@@ -55,13 +58,13 @@ audiofile_decode(struct decoder *decoder, const char *path) ...@@ -55,13 +58,13 @@ audiofile_decode(struct decoder *decoder, const char *path)
char chunk[CHUNK_SIZE]; char chunk[CHUNK_SIZE];
if (stat(path, &st) < 0) { if (stat(path, &st) < 0) {
ERROR("failed to stat: %s\n", path); g_warning("failed to stat: %s\n", path);
return; return;
} }
af_fp = afOpenFile(path, "r", NULL); af_fp = afOpenFile(path, "r", NULL);
if (af_fp == AF_NULL_FILEHANDLE) { if (af_fp == AF_NULL_FILEHANDLE) {
ERROR("failed to open: %s\n", path); g_warning("failed to open: %s\n", path);
return; return;
} }
...@@ -74,19 +77,20 @@ audiofile_decode(struct decoder *decoder, const char *path) ...@@ -74,19 +77,20 @@ audiofile_decode(struct decoder *decoder, const char *path)
audio_format.channels = audio_format.channels =
(uint8_t)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK); (uint8_t)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK);
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
afCloseFile(af_fp);
return;
}
frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK); frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
total_time = ((float)frame_count / (float)audio_format.sample_rate); total_time = ((float)frame_count / (float)audio_format.sample_rate);
bitRate = (uint16_t)(st.st_size * 8.0 / total_time / 1000.0 + 0.5); bitRate = (uint16_t)(st.st_size * 8.0 / total_time / 1000.0 + 0.5);
if (audio_format.bits != 8 && audio_format.bits != 16) {
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
path, audio_format.bits);
afCloseFile(af_fp);
return;
}
fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
decoder_initialized(decoder, &audio_format, true, total_time); decoder_initialized(decoder, &audio_format, true, total_time);
...@@ -120,13 +124,11 @@ static struct tag *audiofileTagDup(const char *file) ...@@ -120,13 +124,11 @@ static struct tag *audiofileTagDup(const char *file)
int total_time = getAudiofileTotalTime(file); int total_time = getAudiofileTotalTime(file);
if (total_time >= 0) { if (total_time >= 0) {
if (!ret) ret = tag_new();
ret = tag_new();
ret->time = total_time; ret->time = total_time;
} else { } else {
DEBUG g_debug("Failed to get total song time from: %s\n",
("audiofileTagDup: Failed to get total song time from: %s\n", file);
file);
} }
return ret; return ret;
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
*/ */
#include "../decoder_api.h" #include "../decoder_api.h"
#include "../log.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
...@@ -27,6 +26,7 @@ ...@@ -27,6 +26,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <glib.h>
#ifdef OLD_FFMPEG_INCLUDES #ifdef OLD_FFMPEG_INCLUDES
#include <avcodec.h> #include <avcodec.h>
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
#include <libavformat/avio.h> #include <libavformat/avio.h>
#endif #endif
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "ffmpeg"
struct ffmpeg_context { struct ffmpeg_context {
int audio_stream; int audio_stream;
AVFormatContext *format_context; AVFormatContext *format_context;
...@@ -89,9 +92,15 @@ static int mpd_ffmpeg_read(URLContext *h, unsigned char *buf, int size) ...@@ -89,9 +92,15 @@ static int mpd_ffmpeg_read(URLContext *h, unsigned char *buf, int size)
static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence) static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence)
{ {
struct ffmpeg_stream *stream = (struct ffmpeg_stream *) h->priv_data; struct ffmpeg_stream *stream = (struct ffmpeg_stream *) h->priv_data;
if (whence != AVSEEK_SIZE) { //only ftell bool ret;
(void) input_stream_seek(stream->input, pos, whence);
} if (whence == AVSEEK_SIZE)
return stream->input->size;
ret = input_stream_seek(stream->input, pos, whence);
if (!ret)
return -1;
return stream->input->offset; return stream->input->offset;
} }
...@@ -150,18 +159,18 @@ ffmpeg_helper(struct input_stream *input, ...@@ -150,18 +159,18 @@ ffmpeg_helper(struct input_stream *input,
//ffmpeg works with ours "fileops" helper //ffmpeg works with ours "fileops" helper
if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) { if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) {
ERROR("Open failed!\n"); g_warning("Open failed\n");
return false; return false;
} }
if (av_find_stream_info(format_context)<0) { if (av_find_stream_info(format_context)<0) {
ERROR("Couldn't find stream info!\n"); g_warning("Couldn't find stream info\n");
return false; return false;
} }
audio_stream = ffmpeg_find_audio_stream(format_context); audio_stream = ffmpeg_find_audio_stream(format_context);
if (audio_stream == -1) { if (audio_stream == -1) {
ERROR("No audio stream inside!\n"); g_warning("No audio stream inside\n");
return false; return false;
} }
...@@ -169,12 +178,12 @@ ffmpeg_helper(struct input_stream *input, ...@@ -169,12 +178,12 @@ ffmpeg_helper(struct input_stream *input,
codec = avcodec_find_decoder(codec_context->codec_id); codec = avcodec_find_decoder(codec_context->codec_id);
if (!codec) { if (!codec) {
ERROR("Unsupported audio codec!\n"); g_warning("Unsupported audio codec\n");
return false; return false;
} }
if (avcodec_open(codec_context, codec)<0) { if (avcodec_open(codec_context, codec)<0) {
ERROR("Could not open codec!\n"); g_warning("Could not open codec\n");
return false; return false;
} }
...@@ -213,7 +222,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, ...@@ -213,7 +222,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
packet->data, packet->size); packet->data, packet->size);
if (len < 0) { if (len < 0) {
WARNING("skipping frame!\n"); g_message("skipping frame\n");
return decoder_get_command(decoder); return decoder_get_command(decoder);
} }
...@@ -246,6 +255,13 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) ...@@ -246,6 +255,13 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
audio_format.sample_rate = (unsigned int)codec_context->sample_rate; audio_format.sample_rate = (unsigned int)codec_context->sample_rate;
audio_format.channels = codec_context->channels; audio_format.channels = codec_context->channels;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
return false;
}
//there is some problem with this on some demux (mp3 at least) //there is some problem with this on some demux (mp3 at least)
if (format_context->duration != (int)AV_NOPTS_VALUE) { if (format_context->duration != (int)AV_NOPTS_VALUE) {
total_time = format_context->duration / AV_TIME_BASE; total_time = format_context->duration / AV_TIME_BASE;
...@@ -295,11 +311,22 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) ...@@ -295,11 +311,22 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx) static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
{ {
struct tag *tag = (struct tag *) ctx->tag; struct tag *tag = (struct tag *) ctx->tag;
const AVFormatContext *f = ctx->format_context;
if (ctx->format_context->duration != (int)AV_NOPTS_VALUE) {
tag->time = ctx->format_context->duration / AV_TIME_BASE; tag->time = 0;
} else { if (f->duration != (int)AV_NOPTS_VALUE)
tag->time = 0; tag->time = f->duration / AV_TIME_BASE;
if (f->author[0])
tag_add_item(tag, TAG_ITEM_ARTIST, f->author);
if (f->title[0])
tag_add_item(tag, TAG_ITEM_TITLE, f->title);
if (f->album[0])
tag_add_item(tag, TAG_ITEM_ALBUM, f->album);
if (f->track > 0) {
char buffer[16];
snprintf(buffer, sizeof(buffer), "%d", f->track);
tag_add_item(tag, TAG_ITEM_TRACK, buffer);
} }
return true; return true;
...@@ -313,7 +340,7 @@ static struct tag *ffmpeg_tag(const char *file) ...@@ -313,7 +340,7 @@ static struct tag *ffmpeg_tag(const char *file)
bool ret; bool ret;
if (!input_stream_open(&input, file)) { if (!input_stream_open(&input, file)) {
ERROR("failed to open %s\n", file); g_warning("failed to open %s\n", file);
return NULL; return NULL;
} }
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
*/ */
#include "_flac_common.h" #include "_flac_common.h"
#include "../utils.h"
#include "../log.h"
#include <assert.h> #include <assert.h>
...@@ -75,6 +73,9 @@ static flac_length_status flacLength(mpd_unused const flac_decoder * flacDec, ...@@ -75,6 +73,9 @@ static flac_length_status flacLength(mpd_unused const flac_decoder * flacDec,
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
if (data->inStream->size < 0)
return flac_length_status_unsupported;
*length = (size_t) (data->inStream->size); *length = (size_t) (data->inStream->size);
return flac_length_status_ok; return flac_length_status_ok;
...@@ -125,7 +126,8 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) ...@@ -125,7 +126,8 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
str = "decoder uninitialized"; str = "decoder uninitialized";
} }
ERROR("flac %s\n", str);
g_warning("%s\n", str);
} }
static int flac_init(FLAC__SeekableStreamDecoder *dec, static int flac_init(FLAC__SeekableStreamDecoder *dec,
...@@ -183,7 +185,8 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state) ...@@ -183,7 +185,8 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state)
case FLAC__STREAM_DECODER_UNINITIALIZED: case FLAC__STREAM_DECODER_UNINITIALIZED:
str = "decoder uninitialized"; str = "decoder uninitialized";
} }
ERROR("flac %s\n", str);
g_warning("%s\n", str);
} }
#endif /* FLAC_API_VERSION_CURRENT >= 7 */ #endif /* FLAC_API_VERSION_CURRENT >= 7 */
...@@ -248,9 +251,8 @@ flacMetadataDup(const char *file, bool *vorbisCommentFound) ...@@ -248,9 +251,8 @@ flacMetadataDup(const char *file, bool *vorbisCommentFound)
default: default:
err = FLAC__Metadata_SimpleIteratorStatusString[s]; err = FLAC__Metadata_SimpleIteratorStatusString[s];
} }
DEBUG("flacMetadataDup: Reading '%s' " g_debug("Reading '%s' metadata gave the following error: %s\n",
"metadata gave the following error: %s\n", file, err);
file, err);
FLAC__metadata_simple_iterator_delete(it); FLAC__metadata_simple_iterator_delete(it);
return ret; return ret;
} }
...@@ -285,8 +287,7 @@ static struct tag *flacTagDup(const char *file) ...@@ -285,8 +287,7 @@ static struct tag *flacTagDup(const char *file)
ret = flacMetadataDup(file, &foundVorbisComment); ret = flacMetadataDup(file, &foundVorbisComment);
if (!ret) { if (!ret) {
DEBUG("flacTagDup: Failed to grab information from: %s\n", g_debug("Failed to grab information from: %s\n", file);
file);
return NULL; return NULL;
} }
if (!foundVorbisComment) { if (!foundVorbisComment) {
...@@ -316,7 +317,7 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream, ...@@ -316,7 +317,7 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 #if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
if(!FLAC__stream_decoder_set_metadata_respond(flacDec, FLAC__METADATA_TYPE_VORBIS_COMMENT)) if(!FLAC__stream_decoder_set_metadata_respond(flacDec, FLAC__METADATA_TYPE_VORBIS_COMMENT))
{ {
DEBUG(__FILE__": Failed to set metadata respond\n"); g_debug("Failed to set metadata respond\n");
} }
#endif #endif
...@@ -342,6 +343,14 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream, ...@@ -342,6 +343,14 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
goto fail; goto fail;
} }
if (!audio_format_valid(&data.audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
data.audio_format.sample_rate,
data.audio_format.bits,
data.audio_format.channels);
goto fail;
}
decoder_initialized(decoder, &data.audio_format, decoder_initialized(decoder, &data.audio_format,
inStream->seekable, data.total_time); inStream->seekable, data.total_time);
...@@ -373,11 +382,8 @@ fail: ...@@ -373,11 +382,8 @@ fail:
if (flacDec) if (flacDec)
flac_delete(flacDec); flac_delete(flacDec);
if (err) { if (err)
ERROR("flac %s\n", err); g_warning("%s\n", err);
return;
}
return;
} }
static void static void
......
...@@ -112,6 +112,14 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) ...@@ -112,6 +112,14 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
unsigned char *mp4_buffer; unsigned char *mp4_buffer;
unsigned int mp4_buffer_size; unsigned int mp4_buffer_size;
uint32_t sample_rate; uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long*)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels; unsigned char channels;
long sample_id; long sample_id;
long num_samples; long num_samples;
...@@ -160,7 +168,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) ...@@ -160,7 +168,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
mp4ff_get_decoder_config(mp4fh, track, &mp4_buffer, &mp4_buffer_size); mp4ff_get_decoder_config(mp4fh, track, &mp4_buffer, &mp4_buffer_size);
if (faacDecInit2(decoder, mp4_buffer, mp4_buffer_size, if (faacDecInit2(decoder, mp4_buffer, mp4_buffer_size,
&sample_rate, &channels) < 0) { sample_rate_r, &channels) < 0) {
g_warning("Not an AAC stream.\n"); g_warning("Not an AAC stream.\n");
faacDecClose(decoder); faacDecClose(decoder);
mp4ff_close(mp4fh); mp4ff_close(mp4fh);
...@@ -267,6 +275,15 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) ...@@ -267,6 +275,15 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
scale = frame_info.samplerate; scale = frame_info.samplerate;
#endif #endif
audio_format.sample_rate = scale; audio_format.sample_rate = scale;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
break;
}
decoder_initialized(mpd_decoder, &audio_format, decoder_initialized(mpd_decoder, &audio_format,
input_stream->seekable, input_stream->seekable,
total_time); total_time);
......
...@@ -155,6 +155,14 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream) ...@@ -155,6 +155,14 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
audio_format.channels = info.channels; audio_format.channels = info.channels;
audio_format.sample_rate = info.sample_freq; audio_format.sample_rate = info.sample_freq;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
return;
}
replayGainInfo = replay_gain_info_new(); replayGainInfo = replay_gain_info_new();
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01; replayGainInfo->tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01;
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0; replayGainInfo->tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0;
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "_flac_common.h" #include "_flac_common.h"
#include "_ogg_common.h" #include "_ogg_common.h"
#include "../utils.h"
#include "../log.h"
#include <OggFLAC/seekable_stream_decoder.h> #include <OggFLAC/seekable_stream_decoder.h>
static void oggflac_cleanup(FlacData * data, static void oggflac_cleanup(FlacData * data,
...@@ -92,6 +89,9 @@ static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(mpd_unused const ...@@ -92,6 +89,9 @@ static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(mpd_unused const
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
if (data->inStream->size < 0)
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
*length = (size_t) (data->inStream->size); *length = (size_t) (data->inStream->size);
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
...@@ -117,25 +117,25 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state) ...@@ -117,25 +117,25 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
{ {
switch (state) { switch (state) {
case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR("oggflac allocation error\n"); g_warning("oggflac allocation error\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: case OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR:
ERROR("oggflac read error\n"); g_warning("oggflac read error\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: case OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR:
ERROR("oggflac seek error\n"); g_warning("oggflac seek error\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: case OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR:
ERROR("oggflac seekable stream error\n"); g_warning("oggflac seekable stream error\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: case OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED:
ERROR("oggflac decoder already initialized\n"); g_warning("oggflac decoder already initialized\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: case OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK:
ERROR("invalid oggflac callback\n"); g_warning("invalid oggflac callback\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: case OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
ERROR("oggflac decoder uninitialized\n"); g_warning("oggflac decoder uninitialized\n");
break; break;
case OggFLAC__SEEKABLE_STREAM_DECODER_OK: case OggFLAC__SEEKABLE_STREAM_DECODER_OK:
case OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING: case OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING:
...@@ -230,17 +230,17 @@ static OggFLAC__SeekableStreamDecoder ...@@ -230,17 +230,17 @@ static OggFLAC__SeekableStreamDecoder
(void *)data); (void *)data);
if (!s) { if (!s) {
ERROR("oggflac problem before init()\n"); g_warning("oggflac problem before init()\n");
goto fail; goto fail;
} }
if (OggFLAC__seekable_stream_decoder_init(decoder) != if (OggFLAC__seekable_stream_decoder_init(decoder) !=
OggFLAC__SEEKABLE_STREAM_DECODER_OK) { OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
ERROR("oggflac problem doing init()\n"); g_warning("oggflac problem doing init()\n");
goto fail; goto fail;
} }
if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata
(decoder)) { (decoder)) {
ERROR("oggflac problem reading metadata\n"); g_warning("oggflac problem reading metadata\n");
goto fail; goto fail;
} }
...@@ -294,6 +294,14 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream) ...@@ -294,6 +294,14 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream)
goto fail; goto fail;
} }
if (!audio_format_valid(&data.audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
data.audio_format.sample_rate,
data.audio_format.bits,
data.audio_format.channels);
goto fail;
}
decoder_initialized(mpd_decoder, &data.audio_format, decoder_initialized(mpd_decoder, &data.audio_format,
inStream->seekable, data.total_time); inStream->seekable, data.total_time);
......
...@@ -214,7 +214,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) ...@@ -214,7 +214,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
long test; long test;
struct replay_gain_info *replayGainInfo = NULL; struct replay_gain_info *replayGainInfo = NULL;
char **comments; char **comments;
const char *errorStr;
bool initialized = false; bool initialized = false;
enum decoder_command cmd = DECODE_COMMAND_NONE; enum decoder_command cmd = DECODE_COMMAND_NONE;
...@@ -233,6 +232,8 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) ...@@ -233,6 +232,8 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
callbacks.close_func = ogg_close_cb; callbacks.close_func = ogg_close_cb;
callbacks.tell_func = ogg_tell_cb; callbacks.tell_func = ogg_tell_cb;
if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) { if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
const char *errorStr;
if (decoder_get_command(decoder) != DECODE_COMMAND_NONE) if (decoder_get_command(decoder) != DECODE_COMMAND_NONE)
return; return;
...@@ -274,6 +275,12 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) ...@@ -274,6 +275,12 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
ret = ov_read(&vf, chunk, sizeof(chunk), ret = ov_read(&vf, chunk, sizeof(chunk),
OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section); OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
if (ret == OV_HOLE) /* bad packet */
ret = 0;
else if (ret <= 0)
/* break on EOF or other error */
break;
if (current_section != prev_section) { if (current_section != prev_section) {
/*printf("new song!\n"); */ /*printf("new song!\n"); */
vorbis_info *vi = ov_info(&vf, -1); vorbis_info *vi = ov_info(&vf, -1);
...@@ -281,6 +288,15 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) ...@@ -281,6 +288,15 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
audio_format.channels = vi->channels; audio_format.channels = vi->channels;
audio_format.sample_rate = vi->rate; audio_format.sample_rate = vi->rate;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
break;
}
if (!initialized) { if (!initialized) {
float total_time = ov_time_total(&vf, -1); float total_time = ov_time_total(&vf, -1);
if (total_time < 0) if (total_time < 0)
...@@ -303,13 +319,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) ...@@ -303,13 +319,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
prev_section = current_section; prev_section = current_section;
if (ret <= 0) {
if (ret == OV_HOLE) /* bad packet */
ret = 0;
else /* break on EOF or other error */
break;
}
if ((test = ov_bitrate_instant(&vf)) > 0) if ((test = ov_bitrate_instant(&vf)) > 0)
bitRate = test / 1000; bitRate = test / 1000;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "../decoder_api.h" #include "../decoder_api.h"
#include "../path.h" #include "../path.h"
#include "../utils.h"
#include <wavpack/wavpack.h> #include <wavpack/wavpack.h>
#include <glib.h> #include <glib.h>
...@@ -71,7 +72,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) ...@@ -71,7 +72,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
* of the output samples never can be greater than the size * of the output samples never can be greater than the size
* of the input ones. Otherwise we would have an overflow. * of the input ones. Otherwise we would have an overflow.
*/ */
assert(sizeof(uchar) <= sizeof(uint32_t)); assert_static(sizeof(*dst) <= sizeof(*src));
/* pass through and align 8-bit samples */ /* pass through and align 8-bit samples */
while (count--) { while (count--) {
...@@ -81,7 +82,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) ...@@ -81,7 +82,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
} }
case 2: { case 2: {
uint16_t *dst = buffer; uint16_t *dst = buffer;
assert(sizeof(uint16_t) <= sizeof(uint32_t)); assert_static(sizeof(*dst) <= sizeof(*src));
/* pass through and align 16-bit samples */ /* pass through and align 16-bit samples */
while (count--) { while (count--) {
...@@ -94,7 +95,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) ...@@ -94,7 +95,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
break; break;
case 4: { case 4: {
uint32_t *dst = buffer; uint32_t *dst = buffer;
assert(sizeof(uint32_t) <= sizeof(uint32_t)); assert_static(sizeof(*dst) <= sizeof(*src));
/* downsample to 24-bit */ /* downsample to 24-bit */
while (count--) { while (count--) {
...@@ -114,7 +115,7 @@ format_samples_float(mpd_unused int bytes_per_sample, void *buffer, ...@@ -114,7 +115,7 @@ format_samples_float(mpd_unused int bytes_per_sample, void *buffer,
{ {
int32_t *dst = buffer; int32_t *dst = buffer;
float *src = buffer; float *src = buffer;
assert(sizeof(int32_t) <= sizeof(float)); assert_static(sizeof(*dst) <= sizeof(*src));
while (count--) { while (count--) {
*dst++ = (int32_t)(*src++ + 0.5f); *dst++ = (int32_t)(*src++ + 0.5f);
...@@ -148,6 +149,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, ...@@ -148,6 +149,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
audio_format.bits = 24; audio_format.bits = 24;
} }
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
return;
}
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) { if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) {
format_samples = format_samples_float; format_samples = format_samples_float;
} else { } else {
...@@ -157,12 +166,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, ...@@ -157,12 +166,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
total_time = WavpackGetNumSamples(wpc); total_time = WavpackGetNumSamples(wpc);
total_time /= audio_format.sample_rate; total_time /= audio_format.sample_rate;
bytes_per_sample = WavpackGetBytesPerSample(wpc); bytes_per_sample = WavpackGetBytesPerSample(wpc);
output_sample_size = audio_format_frame_size(&audio_format);
output_sample_size = bytes_per_sample;
if (output_sample_size == 3) {
output_sample_size = 4;
}
output_sample_size *= audio_format.channels;
/* wavpack gives us all kind of samples in a 32-bit space */ /* wavpack gives us all kind of samples in a 32-bit space */
samples_requested = sizeof(chunk) / (4 * audio_format.channels); samples_requested = sizeof(chunk) / (4 * audio_format.channels);
...@@ -410,6 +414,9 @@ wavpack_input_push_back_byte(void *id, int c) ...@@ -410,6 +414,9 @@ wavpack_input_push_back_byte(void *id, int c)
static uint32_t static uint32_t
wavpack_input_get_length(void *id) wavpack_input_get_length(void *id)
{ {
if (wpin(id)->is->size < 0)
return 0;
return wpin(id)->is->size; return wpin(id)->is->size;
} }
......
...@@ -40,6 +40,7 @@ void decoder_initialized(struct decoder * decoder, ...@@ -40,6 +40,7 @@ void decoder_initialized(struct decoder * decoder,
assert(!decoder->seeking); assert(!decoder->seeking);
assert(audio_format != NULL); assert(audio_format != NULL);
assert(audio_format_defined(audio_format)); assert(audio_format_defined(audio_format));
assert(audio_format_valid(audio_format));
pcm_convert_init(&decoder->conv_state); pcm_convert_init(&decoder->conv_state);
...@@ -106,6 +107,9 @@ size_t decoder_read(struct decoder *decoder, ...@@ -106,6 +107,9 @@ size_t decoder_read(struct decoder *decoder,
assert(is != NULL); assert(is != NULL);
assert(buffer != NULL); assert(buffer != NULL);
if (length == 0)
return 0;
while (true) { while (true) {
/* XXX don't allow decoder==NULL */ /* XXX don't allow decoder==NULL */
if (decoder != NULL && if (decoder != NULL &&
...@@ -191,7 +195,8 @@ decoder_data(struct decoder *decoder, ...@@ -191,7 +195,8 @@ decoder_data(struct decoder *decoder,
assert(dc.state == DECODE_STATE_DECODE); assert(dc.state == DECODE_STATE_DECODE);
if (dc.command == DECODE_COMMAND_STOP || if (dc.command == DECODE_COMMAND_STOP ||
dc.command == DECODE_COMMAND_SEEK) dc.command == DECODE_COMMAND_SEEK ||
length == 0)
return dc.command; return dc.command;
if (is != NULL && !decoder->stream_tag_sent) { if (is != NULL && !decoder->stream_tag_sent) {
...@@ -229,13 +234,14 @@ decoder_data(struct decoder *decoder, ...@@ -229,13 +234,14 @@ decoder_data(struct decoder *decoder,
if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) { if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
data = _data; data = _data;
} else { } else {
length = pcm_convert_size(&dc.in_audio_format, length, size_t out_length =
&dc.out_audio_format); pcm_convert_size(&dc.in_audio_format, length,
if (length > conv_buffer_size) { &dc.out_audio_format);
if (out_length > conv_buffer_size) {
if (conv_buffer != NULL) if (conv_buffer != NULL)
free(conv_buffer); free(conv_buffer);
conv_buffer = xmalloc(length); conv_buffer = xmalloc(out_length);
conv_buffer_size = length; conv_buffer_size = out_length;
} }
data = conv_buffer; data = conv_buffer;
......
...@@ -109,7 +109,7 @@ static void decoder_run(void) ...@@ -109,7 +109,7 @@ static void decoder_run(void)
will be available then */ will be available then */
while (!input_stream.ready) { while (!input_stream.ready) {
if (dc.command != DECODE_COMMAND_NONE) { if (dc.command == DECODE_COMMAND_STOP) {
input_stream_close(&input_stream); input_stream_close(&input_stream);
dc.state = DECODE_STATE_STOP; dc.state = DECODE_STATE_STOP;
return; return;
......
...@@ -30,6 +30,18 @@ ...@@ -30,6 +30,18 @@
static unsigned idle_flags; static unsigned idle_flags;
static pthread_mutex_t idle_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t idle_mutex = PTHREAD_MUTEX_INITIALIZER;
static const char *const idle_names[] = {
"database",
"stored_playlist",
"playlist",
"player",
"mixer",
"output",
"options",
"elapsed",
NULL
};
void void
idle_add(unsigned flags) idle_add(unsigned flags)
{ {
...@@ -54,3 +66,9 @@ idle_get(void) ...@@ -54,3 +66,9 @@ idle_get(void)
return flags; return flags;
} }
const char*const*
idle_get_names(void)
{
return idle_names;
}
...@@ -61,4 +61,10 @@ idle_add(unsigned flags); ...@@ -61,4 +61,10 @@ idle_add(unsigned flags);
unsigned unsigned
idle_get(void); idle_get(void);
/**
* Get idle names
*/
const char*const*
idle_get_names(void);
#endif #endif
...@@ -155,12 +155,14 @@ input_curl_multi_info_read(struct input_stream *is) ...@@ -155,12 +155,14 @@ input_curl_multi_info_read(struct input_stream *is)
while ((msg = curl_multi_info_read(c->multi, while ((msg = curl_multi_info_read(c->multi,
&msgs_in_queue)) != NULL) { &msgs_in_queue)) != NULL) {
if (msg->msg == CURLMSG_DONE && if (msg->msg == CURLMSG_DONE) {
msg->data.result != CURLE_OK) {
g_warning("curl failed: %s\n", c->error);
is->error = -1;
c->eof = true; c->eof = true;
return false;
if (msg->data.result != CURLE_OK) {
g_warning("curl failed: %s\n", c->error);
is->error = -1;
return false;
}
} }
} }
...@@ -205,6 +207,31 @@ input_curl_select(struct input_curl *c) ...@@ -205,6 +207,31 @@ input_curl_select(struct input_curl *c)
return ret; return ret;
} }
/**
* Mark a part of the buffer object as consumed.
*/
static void
consume_buffer(struct buffer *buffer, size_t length,
struct list_head *rewind_head)
{
assert(buffer != NULL);
assert(buffer->consumed < buffer->size);
buffer->consumed += length;
if (buffer->consumed < buffer->size)
return;
assert(buffer->consumed == buffer->size);
list_del(&buffer->siblings);
if (rewind_head != NULL)
/* append this buffer to the rewind buffer list */
list_add_tail(&buffer->siblings, rewind_head);
else
g_free(buffer);
}
static size_t static size_t
read_from_buffer(struct buffer *buffer, void *dest, size_t length, read_from_buffer(struct buffer *buffer, void *dest, size_t length,
struct list_head *rewind_head) struct list_head *rewind_head)
...@@ -216,18 +243,7 @@ read_from_buffer(struct buffer *buffer, void *dest, size_t length, ...@@ -216,18 +243,7 @@ read_from_buffer(struct buffer *buffer, void *dest, size_t length,
length = buffer->size - buffer->consumed; length = buffer->size - buffer->consumed;
memcpy(dest, buffer->data + buffer->consumed, length); memcpy(dest, buffer->data + buffer->consumed, length);
consume_buffer(buffer, length, rewind_head);
buffer->consumed += length;
if (buffer->consumed == buffer->size) {
list_del(&buffer->siblings);
if (rewind_head != NULL)
/* append this buffer to the rewind buffer list */
list_add_tail(&buffer->siblings, rewind_head);
else
g_free(buffer);
}
return length; return length;
} }
...@@ -266,8 +282,6 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) ...@@ -266,8 +282,6 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size)
bret = input_curl_multi_info_read(is); bret = input_curl_multi_info_read(is);
if (!bret) if (!bret)
return 0; return 0;
c->eof = running_handles == 0;
} }
/* send buffer contents */ /* send buffer contents */
...@@ -345,8 +359,6 @@ input_curl_buffer(struct input_stream *is) ...@@ -345,8 +359,6 @@ input_curl_buffer(struct input_stream *is)
if (!ret) if (!ret)
return -1; return -1;
c->eof = running_handles == 0;
return c->buffered; return c->buffered;
} }
...@@ -480,8 +492,6 @@ input_curl_send_request(struct input_curl *c) ...@@ -480,8 +492,6 @@ input_curl_send_request(struct input_curl *c)
mcode = curl_multi_perform(c->multi, &running_handles); mcode = curl_multi_perform(c->multi, &running_handles);
} while (mcode == CURLM_CALL_MULTI_PERFORM); } while (mcode == CURLM_CALL_MULTI_PERFORM);
c->eof = running_handles == 0;
if (mcode != CURLM_OK) { if (mcode != CURLM_OK) {
g_warning("curl_multi_perform() failed: %s\n", g_warning("curl_multi_perform() failed: %s\n",
curl_multi_strerror(mcode)); curl_multi_strerror(mcode));
...@@ -573,28 +583,66 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence) ...@@ -573,28 +583,66 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence)
switch (whence) { switch (whence) {
case SEEK_SET: case SEEK_SET:
is->offset = offset;
break; break;
case SEEK_CUR: case SEEK_CUR:
is->offset += offset; offset += is->offset;
break; break;
case SEEK_END: case SEEK_END:
is->offset = is->size + offset; if (is->size < 0)
/* stream size is not known */
return false;
offset += is->size;
break; break;
default: default:
return false; return false;
} }
if (is->offset < 0) if (offset < 0)
return false; return false;
/* check if we can fast-forward the buffer */
while (offset > is->offset && !list_empty(&c->buffers)) {
struct list_head *rewind_head;
struct buffer *buffer = (struct buffer *)c->buffers.next;
size_t length;
if (!list_empty(&c->rewind) || is->offset == 0)
/* at the beginning or already writing the rewind
buffer list */
rewind_head = &c->rewind;
else
/* we don't need the rewind buffers anymore */
rewind_head = NULL;
length = buffer->size - buffer->consumed;
if (offset - is->offset < (off_t)length)
length = offset - is->offset;
consume_buffer(buffer, length, rewind_head);
is->offset += length;
}
if (offset == is->offset)
return true;
/* close the old connection and open a new one */ /* close the old connection and open a new one */
input_curl_easy_free(c); input_curl_easy_free(c);
is->offset = offset;
if (is->offset == is->size) {
/* seek to EOF: simulate empty result; avoid
triggering a "416 Requested Range Not Satisfiable"
response */
c->eof = true;
return true;
}
ret = input_curl_easy_init(is); ret = input_curl_easy_init(is);
if (!ret) if (!ret)
return false; return false;
...@@ -610,7 +658,7 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence) ...@@ -610,7 +658,7 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence)
if (!ret) if (!ret)
return false; return false;
return true; return input_curl_multi_info_read(is);
} }
static bool static bool
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#endif #endif
#include <glib.h> #include <glib.h>
#include <assert.h>
static const struct input_plugin *const input_plugins[] = { static const struct input_plugin *const input_plugins[] = {
&input_plugin_file, &input_plugin_file,
...@@ -57,7 +58,7 @@ input_stream_open(struct input_stream *is, const char *url) ...@@ -57,7 +58,7 @@ input_stream_open(struct input_stream *is, const char *url)
is->seekable = false; is->seekable = false;
is->ready = false; is->ready = false;
is->offset = 0; is->offset = 0;
is->size = 0; is->size = -1;
is->error = 0; is->error = 0;
is->mime = NULL; is->mime = NULL;
is->meta_name = NULL; is->meta_name = NULL;
...@@ -84,6 +85,9 @@ input_stream_seek(struct input_stream *is, off_t offset, int whence) ...@@ -84,6 +85,9 @@ input_stream_seek(struct input_stream *is, off_t offset, int whence)
size_t size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size) input_stream_read(struct input_stream *is, void *ptr, size_t size)
{ {
assert(ptr != NULL);
assert(size > 0);
return is->plugin->read(is, ptr, size); return is->plugin->read(is, ptr, size);
} }
......
...@@ -67,7 +67,7 @@ static const char *log_date(void) ...@@ -67,7 +67,7 @@ static const char *log_date(void)
} }
static void static void
mpd_log_func(G_GNUC_UNUSED const gchar *log_domain, mpd_log_func(const gchar *log_domain,
G_GNUC_UNUSED GLogLevelFlags log_level, G_GNUC_UNUSED GLogLevelFlags log_level,
const gchar *message, G_GNUC_UNUSED gpointer user_data) const gchar *message, G_GNUC_UNUSED gpointer user_data)
{ {
...@@ -87,8 +87,12 @@ mpd_log_func(G_GNUC_UNUSED const gchar *log_domain, ...@@ -87,8 +87,12 @@ mpd_log_func(G_GNUC_UNUSED const gchar *log_domain,
} else } else
converted = NULL; converted = NULL;
fprintf(file, "%s%s", if (log_domain == NULL)
log_domain = "";
fprintf(file, "%s%s%s%s",
stdout_mode ? "" : log_date(), stdout_mode ? "" : log_date(),
log_domain, *log_domain == 0 ? "" : ": ",
message); message);
g_free(converted); g_free(converted);
......
...@@ -383,6 +383,7 @@ int main(int argc, char *argv[]) ...@@ -383,6 +383,7 @@ int main(int argc, char *argv[])
{ {
Options options; Options options;
clock_t start; clock_t start;
GTimer *save_state_timer;
#ifdef HAVE_LOCALE #ifdef HAVE_LOCALE
/* initialize locale */ /* initialize locale */
...@@ -446,6 +447,8 @@ int main(int argc, char *argv[]) ...@@ -446,6 +447,8 @@ int main(int argc, char *argv[])
player_create(); player_create();
read_state_file(); read_state_file();
save_state_timer = g_timer_new();
while (COMMAND_RETURN_KILL != client_manager_io() && while (COMMAND_RETURN_KILL != client_manager_io() &&
COMMAND_RETURN_KILL != handlePendingSignals()) { COMMAND_RETURN_KILL != handlePendingSignals()) {
unsigned flags; unsigned flags;
...@@ -459,6 +462,12 @@ int main(int argc, char *argv[]) ...@@ -459,6 +462,12 @@ int main(int argc, char *argv[])
flags = idle_get(); flags = idle_get();
if (flags != 0) if (flags != 0)
client_manager_idle_add(flags); client_manager_idle_add(flags);
if (g_timer_elapsed(save_state_timer, NULL) >= 5 * 60) {
g_debug("Saving state file\n");
write_state_file();
g_timer_start(save_state_timer);
}
} }
write_state_file(); write_state_file();
......
...@@ -109,7 +109,7 @@ map_directory_child_fs(const struct directory *directory, const char *name, ...@@ -109,7 +109,7 @@ map_directory_child_fs(const struct directory *directory, const char *name,
if (parent_fs == NULL) if (parent_fs == NULL)
return NULL; return NULL;
utf8_to_fs_charset(buffer, name); name = utf8_to_fs_charset(buffer, name);
pfx_dir(buffer, name, strlen(name), pfx_dir(buffer, name, strlen(name),
parent_fs, strlen(parent_fs)); parent_fs, strlen(parent_fs));
return buffer; return buffer;
......
...@@ -33,7 +33,7 @@ char *fs_charset_to_utf8(char *dst, const char *str) ...@@ -33,7 +33,7 @@ char *fs_charset_to_utf8(char *dst, const char *str)
GError *error = NULL; GError *error = NULL;
p = g_convert(str, -1, p = g_convert(str, -1,
fs_charset, "utf-8", "utf-8", fs_charset,
NULL, NULL, &error); NULL, NULL, &error);
if (p == NULL) { if (p == NULL) {
/* no fallback */ /* no fallback */
...@@ -52,7 +52,7 @@ char *utf8_to_fs_charset(char *dst, const char *str) ...@@ -52,7 +52,7 @@ char *utf8_to_fs_charset(char *dst, const char *str)
GError *error = NULL; GError *error = NULL;
p = g_convert(str, -1, p = g_convert(str, -1,
"utf-8", fs_charset, fs_charset, "utf-8",
NULL, NULL, &error); NULL, NULL, &error);
if (p == NULL) { if (p == NULL) {
/* fall back to UTF-8 */ /* fall back to UTF-8 */
......
...@@ -67,7 +67,7 @@ void music_pipe_free(void) ...@@ -67,7 +67,7 @@ void music_pipe_free(void)
/** return the index of the chunk after i */ /** return the index of the chunk after i */
static inline unsigned successor(unsigned i) static inline unsigned successor(unsigned i)
{ {
assert(i <= music_pipe.num_chunks); assert(i < music_pipe.num_chunks);
++i; ++i;
return i == music_pipe.num_chunks ? 0 : i; return i == music_pipe.num_chunks ? 0 : i;
......
...@@ -389,12 +389,11 @@ updateDirectory(struct directory *directory, const struct stat *st) ...@@ -389,12 +389,11 @@ updateDirectory(struct directory *directory, const struct stat *st)
char *utf8; char *utf8;
struct stat st2; struct stat st2;
if (skip_path(ent->d_name) || if (skip_path(ent->d_name))
skip_symlink(directory, ent->d_name))
continue; continue;
utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name); utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name);
if (!utf8) if (utf8 == NULL || skip_symlink(directory, utf8))
continue; continue;
if (stat_directory_child(directory, utf8, &st2) == 0) if (stat_directory_child(directory, utf8, &st2) == 0)
...@@ -413,7 +412,7 @@ static struct directory * ...@@ -413,7 +412,7 @@ static struct directory *
directory_make_child_checked(struct directory *parent, const char *path) directory_make_child_checked(struct directory *parent, const char *path)
{ {
struct directory *directory; struct directory *directory;
char *basename; char *base;
struct stat st; struct stat st;
struct song *conflicting; struct song *conflicting;
...@@ -421,21 +420,21 @@ directory_make_child_checked(struct directory *parent, const char *path) ...@@ -421,21 +420,21 @@ directory_make_child_checked(struct directory *parent, const char *path)
if (directory != NULL) if (directory != NULL)
return directory; return directory;
basename = g_path_get_basename(path); base = g_path_get_basename(path);
if (stat_directory_child(parent, basename, &st) < 0 || if (stat_directory_child(parent, base, &st) < 0 ||
inodeFoundInParent(parent, st.st_ino, st.st_dev)) { inodeFoundInParent(parent, st.st_ino, st.st_dev)) {
g_free(basename); g_free(base);
return NULL; return NULL;
} }
/* if we're adding directory paths, make sure to delete filenames /* if we're adding directory paths, make sure to delete filenames
with potentially the same name */ with potentially the same name */
conflicting = songvec_find(&parent->songs, basename); conflicting = songvec_find(&parent->songs, base);
if (conflicting) if (conflicting)
delete_song(parent, conflicting); delete_song(parent, conflicting);
g_free(basename); g_free(base);
directory = directory_new_child(parent, path); directory = directory_new_child(parent, path);
directory_set_stat(directory, &st); directory_set_stat(directory, &st);
......
...@@ -29,6 +29,15 @@ ...@@ -29,6 +29,15 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#ifndef assert_static
/* Compile time assertion developed by Ralf Holly */
/* http://pera-software.com/articles/compile-time-assertions.pdf */
#define assert_static(e) \
do { \
enum { assert_static__ = 1/(e) }; \
} while (0)
#endif /* !assert_static */
char *myFgets(char *buffer, int bufferSize, FILE * fp); char *myFgets(char *buffer, int bufferSize, FILE * fp);
void stripReturnChar(char *string); void stripReturnChar(char *string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment