[Pkg-mpd-commits] [SCM] Git repository for pkg-mpd branch, master, updated. debian/0.16.2-1-20-ga4e0297
Alexander Wirt
formorer at debian.org
Thu Oct 13 10:28:20 UTC 2011
The following commit has been merged in the master branch:
commit d91cb09c124f300d10756a87fc3d76da41c96066
Author: Alexander Wirt <formorer at debian.org>
Date: Sat Sep 3 09:20:25 2011 +0200
Imported Upstream version 0.16.4
diff --git a/Makefile.am b/Makefile.am
index 88eebe6..b3620bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@ noinst_LIBRARIES =
src_mpd_CFLAGS = $(AM_CFLAGS) $(MPD_CFLAGS)
src_mpd_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(AVAHI_CFLAGS) \
$(LIBWRAP_CFLAGS) \
$(SQLITE_CFLAGS) \
$(ARCHIVE_CFLAGS) \
@@ -21,6 +22,7 @@ src_mpd_CPPFLAGS = $(AM_CPPFLAGS) \
$(FILTER_CFLAGS) \
$(OUTPUT_CFLAGS)
src_mpd_LDADD = $(MPD_LIBS) \
+ $(AVAHI_LIBS) \
$(LIBWRAP_LDFLAGS) \
$(SQLITE_LIBS) \
$(ARCHIVE_LIBS) \
diff --git a/Makefile.in b/Makefile.in
index 51c39b9..06bd134 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -652,11 +652,11 @@ am__DEPENDENCIES_8 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
src_mpd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4) \
- $(am__DEPENDENCIES_6) $(am__DEPENDENCIES_7) \
- $(am__DEPENDENCIES_8) $(am__DEPENDENCIES_4) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
+ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_6) \
+ $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_8) \
+ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1)
am__test_dump_playlist_SOURCES_DIST = test/dump_playlist.c src/conf.c \
src/tokenizer.c src/utils.c src/uri.c src/song.c src/tag.c \
src/tag_pool.c src/tag_save.c src/text_input_stream.c \
@@ -1580,6 +1580,7 @@ AM_CPPFLAGS = -I$(srcdir)/src $(GLIB_CFLAGS) \
noinst_LIBRARIES = $(am__append_22)
src_mpd_CFLAGS = $(AM_CFLAGS) $(MPD_CFLAGS)
src_mpd_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(AVAHI_CFLAGS) \
$(LIBWRAP_CFLAGS) \
$(SQLITE_CFLAGS) \
$(ARCHIVE_CFLAGS) \
@@ -1591,6 +1592,7 @@ src_mpd_CPPFLAGS = $(AM_CPPFLAGS) \
$(OUTPUT_CFLAGS)
src_mpd_LDADD = $(MPD_LIBS) \
+ $(AVAHI_LIBS) \
$(LIBWRAP_LDFLAGS) \
$(SQLITE_LIBS) \
$(ARCHIVE_LIBS) \
diff --git a/NEWS b/NEWS
index 31169a8..d72e0e0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,27 @@
+ver 0.16.4 (2011/09/01)
+* don't abort configure when avahi is not found
+* auto-detect libmad without pkg-config
+* fix memory leaks
+* don't resume playback when seeking to another song while paused
+* apply follow_inside_symlinks to absolute symlinks
+* fix playback discontinuation after seeking
+* input:
+ - curl: limit the receive buffer size
+ - curl: implement a hard-coded timeout of 10 seconds
+* decoder:
+ - ffmpeg: workaround for semantic API change in recent ffmpeg versions
+ - flac: validate the sample rate when scanning the tag
+ - wavpack: obey all decoder commands, stop at CUE track border
+* encoder:
+ - vorbis: don't send end-of-stream on flush
+* output:
+ - alsa: fix SIGFPE when alsa announces a period size of 0
+ - httpd: don't warn on client disconnect
+ - osx: don't drain the buffer when closing
+ - pulse: fix deadlock when resuming the stream
+ - pulse: fix deadlock when the stream was suspended
+
+
ver 0.16.3 (2011/06/04)
* fix assertion failure in audio format mask parser
* fix NULL pointer dereference in playlist parser
diff --git a/configure b/configure
index 313bcd3..abbe4c2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for mpd 0.16.3.
+# Generated by GNU Autoconf 2.67 for mpd 0.16.4.
#
# Report bugs to <musicpd-dev-team at lists.sourceforge.net>.
#
@@ -552,8 +552,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='mpd'
PACKAGE_TARNAME='mpd'
-PACKAGE_VERSION='0.16.3'
-PACKAGE_STRING='mpd 0.16.3'
+PACKAGE_VERSION='0.16.4'
+PACKAGE_STRING='mpd 0.16.4'
PACKAGE_BUGREPORT='musicpd-dev-team at lists.sourceforge.net'
PACKAGE_URL=''
@@ -726,6 +726,8 @@ FLUIDSYNTH_LIBS
FLUIDSYNTH_CFLAGS
HAVE_FLAC_FALSE
HAVE_FLAC_TRUE
+OGG_LIBS
+OGG_CFLAGS
FLAC_LIBS
FLAC_CFLAGS
HAVE_FFMPEG_FALSE
@@ -766,8 +768,6 @@ ENABLE_MMS_FALSE
ENABLE_MMS_TRUE
MMS_LIBS
MMS_CFLAGS
-OGG_LIBS
-OGG_CFLAGS
ENABLE_LASTFM_FALSE
ENABLE_LASTFM_TRUE
ENABLE_CURL_FALSE
@@ -786,10 +786,10 @@ SQLITE_LIBS
SQLITE_CFLAGS
HAVE_BONJOUR_FALSE
HAVE_BONJOUR_TRUE
-HAVE_AVAHI_FALSE
-HAVE_AVAHI_TRUE
HAVE_ZEROCONF_FALSE
HAVE_ZEROCONF_TRUE
+HAVE_AVAHI_FALSE
+HAVE_AVAHI_TRUE
AVAHI_LIBS
AVAHI_CFLAGS
HAVE_ID3TAG_FALSE
@@ -1001,8 +1001,6 @@ SAMPLERATE_013_CFLAGS
SAMPLERATE_013_LIBS
CURL_CFLAGS
CURL_LIBS
-OGG_CFLAGS
-OGG_LIBS
MMS_CFLAGS
MMS_LIBS
ISO9660_CFLAGS
@@ -1015,6 +1013,8 @@ FFMPEG_CFLAGS
FFMPEG_LIBS
FLAC_CFLAGS
FLAC_LIBS
+OGG_CFLAGS
+OGG_LIBS
FLUIDSYNTH_CFLAGS
FLUIDSYNTH_LIBS
GME_CFLAGS
@@ -1591,7 +1591,7 @@ if test "$ac_init_help" = "long"; then
# 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.
cat <<_ACEOF
-\`configure' configures mpd 0.16.3 to adapt to many kinds of systems.
+\`configure' configures mpd 0.16.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1661,7 +1661,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of mpd 0.16.3:";;
+ short | recursive ) echo "Configuration of mpd 0.16.4:";;
esac
cat <<\_ACEOF
@@ -1684,13 +1684,13 @@ Optional Features:
--enable-ffmpeg enable FFMPEG support
--disable-fifo disable support for writing audio to a FIFO
(default: enable)
- --disable-flac disable flac support (default: enable)
+ --enable-flac enable FLAC decoder
--enable-fluidsynth enable MIDI support via fluidsynth (default:
disable)
--enable-gme enable Blargg's game music emulator plugin
--enable-gprof enable profiling via gprof (default: disabled)
--enable-httpd-output enables the HTTP server output
- --disable-id3 disable id3 support (default: enable)
+ --enable-id3 disable id3 support
--disable-inotify disable support Inotify automatic database update
(default: enabled)
--disable-ipv6 disable IPv6 support (default: enable)
@@ -1729,7 +1729,7 @@ Optional Features:
enable the TwoLAME mp2 encoder
--disable-un disable support for clients connecting via unix
domain sockets (default: enable)
- --disable-vorbis disable Ogg Vorbis support (default: enable)
+ --enable-vorbis enable Ogg Vorbis decoder
--enable-vorbis-encoder enable the Ogg Vorbis encoder
--enable-wave-encoder enable the PCM wave encoder
--enable-wavpack enable WavPack support
@@ -1794,8 +1794,6 @@ Some influential environment variables:
linker flags for SAMPLERATE_013, overriding pkg-config
CURL_CFLAGS C compiler flags for CURL, overriding pkg-config
CURL_LIBS linker flags for CURL, overriding pkg-config
- OGG_CFLAGS C compiler flags for OGG, overriding pkg-config
- OGG_LIBS linker flags for OGG, overriding pkg-config
MMS_CFLAGS C compiler flags for MMS, overriding pkg-config
MMS_LIBS linker flags for MMS, overriding pkg-config
ISO9660_CFLAGS
@@ -1813,6 +1811,8 @@ Some influential environment variables:
FFMPEG_LIBS linker flags for FFMPEG, overriding pkg-config
FLAC_CFLAGS C compiler flags for FLAC, overriding pkg-config
FLAC_LIBS linker flags for FLAC, overriding pkg-config
+ OGG_CFLAGS C compiler flags for OGG, overriding pkg-config
+ OGG_LIBS linker flags for OGG, overriding pkg-config
FLUIDSYNTH_CFLAGS
C compiler flags for FLUIDSYNTH, overriding pkg-config
FLUIDSYNTH_LIBS
@@ -1932,7 +1932,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-mpd configure 0.16.3
+mpd configure 0.16.4
generated by GNU Autoconf 2.67
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2442,7 +2442,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by mpd $as_me 0.16.3, which was
+It was created by mpd $as_me 0.16.4, which was
generated by GNU Autoconf 2.67. Invocation command line was
$ $0 $@
@@ -3258,7 +3258,7 @@ fi
# Define the identity of the package.
PACKAGE='mpd'
- VERSION='0.16.3'
+ VERSION='0.16.4'
cat >>confdefs.h <<_ACEOF
@@ -5979,7 +5979,7 @@ fi
if test "${enable_flac+set}" = set; then :
enableval=$enable_flac;
else
- enable_flac=yes
+ enable_flac=auto
fi
@@ -6019,7 +6019,7 @@ fi
if test "${enable_id3+set}" = set; then :
enableval=$enable_id3;
else
- enable_id3=yes
+ enable_id3=auto
fi
@@ -6468,7 +6468,7 @@ fi
if test "${enable_vorbis+set}" = set; then :
enableval=$enable_vorbis;
else
- enable_vorbis=yes
+ enable_vorbis=auto
fi
@@ -7030,7 +7030,8 @@ else
fi
-if test x$enable_id3 = xyes; then
+
+ if eval "test x`echo '$'enable_id3` != xno"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ID3TAG" >&5
@@ -7129,9 +7130,9 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_id3tag_id3_file_open" >&5
$as_echo "$ac_cv_lib_id3tag_id3_file_open" >&6; }
if test "x$ac_cv_lib_id3tag_id3_file_open" = x""yes; then :
- ID3TAG_LIBS="-lid3tag -lz" ID3TAG_CFLAGS=""
+ eval "found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS=''"
else
- enable_id3=no
+ eval "found_id3=no"
fi
elif test $pkg_failed = untried; then
@@ -7172,9 +7173,9 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_id3tag_id3_file_open" >&5
$as_echo "$ac_cv_lib_id3tag_id3_file_open" >&6; }
if test "x$ac_cv_lib_id3tag_id3_file_open" = x""yes; then :
- ID3TAG_LIBS="-lid3tag -lz" ID3TAG_CFLAGS=""
+ eval "found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS=''"
else
- enable_id3=no
+ eval "found_id3=no"
fi
else
@@ -7182,9 +7183,48 @@ else
ID3TAG_LIBS=$pkg_cv_ID3TAG_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- :
-fi
+ eval "found_id3=yes"
fi
+ fi
+
+
+ name="id3"
+ var="enable_id3"
+ found="found_$name"
+ feature="id3tag"
+ msg="libid3tag not found"
+
+ if eval "test x`echo '$'$var` = xno"; then
+ eval "$found=no"
+ fi
+
+ if eval "test x`echo '$'$found` = xyes"; then
+
+ var="enable_$name"
+ feature="$feature"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5
+$as_echo "$as_me: auto-detected $feature" >&6;}
+ eval "$var=yes"
+ fi
+
+ else
+
+ var="enable_$name"
+ feature="$feature"
+ msg="$msg"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5
+$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
+ eval "$var=no"
+ elif eval "test x`echo '$'$var` = xyes"; then
+ as_fn_error $? "$feature: $msg" "$LINENO" 5
+ fi
+
+ fi
+
if test x$enable_id3 = xyes; then
@@ -7204,15 +7244,22 @@ fi
case $with_zeroconf in
-no|avahi|bonjour)
+no|bonjour)
+ enable_avahi=no
;;
+
+avahi)
+ enable_avahi=yes
+ ;;
+
*)
with_zeroconf=auto
+ enable_avahi=auto
;;
esac
-if test x$with_zeroconf != xno; then
- if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then
+
+ if eval "test x`echo '$'enable_avahi` != xno"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVAHI" >&5
@@ -7274,35 +7321,81 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- found_avahi=0
+ eval "found_avahi=no"
elif test $pkg_failed = untried; then
- found_avahi=0
+ eval "found_avahi=no"
else
AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS
AVAHI_LIBS=$pkg_cv_AVAHI_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- found_avahi=1;
-$as_echo "#define HAVE_AVAHI 1" >>confdefs.h
-
- MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS"
+ eval "found_avahi=yes"
fi
fi
- if test x$found_avahi = x1; then
- with_zeroconf=avahi
- elif test x$with_zeroconf = xavahi; then
- as_fn_error $? "Avahi support requested but not found" "$LINENO" 5
+
+ name="avahi"
+ var="enable_avahi"
+ found="found_$name"
+ feature="avahi client library"
+ msg="avahi client+glib not found"
+
+ if eval "test x`echo '$'$var` = xno"; then
+ eval "$found=no"
+ fi
+
+ if eval "test x`echo '$'$found` = xyes"; then
+
+ var="enable_$name"
+ feature="$feature"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5
+$as_echo "$as_me: auto-detected $feature" >&6;}
+ eval "$var=yes"
+ fi
+
+ else
+
+ var="enable_$name"
+ feature="$feature"
+ msg="$msg"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5
+$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
+ eval "$var=no"
+ elif eval "test x`echo '$'$var` = xyes"; then
+ as_fn_error $? "$feature: $msg" "$LINENO" 5
+ fi
+
fi
+
+if test x$enable_avahi = xyes; then
+
+$as_echo "#define HAVE_AVAHI 1" >>confdefs.h
+
+ with_zeroconf=avahi
+fi
+
+ if test x$enable_avahi = xyes; then
+ HAVE_AVAHI_TRUE=
+ HAVE_AVAHI_FALSE='#'
+else
+ HAVE_AVAHI_TRUE='#'
+ HAVE_AVAHI_FALSE=
+fi
+
+
+enable_bounjour=no
+if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then
ac_fn_c_check_header_mongrel "$LINENO" "dns_sd.h" "ac_cv_header_dns_sd_h" "$ac_includes_default"
if test "x$ac_cv_header_dns_sd_h" = x""yes; then :
- found_bonjour=1;
+ enable_bonjour=yes;
$as_echo "#define HAVE_BONJOUR 1" >>confdefs.h
-else
- found_bonjour=0
fi
@@ -7348,7 +7441,7 @@ fi
fi
- if test x$found_bonjour = x1; then
+ if test x$enable_bonjour = xyes; then
with_zeroconf=bonjour
elif test x$with_zeroconf = xbonjour; then
as_fn_error $? "Bonjour support requested but not found" "$LINENO" 5
@@ -7373,14 +7466,6 @@ else
HAVE_ZEROCONF_FALSE=
fi
- if test x$with_zeroconf = xavahi; then
- HAVE_AVAHI_TRUE=
- HAVE_AVAHI_FALSE='#'
-else
- HAVE_AVAHI_TRUE='#'
- HAVE_AVAHI_FALSE=
-fi
-
if test x$with_zeroconf = xbonjour; then
HAVE_BONJOUR_TRUE=
HAVE_BONJOUR_FALSE='#'
@@ -7876,80 +7961,6 @@ else
fi
-if test x$with_tremor = xno || test -z $with_tremor; then
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OGG" >&5
-$as_echo_n "checking for OGG... " >&6; }
-
-if test -n "$PKG_CONFIG"; then
- if test -n "$OGG_CFLAGS"; then
- pkg_cv_OGG_CFLAGS="$OGG_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5
- ($PKG_CONFIG --exists --print-errors "ogg") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_OGG_CFLAGS=`$PKG_CONFIG --cflags "ogg" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- fi
-else
- pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$OGG_LIBS"; then
- pkg_cv_OGG_LIBS="$OGG_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5
- ($PKG_CONFIG --exists --print-errors "ogg") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_OGG_LIBS=`$PKG_CONFIG --libs "ogg" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- fi
-else
- pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi
- if test $_pkg_short_errors_supported = yes; then
- OGG_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "ogg"`
- else
- OGG_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "ogg"`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$OGG_PKG_ERRORS" >&5
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- enable_ogg=no
-elif test $pkg_failed = untried; then
- enable_ogg=no
-else
- OGG_CFLAGS=$pkg_cv_OGG_CFLAGS
- OGG_LIBS=$pkg_cv_OGG_LIBS
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- enable_ogg=yes
-fi
-fi
-
if eval "test x`echo '$'enable_mms` != xno"; then
@@ -9304,7 +9315,9 @@ else
fi
-if test x$enable_flac = xyes; then
+
+
+ if eval "test x`echo '$'enable_flac` != xno"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FLAC" >&5
@@ -9366,18 +9379,62 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- enable_flac=no
+ eval "found_flac=no"
elif test $pkg_failed = untried; then
- enable_flac=no
+ eval "found_flac=no"
else
FLAC_CFLAGS=$pkg_cv_FLAC_CFLAGS
FLAC_LIBS=$pkg_cv_FLAC_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ eval "found_flac=yes"
+fi
+ fi
+
+
+ name="flac"
+ var="enable_flac"
+ found="found_$name"
+ feature="FLAC decoder"
+ msg="libFLAC not found"
+
+ if eval "test x`echo '$'$var` = xno"; then
+ eval "$found=no"
+ fi
+
+ if eval "test x`echo '$'$found` = xyes"; then
+
+ var="enable_$name"
+ feature="$feature"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5
+$as_echo "$as_me: auto-detected $feature" >&6;}
+ eval "$var=yes"
+ fi
+
+ else
+
+ var="enable_$name"
+ feature="$feature"
+ msg="$msg"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5
+$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
+ eval "$var=no"
+ elif eval "test x`echo '$'$var` = xyes"; then
+ as_fn_error $? "$feature: $msg" "$LINENO" 5
+ fi
+
+ fi
+
+
+
+if test x$enable_flac = xyes; then
$as_echo "#define HAVE_FLAC 1" >>confdefs.h
-fi
oldcflags="$CFLAGS"
oldlibs="$LIBS"
@@ -9395,13 +9452,81 @@ fi
LIBS="$oldlibs"
if test x$enable_oggflac = xflac; then
- if test x$enable_ogg = xyes; then
- FLAC_LIBS="${FLAC_LIBS} -logg"
- else
- enable_oggflac=yes
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OGG" >&5
+$as_echo_n "checking for OGG... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+ if test -n "$OGG_CFLAGS"; then
+ pkg_cv_OGG_CFLAGS="$OGG_CFLAGS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "ogg") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OGG_CFLAGS=`$PKG_CONFIG --cflags "ogg" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+ if test -n "$OGG_LIBS"; then
+ pkg_cv_OGG_LIBS="$OGG_LIBS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "ogg") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OGG_LIBS=`$PKG_CONFIG --libs "ogg" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ OGG_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "ogg"`
+ else
+ OGG_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "ogg"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$OGG_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ enable_oggflac=yes;
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"FLAC has the ogg API built in" >&5
$as_echo "$as_me: WARNING: \"FLAC has the ogg API built in" >&2;}
- fi
+elif test $pkg_failed = untried; then
+ enable_oggflac=yes;
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"FLAC has the ogg API built in" >&5
+$as_echo "$as_me: WARNING: \"FLAC has the ogg API built in" >&2;}
+else
+ OGG_CFLAGS=$pkg_cv_OGG_CFLAGS
+ OGG_LIBS=$pkg_cv_OGG_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ FLAC_LIBS="${FLAC_LIBS} ${OGG_LIBS}" FLAC_CFLAGS="${FLAC_CFLAGS} ${OGG_CFLAGS}"
+fi
fi
fi
@@ -9692,9 +9817,91 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- eval "found_mad=no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mad_stream_init in -lmad" >&5
+$as_echo_n "checking for mad_stream_init in -lmad... " >&6; }
+if test "${ac_cv_lib_mad_mad_stream_init+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmad $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mad_stream_init ();
+int
+main ()
+{
+return mad_stream_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mad_mad_stream_init=yes
+else
+ ac_cv_lib_mad_mad_stream_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_mad_stream_init" >&5
+$as_echo "$ac_cv_lib_mad_mad_stream_init" >&6; }
+if test "x$ac_cv_lib_mad_mad_stream_init" = x""yes; then :
+ eval "found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS=''"
+else
+ eval "found_mad=no"
+fi
+
elif test $pkg_failed = untried; then
- eval "found_mad=no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mad_stream_init in -lmad" >&5
+$as_echo_n "checking for mad_stream_init in -lmad... " >&6; }
+if test "${ac_cv_lib_mad_mad_stream_init+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmad $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mad_stream_init ();
+int
+main ()
+{
+return mad_stream_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mad_mad_stream_init=yes
+else
+ ac_cv_lib_mad_mad_stream_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_mad_stream_init" >&5
+$as_echo "$ac_cv_lib_mad_mad_stream_init" >&6; }
+if test "x$ac_cv_lib_mad_mad_stream_init" = x""yes; then :
+ eval "found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS=''"
+else
+ eval "found_mad=no"
+fi
+
else
MAD_CFLAGS=$pkg_cv_MAD_CFLAGS
MAD_LIBS=$pkg_cv_MAD_LIBS
@@ -10534,7 +10741,7 @@ $as_echo "#define HAVE_TREMOR 1" >>confdefs.h
$as_echo "#define ENABLE_VORBIS_DECODER 1" >>confdefs.h
-,
+
else
TREMOR_CFLAGS=
TREMOR_LIBS=
@@ -10577,12 +10784,17 @@ else
fi
-if test x$enable_vorbis = xyes; then
- if test x$enable_tremor = xyes; then
+
+if test x$enable_tremor = xyes; then
+ if test x$enable_vorbis = xyes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"OggTremor detected, could not enable Vorbis.\"" >&5
$as_echo "$as_me: WARNING: \"OggTremor detected, could not enable Vorbis.\"" >&2;}
- enable_vorbis=no
- elif test x$enable_ogg = xyes; then
+ fi
+ enable_vorbis=no
+fi
+
+
+ if eval "test x`echo '$'enable_vorbis` != xno"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VORBIS" >&5
@@ -10593,12 +10805,12 @@ if test -n "$PKG_CONFIG"; then
pkg_cv_VORBIS_CFLAGS="$VORBIS_CFLAGS"
else
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis vorbisfile\""; } >&5
- ($PKG_CONFIG --exists --print-errors "vorbis vorbisfile") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis vorbisfile ogg\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "vorbis vorbisfile ogg") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_VORBIS_CFLAGS=`$PKG_CONFIG --cflags "vorbis vorbisfile" 2>/dev/null`
+ pkg_cv_VORBIS_CFLAGS=`$PKG_CONFIG --cflags "vorbis vorbisfile ogg" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -10611,12 +10823,12 @@ if test -n "$PKG_CONFIG"; then
pkg_cv_VORBIS_LIBS="$VORBIS_LIBS"
else
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis vorbisfile\""; } >&5
- ($PKG_CONFIG --exists --print-errors "vorbis vorbisfile") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis vorbisfile ogg\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "vorbis vorbisfile ogg") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_VORBIS_LIBS=`$PKG_CONFIG --libs "vorbis vorbisfile" 2>/dev/null`
+ pkg_cv_VORBIS_LIBS=`$PKG_CONFIG --libs "vorbis vorbisfile ogg" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -10635,32 +10847,70 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- VORBIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "vorbis vorbisfile"`
+ VORBIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "vorbis vorbisfile ogg"`
else
- VORBIS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "vorbis vorbisfile"`
+ VORBIS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "vorbis vorbisfile ogg"`
fi
# Put the nasty error message in config.log where it belongs
echo "$VORBIS_PKG_ERRORS" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- enable_vorbis=no
+ eval "found_vorbis=no"
elif test $pkg_failed = untried; then
- enable_vorbis=no
+ eval "found_vorbis=no"
else
VORBIS_CFLAGS=$pkg_cv_VORBIS_CFLAGS
VORBIS_LIBS=$pkg_cv_VORBIS_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ eval "found_vorbis=yes"
+fi
+ fi
-$as_echo "#define ENABLE_VORBIS_DECODER 1" >>confdefs.h
-fi
+ name="vorbis"
+ var="enable_vorbis"
+ found="found_$name"
+ feature="Ogg Vorbis decoder"
+ msg="libvorbis not found"
+
+ if eval "test x`echo '$'$var` = xno"; then
+ eval "$found=no"
+ fi
+
+ if eval "test x`echo '$'$found` = xyes"; then
+
+ var="enable_$name"
+ feature="$feature"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5
+$as_echo "$as_me: auto-detected $feature" >&6;}
+ eval "$var=yes"
+ fi
+
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Ogg not detected, could not enable Vorbis.\"" >&5
-$as_echo "$as_me: WARNING: \"Ogg not detected, could not enable Vorbis.\"" >&2;}
- enable_vorbis=no
+
+ var="enable_$name"
+ feature="$feature"
+ msg="$msg"
+
+ if eval "test x`echo '$'$var` = xauto"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5
+$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
+ eval "$var=no"
+ elif eval "test x`echo '$'$var` = xyes"; then
+ as_fn_error $? "$feature: $msg" "$LINENO" 5
fi
+
+ fi
+
+
+if test x$enable_vorbis = xyes; then
+
+$as_echo "#define ENABLE_VORBIS_DECODER 1" >>confdefs.h
+
fi
if test x$enable_vorbis = xyes || test x$enable_tremor = xyes; then
@@ -14320,14 +14570,14 @@ if test -z "${HAVE_ID3TAG_TRUE}" && test -z "${HAVE_ID3TAG_FALSE}"; then
as_fn_error $? "conditional \"HAVE_ID3TAG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
-if test -z "${HAVE_ZEROCONF_TRUE}" && test -z "${HAVE_ZEROCONF_FALSE}"; then
- as_fn_error $? "conditional \"HAVE_ZEROCONF\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
if test -z "${HAVE_AVAHI_TRUE}" && test -z "${HAVE_AVAHI_FALSE}"; then
as_fn_error $? "conditional \"HAVE_AVAHI\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${HAVE_ZEROCONF_TRUE}" && test -z "${HAVE_ZEROCONF_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_ZEROCONF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${HAVE_BONJOUR_TRUE}" && test -z "${HAVE_BONJOUR_FALSE}"; then
as_fn_error $? "conditional \"HAVE_BONJOUR\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14972,7 +15222,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by mpd $as_me 0.16.3, which was
+This file was extended by mpd $as_me 0.16.4, which was
generated by GNU Autoconf 2.67. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15038,7 +15288,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-mpd config.status 0.16.3
+mpd config.status 0.16.4
configured by $0, generated by GNU Autoconf 2.67,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 0aed23b..49233f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
-AC_INIT(mpd, 0.16.3, musicpd-dev-team at lists.sourceforge.net)
+AC_INIT(mpd, 0.16.4, musicpd-dev-team at lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([foreign 1.10 dist-bzip2 subdir-objects])
AM_CONFIG_HEADER(config.h)
@@ -171,9 +171,9 @@ AC_ARG_ENABLE(fifo,
enable_fifo=yes)
AC_ARG_ENABLE(flac,
- AS_HELP_STRING([--disable-flac],
- [disable flac support (default: enable)]),,
- enable_flac=yes)
+ AS_HELP_STRING([--enable-flac],
+ [enable FLAC decoder]),,
+ enable_flac=auto)
AC_ARG_ENABLE(fluidsynth,
AS_HELP_STRING([--enable-fluidsynth],
@@ -196,9 +196,9 @@ AC_ARG_ENABLE(httpd-output,
[enable_httpd_output=auto])
AC_ARG_ENABLE(id3,
- AS_HELP_STRING([--disable-id3],
- [disable id3 support (default: enable)]),,
- enable_id3=yes)
+ AS_HELP_STRING([--enable-id3],
+ [disable id3 support]),,
+ enable_id3=auto)
AC_ARG_ENABLE(inotify,
AS_HELP_STRING([--disable-inotify],
@@ -353,9 +353,9 @@ AC_ARG_ENABLE(un,
[enable_un=yes])
AC_ARG_ENABLE(vorbis,
- AS_HELP_STRING([--disable-vorbis],
- [disable Ogg Vorbis support (default: enable)]),,
- enable_vorbis=yes)
+ AS_HELP_STRING([--enable-vorbis],
+ [enable Ogg Vorbis decoder]),,
+ enable_vorbis=auto)
AC_ARG_ENABLE(vorbis-encoder,
AS_HELP_STRING([--enable-vorbis-encoder],
@@ -510,13 +510,8 @@ fi
AM_CONDITIONAL(HAVE_CUE, test x$enable_cue = xyes)
dnl -------------------------------- libid3tag --------------------------------
-if test x$enable_id3 = xyes; then
- PKG_CHECK_MODULES([ID3TAG], [id3tag],,
- AC_CHECK_LIB(id3tag, id3_file_open,
- [ID3TAG_LIBS="-lid3tag -lz" ID3TAG_CFLAGS=""],
- enable_id3=no))
-fi
-
+MPD_AUTO_PKG_LIB(id3, ID3TAG, id3tag, id3tag, id3_file_open, [-lid3tag -lz], [],
+ [id3tag], [libid3tag not found])
if test x$enable_id3 = xyes; then
AC_DEFINE(HAVE_ID3TAG, 1, [Define to use id3tag])
fi
@@ -530,36 +525,39 @@ dnl ---------------------------------------------------------------------------
dnl --------------------------------- zeroconf --------------------------------
case $with_zeroconf in
-no|avahi|bonjour)
+no|bonjour)
+ enable_avahi=no
;;
+
+avahi)
+ enable_avahi=yes
+ ;;
+
*)
with_zeroconf=auto
+ enable_avahi=auto
;;
esac
-if test x$with_zeroconf != xno; then
- if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then
- PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib],
- [found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])]
- MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS",
- [found_avahi=0])
- fi
+MPD_AUTO_PKG(avahi, AVAHI, [avahi-client avahi-glib],
+ [avahi client library], [avahi client+glib not found])
+if test x$enable_avahi = xyes; then
+ AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])
+ with_zeroconf=avahi
+fi
- if test x$found_avahi = x1; then
- with_zeroconf=avahi
- elif test x$with_zeroconf = xavahi; then
- AC_MSG_ERROR([Avahi support requested but not found])
- fi
+AM_CONDITIONAL(HAVE_AVAHI, test x$enable_avahi = xyes)
+enable_bounjour=no
+if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then
AC_CHECK_HEADER(dns_sd.h,
- [found_bonjour=1;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])],
- [found_bonjour=0])
+ [enable_bonjour=yes;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])])
AC_CHECK_LIB(dns_sd, DNSServiceRegister,
MPD_LIBS="$MPD_LIBS -ldns_sd")
fi
- if test x$found_bonjour = x1; then
+ if test x$enable_bonjour = xyes; then
with_zeroconf=bonjour
elif test x$with_zeroconf = xbonjour; then
AC_MSG_ERROR([Bonjour support requested but not found])
@@ -574,7 +572,6 @@ if test x$with_zeroconf != xno; then
fi
AM_CONDITIONAL(HAVE_ZEROCONF, test x$with_zeroconf != xno)
-AM_CONDITIONAL(HAVE_AVAHI, test x$with_zeroconf = xavahi)
AM_CONDITIONAL(HAVE_BONJOUR, test x$with_zeroconf = xbonjour)
dnl ---------------------------------------------------------------------------
@@ -634,11 +631,6 @@ if test x$enable_lastfm = xyes; then
fi
AM_CONDITIONAL(ENABLE_LASTFM, test x$enable_lastfm = xyes)
-dnl ---------------------------------- libogg ---------------------------------
-if test x$with_tremor = xno || test -z $with_tremor; then
- PKG_CHECK_MODULES(OGG, [ogg], enable_ogg=yes, enable_ogg=no)
-fi
-
dnl ---------------------------------- libmms ---------------------------------
MPD_AUTO_PKG(mms, MMS, [libmms >= 0.4],
[libmms mms:// protocol support], [libmms not found])
@@ -753,10 +745,12 @@ fi
AM_CONDITIONAL(HAVE_FFMPEG, test x$enable_ffmpeg = xyes)
dnl ----------------------------------- FLAC ----------------------------------
+
+MPD_AUTO_PKG(flac, FLAC, [flac >= 1.1],
+ [FLAC decoder], [libFLAC not found])
+
if test x$enable_flac = xyes; then
- PKG_CHECK_MODULES(FLAC, [flac >= 1.1],
- AC_DEFINE(HAVE_FLAC, 1, [Define for FLAC support]),
- enable_flac=no)
+ AC_DEFINE(HAVE_FLAC, 1, [Define for FLAC support])
oldcflags="$CFLAGS"
oldlibs="$LIBS"
@@ -771,12 +765,10 @@ if test x$enable_flac = xyes; then
LIBS="$oldlibs"
if test x$enable_oggflac = xflac; then
- if test x$enable_ogg = xyes; then
- FLAC_LIBS="${FLAC_LIBS} -logg"
- else
- enable_oggflac=yes
- AC_MSG_WARN("FLAC has the ogg API built in, but couldn't find ogg. Disabling oggflac.")
- fi
+ PKG_CHECK_MODULES(OGG, [ogg],
+ [FLAC_LIBS="${FLAC_LIBS} ${OGG_LIBS}" FLAC_CFLAGS="${FLAC_CFLAGS} ${OGG_CFLAGS}"],
+ [enable_oggflac=yes;
+ AC_MSG_WARN("FLAC has the ogg API built in, but couldn't find ogg. Disabling oggflac.")])
fi
fi
@@ -802,7 +794,8 @@ if test x$enable_gme = xyes; then
fi
dnl ---------------------------------- libmad ---------------------------------
-MPD_AUTO_PKG(mad, MAD, [mad],
+MPD_AUTO_PKG_LIB(mad, MAD, [mad],
+ mad, mad_stream_init, [-lmad], [],
[libmad MP3 decoder plugin], [libmad not found])
if test x$enable_mad = xyes; then
AC_DEFINE(HAVE_MAD, 1, [Define to use libmad])
@@ -943,7 +936,7 @@ fi
if test x$enable_tremor = xyes; then
AC_DEFINE(HAVE_TREMOR,1,
[Define to use tremor (libvorbisidec) for ogg support])
- AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support]),
+ AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support])
else
TREMOR_CFLAGS=
TREMOR_LIBS=
@@ -972,18 +965,18 @@ fi
AM_CONDITIONAL(HAVE_OGGFLAC, test x$enable_oggflac = xyes)
dnl -------------------------------- Ogg Vorbis -------------------------------
-if test x$enable_vorbis = xyes; then
- if test x$enable_tremor = xyes; then
+
+if test x$enable_tremor = xyes; then
+ if test x$enable_vorbis = xyes; then
AC_MSG_WARN(["OggTremor detected, could not enable Vorbis."])
- enable_vorbis=no
- elif test x$enable_ogg = xyes; then
- PKG_CHECK_MODULES(VORBIS, [vorbis vorbisfile],
- AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support]),
- enable_vorbis=no)
- else
- AC_MSG_WARN(["Ogg not detected, could not enable Vorbis."])
- enable_vorbis=no
fi
+ enable_vorbis=no
+fi
+
+MPD_AUTO_PKG(vorbis, VORBIS, [vorbis vorbisfile ogg],
+ [Ogg Vorbis decoder], [libvorbis not found])
+if test x$enable_vorbis = xyes; then
+ AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support])
fi
AM_CONDITIONAL(ENABLE_VORBIS_DECODER, test x$enable_vorbis = xyes || test x$enable_tremor = xyes)
diff --git a/doc/developer.xml b/doc/developer.xml
index c63e2c2..010b850 100644
--- a/doc/developer.xml
+++ b/doc/developer.xml
@@ -57,7 +57,7 @@
Some example code:
</para>
- <programlisting lang="C">static inline bool
+ <programlisting lang="C">static inline int
foo(const char *abc, int xyz)
{
if (abc == NULL) {
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 3eb5aa9..0b4f0d1 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -8,12 +8,38 @@
<title>General protocol syntax</title>
<section>
- <title>Requests</title>
+ <title>Protocol overview</title>
+
+ <para>
+ The MPD command protocol exchanges line-based text records
+ between client and server over TCP. Once the client is
+ connected to the server, they conduct a conversation until the
+ client closes the connection. The conversation flow is always
+ initiated by the client.
+ </para>
+
+ <para>
+ The client transmits a command sequence, terminated by the
+ newline character <constant>\n</constant>. The server will
+ respond with one or more lines, the last of which will be a
+ completion code.
+ </para>
<para>
- If arguments contain spaces, they should be surrounded by double quotation
- marks.
+ When the client connects to the server, the server will answer
+ with the following line:
+
+ <synopsis>OK MPD version</synopsis>
+
+ where <varname>version</varname> is a version identifier such as
+ 0.12.2. This version identifier is the version of the protocol
+ spoken, not the real version of the daemon. (There is no way to
+ retrieve this real version identifier from the connection.)
</para>
+ </section>
+
+ <section>
+ <title>Requests</title>
<cmdsynopsis>
<command>COMMAND</command>
@@ -21,6 +47,16 @@
</cmdsynopsis>
<para>
+ If arguments contain spaces, they should be surrounded by double
+ quotation marks.
+ </para>
+
+ <para>
+ Argument strings are separated from the command and any other
+ arguments by linear white-space (' ' or '\t').
+ </para>
+
+ <para>
All data between the client and the server is encoded in
UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are
the same as a standard ansi encoding. Also, no ansi character
@@ -38,13 +74,97 @@
<title>Responses</title>
<para>
- A command returns <returnvalue>OK</returnvalue> on completion
- or <returnvalue>ACK some error</returnvalue> on failure.
- These denote the end of command execution.
+ A command returns <returnvalue>OK</returnvalue> on completion or
+ <returnvalue>ACK some error</returnvalue> on failure. These
+ denote the end of command execution.
</para>
+
+ <section>
+ <title>Failure responses</title>
+
+ <para>
+ The nature of the error can be gleaned from the information
+ that follows the <returnvalue>ACK</returnvalue>.
+ <returnvalue>ACK</returnvalue> lines are of the form:
+
+ <synopsis>ACK [error at command_listNum] {current_command} message_text\n</synopsis>
+
+ These responses are generated by a call to
+ <function>commandError</function>. They contain four separate
+ terms. Let's look at each of them:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <returnvalue>error</returnvalue>: numeric value of one
+ of the <constant>ACK_ERROR</constant> constants defined
+ in <filename>ack.h</filename>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <returnvalue>command_listNum</returnvalue>:
+ offset of the command that caused the error in a <link
+ linkend="command_lists">Command List</link>.
+ An error will always cause a command list to terminate
+ at the command that causes the error.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <returnvalue>current_command</returnvalue>:
+ name of the command, in a <link
+ linkend="command_lists">Command List</link>,
+ that was executing when the error occurred.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <returnvalue>message_text</returnvalue>:
+ some (hopefully) informative text that describes the
+ nature of the error.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <example>
+ <title>foo</title>
+ <para>
+ An example might help. Consider the following sequence
+ sent from the client to the server.
+
+ <synopsis>
+ command_list_begin
+ volume 86
+ play 10240
+ status
+ command_list_end
+ </synopsis>
+ </para>
+
+ <para>
+ The server responds with:
+
+ <returnvalue>
+ ACK [50 at 1] {play} song doesn't exist: "10240"
+ </returnvalue>
+ </para>
+
+ <para>
+ This tells us that the play command, which was the
+ second in the list (the first or only command is
+ numbered 0), failed with error 50. The number 50
+ translates to <constant>ACK_ERROR_NO_EXIST</constant>--the
+ song doesn't exist. This is reiterated by the message text
+ which also tells us which song doesn't exist.
+ </para>
+
+ </example>
+ </section>
</section>
- <section>
+ <section id="command_lists">
<title>Command lists</title>
<para>
diff --git a/doc/user.xml b/doc/user.xml
index 17bbdf9..6a98710 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -446,7 +446,7 @@ cd mpd-version</programlisting>
</para>
<para>
- To configure a filter, add a
+ To configure a playlist plugin, add a
<varname>playlist_plugin</varname> block to
<filename>mpd.conf</filename>:
</para>
diff --git a/m4/mpd_auto.m4 b/m4/mpd_auto.m4
index 3f23393..23713d5 100644
--- a/m4/mpd_auto.m4
+++ b/m4/mpd_auto.m4
@@ -63,3 +63,18 @@ AC_DEFUN([MPD_AUTO_PKG], [
MPD_AUTO_RESULT([$1], [$4], [$5])
])
+
+dnl Check with pkg-config first, fall back to AC_CHECK_LIB.
+dnl
+dnl Parameters: varname1, varname2, pkgname, libname, symname, libs, cflags, description, errmsg
+AC_DEFUN([MPD_AUTO_PKG_LIB], [
+ if eval "test x`echo '$'enable_$1` != xno"; then
+ PKG_CHECK_MODULES([$2], [$3],
+ [eval "found_$1=yes"],
+ AC_CHECK_LIB($4, $5,
+ [eval "found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'"],
+ [eval "found_$1=no"]))
+ fi
+
+ MPD_AUTO_RESULT([$1], [$8], [$9])
+])
diff --git a/scripts/makedist.sh b/scripts/makedist.sh
index d342cea..7f8624d 100755
--- a/scripts/makedist.sh
+++ b/scripts/makedist.sh
@@ -3,7 +3,7 @@ PWD=`pwd`
## If we're not in the scripts directory
## assume the base directory.
-if test "`basename $PWD`" == "scripts"; then
+if test "`basename $PWD`" = "scripts"; then
cd ../
else
MYOLDPWD=`pwd`
@@ -18,7 +18,7 @@ fi
make
make dist
-if test "`basename $PWD`" == "scripts"; then
+if test "`basename $PWD`" = "scripts"; then
cd contrib/
else
cd $MYOLDPWD
diff --git a/src/ape.c b/src/ape.c
index 5fca98e..5f4da3f 100644
--- a/src/ape.c
+++ b/src/ape.c
@@ -60,8 +60,10 @@ ape_scan_internal(FILE *fp, tag_ape_callback_t callback, void *ctx)
assert(remaining > 10);
char *buffer = g_malloc(remaining);
- if (fread(buffer, 1, remaining, fp) != remaining)
+ if (fread(buffer, 1, remaining, fp) != remaining) {
+ g_free(buffer);
return false;
+ }
/* read tags */
unsigned n = GUINT32_FROM_LE(footer.count);
diff --git a/src/conf.c b/src/conf.c
index 7059420..14dac93 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -367,6 +367,7 @@ config_read_file(const char *file, GError **error_r)
assert(*line != 0);
g_propagate_prefixed_error(error_r, error,
"line %i: ", count);
+ fclose(fp);
return false;
}
@@ -378,6 +379,7 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0,
"unrecognized parameter in config file at "
"line %i: %s\n", count, name);
+ fclose(fp);
return false;
}
@@ -387,6 +389,7 @@ config_read_file(const char *file, GError **error_r)
"config parameter \"%s\" is first defined "
"on line %i and redefined on line %i\n",
name, param->line, count);
+ fclose(fp);
return false;
}
@@ -398,6 +401,7 @@ config_read_file(const char *file, GError **error_r)
if (*line != '{') {
g_set_error(error_r, config_quark(), 0,
"line %i: '{' expected", count);
+ fclose(fp);
return false;
}
@@ -406,12 +410,15 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after '{'",
count);
+ fclose(fp);
return false;
}
param = config_read_block(fp, &count, string, error_r);
- if (param == NULL)
+ if (param == NULL) {
+ fclose(fp);
return false;
+ }
} else {
/* a string value */
@@ -428,6 +435,7 @@ config_read_file(const char *file, GError **error_r)
g_error_free(error);
}
+ fclose(fp);
return false;
}
@@ -435,6 +443,7 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after value",
count);
+ fclose(fp);
return false;
}
diff --git a/src/database.c b/src/database.c
index f255d6c..9f29f95 100644
--- a/src/database.c
+++ b/src/database.c
@@ -180,7 +180,7 @@ db_check(void)
}
/* Check if we can write to the directory */
- if (access(dirPath, R_OK | W_OK)) {
+ if (access(dirPath, X_OK | W_OK)) {
g_warning("Can't create db file in \"%s\": %s",
dirPath, strerror(errno));
g_free(dirPath);
diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c
index 6d794db..70628df 100644
--- a/src/decoder/ffmpeg_decoder_plugin.c
+++ b/src/decoder/ffmpeg_decoder_plugin.c
@@ -89,7 +89,11 @@ struct mpd_ffmpeg_stream {
struct decoder *decoder;
struct input_stream *input;
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,101,0)
+ AVIOContext *io;
+#else
ByteIOContext *io;
+#endif
unsigned char buffer[8192];
};
@@ -135,6 +139,33 @@ mpd_ffmpeg_stream_open(struct decoder *decoder, struct input_stream *input)
return stream;
}
+/**
+ * API compatibility wrapper for av_open_input_stream() and
+ * avformat_open_input().
+ */
+static int
+mpd_ffmpeg_open_input(AVFormatContext **ic_ptr,
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,101,0)
+ AVIOContext *pb,
+#else
+ ByteIOContext *pb,
+#endif
+ const char *filename,
+ AVInputFormat *fmt)
+{
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,1,3)
+ AVFormatContext *context = avformat_alloc_context();
+ if (context == NULL)
+ return AVERROR(ENOMEM);
+
+ context->pb = pb;
+ *ic_ptr = context;
+ return avformat_open_input(ic_ptr, filename, fmt, NULL);
+#else
+ return av_open_input_stream(ic_ptr, pb, filename, fmt, NULL);
+#endif
+}
+
static void
mpd_ffmpeg_stream_close(struct mpd_ffmpeg_stream *stream)
{
@@ -321,9 +352,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
}
//ffmpeg works with ours "fileops" helper
- AVFormatContext *format_context;
- if (av_open_input_stream(&format_context, stream->io, input->uri,
- input_format, NULL) != 0) {
+ AVFormatContext *format_context = NULL;
+ if (mpd_ffmpeg_open_input(&format_context, stream->io, input->uri,
+ input_format) != 0) {
g_warning("Open failed\n");
mpd_ffmpeg_stream_close(stream);
return;
@@ -446,13 +477,26 @@ static const ffmpeg_tag_map ffmpeg_tag_maps[] = {
};
static bool
-ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m,
+ffmpeg_copy_metadata(struct tag *tag,
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0)
+ AVDictionary *m,
+#else
+ AVMetadata *m,
+#endif
const ffmpeg_tag_map tag_map)
{
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0)
+ AVDictionaryEntry *mt = NULL;
+
+ while ((mt = av_dict_get(m, tag_map.name, mt, 0)) != NULL)
+ tag_add_item(tag, tag_map.type, mt->value);
+#else
AVMetadataTag *mt = NULL;
while ((mt = av_metadata_get(m, tag_map.name, mt, 0)) != NULL)
tag_add_item(tag, tag_map.type, mt->value);
+#endif
+
return mt != NULL;
}
@@ -470,9 +514,9 @@ ffmpeg_stream_tag(struct input_stream *is)
if (stream == NULL)
return NULL;
- AVFormatContext *f;
- if (av_open_input_stream(&f, stream->io, is->uri,
- input_format, NULL) != 0) {
+ AVFormatContext *f = NULL;
+ if (mpd_ffmpeg_open_input(&f, stream->io, is->uri,
+ input_format) != 0) {
mpd_ffmpeg_stream_close(stream);
return NULL;
}
diff --git a/src/decoder/flac_metadata.c b/src/decoder/flac_metadata.c
index f2f2f95..5b94fd4 100644
--- a/src/decoder/flac_metadata.c
+++ b/src/decoder/flac_metadata.c
@@ -224,7 +224,8 @@ flac_tag_apply_metadata(struct tag *tag, const char *track,
break;
case FLAC__METADATA_TYPE_STREAMINFO:
- tag->time = flac_duration(&block->data.stream_info);
+ if (block->data.stream_info.sample_rate > 0)
+ tag->time = flac_duration(&block->data.stream_info);
break;
default:
diff --git a/src/decoder/flac_metadata.h b/src/decoder/flac_metadata.h
index 06e691d..e52b0fb 100644
--- a/src/decoder/flac_metadata.h
+++ b/src/decoder/flac_metadata.h
@@ -20,6 +20,7 @@
#ifndef MPD_FLAC_METADATA_H
#define MPD_FLAC_METADATA_H
+#include <assert.h>
#include <stdbool.h>
#include <FLAC/metadata.h>
@@ -29,6 +30,8 @@ struct replay_gain_info;
static inline unsigned
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
{
+ assert(stream_info->sample_rate > 0);
+
return (stream_info->total_samples + stream_info->sample_rate - 1) /
stream_info->sample_rate;
}
diff --git a/src/decoder/mpcdec_decoder_plugin.c b/src/decoder/mpcdec_decoder_plugin.c
index 4df8dd2..eaf470a 100644
--- a/src/decoder/mpcdec_decoder_plugin.c
+++ b/src/decoder/mpcdec_decoder_plugin.c
@@ -153,7 +153,6 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
mpc_uint32_t ret;
int32_t chunk[G_N_ELEMENTS(sample_buffer)];
long bit_rate = 0;
- mpc_uint32_t vbr_update_acc;
mpc_uint32_t vbr_update_bits;
enum decoder_command cmd = DECODE_COMMAND_NONE;
@@ -243,10 +242,11 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
decoder_seek_error(mpd_decoder);
}
- vbr_update_acc = 0;
vbr_update_bits = 0;
#ifdef MPC_IS_OLD_API
+ mpc_uint32_t vbr_update_acc = 0;
+
ret = mpc_decoder_decode(&decoder, sample_buffer,
&vbr_update_acc, &vbr_update_bits);
if (ret == 0 || ret == (mpc_uint32_t)-1)
diff --git a/src/decoder/wavpack_decoder_plugin.c b/src/decoder/wavpack_decoder_plugin.c
index efed988..24d0c17 100644
--- a/src/decoder/wavpack_decoder_plugin.c
+++ b/src/decoder/wavpack_decoder_plugin.c
@@ -34,9 +34,6 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "wavpack"
-/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */
-#define CHUNK_SIZE 1020
-
#define ERRORLEN 80
static struct {
@@ -162,8 +159,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
enum sample_format sample_format;
struct audio_format audio_format;
format_samples_t format_samples;
- char chunk[CHUNK_SIZE];
- int samples_requested, samples_got;
float total_time;
int bytes_per_sample, output_sample_size;
@@ -193,12 +188,15 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
output_sample_size = audio_format_frame_size(&audio_format);
/* wavpack gives us all kind of samples in a 32-bit space */
- samples_requested = sizeof(chunk) / (4 * audio_format.channels);
+ int32_t chunk[1024];
+ const uint32_t samples_requested = G_N_ELEMENTS(chunk) /
+ audio_format.channels;
decoder_initialized(decoder, &audio_format, can_seek, total_time);
- do {
- if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) {
+ enum decoder_command cmd = decoder_get_command(decoder);
+ while (cmd != DECODE_COMMAND_STOP) {
+ if (cmd == DECODE_COMMAND_SEEK) {
if (can_seek) {
unsigned where = decoder_seek_where(decoder) *
audio_format.sample_rate;
@@ -213,29 +211,20 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
}
}
- if (decoder_get_command(decoder) == DECODE_COMMAND_STOP) {
+ uint32_t samples_got = WavpackUnpackSamples(wpc, chunk,
+ samples_requested);
+ if (samples_got == 0)
break;
- }
- samples_got = WavpackUnpackSamples(
- wpc, (int32_t *)chunk, samples_requested
- );
- if (samples_got > 0) {
- int bitrate = (int)(WavpackGetInstantBitrate(wpc) /
- 1000 + 0.5);
-
- format_samples(
- bytes_per_sample, chunk,
- samples_got * audio_format.channels
- );
-
- decoder_data(
- decoder, NULL, chunk,
- samples_got * output_sample_size,
- bitrate
- );
- }
- } while (samples_got > 0);
+ int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 +
+ 0.5);
+ format_samples(bytes_per_sample, chunk,
+ samples_got * audio_format.channels);
+
+ cmd = decoder_data(decoder, NULL, chunk,
+ samples_got * output_sample_size,
+ bitrate);
+ }
}
/**
diff --git a/src/encoder/vorbis_encoder.c b/src/encoder/vorbis_encoder.c
index 08147be..38a998b 100644
--- a/src/encoder/vorbis_encoder.c
+++ b/src/encoder/vorbis_encoder.c
@@ -266,6 +266,15 @@ vorbis_encoder_flush(struct encoder *_encoder, G_GNUC_UNUSED GError **error)
{
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ encoder->flush = true;
+ return true;
+}
+
+static bool
+vorbis_encoder_pre_tag(struct encoder *_encoder, G_GNUC_UNUSED GError **error)
+{
+ struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+
vorbis_analysis_wrote(&encoder->vd, 0);
vorbis_encoder_blockout(encoder);
@@ -366,6 +375,7 @@ vorbis_encoder_read(struct encoder *_encoder, void *_dest, size_t length)
if (ret == 0 && encoder->flush) {
encoder->flush = false;
ret = ogg_stream_flush(&encoder->os, &page);
+
}
if (ret == 0)
@@ -398,6 +408,7 @@ const struct encoder_plugin vorbis_encoder_plugin = {
.open = vorbis_encoder_open,
.close = vorbis_encoder_close,
.flush = vorbis_encoder_flush,
+ .pre_tag = vorbis_encoder_pre_tag,
.tag = vorbis_encoder_tag,
.write = vorbis_encoder_write,
.read = vorbis_encoder_read,
diff --git a/src/encoder_plugin.h b/src/encoder_plugin.h
index 13fb231..fb00413 100644
--- a/src/encoder_plugin.h
+++ b/src/encoder_plugin.h
@@ -50,6 +50,8 @@ struct encoder_plugin {
bool (*flush)(struct encoder *encoder, GError **error);
+ bool (*pre_tag)(struct encoder *encoder, GError **error);
+
bool (*tag)(struct encoder *encoder, const struct tag *tag,
GError **error);
@@ -148,8 +150,30 @@ encoder_flush(struct encoder *encoder, GError **error)
}
/**
+ * Prepare for sending a tag to the encoder. This is used by some
+ * encoders to flush the previous sub-stream, in preparation to begin
+ * a new one.
+ *
+ * @param encoder the encoder
+ * @param tag the tag object
+ * @param error location to store the error occuring, or NULL to ignore errors.
+ * @return true on success
+ */
+static inline bool
+encoder_pre_tag(struct encoder *encoder, GError **error)
+{
+ /* this method is optional */
+ return encoder->plugin->pre_tag != NULL
+ ? encoder->plugin->pre_tag(encoder, error)
+ : true;
+}
+
+/**
* Sends a tag to the encoder.
*
+ * Instructions: call encoder_pre_tag(); then obtain flushed data with
+ * encoder_read(); finally call encoder_tag().
+ *
* @param encoder the encoder
* @param tag the tag object
* @param error location to store the error occuring, or NULL to ignore errors.
diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c
index ae645bd..2c4ac2f 100644
--- a/src/input/curl_input_plugin.c
+++ b/src/input/curl_input_plugin.c
@@ -43,6 +43,13 @@
#define G_LOG_DOMAIN "input_curl"
/**
+ * Do not buffer more than this number of bytes. It should be a
+ * reasonable limit that doesn't make low-end machines suffer too
+ * much, but doesn't cause stuttering on high-latency lines.
+ */
+static const size_t CURL_MAX_BUFFERED = 512 * 1024;
+
+/**
* Buffers created by input_curl_writefunction().
*/
struct buffer {
@@ -144,6 +151,25 @@ input_curl_finish(void)
curl_global_cleanup();
}
+/**
+ * Determine the total sizes of all buffers, including portions that
+ * have already been consumed.
+ */
+G_GNUC_PURE
+static size_t
+curl_total_buffer_size(const struct input_curl *c)
+{
+ size_t total = 0;
+
+ for (GList *i = g_queue_peek_head_link(c->buffers);
+ i != NULL; i = g_list_next(i)) {
+ struct buffer *buffer = i->data;
+ total += buffer->size;
+ }
+
+ return total;
+}
+
static void
buffer_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data)
{
@@ -473,6 +499,10 @@ static int
input_curl_buffer(struct input_stream *is, GError **error_r)
{
struct input_curl *c = (struct input_curl *)is;
+
+ if (curl_total_buffer_size(c) >= CURL_MAX_BUFFERED)
+ return 0;
+
CURLMcode mcode;
int running_handles;
bool ret;
@@ -650,6 +680,9 @@ input_curl_easy_init(struct input_curl *c, GError **error_r)
curl_easy_setopt(c->easy, CURLOPT_MAXREDIRS, 5);
curl_easy_setopt(c->easy, CURLOPT_FAILONERROR, true);
curl_easy_setopt(c->easy, CURLOPT_ERRORBUFFER, c->error);
+ curl_easy_setopt(c->easy, CURLOPT_NOPROGRESS, 1l);
+ curl_easy_setopt(c->easy, CURLOPT_NOSIGNAL, 1l);
+ curl_easy_setopt(c->easy, CURLOPT_CONNECTTIMEOUT, 10l);
if (proxy != NULL)
curl_easy_setopt(c->easy, CURLOPT_PROXY, proxy);
diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c
index 9177fab..422264f 100644
--- a/src/output/alsa_plugin.c
+++ b/src/output/alsa_plugin.c
@@ -508,6 +508,14 @@ configure_hw:
g_debug("buffer_size=%u period_size=%u",
(unsigned)alsa_buffer_size, (unsigned)alsa_period_size);
+ if (alsa_period_size == 0)
+ /* this works around a SIGFPE bug that occurred when
+ an ALSA driver indicated period_size==0; this
+ caused a division by zero in alsa_play(). By using
+ the fallback "1", we make sure that this won't
+ happen again. */
+ alsa_period_size = 1;
+
ad->period_frames = alsa_period_size;
ad->period_position = 0;
diff --git a/src/output/ao_plugin.c b/src/output/ao_plugin.c
index 6fedbc6..42ece5a 100644
--- a/src/output/ao_plugin.c
+++ b/src/output/ao_plugin.c
@@ -106,12 +106,14 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0,
"\"%s\" is not a valid ao driver",
value);
+ g_free(ad);
return NULL;
}
if ((ai = ao_driver_info(ad->driver)) == NULL) {
g_set_error(error, ao_output_quark(), 0,
"problems getting driver info");
+ g_free(ad);
return NULL;
}
@@ -129,6 +131,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0,
"problems parsing options \"%s\"",
options[i]);
+ g_free(ad);
return NULL;
}
diff --git a/src/output/httpd_client.c b/src/output/httpd_client.c
index f5e1492..1119a78 100644
--- a/src/output/httpd_client.c
+++ b/src/output/httpd_client.c
@@ -143,6 +143,8 @@ httpd_client_unref_page(gpointer data, G_GNUC_UNUSED gpointer user_data)
void
httpd_client_free(struct httpd_client *client)
{
+ assert(client != NULL);
+
if (client->state == RESPONSE) {
if (client->write_source_id != 0)
g_source_remove(client->write_source_id);
@@ -169,6 +171,8 @@ httpd_client_free(struct httpd_client *client)
static void
httpd_client_close(struct httpd_client *client)
{
+ assert(client != NULL);
+
httpd_output_remove_client(client->httpd, client);
httpd_client_free(client);
}
@@ -179,6 +183,9 @@ httpd_client_close(struct httpd_client *client)
static void
httpd_client_begin_response(struct httpd_client *client)
{
+ assert(client != NULL);
+ assert(client->state != RESPONSE);
+
client->state = RESPONSE;
client->write_source_id = 0;
client->pages = g_queue_new();
@@ -239,6 +246,9 @@ httpd_client_handle_line(struct httpd_client *client, const char *line)
static char *
httpd_client_read_line(struct httpd_client *client)
{
+ assert(client != NULL);
+ assert(client->state != RESPONSE);
+
const char *p, *newline;
size_t length;
char *line;
@@ -271,6 +281,7 @@ httpd_client_send_response(struct httpd_client *client)
GIOStatus status;
gsize bytes_written;
+ assert(client != NULL);
assert(client->state == RESPONSE);
if (!client->metadata_requested) {
@@ -334,14 +345,19 @@ httpd_client_send_response(struct httpd_client *client)
static bool
httpd_client_received(struct httpd_client *client)
{
+ assert(client != NULL);
+ assert(client->state != RESPONSE);
+
char *line;
bool success;
while ((line = httpd_client_read_line(client)) != NULL) {
success = httpd_client_handle_line(client, line);
g_free(line);
- if (!success)
+ if (!success) {
+ assert(client->state != RESPONSE);
return false;
+ }
if (client->state == RESPONSE) {
if (!fifo_buffer_is_empty(client->input)) {
@@ -370,7 +386,14 @@ httpd_client_read(struct httpd_client *client)
if (client->state == RESPONSE) {
/* the client has already sent the request, and he
must not send more */
- g_warning("unexpected input from client");
+ char buffer[1];
+
+ status = g_io_channel_read_chars(client->channel, buffer,
+ sizeof(buffer), &bytes_read,
+ NULL);
+ if (status == G_IO_STATUS_NORMAL)
+ g_warning("unexpected input from client");
+
return false;
}
diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c
index 6650d89..40ad05c 100644
--- a/src/output/httpd_output_plugin.c
+++ b/src/output/httpd_output_plugin.c
@@ -103,6 +103,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (encoder_plugin == NULL) {
g_set_error(error, httpd_output_quark(), 0,
"No such encoder: %s", encoder_name);
+ g_free(httpd);
return NULL;
}
@@ -492,7 +493,8 @@ httpd_output_pause(void *data)
if (has_clients) {
static const char silence[1020];
- return httpd_output_play(data, silence, sizeof(silence), NULL);
+ return httpd_output_play(data, silence, sizeof(silence),
+ NULL) > 0;
} else {
g_usleep(100000);
return true;
@@ -521,7 +523,7 @@ httpd_output_tag(void *data, const struct tag *tag)
/* flush the current stream, and end it */
- encoder_flush(httpd->encoder, NULL);
+ encoder_pre_tag(httpd->encoder, NULL);
httpd_output_encoder_to_clients(httpd);
/* send the tag to the encoder - which starts a new
diff --git a/src/output/osx_plugin.c b/src/output/osx_plugin.c
index ce82656..7639f3b 100644
--- a/src/output/osx_plugin.c
+++ b/src/output/osx_plugin.c
@@ -95,12 +95,6 @@ static void osx_output_close(void *data)
{
struct osx_output *od = data;
- g_mutex_lock(od->mutex);
- while (od->len) {
- g_cond_wait(od->condition, od->mutex);
- }
- g_mutex_unlock(od->mutex);
-
AudioOutputUnitStop(od->au);
AudioUnitUninitialize(od->au);
CloseComponent(od->au);
@@ -143,8 +137,8 @@ osx_render(void *vdata,
if (od->pos >= od->buffer_size)
od->pos = 0;
- g_mutex_unlock(od->mutex);
g_cond_signal(od->condition);
+ g_mutex_unlock(od->mutex);
buffer->mDataByteSize = buffer_size;
diff --git a/src/output/pulse_output_plugin.c b/src/output/pulse_output_plugin.c
index d29fbd7..34d7365 100644
--- a/src/output/pulse_output_plugin.c
+++ b/src/output/pulse_output_plugin.c
@@ -207,6 +207,9 @@ pulse_output_subscribe_cb(pa_context *context,
static bool
pulse_output_connect(struct pulse_output *po, GError **error_r)
{
+ assert(po != NULL);
+ assert(po->context != NULL);
+
int error;
error = pa_context_connect(po->context, po->server,
@@ -222,6 +225,44 @@ pulse_output_connect(struct pulse_output *po, GError **error_r)
}
/**
+ * Frees and clears the stream.
+ */
+static void
+pulse_output_delete_stream(struct pulse_output *po)
+{
+ assert(po != NULL);
+ assert(po->stream != NULL);
+
+#if PA_CHECK_VERSION(0,9,8)
+ pa_stream_set_suspended_callback(po->stream, NULL, NULL);
+#endif
+
+ pa_stream_set_state_callback(po->stream, NULL, NULL);
+ pa_stream_set_write_callback(po->stream, NULL, NULL);
+
+ pa_stream_disconnect(po->stream);
+ pa_stream_unref(po->stream);
+ po->stream = NULL;
+}
+
+/**
+ * Frees and clears the context.
+ */
+static void
+pulse_output_delete_context(struct pulse_output *po)
+{
+ assert(po != NULL);
+ assert(po->context != NULL);
+
+ pa_context_set_state_callback(po->context, NULL, NULL);
+ pa_context_set_subscribe_callback(po->context, NULL, NULL);
+
+ pa_context_disconnect(po->context);
+ pa_context_unref(po->context);
+ po->context = NULL;
+}
+
+/**
* Create, set up and connect a context.
*
* @return true on success, false on error
@@ -229,6 +270,9 @@ pulse_output_connect(struct pulse_output *po, GError **error_r)
static bool
pulse_output_setup_context(struct pulse_output *po, GError **error_r)
{
+ assert(po != NULL);
+ assert(po->mainloop != NULL);
+
po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop),
MPD_PULSE_NAME);
if (po->context == NULL) {
@@ -243,25 +287,13 @@ pulse_output_setup_context(struct pulse_output *po, GError **error_r)
pulse_output_subscribe_cb, po);
if (!pulse_output_connect(po, error_r)) {
- pa_context_unref(po->context);
- po->context = NULL;
+ pulse_output_delete_context(po);
return false;
}
return true;
}
-/**
- * Frees and clears the context.
- */
-static void
-pulse_output_delete_context(struct pulse_output *po)
-{
- pa_context_disconnect(po->context);
- pa_context_unref(po->context);
- po->context = NULL;
-}
-
static void *
pulse_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
const struct config_param *param,
@@ -347,6 +379,8 @@ pulse_output_disable(void *data)
{
struct pulse_output *po = data;
+ assert(po->mainloop != NULL);
+
pa_threaded_mainloop_stop(po->mainloop);
if (po->context != NULL)
pulse_output_delete_context(po);
@@ -363,6 +397,8 @@ pulse_output_disable(void *data)
static bool
pulse_output_wait_connection(struct pulse_output *po, GError **error_r)
{
+ assert(po->mainloop != NULL);
+
pa_context_state_t state;
pa_threaded_mainloop_lock(po->mainloop);
@@ -399,11 +435,32 @@ pulse_output_wait_connection(struct pulse_output *po, GError **error_r)
}
}
+#if PA_CHECK_VERSION(0,9,8)
+
+static void
+pulse_output_stream_suspended_cb(G_GNUC_UNUSED pa_stream *stream, void *userdata)
+{
+ struct pulse_output *po = userdata;
+
+ assert(stream == po->stream || po->stream == NULL);
+ assert(po->mainloop != NULL);
+
+ /* wake up the main loop to break out of the loop in
+ pulse_output_play() */
+ pa_threaded_mainloop_signal(po->mainloop, 0);
+}
+
+#endif
+
static void
pulse_output_stream_state_cb(pa_stream *stream, void *userdata)
{
struct pulse_output *po = userdata;
+ assert(stream == po->stream || po->stream == NULL);
+ assert(po->mainloop != NULL);
+ assert(po->context != NULL);
+
switch (pa_stream_get_state(stream)) {
case PA_STREAM_READY:
if (po->mixer != NULL)
@@ -432,6 +489,8 @@ pulse_output_stream_write_cb(G_GNUC_UNUSED pa_stream *stream, size_t nbytes,
{
struct pulse_output *po = userdata;
+ assert(po->mainloop != NULL);
+
po->writable = nbytes;
pa_threaded_mainloop_signal(po->mainloop, 0);
}
@@ -444,6 +503,8 @@ pulse_output_open(void *data, struct audio_format *audio_format,
pa_sample_spec ss;
int error;
+ assert(po->mainloop != NULL);
+
if (po->context != NULL) {
switch (pa_context_get_state(po->context)) {
case PA_CONTEXT_UNCONNECTED:
@@ -487,6 +548,11 @@ pulse_output_open(void *data, struct audio_format *audio_format,
return false;
}
+#if PA_CHECK_VERSION(0,9,8)
+ pa_stream_set_suspended_callback(po->stream,
+ pulse_output_stream_suspended_cb, po);
+#endif
+
pa_stream_set_state_callback(po->stream,
pulse_output_stream_state_cb, po);
pa_stream_set_write_callback(po->stream,
@@ -497,8 +563,7 @@ pulse_output_open(void *data, struct audio_format *audio_format,
error = pa_stream_connect_playback(po->stream, po->sink,
NULL, 0, NULL, NULL);
if (error < 0) {
- pa_stream_unref(po->stream);
- po->stream = NULL;
+ pulse_output_delete_stream(po);
g_set_error(error_r, pulse_output_quark(), 0,
"pa_stream_connect_playback() has failed: %s",
@@ -522,6 +587,8 @@ pulse_output_close(void *data)
struct pulse_output *po = data;
pa_operation *o;
+ assert(po->mainloop != NULL);
+
pa_threaded_mainloop_lock(po->mainloop);
if (pa_stream_get_state(po->stream) == PA_STREAM_READY) {
@@ -534,9 +601,7 @@ pulse_output_close(void *data)
pulse_wait_for_operation(po->mainloop, o);
}
- pa_stream_disconnect(po->stream);
- pa_stream_unref(po->stream);
- po->stream = NULL;
+ pulse_output_delete_stream(po);
if (po->context != NULL &&
pa_context_get_state(po->context) != PA_CONTEXT_READY)
@@ -556,6 +621,8 @@ pulse_output_check_stream(struct pulse_output *po)
{
pa_stream_state_t state = pa_stream_get_state(po->stream);
+ assert(po->mainloop != NULL);
+
switch (state) {
case PA_STREAM_READY:
case PA_STREAM_FAILED:
@@ -637,6 +704,8 @@ pulse_output_stream_pause(struct pulse_output *po, bool pause,
{
pa_operation *o;
+ assert(po->mainloop != NULL);
+ assert(po->context != NULL);
assert(po->stream != NULL);
o = pa_stream_cork(po->stream, pause,
@@ -667,6 +736,7 @@ pulse_output_play(void *data, const void *chunk, size_t size, GError **error_r)
struct pulse_output *po = data;
int error;
+ assert(po->mainloop != NULL);
assert(po->stream != NULL);
pa_threaded_mainloop_lock(po->mainloop);
@@ -683,19 +753,30 @@ pulse_output_play(void *data, const void *chunk, size_t size, GError **error_r)
/* unpause if previously paused */
if (pulse_output_stream_is_paused(po) &&
- !pulse_output_stream_pause(po, false, error_r))
+ !pulse_output_stream_pause(po, false, error_r)) {
+ pa_threaded_mainloop_unlock(po->mainloop);
return 0;
+ }
/* wait until the server allows us to write */
while (po->writable == 0) {
+#if PA_CHECK_VERSION(0,9,8)
+ if (pa_stream_is_suspended(po->stream)) {
+ pa_threaded_mainloop_unlock(po->mainloop);
+ g_set_error(error_r, pulse_output_quark(), 0,
+ "suspended");
+ return 0;
+ }
+#endif
+
pa_threaded_mainloop_wait(po->mainloop);
if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
pa_threaded_mainloop_unlock(po->mainloop);
g_set_error(error_r, pulse_output_quark(), 0,
"disconnected");
- return false;
+ return 0;
}
}
@@ -725,6 +806,7 @@ pulse_output_cancel(void *data)
struct pulse_output *po = data;
pa_operation *o;
+ assert(po->mainloop != NULL);
assert(po->stream != NULL);
pa_threaded_mainloop_lock(po->mainloop);
@@ -756,6 +838,7 @@ pulse_output_pause(void *data)
struct pulse_output *po = data;
GError *error = NULL;
+ assert(po->mainloop != NULL);
assert(po->stream != NULL);
pa_threaded_mainloop_lock(po->mainloop);
diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c
index c01d927..10d6410 100644
--- a/src/output/recorder_output_plugin.c
+++ b/src/output/recorder_output_plugin.c
@@ -79,23 +79,27 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (encoder_plugin == NULL) {
g_set_error(error_r, recorder_output_quark(), 0,
"No such encoder: %s", encoder_name);
- return NULL;
+ goto failure;
}
recorder->path = config_get_block_string(param, "path", NULL);
if (recorder->path == NULL) {
g_set_error(error_r, recorder_output_quark(), 0,
"'path' not configured");
- return NULL;
+ goto failure;
}
/* initialize encoder */
recorder->encoder = encoder_init(encoder_plugin, param, error_r);
if (recorder->encoder == NULL)
- return NULL;
+ goto failure;
return recorder;
+
+failure:
+ g_free(recorder);
+ return NULL;
}
static void
diff --git a/src/output/shout_plugin.c b/src/output/shout_plugin.c
index baaeccf..35efd9f 100644
--- a/src/output/shout_plugin.c
+++ b/src/output/shout_plugin.c
@@ -152,7 +152,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (port == 0) {
g_set_error(error, shout_output_quark(), 0,
"shout port must be configured");
- return NULL;
+ goto failure;
}
check_block_param("password");
@@ -174,21 +174,21 @@ my_shout_init_driver(const struct audio_format *audio_format,
"shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i",
value, param->line);
- return NULL;
+ goto failure;
}
if (config_get_block_string(param, "bitrate", NULL) != NULL) {
g_set_error(error, shout_output_quark(), 0,
"quality and bitrate are "
"both defined");
- return NULL;
+ goto failure;
}
} else {
value = config_get_block_string(param, "bitrate", NULL);
if (value == NULL) {
g_set_error(error, shout_output_quark(), 0,
"neither bitrate nor quality defined");
- return NULL;
+ goto failure;
}
sd->bitrate = strtol(value, &test, 10);
@@ -196,7 +196,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (*test != '\0' || sd->bitrate <= 0) {
g_set_error(error, shout_output_quark(), 0,
"bitrate must be a positive integer");
- return NULL;
+ goto failure;
}
}
@@ -206,12 +206,12 @@ my_shout_init_driver(const struct audio_format *audio_format,
g_set_error(error, shout_output_quark(), 0,
"couldn't find shout encoder plugin \"%s\"",
encoding);
- return NULL;
+ goto failure;
}
sd->encoder = encoder_init(encoder_plugin, param, error);
if (sd->encoder == NULL)
- return NULL;
+ goto failure;
if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0)
shout_format = SHOUT_FORMAT_MP3;
@@ -225,7 +225,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
g_set_error(error, shout_output_quark(), 0,
"you cannot stream \"%s\" to shoutcast, use mp3",
encoding);
- return NULL;
+ goto failure;
} else if (0 == strcmp(value, "shoutcast"))
protocol = SHOUT_PROTOCOL_ICY;
else if (0 == strcmp(value, "icecast1"))
@@ -237,7 +237,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
"shout protocol \"%s\" is not \"shoutcast\" or "
"\"icecast1\"or \"icecast2\"",
value);
- return NULL;
+ goto failure;
}
} else {
protocol = SHOUT_PROTOCOL_HTTP;
@@ -256,7 +256,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
shout_set_agent(sd->shout_conn, "MPD") != SHOUTERR_SUCCESS) {
g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn));
- return NULL;
+ goto failure;
}
/* optional paramters */
@@ -267,14 +267,14 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (value != NULL && shout_set_genre(sd->shout_conn, value)) {
g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn));
- return NULL;
+ goto failure;
}
value = config_get_block_string(param, "description", NULL);
if (value != NULL && shout_set_description(sd->shout_conn, value)) {
g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn));
- return NULL;
+ goto failure;
}
{
@@ -300,6 +300,10 @@ my_shout_init_driver(const struct audio_format *audio_format,
}
return sd;
+
+failure:
+ free_shout_data(sd);
+ return NULL;
}
static bool
@@ -507,7 +511,7 @@ static void my_shout_set_tag(void *data,
if (sd->encoder->plugin->tag != NULL) {
/* encoder plugin supports stream tags */
- ret = encoder_flush(sd->encoder, &error);
+ ret = encoder_pre_tag(sd->encoder, &error);
if (!ret) {
g_warning("%s", error->message);
g_error_free(error);
diff --git a/src/output_all.c b/src/output_all.c
index 19c0f01..4e0b2eb 100644
--- a/src/output_all.c
+++ b/src/output_all.c
@@ -206,26 +206,13 @@ static void audio_output_wait_all(void)
}
/**
- * Signals the audio output if it is open. This function locks the
- * mutex.
- */
-static void
-audio_output_lock_signal(struct audio_output *ao)
-{
- g_mutex_lock(ao->mutex);
- if (audio_output_is_open(ao))
- g_cond_signal(ao->cond);
- g_mutex_unlock(ao->mutex);
-}
-
-/**
* Signals all audio outputs which are open.
*/
static void
-audio_output_signal_all(void)
+audio_output_allow_play_all(void)
{
for (unsigned i = 0; i < num_audio_outputs; ++i)
- audio_output_lock_signal(&audio_outputs[i]);
+ audio_output_allow_play(&audio_outputs[i]);
}
static void
@@ -530,7 +517,7 @@ audio_output_all_cancel(void)
/* the audio outputs are now waiting for a signal, to
synchronize the cleared music pipe */
- audio_output_signal_all();
+ audio_output_allow_play_all();
/* invalidate elapsed_time */
diff --git a/src/output_control.c b/src/output_control.c
index 0823b66..f8c5cd8 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -115,6 +115,8 @@ audio_output_open(struct audio_output *ao,
{
bool open;
+ assert(ao != NULL);
+ assert(ao->allow_play);
assert(audio_format_valid(audio_format));
assert(mp != NULL);
@@ -140,10 +142,6 @@ audio_output_open(struct audio_output *ao,
/* we're not using audio_output_cancel() here,
because that function is asynchronous */
ao_command(ao, AO_COMMAND_CANCEL);
-
- /* the audio output is now waiting for a
- signal; wake it up immediately */
- g_cond_signal(ao->cond);
}
return true;
@@ -181,6 +179,7 @@ static void
audio_output_close_locked(struct audio_output *ao)
{
assert(ao != NULL);
+ assert(ao->allow_play);
if (ao->mixer != NULL)
mixer_auto_close(ao->mixer);
@@ -223,6 +222,8 @@ audio_output_play(struct audio_output *ao)
{
g_mutex_lock(ao->mutex);
+ assert(ao->allow_play);
+
if (audio_output_is_open(ao))
g_cond_signal(ao->cond);
@@ -238,6 +239,7 @@ void audio_output_pause(struct audio_output *ao)
mixer_auto_close(ao->mixer);
g_mutex_lock(ao->mutex);
+ assert(ao->allow_play);
if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_PAUSE);
g_mutex_unlock(ao->mutex);
@@ -247,6 +249,7 @@ void
audio_output_drain_async(struct audio_output *ao)
{
g_mutex_lock(ao->mutex);
+ assert(ao->allow_play);
if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_DRAIN);
g_mutex_unlock(ao->mutex);
@@ -255,8 +258,24 @@ audio_output_drain_async(struct audio_output *ao)
void audio_output_cancel(struct audio_output *ao)
{
g_mutex_lock(ao->mutex);
- if (audio_output_is_open(ao))
+
+ if (audio_output_is_open(ao)) {
+ ao->allow_play = false;
ao_command_async(ao, AO_COMMAND_CANCEL);
+ }
+
+ g_mutex_unlock(ao->mutex);
+}
+
+void
+audio_output_allow_play(struct audio_output *ao)
+{
+ g_mutex_lock(ao->mutex);
+
+ ao->allow_play = true;
+ if (audio_output_is_open(ao))
+ g_cond_signal(ao->cond);
+
g_mutex_unlock(ao->mutex);
}
@@ -287,6 +306,7 @@ void audio_output_finish(struct audio_output *ao)
if (ao->thread != NULL) {
g_mutex_lock(ao->mutex);
+ assert(ao->allow_play);
ao_command(ao, AO_COMMAND_KILL);
g_mutex_unlock(ao->mutex);
g_thread_join(ao->thread);
diff --git a/src/output_control.h b/src/output_control.h
index 7f4f4a5..f0e317d 100644
--- a/src/output_control.h
+++ b/src/output_control.h
@@ -70,8 +70,19 @@ void audio_output_pause(struct audio_output *ao);
void
audio_output_drain_async(struct audio_output *ao);
+/**
+ * Clear the "allow_play" flag and send the "CANCEL" command
+ * asynchronously. To finish the operation, the caller has to call
+ * audio_output_allow_play().
+ */
void audio_output_cancel(struct audio_output *ao);
+/**
+ * Set the "allow_play" and signal the thread.
+ */
+void
+audio_output_allow_play(struct audio_output *ao);
+
void audio_output_close(struct audio_output *ao);
/**
diff --git a/src/output_init.c b/src/output_init.c
index f4700df..96f87f5 100644
--- a/src/output_init.c
+++ b/src/output_init.c
@@ -189,6 +189,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
ao->really_enabled = false;
ao->open = false;
ao->pause = false;
+ ao->allow_play = true;
ao->fail_timer = NULL;
pcm_buffer_init(&ao->cross_fade_buffer);
diff --git a/src/output_internal.h b/src/output_internal.h
index 18d4313..7102ea5 100644
--- a/src/output_internal.h
+++ b/src/output_internal.h
@@ -110,6 +110,15 @@ struct audio_output {
bool pause;
/**
+ * When this flag is set, the output thread will not do any
+ * playback. It will wait until the flag is cleared.
+ *
+ * This is used to synchronize the "clear" operation on the
+ * shared music pipe during the CANCEL command.
+ */
+ bool allow_play;
+
+ /**
* If not NULL, the device has failed, and this timer is used
* to estimate how long it should stay disabled (unless
* explicitly reopened with "play").
diff --git a/src/output_thread.c b/src/output_thread.c
index 4e04467..bf56ca9 100644
--- a/src/output_thread.c
+++ b/src/output_thread.c
@@ -640,15 +640,14 @@ static gpointer audio_output_task(gpointer arg)
case AO_COMMAND_CANCEL:
ao->chunk = NULL;
- if (ao->open)
+
+ if (ao->open) {
+ g_mutex_unlock(ao->mutex);
ao_plugin_cancel(ao->plugin, ao->data);
- ao_command_finished(ao);
+ g_mutex_lock(ao->mutex);
+ }
- /* the player thread will now clear our music
- pipe - wait for a notify, to give it some
- time */
- if (ao->command == AO_COMMAND_NONE)
- g_cond_wait(ao->cond, ao->mutex);
+ ao_command_finished(ao);
continue;
case AO_COMMAND_KILL:
@@ -658,7 +657,7 @@ static gpointer audio_output_task(gpointer arg)
return NULL;
}
- if (ao->open && ao_play(ao))
+ if (ao->open && ao->allow_play && ao_play(ao))
/* don't wait for an event if there are more
chunks in the pipe */
continue;
diff --git a/src/pipe.c b/src/pipe.c
index 7e4b0d0..2f5f70e 100644
--- a/src/pipe.c
+++ b/src/pipe.c
@@ -187,5 +187,8 @@ music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk)
unsigned
music_pipe_size(const struct music_pipe *mp)
{
- return mp->size;
+ g_mutex_lock(mp->mutex);
+ unsigned size = mp->size;
+ g_mutex_unlock(mp->mutex);
+ return size;
}
diff --git a/src/pipe.h b/src/pipe.h
index f9540a3..efa7a84 100644
--- a/src/pipe.h
+++ b/src/pipe.h
@@ -20,6 +20,7 @@
#ifndef MPD_PIPE_H
#define MPD_PIPE_H
+#include <glib.h>
#include <stdbool.h>
#ifndef NDEBUG
@@ -38,6 +39,7 @@ struct music_pipe;
/**
* Creates a new #music_pipe object. It is empty.
*/
+G_GNUC_MALLOC
struct music_pipe *
music_pipe_new(void);
@@ -70,6 +72,7 @@ music_pipe_contains(const struct music_pipe *mp,
* Returns the first #music_chunk from the pipe. Returns NULL if the
* pipe is empty.
*/
+G_GNUC_PURE
const struct music_chunk *
music_pipe_peek(const struct music_pipe *mp);
@@ -96,9 +99,11 @@ music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk);
/**
* Returns the number of chunks currently in this pipe.
*/
+G_GNUC_PURE
unsigned
music_pipe_size(const struct music_pipe *mp);
+G_GNUC_PURE
static inline bool
music_pipe_empty(const struct music_pipe *mp)
{
diff --git a/src/player_thread.c b/src/player_thread.c
index cce51c1..a89e599 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -618,7 +618,9 @@ play_chunk(struct song *song, struct music_chunk *chunk,
return true;
}
+ player_lock();
pc.bit_rate = chunk->bit_rate;
+ player_unlock();
/* send the chunk to the audio outputs */
diff --git a/src/playlist_control.c b/src/playlist_control.c
index ce9bc84..76066d2 100644
--- a/src/playlist_control.c
+++ b/src/playlist_control.c
@@ -222,10 +222,12 @@ playlist_seek_song(struct playlist *playlist, unsigned song, float seek_time)
playlist->error_count = 0;
if (!playlist->playing || (unsigned)playlist->current != i) {
- /* seeking is not within the current song - first
- start playing the new song */
+ /* seeking is not within the current song - prepare
+ song change */
+
+ playlist->playing = true;
+ playlist->current = i;
- playlist_play_order(playlist, i);
queued = NULL;
}
diff --git a/src/sticker.c b/src/sticker.c
index c59cdd0..f6cd043 100644
--- a/src/sticker.c
+++ b/src/sticker.c
@@ -579,8 +579,10 @@ sticker_load(const char *type, const char *uri)
bool success;
success = sticker_list_values(sticker->table, type, uri);
- if (!success)
+ if (!success) {
+ sticker_free(sticker);
return NULL;
+ }
if (g_hash_table_size(sticker->table) == 0) {
/* don't return empty sticker objects */
diff --git a/src/update_walk.c b/src/update_walk.c
index 845f152..bf3c8f5 100644
--- a/src/update_walk.c
+++ b/src/update_walk.c
@@ -714,8 +714,14 @@ skip_symlink(const struct directory *directory, const char *utf8_name)
return false;
}
- if (buffer[0] == '/')
- return !follow_outside_symlinks;
+ if (g_path_is_absolute(buffer)) {
+ /* if the symlink points to an absolute path, see if
+ that path is inside the music directory */
+ const char *relative = map_to_relative_path(buffer);
+ return relative > buffer
+ ? !follow_inside_symlinks
+ : !follow_outside_symlinks;
+ }
p = buffer;
while (*p == '.') {
diff --git a/test/read_conf.c b/test/read_conf.c
index 4f43e6a..f1b38ca 100644
--- a/test/read_conf.c
+++ b/test/read_conf.c
@@ -37,30 +37,28 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain,
int main(int argc, char **argv)
{
- const char *path, *name, *value;
- GError *error = NULL;
- bool success;
- int ret;
-
if (argc != 3) {
g_printerr("Usage: read_conf FILE SETTING\n");
return 1;
}
- path = argv[1];
- name = argv[2];
+ const char *path = argv[1];
+ const char *name = argv[2];
g_log_set_default_handler(my_log_func, NULL);
config_global_init();
- success = config_read_file(path, &error);
+
+ GError *error = NULL;
+ bool success = config_read_file(path, &error);
if (!success) {
g_printerr("%s:", error->message);
g_error_free(error);
return 1;
}
- value = config_get_string(name, NULL);
+ const char *value = config_get_string(name, NULL);
+ int ret;
if (value != NULL) {
g_print("%s\n", value);
ret = 0;
@@ -70,5 +68,5 @@ int main(int argc, char **argv)
}
config_global_finish();
- return 0;
+ return ret;
}
diff --git a/test/run_filter.c b/test/run_filter.c
index ee2445e..3758eb5 100644
--- a/test/run_filter.c
+++ b/test/run_filter.c
@@ -106,7 +106,6 @@ int main(int argc, char **argv)
struct filter *filter;
const struct audio_format *out_audio_format;
char buffer[4096];
- size_t frame_size;
if (argc < 3 || argc > 4) {
g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n");
@@ -162,8 +161,6 @@ int main(int argc, char **argv)
g_printerr("audio_format=%s\n",
audio_format_to_string(out_audio_format, &af_string));
- frame_size = audio_format_frame_size(&audio_format);
-
/* play */
while (true) {
--
Git repository for pkg-mpd
More information about the Pkg-mpd-commits
mailing list