Commit 1370cca9 authored by Led's avatar Led

0.13.0

parent ffeacd4b
Developer -> Warren Dukes <warren.dukes@gmail.com> Current Developers
Developer -> tw-nym ------------------
audiofile support and command.c cleanup -> normalperson Warren Dukes <warren.dukes@gmail.com>
setuid patch -> Nagilum general
'next' and 'previous' patch -> Niklas Hofer
command.c and signal handling cleanup -> mackstann J. Alexander Treuman <jat@spatialrift.net>
replayGain -> AliasMrJones general, MP3, ID3, PulseAudio, format conversion, stored playlists
Eric Wong <normalperson@yhbt.net>
general, FLAC, mpd-ke branch
Jos Anarch <anarchsss@gmail.com>
JACK plugin
Guus Sliepen <guus@sliepen.eu.org>
libsamplerate code
Jim Ramsay <i.am@jimramsay.com>
Zerconf/avahi support
Qball Cow <qballcow@gmail.com>
Playlist commands
Patrik Weiskircher <pat@icore.at>
Stored playlist commands
Former Developers
-----------------
tw-nym
Nagilum
setuid
Niklas Hofer
'next' and 'previous' patch
mackstann
command.c and signal handling cleanup
AliasMrJones
replayGain
mp4ff copyrighted by M. Bakker, Ahead Software AG, http://www.nero.com mp4ff copyrighted by M. Bakker, Ahead Software AG, http://www.nero.com
compress.[ch] copyrighted by fluffy <fluffy@beesbuzz.biz> compress.[ch] copyrighted by fluffy <fluffy@beesbuzz.biz>
ver 0.13.0 (2007/5/28)
* New JACK audio output
* Support for "file" as an alternative to "filename" in search, find, and list
* FLAC 1.1.3 API support
* New playlistadd command for adding to stored playlists
* New playlistclear command for clearing stored playlists
* Fix a bug where "find any" and "list <type> any" wouldn't return any results
* Make "list any" return an error instead of no results and an OK
* New gapless_mp3_playback option to disable gapless MP3 playback
* Support for seeking HTTP streams
* Zeroconf support using Avahi
* libsamplerate support for high quality audio resampling
* ID3v2 "Original Artist/Performer" tag support
* New playlistsearch command for searching the playlist (similar to "search")
* New playlistfind command for finding songs in the playlist (similar to "find")
* libmikmod 3.2.0 beta support
* New tagtypes command for retrieving a list of available tag types
* Fix a bug where no ACK was returned if loading a playlist failed
* Fix a bug where db_update in stats would be 0 after initial database creation
* New count command for getting stats on found songs (similar to "find")
* New playlistmove command for moving songs in stored playlists
* New playlistdelete command for deleting songs from stored playlists
* New rename command for renaming stored playlists
* Increased default buffer_before_play from 0% to 10% to prevent skipping
* Lots of bug fixes, cleaned up code, and performance improvements
ver 0.12.2 (2007/3/20) ver 0.12.2 (2007/3/20)
* Fix a bug where clients could cause MPD to segfault * Fix a bug where clients could cause MPD to segfault
...@@ -15,7 +41,6 @@ ver 0.12.0 (2006/9/22) ...@@ -15,7 +41,6 @@ ver 0.12.0 (2006/9/22)
* ALSA * ALSA
* OSS * OSS
* OS X * OS X
* Sun
* Media MVP * Media MVP
* PulseAudio * PulseAudio
* Shout (Icecast or Shoutcast) * Shout (Icecast or Shoutcast)
......
...@@ -20,6 +20,9 @@ Linux. You will need libasound. ...@@ -20,6 +20,9 @@ Linux. You will need libasound.
PulseAudio - http://www.pulseaudio.org/ PulseAudio - http://www.pulseaudio.org/
An advanced sound daemon. You will need libpulse. An advanced sound daemon. You will need libpulse.
JACK - http://www.jackaudio.org/
A low-latency sound daemon.
libshout - http://www.icecast.org/ libshout - http://www.icecast.org/
For streaming to an Icecast or Shoutcast server. For streaming to an Icecast or Shoutcast server.
...@@ -43,7 +46,8 @@ For FLAC support. You will need version 1.1.0 or higher of libflac. ...@@ -43,7 +46,8 @@ For FLAC support. You will need version 1.1.0 or higher of libflac.
OggFLAC - http://www.xiph.org/ogg/vorbis/ and http://flac.sourceforge.net/ OggFLAC - http://www.xiph.org/ogg/vorbis/ and http://flac.sourceforge.net/
For OggFLAC support. You will need liboggflac, which can be built from the For OggFLAC support. You will need liboggflac, which can be built from the
FLAC sources if libogg is already installed. FLAC sources if libogg is already installed. Versions of flac 1.1.3 and
greater will automatically detect and use OggFLAC if it's available.
Audio File - http://www.68k.org/~michael/audiofile/ Audio File - http://www.68k.org/~michael/audiofile/
For WAVE, AIFF, and AU support. You will need libaudiofile. For WAVE, AIFF, and AU support. You will need libaudiofile.
...@@ -57,6 +61,15 @@ For Musepack support. ...@@ -57,6 +61,15 @@ For Musepack support.
MikMod - http://mikmod.raphnet.net/ MikMod - http://mikmod.raphnet.net/
For MOD support. You will need libmikmod. For MOD support. You will need libmikmod.
Optional Miscellaneous Dependencies
-----------------------------------
Avahi - http://www.avahi.org/
For Zeroconf support.
libsamplerate - http://www.mega-nerd.com/SRC/
For advanced samplerate conversions.
Download Download
-------- --------
...@@ -112,8 +125,7 @@ mp3's. ...@@ -112,8 +125,7 @@ mp3's.
Using MPD Using MPD
--------- ---------
You can download a web interface (phpMp) to MPD at <http://www.musicpd.org/>. You can download many different interfaces for MPD at
<http://mpd.wikia.com/wiki/Clients>
Also, several other clients can be found for MPD at <http://www.musicpd.org/>.
MPD can be interfaced directly using telnet (see COMMANDS, if you are brave). MPD can be interfaced directly using telnet (see COMMANDS, if you are brave).
Music Player Daemon (MPD) Music Player Daemon (MPD)
http://www.musicpd.org http://www.musicpd.org
A daemon for playing music (mp3, ogg vorbis, and flac). Music is played A daemon for playing music of various formats. Music is played through the
through the server's audio device. The daemon stores info about all available server's audio device. The daemon stores info about all available music,
music, and this info can be easily searched and retrieved. Player control, info and this info can be easily searched and retrieved. Player control, info
retrieval, and playlist management can all be managed remotely. retrieval, and playlist management can all be managed remotely.
To install MPD, see INSTALL. To install MPD, see INSTALL.
MPD includes 3 libraries in the source. libid3tag and libmad are released under MPD includes mp4ff in the source, due to licensing issues of the newer
the GPL and copyrighted by Robert Leslie (http://www.underbit.com/products/mad). version and includes bugfixes with the properly licensed version. mp4ff is
mp4ff is released under the GPL and copyrighted by M. Bakker, Ahead Software AG released under the GPL and copyrighted by M. Bakker, Ahead Software AG
(http://www.nero.com) and is distributed as a part of the FAAD2 - Freeware (http://www.nero.com) and is distributed as a part of the FAAD2 - Freeware
Advance Audio (AAC) Decoder. Advance Audio (AAC) Decoder.
MPD is released under the GNU Public License. MPD is released under the GNU Public License.
......
0.13 0.14
---- ----
*) data structures *) data structures
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
*) cleanup linked list code! *) cleanup linked list code!
*) implement listener socket protocol as documented here: *) implement listener socket protocol as documented here:
http://www.musicpd.org/wiki/moin.cgi/MpdListenerProtocol http://mpd.wikia.com/wiki/MusicPlayerDaemonListenerProtocol
*) support for dynamically loading plugins *) support for dynamically loading plugins
*) cleanup input plugins "API" *) cleanup input plugins "API"
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
*) audio output *) audio output
*) write a esd native audioOutput *) write a esd native audioOutput
*) write a nas native audioOutput *) write a nas native audioOutput
*) need better resampling code
*) allowing "pausing" of audio output devices *) allowing "pausing" of audio output devices
*) while pausing, play silence for the devices that don't support *) while pausing, play silence for the devices that don't support
"pausing" "pausing"
...@@ -41,17 +40,8 @@ ...@@ -41,17 +40,8 @@
*) abstract out state code from playlist.c *) abstract out state code from playlist.c
*) put MPD Version in statefile *) put MPD Version in statefile
*) rewrite saved playlist code *) add playlistreplace command (replace current playlist with saved playlist
*) abstract out saved playlists from playlist.c and keep playing)
*) command for displaying playlist contents
*) command for appending to playlist
*) new commands
*) clear <playlist> /* synonym for rm */
*) add <playlist> <path>
*) playlist <playlist> /* displays saved playlist */
*) replace <playlist> /* replace current playlist
with saved playlist and
keep playing */
*) add command for inserting songs in a specific position *) add command for inserting songs in a specific position
...@@ -61,7 +51,7 @@ ...@@ -61,7 +51,7 @@
*) bug fixes *) bug fixes
post-1.0 post-1.0
---- --------
*) rewrite audio pipe *) rewrite audio pipe
*) use pthreads/clone *) use pthreads/clone
......
Music Player Daemon (MPD) - UPGRADING Music Player Daemon (MPD) - UPGRADING
Upgrading to 0.13.0
-------------------
JACK, Avahi, and libsamplerate have been added as optional dependencies.
FLAC/OggFLAC now supports the 1.1.3 API, and libmikmod 3.2.0 betas are
supported as well.
New mpd.conf parameters include zeroconf_name, samplerate_converter, and
gapless_mp3_playback. See the mpd.conf man page or updated mpconf.example for
more information on these parameters.
Support for the ID3v2 "Original Artist/Performer" tag has been added. Your
MP3s will need to be rescanned for these tags to be included in the database.
This can be done by running mpd --create-db.
Upgrading to 0.12.0 Upgrading to 0.12.0
------------------- -------------------
......
...@@ -756,6 +756,46 @@ AC_CONFIG_COMMANDS_PRE( ...@@ -756,6 +756,46 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]) Usually this means the macro was only invoked conditionally.])
fi])]) fi])])
# serial 2
# AM_PROG_CC_C_O
# --------------
# Like AC_PROG_CC_C_O, but changed for automake.
# Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
AC_DEFUN([AM_PROG_CC_C_O],
[AC_REQUIRE([AC_PROG_CC_C_O])dnl
AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
# FIXME: we rely on the cache variable name because
# there is no other way.
set dummy $CC
ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
])
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
# serial 48 AC_PROG_LIBTOOL # serial 48 AC_PROG_LIBTOOL
...@@ -8066,7 +8106,7 @@ AC_ARG_ENABLE(libFLACtest, [ --disable-libFLACtest Do not try to compile ...@@ -8066,7 +8106,7 @@ AC_ARG_ENABLE(libFLACtest, [ --disable-libFLACtest Do not try to compile
elif test "x$libFLAC_prefix" != "x" ; then elif test "x$libFLAC_prefix" != "x" ; then
LIBFLAC_LIBS="-L$libFLAC_prefix/lib" LIBFLAC_LIBS="-L$libFLAC_prefix/lib"
elif test "x$prefix" != "xNONE" ; then elif test "x$prefix" != "xNONE" ; then
LIBFLAC_LIBS="-L$prefix/lib" LIBFLAC_LIBS="-L$libdir"
fi fi
LIBFLAC_LIBS="$LIBFLAC_LIBS -lFLAC -lm" LIBFLAC_LIBS="$LIBFLAC_LIBS -lFLAC -lm"
...@@ -8075,8 +8115,8 @@ AC_ARG_ENABLE(libFLACtest, [ --disable-libFLACtest Do not try to compile ...@@ -8075,8 +8115,8 @@ AC_ARG_ENABLE(libFLACtest, [ --disable-libFLACtest Do not try to compile
LIBFLAC_CFLAGS="-I$libFLAC_includes" LIBFLAC_CFLAGS="-I$libFLAC_includes"
elif test "x$libFLAC_prefix" != "x" ; then elif test "x$libFLAC_prefix" != "x" ; then
LIBFLAC_CFLAGS="-I$libFLAC_prefix/include" LIBFLAC_CFLAGS="-I$libFLAC_prefix/include"
elif test "x$prefix" != "xNONE"; then elif test "$prefix" != "xNONE"; then
LIBFLAC_CFLAGS="-I$prefix/include" LIBFLAC_CFLAGS="-I$libdir"
fi fi
AC_MSG_CHECKING(for libFLAC) AC_MSG_CHECKING(for libFLAC)
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
/* Define for audiofile support */ /* Define for audiofile support */
#undef HAVE_AUDIOFILE #undef HAVE_AUDIOFILE
/* Define to enable Avahi Zeroconf support */
#undef HAVE_AVAHI
/* Define to 1 if you have the <dlfcn.h> header file. */ /* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H #undef HAVE_DLFCN_H
...@@ -49,6 +52,9 @@ ...@@ -49,6 +52,9 @@
/* Define if IPv6 support present */ /* Define if IPv6 support present */
#undef HAVE_IPV6 #undef HAVE_IPV6
/* Define to enable JACK support */
#undef HAVE_JACK
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */ /* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET #undef HAVE_LANGINFO_CODESET
...@@ -58,6 +64,9 @@ ...@@ -58,6 +64,9 @@
/* Define to 1 if you have the `FLAC' library (-lFLAC). */ /* Define to 1 if you have the `FLAC' library (-lFLAC). */
#undef HAVE_LIBFLAC #undef HAVE_LIBFLAC
/* Define to enable libsamplerate */
#undef HAVE_LIBSAMPLERATE
/* Define if locale.h is present */ /* Define if locale.h is present */
#undef HAVE_LOCALE #undef HAVE_LOCALE
...@@ -94,7 +103,7 @@ ...@@ -94,7 +103,7 @@
/* Define for compiling OS X support */ /* Define for compiling OS X support */
#undef HAVE_OSX #undef HAVE_OSX
/* Define to enable PulseAudio */ /* Define to enable PulseAudio support */
#undef HAVE_PULSE #undef HAVE_PULSE
/* Define to 1 if you have the `setenv' function. */ /* Define to 1 if you have the `setenv' function. */
...@@ -118,9 +127,6 @@ ...@@ -118,9 +127,6 @@
/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H #undef HAVE_STRING_H
/* Define to enable SUN audio support */
#undef HAVE_SUN
/* Define if sys/inttypes.h present */ /* Define if sys/inttypes.h present */
#undef HAVE_SYS_INTTYPES_H #undef HAVE_SYS_INTTYPES_H
...@@ -136,6 +142,9 @@ ...@@ -136,6 +142,9 @@
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */ /* Name of package */
#undef PACKAGE #undef PACKAGE
......
#! /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.60 for mpd 0.12.2. # Generated by GNU Autoconf 2.60 for mpd 0.13.0.
# #
# Report bugs to <warren.dukes@gmail.com>. # Report bugs to <warren.dukes@gmail.com>.
# #
...@@ -713,8 +713,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} ...@@ -713,8 +713,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.12.2' PACKAGE_VERSION='0.13.0'
PACKAGE_STRING='mpd 0.12.2' PACKAGE_STRING='mpd 0.13.0'
PACKAGE_BUGREPORT='warren.dukes@gmail.com' PACKAGE_BUGREPORT='warren.dukes@gmail.com'
# Factoring default headers for most tests. # Factoring default headers for most tests.
...@@ -855,8 +855,12 @@ SHOUTCONFIG ...@@ -855,8 +855,12 @@ SHOUTCONFIG
PKG_CONFIG PKG_CONFIG
PULSE_CFLAGS PULSE_CFLAGS
PULSE_LIBS PULSE_LIBS
SAMPLERATE_CFLAGS
SAMPLERATE_LIBS
ALSA_CFLAGS ALSA_CFLAGS
ALSA_LIBS ALSA_LIBS
JACK_CFLAGS
JACK_LIBS
OGG_CFLAGS OGG_CFLAGS
OGG_LIBS OGG_LIBS
VORBIS_CFLAGS VORBIS_CFLAGS
...@@ -874,6 +878,8 @@ LIBMIKMOD_CONFIG ...@@ -874,6 +878,8 @@ LIBMIKMOD_CONFIG
LIBMIKMOD_CFLAGS LIBMIKMOD_CFLAGS
LIBMIKMOD_LIBS LIBMIKMOD_LIBS
LIBMIKMOD_LDADD LIBMIKMOD_LDADD
AVAHI_CFLAGS
AVAHI_LIBS
LIBOBJS LIBOBJS
LTLIBOBJS' LTLIBOBJS'
ac_subst_files='' ac_subst_files=''
...@@ -893,7 +899,13 @@ F77 ...@@ -893,7 +899,13 @@ F77
FFLAGS FFLAGS
PKG_CONFIG PKG_CONFIG
PULSE_CFLAGS PULSE_CFLAGS
PULSE_LIBS' PULSE_LIBS
SAMPLERATE_CFLAGS
SAMPLERATE_LIBS
JACK_CFLAGS
JACK_LIBS
AVAHI_CFLAGS
AVAHI_LIBS'
# Initialize some variables set by options. # Initialize some variables set by options.
...@@ -1396,7 +1408,7 @@ if test "$ac_init_help" = "long"; then ...@@ -1396,7 +1408,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.12.2 to adapt to many kinds of systems. \`configure' configures mpd 0.13.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
...@@ -1466,7 +1478,7 @@ fi ...@@ -1466,7 +1478,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.12.2:";; short | recursive ) echo "Configuration of mpd 0.13.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
...@@ -1484,9 +1496,9 @@ Optional Features: ...@@ -1484,9 +1496,9 @@ Optional Features:
--disable-shout disable support for streaming through shout (default: enable) --disable-shout disable support for streaming through shout (default: enable)
--disable-iconv disable iconv support (default: enable) --disable-iconv disable iconv support (default: enable)
--disable-ipv6 disable IPv6 support (default: enable) --disable-ipv6 disable IPv6 support (default: enable)
--disable-sun disable sun support (default: enable)
--disable-oss disable OSS support (default: enable) --disable-oss disable OSS support (default: enable)
--disable-alsa disable ALSA support (default: enable) --disable-alsa disable ALSA support (default: enable)
--disable-jack disable jack support (default: enable)
--disable-pulse disable support for the PulseAudio sound server (default: enable) --disable-pulse disable support for the PulseAudio sound server (default: enable)
--enable-mvp enable support for Hauppauge Media MVP (default: disable) --enable-mvp enable support for Hauppauge Media MVP (default: disable)
--disable-oggvorbis disable Ogg Vorbis support (default: enable) --disable-oggvorbis disable Ogg Vorbis support (default: enable)
...@@ -1498,6 +1510,7 @@ Optional Features: ...@@ -1498,6 +1510,7 @@ Optional Features:
--enable-mod enable MOD support (default: disable --enable-mod enable MOD support (default: disable
--disable-mpc disable musepack (MPC) support (default: enable) --disable-mpc disable musepack (MPC) support (default: enable)
--disable-id3 disable id3 support (default: enable) --disable-id3 disable id3 support (default: enable)
--disable-lsr disable libsamplerate support (default: enable)
--disable-aotest Do not try to compile and run a test ao program --disable-aotest Do not try to compile and run a test ao program
--disable-alsatest Do not try to compile and run a test Alsa program --disable-alsatest Do not try to compile and run a test Alsa program
--disable-oggtest Do not try to compile and run a test Ogg program --disable-oggtest Do not try to compile and run a test Ogg program
...@@ -1529,6 +1542,10 @@ Optional Packages: ...@@ -1529,6 +1542,10 @@ Optional Packages:
--with-faad=PFX Prefix where faad2 is installed --with-faad=PFX Prefix where faad2 is installed
--with-faad-libraries=DIR Directory where faad2 library is installed (optional) --with-faad-libraries=DIR Directory where faad2 library is installed (optional)
--with-faad-includes=DIR Directory where faad2 header files are installed (optional) --with-faad-includes=DIR Directory where faad2 header files are installed (optional)
--with-zeroconf=[auto|avahi|bonjour|no] Enable zeroconf backend (default=auto)
--with-src=PFX Prefix where libsamplerate is installed
--with-lsr-libraries=DIR Directory where libsamplerate library is installed (optional)
--with-lsr-includes=DIR Directory where libsamplerate header files are installed (optional)
--with-ao=PFX Prefix where libao is installed (optional) --with-ao=PFX Prefix where libao is installed (optional)
--with-ao-libraries=DIR Directory where libao library is installed (optional) --with-ao-libraries=DIR Directory where libao library is installed (optional)
--with-ao-includes=DIR Directory where libao header files are installed (optional) --with-ao-includes=DIR Directory where libao header files are installed (optional)
...@@ -1568,6 +1585,15 @@ Some influential environment variables: ...@@ -1568,6 +1585,15 @@ Some influential environment variables:
PULSE_CFLAGS PULSE_CFLAGS
C compiler flags for PULSE, overriding pkg-config C compiler flags for PULSE, overriding pkg-config
PULSE_LIBS linker flags for PULSE, overriding pkg-config PULSE_LIBS linker flags for PULSE, overriding pkg-config
SAMPLERATE_CFLAGS
C compiler flags for SAMPLERATE, overriding pkg-config
SAMPLERATE_LIBS
linker flags for SAMPLERATE, overriding pkg-config
JACK_CFLAGS C compiler flags for JACK, overriding pkg-config
JACK_LIBS linker flags for JACK, overriding pkg-config
AVAHI_CFLAGS
C compiler flags for AVAHI, overriding pkg-config
AVAHI_LIBS linker flags for AVAHI, overriding pkg-config
Use these variables to override the choices made by `configure' or to help Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations. it to find libraries and programs with nonstandard names/locations.
...@@ -1633,7 +1659,7 @@ fi ...@@ -1633,7 +1659,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.12.2 mpd configure 0.13.0
generated by GNU Autoconf 2.60 generated by GNU Autoconf 2.60
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
...@@ -1647,7 +1673,7 @@ cat >config.log <<_ACEOF ...@@ -1647,7 +1673,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.12.2, which was It was created by mpd $as_me 0.13.0, which was
generated by GNU Autoconf 2.60. Invocation command line was generated by GNU Autoconf 2.60. Invocation command line was
$ $0 $@ $ $0 $@
...@@ -3556,6 +3582,131 @@ echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } ...@@ -3556,6 +3582,131 @@ echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
if test "x$CC" != xcc; then
{ echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5
echo $ECHO_N "checking whether $CC and cc understand -c and -o together... $ECHO_C" >&6; }
else
{ echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5
echo $ECHO_N "checking whether cc understands -c and -o together... $ECHO_C" >&6; }
fi
set dummy $CC; ac_cc=`echo $2 |
sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
# Make sure it works both with $CC and with simple cc.
# We do the test twice because some compilers refuse to overwrite an
# existing .o file with -o, though they will create one.
ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
rm -f conftest2.*
if { (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
test -f conftest2.$ac_objext && { (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); };
then
eval ac_cv_prog_cc_${ac_cc}_c_o=yes
if test "x$CC" != xcc; then
# Test first that cc exists at all.
if { ac_try='cc -c conftest.$ac_ext >&5'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
rm -f conftest2.*
if { (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
test -f conftest2.$ac_objext && { (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); };
then
# cc works too.
:
else
# cc exists but doesn't like -o.
eval ac_cv_prog_cc_${ac_cc}_c_o=no
fi
fi
fi
else
eval ac_cv_prog_cc_${ac_cc}_c_o=no
fi
rm -f core conftest*
fi
if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
else
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
cat >>confdefs.h <<\_ACEOF
#define NO_MINUS_C_MINUS_O 1
_ACEOF
fi
# FIXME: we rely on the cache variable name because
# there is no other way.
set dummy $CC
ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
# Find a good install program. We prefer a C program (faster), # Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or # so one script is as good as another. But avoid the broken or
# incompatible versions: # incompatible versions:
...@@ -4432,7 +4583,7 @@ ia64-*-hpux*) ...@@ -4432,7 +4583,7 @@ ia64-*-hpux*)
;; ;;
*-*-irix6*) *-*-irix6*)
# Find out which ABI we are using. # Find out which ABI we are using.
echo '#line 4435 "configure"' > conftest.$ac_ext echo '#line 4586 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5 (eval $ac_compile) 2>&5
ac_status=$? ac_status=$?
...@@ -7417,11 +7568,11 @@ else ...@@ -7417,11 +7568,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7420: $lt_compile\"" >&5) (eval echo "\"\$as_me:7571: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:7424: \$? = $ac_status" >&5 echo "$as_me:7575: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -7685,11 +7836,11 @@ else ...@@ -7685,11 +7836,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7688: $lt_compile\"" >&5) (eval echo "\"\$as_me:7839: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:7692: \$? = $ac_status" >&5 echo "$as_me:7843: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -7789,11 +7940,11 @@ else ...@@ -7789,11 +7940,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7792: $lt_compile\"" >&5) (eval echo "\"\$as_me:7943: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 cat out/conftest.err >&5
echo "$as_me:7796: \$? = $ac_status" >&5 echo "$as_me:7947: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
...@@ -10278,7 +10429,7 @@ else ...@@ -10278,7 +10429,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10281 "configure" #line 10432 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -10378,7 +10529,7 @@ else ...@@ -10378,7 +10529,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10381 "configure" #line 10532 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -12746,11 +12897,11 @@ else ...@@ -12746,11 +12897,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:12749: $lt_compile\"" >&5) (eval echo "\"\$as_me:12900: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:12753: \$? = $ac_status" >&5 echo "$as_me:12904: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -12850,11 +13001,11 @@ else ...@@ -12850,11 +13001,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:12853: $lt_compile\"" >&5) (eval echo "\"\$as_me:13004: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 cat out/conftest.err >&5
echo "$as_me:12857: \$? = $ac_status" >&5 echo "$as_me:13008: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
...@@ -14457,11 +14608,11 @@ else ...@@ -14457,11 +14608,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:14460: $lt_compile\"" >&5) (eval echo "\"\$as_me:14611: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:14464: \$? = $ac_status" >&5 echo "$as_me:14615: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -14561,11 +14712,11 @@ else ...@@ -14561,11 +14712,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:14564: $lt_compile\"" >&5) (eval echo "\"\$as_me:14715: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 cat out/conftest.err >&5
echo "$as_me:14568: \$? = $ac_status" >&5 echo "$as_me:14719: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
...@@ -16828,11 +16979,11 @@ else ...@@ -16828,11 +16979,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:16831: $lt_compile\"" >&5) (eval echo "\"\$as_me:16982: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:16835: \$? = $ac_status" >&5 echo "$as_me:16986: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -17096,11 +17247,11 @@ else ...@@ -17096,11 +17247,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:17099: $lt_compile\"" >&5) (eval echo "\"\$as_me:17250: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 cat conftest.err >&5
echo "$as_me:17103: \$? = $ac_status" >&5 echo "$as_me:17254: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # So say no if there are warnings other than the usual output.
...@@ -17200,11 +17351,11 @@ else ...@@ -17200,11 +17351,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:17203: $lt_compile\"" >&5) (eval echo "\"\$as_me:17354: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 cat out/conftest.err >&5
echo "$as_me:17207: \$? = $ac_status" >&5 echo "$as_me:17358: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
...@@ -19970,17 +20121,15 @@ ac_config_headers="$ac_config_headers config.h" ...@@ -19970,17 +20121,15 @@ ac_config_headers="$ac_config_headers config.h"
cat >>confdefs.h <<\_ACEOF cat >>confdefs.h <<\_ACEOF
#define PROTOCOL_VERSION "0.12.2" #define PROTOCOL_VERSION "0.13.0"
_ACEOF _ACEOF
MPD_LIBS="" MPD_LIBS=""
MPD_CFLAGS="" MPD_CFLAGS=""
case "$CC" in if test x$GCC = xyes; then
*gcc*)
MPD_CFLAGS="-Wall -Wmissing-prototypes" MPD_CFLAGS="-Wall -Wmissing-prototypes"
;; fi
esac
if test -z "$prefix" || test "x$prefix" = xNONE; then if test -z "$prefix" || test "x$prefix" = xNONE; then
local_lib= local_lib=
...@@ -20046,13 +20195,6 @@ else ...@@ -20046,13 +20195,6 @@ else
enable_ipv6=yes enable_ipv6=yes
fi fi
# Check whether --enable-sun was given.
if test "${enable_sun+set}" = set; then
enableval=$enable_sun; enable_sun=$enableval
else
enable_sun=yes
fi
# Check whether --enable-oss was given. # Check whether --enable-oss was given.
if test "${enable_oss+set}" = set; then if test "${enable_oss+set}" = set; then
enableval=$enable_oss; enable_oss=$enableval enableval=$enable_oss; enable_oss=$enableval
...@@ -20067,6 +20209,13 @@ else ...@@ -20067,6 +20209,13 @@ else
enable_alsa=yes enable_alsa=yes
fi fi
# Check whether --enable-jack was given.
if test "${enable_jack+set}" = set; then
enableval=$enable_jack; enable_jack=$enableval
else
enable_jack=yes
fi
# Check whether --enable-pulse was given. # Check whether --enable-pulse was given.
if test "${enable_pulse+set}" = set; then if test "${enable_pulse+set}" = set; then
enableval=$enable_pulse; enable_pulse=$enableval enableval=$enable_pulse; enable_pulse=$enableval
...@@ -20144,6 +20293,13 @@ else ...@@ -20144,6 +20293,13 @@ else
enable_id3=yes enable_id3=yes
fi fi
# Check whether --enable-lsr was given.
if test "${enable_lsr+set}" = set; then
enableval=$enable_lsr; enable_lsr=$enableval
else
enable_lsr=yes
fi
# Check whether --with-tremor was given. # Check whether --with-tremor was given.
...@@ -20268,6 +20424,39 @@ else ...@@ -20268,6 +20424,39 @@ else
fi fi
# Check whether --with-zeroconf was given.
if test "${with_zeroconf+set}" = set; then
withval=$with_zeroconf; with_zeroconf="$withval"
else
with_zeroconf="auto"
fi
# Check whether --with-lsr was given.
if test "${with_lsr+set}" = set; then
withval=$with_lsr; src_prefix="$withval"
else
src_prefix=""
fi
# Check whether --with-lsr-libraries was given.
if test "${with_lsr_libraries+set}" = set; then
withval=$with_lsr_libraries; lsr_libraries="$withval"
else
lsr_libraries=""
fi
# Check whether --with-lsr-includes was given.
if test "${with_lsr_includes+set}" = set; then
withval=$with_lsr_includes; lsr_includes="$withval"
else
lsr_includes=""
fi
{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
if test "${ac_cv_c_bigendian+set}" = set; then if test "${ac_cv_c_bigendian+set}" = set; then
...@@ -24257,175 +24446,6 @@ fi ...@@ -24257,175 +24446,6 @@ fi
fi fi
if test x$enable_sun = xyes; then
if test "${ac_cv_header_sys_audioio_h+set}" = set; then
{ echo "$as_me:$LINENO: checking for sys/audioio.h" >&5
echo $ECHO_N "checking for sys/audioio.h... $ECHO_C" >&6; }
if test "${ac_cv_header_sys_audioio_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_audioio_h" >&5
echo "${ECHO_T}$ac_cv_header_sys_audioio_h" >&6; }
else
# Is the header compilable?
{ echo "$as_me:$LINENO: checking sys/audioio.h usability" >&5
echo $ECHO_N "checking sys/audioio.h usability... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <sys/audioio.h>
_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 "echo \"\$as_me:$LINENO: $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
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6; }
# Is the header present?
{ echo "$as_me:$LINENO: checking sys/audioio.h presence" >&5
echo $ECHO_N "checking sys/audioio.h presence... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/audioio.h>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
else
ac_cpp_err=
fi
else
ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: sys/audioio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: sys/audioio.h: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: sys/audioio.h: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: sys/audioio.h: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: sys/audioio.h: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: sys/audioio.h: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: sys/audioio.h: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: sys/audioio.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: sys/audioio.h: in the future, the compiler will take precedence" >&2;}
( cat <<\_ASBOX
## ------------------------------------- ##
## Report this to warren.dukes@gmail.com ##
## ------------------------------------- ##
_ASBOX
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ echo "$as_me:$LINENO: checking for sys/audioio.h" >&5
echo $ECHO_N "checking for sys/audioio.h... $ECHO_C" >&6; }
if test "${ac_cv_header_sys_audioio_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_header_sys_audioio_h=$ac_header_preproc
fi
{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_audioio_h" >&5
echo "${ECHO_T}$ac_cv_header_sys_audioio_h" >&6; }
fi
if test $ac_cv_header_sys_audioio_h = yes; then
enable_sun=yes;
cat >>confdefs.h <<\_ACEOF
#define HAVE_SUN 1
_ACEOF
else
{ echo "$as_me:$LINENO: WARNING: Sun audioio headers not found -- disabling SUN support" >&5
echo "$as_me: WARNING: Sun audioio headers not found -- disabling SUN support" >&2;};enable_sun=no
fi
fi
if test x$enable_oss = xyes; then if test x$enable_oss = xyes; then
if test "${ac_cv_header_sys_soundcard_h+set}" = set; then if test "${ac_cv_header_sys_soundcard_h+set}" = set; then
{ echo "$as_me:$LINENO: checking for sys/soundcard.h" >&5 { echo "$as_me:$LINENO: checking for sys/soundcard.h" >&5
...@@ -24595,7 +24615,8 @@ fi ...@@ -24595,7 +24615,8 @@ fi
fi fi
if test x$enable_pulse = xyes; then if test x$enable_pulse = xyes || test x$enable_jack = xyes ||
test x$enable_lsr = xyes || test x$with_zeroconf != xno; then
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
...@@ -24716,6 +24737,9 @@ echo "${ECHO_T}no" >&6; } ...@@ -24716,6 +24737,9 @@ echo "${ECHO_T}no" >&6; }
fi fi
fi fi
fi
if test x$enable_pulse = xyes; then
pkg_failed=no pkg_failed=no
{ echo "$as_me:$LINENO: checking for PULSE" >&5 { echo "$as_me:$LINENO: checking for PULSE" >&5
...@@ -24795,19 +24819,99 @@ _ACEOF ...@@ -24795,19 +24819,99 @@ _ACEOF
fi fi
fi fi
if test x$enable_mvp = xyes; then if test x$enable_lsr = xyes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_MVP 1
_ACEOF
fi pkg_failed=no
{ echo "$as_me:$LINENO: checking for SAMPLERATE" >&5
echo $ECHO_N "checking for SAMPLERATE... $ECHO_C" >&6; }
if test x$enable_alsa = xyes; then if test -n "$PKG_CONFIG"; then
alsa_save_CFLAGS="$CFLAGS" if test -n "$SAMPLERATE_CFLAGS"; then
alsa_save_LDFLAGS="$LDFLAGS" pkg_cv_SAMPLERATE_CFLAGS="$SAMPLERATE_CFLAGS"
alsa_save_LIBS="$LIBS" else
alsa_found=yes if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"samplerate >= 0.0.15\"") >&5
($PKG_CONFIG --exists --print-errors "samplerate >= 0.0.15") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_SAMPLERATE_CFLAGS=`$PKG_CONFIG --cflags "samplerate >= 0.0.15" 2>/dev/null`
else
pkg_failed=yes
fi
fi
else
pkg_failed=untried
fi
if test -n "$PKG_CONFIG"; then
if test -n "$SAMPLERATE_LIBS"; then
pkg_cv_SAMPLERATE_LIBS="$SAMPLERATE_LIBS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"samplerate >= 0.0.15\"") >&5
($PKG_CONFIG --exists --print-errors "samplerate >= 0.0.15") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_SAMPLERATE_LIBS=`$PKG_CONFIG --libs "samplerate >= 0.0.15" 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
SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "samplerate >= 0.0.15"`
else
SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "samplerate >= 0.0.15"`
fi
# Put the nasty error message in config.log where it belongs
echo "$SAMPLERATE_PKG_ERRORS" >&5
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
enable_lsr=no;{ echo "$as_me:$LINENO: WARNING: libsamplerate not found -- disabling" >&5
echo "$as_me: WARNING: libsamplerate not found -- disabling" >&2;}
elif test $pkg_failed = untried; then
enable_lsr=no;{ echo "$as_me:$LINENO: WARNING: libsamplerate not found -- disabling" >&5
echo "$as_me: WARNING: libsamplerate not found -- disabling" >&2;}
else
SAMPLERATE_CFLAGS=$pkg_cv_SAMPLERATE_CFLAGS
SAMPLERATE_LIBS=$pkg_cv_SAMPLERATE_LIBS
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
enable_lsr=yes;
cat >>confdefs.h <<\_ACEOF
#define HAVE_LIBSAMPLERATE 1
_ACEOF
MPD_LIBS="$MPD_LIBS $SAMPLERATE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $SAMPLERATE_CFLAGS"
fi
fi
if test x$enable_mvp = xyes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_MVP 1
_ACEOF
fi
if test x$enable_alsa = xyes; then
alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS"
alsa_save_LIBS="$LIBS"
alsa_found=yes
# Check whether --with-alsa-prefix was given. # Check whether --with-alsa-prefix was given.
...@@ -25097,13 +25201,91 @@ fi ...@@ -25097,13 +25201,91 @@ fi
fi fi
if test x$enable_jack = xyes; then
pkg_failed=no
{ echo "$as_me:$LINENO: checking for JACK" >&5
echo $ECHO_N "checking for JACK... $ECHO_C" >&6; }
if test -n "$PKG_CONFIG"; then
if test -n "$JACK_CFLAGS"; then
pkg_cv_JACK_CFLAGS="$JACK_CFLAGS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"jack >= 0.4\"") >&5
($PKG_CONFIG --exists --print-errors "jack >= 0.4") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_JACK_CFLAGS=`$PKG_CONFIG --cflags "jack >= 0.4" 2>/dev/null`
else
pkg_failed=yes
fi
fi
else
pkg_failed=untried
fi
if test -n "$PKG_CONFIG"; then
if test -n "$JACK_LIBS"; then
pkg_cv_JACK_LIBS="$JACK_LIBS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"jack >= 0.4\"") >&5
($PKG_CONFIG --exists --print-errors "jack >= 0.4") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_JACK_LIBS=`$PKG_CONFIG --libs "jack >= 0.4" 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
JACK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "jack >= 0.4"`
else
JACK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "jack >= 0.4"`
fi
# Put the nasty error message in config.log where it belongs
echo "$JACK_PKG_ERRORS" >&5
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
enable_jack=no;{ echo "$as_me:$LINENO: WARNING: JACK not found -- disabling" >&5
echo "$as_me: WARNING: JACK not found -- disabling" >&2;}
elif test $pkg_failed = untried; then
enable_jack=no;{ echo "$as_me:$LINENO: WARNING: JACK not found -- disabling" >&5
echo "$as_me: WARNING: JACK not found -- disabling" >&2;}
else
JACK_CFLAGS=$pkg_cv_JACK_CFLAGS
JACK_LIBS=$pkg_cv_JACK_LIBS
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
enable_jack=yes;
cat >>confdefs.h <<\_ACEOF
#define HAVE_JACK 1
_ACEOF
MPD_LIBS="$MPD_LIBS $JACK_LIBS" MPD_CFLAGS="$MPD_CFLAGS $JACK_CFLAGS"
fi
fi
if test x$enable_iconv = xyes; then if test x$enable_iconv = xyes; then
if test "x$iconv_libraries" != "x" ; then if test "x$iconv_libraries" != "x" ; then
ICONV_LIBS="-L$iconv_libraries" ICONV_LIBS="-L$iconv_libraries"
elif test "x$iconv_prefix" != "x" ; then elif test "x$iconv_prefix" != "x" ; then
ICONV_LIBS="-L$iconv_prefix/lib" ICONV_LIBS="-L$iconv_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ICONV_LIBS="-L$libdir"
fi fi
ICONV_LIBS="$ICONV_LIBS -liconv" ICONV_LIBS="$ICONV_LIBS -liconv"
...@@ -25112,8 +25294,6 @@ if test x$enable_iconv = xyes; then ...@@ -25112,8 +25294,6 @@ if test x$enable_iconv = xyes; then
ICONV_CFLAGS="-I$iconv_includes" ICONV_CFLAGS="-I$iconv_includes"
elif test "x$iconv_prefix" != "x" ; then elif test "x$iconv_prefix" != "x" ; then
ICONV_CFLAGS="-I$iconv_prefix/include" ICONV_CFLAGS="-I$iconv_prefix/include"
elif test "x$prefix" != "xNONE"; then
ICONV_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -25377,8 +25557,6 @@ if test x$enable_id3 = xyes; then ...@@ -25377,8 +25557,6 @@ if test x$enable_id3 = xyes; then
ID3TAG_LIBS="-L$id3tag_libraries" ID3TAG_LIBS="-L$id3tag_libraries"
elif test "x$id3tag_prefix" != "x" ; then elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_LIBS="-L$id3tag_prefix/lib" ID3TAG_LIBS="-L$id3tag_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ID3TAG_LIBS="-L$libdir"
fi fi
ID3TAG_LIBS="$ID3TAG_LIBS -lid3tag -lz" ID3TAG_LIBS="$ID3TAG_LIBS -lid3tag -lz"
...@@ -25387,8 +25565,6 @@ if test x$enable_id3 = xyes; then ...@@ -25387,8 +25565,6 @@ if test x$enable_id3 = xyes; then
ID3TAG_CFLAGS="-I$id3tag_includes" ID3TAG_CFLAGS="-I$id3tag_includes"
elif test "x$id3tag_prefix" != "x" ; then elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_CFLAGS="-I$id3tag_prefix/include" ID3TAG_CFLAGS="-I$id3tag_prefix/include"
elif test "x$prefix" != "xNONE"; then
ID3TAG_CFLAGS="-I$includedir"
fi fi
ID3TAG_CFLAGS="$ID3TAG_CFLAGS" ID3TAG_CFLAGS="$ID3TAG_CFLAGS"
...@@ -25678,8 +25854,6 @@ if test x$enable_mp3 = xyes; then ...@@ -25678,8 +25854,6 @@ if test x$enable_mp3 = xyes; then
MAD_LIBS="-L$mad_libraries" MAD_LIBS="-L$mad_libraries"
elif test "x$mad_prefix" != "x" ; then elif test "x$mad_prefix" != "x" ; then
MAD_LIBS="-L$mad_prefix/lib" MAD_LIBS="-L$mad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MAD_LIBS="-L$libdir"
fi fi
MAD_LIBS="$MAD_LIBS -lmad" MAD_LIBS="$MAD_LIBS -lmad"
...@@ -25688,8 +25862,6 @@ if test x$enable_mp3 = xyes; then ...@@ -25688,8 +25862,6 @@ if test x$enable_mp3 = xyes; then
MAD_CFLAGS="-I$mad_includes" MAD_CFLAGS="-I$mad_includes"
elif test "x$mad_prefix" != "x" ; then elif test "x$mad_prefix" != "x" ; then
MAD_CFLAGS="-I$mad_prefix/include" MAD_CFLAGS="-I$mad_prefix/include"
elif test "x$prefix" != "xNONE"; then
MAD_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -25975,8 +26147,6 @@ if test x$enable_mpc = xyes; then ...@@ -25975,8 +26147,6 @@ if test x$enable_mpc = xyes; then
MPCDEC_LIBS="-L$mpcdec_libraries" MPCDEC_LIBS="-L$mpcdec_libraries"
elif test "x$mpcdec_prefix" != "x" ; then elif test "x$mpcdec_prefix" != "x" ; then
MPCDEC_LIBS="-L$mpcdec_prefix/lib" MPCDEC_LIBS="-L$mpcdec_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MPCDEC_LIBS="-L$libdir"
fi fi
MPCDEC_LIBS="$MPCDEC_LIBS -lmpcdec" MPCDEC_LIBS="$MPCDEC_LIBS -lmpcdec"
...@@ -25985,8 +26155,6 @@ if test x$enable_mpc = xyes; then ...@@ -25985,8 +26155,6 @@ if test x$enable_mpc = xyes; then
MPCDEC_CFLAGS="-I$mpcdec_includes" MPCDEC_CFLAGS="-I$mpcdec_includes"
elif test "x$mpcdec_prefix" != "x" ; then elif test "x$mpcdec_prefix" != "x" ; then
MPCDEC_CFLAGS="-I$mpcdec_prefix/include" MPCDEC_CFLAGS="-I$mpcdec_prefix/include"
elif test "x$prefix" != "xNONE"; then
MPCDEC_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -26257,8 +26425,6 @@ if test x$enable_aac = xyes; then ...@@ -26257,8 +26425,6 @@ if test x$enable_aac = xyes; then
FAAD_LIBS="-L$faad_libraries" FAAD_LIBS="-L$faad_libraries"
elif test "x$faad_prefix" != "x" ; then elif test "x$faad_prefix" != "x" ; then
FAAD_LIBS="-L$faad_prefix/lib" FAAD_LIBS="-L$faad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
FAAD_LIBS="-L$libdir"
fi fi
FAAD_LIBS="$FAAD_LIBS -lfaad" FAAD_LIBS="$FAAD_LIBS -lfaad"
...@@ -26267,8 +26433,6 @@ if test x$enable_aac = xyes; then ...@@ -26267,8 +26433,6 @@ if test x$enable_aac = xyes; then
FAAD_CFLAGS="-I$faad_includes" FAAD_CFLAGS="-I$faad_includes"
elif test "x$faad_prefix" != "x" ; then elif test "x$faad_prefix" != "x" ; then
FAAD_CFLAGS="-I$faad_prefix/include" FAAD_CFLAGS="-I$faad_prefix/include"
elif test "x$prefix" != "xNONE"; then
FAAD_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -27439,16 +27603,12 @@ if test x$use_tremor = xyes; then ...@@ -27439,16 +27603,12 @@ if test x$use_tremor = xyes; then
TREMOR_LIBS="-L$tremor_libraries" TREMOR_LIBS="-L$tremor_libraries"
elif test "x$tremor_prefix" != "x" ; then elif test "x$tremor_prefix" != "x" ; then
TREMOR_LIBS="-L$tremor_prefix/lib" TREMOR_LIBS="-L$tremor_prefix/lib"
elif test "x$prefix" != "xNONE"; then
TREMOR_LIBS="-L$libdir"
fi fi
TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec" TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec"
if test "x$tremor_includes" != "x" ; then if test "x$tremor_includes" != "x" ; then
TREMOR_CFLAGS="-I$tremor_includes" TREMOR_CFLAGS="-I$tremor_includes"
elif test "x$tremor_prefix" != "x" ; then elif test "x$tremor_prefix" != "x" ; then
TREMOR_CFLAGS="-I$tremor_prefix/include" TREMOR_CFLAGS="-I$tremor_prefix/include"
elif test "x$prefix" != "xNONE"; then
TREMOR_CFLAGS="-I$includedir"
fi fi
ac_save_CFLAGS="$CFLAGS" ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
...@@ -28002,7 +28162,7 @@ rm -f core conftest.err conftest.$ac_objext \ ...@@ -28002,7 +28162,7 @@ rm -f core conftest.err conftest.$ac_objext \
if test x$enable_shout = xyes; then if test x$enable_shout = xyes; then
MPD_LIBS="$MPD_LIBS $VORBISENC_LIBS" MPD_LIBS="$MPD_LIBS $VORBISENC_LIBS"
MPD_CFLAGS="$VORBISFILE_CFLAGS $VORBISENC_CFLAGS" MPD_CFLAGS="$MPD_CFLAGS $VORBISFILE_CFLAGS $VORBISENC_CFLAGS"
fi fi
fi fi
fi fi
...@@ -28068,7 +28228,7 @@ fi ...@@ -28068,7 +28228,7 @@ fi
elif test "x$libFLAC_prefix" != "x" ; then elif test "x$libFLAC_prefix" != "x" ; then
LIBFLAC_LIBS="-L$libFLAC_prefix/lib" LIBFLAC_LIBS="-L$libFLAC_prefix/lib"
elif test "x$prefix" != "xNONE" ; then elif test "x$prefix" != "xNONE" ; then
LIBFLAC_LIBS="-L$prefix/lib" LIBFLAC_LIBS="-L$libdir"
fi fi
LIBFLAC_LIBS="$LIBFLAC_LIBS -lFLAC -lm" LIBFLAC_LIBS="$LIBFLAC_LIBS -lFLAC -lm"
...@@ -28077,8 +28237,8 @@ fi ...@@ -28077,8 +28237,8 @@ fi
LIBFLAC_CFLAGS="-I$libFLAC_includes" LIBFLAC_CFLAGS="-I$libFLAC_includes"
elif test "x$libFLAC_prefix" != "x" ; then elif test "x$libFLAC_prefix" != "x" ; then
LIBFLAC_CFLAGS="-I$libFLAC_prefix/include" LIBFLAC_CFLAGS="-I$libFLAC_prefix/include"
elif test "x$prefix" != "xNONE"; then elif test "$prefix" != "xNONE"; then
LIBFLAC_CFLAGS="-I$prefix/include" LIBFLAC_CFLAGS="-I$libdir"
fi fi
{ echo "$as_me:$LINENO: checking for libFLAC" >&5 { echo "$as_me:$LINENO: checking for libFLAC" >&5
...@@ -28352,6 +28512,82 @@ fi ...@@ -28352,6 +28512,82 @@ fi
if test x$enable_flac = xno; then if test x$enable_flac = xno; then
MPD_CFLAGS="$oldmpdcflags" MPD_CFLAGS="$oldmpdcflags"
MPD_LIBS="$oldmpdlibs" MPD_LIBS="$oldmpdlibs"
else
{ echo "$as_me:$LINENO: checking whether FLAC_API_SUPPORTS_OGG_FLAC is declared" >&5
echo $ECHO_N "checking whether FLAC_API_SUPPORTS_OGG_FLAC is declared... $ECHO_C" >&6; }
if test "${ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <FLAC/export.h>
int
main ()
{
#ifndef FLAC_API_SUPPORTS_OGG_FLAC
char *p = (char *) FLAC_API_SUPPORTS_OGG_FLAC;
return !p;
#endif
;
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 "echo \"\$as_me:$LINENO: $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
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC" >&5
echo "${ECHO_T}$ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC" >&6; }
if test $ac_cv_have_decl_FLAC_API_SUPPORTS_OGG_FLAC = yes; then
enable_oggflac=flac
fi
fi fi
CFLAGS="$oldcflags" CFLAGS="$oldcflags"
LIBS="$oldlibs" LIBS="$oldlibs"
...@@ -29332,6 +29568,225 @@ _ACEOF ...@@ -29332,6 +29568,225 @@ _ACEOF
fi fi
fi fi
case $with_zeroconf in
no|avahi|bonjour)
;;
*)
with_zeroconf=auto
;;
esac
if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xauto; then
pkg_failed=no
{ echo "$as_me:$LINENO: checking for AVAHI" >&5
echo $ECHO_N "checking for AVAHI... $ECHO_C" >&6; }
if test -n "$PKG_CONFIG"; then
if test -n "$AVAHI_CFLAGS"; then
pkg_cv_AVAHI_CFLAGS="$AVAHI_CFLAGS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client\"") >&5
($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_AVAHI_CFLAGS=`$PKG_CONFIG --cflags "avahi-client" 2>/dev/null`
else
pkg_failed=yes
fi
fi
else
pkg_failed=untried
fi
if test -n "$PKG_CONFIG"; then
if test -n "$AVAHI_LIBS"; then
pkg_cv_AVAHI_LIBS="$AVAHI_LIBS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client\"") >&5
($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_AVAHI_LIBS=`$PKG_CONFIG --libs "avahi-client" 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
AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "avahi-client"`
else
AVAHI_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "avahi-client"`
fi
# Put the nasty error message in config.log where it belongs
echo "$AVAHI_PKG_ERRORS" >&5
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
with_zeroconf=auto
elif test $pkg_failed = untried; then
with_zeroconf=auto
else
AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS
AVAHI_LIBS=$pkg_cv_AVAHI_LIBS
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
with_zeroconf=avahi;
cat >>confdefs.h <<\_ACEOF
#define HAVE_AVAHI 1
_ACEOF
MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS"
fi
elif test x$with_zeroconf = xavahi; then
pkg_failed=no
{ echo "$as_me:$LINENO: checking for AVAHI" >&5
echo $ECHO_N "checking for AVAHI... $ECHO_C" >&6; }
if test -n "$PKG_CONFIG"; then
if test -n "$AVAHI_CFLAGS"; then
pkg_cv_AVAHI_CFLAGS="$AVAHI_CFLAGS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client\"") >&5
($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_AVAHI_CFLAGS=`$PKG_CONFIG --cflags "avahi-client" 2>/dev/null`
else
pkg_failed=yes
fi
fi
else
pkg_failed=untried
fi
if test -n "$PKG_CONFIG"; then
if test -n "$AVAHI_LIBS"; then
pkg_cv_AVAHI_LIBS="$AVAHI_LIBS"
else
if test -n "$PKG_CONFIG" && \
{ (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client\"") >&5
($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
pkg_cv_AVAHI_LIBS=`$PKG_CONFIG --libs "avahi-client" 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
AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "avahi-client"`
else
AVAHI_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "avahi-client"`
fi
# Put the nasty error message in config.log where it belongs
echo "$AVAHI_PKG_ERRORS" >&5
{ { echo "$as_me:$LINENO: error: Package requirements (avahi-client) were not met:
$AVAHI_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables AVAHI_CFLAGS
and AVAHI_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
" >&5
echo "$as_me: error: Package requirements (avahi-client) were not met:
$AVAHI_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables AVAHI_CFLAGS
and AVAHI_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
" >&2;}
{ (exit 1); exit 1; }; }
elif test $pkg_failed = untried; then
{ { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables AVAHI_CFLAGS
and AVAHI_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.
See \`config.log' for more details." >&5
echo "$as_me: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables AVAHI_CFLAGS
and AVAHI_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.
See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
else
AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS
AVAHI_LIBS=$pkg_cv_AVAHI_LIBS
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
with_zeroconf=avahi;
cat >>confdefs.h <<\_ACEOF
#define HAVE_AVAHI 1
_ACEOF
MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS"
fi
fi
# In the future, should add bonjour support (for OSX) and check at autodetect
# time
#if test x$with_zeroconf = xbonjour -o x$with_zeroconf = xauto; then
if test x$with_zeroconf = xbonjour; then
{ echo "$as_me:$LINENO: WARNING: Bonjour support has not been implemented yet, disabling Zeroconf" >&5
echo "$as_me: WARNING: Bonjour support has not been implemented yet, disabling Zeroconf" >&2;}
with_zeroconf=no
fi
if test x$with_zeroconf = xauto; then
{ echo "$as_me:$LINENO: WARNING: No supported Zeroconf backend found, disabling Zeroconf" >&5
echo "$as_me: WARNING: No supported Zeroconf backend found, disabling Zeroconf" >&2;}
with_zeroconf=no
fi
fi
ac_config_files="$ac_config_files src/mp4ff/Makefile doc/Makefile src/Makefile Makefile" ac_config_files="$ac_config_files src/mp4ff/Makefile doc/Makefile src/Makefile Makefile"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
...@@ -29724,7 +30179,7 @@ exec 6>&1 ...@@ -29724,7 +30179,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.12.2, which was This file was extended by mpd $as_me 0.13.0, which was
generated by GNU Autoconf 2.60. Invocation command line was generated by GNU Autoconf 2.60. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
...@@ -29777,7 +30232,7 @@ Report bugs to <bug-autoconf@gnu.org>." ...@@ -29777,7 +30232,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
mpd config.status 0.12.2 mpd config.status 0.13.0
configured by $0, generated by GNU Autoconf 2.60, configured by $0, generated by GNU Autoconf 2.60,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
...@@ -30101,8 +30556,12 @@ SHOUTCONFIG!$SHOUTCONFIG$ac_delim ...@@ -30101,8 +30556,12 @@ SHOUTCONFIG!$SHOUTCONFIG$ac_delim
PKG_CONFIG!$PKG_CONFIG$ac_delim PKG_CONFIG!$PKG_CONFIG$ac_delim
PULSE_CFLAGS!$PULSE_CFLAGS$ac_delim PULSE_CFLAGS!$PULSE_CFLAGS$ac_delim
PULSE_LIBS!$PULSE_LIBS$ac_delim PULSE_LIBS!$PULSE_LIBS$ac_delim
SAMPLERATE_CFLAGS!$SAMPLERATE_CFLAGS$ac_delim
SAMPLERATE_LIBS!$SAMPLERATE_LIBS$ac_delim
ALSA_CFLAGS!$ALSA_CFLAGS$ac_delim ALSA_CFLAGS!$ALSA_CFLAGS$ac_delim
ALSA_LIBS!$ALSA_LIBS$ac_delim ALSA_LIBS!$ALSA_LIBS$ac_delim
JACK_CFLAGS!$JACK_CFLAGS$ac_delim
JACK_LIBS!$JACK_LIBS$ac_delim
OGG_CFLAGS!$OGG_CFLAGS$ac_delim OGG_CFLAGS!$OGG_CFLAGS$ac_delim
OGG_LIBS!$OGG_LIBS$ac_delim OGG_LIBS!$OGG_LIBS$ac_delim
VORBIS_CFLAGS!$VORBIS_CFLAGS$ac_delim VORBIS_CFLAGS!$VORBIS_CFLAGS$ac_delim
...@@ -30120,11 +30579,13 @@ LIBMIKMOD_CONFIG!$LIBMIKMOD_CONFIG$ac_delim ...@@ -30120,11 +30579,13 @@ LIBMIKMOD_CONFIG!$LIBMIKMOD_CONFIG$ac_delim
LIBMIKMOD_CFLAGS!$LIBMIKMOD_CFLAGS$ac_delim LIBMIKMOD_CFLAGS!$LIBMIKMOD_CFLAGS$ac_delim
LIBMIKMOD_LIBS!$LIBMIKMOD_LIBS$ac_delim LIBMIKMOD_LIBS!$LIBMIKMOD_LIBS$ac_delim
LIBMIKMOD_LDADD!$LIBMIKMOD_LDADD$ac_delim LIBMIKMOD_LDADD!$LIBMIKMOD_LDADD$ac_delim
AVAHI_CFLAGS!$AVAHI_CFLAGS$ac_delim
AVAHI_LIBS!$AVAHI_LIBS$ac_delim
LIBOBJS!$LIBOBJS$ac_delim LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF _ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 26; then if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 32; then
break break
elif $ac_last_try; then elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
...@@ -30715,10 +31176,10 @@ else ...@@ -30715,10 +31176,10 @@ else
echo " ALSA support ..................disabled" echo " ALSA support ..................disabled"
fi fi
if test x$enable_sun = xyes; then if test x$enable_jack = xyes; then
echo " Sun support ...................enabled" echo " JACK support ..................enabled"
else else
echo " Sun support ...................disabled" echo " JACK support ..................disabled"
fi fi
if test x$enable_osx = xyes; then if test x$enable_osx = xyes; then
...@@ -30750,10 +31211,10 @@ echo "" ...@@ -30750,10 +31211,10 @@ echo ""
if test x$enable_ao = xno && if test x$enable_ao = xno &&
test x$enable_oss = xno && test x$enable_oss = xno &&
test x$enable_shout = xno && test x$enable_shout = xno &&
test x$enable_sun = xno &&
test x$enable_alsa = xno && test x$enable_alsa = xno &&
test x$enable_osx = xno && test x$enable_osx = xno &&
test x$enable_pulse = xno && test x$enable_pulse = xno &&
test x$enable_jack = xno &&
test x$enable_mvp = xno; then test x$enable_mvp = xno; then
{ { echo "$as_me:$LINENO: error: No Audio Output types configured!" >&5 { { echo "$as_me:$LINENO: error: No Audio Output types configured!" >&5
echo "$as_me: error: No Audio Output types configured!" >&2;} echo "$as_me: error: No Audio Output types configured!" >&2;}
...@@ -30791,11 +31252,17 @@ else ...@@ -30791,11 +31252,17 @@ else
echo " FLAC support ..................disabled" echo " FLAC support ..................disabled"
fi fi
if test x$enable_oggflac = xyes; then case $enable_oggflac in
yes)
echo " OggFLAC support ...............enabled" echo " OggFLAC support ...............enabled"
else ;;
flac)
echo " OggFLAC support ...............enabled(FLAC 1.1.3)"
;;
*)
echo " OggFLAC support ...............disabled" echo " OggFLAC support ...............disabled"
fi ;;
esac
if test x$enable_audiofile = xyes; then if test x$enable_audiofile = xyes; then
echo " Wave file support .............enabled" echo " Wave file support .............enabled"
...@@ -30836,6 +31303,22 @@ echo "$as_me: error: No input plugins supported!" >&2;} ...@@ -30836,6 +31303,22 @@ echo "$as_me: error: No input plugins supported!" >&2;}
fi fi
echo "" echo ""
echo " Other features:"
if test x$enable_lsr = xyes; then
echo " libsamplerate support .........enabled"
else
echo " libsamplerate support .........disabled"
fi
if test x$with_zeroconf != xno; then
echo " Zeroconf support ..............$with_zeroconf"
else
echo " Zeroconf support ..............disabled"
fi
echo ""
echo "##########################################" echo "##########################################"
echo "" echo ""
echo "You are now ready to compile MPD" echo "You are now ready to compile MPD"
......
dnl AC_INIT(src/main.c) dnl AC_INIT(src/main.c)
dnl AM_INIT_AUTOMAKE(mpd, 0.12.2) dnl AM_INIT_AUTOMAKE(mpd, 0.13.0)
AC_PREREQ(2.58) AC_PREREQ(2.58)
AC_INIT(mpd, 0.12.2, warren.dukes@gmail.com) AC_INIT(mpd, 0.13.0, warren.dukes@gmail.com)
AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION) AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
AC_SUBST(MPD_LIBS) AC_SUBST(MPD_LIBS)
...@@ -11,20 +11,19 @@ AC_SUBST(MP4FF_LIB) ...@@ -11,20 +11,19 @@ AC_SUBST(MP4FF_LIB)
AC_SUBST(MP4FF_SUBDIR) AC_SUBST(MP4FF_SUBDIR)
AC_PROG_CC AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
AC_DEFINE(PROTOCOL_VERSION, "0.12.2", [The mpd protocol version]) AC_DEFINE(PROTOCOL_VERSION, "0.13.0", [The mpd protocol version])
MPD_LIBS="" MPD_LIBS=""
MPD_CFLAGS="" MPD_CFLAGS=""
case "$CC" in if test x$GCC = xyes; then
*gcc*)
MPD_CFLAGS="-Wall -Wmissing-prototypes" MPD_CFLAGS="-Wall -Wmissing-prototypes"
;; fi
esac
if test -z "$prefix" || test "x$prefix" = xNONE; then if test -z "$prefix" || test "x$prefix" = xNONE; then
local_lib= local_lib=
...@@ -66,9 +65,9 @@ AC_ARG_ENABLE(ao,[ --enable-ao enable support for libao (default: d ...@@ -66,9 +65,9 @@ AC_ARG_ENABLE(ao,[ --enable-ao enable support for libao (default: d
AC_ARG_ENABLE(shout,[ --disable-shout disable support for streaming through shout (default: enable)],[enable_shout=$enableval],[enable_shout=yes]) AC_ARG_ENABLE(shout,[ --disable-shout disable support for streaming through shout (default: enable)],[enable_shout=$enableval],[enable_shout=yes])
AC_ARG_ENABLE(iconv,[ --disable-iconv disable iconv support (default: enable)],[enable_iconv=$enableval],[enable_iconv=yes]) AC_ARG_ENABLE(iconv,[ --disable-iconv disable iconv support (default: enable)],[enable_iconv=$enableval],[enable_iconv=yes])
AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support (default: enable)],[enable_ipv6=$enableval],[enable_ipv6=yes]) AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support (default: enable)],[enable_ipv6=$enableval],[enable_ipv6=yes])
AC_ARG_ENABLE(sun,[ --disable-sun disable sun support (default: enable)],[enable_sun=$enableval],[enable_sun=yes])
AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enable)],[enable_oss=$enableval],[enable_oss=yes]) AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enable)],[enable_oss=$enableval],[enable_oss=yes])
AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA support (default: enable)],[enable_alsa=$enableval],[enable_alsa=yes]) AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA support (default: enable)],[enable_alsa=$enableval],[enable_alsa=yes])
AC_ARG_ENABLE(jack,[ --disable-jack disable jack support (default: enable)],[enable_jack=$enableval],[enable_jack=yes])
AC_ARG_ENABLE(pulse,[ --disable-pulse disable support for the PulseAudio sound server (default: enable)],[enable_pulse=$enableval],[enable_pulse=yes]) AC_ARG_ENABLE(pulse,[ --disable-pulse disable support for the PulseAudio sound server (default: enable)],[enable_pulse=$enableval],[enable_pulse=yes])
AC_ARG_ENABLE(mvp,[ --enable-mvp enable support for Hauppauge Media MVP (default: disable)],[enable_mvp=$enableval],[enable_mvp=no]) AC_ARG_ENABLE(mvp,[ --enable-mvp enable support for Hauppauge Media MVP (default: disable)],[enable_mvp=$enableval],[enable_mvp=no])
AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (default: enable)],[enable_oggvorbis=$enableval],enable_oggvorbis=yes) AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (default: enable)],[enable_oggvorbis=$enableval],enable_oggvorbis=yes)
...@@ -80,6 +79,7 @@ AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support, di ...@@ -80,6 +79,7 @@ AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support, di
AC_ARG_ENABLE(mod,[ --enable-mod enable MOD support (default: disable],[enable_mod=$enableval],[enable_mod=yes]) AC_ARG_ENABLE(mod,[ --enable-mod enable MOD support (default: disable],[enable_mod=$enableval],[enable_mod=yes])
AC_ARG_ENABLE(mpc,[ --disable-mpc disable musepack (MPC) support (default: enable)],[enable_mpc=$enableval],[enable_mpc=yes]) AC_ARG_ENABLE(mpc,[ --disable-mpc disable musepack (MPC) support (default: enable)],[enable_mpc=$enableval],[enable_mpc=yes])
AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support (default: enable)],[enable_id3=$enableval],[enable_id3=yes]) AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support (default: enable)],[enable_id3=$enableval],[enable_id3=yes])
AC_ARG_ENABLE(lsr,[ --disable-lsr disable libsamplerate support (default: enable)],[enable_lsr=$enableval],[enable_lsr=yes])
AC_ARG_WITH(tremor,[[ --with-tremor[=PFX] Use Tremor(vorbisidec) integer Ogg-Vorbis decoder (with optional prefix)]], use_tremor=yes; test x$withval != xyes && tremor_prefix="$withval",) AC_ARG_WITH(tremor,[[ --with-tremor[=PFX] Use Tremor(vorbisidec) integer Ogg-Vorbis decoder (with optional prefix)]], use_tremor=yes; test x$withval != xyes && tremor_prefix="$withval",)
AC_ARG_WITH(tremor-libraries,[ --with-tremor-libraries=DIR Directory where Tremor library is installed (optional)], tremor_libraries="$withval", tremor_libraries="") AC_ARG_WITH(tremor-libraries,[ --with-tremor-libraries=DIR Directory where Tremor library is installed (optional)], tremor_libraries="$withval", tremor_libraries="")
...@@ -100,6 +100,11 @@ AC_ARG_WITH(mad-includes,[ --with-mad-includes=DIR Directory where mad head ...@@ -100,6 +100,11 @@ AC_ARG_WITH(mad-includes,[ --with-mad-includes=DIR Directory where mad head
AC_ARG_WITH(faad,[ --with-faad=PFX Prefix where faad2 is installed], faad_prefix="$withval", faad_prefix="") AC_ARG_WITH(faad,[ --with-faad=PFX Prefix where faad2 is installed], faad_prefix="$withval", faad_prefix="")
AC_ARG_WITH(faad-libraries,[ --with-faad-libraries=DIR Directory where faad2 library is installed (optional)], faad_libraries="$withval", faad_libraries="") AC_ARG_WITH(faad-libraries,[ --with-faad-libraries=DIR Directory where faad2 library is installed (optional)], faad_libraries="$withval", faad_libraries="")
AC_ARG_WITH(faad-includes,[ --with-faad-includes=DIR Directory where faad2 header files are installed (optional)], faad_includes="$withval", faad_includes="") AC_ARG_WITH(faad-includes,[ --with-faad-includes=DIR Directory where faad2 header files are installed (optional)], faad_includes="$withval", faad_includes="")
AC_ARG_WITH(zeroconf,[[ --with-zeroconf=[auto|avahi|bonjour|no] Enable zeroconf backend (default=auto)]], with_zeroconf="$withval", with_zeroconf="auto")
AC_ARG_WITH(lsr,[ --with-src=PFX Prefix where libsamplerate is installed], src_prefix="$withval", src_prefix="")
AC_ARG_WITH(lsr-libraries,[ --with-lsr-libraries=DIR Directory where libsamplerate library is installed (optional)], lsr_libraries="$withval", lsr_libraries="")
AC_ARG_WITH(lsr-includes,[ --with-lsr-includes=DIR Directory where libsamplerate header files are installed (optional)], lsr_includes="$withval", lsr_includes="")
AC_C_BIGENDIAN AC_C_BIGENDIAN
...@@ -168,20 +173,27 @@ if test x$enable_shout = xyes; then ...@@ -168,20 +173,27 @@ if test x$enable_shout = xyes; then
XIPH_PATH_SHOUT([AC_DEFINE(HAVE_SHOUT, 1, [Define to enable libshout support]) MPD_LIBS="$MPD_LIBS $SHOUT_LIBS" MPD_CFLAGS="$MPD_CFLAGS $SHOUT_CFLAGS"], enable_shout=no) XIPH_PATH_SHOUT([AC_DEFINE(HAVE_SHOUT, 1, [Define to enable libshout support]) MPD_LIBS="$MPD_LIBS $SHOUT_LIBS" MPD_CFLAGS="$MPD_CFLAGS $SHOUT_CFLAGS"], enable_shout=no)
fi fi
if test x$enable_sun = xyes; then
AC_CHECK_HEADER(sys/audioio.h,[enable_sun=yes;AC_DEFINE(HAVE_SUN,1,[Define to enable SUN audio support])],[AC_MSG_WARN(Sun audioio headers not found -- disabling SUN support);enable_sun=no])
fi
if test x$enable_oss = xyes; then if test x$enable_oss = xyes; then
AC_CHECK_HEADER(sys/soundcard.h,[enable_oss=yes;AC_DEFINE(HAVE_OSS,1,[Define to enable OSS])],[AC_MSG_WARN(Soundcard headers not found -- disabling OSS support);enable_oss=no]) AC_CHECK_HEADER(sys/soundcard.h,[enable_oss=yes;AC_DEFINE(HAVE_OSS,1,[Define to enable OSS])],[AC_MSG_WARN(Soundcard headers not found -- disabling OSS support);enable_oss=no])
fi fi
if test x$enable_pulse = xyes || test x$enable_jack = xyes ||
test x$enable_lsr = xyes || test x$with_zeroconf != xno; then
PKG_PROG_PKG_CONFIG
fi
if test x$enable_pulse = xyes; then if test x$enable_pulse = xyes; then
PKG_CHECK_MODULES([PULSE], [libpulse-simple], PKG_CHECK_MODULES([PULSE], [libpulse-simple],
[enable_pulse=yes;AC_DEFINE([HAVE_PULSE], 1, [Define to enable PulseAudio])] MPD_LIBS="$MPD_LIBS $PULSE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $PULSE_CFLAGS", [enable_pulse=yes;AC_DEFINE([HAVE_PULSE], 1, [Define to enable PulseAudio support])] MPD_LIBS="$MPD_LIBS $PULSE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $PULSE_CFLAGS",
[enable_pulse=no;AC_MSG_WARN([PulseAudio not found -- disabling])]) [enable_pulse=no;AC_MSG_WARN([PulseAudio not found -- disabling])])
fi fi
if test x$enable_lsr = xyes; then
PKG_CHECK_MODULES([SAMPLERATE], [samplerate >= 0.0.15],
[enable_lsr=yes;AC_DEFINE([HAVE_LIBSAMPLERATE], 1, [Define to enable libsamplerate])] MPD_LIBS="$MPD_LIBS $SAMPLERATE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $SAMPLERATE_CFLAGS",
[enable_lsr=no;AC_MSG_WARN([libsamplerate not found -- disabling])])
fi
if test x$enable_mvp = xyes; then if test x$enable_mvp = xyes; then
AC_DEFINE(HAVE_MVP,1,[Define to enable Hauppauge Media MVP support]) AC_DEFINE(HAVE_MVP,1,[Define to enable Hauppauge Media MVP support])
fi fi
...@@ -190,13 +202,17 @@ if test x$enable_alsa = xyes; then ...@@ -190,13 +202,17 @@ if test x$enable_alsa = xyes; then
AM_PATH_ALSA(0.9.0,[AC_DEFINE(HAVE_ALSA,1,[Define to enable ALSA support]) MPD_LIBS="$MPD_LIBS $ALSA_LIBS" MPD_CFLAGS="$MPD_CFLAGS $ALSA_CFLAGS"],enable_alsa=no) AM_PATH_ALSA(0.9.0,[AC_DEFINE(HAVE_ALSA,1,[Define to enable ALSA support]) MPD_LIBS="$MPD_LIBS $ALSA_LIBS" MPD_CFLAGS="$MPD_CFLAGS $ALSA_CFLAGS"],enable_alsa=no)
fi fi
if test x$enable_jack = xyes; then
PKG_CHECK_MODULES([JACK], [jack >= 0.4],
[enable_jack=yes;AC_DEFINE([HAVE_JACK], 1, [Define to enable JACK support])] MPD_LIBS="$MPD_LIBS $JACK_LIBS" MPD_CFLAGS="$MPD_CFLAGS $JACK_CFLAGS",
[enable_jack=no;AC_MSG_WARN([JACK not found -- disabling])])
fi
if test x$enable_iconv = xyes; then if test x$enable_iconv = xyes; then
if test "x$iconv_libraries" != "x" ; then if test "x$iconv_libraries" != "x" ; then
ICONV_LIBS="-L$iconv_libraries" ICONV_LIBS="-L$iconv_libraries"
elif test "x$iconv_prefix" != "x" ; then elif test "x$iconv_prefix" != "x" ; then
ICONV_LIBS="-L$iconv_prefix/lib" ICONV_LIBS="-L$iconv_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ICONV_LIBS="-L$libdir"
fi fi
ICONV_LIBS="$ICONV_LIBS -liconv" ICONV_LIBS="$ICONV_LIBS -liconv"
...@@ -205,8 +221,6 @@ if test x$enable_iconv = xyes; then ...@@ -205,8 +221,6 @@ if test x$enable_iconv = xyes; then
ICONV_CFLAGS="-I$iconv_includes" ICONV_CFLAGS="-I$iconv_includes"
elif test "x$iconv_prefix" != "x" ; then elif test "x$iconv_prefix" != "x" ; then
ICONV_CFLAGS="-I$iconv_prefix/include" ICONV_CFLAGS="-I$iconv_prefix/include"
elif test "x$prefix" != "xNONE"; then
ICONV_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -232,8 +246,6 @@ if test x$enable_id3 = xyes; then ...@@ -232,8 +246,6 @@ if test x$enable_id3 = xyes; then
ID3TAG_LIBS="-L$id3tag_libraries" ID3TAG_LIBS="-L$id3tag_libraries"
elif test "x$id3tag_prefix" != "x" ; then elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_LIBS="-L$id3tag_prefix/lib" ID3TAG_LIBS="-L$id3tag_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ID3TAG_LIBS="-L$libdir"
fi fi
ID3TAG_LIBS="$ID3TAG_LIBS -lid3tag -lz" ID3TAG_LIBS="$ID3TAG_LIBS -lid3tag -lz"
...@@ -242,8 +254,6 @@ if test x$enable_id3 = xyes; then ...@@ -242,8 +254,6 @@ if test x$enable_id3 = xyes; then
ID3TAG_CFLAGS="-I$id3tag_includes" ID3TAG_CFLAGS="-I$id3tag_includes"
elif test "x$id3tag_prefix" != "x" ; then elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_CFLAGS="-I$id3tag_prefix/include" ID3TAG_CFLAGS="-I$id3tag_prefix/include"
elif test "x$prefix" != "xNONE"; then
ID3TAG_CFLAGS="-I$includedir"
fi fi
ID3TAG_CFLAGS="$ID3TAG_CFLAGS" ID3TAG_CFLAGS="$ID3TAG_CFLAGS"
...@@ -280,8 +290,6 @@ if test x$enable_mp3 = xyes; then ...@@ -280,8 +290,6 @@ if test x$enable_mp3 = xyes; then
MAD_LIBS="-L$mad_libraries" MAD_LIBS="-L$mad_libraries"
elif test "x$mad_prefix" != "x" ; then elif test "x$mad_prefix" != "x" ; then
MAD_LIBS="-L$mad_prefix/lib" MAD_LIBS="-L$mad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MAD_LIBS="-L$libdir"
fi fi
MAD_LIBS="$MAD_LIBS -lmad" MAD_LIBS="$MAD_LIBS -lmad"
...@@ -290,8 +298,6 @@ if test x$enable_mp3 = xyes; then ...@@ -290,8 +298,6 @@ if test x$enable_mp3 = xyes; then
MAD_CFLAGS="-I$mad_includes" MAD_CFLAGS="-I$mad_includes"
elif test "x$mad_prefix" != "x" ; then elif test "x$mad_prefix" != "x" ; then
MAD_CFLAGS="-I$mad_prefix/include" MAD_CFLAGS="-I$mad_prefix/include"
elif test "x$prefix" != "xNONE"; then
MAD_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -322,8 +328,6 @@ if test x$enable_mpc = xyes; then ...@@ -322,8 +328,6 @@ if test x$enable_mpc = xyes; then
MPCDEC_LIBS="-L$mpcdec_libraries" MPCDEC_LIBS="-L$mpcdec_libraries"
elif test "x$mpcdec_prefix" != "x" ; then elif test "x$mpcdec_prefix" != "x" ; then
MPCDEC_LIBS="-L$mpcdec_prefix/lib" MPCDEC_LIBS="-L$mpcdec_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MPCDEC_LIBS="-L$libdir"
fi fi
MPCDEC_LIBS="$MPCDEC_LIBS -lmpcdec" MPCDEC_LIBS="$MPCDEC_LIBS -lmpcdec"
...@@ -332,8 +336,6 @@ if test x$enable_mpc = xyes; then ...@@ -332,8 +336,6 @@ if test x$enable_mpc = xyes; then
MPCDEC_CFLAGS="-I$mpcdec_includes" MPCDEC_CFLAGS="-I$mpcdec_includes"
elif test "x$mpcdec_prefix" != "x" ; then elif test "x$mpcdec_prefix" != "x" ; then
MPCDEC_CFLAGS="-I$mpcdec_prefix/include" MPCDEC_CFLAGS="-I$mpcdec_prefix/include"
elif test "x$prefix" != "xNONE"; then
MPCDEC_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -363,8 +365,6 @@ if test x$enable_aac = xyes; then ...@@ -363,8 +365,6 @@ if test x$enable_aac = xyes; then
FAAD_LIBS="-L$faad_libraries" FAAD_LIBS="-L$faad_libraries"
elif test "x$faad_prefix" != "x" ; then elif test "x$faad_prefix" != "x" ; then
FAAD_LIBS="-L$faad_prefix/lib" FAAD_LIBS="-L$faad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
FAAD_LIBS="-L$libdir"
fi fi
FAAD_LIBS="$FAAD_LIBS -lfaad" FAAD_LIBS="$FAAD_LIBS -lfaad"
...@@ -373,8 +373,6 @@ if test x$enable_aac = xyes; then ...@@ -373,8 +373,6 @@ if test x$enable_aac = xyes; then
FAAD_CFLAGS="-I$faad_includes" FAAD_CFLAGS="-I$faad_includes"
elif test "x$faad_prefix" != "x" ; then elif test "x$faad_prefix" != "x" ; then
FAAD_CFLAGS="-I$faad_prefix/include" FAAD_CFLAGS="-I$faad_prefix/include"
elif test "x$prefix" != "xNONE"; then
FAAD_CFLAGS="-I$includedir"
fi fi
oldcflags=$CFLAGS oldcflags=$CFLAGS
...@@ -474,16 +472,12 @@ if test x$use_tremor = xyes; then ...@@ -474,16 +472,12 @@ if test x$use_tremor = xyes; then
TREMOR_LIBS="-L$tremor_libraries" TREMOR_LIBS="-L$tremor_libraries"
elif test "x$tremor_prefix" != "x" ; then elif test "x$tremor_prefix" != "x" ; then
TREMOR_LIBS="-L$tremor_prefix/lib" TREMOR_LIBS="-L$tremor_prefix/lib"
elif test "x$prefix" != "xNONE"; then
TREMOR_LIBS="-L$libdir"
fi fi
TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec" TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec"
if test "x$tremor_includes" != "x" ; then if test "x$tremor_includes" != "x" ; then
TREMOR_CFLAGS="-I$tremor_includes" TREMOR_CFLAGS="-I$tremor_includes"
elif test "x$tremor_prefix" != "x" ; then elif test "x$tremor_prefix" != "x" ; then
TREMOR_CFLAGS="-I$tremor_prefix/include" TREMOR_CFLAGS="-I$tremor_prefix/include"
elif test "x$prefix" != "xNONE"; then
TREMOR_CFLAGS="-I$includedir"
fi fi
ac_save_CFLAGS="$CFLAGS" ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
...@@ -503,7 +497,7 @@ elif test x$enable_oggvorbis = xyes; then ...@@ -503,7 +497,7 @@ elif test x$enable_oggvorbis = xyes; then
if test x$enable_shout = xyes; then if test x$enable_shout = xyes; then
MPD_LIBS="$MPD_LIBS $VORBISENC_LIBS" MPD_LIBS="$MPD_LIBS $VORBISENC_LIBS"
MPD_CFLAGS="$VORBISFILE_CFLAGS $VORBISENC_CFLAGS" MPD_CFLAGS="$MPD_CFLAGS $VORBISFILE_CFLAGS $VORBISENC_CFLAGS"
fi fi
fi fi
fi fi
...@@ -537,6 +531,10 @@ if test x$enable_flac = xyes; then ...@@ -537,6 +531,10 @@ if test x$enable_flac = xyes; then
if test x$enable_flac = xno; then if test x$enable_flac = xno; then
MPD_CFLAGS="$oldmpdcflags" MPD_CFLAGS="$oldmpdcflags"
MPD_LIBS="$oldmpdlibs" MPD_LIBS="$oldmpdlibs"
else
AC_CHECK_DECL(FLAC_API_SUPPORTS_OGG_FLAC,
[enable_oggflac=flac], [],
[#include <FLAC/export.h>])
fi fi
CFLAGS="$oldcflags" CFLAGS="$oldcflags"
LIBS="$oldlibs" LIBS="$oldlibs"
...@@ -576,6 +574,38 @@ if test x$enable_mod = xyes; then ...@@ -576,6 +574,38 @@ if test x$enable_mod = xyes; then
fi fi
fi fi
case $with_zeroconf in
no|avahi|bonjour)
;;
*)
with_zeroconf=auto
;;
esac
if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xauto; then
PKG_CHECK_MODULES([AVAHI], [avahi-client],
[with_zeroconf=avahi;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS",
[with_zeroconf=auto])
elif test x$with_zeroconf = xavahi; then
PKG_CHECK_MODULES([AVAHI], [avahi-client],
[with_zeroconf=avahi;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS")
fi
# In the future, should add bonjour support (for OSX) and check at autodetect
# time
#if test x$with_zeroconf = xbonjour -o x$with_zeroconf = xauto; then
if test x$with_zeroconf = xbonjour; then
AC_MSG_WARN([Bonjour support has not been implemented yet, disabling Zeroconf])
with_zeroconf=no
fi
if test x$with_zeroconf = xauto; then
AC_MSG_WARN([No supported Zeroconf backend found, disabling Zeroconf])
with_zeroconf=no
fi
fi
AC_OUTPUT(src/mp4ff/Makefile doc/Makefile src/Makefile Makefile ) AC_OUTPUT(src/mp4ff/Makefile doc/Makefile src/Makefile Makefile )
echo "" echo ""
...@@ -601,10 +631,10 @@ else ...@@ -601,10 +631,10 @@ else
echo " ALSA support ..................disabled" echo " ALSA support ..................disabled"
fi fi
if test x$enable_sun = xyes; then if test x$enable_jack = xyes; then
echo " Sun support ...................enabled" echo " JACK support ..................enabled"
else else
echo " Sun support ...................disabled" echo " JACK support ..................disabled"
fi fi
if test x$enable_osx = xyes; then if test x$enable_osx = xyes; then
...@@ -636,10 +666,10 @@ echo "" ...@@ -636,10 +666,10 @@ echo ""
if test x$enable_ao = xno && if test x$enable_ao = xno &&
test x$enable_oss = xno && test x$enable_oss = xno &&
test x$enable_shout = xno && test x$enable_shout = xno &&
test x$enable_sun = xno &&
test x$enable_alsa = xno && test x$enable_alsa = xno &&
test x$enable_osx = xno && test x$enable_osx = xno &&
test x$enable_pulse = xno && test x$enable_pulse = xno &&
test x$enable_jack = xno &&
test x$enable_mvp = xno; then test x$enable_mvp = xno; then
AC_MSG_ERROR([No Audio Output types configured!]) AC_MSG_ERROR([No Audio Output types configured!])
fi fi
...@@ -675,11 +705,17 @@ else ...@@ -675,11 +705,17 @@ else
echo " FLAC support ..................disabled" echo " FLAC support ..................disabled"
fi fi
if test x$enable_oggflac = xyes; then case $enable_oggflac in
yes)
echo " OggFLAC support ...............enabled" echo " OggFLAC support ...............enabled"
else ;;
flac)
echo " OggFLAC support ...............enabled(FLAC 1.1.3)"
;;
*)
echo " OggFLAC support ...............disabled" echo " OggFLAC support ...............disabled"
fi ;;
esac
if test x$enable_audiofile = xyes; then if test x$enable_audiofile = xyes; then
echo " Wave file support .............enabled" echo " Wave file support .............enabled"
...@@ -718,6 +754,22 @@ if ...@@ -718,6 +754,22 @@ if
fi fi
echo "" echo ""
echo " Other features:"
if test x$enable_lsr = xyes; then
echo " libsamplerate support .........enabled"
else
echo " libsamplerate support .........disabled"
fi
if test x$with_zeroconf != xno; then
echo " Zeroconf support ..............$with_zeroconf"
else
echo " Zeroconf support ..............disabled"
fi
echo ""
echo "##########################################" echo "##########################################"
echo "" echo ""
echo "You are now ready to compile MPD" echo "You are now ready to compile MPD"
......
...@@ -71,6 +71,11 @@ reports from what address a connection is opened, and when it is closed, and ...@@ -71,6 +71,11 @@ reports from what address a connection is opened, and when it is closed, and
"verbose" records excessive amounts of information for debugging purposes. The "verbose" records excessive amounts of information for debugging purposes. The
default is "default". default is "default".
.TP .TP
.B zeroconf_name <name>
If Zerconf is compiled into MPD, this is the service name to publish. This
should be unique to your local network, but name collisions will be properly
dealt with.
.TP
.B password <password@permissions> .B password <password@permissions>
This specifies a password for access to mpd. The format is This specifies a password for access to mpd. The format is
"password@permissions" where permissions is a comma delimited list composed "password@permissions" where permissions is a comma delimited list composed
...@@ -100,6 +105,39 @@ their own audio format which will be used for actual output to the audio ...@@ -100,6 +105,39 @@ their own audio format which will be used for actual output to the audio
device. An example is "44100:16:2" for 44100Hz, 16 bits, and 2 channels. The device. An example is "44100:16:2" for 44100Hz, 16 bits, and 2 channels. The
default is to use the audio format of the input file. default is to use the audio format of the input file.
.TP .TP
.B samplerate_converter <integer or prefix>
This specifies the libsamplerate converter to use. The supplied value should
either be an integer or a prefix of the name of a converter. The default is
"Fastest Sinc Interpolator".
At the time of this writing, the following converters are available:
.RS
.TP
Best Sinc Interpolator (0)
Band limited sinc interpolation, best quality, 97dB SNR, 96% BW.
.TP
Medium Sinc Interpolator (1)
Band limited sinc interpolation, medium quality, 97dB SNR, 90% BW.
.TP
Fastest Sinc Interpolator (2)
Band limited sinc interpolation, fastest, 97dB SNR, 80% BW.
.TP
ZOH Interpolator (3)
Zero order hold interpolator, very fast, very poor quality with audible
distortions.
.TP
Linear Interpolator (4)
Linear interpolator, very fast, poor quality.
.RE
.IP
For an up-to-date list of available converters, please see the libsamplerate
documentation (available online at <\fBhttp://www.mega-nerd.com/SRC/\fP>).
.TP
.B mixer_type <oss, alsa or software> .B mixer_type <oss, alsa or software>
This specifies which mixer to use. The default depends on what audio output This specifies which mixer to use. The default depends on what audio output
support mpd was built with. support mpd was built with.
...@@ -124,15 +162,17 @@ Musepack, and MP3 (through ID3v2 ReplayGain tags, not APEv2) are supported. ...@@ -124,15 +162,17 @@ Musepack, and MP3 (through ID3v2 ReplayGain tags, not APEv2) are supported.
This is the gain (in dB) applied to songs with ReplayGain tags. This is the gain (in dB) applied to songs with ReplayGain tags.
.TP .TP
.B volume_normalization <yes or no> .B volume_normalization <yes or no>
If yes, mpd will normalize the volume of songs as they play. Default is no. If yes, mpd will normalize the volume of songs as they play. The default is no.
.TP .TP
.B audio_buffer_size <size in KiB> .B audio_buffer_size <size in KiB>
This specifies the size of the audio output buffer that mpd uses. The default This specifies the size of the audio buffer in kibibytes. The default is 2048,
is 2048. large enough for nearly 12 seconds of CD-quality audio.
.TP .TP
.B buffer_before_play <0-100%> .B buffer_before_play <0-100%>
This specifies the amount of the audio buffer that will be filled before a song This specifies how much of the audio buffer should be filled before playing a
begins playing. The default is 25%. song. Try increasing this if you hear skipping when manually changing songs.
The default is 10%, a little over 1 second of CD-quality audio with the default
buffer size.
.TP .TP
.B http_buffer_size <size in KiB> .B http_buffer_size <size in KiB>
This specifies the size of the buffer used for playing HTTP streams. The This specifies the size of the buffer used for playing HTTP streams. The
...@@ -184,8 +224,20 @@ supported character sets can be obtained by running "iconv -l". The default is ...@@ -184,8 +224,20 @@ supported character sets can be obtained by running "iconv -l". The default is
to let libid3tag convert them (from ISO-8859-1, as the standard specifies) and to let libid3tag convert them (from ISO-8859-1, as the standard specifies) and
do no additional conversion. do no additional conversion.
.TP .TP
.B gapless_mp3_playback <yes or no>
This specifies whether to support gapless playback of MP3s which have the
necessary headers. Useful if your MP3s have headers with incorrect
information. If you have such MP3s, it is highly recommended that you fix them
using vbrfix (available from <http://www.willwap.co.uk/Programs/vbrfix.php>)
instead of disabling gapless MP3 playback. The default is to support gapless
MP3 playback.
.TP
.B save_absolute_paths_in_playlists <yes or no>
This specifies whether relative or absolute paths for song filenames are used
when saving playlists. The default is "no".
.TP
.B metadata_to_use <tags> .B metadata_to_use <tags>
This specifies the song metadata that will be scanned and made available to This specifies the tag types that will be scanned for and made available to
clients. Note that you must recreate (not update) your database for changes to clients. Note that you must recreate (not update) your database for changes to
this parameter to take effect. Possible values are artist, album, title, this parameter to take effect. Possible values are artist, album, title,
track, name, genre, date, composer, performer, comment, and disc. Multiple track, name, genre, date, composer, performer, comment, and disc. Multiple
...@@ -193,10 +245,6 @@ tags may be specified as a comma separated list. An example value is ...@@ -193,10 +245,6 @@ tags may be specified as a comma separated list. An example value is
"artist,album,title,track". The special value "none" may be used alone to "artist,album,title,track". The special value "none" may be used alone to
disable all metadata. The default is to use all known tag types except for disable all metadata. The default is to use all known tag types except for
comments. comments.
.TP
.B save_absolute_paths_in_playlists <yes or no>
This specifies whether relative or absolute paths for song filenames are used
when saving playlists. The default is "no".
.SH REQUIRED AUDIO OUTPUT PARAMETERS .SH REQUIRED AUDIO OUTPUT PARAMETERS
.TP .TP
.B type <type> .B type <type>
...@@ -215,11 +263,12 @@ whatever audio format is passed to the audio output. ...@@ -215,11 +263,12 @@ whatever audio format is passed to the audio output.
.SH OPTIONAL ALSA OUTPUT PARAMETERS .SH OPTIONAL ALSA OUTPUT PARAMETERS
.TP .TP
.B device <dev> .B device <dev>
This specifies the device to use for audio output. The default is "hw:0,0". This specifies the device to use for audio output. The default is "default".
.TP .TP
.B use_mmap <yes or no> .B use_mmap <yes or no>
Setting this allows you to use memory-mapped I/O. Certain hardware setups may Setting this allows you to use memory-mapped I/O. Certain hardware setups may
benefit from this, but most do not. Most users do not need to set this. benefit from this, but most do not. Most users do not need to set this. The
default is to not use memory-mapped I/O.
.TP .TP
.B buffer_time <time in microseconds> .B buffer_time <time in microseconds>
This sets the length of the hardware sample buffer in microseconds. Increasing This sets the length of the hardware sample buffer in microseconds. Increasing
...@@ -246,6 +295,20 @@ default is to let PulseAudio choose a server. ...@@ -246,6 +295,20 @@ default is to let PulseAudio choose a server.
.TP .TP
.B sink <sink> .B sink <sink>
The sink to output to. The default is to let PulseAudio choose a sink. The sink to output to. The default is to let PulseAudio choose a sink.
.SH REQUIRED JACK OUTPUT PARAMETERS
.TP
.B name <name>
The client name to use when connecting to JACK. The output ports <name>:left
and <name>:right will also be created for the left and right channels,
respectively.
.SH OPTIONAL JACK OUTPUT PARAMETERS
.TP
.B ports <left_port,right_port>
This specifies the left and right ports to connect to for the left and right
channels, respectively. The default is to let JACK choose a pair of ports.
.TP
.B ringbuffer_size <size in bytes>
This specifies the size of the ringbuffer in bytes. The default is 32768.
.SH OPTIONAL AO OUTPUT PARAMETERS .SH OPTIONAL AO OUTPUT PARAMETERS
.TP .TP
.B driver <driver> .B driver <driver>
......
...@@ -45,6 +45,12 @@ error_file "~/.mpd/mpd.error" ...@@ -45,6 +45,12 @@ error_file "~/.mpd/mpd.error"
# #
#log_level "default" #log_level "default"
# #
# If Zeroconf is configured, the service name to publish. This
# should be unique on your local network, but name collisions
# will be taken care of for you.
#
#zeroconf_name "Music Player"
#
################################################################ ################################################################
...@@ -117,6 +123,13 @@ error_file "~/.mpd/mpd.error" ...@@ -117,6 +123,13 @@ error_file "~/.mpd/mpd.error"
# #
#audio_output_format "44100:16:2" #audio_output_format "44100:16:2"
# #
# If MPD has been compiled with libsamplerate support, this
# specifies the sample rate converter to use. Possible
# values can be found in the mpd.conf man page or the
# libsamplerate documentation.
#
#samplerate_converter "Fastest Sinc Interpolator"
#
################################################################ ################################################################
...@@ -175,8 +188,9 @@ error_file "~/.mpd/mpd.error" ...@@ -175,8 +188,9 @@ error_file "~/.mpd/mpd.error"
#audio_buffer_size "2048" #audio_buffer_size "2048"
# #
# How much of the buffer to fill before beginning to play. # How much of the buffer to fill before beginning to play.
# Increase this if you hear skipping when changing songs.
# #
#buffer_before_play "0%" #buffer_before_play "10%"
# #
# Similar options for the HTTP stream buffer. If you hear # Similar options for the HTTP stream buffer. If you hear
# skipping while playing HTTP streams, you may wish to increase # skipping while playing HTTP streams, you may wish to increase
...@@ -233,13 +247,22 @@ error_file "~/.mpd/mpd.error" ...@@ -233,13 +247,22 @@ error_file "~/.mpd/mpd.error"
######################### OTHER OPTIONS ######################## ######################### OTHER OPTIONS ########################
# #
# The metadata types MPD will recognize. # Try disabling this if you have MP3s which appear to end
# abruptly. If this solves the problem, it is highly
# recommended that you fix your MP3s with vbrfix (available from
# <http://www.willwap.co.uk/Programs/vbrfix.php>), at which
# point you can re-enable support for gapless MP3 playback.
# #
#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc" #gapless_mp3_playback "yes"
# #
# Enable this if you wish to use your MPD created playlists in # Enable this if you wish to use your MPD created playlists in
# other music players. # other music players.
# #
#save_absolute_paths_in_playlists "no" #save_absolute_paths_in_playlists "no"
# #
# A list of tag types that MPD will scan for and make available
# to clients.
#
#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc"
#
################################################################ ################################################################
...@@ -8,7 +8,8 @@ mpd_audioOutputs = \ ...@@ -8,7 +8,8 @@ mpd_audioOutputs = \
audioOutputs/audioOutput_osx.c \ audioOutputs/audioOutput_osx.c \
audioOutputs/audioOutput_pulse.c \ audioOutputs/audioOutput_pulse.c \
audioOutputs/audioOutput_mvp.c \ audioOutputs/audioOutput_mvp.c \
audioOutputs/audioOutput_shout.c audioOutputs/audioOutput_shout.c \
audioOutputs/audioOutput_jack.c
mpd_inputPlugins = \ mpd_inputPlugins = \
inputPlugins/_flac_common.c \ inputPlugins/_flac_common.c \
...@@ -71,7 +72,11 @@ mpd_headers = \ ...@@ -71,7 +72,11 @@ mpd_headers = \
tree.h \ tree.h \
utf8.h \ utf8.h \
utils.h \ utils.h \
volume.h volume.h \
ioops.h \
zeroconf.h \
locate.h \
storedPlaylist.h
mpd_SOURCES = \ mpd_SOURCES = \
...@@ -120,7 +125,10 @@ mpd_SOURCES = \ ...@@ -120,7 +125,10 @@ mpd_SOURCES = \
tree.c \ tree.c \
utils.c \ utils.c \
volume.c \ volume.c \
utf8.c utf8.c \
zeroconf.c \
locate.c \
storedPlaylist.c
mpd_CFLAGS = $(MPD_CFLAGS) mpd_CFLAGS = $(MPD_CFLAGS)
......
...@@ -129,7 +129,8 @@ mpd_audioOutputs = \ ...@@ -129,7 +129,8 @@ mpd_audioOutputs = \
audioOutputs/audioOutput_osx.c \ audioOutputs/audioOutput_osx.c \
audioOutputs/audioOutput_pulse.c \ audioOutputs/audioOutput_pulse.c \
audioOutputs/audioOutput_mvp.c \ audioOutputs/audioOutput_mvp.c \
audioOutputs/audioOutput_shout.c audioOutputs/audioOutput_shout.c \
audioOutputs/audioOutput_jack.c
mpd_inputPlugins = \ mpd_inputPlugins = \
...@@ -193,7 +194,11 @@ mpd_headers = \ ...@@ -193,7 +194,11 @@ mpd_headers = \
tree.h \ tree.h \
utf8.h \ utf8.h \
utils.h \ utils.h \
volume.h volume.h \
ioops.h \
zeroconf.h \
locate.h \
storedPlaylist.h
mpd_SOURCES = \ mpd_SOURCES = \
...@@ -242,7 +247,10 @@ mpd_SOURCES = \ ...@@ -242,7 +247,10 @@ mpd_SOURCES = \
tree.c \ tree.c \
utils.c \ utils.c \
volume.c \ volume.c \
utf8.c utf8.c \
zeroconf.c \
locate.c \
storedPlaylist.c
mpd_CFLAGS = $(MPD_CFLAGS) mpd_CFLAGS = $(MPD_CFLAGS)
...@@ -265,7 +273,8 @@ am__objects_1 = ...@@ -265,7 +273,8 @@ am__objects_1 =
am__objects_2 = mpd-audioOutput_alsa.$(OBJEXT) \ am__objects_2 = mpd-audioOutput_alsa.$(OBJEXT) \
mpd-audioOutput_ao.$(OBJEXT) mpd-audioOutput_oss.$(OBJEXT) \ mpd-audioOutput_ao.$(OBJEXT) mpd-audioOutput_oss.$(OBJEXT) \
mpd-audioOutput_osx.$(OBJEXT) mpd-audioOutput_pulse.$(OBJEXT) \ mpd-audioOutput_osx.$(OBJEXT) mpd-audioOutput_pulse.$(OBJEXT) \
mpd-audioOutput_mvp.$(OBJEXT) mpd-audioOutput_shout.$(OBJEXT) mpd-audioOutput_mvp.$(OBJEXT) mpd-audioOutput_shout.$(OBJEXT) \
mpd-audioOutput_jack.$(OBJEXT)
am__objects_3 = mpd-_flac_common.$(OBJEXT) mpd-_ogg_common.$(OBJEXT) \ am__objects_3 = mpd-_flac_common.$(OBJEXT) mpd-_ogg_common.$(OBJEXT) \
mpd-oggflac_plugin.$(OBJEXT) mpd-oggvorbis_plugin.$(OBJEXT) \ mpd-oggflac_plugin.$(OBJEXT) mpd-oggvorbis_plugin.$(OBJEXT) \
mpd-aac_plugin.$(OBJEXT) mpd-audiofile_plugin.$(OBJEXT) \ mpd-aac_plugin.$(OBJEXT) mpd-audiofile_plugin.$(OBJEXT) \
...@@ -291,7 +300,8 @@ am_mpd_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ ...@@ -291,7 +300,8 @@ am_mpd_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
mpd-sllist.$(OBJEXT) mpd-song.$(OBJEXT) \ mpd-sllist.$(OBJEXT) mpd-song.$(OBJEXT) \
mpd-state_file.$(OBJEXT) mpd-stats.$(OBJEXT) mpd-tag.$(OBJEXT) \ mpd-state_file.$(OBJEXT) mpd-stats.$(OBJEXT) mpd-tag.$(OBJEXT) \
mpd-tagTracker.$(OBJEXT) mpd-tree.$(OBJEXT) mpd-utils.$(OBJEXT) \ mpd-tagTracker.$(OBJEXT) mpd-tree.$(OBJEXT) mpd-utils.$(OBJEXT) \
mpd-volume.$(OBJEXT) mpd-utf8.$(OBJEXT) mpd-volume.$(OBJEXT) mpd-utf8.$(OBJEXT) mpd-zeroconf.$(OBJEXT) \
mpd-locate.$(OBJEXT) mpd-storedPlaylist.$(OBJEXT)
mpd_OBJECTS = $(am_mpd_OBJECTS) mpd_OBJECTS = $(am_mpd_OBJECTS)
mpd_DEPENDENCIES = mpd_DEPENDENCIES =
mpd_LDFLAGS = mpd_LDFLAGS =
...@@ -310,6 +320,7 @@ am__depfiles_maybe = depfiles ...@@ -310,6 +320,7 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_alsa.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_alsa.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_ao.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_ao.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_jack.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_mvp.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_mvp.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_oss.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_oss.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_osx.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_osx.Po \
...@@ -330,8 +341,8 @@ am__depfiles_maybe = depfiles ...@@ -330,8 +341,8 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-inputStream_http.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-inputStream_http.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-interface.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-interface.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-list.Po ./$(DEPDIR)/mpd-listen.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-list.Po ./$(DEPDIR)/mpd-listen.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-log.Po ./$(DEPDIR)/mpd-ls.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-locate.Po ./$(DEPDIR)/mpd-log.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-main.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-ls.Po ./$(DEPDIR)/mpd-main.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-metadataChunk.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-metadataChunk.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-mod_plugin.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-mod_plugin.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp3_plugin.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp3_plugin.Po \
...@@ -353,10 +364,13 @@ am__depfiles_maybe = depfiles ...@@ -353,10 +364,13 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-signal_check.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-signal_check.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-sllist.Po ./$(DEPDIR)/mpd-song.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-sllist.Po ./$(DEPDIR)/mpd-song.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-state_file.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-state_file.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-stats.Po ./$(DEPDIR)/mpd-tag.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-stats.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-storedPlaylist.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-tag.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-tagTracker.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-tagTracker.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-tree.Po ./$(DEPDIR)/mpd-utf8.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-tree.Po ./$(DEPDIR)/mpd-utf8.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-utils.Po ./$(DEPDIR)/mpd-volume.Po @AMDEP_TRUE@ ./$(DEPDIR)/mpd-utils.Po ./$(DEPDIR)/mpd-volume.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-zeroconf.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
...@@ -419,6 +433,7 @@ mpd-audioOutput_osx.$(OBJEXT): audioOutputs/audioOutput_osx.c ...@@ -419,6 +433,7 @@ mpd-audioOutput_osx.$(OBJEXT): audioOutputs/audioOutput_osx.c
mpd-audioOutput_pulse.$(OBJEXT): audioOutputs/audioOutput_pulse.c mpd-audioOutput_pulse.$(OBJEXT): audioOutputs/audioOutput_pulse.c
mpd-audioOutput_mvp.$(OBJEXT): audioOutputs/audioOutput_mvp.c mpd-audioOutput_mvp.$(OBJEXT): audioOutputs/audioOutput_mvp.c
mpd-audioOutput_shout.$(OBJEXT): audioOutputs/audioOutput_shout.c mpd-audioOutput_shout.$(OBJEXT): audioOutputs/audioOutput_shout.c
mpd-audioOutput_jack.$(OBJEXT): audioOutputs/audioOutput_jack.c
mpd-_flac_common.$(OBJEXT): inputPlugins/_flac_common.c mpd-_flac_common.$(OBJEXT): inputPlugins/_flac_common.c
mpd-_ogg_common.$(OBJEXT): inputPlugins/_ogg_common.c mpd-_ogg_common.$(OBJEXT): inputPlugins/_ogg_common.c
mpd-oggflac_plugin.$(OBJEXT): inputPlugins/oggflac_plugin.c mpd-oggflac_plugin.$(OBJEXT): inputPlugins/oggflac_plugin.c
...@@ -473,6 +488,9 @@ mpd-tree.$(OBJEXT): tree.c ...@@ -473,6 +488,9 @@ mpd-tree.$(OBJEXT): tree.c
mpd-utils.$(OBJEXT): utils.c mpd-utils.$(OBJEXT): utils.c
mpd-volume.$(OBJEXT): volume.c mpd-volume.$(OBJEXT): volume.c
mpd-utf8.$(OBJEXT): utf8.c mpd-utf8.$(OBJEXT): utf8.c
mpd-zeroconf.$(OBJEXT): zeroconf.c
mpd-locate.$(OBJEXT): locate.c
mpd-storedPlaylist.$(OBJEXT): storedPlaylist.c
mpd$(EXEEXT): $(mpd_OBJECTS) $(mpd_DEPENDENCIES) mpd$(EXEEXT): $(mpd_OBJECTS) $(mpd_DEPENDENCIES)
@rm -f mpd$(EXEEXT) @rm -f mpd$(EXEEXT)
$(LINK) $(mpd_LDFLAGS) $(mpd_OBJECTS) $(mpd_LDADD) $(LIBS) $(LINK) $(mpd_LDFLAGS) $(mpd_OBJECTS) $(mpd_LDADD) $(LIBS)
...@@ -490,6 +508,7 @@ distclean-compile: ...@@ -490,6 +508,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_alsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_alsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_ao.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_ao.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_jack.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_mvp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_mvp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_oss.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_oss.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_osx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_osx.Po@am__quote@
...@@ -512,6 +531,7 @@ distclean-compile: ...@@ -512,6 +531,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-interface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-interface.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-listen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-listen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-locate.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-log.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-ls.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-ls.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-main.Po@am__quote@
...@@ -538,12 +558,14 @@ distclean-compile: ...@@ -538,12 +558,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-song.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-song.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-state_file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-state_file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-stats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-stats.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-storedPlaylist.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tag.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tagTracker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tagTracker.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-tree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-utf8.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-utf8.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-volume.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-volume.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-zeroconf.Po@am__quote@
distclean-depend: distclean-depend:
-rm -rf ./$(DEPDIR) -rm -rf ./$(DEPDIR)
...@@ -692,6 +714,24 @@ mpd-audioOutput_shout.lo: audioOutputs/audioOutput_shout.c ...@@ -692,6 +714,24 @@ mpd-audioOutput_shout.lo: audioOutputs/audioOutput_shout.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_shout.lo `test -f 'audioOutputs/audioOutput_shout.c' || echo '$(srcdir)/'`audioOutputs/audioOutput_shout.c $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_shout.lo `test -f 'audioOutputs/audioOutput_shout.c' || echo '$(srcdir)/'`audioOutputs/audioOutput_shout.c
mpd-audioOutput_jack.o: audioOutputs/audioOutput_jack.c
@AMDEP_TRUE@ source='audioOutputs/audioOutput_jack.c' object='mpd-audioOutput_jack.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_jack.Po' tmpdepfile='$(DEPDIR)/mpd-audioOutput_jack.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_jack.o `test -f 'audioOutputs/audioOutput_jack.c' || echo '$(srcdir)/'`audioOutputs/audioOutput_jack.c
mpd-audioOutput_jack.obj: audioOutputs/audioOutput_jack.c
@AMDEP_TRUE@ source='audioOutputs/audioOutput_jack.c' object='mpd-audioOutput_jack.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_jack.Po' tmpdepfile='$(DEPDIR)/mpd-audioOutput_jack.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_jack.obj `cygpath -w audioOutputs/audioOutput_jack.c`
mpd-audioOutput_jack.lo: audioOutputs/audioOutput_jack.c
@AMDEP_TRUE@ source='audioOutputs/audioOutput_jack.c' object='mpd-audioOutput_jack.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_jack.Plo' tmpdepfile='$(DEPDIR)/mpd-audioOutput_jack.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_jack.lo `test -f 'audioOutputs/audioOutput_jack.c' || echo '$(srcdir)/'`audioOutputs/audioOutput_jack.c
mpd-_flac_common.o: inputPlugins/_flac_common.c mpd-_flac_common.o: inputPlugins/_flac_common.c
@AMDEP_TRUE@ source='inputPlugins/_flac_common.c' object='mpd-_flac_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ source='inputPlugins/_flac_common.c' object='mpd-_flac_common.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-_flac_common.Po' tmpdepfile='$(DEPDIR)/mpd-_flac_common.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-_flac_common.Po' tmpdepfile='$(DEPDIR)/mpd-_flac_common.TPo' @AMDEPBACKSLASH@
...@@ -1663,6 +1703,60 @@ mpd-utf8.lo: utf8.c ...@@ -1663,6 +1703,60 @@ mpd-utf8.lo: utf8.c
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-utf8.Plo' tmpdepfile='$(DEPDIR)/mpd-utf8.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-utf8.Plo' tmpdepfile='$(DEPDIR)/mpd-utf8.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-utf8.lo `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-utf8.lo `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c
mpd-zeroconf.o: zeroconf.c
@AMDEP_TRUE@ source='zeroconf.c' object='mpd-zeroconf.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-zeroconf.Po' tmpdepfile='$(DEPDIR)/mpd-zeroconf.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-zeroconf.o `test -f 'zeroconf.c' || echo '$(srcdir)/'`zeroconf.c
mpd-zeroconf.obj: zeroconf.c
@AMDEP_TRUE@ source='zeroconf.c' object='mpd-zeroconf.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-zeroconf.Po' tmpdepfile='$(DEPDIR)/mpd-zeroconf.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-zeroconf.obj `cygpath -w zeroconf.c`
mpd-zeroconf.lo: zeroconf.c
@AMDEP_TRUE@ source='zeroconf.c' object='mpd-zeroconf.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-zeroconf.Plo' tmpdepfile='$(DEPDIR)/mpd-zeroconf.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-zeroconf.lo `test -f 'zeroconf.c' || echo '$(srcdir)/'`zeroconf.c
mpd-locate.o: locate.c
@AMDEP_TRUE@ source='locate.c' object='mpd-locate.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-locate.Po' tmpdepfile='$(DEPDIR)/mpd-locate.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-locate.o `test -f 'locate.c' || echo '$(srcdir)/'`locate.c
mpd-locate.obj: locate.c
@AMDEP_TRUE@ source='locate.c' object='mpd-locate.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-locate.Po' tmpdepfile='$(DEPDIR)/mpd-locate.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-locate.obj `cygpath -w locate.c`
mpd-locate.lo: locate.c
@AMDEP_TRUE@ source='locate.c' object='mpd-locate.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-locate.Plo' tmpdepfile='$(DEPDIR)/mpd-locate.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-locate.lo `test -f 'locate.c' || echo '$(srcdir)/'`locate.c
mpd-storedPlaylist.o: storedPlaylist.c
@AMDEP_TRUE@ source='storedPlaylist.c' object='mpd-storedPlaylist.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-storedPlaylist.Po' tmpdepfile='$(DEPDIR)/mpd-storedPlaylist.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-storedPlaylist.o `test -f 'storedPlaylist.c' || echo '$(srcdir)/'`storedPlaylist.c
mpd-storedPlaylist.obj: storedPlaylist.c
@AMDEP_TRUE@ source='storedPlaylist.c' object='mpd-storedPlaylist.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-storedPlaylist.Po' tmpdepfile='$(DEPDIR)/mpd-storedPlaylist.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-storedPlaylist.obj `cygpath -w storedPlaylist.c`
mpd-storedPlaylist.lo: storedPlaylist.c
@AMDEP_TRUE@ source='storedPlaylist.c' object='mpd-storedPlaylist.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-storedPlaylist.Plo' tmpdepfile='$(DEPDIR)/mpd-storedPlaylist.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-storedPlaylist.lo `test -f 'storedPlaylist.c' || echo '$(srcdir)/'`storedPlaylist.c
CCDEPMODE = @CCDEPMODE@ CCDEPMODE = @CCDEPMODE@
mostlyclean-libtool: mostlyclean-libtool:
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -39,12 +39,12 @@ ...@@ -39,12 +39,12 @@
#define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */ #define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */
#define AUDIO_BUFFER_SIZE 2*MAXPATHLEN #define AUDIO_BUFFER_SIZE 2*MAXPATHLEN
static AudioFormat audio_format = { 0, 0, 0 }; static AudioFormat audio_format;
static AudioFormat *audio_configFormat = NULL; static AudioFormat *audio_configFormat;
static AudioOutput *audioOutputArray = NULL; static AudioOutput *audioOutputArray;
static mpd_uint8 audioOutputArraySize = 0; static mpd_uint8 audioOutputArraySize;
#define DEVICE_OFF 0x00 #define DEVICE_OFF 0x00
#define DEVICE_ENABLE 0x01 /* currently off, but to be turned on */ #define DEVICE_ENABLE 0x01 /* currently off, but to be turned on */
...@@ -53,13 +53,13 @@ static mpd_uint8 audioOutputArraySize = 0; ...@@ -53,13 +53,13 @@ static mpd_uint8 audioOutputArraySize = 0;
/* the audioEnabledArray should be stuck into shared memory, and then disable /* the audioEnabledArray should be stuck into shared memory, and then disable
and enable in playAudio() routine */ and enable in playAudio() routine */
static mpd_uint8 *audioDeviceStates = NULL; static mpd_uint8 *audioDeviceStates;
static mpd_uint8 audioOpened = 0; static mpd_uint8 audioOpened;
static mpd_sint32 audioBufferSize = 0; static mpd_sint32 audioBufferSize;
static char *audioBuffer = NULL; static char *audioBuffer;
static mpd_sint32 audioBufferPos = 0; static mpd_sint32 audioBufferPos;
size_t audio_device_count(void) size_t audio_device_count(void)
{ {
...@@ -89,14 +89,6 @@ int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2) ...@@ -89,14 +89,6 @@ int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2)
return 1; return 1;
} }
extern AudioOutputPlugin alsaPlugin;
extern AudioOutputPlugin aoPlugin;
extern AudioOutputPlugin ossPlugin;
extern AudioOutputPlugin osxPlugin;
extern AudioOutputPlugin pulsePlugin;
extern AudioOutputPlugin mvpPlugin;
extern AudioOutputPlugin shoutPlugin;
void loadAudioDrivers(void) void loadAudioDrivers(void)
{ {
initAudioOutputPlugins(); initAudioOutputPlugins();
...@@ -107,6 +99,7 @@ void loadAudioDrivers(void) ...@@ -107,6 +99,7 @@ void loadAudioDrivers(void)
loadAudioOutputPlugin(&pulsePlugin); loadAudioOutputPlugin(&pulsePlugin);
loadAudioOutputPlugin(&mvpPlugin); loadAudioOutputPlugin(&mvpPlugin);
loadAudioOutputPlugin(&shoutPlugin); loadAudioOutputPlugin(&shoutPlugin);
loadAudioOutputPlugin(&jackPlugin);
} }
/* make sure initPlayerData is called before this function!! */ /* make sure initPlayerData is called before this function!! */
...@@ -134,23 +127,21 @@ void initAudioDriver(void) ...@@ -134,23 +127,21 @@ void initAudioDriver(void)
if (!initAudioOutput(output, param)) { if (!initAudioOutput(output, param)) {
if (param) if (param)
{ {
ERROR("problems configuring output device " FATAL("problems configuring output device "
"defined at line %i\n", param->line); "defined at line %i\n", param->line);
} }
else else
{ {
ERROR("No audio_output specified and unable to " FATAL("No audio_output specified and unable to "
"detect a default audio output device\n"); "detect a default audio output device\n");
} }
exit(EXIT_FAILURE);
} }
/* require output names to be unique: */ /* require output names to be unique: */
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
if (!strcmp(output->name, audioOutputArray[j].name)) { if (!strcmp(output->name, audioOutputArray[j].name)) {
ERROR("output devices with identical " FATAL("output devices with identical "
"names: %s\n", output->name); "names: %s\n", output->name);
exit(EXIT_FAILURE);
} }
} }
audioDeviceStates[i] = DEVICE_ENABLE; audioDeviceStates[i] = DEVICE_ENABLE;
...@@ -176,9 +167,8 @@ void initAudioConfig(void) ...@@ -176,9 +167,8 @@ void initAudioConfig(void)
audio_configFormat = xmalloc(sizeof(AudioFormat)); audio_configFormat = xmalloc(sizeof(AudioFormat));
if (0 != parseAudioConfig(audio_configFormat, param->value)) { if (0 != parseAudioConfig(audio_configFormat, param->value)) {
ERROR("error parsing \"%s\" at line %i\n", FATAL("error parsing \"%s\" at line %i\n",
CONF_AUDIO_OUTPUT_FORMAT, param->line); CONF_AUDIO_OUTPUT_FORMAT, param->line);
exit(EXIT_FAILURE);
} }
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -58,10 +58,9 @@ void finishAudioOutputPlugins(void) ...@@ -58,10 +58,9 @@ void finishAudioOutputPlugins(void)
#define getBlockParam(name, str, force) { \ #define getBlockParam(name, str, force) { \
bp = getBlockParam(param, name); \ bp = getBlockParam(param, name); \
if(force && bp == NULL) { \ if(force && bp == NULL) { \
ERROR("couldn't find parameter \"%s\" in audio output " \ FATAL("couldn't find parameter \"%s\" in audio output " \
"definition beginning at %i\n", \ "definition beginning at %i\n", \
name, param->line); \ name, param->line); \
exit(EXIT_FAILURE); \
} \ } \
if(bp) str = bp->value; \ if(bp) str = bp->value; \
} }
...@@ -81,9 +80,8 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param) ...@@ -81,9 +80,8 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param)
getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0); getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0);
if (!findInList(audioOutputPluginList, type, &data)) { if (!findInList(audioOutputPluginList, type, &data)) {
ERROR("couldn't find audio output plugin for type " FATAL("couldn't find audio output plugin for type "
"\"%s\" at line %i\n", type, param->line); "\"%s\" at line %i\n", type, param->line);
exit(EXIT_FAILURE);
} }
plugin = (AudioOutputPlugin *) data; plugin = (AudioOutputPlugin *) data;
...@@ -135,13 +133,13 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param) ...@@ -135,13 +133,13 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param)
memset(&ao->inAudioFormat, 0, sizeof(AudioFormat)); memset(&ao->inAudioFormat, 0, sizeof(AudioFormat));
memset(&ao->outAudioFormat, 0, sizeof(AudioFormat)); memset(&ao->outAudioFormat, 0, sizeof(AudioFormat));
memset(&ao->reqAudioFormat, 0, sizeof(AudioFormat)); memset(&ao->reqAudioFormat, 0, sizeof(AudioFormat));
memset(&ao->convState, 0, sizeof(ConvState));
if (format) { if (format) {
ao->convertAudioFormat = 1; ao->convertAudioFormat = 1;
if (0 != parseAudioConfig(&ao->reqAudioFormat, format)) { if (0 != parseAudioConfig(&ao->reqAudioFormat, format)) {
ERROR("error parsing format at line %i\n", bp->line); FATAL("error parsing format at line %i\n", bp->line);
exit(EXIT_FAILURE);
} }
copyAudioFormat(&ao->outAudioFormat, &ao->reqAudioFormat); copyAudioFormat(&ao->outAudioFormat, &ao->reqAudioFormat);
...@@ -155,33 +153,38 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param) ...@@ -155,33 +153,38 @@ int initAudioOutput(AudioOutput *ao, ConfigParam * param)
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat)
{ {
int ret; int ret = 0;
if (audioOutput->open) { if (audioOutput->open)
if (cmpAudioFormat(audioFormat, &audioOutput->inAudioFormat) {
== 0) { if (0==cmpAudioFormat(audioFormat, &audioOutput->inAudioFormat))
{
return 0; return 0;
} }
closeAudioOutput(audioOutput);
} }
copyAudioFormat(&audioOutput->inAudioFormat, audioFormat); copyAudioFormat(&audioOutput->inAudioFormat, audioFormat);
if (audioOutput->convertAudioFormat) { if (audioOutput->convertAudioFormat)
{
copyAudioFormat(&audioOutput->outAudioFormat, copyAudioFormat(&audioOutput->outAudioFormat,
&audioOutput->reqAudioFormat); &audioOutput->reqAudioFormat);
} else { }
else
{
copyAudioFormat(&audioOutput->outAudioFormat, copyAudioFormat(&audioOutput->outAudioFormat,
&audioOutput->inAudioFormat); &audioOutput->inAudioFormat);
if (audioOutput->open) closeAudioOutput(audioOutput);
} }
ret = audioOutput->openDeviceFunc(audioOutput); if (!audioOutput->open)
{
ret = audioOutput->openDeviceFunc(audioOutput);
}
if (cmpAudioFormat(&audioOutput->inAudioFormat, audioOutput->sameInAndOutFormats =
&audioOutput->outAudioFormat) == 0) { !cmpAudioFormat(&audioOutput->inAudioFormat,
audioOutput->sameInAndOutFormats = 1; &audioOutput->outAudioFormat);
} else
audioOutput->sameInAndOutFormats = 0;
return ret; return ret;
} }
...@@ -189,12 +192,9 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) ...@@ -189,12 +192,9 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat)
static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr, static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr,
int *sizeArgPtr) int *sizeArgPtr)
{ {
int size = int size = pcm_sizeOfConvBuffer(&(audioOutput->inAudioFormat),
pcm_sizeOfOutputBufferForAudioFormatConversion(& *sizeArgPtr,
(audioOutput-> &(audioOutput->outAudioFormat));
inAudioFormat),
*sizeArgPtr,
&(audioOutput->outAudioFormat));
if (size > audioOutput->convBufferLen) { if (size > audioOutput->convBufferLen) {
audioOutput->convBuffer = audioOutput->convBuffer =
...@@ -202,11 +202,12 @@ static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr, ...@@ -202,11 +202,12 @@ static void convertAudioFormat(AudioOutput * audioOutput, char **chunkArgPtr,
audioOutput->convBufferLen = size; audioOutput->convBufferLen = size;
} }
pcm_convertAudioFormat(&(audioOutput->inAudioFormat), *chunkArgPtr, *sizeArgPtr = pcm_convertAudioFormat(&(audioOutput->inAudioFormat),
*sizeArgPtr, &(audioOutput->outAudioFormat), *chunkArgPtr, *sizeArgPtr,
audioOutput->convBuffer); &(audioOutput->outAudioFormat),
audioOutput->convBuffer,
&audioOutput->convState);
*sizeArgPtr = size;
*chunkArgPtr = audioOutput->convBuffer; *chunkArgPtr = audioOutput->convBuffer;
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -21,24 +21,14 @@ ...@@ -21,24 +21,14 @@
#include "../config.h" #include "../config.h"
#include "pcm_utils.h"
#include "mpd_types.h" #include "mpd_types.h"
#include "audio.h" #include "audio.h"
#include "tag.h" #include "tag.h"
#include "conf.h" #include "conf.h"
#include "utils.h" #include "utils.h"
#define DISABLED_AUDIO_OUTPUT_PLUGIN(plugin) \ #define DISABLED_AUDIO_OUTPUT_PLUGIN(plugin) AudioOutputPlugin plugin;
AudioOutputPlugin plugin = { \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL \
};
typedef struct _AudioOutput AudioOutput; typedef struct _AudioOutput AudioOutput;
...@@ -77,6 +67,7 @@ struct _AudioOutput { ...@@ -77,6 +67,7 @@ struct _AudioOutput {
AudioFormat inAudioFormat; AudioFormat inAudioFormat;
AudioFormat outAudioFormat; AudioFormat outAudioFormat;
AudioFormat reqAudioFormat; AudioFormat reqAudioFormat;
ConvState convState;
char *convBuffer; char *convBuffer;
int convBufferLen; int convBufferLen;
int sameInAndOutFormats; int sameInAndOutFormats;
...@@ -113,4 +104,14 @@ int keepAudioOutputAlive(AudioOutput * audioOutput, int ms); ...@@ -113,4 +104,14 @@ int keepAudioOutputAlive(AudioOutput * audioOutput, int ms);
void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag); void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag);
void printAllOutputPluginTypes(FILE * fp); void printAllOutputPluginTypes(FILE * fp);
extern AudioOutputPlugin alsaPlugin;
extern AudioOutputPlugin aoPlugin;
extern AudioOutputPlugin ossPlugin;
extern AudioOutputPlugin osxPlugin;
extern AudioOutputPlugin pulsePlugin;
extern AudioOutputPlugin mvpPlugin;
extern AudioOutputPlugin shoutPlugin;
extern AudioOutputPlugin jackPlugin;
#endif #endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -34,11 +34,8 @@ ...@@ -34,11 +34,8 @@
#include "../conf.h" #include "../conf.h"
#include "../log.h" #include "../log.h"
#include "../sig_handlers.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
...@@ -88,8 +85,7 @@ static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -88,8 +85,7 @@ static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param)
ad->device = bp ? xstrdup(bp->value) : xstrdup("default"); ad->device = bp ? xstrdup(bp->value) : xstrdup("default");
if ((bp = getBlockParam(param, "use_mmap")) && if ((bp = getBlockParam(param, "use_mmap")) &&
(!strcasecmp(bp->value, "yes") || !strcasecmp(bp->value, "yes"))
!strcasecmp(bp->value, "true")))
ad->useMmap = 1; ad->useMmap = 1;
if ((bp = getBlockParam(param, "buffer_time"))) if ((bp = getBlockParam(param, "buffer_time")))
ad->buffer_time = atoi(bp->value); ad->buffer_time = atoi(bp->value);
...@@ -210,7 +206,7 @@ configure_hw: ...@@ -210,7 +206,7 @@ configure_hw:
err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat); err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat);
if (err < 0) { if (err < 0) {
ERROR("ALSA device \"%s\" does not support %i bit audio: " ERROR("ALSA device \"%s\" does not support %i bit audio: "
"%s\n", ad->device, (int)bitformat, snd_strerror(-err)); "%s\n", ad->device, audioFormat->bits, snd_strerror(-err));
goto fail; goto fail;
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -24,12 +24,10 @@ ...@@ -24,12 +24,10 @@
#include "../log.h" #include "../log.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
#include <ao/ao.h> #include <ao/ao.h>
static int driverInitCount = 0; static int driverInitCount;
typedef struct _AoData { typedef struct _AoData {
int writeSize; int writeSize;
...@@ -77,9 +75,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput, ...@@ -77,9 +75,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
if ((blockParam = getBlockParam(param, "write_size"))) { if ((blockParam = getBlockParam(param, "write_size"))) {
ad->writeSize = strtol(blockParam->value, &test, 10); ad->writeSize = strtol(blockParam->value, &test, 10);
if (*test != '\0') { if (*test != '\0') {
ERROR("\"%s\" is not a valid write size at line %i\n", FATAL("\"%s\" is not a valid write size at line %i\n",
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE);
} }
} else } else
ad->writeSize = 1024; ad->writeSize = 1024;
...@@ -94,16 +91,13 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput, ...@@ -94,16 +91,13 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
if (!blockParam || 0 == strcmp(blockParam->value, "default")) { if (!blockParam || 0 == strcmp(blockParam->value, "default")) {
ad->driverId = ao_default_driver_id(); ad->driverId = ao_default_driver_id();
} else if ((ad->driverId = ao_driver_id(blockParam->value)) < 0) { } else if ((ad->driverId = ao_driver_id(blockParam->value)) < 0) {
ERROR("\"%s\" is not a valid ao driver at line %i\n", FATAL("\"%s\" is not a valid ao driver at line %i\n",
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE);
} }
if ((ai = ao_driver_info(ad->driverId)) == NULL) { if ((ai = ao_driver_info(ad->driverId)) == NULL) {
ERROR("problems getting driver info for device defined at " FATAL("problems getting driver info for device defined at line %i\n"
"line %i\n", param->line); "you may not have permission to the audio device\n", param->line);
ERROR("you may not have permission to the audio device\n");
exit(EXIT_FAILURE);
} }
DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name, DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name,
...@@ -122,11 +116,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput, ...@@ -122,11 +116,8 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
while (n1) { while (n1) {
stk2 = NULL; stk2 = NULL;
key = strtok_r(n1, "=", &stk2); key = strtok_r(n1, "=", &stk2);
if (!key) { if (!key)
ERROR("problems parsing " FATAL("problems parsing options \"%s\"\n", n1);
"ao_driver_options \"%s\"\n", n1);
exit(EXIT_FAILURE);
}
/*found = 0; /*found = 0;
for(i=0;i<ai->option_count;i++) { for(i=0;i<ai->option_count;i++) {
if(strcmp(ai->options[i],key)==0) { if(strcmp(ai->options[i],key)==0) {
...@@ -135,17 +126,13 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput, ...@@ -135,17 +126,13 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput,
} }
} }
if(!found) { if(!found) {
ERROR("\"%s\" is not an option for " FATAL("\"%s\" is not an option for "
"\"%s\" ao driver\n",key, "\"%s\" ao driver\n",key,
ai->short_name); ai->short_name);
exit(EXIT_FAILURE);
} */ } */
value = strtok_r(NULL, "", &stk2); value = strtok_r(NULL, "", &stk2);
if (!value) { if (!value)
ERROR("problems parsing " FATAL("problems parsing options \"%s\"\n", n1);
"ao_driver_options \"%s\"\n", n1);
exit(EXIT_FAILURE);
}
ao_append_option(&ad->options, key, value); ao_append_option(&ad->options, key, value);
n1 = strtok_r(NULL, ";", &stk1); n1 = strtok_r(NULL, ";", &stk1);
} }
......
/* jack plug in for the Music Player Daemon (MPD)
* (c)2006 by anarch(anarchsss@gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../audioOutput.h"
#ifdef HAVE_JACK
#include <stdlib.h>
#include <errno.h>
#include "../conf.h"
#include "../log.h"
#include <string.h>
#include <pthread.h>
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/ringbuffer.h>
pthread_mutex_t play_audio_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t play_audio = PTHREAD_COND_INITIALIZER;
/*#include "dmalloc.h"*/
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/*#define SAMPLE_SIZE sizeof(jack_default_audio_sample_t);*/
static char *name = "mpd";
static char *output_ports[2];
static int ringbuf_sz = 32768;
size_t sample_size = sizeof(jack_default_audio_sample_t);
typedef struct _JackData {
jack_port_t *ports[2];
jack_client_t *client;
jack_ringbuffer_t *ringbuffer[2];
int bps;
int shutdown;
} JackData;
/*JackData *jd = NULL;*/
static JackData *newJackData(void)
{
JackData *ret;
ret = xcalloc(sizeof(JackData), 1);
return ret;
}
static void freeJackData(AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
if (jd) {
if (jd->ringbuffer[0])
jack_ringbuffer_free(jd->ringbuffer[0]);
if (jd->ringbuffer[1])
jack_ringbuffer_free(jd->ringbuffer[1]);
free(jd);
audioOutput->data = NULL;
}
}
static void jack_finishDriver(AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
int i;
if ( jd && jd->client ) {
jack_deactivate(jd->client);
jack_client_close(jd->client);
}
DEBUG("disconnect_jack (pid=%d)\n", getpid ());
if ( strcmp(name, "mpd") ) {
free(name);
name = "mpd";
}
for ( i = ARRAY_SIZE(output_ports); --i >= 0; ) {
if (!output_ports[i])
continue;
free(output_ports[i]);
output_ports[i] = NULL;
}
freeJackData(audioOutput);
}
static int srate(jack_nframes_t rate, void *data)
{
JackData *jd = (JackData *) ((AudioOutput*) data)->data;
AudioFormat *audioFormat = &(((AudioOutput*) data)->outAudioFormat);
audioFormat->sampleRate = (int)jack_get_sample_rate(jd->client);
return 0;
}
static int process(jack_nframes_t nframes, void *arg)
{
size_t i;
JackData *jd = (JackData *) arg;
jack_default_audio_sample_t *out[2];
size_t avail_data, avail_frames;
if ( nframes <= 0 )
return 0;
out[0] = jack_port_get_buffer(jd->ports[0], nframes);
out[1] = jack_port_get_buffer(jd->ports[1], nframes);
while ( nframes ) {
avail_data = jack_ringbuffer_read_space(jd->ringbuffer[1]);
if ( avail_data > 0 ) {
avail_frames = avail_data / sample_size;
if (avail_frames > nframes) {
avail_frames = nframes;
avail_data = nframes*sample_size;
}
jack_ringbuffer_read(jd->ringbuffer[0], (char *)out[0],
avail_data);
jack_ringbuffer_read(jd->ringbuffer[1], (char *)out[1],
avail_data);
nframes -= avail_frames;
out[0] += avail_data;
out[1] += avail_data;
} else {
for (i = 0; i < nframes; i++)
out[0][i] = out[1][i] = 0.0;
nframes = 0;
}
if (pthread_mutex_trylock (&play_audio_lock) == 0) {
pthread_cond_signal (&play_audio);
pthread_mutex_unlock (&play_audio_lock);
}
}
/*DEBUG("process (pid=%d)\n", getpid());*/
return 0;
}
static void shutdown_callback(void *arg)
{
JackData *jd = (JackData *) arg;
jd->shutdown = 1;
}
static void set_audioformat(AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
AudioFormat *audioFormat = &audioOutput->outAudioFormat;
audioFormat->sampleRate = (int) jack_get_sample_rate(jd->client);
DEBUG("samplerate = %d\n", audioFormat->sampleRate);
audioFormat->channels = 2;
audioFormat->bits = 16;
jd->bps = audioFormat->channels
* sizeof(jack_default_audio_sample_t)
* audioFormat->sampleRate;
}
static void error_callback(const char *msg)
{
ERROR("jack: %s\n", msg);
}
static int jack_initDriver(AudioOutput *audioOutput, ConfigParam *param)
{
BlockParam *bp;
char *endptr;
int val;
char *cp = NULL;
DEBUG("jack_initDriver (pid=%d)\n", getpid());
if ( ! param ) return 0;
if ( (bp = getBlockParam(param, "ports")) ) {
DEBUG("output_ports=%s\n", bp->value);
if (!(cp = strchr(bp->value, ',')))
FATAL("expected comma and a second value for '%s' "
"at line %d: %s\n",
bp->name, bp->line, bp->value);
*cp = '\0';
output_ports[0] = xstrdup(bp->value);
*cp++ = ',';
if (!*cp)
FATAL("expected a second value for '%s' at line %d: "
"%s\n", bp->name, bp->line, bp->value);
output_ports[1] = xstrdup(cp);
if (strchr(cp,','))
FATAL("Only %d values are supported for '%s' "
"at line %d\n", (int)ARRAY_SIZE(output_ports),
bp->name, bp->line);
}
if ( (bp = getBlockParam(param, "ringbuffer_size")) ) {
errno = 0;
val = strtol(bp->value, &endptr, 10);
if ( errno == 0 && endptr != bp->value) {
ringbuf_sz = val < 32768 ? 32768 : val;
DEBUG("ringbuffer_size=%d\n", ringbuf_sz);
} else {
FATAL("%s is not a number; ringbuf_size=%d\n",
bp->value, ringbuf_sz);
}
}
if ( (bp = getBlockParam(param, "name"))
&& (strcmp(bp->value, "mpd") != 0) ) {
name = xstrdup(bp->value);
DEBUG("name=%s\n", name);
}
return 0;
}
static int jack_testDefault(void)
{
return 0;
}
static int connect_jack(AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
char **jports;
char *port_name;
if ( (jd->client = jack_client_new(name)) == NULL ) {
ERROR("jack server not running?\n");
freeJackData(audioOutput);
return -1;
}
jack_set_error_function(error_callback);
jack_set_process_callback(jd->client, process, (void *)jd);
jack_set_sample_rate_callback(jd->client, (JackProcessCallback)srate,
(void *)audioOutput);
jack_on_shutdown(jd->client, shutdown_callback, (void *)jd);
if ( jack_activate(jd->client) ) {
ERROR("cannot activate client");
freeJackData(audioOutput);
return -1;
}
jd->ports[0] = jack_port_register(jd->client, "left",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ( !jd->ports[0] ) {
ERROR("Cannot register left output port.\n");
freeJackData(audioOutput);
return -1;
}
jd->ports[1] = jack_port_register(jd->client, "right",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ( !jd->ports[1] ) {
ERROR("Cannot register right output port.\n");
freeJackData(audioOutput);
return -1;
}
/* hay que buscar que hay */
if ( !output_ports[1]
&& (jports = (char **)jack_get_ports(jd->client, NULL, NULL,
JackPortIsPhysical|
JackPortIsInput)) ) {
output_ports[0] = jports[0];
output_ports[1] = jports[1] ? jports[1] : jports[0];
DEBUG("output_ports: %s %s\n", output_ports[0], output_ports[1]);
free(jports);
}
if ( output_ports[1] ) {
jd->ringbuffer[0] = jack_ringbuffer_create(ringbuf_sz);
jd->ringbuffer[1] = jack_ringbuffer_create(ringbuf_sz);
memset(jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size);
memset(jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size);
port_name = xmalloc(sizeof(char)*(7+strlen(name)));
sprintf(port_name, "%s:left", name);
if ( (jack_connect(jd->client, port_name,
output_ports[0])) != 0 ) {
ERROR("%s is not a valid Jack Client / Port ",
output_ports[0]);
freeJackData(audioOutput);
free(port_name);
return -1;
}
sprintf(port_name, "%s:right", name);
if ( (jack_connect(jd->client, port_name,
output_ports[1])) != 0 ) {
ERROR("%s is not a valid Jack Client / Port ",
output_ports[1]);
freeJackData(audioOutput);
free(port_name);
return -1;
}
free(port_name);
}
DEBUG("connect_jack (pid=%d)\n", getpid());
return 1;
}
static int jack_openDevice(AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
if ( !jd ) {
DEBUG("connect!\n");
jd = newJackData();
audioOutput->data = jd;
if (connect_jack(audioOutput) < 0) {
freeJackData(audioOutput);
audioOutput->open = 0;
return -1;
}
}
set_audioformat(audioOutput);
audioOutput->open = 1;
DEBUG("jack_openDevice (pid=%d)!\n", getpid ());
return 0;
}
static void jack_closeDevice(AudioOutput * audioOutput)
{
/*jack_finishDriver(audioOutput);*/
audioOutput->open = 0;
DEBUG("jack_closeDevice (pid=%d)\n", getpid());
}
static void jack_dropBufferedAudio (AudioOutput * audioOutput)
{
}
static int jack_playAudio(AudioOutput * audioOutput, char *buff, int size)
{
JackData *jd = audioOutput->data;
size_t space;
int i;
short *buffer = (short *) buff;
jack_default_audio_sample_t sample;
size_t samples = size/4;
/*DEBUG("jack_playAudio: (pid=%d)!\n", getpid());*/
if ( jd->shutdown ) {
ERROR("Refusing to play, because there is no client thread.\n");
freeJackData(audioOutput);
audioOutput->open = 0;
return 0;
}
while ( samples && !jd->shutdown ) {
if ( (space = jack_ringbuffer_write_space(jd->ringbuffer[0]))
>= samples*sample_size ) {
/*space = MIN(space, samples*sample_size);*/
/*space = samples*sample_size;*/
/*for(i=0; i<space/sample_size; i++) {*/
for(i=0; i<samples; i++) {
sample = (jack_default_audio_sample_t) *(buffer++)/32768.0;
jack_ringbuffer_write(jd->ringbuffer[0], (void*)&sample,
sample_size);
sample = (jack_default_audio_sample_t) *(buffer++)/32768.0;
jack_ringbuffer_write(jd->ringbuffer[1], (void*)&sample,
sample_size);
/*samples--;*/
}
samples=0;
} else {
pthread_mutex_lock(&play_audio_lock);
pthread_cond_wait(&play_audio, &play_audio_lock);
pthread_mutex_unlock(&play_audio_lock);
}
}
return 0;
}
AudioOutputPlugin jackPlugin = {
"jack",
jack_testDefault,
jack_initDriver,
jack_finishDriver,
jack_openDevice,
jack_playAudio,
jack_dropBufferedAudio,
jack_closeDevice,
NULL, /* sendMetadataFunc */
};
#else /* HAVE JACK */
DISABLED_AUDIO_OUTPUT_PLUGIN(jackPlugin)
#endif /* HAVE_JACK */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Media MVP audio output based on code from MVPMC project: * Media MVP audio output based on code from MVPMC project:
...@@ -27,11 +27,8 @@ ...@@ -27,11 +27,8 @@
#include "../conf.h" #include "../conf.h"
#include "../log.h" #include "../log.h"
#include "../sig_handlers.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* OSS audio output (c) 2004, 2005, 2006 by Eric Wong <eric@petta-tech.com> * OSS audio output (c) 2004, 2005, 2006, 2007 by Eric Wong <eric@petta-tech.com>
* and Warren Dukes <warren.dukes@gmail.com> * and Warren Dukes <warren.dukes@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -25,14 +25,10 @@ ...@@ -25,14 +25,10 @@
#ifdef HAVE_OSS #ifdef HAVE_OSS
#include "../utils.h"
#include "../conf.h" #include "../conf.h"
#include "../log.h" #include "../log.h"
#include "../sig_handlers.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -363,7 +359,7 @@ static int oss_open_default(AudioOutput *ao, ConfigParam *param, OssData *od) ...@@ -363,7 +359,7 @@ static int oss_open_default(AudioOutput *ao, ConfigParam *param, OssData *od)
} }
if (param) if (param)
ERROR("Error trying to open specified OSS device" ERROR("error trying to open specified OSS device"
" at line %i\n", param->line); " at line %i\n", param->line);
else else
ERROR("error trying to open default OSS device\n"); ERROR("error trying to open default OSS device\n");
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <pthread.h> #include <pthread.h>
#include "../log.h" #include "../log.h"
#include "../utils.h"
typedef struct _OsxData { typedef struct _OsxData {
AudioUnit au; AudioUnit au;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -24,12 +24,9 @@ ...@@ -24,12 +24,9 @@
#include "../conf.h" #include "../conf.h"
#include "../log.h" #include "../log.h"
#include "../sig_handlers.h"
#include "../pcm_utils.h" #include "../pcm_utils.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
#include <time.h> #include <time.h>
#include <shout/shout.h> #include <shout/shout.h>
...@@ -37,7 +34,7 @@ ...@@ -37,7 +34,7 @@
#define CONN_ATTEMPT_INTERVAL 60 #define CONN_ATTEMPT_INTERVAL 60
static int shoutInitCount = 0; static int shoutInitCount;
/* lots of this code blatantly stolent from bossogg/bossao2 */ /* lots of this code blatantly stolent from bossogg/bossao2 */
...@@ -67,6 +64,7 @@ typedef struct _ShoutData { ...@@ -67,6 +64,7 @@ typedef struct _ShoutData {
int connAttempts; int connAttempts;
time_t lastAttempt; time_t lastAttempt;
int last_err;
/* just a pointer to audioOutput->outAudioFormat */ /* just a pointer to audioOutput->outAudioFormat */
AudioFormat *audioFormat; AudioFormat *audioFormat;
...@@ -85,6 +83,7 @@ static ShoutData *newShoutData(void) ...@@ -85,6 +83,7 @@ static ShoutData *newShoutData(void)
ret->connAttempts = 0; ret->connAttempts = 0;
ret->lastAttempt = 0; ret->lastAttempt = 0;
ret->audioFormat = NULL; ret->audioFormat = NULL;
ret->last_err = SHOUTERR_UNCONNECTED;
return ret; return ret;
} }
...@@ -101,10 +100,9 @@ static void freeShoutData(ShoutData * sd) ...@@ -101,10 +100,9 @@ static void freeShoutData(ShoutData * sd)
#define checkBlockParam(name) { \ #define checkBlockParam(name) { \
blockParam = getBlockParam(param, name); \ blockParam = getBlockParam(param, name); \
if(!blockParam) { \ if (!blockParam) { \
ERROR("no \"%s\" defined for shout device defined at line " \ FATAL("no \"%s\" defined for shout device defined at line " \
"%i\n", name, param->line); \ "%i\n", name, param->line); \
exit(EXIT_FAILURE); \
} \ } \
} }
...@@ -119,7 +117,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -119,7 +117,7 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
char *user; char *user;
char *name; char *name;
BlockParam *blockParam; BlockParam *blockParam;
unsigned int public; unsigned int public = 0;
sd = newShoutData(); sd = newShoutData();
...@@ -139,9 +137,8 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -139,9 +137,8 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
port = strtol(blockParam->value, &test, 10); port = strtol(blockParam->value, &test, 10);
if (*test != '\0' || port <= 0) { if (*test != '\0' || port <= 0) {
ERROR("shout port \"%s\" is not a positive integer, line %i\n", FATAL("shout port \"%s\" is not a positive integer, line %i\n",
blockParam->value, blockParam->line); blockParam->value, blockParam->line);
exit(EXIT_FAILURE);
} }
checkBlockParam("password"); checkBlockParam("password");
...@@ -152,17 +149,15 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -152,17 +149,15 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
blockParam = getBlockParam(param, "public"); blockParam = getBlockParam(param, "public");
if (blockParam) { if (blockParam) {
if (0 == strcmp(blockParam->value, "yes")) if (0 == strcmp(blockParam->value, "yes")) {
public = 1; public = 1;
else if (0 == strcmp(blockParam->value, "no")) } else if (0 == strcmp(blockParam->value, "no")) {
public = 0; public = 0;
else { } else {
ERROR("public \"%s\" is not \"yes\" or \"no\" at line " FATAL("public \"%s\" is not \"yes\" or \"no\" at line "
"%i\n", param->value, param->line); "%i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
} else }
public = 0;
blockParam = getBlockParam(param, "user"); blockParam = getBlockParam(param, "user");
if (blockParam) if (blockParam)
...@@ -178,35 +173,31 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -178,35 +173,31 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
sd->quality = strtod(blockParam->value, &test); sd->quality = strtod(blockParam->value, &test);
if (*test != '\0' || sd->quality < -1.0 || sd->quality > 10.0) { if (*test != '\0' || sd->quality < -1.0 || sd->quality > 10.0) {
ERROR("shout quality \"%s\" is not a number in the " FATAL("shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i\n", blockParam->value, "range -1 to 10, line %i\n", blockParam->value,
blockParam->line); blockParam->line);
exit(EXIT_FAILURE);
} }
blockParam = getBlockParam(param, "bitrate"); blockParam = getBlockParam(param, "bitrate");
if (blockParam) { if (blockParam) {
ERROR("quality (line %i) and bitrate (line %i) are " FATAL("quality (line %i) and bitrate (line %i) are "
"both defined for shout output\n", line, "both defined for shout output\n", line,
blockParam->line); blockParam->line);
exit(EXIT_FAILURE);
} }
} else { } else {
blockParam = getBlockParam(param, "bitrate"); blockParam = getBlockParam(param, "bitrate");
if (!blockParam) { if (!blockParam) {
ERROR("neither bitrate nor quality defined for shout " FATAL("neither bitrate nor quality defined for shout "
"output at line %i\n", param->line); "output at line %i\n", param->line);
exit(EXIT_FAILURE);
} }
sd->bitrate = strtol(blockParam->value, &test, 10); sd->bitrate = strtol(blockParam->value, &test, 10);
if (*test != '\0' || sd->bitrate <= 0) { if (*test != '\0' || sd->bitrate <= 0) {
ERROR("bitrate at line %i should be a positive integer " FATAL("bitrate at line %i should be a positive integer "
"\n", blockParam->line); "\n", blockParam->line);
exit(EXIT_FAILURE);
} }
} }
...@@ -220,30 +211,28 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param) ...@@ -220,30 +211,28 @@ static int myShout_initDriver(AudioOutput * audioOutput, ConfigParam * param)
shout_set_name(sd->shoutConn, name) != SHOUTERR_SUCCESS || shout_set_name(sd->shoutConn, name) != SHOUTERR_SUCCESS ||
shout_set_user(sd->shoutConn, user) != SHOUTERR_SUCCESS || shout_set_user(sd->shoutConn, user) != SHOUTERR_SUCCESS ||
shout_set_public(sd->shoutConn, public) != SHOUTERR_SUCCESS || shout_set_public(sd->shoutConn, public) != SHOUTERR_SUCCESS ||
shout_set_nonblocking(sd->shoutConn, 1) != SHOUTERR_SUCCESS ||
shout_set_format(sd->shoutConn, SHOUT_FORMAT_VORBIS) shout_set_format(sd->shoutConn, SHOUT_FORMAT_VORBIS)
!= SHOUTERR_SUCCESS || != SHOUTERR_SUCCESS ||
shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP) shout_set_protocol(sd->shoutConn, SHOUT_PROTOCOL_HTTP)
!= SHOUTERR_SUCCESS || != SHOUTERR_SUCCESS ||
shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) { shout_set_agent(sd->shoutConn, "MPD") != SHOUTERR_SUCCESS) {
ERROR("error configuring shout defined at line %i: %s\n", FATAL("error configuring shout defined at line %i: %s\n",
param->line, shout_get_error(sd->shoutConn)); param->line, shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE);
} }
/* optional paramters */ /* optional paramters */
blockParam = getBlockParam(param, "genre"); blockParam = getBlockParam(param, "genre");
if (blockParam && shout_set_genre(sd->shoutConn, blockParam->value)) { if (blockParam && shout_set_genre(sd->shoutConn, blockParam->value)) {
ERROR("error configuring shout defined at line %i: %s\n", FATAL("error configuring shout defined at line %i: %s\n",
param->line, shout_get_error(sd->shoutConn)); param->line, shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE);
} }
blockParam = getBlockParam(param, "description"); blockParam = getBlockParam(param, "description");
if (blockParam && shout_set_description(sd->shoutConn, if (blockParam && shout_set_description(sd->shoutConn,
blockParam->value)) { blockParam->value)) {
ERROR("error configuring shout defined at line %i: %s\n", FATAL("error configuring shout defined at line %i: %s\n",
param->line, shout_get_error(sd->shoutConn)); param->line, shout_get_error(sd->shoutConn));
exit(EXIT_FAILURE);
} }
{ {
...@@ -358,6 +347,7 @@ static void myShout_closeShoutConn(ShoutData * sd) ...@@ -358,6 +347,7 @@ static void myShout_closeShoutConn(ShoutData * sd)
} }
} }
sd->last_err = SHOUTERR_UNCONNECTED;
sd->opened = 0; sd->opened = 0;
} }
...@@ -460,9 +450,19 @@ static int myShout_openShoutConn(AudioOutput * audioOutput) ...@@ -460,9 +450,19 @@ static int myShout_openShoutConn(AudioOutput * audioOutput)
sd->connAttempts++; sd->connAttempts++;
sd->lastAttempt = t; if (sd->last_err == SHOUTERR_UNCONNECTED)
sd->last_err = shout_open(sd->shoutConn);
if (shout_open(sd->shoutConn) != SHOUTERR_SUCCESS) { switch (sd->last_err) {
case SHOUTERR_SUCCESS:
case SHOUTERR_CONNECTED:
break;
case SHOUTERR_BUSY:
sd->last_err = shout_get_connected(sd->shoutConn);
if (sd->last_err == SHOUTERR_CONNECTED)
break;
return -1;
default:
sd->lastAttempt = t;
ERROR("problem opening connection to shout server %s:%i " ERROR("problem opening connection to shout server %s:%i "
"(attempt %i): %s\n", "(attempt %i): %s\n",
shout_get_host(sd->shoutConn), shout_get_host(sd->shoutConn),
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -27,18 +27,18 @@ ...@@ -27,18 +27,18 @@
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
#include <iconv.h> #include <iconv.h>
iconv_t char_conv_iconv; static iconv_t char_conv_iconv;
#endif #endif
char *char_conv_to = NULL; static char *char_conv_to;
char *char_conv_from = NULL; static char *char_conv_from;
mpd_sint8 char_conv_same = 0; static mpd_sint8 char_conv_same;
mpd_sint8 char_conv_use_iconv = 0; static mpd_sint8 char_conv_use_iconv;
/* 1 is to use latin1ToUtf8 /* 1 is to use latin1ToUtf8
0 is not to use latin1/utf8 converter 0 is not to use latin1/utf8 converter
-1 is to use utf8ToLatin1*/ -1 is to use utf8ToLatin1*/
mpd_sint8 char_conv_latin1ToUtf8 = 0; static mpd_sint8 char_conv_latin1ToUtf8;
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -28,9 +28,9 @@ ...@@ -28,9 +28,9 @@
#include "permission.h" #include "permission.h"
#include "buffer2array.h" #include "buffer2array.h"
#include "log.h" #include "log.h"
#include "dbUtils.h"
#include "tag.h" #include "tag.h"
#include "utils.h" #include "utils.h"
#include "storedPlaylist.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
...@@ -92,6 +92,15 @@ ...@@ -92,6 +92,15 @@
#define COMMAND_DEVICES "outputs" #define COMMAND_DEVICES "outputs"
#define COMMAND_COMMANDS "commands" #define COMMAND_COMMANDS "commands"
#define COMMAND_NOTCOMMANDS "notcommands" #define COMMAND_NOTCOMMANDS "notcommands"
#define COMMAND_PLAYLISTCLEAR "playlistclear"
#define COMMAND_PLAYLISTADD "playlistadd"
#define COMMAND_PLAYLISTFIND "playlistfind"
#define COMMAND_PLAYLISTSEARCH "playlistsearch"
#define COMMAND_PLAYLISTMOVE "playlistmove"
#define COMMAND_PLAYLISTDELETE "playlistdelete"
#define COMMAND_TAGTYPES "tagtypes"
#define COMMAND_COUNT "count"
#define COMMAND_RENAME "rename"
#define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_STATE "state"
...@@ -132,8 +141,8 @@ struct _CommandEntry { ...@@ -132,8 +141,8 @@ struct _CommandEntry {
CommandListHandlerFunction listHandler; CommandListHandlerFunction listHandler;
}; };
static char *current_command = NULL; static char *current_command;
static int command_listNum = 0; static int command_listNum;
static CommandEntry *getCommandEntryFromString(char *string, int *permission); static CommandEntry *getCommandEntryFromString(char *string, int *permission);
...@@ -174,6 +183,12 @@ static int handleUrlHandlers(int fd, int *permission, int argc, char *argv[]) ...@@ -174,6 +183,12 @@ static int handleUrlHandlers(int fd, int *permission, int argc, char *argv[])
return printRemoteUrlHandlers(fd); return printRemoteUrlHandlers(fd);
} }
static int handleTagTypes(int fd, int *permission, int argc, char *argv[])
{
printTagTypes(fd);
return 0;
}
static int handlePlay(int fd, int *permission, int argc, char *argv[]) static int handlePlay(int fd, int *permission, int argc, char *argv[])
{ {
int song = -1; int song = -1;
...@@ -388,17 +403,18 @@ static int handleListPlaylistInfo(int fd, int *permission, ...@@ -388,17 +403,18 @@ static int handleListPlaylistInfo(int fd, int *permission,
static int handleLsInfo(int fd, int *permission, int argc, char *argv[]) static int handleLsInfo(int fd, int *permission, int argc, char *argv[])
{ {
if (argc == 1) { char *path = "";
if (printDirectoryInfo(fd, NULL) < 0)
return -1; if (argc == 2)
else path = argv[1];
return lsPlaylists(fd, "");
} else { if (printDirectoryInfo(fd, path) < 0)
if (printDirectoryInfo(fd, argv[1]) < 0) return -1;
return -1;
else if (isRootDirectory(path))
return lsPlaylists(fd, argv[1]); return lsPlaylists(fd, path);
}
return 0;
} }
static int handleRm(int fd, int *permission, int argc, char *argv[]) static int handleRm(int fd, int *permission, int argc, char *argv[])
...@@ -406,6 +422,11 @@ static int handleRm(int fd, int *permission, int argc, char *argv[]) ...@@ -406,6 +422,11 @@ static int handleRm(int fd, int *permission, int argc, char *argv[])
return deletePlaylist(fd, argv[1]); return deletePlaylist(fd, argv[1]);
} }
static int handleRename(int fd, int *permission, int argc, char *argv[])
{
return renameStoredPlaylist(fd, argv[1], argv[2]);
}
static int handlePlaylistChanges(int fd, int *permission, static int handlePlaylistChanges(int fd, int *permission,
int argc, char *argv[]) int argc, char *argv[])
{ {
...@@ -508,13 +529,109 @@ static int handleSearch(int fd, int *permission, int argc, char *argv[]) ...@@ -508,13 +529,109 @@ static int handleSearch(int fd, int *permission, int argc, char *argv[])
return ret; return ret;
} }
static int handleCount(int fd, int *permission, int argc, char *argv[])
{
int ret;
LocateTagItem *items;
int numItems = newLocateTagItemArrayFromArgArray(argv + 1,
argc - 1,
&items);
if (numItems <= 0) {
commandError(fd, ACK_ERROR_ARG, "incorrect arguments");
return -1;
}
ret = searchStatsForSongsIn(fd, NULL, numItems, items);
freeLocateTagItemArray(numItems, items);
return ret;
}
static int handlePlaylistFind(int fd, int *permission, int argc, char *argv[])
{
LocateTagItem *items;
int numItems = newLocateTagItemArrayFromArgArray(argv + 1,
argc - 1,
&items);
if (numItems <= 0) {
commandError(fd, ACK_ERROR_ARG, "incorrect arguments");
return -1;
}
findSongsInPlaylist(fd, numItems, items);
freeLocateTagItemArray(numItems, items);
return 0;
}
static int handlePlaylistSearch(int fd, int *permission, int argc, char *argv[])
{
LocateTagItem *items;
int numItems = newLocateTagItemArrayFromArgArray(argv + 1,
argc - 1,
&items);
if (numItems <= 0) {
commandError(fd, ACK_ERROR_ARG, "incorrect arguments");
return -1;
}
searchForSongsInPlaylist(fd, numItems, items);
freeLocateTagItemArray(numItems, items);
return 0;
}
static int handlePlaylistDelete(int fd, int *permission, int argc, char *argv[]) {
char *playlist = argv[1];
int from;
char *test;
from = strtol(argv[2], &test, 10);
if (*test != '\0') {
commandError(fd, ACK_ERROR_ARG,
"\"%s\" is not a integer", argv[2]);
return -1;
}
return removeOneSongFromStoredPlaylistByPath(fd, playlist, from);
}
static int handlePlaylistMove(int fd, int *permission, int argc, char *argv[])
{
char *playlist = argv[1];
int from, to;
char *test;
from = strtol(argv[2], &test, 10);
if (*test != '\0') {
commandError(fd, ACK_ERROR_ARG,
"\"%s\" is not a integer", argv[2]);
return -1;
}
to = strtol(argv[3], &test, 10);
if (*test != '\0') {
commandError(fd, ACK_ERROR_ARG,
"\"%s\" is not a integer", argv[3]);
return -1;
}
return moveSongInStoredPlaylistByPath(fd, playlist, from, to);
}
static int listHandleUpdate(int fd, static int listHandleUpdate(int fd,
int *permission, int *permission,
int argc, int argc,
char *argv[], char *argv[],
struct strnode *cmdnode, CommandEntry * cmd) struct strnode *cmdnode, CommandEntry * cmd)
{ {
static List *pathList = NULL; static List *pathList;
CommandEntry *nextCmd = NULL; CommandEntry *nextCmd = NULL;
struct strnode *next = cmdnode->next; struct strnode *next = cmdnode->next;
...@@ -646,6 +763,12 @@ static int handleList(int fd, int *permission, int argc, char *argv[]) ...@@ -646,6 +763,12 @@ static int handleList(int fd, int *permission, int argc, char *argv[])
return -1; return -1;
} }
if (tagType == LOCATE_TAG_ANY_TYPE) {
commandError(fd, ACK_ERROR_ARG,
"\"any\" is not a valid return tag type");
return -1;
}
/* for compatibility with < 0.12.0 */ /* for compatibility with < 0.12.0 */
if (argc == 3) { if (argc == 3) {
if (tagType != TAG_ITEM_ALBUM) { if (tagType != TAG_ITEM_ALBUM) {
...@@ -917,6 +1040,22 @@ static int handleNotcommands(int fd, int *permission, int argc, char *argv[]) ...@@ -917,6 +1040,22 @@ static int handleNotcommands(int fd, int *permission, int argc, char *argv[])
return 0; return 0;
} }
static int handlePlaylistClear(int fd, int *permission, int argc, char *argv[])
{
return clearStoredPlaylist(fd, argv[1]);
}
static int handlePlaylistAdd(int fd, int *permission, int argc, char *argv[])
{
char *playlist = argv[1];
char *path = argv[2];
if (isRemoteUrl(path))
return addToStoredPlaylist(fd, path, playlist);
return addAllInToStoredPlaylist(fd, path, playlist);
}
void initCommands(void) void initCommands(void)
{ {
commandList = makeList(free, 1); commandList = makeList(free, 1);
...@@ -976,6 +1115,15 @@ void initCommands(void) ...@@ -976,6 +1115,15 @@ void initCommands(void)
addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL); addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL);
addCommand(COMMAND_COMMANDS, PERMISSION_NONE, 0, 0, handleCommands, NULL); addCommand(COMMAND_COMMANDS, PERMISSION_NONE, 0, 0, handleCommands, NULL);
addCommand(COMMAND_NOTCOMMANDS, PERMISSION_NONE, 0, 0, handleNotcommands, NULL); addCommand(COMMAND_NOTCOMMANDS, PERMISSION_NONE, 0, 0, handleNotcommands, NULL);
addCommand(COMMAND_PLAYLISTCLEAR, PERMISSION_CONTROL, 1, 1, handlePlaylistClear, NULL);
addCommand(COMMAND_PLAYLISTADD, PERMISSION_CONTROL, 2, 2, handlePlaylistAdd, NULL);
addCommand(COMMAND_PLAYLISTFIND, PERMISSION_READ, 2, -1, handlePlaylistFind, NULL);
addCommand(COMMAND_PLAYLISTSEARCH, PERMISSION_READ, 2, -1, handlePlaylistSearch, NULL);
addCommand(COMMAND_PLAYLISTMOVE, PERMISSION_CONTROL, 3, 3, handlePlaylistMove, NULL);
addCommand(COMMAND_PLAYLISTDELETE, PERMISSION_CONTROL, 2, 2, handlePlaylistDelete, NULL);
addCommand(COMMAND_TAGTYPES, PERMISSION_READ, 0, 0, handleTagTypes, NULL);
addCommand(COMMAND_COUNT, PERMISSION_READ, 2, -1, handleCount, NULL);
addCommand(COMMAND_RENAME, PERMISSION_CONTROL, 2, 2, handleRename, NULL);
sortList(commandList); sortList(commandList);
} }
...@@ -1134,15 +1282,18 @@ mpd_fprintf_ void commandError(int fd, int error, const char *fmt, ...) ...@@ -1134,15 +1282,18 @@ mpd_fprintf_ void commandError(int fd, int error, const char *fmt, ...)
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
if (current_command) { if (current_command && fd != STDERR_FILENO) {
fdprintf(fd, "ACK [%i@%i] {%s} ", fdprintf(fd, "ACK [%i@%i] {%s} ",
(int)error, command_listNum, current_command); (int)error, command_listNum, current_command);
vfdprintf(fd, fmt, args);
fdprintf(fd, "\n");
current_command = NULL; current_command = NULL;
} else } else {
fdprintf(STDERR_FILENO, "ACK [%i@%i] ", fdprintf(STDERR_FILENO, "ACK [%i@%i] ",
(int)error, command_listNum); (int)error, command_listNum);
vfdprintf(STDERR_FILENO, fmt, args);
fdprintf(STDERR_FILENO, "\n");
}
vfdprintf(fd, fmt, args);
va_end(args); va_end(args);
fdprintf(fd, "\n");
} }
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Compressor logic by * Compressor logic by
...@@ -39,7 +39,7 @@ static int screen; ...@@ -39,7 +39,7 @@ static int screen;
static GC blackGC, whiteGC, blueGC, yellowGC, dkyellowGC, redGC; static GC blackGC, whiteGC, blueGC, yellowGC, dkyellowGC, redGC;
#endif #endif
static int *peaks = NULL; static int *peaks;
static int gainCurrent, gainTarget; static int gainCurrent, gainTarget;
static struct { static struct {
...@@ -52,13 +52,13 @@ static struct { ...@@ -52,13 +52,13 @@ static struct {
} prefs; } prefs;
#ifdef USE_X #ifdef USE_X
static int mon_init = 0; static int mon_init;
#endif #endif
void CompressCfg(int show_mon, int anticlip, int target, int gainmax, void CompressCfg(int show_mon, int anticlip, int target, int gainmax,
int gainsmooth, int buckets) int gainsmooth, int buckets)
{ {
static int lastsize = 0; static int lastsize;
prefs.show_mon = show_mon; prefs.show_mon = show_mon;
prefs.anticlip = anticlip; prefs.anticlip = anticlip;
...@@ -179,9 +179,9 @@ void CompressDo(void *data, unsigned int length) ...@@ -179,9 +179,9 @@ void CompressDo(void *data, unsigned int length)
int gr, gf, gn; int gr, gf, gn;
static int pn = -1; static int pn = -1;
#ifdef STATS #ifdef STATS
static int clip = 0; static int clip;
#endif #endif
static int clipped = 0; static int clipped;
if (!peaks) if (!peaks)
return; return;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* interface to audio compression * interface to audio compression
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -48,7 +48,7 @@ typedef struct _configEntry { ...@@ -48,7 +48,7 @@ typedef struct _configEntry {
List *configParamList; List *configParamList;
} ConfigEntry; } ConfigEntry;
static List *configEntriesList = NULL; static List *configEntriesList;
static ConfigParam *newConfigParam(char *value, int line) static ConfigParam *newConfigParam(char *value, int line)
{ {
...@@ -115,10 +115,8 @@ static void registerConfigParam(char *name, int repeatable, int block) ...@@ -115,10 +115,8 @@ static void registerConfigParam(char *name, int repeatable, int block)
{ {
ConfigEntry *entry; ConfigEntry *entry;
if (findInList(configEntriesList, name, NULL)) { if (findInList(configEntriesList, name, NULL))
ERROR("config parameter \"%s\" already registered\n", name); FATAL("config parameter \"%s\" already registered\n", name);
exit(EXIT_FAILURE);
}
entry = newConfigEntry(repeatable, block); entry = newConfigEntry(repeatable, block);
...@@ -146,6 +144,7 @@ void initConf(void) ...@@ -146,6 +144,7 @@ void initConf(void)
registerConfigParam(CONF_BIND_TO_ADDRESS, 1, 0); registerConfigParam(CONF_BIND_TO_ADDRESS, 1, 0);
registerConfigParam(CONF_PORT, 0, 0); registerConfigParam(CONF_PORT, 0, 0);
registerConfigParam(CONF_LOG_LEVEL, 0, 0); registerConfigParam(CONF_LOG_LEVEL, 0, 0);
registerConfigParam(CONF_ZEROCONF_NAME, 0, 0);
registerConfigParam(CONF_PASSWORD, 1, 0); registerConfigParam(CONF_PASSWORD, 1, 0);
registerConfigParam(CONF_DEFAULT_PERMS, 0, 0); registerConfigParam(CONF_DEFAULT_PERMS, 0, 0);
registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1); registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1);
...@@ -156,6 +155,7 @@ void initConf(void) ...@@ -156,6 +155,7 @@ void initConf(void)
registerConfigParam(CONF_REPLAYGAIN, 0, 0); registerConfigParam(CONF_REPLAYGAIN, 0, 0);
registerConfigParam(CONF_REPLAYGAIN_PREAMP, 0, 0); registerConfigParam(CONF_REPLAYGAIN_PREAMP, 0, 0);
registerConfigParam(CONF_VOLUME_NORMALIZATION, 0, 0); registerConfigParam(CONF_VOLUME_NORMALIZATION, 0, 0);
registerConfigParam(CONF_SAMPLERATE_CONVERTER, 0, 0);
registerConfigParam(CONF_AUDIO_BUFFER_SIZE, 0, 0); registerConfigParam(CONF_AUDIO_BUFFER_SIZE, 0, 0);
registerConfigParam(CONF_BUFFER_BEFORE_PLAY, 0, 0); registerConfigParam(CONF_BUFFER_BEFORE_PLAY, 0, 0);
registerConfigParam(CONF_HTTP_BUFFER_SIZE, 0, 0); registerConfigParam(CONF_HTTP_BUFFER_SIZE, 0, 0);
...@@ -173,6 +173,7 @@ void initConf(void) ...@@ -173,6 +173,7 @@ void initConf(void)
registerConfigParam(CONF_ID3V1_ENCODING, 0, 0); registerConfigParam(CONF_ID3V1_ENCODING, 0, 0);
registerConfigParam(CONF_METADATA_TO_USE, 0, 0); registerConfigParam(CONF_METADATA_TO_USE, 0, 0);
registerConfigParam(CONF_SAVE_ABSOLUTE_PATHS, 0, 0); registerConfigParam(CONF_SAVE_ABSOLUTE_PATHS, 0, 0);
registerConfigParam(CONF_GAPLESS_MP3_PLAYBACK, 0, 0);
} }
static void addBlockParam(ConfigParam * param, char *name, char *value, static void addBlockParam(ConfigParam * param, char *name, char *value,
...@@ -222,19 +223,17 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string) ...@@ -222,19 +223,17 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
} }
if (2 != argsMinusComment) { if (2 != argsMinusComment) {
ERROR("improperly formatted config file at line %i:" FATAL("improperly formatted config file at line %i:"
" %s\n", *count, string); " %s\n", *count, string);
exit(EXIT_FAILURE);
} }
if (0 == strcmp(array[0], CONF_BLOCK_BEGIN) || if (0 == strcmp(array[0], CONF_BLOCK_BEGIN) ||
0 == strcmp(array[1], CONF_BLOCK_BEGIN) || 0 == strcmp(array[1], CONF_BLOCK_BEGIN) ||
0 == strcmp(array[0], CONF_BLOCK_END) || 0 == strcmp(array[0], CONF_BLOCK_END) ||
0 == strcmp(array[1], CONF_BLOCK_END)) { 0 == strcmp(array[1], CONF_BLOCK_END)) {
ERROR("improperly formatted config file at line %i:" FATAL("improperly formatted config file at line %i: %s\n"
" %s\n", *count, string); "in block beginning at line %i\n",
ERROR("in block beginning at line %i\n", ret->line); *count, string, ret->line);;
exit(EXIT_FAILURE);
} }
addBlockParam(ret, array[0], array[1], *count); addBlockParam(ret, array[0], array[1], *count);
...@@ -256,9 +255,8 @@ void readConf(char *file) ...@@ -256,9 +255,8 @@ void readConf(char *file)
ConfigParam *param; ConfigParam *param;
if (!(fp = fopen(file, "r"))) { if (!(fp = fopen(file, "r"))) {
ERROR("problems opening file %s for reading: %s\n", file, FATAL("problems opening file %s for reading: %s\n", file,
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE);
} }
while (myFgets(string, MAX_STRING_SIZE, fp)) { while (myFgets(string, MAX_STRING_SIZE, fp)) {
...@@ -279,15 +277,13 @@ void readConf(char *file) ...@@ -279,15 +277,13 @@ void readConf(char *file)
} }
if (2 != argsMinusComment) { if (2 != argsMinusComment) {
ERROR("improperly formatted config file at line %i:" FATAL("improperly formatted config file at line %i:"
" %s\n", count, string); " %s\n", count, string);
exit(EXIT_FAILURE);
} }
if (!findInList(configEntriesList, array[0], &voidPtr)) { if (!findInList(configEntriesList, array[0], &voidPtr)) {
ERROR("unrecognized parameter in config file at line " FATAL("unrecognized parameter in config file at line "
"%i: %s\n", count, string); "%i: %s\n", count, string);
exit(EXIT_FAILURE);
} }
entry = (ConfigEntry *) voidPtr; entry = (ConfigEntry *) voidPtr;
...@@ -295,18 +291,15 @@ void readConf(char *file) ...@@ -295,18 +291,15 @@ void readConf(char *file)
if (!(entry->mask & CONF_REPEATABLE_MASK) && if (!(entry->mask & CONF_REPEATABLE_MASK) &&
entry->configParamList->numberOfNodes) { entry->configParamList->numberOfNodes) {
param = entry->configParamList->firstNode->data; param = entry->configParamList->firstNode->data;
ERROR FATAL("config parameter \"%s\" is first defined on line "
("config parameter \"%s\" is first defined on line "
"%i and redefined on line %i\n", array[0], "%i and redefined on line %i\n", array[0],
param->line, count); param->line, count);
exit(EXIT_FAILURE);
} }
if (entry->mask & CONF_BLOCK_MASK) { if (entry->mask & CONF_BLOCK_MASK) {
if (0 != strcmp(array[1], CONF_BLOCK_BEGIN)) { if (0 != strcmp(array[1], CONF_BLOCK_BEGIN)) {
ERROR("improperly formatted config file at " FATAL("improperly formatted config file at "
"line %i: %s\n", count, string); "line %i: %s\n", count, string);
exit(EXIT_FAILURE);
} }
param = readConfigBlock(fp, &count, string); param = readConfigBlock(fp, &count, string);
} else } else
...@@ -397,10 +390,8 @@ ConfigParam *parseConfigFilePath(char *name, int force) ...@@ -397,10 +390,8 @@ ConfigParam *parseConfigFilePath(char *name, int force)
ConfigParam *param = getConfigParam(name); ConfigParam *param = getConfigParam(name);
char *path; char *path;
if (!param && force) { if (!param && force)
ERROR("config parameter \"%s\" not found\n", name); FATAL("config parameter \"%s\" not found\n", name);
exit(EXIT_FAILURE);
}
if (!param) if (!param)
return NULL; return NULL;
...@@ -408,9 +399,8 @@ ConfigParam *parseConfigFilePath(char *name, int force) ...@@ -408,9 +399,8 @@ ConfigParam *parseConfigFilePath(char *name, int force)
path = param->value; path = param->value;
if (path[0] != '/' && path[0] != '~') { if (path[0] != '/' && path[0] != '~') {
ERROR("\"%s\" is not an absolute path at line %i\n", FATAL("\"%s\" is not an absolute path at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
/* Parse ~ in path */ /* Parse ~ in path */
else if (path[0] == '~') { else if (path[0] == '~') {
...@@ -423,17 +413,15 @@ ConfigParam *parseConfigFilePath(char *name, int force) ...@@ -423,17 +413,15 @@ ConfigParam *parseConfigFilePath(char *name, int force)
if (userParam) { if (userParam) {
pwd = getpwnam(userParam->value); pwd = getpwnam(userParam->value);
if (!pwd) { if (!pwd) {
ERROR("no such user %s at line %i\n", FATAL("no such user %s at line %i\n",
userParam->value, userParam->value,
userParam->line); userParam->line);
exit(EXIT_FAILURE);
} }
} else { } else {
uid_t uid = geteuid(); uid_t uid = geteuid();
if ((pwd = getpwuid(uid)) == NULL) { if ((pwd = getpwuid(uid)) == NULL) {
ERROR("problems getting passwd entry " FATAL("problems getting passwd entry "
"for current user\n"); "for current user\n");
exit(EXIT_FAILURE);
} }
} }
} else { } else {
...@@ -445,9 +433,8 @@ ConfigParam *parseConfigFilePath(char *name, int force) ...@@ -445,9 +433,8 @@ ConfigParam *parseConfigFilePath(char *name, int force)
*ch = '\0'; *ch = '\0';
pos += ch - path - 1; pos += ch - path - 1;
if ((pwd = getpwnam(path + 1)) == NULL) { if ((pwd = getpwnam(path + 1)) == NULL) {
ERROR("user \"%s\" not found at line %i\n", FATAL("user \"%s\" not found at line %i\n",
path + 1, param->line); path + 1, param->line);
exit(EXIT_FAILURE);
} }
if (foundSlash) if (foundSlash)
*ch = '/'; *ch = '/';
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define CONF_BIND_TO_ADDRESS "bind_to_address" #define CONF_BIND_TO_ADDRESS "bind_to_address"
#define CONF_PORT "port" #define CONF_PORT "port"
#define CONF_LOG_LEVEL "log_level" #define CONF_LOG_LEVEL "log_level"
#define CONF_ZEROCONF_NAME "zeroconf_name"
#define CONF_PASSWORD "password" #define CONF_PASSWORD "password"
#define CONF_DEFAULT_PERMS "default_permissions" #define CONF_DEFAULT_PERMS "default_permissions"
#define CONF_AUDIO_OUTPUT "audio_output" #define CONF_AUDIO_OUTPUT "audio_output"
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#define CONF_REPLAYGAIN "replaygain" #define CONF_REPLAYGAIN "replaygain"
#define CONF_REPLAYGAIN_PREAMP "replaygain_preamp" #define CONF_REPLAYGAIN_PREAMP "replaygain_preamp"
#define CONF_VOLUME_NORMALIZATION "volume_normalization" #define CONF_VOLUME_NORMALIZATION "volume_normalization"
#define CONF_SAMPLERATE_CONVERTER "samplerate_converter"
#define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size" #define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size"
#define CONF_BUFFER_BEFORE_PLAY "buffer_before_play" #define CONF_BUFFER_BEFORE_PLAY "buffer_before_play"
#define CONF_HTTP_BUFFER_SIZE "http_buffer_size" #define CONF_HTTP_BUFFER_SIZE "http_buffer_size"
...@@ -59,6 +61,7 @@ ...@@ -59,6 +61,7 @@
#define CONF_ID3V1_ENCODING "id3v1_encoding" #define CONF_ID3V1_ENCODING "id3v1_encoding"
#define CONF_METADATA_TO_USE "metadata_to_use" #define CONF_METADATA_TO_USE "metadata_to_use"
#define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists" #define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists"
#define CONF_GAPLESS_MP3_PLAYBACK "gapless_mp3_playback"
typedef struct _BlockParam { typedef struct _BlockParam {
char *name; char *name;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -22,14 +22,11 @@ ...@@ -22,14 +22,11 @@
#include "myfprintf.h" #include "myfprintf.h"
#include "utils.h" #include "utils.h"
#include "playlist.h" #include "playlist.h"
#include "song.h"
#include "tag.h" #include "tag.h"
#include "tagTracker.h" #include "tagTracker.h"
#include "log.h" #include "log.h"
#include "storedPlaylist.h"
#define LOCATE_TAG_FILE_TYPE TAG_NUM_OF_ITEM_TYPES+10
#define LOCATE_TAG_FILE_KEY "filename"
#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20
#define LOCATE_TAG_ANY_KEY "any"
typedef struct _ListCommandItem { typedef struct _ListCommandItem {
mpd_sint8 tagType; mpd_sint8 tagType;
...@@ -42,97 +39,11 @@ typedef struct _LocateTagItemArray { ...@@ -42,97 +39,11 @@ typedef struct _LocateTagItemArray {
LocateTagItem *items; LocateTagItem *items;
} LocateTagItemArray; } LocateTagItemArray;
int getLocateTagItemType(char *str) typedef struct _SearchStats {
{ LocateTagItemArray locateArray;
int i; int numberOfSongs;
unsigned long playTime;
if (0 == strcasecmp(str, LOCATE_TAG_FILE_KEY)) { } SearchStats;
return LOCATE_TAG_FILE_TYPE;
}
if (0 == strcasecmp(str, LOCATE_TAG_ANY_KEY)) {
return LOCATE_TAG_ANY_TYPE;
}
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if (0 == strcasecmp(str, mpdTagItemKeys[i]))
return i;
}
return -1;
}
static int initLocateTagItem(LocateTagItem * item, char *typeStr, char *needle)
{
item->tagType = getLocateTagItemType(typeStr);
if (item->tagType < 0)
return -1;
item->needle = xstrdup(needle);
return 0;
}
LocateTagItem *newLocateTagItem(char *typeStr, char *needle)
{
LocateTagItem *ret = xmalloc(sizeof(LocateTagItem));
if (initLocateTagItem(ret, typeStr, needle) < 0) {
free(ret);
ret = NULL;
}
return ret;
}
void freeLocateTagItemArray(int count, LocateTagItem * array)
{
int i;
for (i = 0; i < count; i++)
free(array[i].needle);
free(array);
}
int newLocateTagItemArrayFromArgArray(char *argArray[],
int numArgs, LocateTagItem ** arrayRet)
{
int i, j;
LocateTagItem *item;
if (numArgs == 0)
return 0;
if (numArgs % 2 != 0)
return -1;
*arrayRet = xmalloc(sizeof(LocateTagItem) * numArgs / 2);
for (i = 0, item = *arrayRet; i < numArgs / 2; i++, item++) {
if (initLocateTagItem
(item, argArray[i * 2], argArray[i * 2 + 1]) < 0)
goto fail;
}
return numArgs / 2;
fail:
for (j = 0; j < i; j++) {
free((*arrayRet)[j].needle);
}
free(*arrayRet);
*arrayRet = NULL;
return -1;
}
void freeLocateTagItem(LocateTagItem * item)
{
free(item->needle);
free(item);
}
static int countSongsInDirectory(int fd, Directory * directory, void *data) static int countSongsInDirectory(int fd, Directory * directory, void *data)
{ {
...@@ -158,53 +69,12 @@ static int printSongInDirectory(int fd, Song * song, void *data) ...@@ -158,53 +69,12 @@ static int printSongInDirectory(int fd, Song * song, void *data)
return 0; return 0;
} }
static int strstrSearchTag(Song * song, int type, char *str)
{
int i;
char *dup;
int ret = 0;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
dup = strDupToUpper(getSongUrl(song));
if (strstr(dup, str))
ret = 1;
free(dup);
if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) {
return ret;
}
}
if (!song->tag)
return 0;
for (i = 0; i < song->tag->numOfItems && !ret; i++) {
if (type != LOCATE_TAG_ANY_TYPE &&
song->tag->items[i].type != type) {
continue;
}
dup = strDupToUpper(song->tag->items[i].value);
if (strstr(dup, str))
ret = 1;
free(dup);
}
return ret;
}
static int searchInDirectory(int fd, Song * song, void *data) static int searchInDirectory(int fd, Song * song, void *data)
{ {
LocateTagItemArray *array = data; LocateTagItemArray *array = data;
int i;
for (i = 0; i < array->numItems; i++) { if (strstrSearchTags(song, array->numItems, array->items))
if (!strstrSearchTag(song, array->items[i].tagType, printSongInfo(fd, song);
array->items[i].needle)) {
return 0;
}
}
printSongInfo(fd, song);
return 0; return 0;
} }
...@@ -237,54 +107,62 @@ int searchForSongsIn(int fd, char *name, int numItems, LocateTagItem * items) ...@@ -237,54 +107,62 @@ int searchForSongsIn(int fd, char *name, int numItems, LocateTagItem * items)
return ret; return ret;
} }
static int tagItemFoundAndMatches(Song * song, int type, char *str) static int findInDirectory(int fd, Song * song, void *data)
{ {
int i; LocateTagItemArray *array = data;
if (type == LOCATE_TAG_FILE_TYPE) { if (tagItemsFoundAndMatches(song, array->numItems, array->items))
if (0 == strcmp(str, getSongUrl(song))) printSongInfo(fd, song);
return 1;
}
if (!song->tag) return 0;
return 0; }
for (i = 0; i < song->tag->numOfItems; i++) { int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items)
if (song->tag->items[i].type != type) {
continue; LocateTagItemArray array;
if (0 == strcmp(str, song->tag->items[i].value)) array.numItems = numItems;
return 1; array.items = items;
}
return 0; return traverseAllIn(fd, name, findInDirectory, NULL, (void *)&array);
} }
static int findInDirectory(int fd, Song * song, void *data) static void printSearchStats(int fd, SearchStats *stats)
{ {
LocateTagItemArray *array = data; fdprintf(fd, "songs: %i\n", stats->numberOfSongs);
int i; fdprintf(fd, "playtime: %li\n", stats->playTime);
}
for (i = 0; i < array->numItems; i++) { static int searchStatsInDirectory(int fd, Song * song, void *data)
if (!tagItemFoundAndMatches(song, array->items[i].tagType, {
array->items[i].needle)) { SearchStats *stats = data;
return 0;
}
}
printSongInfo(fd, song); if (tagItemsFoundAndMatches(song, stats->locateArray.numItems,
stats->locateArray.items)) {
stats->numberOfSongs++;
if (song->tag->time > 0)
stats->playTime += song->tag->time;
}
return 0; return 0;
} }
int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items) int searchStatsForSongsIn(int fd, char *name, int numItems,
LocateTagItem * items)
{ {
LocateTagItemArray array; SearchStats stats;
int ret;
array.numItems = numItems; stats.locateArray.numItems = numItems;
array.items = items; stats.locateArray.items = items;
stats.numberOfSongs = 0;
stats.playTime = 0;
return traverseAllIn(fd, name, findInDirectory, NULL, (void *)&array); ret = traverseAllIn(fd, name, searchStatsInDirectory, NULL, &stats);
if (ret == 0)
printSearchStats(fd, &stats);
return ret;
} }
int printAllIn(int fd, char *name) int printAllIn(int fd, char *name)
...@@ -298,11 +176,24 @@ static int directoryAddSongToPlaylist(int fd, Song * song, void *data) ...@@ -298,11 +176,24 @@ static int directoryAddSongToPlaylist(int fd, Song * song, void *data)
return addSongToPlaylist(fd, song, 0); return addSongToPlaylist(fd, song, 0);
} }
static int directoryAddSongToStoredPlaylist(int fd, Song *song, void *data)
{
if (appendSongToStoredPlaylistByPath(fd, (char *)data, song) != 0)
return -1;
return 0;
}
int addAllIn(int fd, char *name) int addAllIn(int fd, char *name)
{ {
return traverseAllIn(fd, name, directoryAddSongToPlaylist, NULL, NULL); return traverseAllIn(fd, name, directoryAddSongToPlaylist, NULL, NULL);
} }
int addAllInToStoredPlaylist(int fd, char *name, char *utf8file)
{
return traverseAllIn(fd, name, directoryAddSongToStoredPlaylist, NULL,
(void *)utf8file);
}
static int directoryPrintSongInfo(int fd, Song * song, void *data) static int directoryPrintSongInfo(int fd, Song * song, void *data)
{ {
return printSongInfo(fd, song); return printSongInfo(fd, song);
...@@ -384,17 +275,12 @@ static void visitTag(int fd, Song * song, int tagType) ...@@ -384,17 +275,12 @@ static void visitTag(int fd, Song * song, int tagType)
static int listUniqueTagsInDirectory(int fd, Song * song, void *data) static int listUniqueTagsInDirectory(int fd, Song * song, void *data)
{ {
ListCommandItem *item = data; ListCommandItem *item = data;
int i;
for (i = 0; i < item->numConditionals; i++) { if (tagItemsFoundAndMatches(song, item->numConditionals,
if (!tagItemFoundAndMatches(song, item->conditionals[i].tagType, item->conditionals)) {
item->conditionals[i].needle)) { visitTag(fd, song, item->tagType);
return 0;
}
} }
visitTag(fd, song, item->tagType);
return 0; return 0;
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -21,39 +21,24 @@ ...@@ -21,39 +21,24 @@
#include <stdio.h> #include <stdio.h>
#include "tag.h" #include "locate.h"
/* struct used for search, find, list queries */
typedef struct _LocateTagItem {
mpd_sint8 tagType;
/* what we are looking for */
char *needle;
} LocateTagItem;
int getLocateTagItemType(char *str);
/* returns NULL if not a known type */
LocateTagItem *newLocateTagItem(char *typeString, char *needle);
/* return number of items or -1 on error */
int newLocateTagItemArrayFromArgArray(char *argArray[], int numArgs,
LocateTagItem ** arrayRet);
void freeLocateTagItemArray(int count, LocateTagItem * array);
void freeLocateTagItem(LocateTagItem * item);
int printAllIn(int fd, char *name); int printAllIn(int fd, char *name);
int addAllIn(int fd, char *name); int addAllIn(int fd, char *name);
int addAllInToStoredPlaylist(int fd, char *name, char *utf8file);
int printInfoForAllIn(int fd, char *name); int printInfoForAllIn(int fd, char *name);
int searchForSongsIn(int fd, char *name, int numItems, int searchForSongsIn(int fd, char *name, int numItems,
LocateTagItem * items); LocateTagItem * items);
int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items); int findSongsIn(int fd, char *name, int numItems, LocateTagItem * items);
int searchStatsForSongsIn(int fd, char *name, int numItems,
LocateTagItem * items);
int countSongsIn(int fd, char *name); int countSongsIn(int fd, char *name);
unsigned long sumSongTimesIn(int fd, char *name); unsigned long sumSongTimesIn(int fd, char *name);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
static int decode_pid = 0; static int decode_pid;
void decodeSigHandler(int sig, siginfo_t * si, void *v) void decodeSigHandler(int sig, siginfo_t * si, void *v)
{ {
...@@ -76,7 +76,6 @@ static void stopDecode(DecoderControl * dc) ...@@ -76,7 +76,6 @@ static void stopDecode(DecoderControl * dc)
static void quitDecode(PlayerControl * pc, DecoderControl * dc) static void quitDecode(PlayerControl * pc, DecoderControl * dc)
{ {
stopDecode(dc); stopDecode(dc);
pc->metadataState = PLAYER_METADATA_STATE_READ;
pc->state = PLAYER_STATE_STOP; pc->state = PLAYER_STATE_STOP;
dc->seek = 0; dc->seek = 0;
pc->play = 0; pc->play = 0;
...@@ -221,20 +220,20 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc, ...@@ -221,20 +220,20 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc,
} \ } \
if(pc->pause) { \ if(pc->pause) { \
pause = !pause; \ pause = !pause; \
if(pause) pc->state = PLAYER_STATE_PAUSE; \ if (pause) pc->state = PLAYER_STATE_PAUSE; \
else { \ else { \
if(openAudioDevice(NULL)<0) { \ if (openAudioDevice(NULL) >= 0) pc->state = PLAYER_STATE_PLAY; \
else { \
pathcpy_trunc(pc->erroredUrl, pc->utf8url); \ pathcpy_trunc(pc->erroredUrl, pc->utf8url); \
pc->error = PLAYER_ERROR_AUDIO; \ pc->error = PLAYER_ERROR_AUDIO; \
ERROR("problems opening audio device while playing \"%s\"\n", pc->utf8url); \ ERROR("problems opening audio device while playing \"%s\"\n", pc->utf8url); \
quitDecode(pc,dc); \ pause = -1; \
return; \
} \ } \
pc->state = PLAYER_STATE_PLAY; \
} \ } \
pc->pause = 0; \ pc->pause = 0; \
kill(getppid(),SIGUSR1); \ kill(getppid(), SIGUSR1); \
if(pause) { \ if (pause == -1) pause = 1; \
else if (pause) { \
dropBufferedAudio(); \ dropBufferedAudio(); \
closeAudioDevice(); \ closeAudioDevice(); \
} \ } \
...@@ -285,7 +284,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -285,7 +284,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
return; return;
} }
dc->seekable = inStream.seekable;
dc->state = DECODE_STATE_START; dc->state = DECODE_STATE_START;
dc->start = 0; dc->start = 0;
...@@ -295,6 +293,9 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -295,6 +293,9 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
my_usleep(1000); my_usleep(1000);
} }
/* for http streams, seekable is determined in bufferInputStream */
dc->seekable = inStream.seekable;
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
...@@ -480,10 +481,10 @@ static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc, ...@@ -480,10 +481,10 @@ static void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc,
while (cb->begin != to) { while (cb->begin != to) {
handleMetadata(cb, pc, previous, currentChunkSent, handleMetadata(cb, pc, previous, currentChunkSent,
currentChunk); currentChunk);
cb->begin++; if (cb->begin + 1 >= buffered_chunks) {
if (cb->begin >= buffered_chunks) {
cb->begin = 0; cb->begin = 0;
} }
else cb->begin++;
} }
} }
...@@ -516,7 +517,8 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * ...@@ -516,7 +517,8 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
pc->play = 0; pc->play = 0;
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
while (decode_pid > 0 && cb->end - cb->begin < bbp && while (decode_pid > 0 &&
cb->end - cb->begin < bbp &&
cb->end != buffered_chunks - 1 && cb->end != buffered_chunks - 1 &&
dc->state != DECODE_STATE_STOP) { dc->state != DECODE_STATE_STOP) {
processDecodeInput(); processDecodeInput();
...@@ -617,10 +619,10 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * ...@@ -617,10 +619,10 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
cb->begin = 0; cb->begin = 0;
} else } else
cb->begin++; cb->begin++;
} else if (next == cb->begin) { } else if (cb->begin != end && cb->begin == next) {
if (doCrossFade == 1 && nextChunk >= 0) { if (doCrossFade == 1 && nextChunk >= 0) {
nextChunk = cb->begin + crossFadeChunks; nextChunk = cb->begin + crossFadeChunks;
test = cb->end; test = end;
if (end < cb->begin) if (end < cb->begin)
test += buffered_chunks; test += buffered_chunks;
if (nextChunk < test) { if (nextChunk < test) {
...@@ -663,6 +665,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * ...@@ -663,6 +665,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
quit = 1; quit = 1;
break; break;
} else { } else {
/*DEBUG("waiting for decoded audio, play silence\n");*/
if (playAudio(silence, CHUNK_SIZE) < 0) if (playAudio(silence, CHUNK_SIZE) < 0)
quit = 1; quit = 1;
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -59,15 +59,15 @@ ...@@ -59,15 +59,15 @@
#define DIRECTORY_RETURN_UPDATE 1 #define DIRECTORY_RETURN_UPDATE 1
#define DIRECTORY_RETURN_ERROR -1 #define DIRECTORY_RETURN_ERROR -1
Directory *mp3rootDirectory = NULL; static Directory *mp3rootDirectory;
time_t directory_dbModTime = 0; static time_t directory_dbModTime;
volatile int directory_updatePid = 0; static volatile int directory_updatePid;
volatile int directory_reReadDB = 0; static volatile int directory_reReadDB;
volatile mpd_uint16 directory_updateJobId = 0; static volatile mpd_uint16 directory_updateJobId;
static DirectoryList *newDirectoryList(); static DirectoryList *newDirectoryList();
...@@ -543,7 +543,7 @@ static int updatePath(char *utf8path) ...@@ -543,7 +543,7 @@ static int updatePath(char *utf8path)
free(path); free(path);
return 0; return 0;
} }
/* if updateDirectory fials, means we should delete it */ /* if updateDirectory fails, means we should delete it */
else { else {
LOG("removing directory: %s\n", path); LOG("removing directory: %s\n", path);
deleteFromList(parentDirectory->subDirectories, deleteFromList(parentDirectory->subDirectories,
...@@ -573,7 +573,7 @@ static int updatePath(char *utf8path) ...@@ -573,7 +573,7 @@ static int updatePath(char *utf8path)
return 1; return 1;
} }
} }
/* if updateDirectory fials, means we should delete it */ /* if updateDirectory fails, means we should delete it */
else { else {
removeSongFromDirectory(parentDirectory, shortname); removeSongFromDirectory(parentDirectory, shortname);
ret = 1; ret = 1;
...@@ -835,13 +835,21 @@ static Directory *findSubDirectory(Directory * directory, char *name) ...@@ -835,13 +835,21 @@ static Directory *findSubDirectory(Directory * directory, char *name)
return NULL; return NULL;
} }
int isRootDirectory(char *name)
{
if (name == NULL || name[0] == '\0' || strcmp(name, "/") == 0) {
return 1;
}
return 0;
}
static Directory *getSubDirectory(Directory * directory, char *name, static Directory *getSubDirectory(Directory * directory, char *name,
char **shortname) char **shortname)
{ {
Directory *subDirectory; Directory *subDirectory;
int len; int len;
if (name == NULL || name[0] == '\0' || strcmp(name, "/") == 0) { if (isRootDirectory(name)) {
return directory; return directory;
} }
...@@ -943,23 +951,18 @@ static void readDirectoryInfo(FILE * fp, Directory * directory) ...@@ -943,23 +951,18 @@ static void readDirectoryInfo(FILE * fp, Directory * directory)
&& 0 != strncmp(DIRECTORY_END, buffer, strlen(DIRECTORY_END))) { && 0 != strncmp(DIRECTORY_END, buffer, strlen(DIRECTORY_END))) {
if (0 == strncmp(DIRECTORY_DIR, buffer, strlen(DIRECTORY_DIR))) { if (0 == strncmp(DIRECTORY_DIR, buffer, strlen(DIRECTORY_DIR))) {
key = xstrdup(&(buffer[strlen(DIRECTORY_DIR)])); key = xstrdup(&(buffer[strlen(DIRECTORY_DIR)]));
if (!myFgets(buffer, bufferSize, fp)) { if (!myFgets(buffer, bufferSize, fp))
ERROR("Error reading db, fgets\n"); FATAL("Error reading db, fgets\n");
exit(EXIT_FAILURE);
}
/* for compatibility with db's prior to 0.11 */ /* for compatibility with db's prior to 0.11 */
if (0 == strncmp(DIRECTORY_MTIME, buffer, if (0 == strncmp(DIRECTORY_MTIME, buffer,
strlen(DIRECTORY_MTIME))) { strlen(DIRECTORY_MTIME))) {
if (!myFgets(buffer, bufferSize, fp)) { if (!myFgets(buffer, bufferSize, fp))
ERROR("Error reading db, fgets\n"); FATAL("Error reading db, fgets\n");
exit(EXIT_FAILURE);
}
} }
if (strncmp if (strncmp
(DIRECTORY_BEGIN, buffer, (DIRECTORY_BEGIN, buffer,
strlen(DIRECTORY_BEGIN))) { strlen(DIRECTORY_BEGIN))) {
ERROR("Error reading db at line: %s\n", buffer); FATAL("Error reading db at line: %s\n", buffer);
exit(EXIT_FAILURE);
} }
name = xstrdup(&(buffer[strlen(DIRECTORY_BEGIN)])); name = xstrdup(&(buffer[strlen(DIRECTORY_BEGIN)]));
...@@ -993,8 +996,7 @@ static void readDirectoryInfo(FILE * fp, Directory * directory) ...@@ -993,8 +996,7 @@ static void readDirectoryInfo(FILE * fp, Directory * directory)
} else if (0 == strncmp(SONG_BEGIN, buffer, strlen(SONG_BEGIN))) { } else if (0 == strncmp(SONG_BEGIN, buffer, strlen(SONG_BEGIN))) {
readSongInfoIntoList(fp, directory->songs, directory); readSongInfoIntoList(fp, directory->songs, directory);
} else { } else {
ERROR("Unknown line in db: %s\n", buffer); FATAL("Unknown line in db: %s\n", buffer);
exit(EXIT_FAILURE);
} }
} }
...@@ -1091,6 +1093,7 @@ int writeDirectoryDB(void) ...@@ -1091,6 +1093,7 @@ int writeDirectoryDB(void)
{ {
FILE *fp; FILE *fp;
char *dbFile = getDbFile(); char *dbFile = getDbFile();
struct stat st;
DEBUG("removing empty directories from DB\n"); DEBUG("removing empty directories from DB\n");
deleteEmptyDirectoriesInDirectory(mp3rootDirectory); deleteEmptyDirectoriesInDirectory(mp3rootDirectory);
...@@ -1101,7 +1104,7 @@ int writeDirectoryDB(void) ...@@ -1101,7 +1104,7 @@ int writeDirectoryDB(void)
DEBUG("writing DB\n"); DEBUG("writing DB\n");
while (!(fp = fopen(dbFile, "w")) && errno == EINTR) ; while (!(fp = fopen(dbFile, "w")) && errno == EINTR);
if (!fp) { if (!fp) {
ERROR("unable to write to db file \"%s\": %s\n", ERROR("unable to write to db file \"%s\": %s\n",
dbFile, strerror(errno)); dbFile, strerror(errno));
...@@ -1116,7 +1119,10 @@ int writeDirectoryDB(void) ...@@ -1116,7 +1119,10 @@ int writeDirectoryDB(void)
writeDirectoryInfo(fp, mp3rootDirectory); writeDirectoryInfo(fp, mp3rootDirectory);
while (fclose(fp) && errno == EINTR) ; while (fclose(fp) && errno == EINTR);
if (stat(dbFile, &st) == 0)
directory_dbModTime = st.st_mtime;
return 0; return 0;
} }
...@@ -1131,7 +1137,7 @@ int readDirectoryDB(void) ...@@ -1131,7 +1137,7 @@ int readDirectoryDB(void)
mp3rootDirectory = newDirectory(NULL, NULL); mp3rootDirectory = newDirectory(NULL, NULL);
while (!(fp = fopen(dbFile, "r")) && errno == EINTR) ; while (!(fp = fopen(dbFile, "r")) && errno == EINTR) ;
if (fp == NULL) { if (fp == NULL) {
ERROR("unable open db file \"%s\": %s\n", ERROR("unable to open db file \"%s\": %s\n",
dbFile, strerror(errno)); dbFile, strerror(errno));
return -1; return -1;
} }
...@@ -1143,21 +1149,16 @@ int readDirectoryDB(void) ...@@ -1143,21 +1149,16 @@ int readDirectoryDB(void)
int foundFsCharset = 0; int foundFsCharset = 0;
int foundVersion = 0; int foundVersion = 0;
if (!myFgets(buffer, bufferSize, fp)) { if (!myFgets(buffer, bufferSize, fp))
ERROR("Error reading db, fgets\n"); FATAL("Error reading db, fgets\n");
exit(EXIT_FAILURE);
}
if (0 == strcmp(DIRECTORY_INFO_BEGIN, buffer)) { if (0 == strcmp(DIRECTORY_INFO_BEGIN, buffer)) {
while (myFgets(buffer, bufferSize, fp) && while (myFgets(buffer, bufferSize, fp) &&
0 != strcmp(DIRECTORY_INFO_END, buffer)) { 0 != strcmp(DIRECTORY_INFO_END, buffer)) {
if (0 == strncmp(DIRECTORY_MPD_VERSION, buffer, if (0 == strncmp(DIRECTORY_MPD_VERSION, buffer,
strlen(DIRECTORY_MPD_VERSION))) strlen(DIRECTORY_MPD_VERSION)))
{ {
if (foundVersion) { if (foundVersion)
ERROR("already found " FATAL("already found version in db\n");
"version in db\n");
exit(EXIT_FAILURE);
}
foundVersion = 1; foundVersion = 1;
} else if (0 == } else if (0 ==
strncmp(DIRECTORY_FS_CHARSET, buffer, strncmp(DIRECTORY_FS_CHARSET, buffer,
...@@ -1166,20 +1167,13 @@ int readDirectoryDB(void) ...@@ -1166,20 +1167,13 @@ int readDirectoryDB(void)
char *fsCharset; char *fsCharset;
char *tempCharset; char *tempCharset;
if (foundFsCharset) { if (foundFsCharset)
WARNING("already found " FATAL("already found fs charset in db\n");
"fs charset in db\n");
exit(EXIT_FAILURE);
}
foundFsCharset = 1; foundFsCharset = 1;
fsCharset = fsCharset = &(buffer[strlen(DIRECTORY_FS_CHARSET)]);
&(buffer if ((tempCharset = getConfigParamValue(CONF_FS_CHARSET))
[strlen(DIRECTORY_FS_CHARSET)]);
if ((tempCharset =
getConfigParamValue
(CONF_FS_CHARSET))
&& strcmp(fsCharset, tempCharset)) { && strcmp(fsCharset, tempCharset)) {
WARNING("Using \"%s\" for the " WARNING("Using \"%s\" for the "
"filesystem charset " "filesystem charset "
...@@ -1190,10 +1184,8 @@ int readDirectoryDB(void) ...@@ -1190,10 +1184,8 @@ int readDirectoryDB(void)
setFsCharset(fsCharset); setFsCharset(fsCharset);
} }
} else { } else {
ERROR FATAL("directory: unknown line in db info: %s\n",
("directory: unknown line in db info: %s\n",
buffer); buffer);
exit(EXIT_FAILURE);
} }
} }
} else { } else {
...@@ -1225,14 +1217,12 @@ void updateMp3Directory(void) ...@@ -1225,14 +1217,12 @@ void updateMp3Directory(void)
/* nothing updated */ /* nothing updated */
return; return;
case 1: case 1:
if (writeDirectoryDB() < 0) { if (writeDirectoryDB() < 0)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
break; break;
default: default:
/* something was updated and db should be written */ /* something was updated and db should be written */
ERROR("problems updating music db\n"); FATAL("problems updating music db\n");
exit(EXIT_FAILURE);
} }
return; return;
...@@ -1311,16 +1301,11 @@ static void freeAllDirectoryStats(Directory * directory) ...@@ -1311,16 +1301,11 @@ static void freeAllDirectoryStats(Directory * directory)
void initMp3Directory(void) void initMp3Directory(void)
{ {
struct stat st;
mp3rootDirectory = newDirectory(NULL, NULL); mp3rootDirectory = newDirectory(NULL, NULL);
exploreDirectory(mp3rootDirectory); exploreDirectory(mp3rootDirectory);
freeAllDirectoryStats(mp3rootDirectory); freeAllDirectoryStats(mp3rootDirectory);
stats.numberOfSongs = countSongsIn(STDERR_FILENO, NULL); stats.numberOfSongs = countSongsIn(STDERR_FILENO, NULL);
stats.dbPlayTime = sumSongTimesIn(STDERR_FILENO, NULL); stats.dbPlayTime = sumSongTimesIn(STDERR_FILENO, NULL);
if (stat(getDbFile(), &st) == 0)
directory_dbModTime = st.st_mtime;
} }
static Song *getSongDetails(char *file, char **shortnameRet, static Song *getSongDetails(char *file, char **shortnameRet,
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -51,6 +51,8 @@ void initMp3Directory(void); ...@@ -51,6 +51,8 @@ void initMp3Directory(void);
void closeMp3Directory(void); void closeMp3Directory(void);
int isRootDirectory(char *name);
int printDirectoryInfo(int fd, char *dirname); int printDirectoryInfo(int fd, char *dirname);
int checkDirectoryDB(void); int checkDirectoryDB(void);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
static List *inputPlugin_list = NULL; static List *inputPlugin_list;
void loadInputPlugin(InputPlugin * inputPlugin) void loadInputPlugin(InputPlugin * inputPlugin)
{ {
...@@ -59,7 +59,7 @@ static int stringFoundInStringArray(char **array, char *suffix) ...@@ -59,7 +59,7 @@ static int stringFoundInStringArray(char **array, char *suffix)
InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next) InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next)
{ {
static ListNode *pos = NULL; static ListNode *pos;
ListNode *node; ListNode *node;
InputPlugin *plugin; InputPlugin *plugin;
...@@ -88,7 +88,7 @@ InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next) ...@@ -88,7 +88,7 @@ InputPlugin *getInputPluginFromSuffix(char *suffix, unsigned int next)
InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next) InputPlugin *getInputPluginFromMimeType(char *mimeType, unsigned int next)
{ {
static ListNode *pos = NULL; static ListNode *pos;
ListNode *node; ListNode *node;
InputPlugin *plugin; InputPlugin *plugin;
...@@ -137,16 +137,6 @@ void printAllInputPluginSuffixes(FILE * fp) ...@@ -137,16 +137,6 @@ void printAllInputPluginSuffixes(FILE * fp)
fflush(fp); fflush(fp);
} }
extern InputPlugin mp3Plugin;
extern InputPlugin oggvorbisPlugin;
extern InputPlugin flacPlugin;
extern InputPlugin oggflacPlugin;
extern InputPlugin audiofilePlugin;
extern InputPlugin mp4Plugin;
extern InputPlugin mpcPlugin;
extern InputPlugin aacPlugin;
extern InputPlugin modPlugin;
void initInputPlugins(void) void initInputPlugins(void)
{ {
inputPlugin_list = makeList(NULL, 1); inputPlugin_list = makeList(NULL, 1);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -96,4 +96,14 @@ void initInputPlugins(void); ...@@ -96,4 +96,14 @@ void initInputPlugins(void);
/* this is where we "unload" all the "plugins" */ /* this is where we "unload" all the "plugins" */
void finishInputPlugins(void); void finishInputPlugins(void);
extern InputPlugin mp3Plugin;
extern InputPlugin oggvorbisPlugin;
extern InputPlugin flacPlugin;
extern InputPlugin oggflacPlugin;
extern InputPlugin audiofilePlugin;
extern InputPlugin mp4Plugin;
extern InputPlugin mpcPlugin;
extern InputPlugin aacPlugin;
extern InputPlugin modPlugin;
#endif #endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Common data structures and functions used by FLAC and OggFLAC * Common data structures and functions used by FLAC and OggFLAC
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Common data structures and functions used by FLAC and OggFLAC * Common data structures and functions used by FLAC and OggFLAC
...@@ -30,7 +30,116 @@ ...@@ -30,7 +30,116 @@
#include "../inputStream.h" #include "../inputStream.h"
#include "../outputBuffer.h" #include "../outputBuffer.h"
#include "../decode.h" #include "../decode.h"
#include <FLAC/seekable_stream_decoder.h> #include <FLAC/export.h>
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# include <FLAC/seekable_stream_decoder.h>
# define flac_decoder FLAC__SeekableStreamDecoder
# define flac_new() FLAC__seekable_stream_decoder_new()
# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) (0)
# define flac_get_decode_position(x,y) \
FLAC__seekable_stream_decoder_get_decode_position(x,y)
# define flac_get_state(x) FLAC__seekable_stream_decoder_get_state(x)
# define flac_process_single(x) FLAC__seekable_stream_decoder_process_single(x)
# define flac_process_metadata(x) \
FLAC__seekable_stream_decoder_process_until_end_of_metadata(x)
# define flac_seek_absolute(x,y) \
FLAC__seekable_stream_decoder_seek_absolute(x,y)
# define flac_finish(x) FLAC__seekable_stream_decoder_finish(x)
# define flac_delete(x) FLAC__seekable_stream_decoder_delete(x)
# define flac_decoder_eof FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
typedef unsigned flac_read_status_size_t;
# define flac_read_status FLAC__SeekableStreamDecoderReadStatus
# define flac_read_status_continue \
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
# define flac_read_status_eof FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
# define flac_read_status_abort \
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
# define flac_seek_status FLAC__SeekableStreamDecoderSeekStatus
# define flac_seek_status_ok FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
# define flac_seek_status_error FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
# define flac_tell_status FLAC__SeekableStreamDecoderTellStatus
# define flac_tell_status_ok FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
# define flac_tell_status_error \
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
# define flac_tell_status_unsupported \
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
# define flac_length_status FLAC__SeekableStreamDecoderLengthStatus
# define flac_length_status_ok FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
# define flac_length_status_error \
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
# define flac_length_status_unsupported \
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
# ifdef HAVE_OGGFLAC
# include <OggFLAC/seekable_stream_decoder.h>
# endif
#else /* FLAC_API_VERSION_CURRENT >= 7 */
/* OggFLAC support is handled by our flac_plugin already, and
* thus we *can* always have it if libFLAC was compiled with it */
# ifndef HAVE_OGGFLAC
# define HAVE_OGGFLAC 1
# endif
# include "_ogg_common.h"
# undef HAVE_OGGFLAC /* we don't need this defined anymore */
# include <FLAC/stream_decoder.h>
# define flac_decoder FLAC__StreamDecoder
# define flac_new() FLAC__stream_decoder_new()
# define flac_init(a,b,c,d,e,f,g,h,i,j) \
(FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \
== FLAC__STREAM_DECODER_INIT_STATUS_OK)
# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) \
(FLAC__stream_decoder_init_ogg_stream(a,b,c,d,e,f,g,h,i,j) \
== FLAC__STREAM_DECODER_INIT_STATUS_OK)
# define flac_get_decode_position(x,y) \
FLAC__stream_decoder_get_decode_position(x,y)
# define flac_get_state(x) FLAC__stream_decoder_get_state(x)
# define flac_process_single(x) FLAC__stream_decoder_process_single(x)
# define flac_process_metadata(x) \
FLAC__stream_decoder_process_until_end_of_metadata(x)
# define flac_seek_absolute(x,y) FLAC__stream_decoder_seek_absolute(x,y)
# define flac_finish(x) FLAC__stream_decoder_finish(x)
# define flac_delete(x) FLAC__stream_decoder_delete(x)
# define flac_decoder_eof FLAC__STREAM_DECODER_END_OF_STREAM
typedef size_t flac_read_status_size_t;
# define flac_read_status FLAC__StreamDecoderReadStatus
# define flac_read_status_continue \
FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
# define flac_read_status_eof FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
# define flac_read_status_abort FLAC__STREAM_DECODER_READ_STATUS_ABORT
# define flac_seek_status FLAC__StreamDecoderSeekStatus
# define flac_seek_status_ok FLAC__STREAM_DECODER_SEEK_STATUS_OK
# define flac_seek_status_error FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
# define flac_seek_status_unsupported \
FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
# define flac_tell_status FLAC__StreamDecoderTellStatus
# define flac_tell_status_ok FLAC__STREAM_DECODER_TELL_STATUS_OK
# define flac_tell_status_error FLAC__STREAM_DECODER_TELL_STATUS_ERROR
# define flac_tell_status_unsupported \
FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
# define flac_length_status FLAC__StreamDecoderLengthStatus
# define flac_length_status_ok FLAC__STREAM_DECODER_LENGTH_STATUS_OK
# define flac_length_status_error FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
# define flac_length_status_unsupported \
FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
#define FLAC_CHUNK_SIZE 4080 #define FLAC_CHUNK_SIZE 4080
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC) * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC) * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -237,7 +237,7 @@ static float getAacFloatTotalTime(char *file) ...@@ -237,7 +237,7 @@ static float getAacFloatTotalTime(char *file)
size_t fileread, tagsize; size_t fileread, tagsize;
faacDecHandle decoder; faacDecHandle decoder;
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
unsigned int sampleRate; unsigned long sampleRate;
unsigned char channels; unsigned char channels;
InputStream inStream; InputStream inStream;
long bread; long bread;
...@@ -293,7 +293,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path) ...@@ -293,7 +293,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
faacDecFrameInfo frameInfo; faacDecFrameInfo frameInfo;
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
long bread; long bread;
unsigned int sampleRate; unsigned long sampleRate;
unsigned char channels; unsigned char channels;
int eof = 0; int eof = 0;
unsigned int sampleCount; unsigned int sampleCount;
...@@ -470,17 +470,6 @@ InputPlugin aacPlugin = { ...@@ -470,17 +470,6 @@ InputPlugin aacPlugin = {
#else #else
InputPlugin aacPlugin = { InputPlugin aacPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
};
#endif /* HAVE_FAAD */ #endif /* HAVE_FAAD */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net> * libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net>
...@@ -183,17 +183,6 @@ InputPlugin audiofilePlugin = { ...@@ -183,17 +183,6 @@ InputPlugin audiofilePlugin = {
#else #else
InputPlugin audiofilePlugin = { InputPlugin audiofilePlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL
};
#endif /* HAVE_AUDIOFILE */ #endif /* HAVE_AUDIOFILE */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -16,12 +16,10 @@ ...@@ -16,12 +16,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "../inputPlugin.h" #include "_flac_common.h"
#ifdef HAVE_FLAC #ifdef HAVE_FLAC
#include "_flac_common.h"
#include "../utils.h" #include "../utils.h"
#include "../log.h" #include "../log.h"
#include "../pcm_utils.h" #include "../pcm_utils.h"
...@@ -33,166 +31,14 @@ ...@@ -33,166 +31,14 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <FLAC/seekable_stream_decoder.h> #include <assert.h>
#include <FLAC/metadata.h>
/* this code is based on flac123, from flac-tools */
static void flacError(const FLAC__SeekableStreamDecoder *,
FLAC__StreamDecoderErrorStatus, void *);
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state);
static void flacMetadata(const FLAC__SeekableStreamDecoder *,
const FLAC__StreamMetadata *, void *);
static FLAC__StreamDecoderWriteStatus flacWrite(const
FLAC__SeekableStreamDecoder *,
const FLAC__Frame *,
const FLAC__int32 * const buf[],
void *);
static FLAC__SeekableStreamDecoderReadStatus flacRead(const
FLAC__SeekableStreamDecoder
*, FLAC__byte buf[],
unsigned *, void *);
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const
FLAC__SeekableStreamDecoder
*, FLAC__uint64, void *);
static FLAC__SeekableStreamDecoderTellStatus flacTell(const
FLAC__SeekableStreamDecoder
*, FLAC__uint64 *,
void *);
static FLAC__SeekableStreamDecoderLengthStatus flacLength(const
FLAC__SeekableStreamDecoder
*, FLAC__uint64 *,
void *);
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *);
static int flac_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream)
{
FLAC__SeekableStreamDecoder *flacDec = NULL;
FlacData data;
int status = 1;
int ret = 0;
init_FlacData(&data, cb, dc, inStream);
if (!(flacDec = FLAC__seekable_stream_decoder_new())) {
ret = -1;
goto fail;
}
/*status&=FLAC__file_decoder_set_md5_checking(flacDec,1); */
status &= FLAC__seekable_stream_decoder_set_read_callback(flacDec,
flacRead);
status &= FLAC__seekable_stream_decoder_set_seek_callback(flacDec,
flacSeek);
status &= FLAC__seekable_stream_decoder_set_tell_callback(flacDec,
flacTell);
status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec,
flacLength);
status &=
FLAC__seekable_stream_decoder_set_eof_callback(flacDec, flacEOF);
status &=
FLAC__seekable_stream_decoder_set_write_callback(flacDec,
flacWrite);
status &=
FLAC__seekable_stream_decoder_set_metadata_callback(flacDec,
flacMetadata);
status &=
FLAC__seekable_stream_decoder_set_metadata_respond(flacDec,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
status &=
FLAC__seekable_stream_decoder_set_error_callback(flacDec,
flacError);
status &=
FLAC__seekable_stream_decoder_set_client_data(flacDec,
(void *)&data);
if (!status) {
ERROR("flac problem before init()\n");
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
(flacDec));
ret = -1;
goto fail;
}
if (FLAC__seekable_stream_decoder_init(flacDec) !=
FLAC__SEEKABLE_STREAM_DECODER_OK) {
ERROR("flac problem doing init()\n");
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
(flacDec));
ret = -1;
goto fail;
}
if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata
(flacDec)) {
ERROR("flac problem reading metadata\n");
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
(flacDec));
ret = -1;
goto fail;
}
dc->state = DECODE_STATE_DECODE;
while (1) {
FLAC__seekable_stream_decoder_process_single(flacDec);
if (FLAC__seekable_stream_decoder_get_state(flacDec) !=
FLAC__SEEKABLE_STREAM_DECODER_OK) {
break;
}
if (dc->seek) {
FLAC__uint64 sampleToSeek = dc->seekWhere *
dc->audioFormat.sampleRate + 0.5;
if (FLAC__seekable_stream_decoder_seek_absolute(flacDec,
sampleToSeek))
{
clearOutputBuffer(cb);
data.time = ((float)sampleToSeek) /
dc->audioFormat.sampleRate;
data.position = 0;
} else
dc->seekError = 1;
dc->seek = 0;
}
}
/* I don't think we need this bit here! -shank */
/*FLAC__file_decoder_process_until_end_of_file(flacDec); */
if (!dc->stop) {
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
(flacDec));
FLAC__seekable_stream_decoder_finish(flacDec);
}
/* send last little bit */
if (data.chunk_length > 0 && !dc->stop) {
flacSendChunk(&data);
flushOutputBuffer(data.cb);
}
/*if(dc->seek) {
dc->seekError = 1;
dc->seek = 0;
} */
dc->state = DECODE_STATE_STOP;
dc->stop = 0;
fail:
if (data.replayGainInfo)
freeReplayGainInfo(data.replayGainInfo);
if (flacDec)
FLAC__seekable_stream_decoder_delete(flacDec);
closeInputStream(inStream);
return ret; /* this code was based on flac123, from flac-tools */
}
static FLAC__SeekableStreamDecoderReadStatus flacRead(const static flac_read_status flacRead(const flac_decoder * flacDec,
FLAC__SeekableStreamDecoder FLAC__byte buf[],
* flacDec, flac_read_status_size_t *bytes,
FLAC__byte buf[], void *fdata)
unsigned *bytes,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
size_t r; size_t r;
...@@ -207,55 +53,51 @@ static FLAC__SeekableStreamDecoderReadStatus flacRead(const ...@@ -207,55 +53,51 @@ static FLAC__SeekableStreamDecoderReadStatus flacRead(const
} }
*bytes = r; *bytes = r;
if (*bytes == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) if (r == 0 && !data->dc->stop) {
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; if (inputStreamAtEOF(data->inStream))
return flac_read_status_eof;
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; else
return flac_read_status_abort;
}
return flac_read_status_continue;
} }
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const static flac_seek_status flacSeek(const flac_decoder * flacDec,
FLAC__SeekableStreamDecoder FLAC__uint64 offset,
* flacDec, void *fdata)
FLAC__uint64 offset,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; return flac_seek_status_error;
} }
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; return flac_seek_status_ok;
} }
static FLAC__SeekableStreamDecoderTellStatus flacTell(const static flac_tell_status flacTell(const flac_decoder * flacDec,
FLAC__SeekableStreamDecoder FLAC__uint64 * offset,
* flacDec, void *fdata)
FLAC__uint64 * offset,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
*offset = (long)(data->inStream->offset); *offset = (long)(data->inStream->offset);
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; return flac_tell_status_ok;
} }
static FLAC__SeekableStreamDecoderLengthStatus flacLength(const static flac_length_status flacLength(const flac_decoder * flacDec,
FLAC__SeekableStreamDecoder FLAC__uint64 * length,
* flacDec, void *fdata)
FLAC__uint64 * length,
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
*length = (size_t) (data->inStream->size); *length = (size_t) (data->inStream->size);
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; return flac_length_status_ok;
} }
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata)
void *fdata)
{ {
FlacData *data = (FlacData *) fdata; FlacData *data = (FlacData *) fdata;
...@@ -264,52 +106,112 @@ static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, ...@@ -264,52 +106,112 @@ static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec,
return false; return false;
} }
static void flacError(const FLAC__SeekableStreamDecoder * dec, static void flacError(const flac_decoder *dec,
FLAC__StreamDecoderErrorStatus status, void *fdata) FLAC__StreamDecoderErrorStatus status, void *fdata)
{ {
flac_error_common_cb("flac", status, (FlacData *) fdata); flac_error_common_cb("flac", status, (FlacData *) fdata);
} }
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
{ {
const char *str = ""; /* "" to silence compiler warning */
switch (state) { switch (state) {
case FLAC__SEEKABLE_STREAM_DECODER_OK:
case FLAC__SEEKABLE_STREAM_DECODER_SEEKING:
case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM:
return;
case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR("flac allocation error\n"); str = "allocation error";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR:
ERROR("flac read error\n"); str = "read error";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR:
ERROR("flac seek error\n"); str = "seek error";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR:
ERROR("flac seekable stream error\n"); str = "seekable stream error";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED:
ERROR("flac decoder already initialized\n"); str = "decoder already initialized";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK:
ERROR("invalid flac callback\n"); str = "invalid callback";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
ERROR("flac decoder uninitialized\n"); str = "decoder uninitialized";
}
ERROR("flac %s\n", str);
}
static int flac_init(FLAC__SeekableStreamDecoder *dec,
FLAC__SeekableStreamDecoderReadCallback read_cb,
FLAC__SeekableStreamDecoderSeekCallback seek_cb,
FLAC__SeekableStreamDecoderTellCallback tell_cb,
FLAC__SeekableStreamDecoderLengthCallback length_cb,
FLAC__SeekableStreamDecoderEofCallback eof_cb,
FLAC__SeekableStreamDecoderWriteCallback write_cb,
FLAC__SeekableStreamDecoderMetadataCallback metadata_cb,
FLAC__SeekableStreamDecoderErrorCallback error_cb,
void *data)
{
int s = 1;
s &= FLAC__seekable_stream_decoder_set_read_callback(dec, read_cb);
s &= FLAC__seekable_stream_decoder_set_seek_callback(dec, seek_cb);
s &= FLAC__seekable_stream_decoder_set_tell_callback(dec, tell_cb);
s &= FLAC__seekable_stream_decoder_set_length_callback(dec, length_cb);
s &= FLAC__seekable_stream_decoder_set_eof_callback(dec, eof_cb);
s &= FLAC__seekable_stream_decoder_set_write_callback(dec, write_cb);
s &= FLAC__seekable_stream_decoder_set_metadata_callback(dec,
metadata_cb);
s &= FLAC__seekable_stream_decoder_set_metadata_respond(dec,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
s &= FLAC__seekable_stream_decoder_set_error_callback(dec, error_cb);
s &= FLAC__seekable_stream_decoder_set_client_data(dec, data);
if (!s || (FLAC__seekable_stream_decoder_init(dec) !=
FLAC__SEEKABLE_STREAM_DECODER_OK))
return 0;
return 1;
}
#else /* FLAC_API_VERSION_CURRENT >= 7 */
static void flacPrintErroredState(FLAC__StreamDecoderState state)
{
const char *str = ""; /* "" to silence compiler warning */
switch (state) {
case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
case FLAC__STREAM_DECODER_READ_METADATA:
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
case FLAC__STREAM_DECODER_READ_FRAME:
case FLAC__STREAM_DECODER_END_OF_STREAM:
return;
case FLAC__STREAM_DECODER_OGG_ERROR:
str = "error in the Ogg layer";
break; break;
case FLAC__SEEKABLE_STREAM_DECODER_OK: case FLAC__STREAM_DECODER_SEEK_ERROR:
case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: str = "seek error";
case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: break;
case FLAC__STREAM_DECODER_ABORTED:
str = "decoder aborted by read";
break; break;
case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
str = "allocation error";
break;
case FLAC__STREAM_DECODER_UNINITIALIZED:
str = "decoder uninitialized";
} }
ERROR("flac %s\n", str);
} }
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
static void flacMetadata(const FLAC__SeekableStreamDecoder * dec, static void flacMetadata(const flac_decoder * dec,
const FLAC__StreamMetadata * block, void *vdata) const FLAC__StreamMetadata * block, void *vdata)
{ {
flac_metadata_common_cb(block, (FlacData *) vdata); flac_metadata_common_cb(block, (FlacData *) vdata);
} }
static FLAC__StreamDecoderWriteStatus flacWrite(const static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec,
FLAC__SeekableStreamDecoder * const FLAC__Frame * frame,
dec, const FLAC__Frame * frame,
const FLAC__int32 * const buf[], const FLAC__int32 * const buf[],
void *vdata) void *vdata)
{ {
...@@ -325,7 +227,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const ...@@ -325,7 +227,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const
timeChange = ((float)samples) / frame->header.sample_rate; timeChange = ((float)samples) / frame->header.sample_rate;
data->time += timeChange; data->time += timeChange;
FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition); flac_get_decode_position(dec, &newPosition);
if (data->position) { if (data->position) {
data->bitRate = data->bitRate =
((newPosition - data->position) * 8.0 / timeChange) ((newPosition - data->position) * 8.0 / timeChange)
...@@ -438,12 +340,179 @@ static MpdTag *flacTagDup(char *file) ...@@ -438,12 +340,179 @@ static MpdTag *flacTagDup(char *file)
return ret; return ret;
} }
static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream, int is_ogg)
{
flac_decoder *flacDec;
FlacData data;
const char *err = NULL;
if (!(flacDec = flac_new()))
return -1;
init_FlacData(&data, cb, dc, inStream);
if (is_ogg) {
if (!flac_ogg_init(flacDec, flacRead, flacSeek, flacTell,
flacLength, flacEOF, flacWrite, flacMetadata,
flacError, (void *)&data)) {
err = "doing Ogg init()";
goto fail;
}
} else {
if (!flac_init(flacDec, flacRead, flacSeek, flacTell,
flacLength, flacEOF, flacWrite, flacMetadata,
flacError, (void *)&data)) {
err = "doing init()";
goto fail;
}
if (!flac_process_metadata(flacDec)) {
err = "problem reading metadata";
goto fail;
}
}
dc->state = DECODE_STATE_DECODE;
while (1) {
if (!flac_process_single(flacDec))
break;
if (flac_get_state(flacDec) == flac_decoder_eof)
break;
if (dc->seek) {
FLAC__uint64 sampleToSeek = dc->seekWhere *
dc->audioFormat.sampleRate + 0.5;
if (flac_seek_absolute(flacDec, sampleToSeek)) {
clearOutputBuffer(cb);
data.time = ((float)sampleToSeek) /
dc->audioFormat.sampleRate;
data.position = 0;
} else
dc->seekError = 1;
dc->seek = 0;
}
}
if (!dc->stop) {
flacPrintErroredState(flac_get_state(flacDec));
flac_finish(flacDec);
}
/* send last little bit */
if (data.chunk_length > 0 && !dc->stop) {
flacSendChunk(&data);
flushOutputBuffer(data.cb);
}
/*if(dc->seek) {
dc->seekError = 1;
dc->seek = 0;
} */
dc->state = DECODE_STATE_STOP;
dc->stop = 0;
fail:
if (data.replayGainInfo)
freeReplayGainInfo(data.replayGainInfo);
if (flacDec)
flac_delete(flacDec);
closeInputStream(inStream);
if (err) {
ERROR("flac %s\n", err);
return -1;
}
return 0;
}
static int flac_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream)
{
return flac_decode_internal(cb, dc, inStream, 0);
}
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# define flac_plugin_init NULL
#else /* FLAC_API_VERSION_CURRENT >= 7 */
/* some of this stuff is duplicated from oggflac_plugin.c */
extern InputPlugin oggflacPlugin;
static MpdTag *oggflac_tag_dup(char *file)
{
MpdTag *ret = NULL;
FLAC__Metadata_Iterator *it;
FLAC__StreamMetadata *block;
FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
if (!(FLAC__metadata_chain_read_ogg(chain, file)))
goto out;
it = FLAC__metadata_iterator_new();
FLAC__metadata_iterator_init(it, chain);
do {
if (!(block = FLAC__metadata_iterator_get_block(it)))
break;
if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
ret = copyVorbisCommentBlockToMpdTag(block, ret);
} else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) {
if (!ret)
ret = newMpdTag();
ret->time = ((float)block->data.stream_info.
total_samples) /
block->data.stream_info.sample_rate + 0.5;
}
} while (FLAC__metadata_iterator_next(it));
FLAC__metadata_iterator_delete(it);
out:
FLAC__metadata_chain_delete(chain);
return ret;
}
static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
InputStream * inStream)
{
return flac_decode_internal(cb, dc, inStream, 1);
}
static unsigned int oggflac_try_decode(InputStream * inStream)
{
return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0;
}
static char *oggflac_suffixes[] = { "ogg", NULL };
static char *oggflac_mime_types[] = { "audio/x-flac+ogg",
"application/ogg",
"application/x-ogg",
NULL };
static int flac_plugin_init(void)
{
if (!FLAC_API_SUPPORTS_OGG_FLAC) {
DEBUG("libFLAC does not support OggFLAC\n");
return 1;
}
DEBUG("libFLAC supports OggFLAC, initializing OggFLAC support\n");
assert(oggflacPlugin.name == NULL);
oggflacPlugin.name = "oggflac";
oggflacPlugin.tryDecodeFunc = oggflac_try_decode;
oggflacPlugin.streamDecodeFunc = oggflac_decode;
oggflacPlugin.tagDupFunc = oggflac_tag_dup;
oggflacPlugin.streamTypes = INPUT_PLUGIN_STREAM_URL |
INPUT_PLUGIN_STREAM_FILE;
oggflacPlugin.suffixes = oggflac_suffixes;
oggflacPlugin.mimeTypes = oggflac_mime_types;
loadInputPlugin(&oggflacPlugin);
return 1;
}
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
static char *flacSuffixes[] = { "flac", NULL }; static char *flacSuffixes[] = { "flac", NULL };
static char *flac_mime_types[] = { "application/x-flac", NULL }; static char *flac_mime_types[] = { "audio/x-flac",
"application/x-flac",
NULL };
InputPlugin flacPlugin = { InputPlugin flacPlugin = {
"flac", "flac",
NULL, flac_plugin_init,
NULL, NULL,
NULL, NULL,
flac_decode, flac_decode,
...@@ -456,17 +525,6 @@ InputPlugin flacPlugin = { ...@@ -456,17 +525,6 @@ InputPlugin flacPlugin = {
#else /* !HAVE_FLAC */ #else /* !HAVE_FLAC */
InputPlugin flacPlugin = { InputPlugin flacPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
};
#endif /* HAVE_FLAC */ #endif /* HAVE_FLAC */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -64,8 +64,13 @@ static MDRIVER drv_mpd = { ...@@ -64,8 +64,13 @@ static MDRIVER drv_mpd = {
"MPD Output Driver v0.1", "MPD Output Driver v0.1",
0, 0,
255, 255,
"mpd", #if (LIBMIKMOD_VERSION > 0x030106)
NULL, "mpd", /* Alias */
#if (LIBMIKMOD_VERSION > 0x030200)
NULL, /* CmdLineHelp */
#endif
NULL, /* CommandLine */
#endif
mod_mpd_IsThere, mod_mpd_IsThere,
VC_SampleLoad, VC_SampleLoad,
VC_SampleUnload, VC_SampleUnload,
...@@ -92,8 +97,8 @@ static MDRIVER drv_mpd = { ...@@ -92,8 +97,8 @@ static MDRIVER drv_mpd = {
VC_VoiceRealVolume VC_VoiceRealVolume
}; };
static int mod_mikModInitiated = 0; static int mod_mikModInitiated;
static int mod_mikModInitError = 0; static int mod_mikModInitError;
static int mod_initMikMod(void) static int mod_initMikMod(void)
{ {
...@@ -143,6 +148,9 @@ static mod_Data *mod_open(char *path) ...@@ -143,6 +148,9 @@ static mod_Data *mod_open(char *path)
if (!(moduleHandle = Player_Load(path, 128, 0))) if (!(moduleHandle = Player_Load(path, 128, 0)))
return NULL; return NULL;
/* Prevent module from looping forever */
moduleHandle->loop = 0;
data = xmalloc(sizeof(mod_Data)); data = xmalloc(sizeof(mod_Data));
data->audio_buffer = xmalloc(MIKMOD_FRAME_SIZE); data->audio_buffer = xmalloc(MIKMOD_FRAME_SIZE);
...@@ -177,6 +185,7 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path) ...@@ -177,6 +185,7 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
return -1; return -1;
} }
dc->totalTime = 0;
dc->audioFormat.bits = 16; dc->audioFormat.bits = 16;
dc->audioFormat.sampleRate = 44100; dc->audioFormat.sampleRate = 44100;
dc->audioFormat.channels = 2; dc->audioFormat.channels = 2;
...@@ -285,17 +294,6 @@ InputPlugin modPlugin = { ...@@ -285,17 +294,6 @@ InputPlugin modPlugin = {
#else #else
InputPlugin modPlugin = { InputPlugin modPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL
};
#endif /* HAVE_AUDIOFILE */ #endif /* HAVE_MIKMOD */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "../utils.h" #include "../utils.h"
#include "../replayGain.h" #include "../replayGain.h"
#include "../tag.h" #include "../tag.h"
#include "../conf.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -55,6 +56,10 @@ ...@@ -55,6 +56,10 @@
/* the number of samples of silence the decoder inserts at start */ /* the number of samples of silence the decoder inserts at start */
#define DECODERDELAY 529 #define DECODERDELAY 529
#define DEFAULT_GAPLESS_MP3_PLAYBACK 1
static int gaplessPlayback;
/* this is stolen from mpg321! */ /* this is stolen from mpg321! */
struct audio_dither { struct audio_dither {
mad_fixed_t error[3]; mad_fixed_t error[3];
...@@ -113,6 +118,14 @@ static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, ...@@ -113,6 +118,14 @@ static signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
/* end of stolen stuff from mpg321 */ /* end of stolen stuff from mpg321 */
static int mp3_plugin_init(void)
{
gaplessPlayback = getBoolConfigParam(CONF_GAPLESS_MP3_PLAYBACK);
if (gaplessPlayback == -1) gaplessPlayback = DEFAULT_GAPLESS_MP3_PLAYBACK;
else if (gaplessPlayback < 0) exit(EXIT_FAILURE);
return 1;
}
/* decoder stuff is based on madlld */ /* decoder stuff is based on madlld */
#define MP3_DATA_OUTPUT_BUFFER_SIZE 4096 #define MP3_DATA_OUTPUT_BUFFER_SIZE 4096
...@@ -679,7 +692,8 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc, ...@@ -679,7 +692,8 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
data->foundXing = 1; data->foundXing = 1;
data->muteFrame = MUTEFRAME_SKIP; data->muteFrame = MUTEFRAME_SKIP;
if (parse_lame(&lame, &ptr, &bitlen)) { if (gaplessPlayback && data->inStream->seekable &&
parse_lame(&lame, &ptr, &bitlen)) {
data->dropSamplesAtStart = lame.encoderDelay + DECODERDELAY; data->dropSamplesAtStart = lame.encoderDelay + DECODERDELAY;
data->dropSamplesAtEnd = lame.encoderPadding; data->dropSamplesAtEnd = lame.encoderPadding;
} }
...@@ -759,8 +773,6 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, ...@@ -759,8 +773,6 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
mad_timer_add(&data->timer, (data->frame).header.duration); mad_timer_add(&data->timer, (data->frame).header.duration);
data->bitRate = (data->frame).header.bitrate; data->bitRate = (data->frame).header.bitrate;
if (data->currentFrame >= data->maxFrames) { if (data->currentFrame >= data->maxFrames) {
/* stop decoding, since Xing maxFrames is accurate */
if (data->foundXing) return DECODE_BREAK;
data->currentFrame = data->maxFrames - 1; data->currentFrame = data->maxFrames - 1;
} else { } else {
data->highestFrame++; data->highestFrame++;
...@@ -811,8 +823,9 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, ...@@ -811,8 +823,9 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
break; break;
} else if ((data->dropFramesAtEnd > 0) && } else if ((data->dropFramesAtEnd > 0) &&
(data->currentFrame == (data->maxFrames + 1 - data->dropFramesAtEnd))) { (data->currentFrame == (data->maxFrames + 1 - data->dropFramesAtEnd))) {
data->dropFramesAtEnd--; /* stop decoding, effectively dropping all remaining
break; * frames */
return DECODE_BREAK;
} }
if (data->inStream->metaTitle) { if (data->inStream->metaTitle) {
...@@ -835,59 +848,43 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, ...@@ -835,59 +848,43 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
for (i = 0; i < (data->synth).pcm.length; i++) { for (i = 0; i < (data->synth).pcm.length; i++) {
mpd_sint16 *sample; mpd_sint16 *sample;
samplesLeft--;
if (!data->decodedFirstFrame && if (!data->decodedFirstFrame &&
(i < data->dropSamplesAtStart)) { (i < data->dropSamplesAtStart)) {
continue; continue;
} else if (data->dropSamplesAtEnd && } else if (data->dropSamplesAtEnd &&
(data->currentFrame == (data->maxFrames - data->dropFramesAtEnd))) { (data->currentFrame == (data->maxFrames - data->dropFramesAtEnd)) &&
samplesLeft--; (samplesLeft < data->dropSamplesAtEnd)) {
/* stop decoding, since samples were dropped */ /* stop decoding, effectively dropping
if (samplesLeft < data->dropSamplesAtEnd) * all remaining samples */
return DECODE_BREAK; return DECODE_BREAK;
} }
sample = (mpd_sint16 *) data->outputPtr; sample = (mpd_sint16 *) data->outputPtr;
*sample = (mpd_sint16) audio_linear_dither(16, *sample = (mpd_sint16) audio_linear_dither(16,
(data-> (data->synth).pcm.samples[0][i],
synth).pcm. &(data->dither));
samples[0]
[i],
&(data->
dither));
data->outputPtr += 2; data->outputPtr += 2;
if (MAD_NCHANNELS(&(data->frame).header) == 2) { if (MAD_NCHANNELS(&(data->frame).header) == 2) {
sample = (mpd_sint16 *) data->outputPtr; sample = (mpd_sint16 *) data->outputPtr;
*sample = (mpd_sint16) audio_linear_dither(16, *sample = (mpd_sint16) audio_linear_dither(16,
(data-> (data->synth).pcm.samples[1][i],
synth). &(data->dither));
pcm.
samples
[1]
[i],
&
(data->
dither));
data->outputPtr += 2; data->outputPtr += 2;
} }
if (data->outputPtr >= data->outputBufferEnd) { if (data->outputPtr >= data->outputBufferEnd) {
long ret;
ret = sendDataToOutputBuffer(cb, ret = sendDataToOutputBuffer(cb,
data->inStream, data->inStream,
dc, dc,
data->inStream-> data->inStream->seekable,
seekable,
data->outputBuffer,
data->outputPtr -
data->outputBuffer, data->outputBuffer,
data->outputPtr - data->outputBuffer,
data->elapsedTime, data->elapsedTime,
data->bitRate / data->bitRate / 1000,
1000, (replayGainInfo != NULL) ? *replayGainInfo : NULL);
(replayGainInfo !=
NULL) ?
*replayGainInfo :
NULL);
if (ret == OUTPUT_BUFFER_DC_STOP) { if (ret == OUTPUT_BUFFER_DC_STOP) {
data->flush = 0; data->flush = 0;
return DECODE_BREAK; return DECODE_BREAK;
...@@ -903,21 +900,21 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc, ...@@ -903,21 +900,21 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
data->decodedFirstFrame = 1; data->decodedFirstFrame = 1;
if (dc->seek && data->inStream->seekable) { if (dc->seek && data->inStream->seekable) {
long i = 0; long j = 0;
data->muteFrame = MUTEFRAME_SEEK; data->muteFrame = MUTEFRAME_SEEK;
while (i < data->highestFrame && dc->seekWhere > while (j < data->highestFrame && dc->seekWhere >
((float)mad_timer_count(data->times[i], ((float)mad_timer_count(data->times[j],
MAD_UNITS_MILLISECONDS)) MAD_UNITS_MILLISECONDS))
/ 1000) { / 1000) {
i++; j++;
} }
if (i < data->highestFrame) { if (j < data->highestFrame) {
if (seekMp3InputBuffer(data, if (seekMp3InputBuffer(data,
data->frameOffset[i]) == data->frameOffset[j]) ==
0) { 0) {
data->outputPtr = data->outputBuffer; data->outputPtr = data->outputBuffer;
clearOutputBuffer(cb); clearOutputBuffer(cb);
data->currentFrame = i; data->currentFrame = j;
} else } else
dc->seekError = 1; dc->seekError = 1;
data->muteFrame = 0; data->muteFrame = 0;
...@@ -1078,7 +1075,7 @@ static char *mp3_mimeTypes[] = { "audio/mpeg", NULL }; ...@@ -1078,7 +1075,7 @@ static char *mp3_mimeTypes[] = { "audio/mpeg", NULL };
InputPlugin mp3Plugin = { InputPlugin mp3Plugin = {
"mp3", "mp3",
NULL, mp3_plugin_init,
NULL, NULL,
NULL, NULL,
mp3_decode, mp3_decode,
...@@ -1090,17 +1087,6 @@ InputPlugin mp3Plugin = { ...@@ -1090,17 +1087,6 @@ InputPlugin mp3Plugin = {
}; };
#else #else
InputPlugin mp3Plugin = { InputPlugin mp3Plugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL
};
#endif #endif /* HAVE_MAD */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -100,7 +100,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path) ...@@ -100,7 +100,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
faacDecConfigurationPtr config; faacDecConfigurationPtr config;
unsigned char *mp4Buffer; unsigned char *mp4Buffer;
unsigned int mp4BufferSize; unsigned int mp4BufferSize;
uint32_t sampleRate; unsigned long sampleRate;
unsigned char channels; unsigned char channels;
long sampleId; long sampleId;
long numSamples; long numSamples;
...@@ -450,17 +450,6 @@ InputPlugin mp4Plugin = { ...@@ -450,17 +450,6 @@ InputPlugin mp4Plugin = {
#else #else
InputPlugin mp4Plugin = { InputPlugin mp4Plugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL
};
#endif /* HAVE_FAAD */ #endif /* HAVE_FAAD */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -338,7 +338,6 @@ static MpdTag *mpcTagDup(char *file) ...@@ -338,7 +338,6 @@ static MpdTag *mpcTagDup(char *file)
} }
static char *mpcSuffixes[] = { "mpc", NULL }; static char *mpcSuffixes[] = { "mpc", NULL };
static char *mpcMimeTypes[] = { NULL };
InputPlugin mpcPlugin = { InputPlugin mpcPlugin = {
"mpc", "mpc",
...@@ -350,22 +349,11 @@ InputPlugin mpcPlugin = { ...@@ -350,22 +349,11 @@ InputPlugin mpcPlugin = {
mpcTagDup, mpcTagDup,
INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE, INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
mpcSuffixes, mpcSuffixes,
mpcMimeTypes NULL
}; };
#else #else
InputPlugin mpcPlugin = { InputPlugin mpcPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL
};
#endif #endif /* HAVE_MPCDEC */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* OggFLAC support (half-stolen from flac_plugin.c :)) * OggFLAC support (half-stolen from flac_plugin.c :))
...@@ -19,11 +19,10 @@ ...@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "../inputPlugin.h" #include "_flac_common.h"
#ifdef HAVE_OGGFLAC #ifdef HAVE_OGGFLAC
#include "_flac_common.h"
#include "_ogg_common.h" #include "_ogg_common.h"
#include "../utils.h" #include "../utils.h"
...@@ -37,8 +36,6 @@ ...@@ -37,8 +36,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <OggFLAC/seekable_stream_decoder.h>
#include <FLAC/metadata.h>
static void oggflac_cleanup(InputStream * inStream, static void oggflac_cleanup(InputStream * inStream,
FlacData * data, FlacData * data,
...@@ -401,7 +398,10 @@ fail: ...@@ -401,7 +398,10 @@ fail:
} }
static char *oggflac_Suffixes[] = { "ogg", NULL }; static char *oggflac_Suffixes[] = { "ogg", NULL };
static char *oggflac_mime_types[] = { "application/ogg", NULL }; static char *oggflac_mime_types[] = { "audio/x-flac+ogg",
"application/ogg",
"application/x-ogg",
NULL };
InputPlugin oggflacPlugin = { InputPlugin oggflacPlugin = {
"oggflac", "oggflac",
...@@ -418,17 +418,6 @@ InputPlugin oggflacPlugin = { ...@@ -418,17 +418,6 @@ InputPlugin oggflacPlugin = {
#else /* !HAVE_FLAC */ #else /* !HAVE_FLAC */
InputPlugin oggflacPlugin = { InputPlugin oggflacPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
};
#endif /* HAVE_OGGFLAC */ #endif /* HAVE_OGGFLAC */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -409,7 +409,10 @@ static unsigned int oggvorbis_try_decode(InputStream * inStream) ...@@ -409,7 +409,10 @@ static unsigned int oggvorbis_try_decode(InputStream * inStream)
} }
static char *oggvorbis_Suffixes[] = { "ogg", NULL }; static char *oggvorbis_Suffixes[] = { "ogg", NULL };
static char *oggvorbis_MimeTypes[] = { "application/ogg", NULL }; static char *oggvorbis_MimeTypes[] = { "application/ogg",
"audio/x-vorbis+ogg",
"application/x-ogg",
NULL };
InputPlugin oggvorbisPlugin = { InputPlugin oggvorbisPlugin = {
"oggvorbis", "oggvorbis",
...@@ -426,17 +429,6 @@ InputPlugin oggvorbisPlugin = { ...@@ -426,17 +429,6 @@ InputPlugin oggvorbisPlugin = {
#else /* !HAVE_OGGVORBIS */ #else /* !HAVE_OGGVORBIS */
InputPlugin oggvorbisPlugin = { InputPlugin oggvorbisPlugin;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
};
#endif /* HAVE_OGGVORBIS */ #endif /* HAVE_OGGVORBIS */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#define _XOPEN_SOURCE 600
#include <fcntl.h>
void inputStream_initFile(void) void inputStream_initFile(void)
{ {
...@@ -46,6 +48,10 @@ int inputStream_fileOpen(InputStream * inStream, char *filename) ...@@ -46,6 +48,10 @@ int inputStream_fileOpen(InputStream * inStream, char *filename)
inStream->size = ftell(fp); inStream->size = ftell(fp);
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
#ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(fileno(fp), (off_t)0, inStream->size, POSIX_FADV_SEQUENTIAL);
#endif
inStream->data = fp; inStream->data = fp;
inStream->seekFunc = inputStream_fileSeek; inStream->seekFunc = inputStream_fileSeek;
inStream->closeFunc = inputStream_fileClose; inStream->closeFunc = inputStream_fileClose;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -47,10 +47,10 @@ ...@@ -47,10 +47,10 @@
#define HTTP_REDIRECT_MAX 10 #define HTTP_REDIRECT_MAX 10
static char *proxyHost = NULL; static char *proxyHost;
static char *proxyPort = NULL; static char *proxyPort;
static char *proxyUser = NULL; static char *proxyUser;
static char *proxyPassword = NULL; static char *proxyPassword;
static int bufferSize = HTTP_BUFFER_SIZE_DEFAULT; static int bufferSize = HTTP_BUFFER_SIZE_DEFAULT;
static int prebufferSize = HTTP_PREBUFFER_SIZE_DEFAULT; static int prebufferSize = HTTP_PREBUFFER_SIZE_DEFAULT;
...@@ -81,9 +81,8 @@ void inputStream_initHttp(void) ...@@ -81,9 +81,8 @@ void inputStream_initHttp(void)
param = getConfigParam(CONF_HTTP_PROXY_PORT); param = getConfigParam(CONF_HTTP_PROXY_PORT);
if (!param) { if (!param) {
ERROR("%s specified but not %s", CONF_HTTP_PROXY_HOST, FATAL("%s specified but not %s", CONF_HTTP_PROXY_HOST,
CONF_HTTP_PROXY_PORT); CONF_HTTP_PROXY_PORT);
exit(EXIT_FAILURE);
} }
proxyPort = param->value; proxyPort = param->value;
...@@ -95,35 +94,30 @@ void inputStream_initHttp(void) ...@@ -95,35 +94,30 @@ void inputStream_initHttp(void)
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD); param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
if (!param) { if (!param) {
ERROR("%s specified but not %s\n", FATAL("%s specified but not %s\n",
CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_USER,
CONF_HTTP_PROXY_PASSWORD); CONF_HTTP_PROXY_PASSWORD);
exit(EXIT_FAILURE);
} }
proxyPassword = param->value; proxyPassword = param->value;
} } else {
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
if (param) { if (param) {
ERROR("%s specified but not %s\n", FATAL("%s specified but not %s\n",
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER); CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
exit(EXIT_FAILURE); }
} }
} else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) { } else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
ERROR("%s specified but not %s, line %i\n", FATAL("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, param->line); CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, param->line);
exit(EXIT_FAILURE);
} else if ((param = getConfigParam(CONF_HTTP_PROXY_USER))) { } else if ((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
ERROR("%s specified but not %s, line %i\n", FATAL("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, param->line); CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, param->line);
exit(EXIT_FAILURE);
} else if ((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) { } else if ((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
ERROR("%s specified but not %s, line %i\n", FATAL("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST, CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
param->line); param->line);
exit(EXIT_FAILURE);
} }
param = getConfigParam(CONF_HTTP_BUFFER_SIZE); param = getConfigParam(CONF_HTTP_BUFFER_SIZE);
...@@ -132,10 +126,9 @@ void inputStream_initHttp(void) ...@@ -132,10 +126,9 @@ void inputStream_initHttp(void)
bufferSize = strtol(param->value, &test, 10); bufferSize = strtol(param->value, &test, 10);
if (bufferSize <= 0 || *test != '\0') { if (bufferSize <= 0 || *test != '\0') {
ERROR("\"%s\" specified for %s at line %i is not a " FATAL("\"%s\" specified for %s at line %i is not a "
"positive integer\n", "positive integer\n",
param->value, CONF_HTTP_BUFFER_SIZE, param->line); param->value, CONF_HTTP_BUFFER_SIZE, param->line);
exit(EXIT_FAILURE);
} }
bufferSize *= 1024; bufferSize *= 1024;
...@@ -150,11 +143,10 @@ void inputStream_initHttp(void) ...@@ -150,11 +143,10 @@ void inputStream_initHttp(void)
prebufferSize = strtol(param->value, &test, 10); prebufferSize = strtol(param->value, &test, 10);
if (prebufferSize <= 0 || *test != '\0') { if (prebufferSize <= 0 || *test != '\0') {
ERROR("\"%s\" specified for %s at line %i is not a " FATAL("\"%s\" specified for %s at line %i is not a "
"positive integer\n", "positive integer\n",
param->value, CONF_HTTP_PREBUFFER_SIZE, param->value, CONF_HTTP_PREBUFFER_SIZE,
param->line); param->line);
exit(EXIT_FAILURE);
} }
prebufferSize *= 1024; prebufferSize *= 1024;
...@@ -446,7 +438,8 @@ static int finishHTTPInit(InputStream * inStream) ...@@ -446,7 +438,8 @@ static int finishHTTPInit(InputStream * inStream)
int error; int error;
socklen_t error_len = sizeof(int); socklen_t error_len = sizeof(int);
int ret; int ret;
char request[2049]; int length;
char request[2048];
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
...@@ -463,42 +456,41 @@ static int finishHTTPInit(InputStream * inStream) ...@@ -463,42 +456,41 @@ static int finishHTTPInit(InputStream * inStream)
if (ret < 0) { if (ret < 0) {
DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno)); DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno));
close(data->sock); goto close_err;
data->connState = HTTP_CONN_STATE_CLOSED;
return -1;
} }
getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len); getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len);
if (error) { if (error)
close(data->sock); goto close_err;
data->connState = HTTP_CONN_STATE_CLOSED;
return -1;
}
memset(request, 0, 2049);
/* deal with ICY metadata later, for now its fucking up stuff! */ /* deal with ICY metadata later, for now its fucking up stuff! */
snprintf(request, 2048, "GET %s HTTP/1.0\r\n" "Host: %s\r\n" length = snprintf(request, sizeof(request),
/*"Connection: close\r\n" */ "GET %s HTTP/1.1\r\n" "Host: %s\r\n"
"User-Agent: %s/%s\r\n" /*"Connection: close\r\n" */
/*"Range: bytes=%ld-\r\n" */ "User-Agent: %s/%s\r\n"
"%s" /* authorization */ "Range: bytes=%ld-\r\n"
"Icy-Metadata:1\r\n" "%s" /* authorization */
"\r\n", data->path, data->host, PACKAGE_NAME, PACKAGE_VERSION, "Icy-Metadata:1\r\n"
/*inStream->offset, */ "\r\n",
data->proxyAuth ? data->proxyAuth : data->path, data->host,
(data->httpAuth ? data->httpAuth : "") PACKAGE_NAME, PACKAGE_VERSION,
); inStream->offset,
data->proxyAuth ? data->proxyAuth :
ret = write(data->sock, request, strlen(request)); (data->httpAuth ? data->httpAuth : ""));
if (ret != strlen(request)) {
close(data->sock); if (length >= sizeof(request))
data->connState = HTTP_CONN_STATE_CLOSED; goto close_err;
return -1; ret = write(data->sock, request, length);
} if (ret != length)
goto close_err;
data->connState = HTTP_CONN_STATE_HELLO; data->connState = HTTP_CONN_STATE_HELLO;
return 0; return 0;
close_err:
close(data->sock);
data->connState = HTTP_CONN_STATE_CLOSED;
return -1;
} }
static int getHTTPHello(InputStream * inStream) static int getHTTPHello(InputStream * inStream)
...@@ -681,9 +673,6 @@ static int getHTTPHello(InputStream * inStream) ...@@ -681,9 +673,6 @@ static int getHTTPHello(InputStream * inStream)
data->prebuffer = 1; data->prebuffer = 1;
/*mark as unseekable till we actually implement seeking */
inStream->seekable = 0;
return 0; return 0;
} }
...@@ -714,21 +703,33 @@ int inputStream_httpOpen(InputStream * inStream, char *url) ...@@ -714,21 +703,33 @@ int inputStream_httpOpen(InputStream * inStream, char *url)
int inputStream_httpSeek(InputStream * inStream, long offset, int whence) int inputStream_httpSeek(InputStream * inStream, long offset, int whence)
{ {
/* hack to reopen an HTTP stream if we're trying to seek to InputStreamHTTPData *data;
* the beginning */
if ((whence == SEEK_SET) && (offset == 0)) {
InputStreamHTTPData *data;
data = (InputStreamHTTPData *) inStream->data; if (!inStream->seekable)
close(data->sock); return -1;
data->connState = HTTP_CONN_STATE_REOPEN;
data->buflen = 0; switch (whence) {
inStream->offset = 0; case SEEK_SET:
return 0; inStream->offset = offset;
break;
case SEEK_CUR:
inStream->offset += offset;
break;
case SEEK_END:
inStream->offset = inStream->size + offset;
break;
default:
return -1;
} }
/* otherwise, we don't know how to seek in HTTP yet */ data = (InputStreamHTTPData *)inStream->data;
return -1; close(data->sock);
data->connState = HTTP_CONN_STATE_REOPEN;
data->buflen = 0;
inputStream_httpBuffer(inStream);
return 0;
} }
static void parseIcyMetadata(InputStream * inStream, char *metadata, int size) static void parseIcyMetadata(InputStream * inStream, char *metadata, int size)
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "permission.h" #include "permission.h"
#include "sllist.h" #include "sllist.h"
#include "utils.h" #include "utils.h"
#include "ioops.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -55,20 +56,23 @@ ...@@ -55,20 +56,23 @@
#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024) #define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024)
/* set this to zero to indicate we have no possible interfaces */ /* set this to zero to indicate we have no possible interfaces */
static int interface_max_connections = 0; /*INTERFACE_MAX_CONNECTIONS_DEFAULT; */ static int interface_max_connections; /*INTERFACE_MAX_CONNECTIONS_DEFAULT; */
static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT; static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT;
static size_t interface_max_command_list_size = static size_t interface_max_command_list_size =
INTERFACE_MAX_COMMAND_LIST_DEFAULT; INTERFACE_MAX_COMMAND_LIST_DEFAULT;
static size_t interface_max_output_buffer_size = static size_t interface_max_output_buffer_size =
INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT; INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT;
/* List of registered external IO handlers */
static struct ioOps *ioList;
/* maybe make conf option for this, or... 32 might be good enough */ /* maybe make conf option for this, or... 32 might be good enough */
static long int interface_list_cache_size = 32; static long int interface_list_cache_size = 32;
/* shared globally between all interfaces: */ /* shared globally between all interfaces: */
static struct strnode *list_cache = NULL; static struct strnode *list_cache;
static struct strnode *list_cache_head = NULL; static struct strnode *list_cache_head;
static struct strnode *list_cache_tail = NULL; static struct strnode *list_cache_tail;
typedef struct _Interface { typedef struct _Interface {
char buffer[INTERFACE_MAX_BUFFER_LENGTH]; char buffer[INTERFACE_MAX_BUFFER_LENGTH];
...@@ -94,7 +98,7 @@ typedef struct _Interface { ...@@ -94,7 +98,7 @@ typedef struct _Interface {
int send_buf_alloc; /* bytes actually allocated */ int send_buf_alloc; /* bytes actually allocated */
} Interface; } Interface;
static Interface *interfaces = NULL; static Interface *interfaces;
static void flushInterfaceBuffer(Interface * interface); static void flushInterfaceBuffer(Interface * interface);
...@@ -489,6 +493,7 @@ int doIOForInterfaces(void) ...@@ -489,6 +493,7 @@ int doIOForInterfaces(void)
{ {
fd_set rfds; fd_set rfds;
fd_set wfds; fd_set wfds;
fd_set efds;
struct timeval tv; struct timeval tv;
int i; int i;
int selret; int selret;
...@@ -500,12 +505,43 @@ int doIOForInterfaces(void) ...@@ -500,12 +505,43 @@ int doIOForInterfaces(void)
while (1) { while (1) {
fdmax = 0; fdmax = 0;
FD_ZERO( &rfds );
FD_ZERO( &wfds );
FD_ZERO( &efds );
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds, &fdmax); addInterfacesReadyToReadAndListenSocketToFdSet(&rfds, &fdmax);
addInterfacesForBufferFlushToFdSet(&wfds, &fdmax); addInterfacesForBufferFlushToFdSet(&wfds, &fdmax);
selret = select(fdmax + 1, &rfds, &wfds, NULL, &tv); /* Add fds for all registered IO handlers */
if( ioList ) {
struct ioOps *o = ioList;
while( o ) {
struct ioOps *current = o;
int fdnum;
assert( current->fdset );
fdnum = current->fdset( &rfds, &wfds, &efds );
if( fdmax < fdnum )
fdmax = fdnum;
o = o->next;
}
}
selret = select(fdmax + 1, &rfds, &wfds, &efds, &tv);
if (selret < 0 && errno == EINTR)
break;
/* Consume fds for all registered IO handlers */
if( ioList ) {
struct ioOps *o = ioList;
while( o ) {
struct ioOps *current = o;
assert( current->consume );
selret = current->consume( selret, &rfds, &wfds, &efds );
o = o->next;
}
}
if (selret == 0 || (selret < 0 && errno == EINTR)) if (selret == 0)
break; break;
if (selret < 0) { if (selret < 0) {
...@@ -549,10 +585,9 @@ void initInterfaces(void) ...@@ -549,10 +585,9 @@ void initInterfaces(void)
if (param) { if (param) {
interface_timeout = strtol(param->value, &test, 10); interface_timeout = strtol(param->value, &test, 10);
if (*test != '\0' || interface_timeout <= 0) { if (*test != '\0' || interface_timeout <= 0) {
ERROR("connection timeout \"%s\" is not a positive " FATAL("connection timeout \"%s\" is not a positive "
"integer, line %i\n", CONF_CONN_TIMEOUT, "integer, line %i\n", CONF_CONN_TIMEOUT,
param->line); param->line);
exit(EXIT_FAILURE);
} }
} }
...@@ -561,9 +596,8 @@ void initInterfaces(void) ...@@ -561,9 +596,8 @@ void initInterfaces(void)
if (param) { if (param) {
interface_max_connections = strtol(param->value, &test, 10); interface_max_connections = strtol(param->value, &test, 10);
if (*test != '\0' || interface_max_connections <= 0) { if (*test != '\0' || interface_max_connections <= 0) {
ERROR("max connections \"%s\" is not a positive integer" FATAL("max connections \"%s\" is not a positive integer"
", line %i\n", param->value, param->line); ", line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
} else } else
interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT; interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT;
...@@ -574,9 +608,8 @@ void initInterfaces(void) ...@@ -574,9 +608,8 @@ void initInterfaces(void)
interface_max_command_list_size = strtol(param->value, interface_max_command_list_size = strtol(param->value,
&test, 10); &test, 10);
if (*test != '\0' || interface_max_command_list_size <= 0) { if (*test != '\0' || interface_max_command_list_size <= 0) {
ERROR("max command list size \"%s\" is not a positive " FATAL("max command list size \"%s\" is not a positive "
"integer, line %i\n", param->value, param->line); "integer, line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
interface_max_command_list_size *= 1024; interface_max_command_list_size *= 1024;
} }
...@@ -587,9 +620,8 @@ void initInterfaces(void) ...@@ -587,9 +620,8 @@ void initInterfaces(void)
interface_max_output_buffer_size = strtol(param->value, interface_max_output_buffer_size = strtol(param->value,
&test, 10); &test, 10);
if (*test != '\0' || interface_max_output_buffer_size <= 0) { if (*test != '\0' || interface_max_output_buffer_size <= 0) {
ERROR("max output buffer size \"%s\" is not a positive " FATAL("max output buffer size \"%s\" is not a positive "
"integer, line %i\n", param->value, param->line); "integer, line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
interface_max_output_buffer_size *= 1024; interface_max_output_buffer_size *= 1024;
} }
...@@ -696,7 +728,7 @@ static void flushInterfaceBuffer(Interface * interface) ...@@ -696,7 +728,7 @@ static void flushInterfaceBuffer(Interface * interface)
int interfacePrintWithFD(int fd, char *buffer, int buflen) int interfacePrintWithFD(int fd, char *buffer, int buflen)
{ {
static int i = 0; static int i;
int copylen; int copylen;
Interface *interface; Interface *interface;
...@@ -795,3 +827,25 @@ static void printInterfaceOutBuffer(Interface * interface) ...@@ -795,3 +827,25 @@ static void printInterfaceOutBuffer(Interface * interface)
interface->send_buf_used = 0; interface->send_buf_used = 0;
} }
/* From ioops.h: */
void registerIO( struct ioOps *ops )
{
assert( ops != NULL );
ops->next = ioList;
ioList = ops;
ops->prev = NULL;
if( ops->next )
ops->next->prev = ops;
}
void deregisterIO( struct ioOps *ops )
{
assert( ops != NULL );
if( ioList == ops )
ioList = ops->next;
else if( ops->prev != NULL )
ops->prev->next = ops->next;
}
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD)
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef IOOPS_H
#define IOOPS_H
#include <sys/select.h>
struct ioOps {
struct ioOps *prev, *next;
/*
* Called before each 'select' statement.
* To register for IO, call FD_SET for each required queue
* Return the highest fd number you registered
*/
int (*fdset) ( fd_set *rfds, fd_set *wfds, fd_set *efds );
/*
* Called after each 'select' statement.
* fdCount is the number of fds total in all sets. It may be 0.
* For each fd you registered for in (fdset), you should FD_CLR it from the
* appropriate queue(s).
* Return the total number of fds left in all sets (Ie, return fdCount
* minus the number of times you called FD_CLR).
*/
int (*consume) ( int fdCount, fd_set *rfds, fd_set *wfds, fd_set *efds );
};
/* Call this to register your io operation handler struct */
void registerIO( struct ioOps *ops );
/* Call this to deregister your io operation handler struct */
void deregisterIO( struct ioOps *ops );
#endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -53,7 +53,7 @@ typedef struct _List { ...@@ -53,7 +53,7 @@ typedef struct _List {
ListNode **nodesArray; ListNode **nodesArray;
/* sorted */ /* sorted */
int sorted; int sorted;
/* weather to strdup() key's on insertion */ /* whether to strdup() key's on insertion */
int strdupKeys; int strdupKeys;
} List; } List;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -41,17 +41,19 @@ ...@@ -41,17 +41,19 @@
#define DEFAULT_PORT 6600 #define DEFAULT_PORT 6600
#define BINDERROR() do { \ #define BINDERROR() do { \
ERROR("unable to bind port %u: %s\n", port, strerror(errno)); \ FATAL("unable to bind port %u: %s\n" \
ERROR("maybe MPD is still running?\n"); \ "maybe MPD is still running?\n", \
port, strerror(errno)); \
} while (0); } while (0);
int *listenSockets = NULL; static int *listenSockets;
int numberOfListenSockets = 0; static int numberOfListenSockets;
static int boundPort;
static int establishListen(unsigned int port, static int establishListen(unsigned int port,
struct sockaddr *addrp, socklen_t addrlen) struct sockaddr *addrp, socklen_t addrlen)
{ {
int pf; int pf = 0;
int sock; int sock;
int allowReuse = ALLOW_REUSE; int allowReuse = ALLOW_REUSE;
...@@ -68,25 +70,20 @@ static int establishListen(unsigned int port, ...@@ -68,25 +70,20 @@ static int establishListen(unsigned int port,
pf = PF_UNIX; pf = PF_UNIX;
break; break;
default: default:
ERROR("unknown address family: %i\n", addrp->sa_family); FATAL("unknown address family: %i\n", addrp->sa_family);
exit(EXIT_FAILURE);
} }
if ((sock = socket(pf, SOCK_STREAM, 0)) < 0) { if ((sock = socket(pf, SOCK_STREAM, 0)) < 0)
ERROR("socket < 0\n"); FATAL("socket < 0\n");
exit(EXIT_FAILURE);
}
if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) { if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
ERROR("problems setting nonblocking on listen socket: %s\n", FATAL("problems setting nonblocking on listen socket: %s\n",
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE);
} }
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&allowReuse, if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&allowReuse,
sizeof(allowReuse)) < 0) { sizeof(allowReuse)) < 0) {
ERROR("problems setsockopt'ing: %s\n", strerror(errno)); FATAL("problems setsockopt'ing: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} }
if (bind(sock, addrp, addrlen) < 0) { if (bind(sock, addrp, addrlen) < 0) {
...@@ -94,10 +91,8 @@ static int establishListen(unsigned int port, ...@@ -94,10 +91,8 @@ static int establishListen(unsigned int port,
return -1; return -1;
} }
if (listen(sock, 5) < 0) { if (listen(sock, 5) < 0)
ERROR("problems listen'ing: %s\n", strerror(errno)); FATAL("problems listen'ing: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
numberOfListenSockets++; numberOfListenSockets++;
listenSockets = listenSockets =
...@@ -110,8 +105,8 @@ static int establishListen(unsigned int port, ...@@ -110,8 +105,8 @@ static int establishListen(unsigned int port,
static void parseListenConfigParam(unsigned int port, ConfigParam * param) static void parseListenConfigParam(unsigned int port, ConfigParam * param)
{ {
struct sockaddr *addrp; struct sockaddr *addrp = NULL;
socklen_t addrlen; socklen_t addrlen = 0;
struct sockaddr_in sin; struct sockaddr_in sin;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
...@@ -132,10 +127,8 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) ...@@ -132,10 +127,8 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param)
sin6.sin6_addr = in6addr_any; sin6.sin6_addr = in6addr_any;
addrp = (struct sockaddr *)&sin6; addrp = (struct sockaddr *)&sin6;
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
if (establishListen(port, addrp, addrlen) < 0) { if (establishListen(port, addrp, addrlen) < 0)
BINDERROR(); BINDERROR();
exit(EXIT_FAILURE);
}
} }
#endif #endif
sin.sin_addr.s_addr = INADDR_ANY; sin.sin_addr.s_addr = INADDR_ANY;
...@@ -147,24 +140,21 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) ...@@ -147,24 +140,21 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param)
if (establishListen(port, addrp, addrlen) < 0) { if (establishListen(port, addrp, addrlen) < 0) {
#endif #endif
BINDERROR(); BINDERROR();
exit(EXIT_FAILURE);
} }
} else { } else {
struct hostent *he; struct hostent *he;
DEBUG("binding to address for %s\n", param->value); DEBUG("binding to address for %s\n", param->value);
if (!(he = gethostbyname(param->value))) { if (!(he = gethostbyname(param->value))) {
ERROR("can't lookup host \"%s\" at line %i\n", FATAL("can't lookup host \"%s\" at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
switch (he->h_addrtype) { switch (he->h_addrtype) {
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case AF_INET6: case AF_INET6:
if (!useIpv6) { if (!useIpv6) {
ERROR("no IPv6 support, but a IPv6 address " FATAL("no IPv6 support, but a IPv6 address "
"found for \"%s\" at line %i\n", "found for \"%s\" at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
memcpy((char *)&sin6.sin6_addr.s6_addr, memcpy((char *)&sin6.sin6_addr.s6_addr,
(char *)he->h_addr, he->h_length); (char *)he->h_addr, he->h_length);
...@@ -179,15 +169,12 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param) ...@@ -179,15 +169,12 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param)
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
break; break;
default: default:
ERROR("address type for \"%s\" is not IPv4 or IPv6 " FATAL("address type for \"%s\" is not IPv4 or IPv6 "
"at line %i\n", param->value, param->line); "at line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
if (establishListen(port, addrp, addrlen) < 0) { if (establishListen(port, addrp, addrlen) < 0)
BINDERROR(); BINDERROR();
exit(EXIT_FAILURE);
}
} }
} }
...@@ -195,22 +182,20 @@ void listenOnPort(void) ...@@ -195,22 +182,20 @@ void listenOnPort(void)
{ {
int port = DEFAULT_PORT; int port = DEFAULT_PORT;
ConfigParam *param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL); ConfigParam *param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL);
ConfigParam *portParam = getConfigParam(CONF_PORT);
{
ConfigParam *portParam = getConfigParam(CONF_PORT); if (portParam) {
char *test;
if (portParam) { port = strtol(portParam->value, &test, 10);
char *test; if (port <= 0 || *test != '\0') {
port = strtol(portParam->value, &test, 10); FATAL("%s \"%s\" specified at line %i is not a "
if (port <= 0 || *test != '\0') { "positive integer", CONF_PORT,
ERROR("%s \"%s\" specified at line %i is not a " portParam->value, portParam->line);
"positive integer", CONF_PORT,
portParam->value, portParam->line);
exit(EXIT_FAILURE);
}
} }
} }
boundPort = port;
do { do {
parseListenConfigParam(port, param); parseListenConfigParam(port, param);
} while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param))); } while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param)));
...@@ -266,3 +251,8 @@ void getConnections(fd_set * fds) ...@@ -266,3 +251,8 @@ void getConnections(fd_set * fds)
} }
} }
} }
int getBoundPort(void)
{
return boundPort;
}
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -36,4 +36,6 @@ void freeAllListenSockets(void); ...@@ -36,4 +36,6 @@ void freeAllListenSockets(void);
/* fdmax should be initialized to something */ /* fdmax should be initialized to something */
void addListenSocketsToFdSet(fd_set * fds, int *fdmax); void addListenSocketsToFdSet(fd_set * fds, int *fdmax);
int getBoundPort(void);
#endif #endif
/* the Music Player Daemon (MPD)
* (c)2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "locate.h"
#include "utils.h"
#define LOCATE_TAG_FILE_KEY "file"
#define LOCATE_TAG_FILE_KEY_OLD "filename"
#define LOCATE_TAG_ANY_KEY "any"
int getLocateTagItemType(char *str)
{
int i;
if (0 == strcasecmp(str, LOCATE_TAG_FILE_KEY) ||
0 == strcasecmp(str, LOCATE_TAG_FILE_KEY_OLD))
{
return LOCATE_TAG_FILE_TYPE;
}
if (0 == strcasecmp(str, LOCATE_TAG_ANY_KEY))
{
return LOCATE_TAG_ANY_TYPE;
}
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++)
{
if (0 == strcasecmp(str, mpdTagItemKeys[i]))
return i;
}
return -1;
}
static int initLocateTagItem(LocateTagItem * item, char *typeStr, char *needle)
{
item->tagType = getLocateTagItemType(typeStr);
if (item->tagType < 0)
return -1;
item->needle = xstrdup(needle);
return 0;
}
LocateTagItem *newLocateTagItem(char *typeStr, char *needle)
{
LocateTagItem *ret = xmalloc(sizeof(LocateTagItem));
if (initLocateTagItem(ret, typeStr, needle) < 0) {
free(ret);
ret = NULL;
}
return ret;
}
void freeLocateTagItemArray(int count, LocateTagItem * array)
{
int i;
for (i = 0; i < count; i++)
free(array[i].needle);
free(array);
}
int newLocateTagItemArrayFromArgArray(char *argArray[],
int numArgs, LocateTagItem ** arrayRet)
{
int i, j;
LocateTagItem *item;
if (numArgs == 0)
return 0;
if (numArgs % 2 != 0)
return -1;
*arrayRet = xmalloc(sizeof(LocateTagItem) * numArgs / 2);
for (i = 0, item = *arrayRet; i < numArgs / 2; i++, item++) {
if (initLocateTagItem
(item, argArray[i * 2], argArray[i * 2 + 1]) < 0)
goto fail;
}
return numArgs / 2;
fail:
for (j = 0; j < i; j++) {
free((*arrayRet)[j].needle);
}
free(*arrayRet);
*arrayRet = NULL;
return -1;
}
void freeLocateTagItem(LocateTagItem * item)
{
free(item->needle);
free(item);
}
static int strstrSearchTag(Song * song, int type, char *str)
{
int i;
char *dup;
int ret = 0;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
dup = strDupToUpper(getSongUrl(song));
if (strstr(dup, str))
ret = 1;
free(dup);
if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) {
return ret;
}
}
if (!song->tag)
return 0;
for (i = 0; i < song->tag->numOfItems && !ret; i++) {
if (type != LOCATE_TAG_ANY_TYPE &&
song->tag->items[i].type != type) {
continue;
}
dup = strDupToUpper(song->tag->items[i].value);
if (strstr(dup, str))
ret = 1;
free(dup);
}
return ret;
}
int strstrSearchTags(Song * song, int numItems, LocateTagItem * items)
{
int i;
for (i = 0; i < numItems; i++) {
if (!strstrSearchTag(song, items[i].tagType,
items[i].needle)) {
return 0;
}
}
return 1;
}
static int tagItemFoundAndMatches(Song * song, int type, char *str)
{
int i;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
if (0 == strcmp(str, getSongUrl(song)))
return 1;
if (type == LOCATE_TAG_FILE_TYPE)
return 0;
}
if (!song->tag)
return 0;
for (i = 0; i < song->tag->numOfItems; i++) {
if (type != LOCATE_TAG_ANY_TYPE &&
song->tag->items[i].type != type) {
continue;
}
if (0 == strcmp(str, song->tag->items[i].value))
return 1;
}
return 0;
}
int tagItemsFoundAndMatches(Song * song, int numItems, LocateTagItem * items)
{
int i;
for (i = 0; i < numItems; i++) {
if (!tagItemFoundAndMatches(song, items[i].tagType,
items[i].needle)) {
return 0;
}
}
return 1;
}
/* the Music Player Daemon (MPD)
* (c)2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "song.h"
#define LOCATE_TAG_FILE_TYPE TAG_NUM_OF_ITEM_TYPES+10
#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20
/* struct used for search, find, list queries */
typedef struct _LocateTagItem {
mpd_sint8 tagType;
/* what we are looking for */
char *needle;
} LocateTagItem;
int getLocateTagItemType(char *str);
/* returns NULL if not a known type */
LocateTagItem *newLocateTagItem(char *typeString, char *needle);
/* return number of items or -1 on error */
int newLocateTagItemArrayFromArgArray(char *argArray[], int numArgs,
LocateTagItem ** arrayRet);
void freeLocateTagItemArray(int count, LocateTagItem * array);
void freeLocateTagItem(LocateTagItem * item);
int strstrSearchTags(Song * song, int numItems, LocateTagItem * items);
int tagItemsFoundAndMatches(Song * song, int numItems, LocateTagItem * items);
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -29,13 +29,13 @@ ...@@ -29,13 +29,13 @@
#include <time.h> #include <time.h>
static unsigned int logLevel = LOG_LEVEL_LOW; static unsigned int logLevel = LOG_LEVEL_LOW;
static int warningFlushed = 0; static int warningFlushed;
static int stdout_mode = 1; static int stdout_mode = 1;
static char *warningBuffer = NULL; static char *warningBuffer;
static int out_fd = -1; static int out_fd = -1;
static int err_fd = -1; static int err_fd = -1;
static const char *out_filename = NULL; static const char *out_filename;
static const char *err_filename = NULL; static const char *err_filename;
/* redirect stdin to /dev/null to work around a libao bug */ /* redirect stdin to /dev/null to work around a libao bug */
static void redirect_stdin(void) static void redirect_stdin(void)
...@@ -59,7 +59,7 @@ static void redirect_logs(void) ...@@ -59,7 +59,7 @@ static void redirect_logs(void)
static const char *log_date(void) static const char *log_date(void)
{ {
static char buf[16] = { '\0' }; static char buf[16];
time_t t = time(NULL); time_t t = time(NULL);
strftime(buf, 16, "%b %d %H:%M : ", localtime(&t)); strftime(buf, 16, "%b %d %H:%M : ", localtime(&t));
return buf; return buf;
...@@ -68,7 +68,7 @@ static const char *log_date(void) ...@@ -68,7 +68,7 @@ static const char *log_date(void)
#define BUFFER_LENGTH 4096 #define BUFFER_LENGTH 4096
static void buffer_warning(const char *fmt, va_list args) static void buffer_warning(const char *fmt, va_list args)
{ {
char buffer[BUFFER_LENGTH + 1]; char buffer[BUFFER_LENGTH];
char *tmp = buffer; char *tmp = buffer;
size_t len = BUFFER_LENGTH; size_t len = BUFFER_LENGTH;
...@@ -100,11 +100,10 @@ void flushWarningLog(void) ...@@ -100,11 +100,10 @@ void flushWarningLog(void)
if (warningBuffer != NULL) if (warningBuffer != NULL)
{ {
while (s != NULL) { while (s != NULL) {
char * next = strchr(s, '\n'); char *next = strchr(s, '\n');
if (next != NULL) { if (next == NULL) break;
*next = '\0'; *next = '\0';
next++; next++;
}
fprintf(stderr, "%s\n", s); fprintf(stderr, "%s\n", s);
s = next; s = next;
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "../config.h" #include "../config.h"
#include "utils.h" #include "utils.h"
#include "normalize.h" #include "normalize.h"
#include "zeroconf.h"
#include <stdio.h> #include <stdio.h>
#include <sys/select.h> #include <sys/select.h>
...@@ -65,7 +66,6 @@ typedef struct _Options { ...@@ -65,7 +66,6 @@ typedef struct _Options {
int daemon; int daemon;
int stdOutput; int stdOutput;
int createDB; int createDB;
int updateDB;
int verbose; int verbose;
} Options; } Options;
...@@ -126,7 +126,6 @@ static void usage(char *argv[]) ...@@ -126,7 +126,6 @@ static void usage(char *argv[])
(" --no-create-db don't create database, even if it doesn't exist\n"); (" --no-create-db don't create database, even if it doesn't exist\n");
ERROR(" --no-daemon don't detach from console\n"); ERROR(" --no-daemon don't detach from console\n");
ERROR(" --stdout print messages to stdout and stderr\n"); ERROR(" --stdout print messages to stdout and stderr\n");
/*ERROR(" --update-db create database and exit\n"); */
ERROR(" --verbose verbose logging\n"); ERROR(" --verbose verbose logging\n");
ERROR(" --version prints version information\n"); ERROR(" --version prints version information\n");
} }
...@@ -135,7 +134,7 @@ static void version(void) ...@@ -135,7 +134,7 @@ static void version(void)
{ {
LOG("mpd (MPD: Music Player Daemon) %s\n", VERSION); LOG("mpd (MPD: Music Player Daemon) %s\n", VERSION);
LOG("\n"); LOG("\n");
LOG("Copyright (C) 2003-2006 Warren Dukes <warren.dukes@gmail.com>\n"); LOG("Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n");
LOG("This is free software; see the source for copying conditions. There is NO\n"); LOG("This is free software; see the source for copying conditions. There is NO\n");
LOG("warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); LOG("warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
LOG("\n"); LOG("\n");
...@@ -158,7 +157,6 @@ static void parseOptions(int argc, char **argv, Options * options) ...@@ -158,7 +157,6 @@ static void parseOptions(int argc, char **argv, Options * options)
options->daemon = 1; options->daemon = 1;
options->stdOutput = 0; options->stdOutput = 0;
options->createDB = 0; options->createDB = 0;
options->updateDB = 0;
options->kill = 0; options->kill = 0;
if (argc > 1) { if (argc > 1) {
...@@ -248,15 +246,13 @@ static void changeToUser(void) ...@@ -248,15 +246,13 @@ static void changeToUser(void)
/* get uid */ /* get uid */
struct passwd *userpwd; struct passwd *userpwd;
if ((userpwd = getpwnam(param->value)) == NULL) { if ((userpwd = getpwnam(param->value)) == NULL) {
ERROR("no such user \"%s\" at line %i\n", param->value, FATAL("no such user \"%s\" at line %i\n", param->value,
param->line); param->line);
exit(EXIT_FAILURE);
} }
if (setgid(userpwd->pw_gid) == -1) { if (setgid(userpwd->pw_gid) == -1) {
ERROR("cannot setgid for user \"%s\" at line %i: %s\n", FATAL("cannot setgid for user \"%s\" at line %i: %s\n",
param->value, param->line, strerror(errno)); param->value, param->line, strerror(errno));
exit(EXIT_FAILURE);
} }
#ifdef _BSD_SOURCE #ifdef _BSD_SOURCE
/* init suplementary groups /* init suplementary groups
...@@ -271,10 +267,9 @@ static void changeToUser(void) ...@@ -271,10 +267,9 @@ static void changeToUser(void)
/* set uid */ /* set uid */
if (setuid(userpwd->pw_uid) == -1) { if (setuid(userpwd->pw_uid) == -1) {
ERROR("cannot change to uid of user " FATAL("cannot change to uid of user "
"\"%s\" at line %i: %s\n", "\"%s\" at line %i: %s\n",
param->value, param->line, strerror(errno)); param->value, param->line, strerror(errno));
exit(EXIT_FAILURE);
} }
/* this is needed by libs such as arts */ /* this is needed by libs such as arts */
...@@ -288,10 +283,9 @@ static void openDB(Options * options, char *argv0) ...@@ -288,10 +283,9 @@ static void openDB(Options * options, char *argv0)
{ {
if (options->createDB > 0 || readDirectoryDB() < 0) { if (options->createDB > 0 || readDirectoryDB() < 0) {
if (options->createDB < 0) { if (options->createDB < 0) {
ERROR("can't open db file and using \"--no-create-db\"" FATAL("can't open db file and using "
" command line option\n"); "\"--no-create-db\" command line option\n"
ERROR("try running \"%s --create-db\"\n", argv0); "try running \"%s --create-db\"\n", argv0);
exit(EXIT_FAILURE);
} }
flushWarningLog(); flushWarningLog();
if (checkDirectoryDB() < 0) if (checkDirectoryDB() < 0)
...@@ -302,11 +296,6 @@ static void openDB(Options * options, char *argv0) ...@@ -302,11 +296,6 @@ static void openDB(Options * options, char *argv0)
if (options->createDB) if (options->createDB)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (options->updateDB) {
flushWarningLog();
updateMp3Directory();
exit(EXIT_SUCCESS);
}
} }
static void daemonize(Options * options) static void daemonize(Options * options)
...@@ -320,11 +309,9 @@ static void daemonize(Options * options) ...@@ -320,11 +309,9 @@ static void daemonize(Options * options)
DEBUG("opening pid file\n"); DEBUG("opening pid file\n");
fp = fopen(pidFileParam->value, "w+"); fp = fopen(pidFileParam->value, "w+");
if (!fp) { if (!fp) {
ERROR FATAL("could not open %s \"%s\" (at line %i) for writing: %s\n",
("could not open %s \"%s\" (at line %i) for writing: %s\n",
CONF_PID_FILE, pidFileParam->value, CONF_PID_FILE, pidFileParam->value,
pidFileParam->line, strerror(errno)); pidFileParam->line, strerror(errno));
exit(EXIT_FAILURE);
} }
} }
...@@ -336,18 +323,15 @@ static void daemonize(Options * options) ...@@ -336,18 +323,15 @@ static void daemonize(Options * options)
if (pid > 0) if (pid > 0)
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
else if (pid < 0) { else if (pid < 0) {
ERROR("problems fork'ing for daemon!\n"); FATAL("problems fork'ing for daemon!\n");
exit(EXIT_FAILURE);
} }
if (chdir("/") < 0) { if (chdir("/") < 0) {
ERROR("problems changing to root directory\n"); FATAL("problems changing to root directory\n");
exit(EXIT_FAILURE);
} }
if (setsid() < 0) { if (setsid() < 0) {
ERROR("problems setsid'ing\n"); FATAL("problems setsid'ing\n");
exit(EXIT_FAILURE);
} }
fflush(NULL); fflush(NULL);
...@@ -355,8 +339,7 @@ static void daemonize(Options * options) ...@@ -355,8 +339,7 @@ static void daemonize(Options * options)
if (pid > 0) if (pid > 0)
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
else if (pid < 0) { else if (pid < 0) {
ERROR("problems fork'ing for daemon!\n"); FATAL("problems fork'ing for daemon!\n");
exit(EXIT_FAILURE);
} }
DEBUG("daemonized!\n"); DEBUG("daemonized!\n");
...@@ -388,26 +371,22 @@ static void killFromPidFile(char *cmd, int killOption) ...@@ -388,26 +371,22 @@ static void killFromPidFile(char *cmd, int killOption)
int pid; int pid;
if (!pidFileParam) { if (!pidFileParam) {
ERROR("no pid_file specified in the config file\n"); FATAL("no pid_file specified in the config file\n");
exit(EXIT_FAILURE);
} }
fp = fopen(pidFileParam->value, "r"); fp = fopen(pidFileParam->value, "r");
if (!fp) { if (!fp) {
ERROR("unable to open %s \"%s\": %s\n", FATAL("unable to open %s \"%s\": %s\n",
CONF_PID_FILE, pidFileParam->value, strerror(errno)); CONF_PID_FILE, pidFileParam->value, strerror(errno));
exit(EXIT_FAILURE);
} }
if (fscanf(fp, "%i", &pid) != 1) { if (fscanf(fp, "%i", &pid) != 1) {
ERROR("unable to read the pid from file \"%s\"\n", FATAL("unable to read the pid from file \"%s\"\n",
pidFileParam->value); pidFileParam->value);
exit(EXIT_FAILURE);
} }
fclose(fp); fclose(fp);
if (kill(pid, SIGTERM)) { if (kill(pid, SIGTERM)) {
ERROR("unable to kill proccess %i: %s\n", pid, strerror(errno)); FATAL("unable to kill proccess %i: %s\n", pid, strerror(errno));
exit(EXIT_FAILURE);
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -430,7 +409,7 @@ int main(int argc, char *argv[]) ...@@ -430,7 +409,7 @@ int main(int argc, char *argv[])
initTagConfig(); initTagConfig();
initLog(options.verbose); initLog(options.verbose);
if (options.createDB <= 0 && !options.updateDB) if (options.createDB <= 0)
listenOnPort(); listenOnPort();
changeToUser(); changeToUser();
...@@ -450,6 +429,7 @@ int main(int argc, char *argv[]) ...@@ -450,6 +429,7 @@ int main(int argc, char *argv[])
initAudioDriver(); initAudioDriver();
initVolume(); initVolume();
initInterfaces(); initInterfaces();
initZeroconf();
initReplayGainState(); initReplayGainState();
initNormalization(); initNormalization();
initInputStream(); initInputStream();
...@@ -475,6 +455,7 @@ int main(int argc, char *argv[]) ...@@ -475,6 +455,7 @@ int main(int argc, char *argv[])
write_state_file(); write_state_file();
playerKill(); playerKill();
finishZeroconf();
freeAllInterfaces(); freeAllInterfaces();
closeAllListenSockets(); closeAllListenSockets();
finishPlaylist(); finishPlaylist();
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -50,7 +50,7 @@ static void blockingWrite(const int fd, const char *string, size_t len) ...@@ -50,7 +50,7 @@ static void blockingWrite(const int fd, const char *string, size_t len)
void vfdprintf(const int fd, const char *fmt, va_list args) void vfdprintf(const int fd, const char *fmt, va_list args)
{ {
static char buffer[BUFFER_LENGTH + 1]; static char buffer[BUFFER_LENGTH];
char *buf = buffer; char *buf = buffer;
size_t len; size_t len;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
static mpd_sint16 currentChunk = -1; static mpd_sint16 currentChunk = -1;
static mpd_sint8 currentMetaChunk = -1; static mpd_sint8 currentMetaChunk = -1;
static mpd_sint8 sendMetaChunk = 0; static mpd_sint8 sendMetaChunk;
void clearAllMetaChunkSets(OutputBuffer * cb) void clearAllMetaChunkSets(OutputBuffer * cb)
{ {
...@@ -58,11 +58,10 @@ void clearOutputBuffer(OutputBuffer * cb) ...@@ -58,11 +58,10 @@ void clearOutputBuffer(OutputBuffer * cb)
void flushOutputBuffer(OutputBuffer * cb) void flushOutputBuffer(OutputBuffer * cb)
{ {
if (currentChunk == cb->end) { if (currentChunk == cb->end) {
int next = cb->end + 1; if ((cb->end + 1) >= buffered_chunks) {
if (next >= buffered_chunks) { cb->end = 0;
next = 0;
} }
cb->end = next; else cb->end++;
currentChunk = -1; currentChunk = -1;
} }
} }
...@@ -76,27 +75,23 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -76,27 +75,23 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
mpd_uint16 chunkLeft; mpd_uint16 chunkLeft;
char *data; char *data;
size_t datalen; size_t datalen;
static char *convBuffer = NULL; static char *convBuffer;
static long convBufferLen = 0; static long convBufferLen;
if (cmpAudioFormat(&(cb->audioFormat), &(dc->audioFormat)) == 0) { if (cmpAudioFormat(&(cb->audioFormat), &(dc->audioFormat)) == 0) {
data = dataIn; data = dataIn;
datalen = dataInLen; datalen = dataInLen;
} else { } else {
datalen = datalen = pcm_sizeOfConvBuffer(&(dc->audioFormat), dataInLen,
pcm_sizeOfOutputBufferForAudioFormatConversion(& &(cb->audioFormat));
(dc->
audioFormat),
dataInLen,
&(cb->
audioFormat));
if (datalen > convBufferLen) { if (datalen > convBufferLen) {
convBuffer = xrealloc(convBuffer, datalen); convBuffer = xrealloc(convBuffer, datalen);
convBufferLen = datalen; convBufferLen = datalen;
} }
data = convBuffer; data = convBuffer;
pcm_convertAudioFormat(&(dc->audioFormat), dataIn, dataInLen, datalen = pcm_convertAudioFormat(&(dc->audioFormat), dataIn,
&(cb->audioFormat), data); dataInLen, &(cb->audioFormat),
data, &(cb->convState));
} }
if (replayGainInfo && (replayGainState != REPLAYGAIN_OFF)) if (replayGainInfo && (replayGainState != REPLAYGAIN_OFF))
...@@ -158,7 +153,7 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -158,7 +153,7 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag)
{ {
int nextChunk; int nextChunk;
static MpdTag *last = NULL; static MpdTag *last;
if (!cb->acceptMetadata || !tag) { if (!cb->acceptMetadata || !tag) {
sendMetaChunk = 0; sendMetaChunk = 0;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#ifndef OUTPUT_BUFFER_H #ifndef OUTPUT_BUFFER_H
#define OUTPUT_BUFFER_H #define OUTPUT_BUFFER_H
#include "pcm_utils.h"
#include "mpd_types.h" #include "mpd_types.h"
#include "decode.h" #include "decode.h"
#include "audio.h" #include "audio.h"
...@@ -39,6 +40,7 @@ typedef struct _OutputBuffer { ...@@ -39,6 +40,7 @@ typedef struct _OutputBuffer {
mpd_sint16 volatile begin; mpd_sint16 volatile begin;
mpd_sint16 volatile end; mpd_sint16 volatile end;
AudioFormat audioFormat; AudioFormat audioFormat;
ConvState convState;
MetadataChunk metadataChunks[BUFFERED_METACHUNKS]; MetadataChunk metadataChunks[BUFFERED_METACHUNKS];
mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS]; mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS];
mpd_sint8 *volatile metaChunk; mpd_sint8 *volatile metaChunk;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
const char *musicDir; const char *musicDir;
static const char *playlistDir; static const char *playlistDir;
static char *fsCharset = NULL; static char *fsCharset;
static char *pathConvCharset(char *to, char *from, char *str, char *ret) static char *pathConvCharset(char *to, char *from, char *str, char *ret)
{ {
...@@ -51,7 +51,7 @@ static char *pathConvCharset(char *to, char *from, char *str, char *ret) ...@@ -51,7 +51,7 @@ static char *pathConvCharset(char *to, char *from, char *str, char *ret)
char *fsCharsetToUtf8(char *str) char *fsCharsetToUtf8(char *str)
{ {
static char *ret = NULL; static char *ret;
ret = pathConvCharset("UTF-8", fsCharset, str, ret); ret = pathConvCharset("UTF-8", fsCharset, str, ret);
...@@ -65,7 +65,7 @@ char *fsCharsetToUtf8(char *str) ...@@ -65,7 +65,7 @@ char *fsCharsetToUtf8(char *str)
char *utf8ToFsCharset(char *str) char *utf8ToFsCharset(char *str)
{ {
static char *ret = NULL; static char *ret;
ret = pathConvCharset(fsCharset, "UTF-8", str, ret); ret = pathConvCharset(fsCharset, "UTF-8", str, ret);
...@@ -142,18 +142,16 @@ void initPaths(void) ...@@ -142,18 +142,16 @@ void initPaths(void)
playlistDir = appendSlash(&(playlistParam->value)); playlistDir = appendSlash(&(playlistParam->value));
if ((dir = opendir(playlistDir)) == NULL) { if ((dir = opendir(playlistDir)) == NULL) {
ERROR("cannot open %s \"%s\" (config line %i): %s\n", FATAL("cannot open %s \"%s\" (config line %i): %s\n",
CONF_PLAYLIST_DIR, playlistParam->value, CONF_PLAYLIST_DIR, playlistParam->value,
playlistParam->line, strerror(errno)); playlistParam->line, strerror(errno));
exit(EXIT_FAILURE);
} }
closedir(dir); closedir(dir);
if ((dir = opendir(musicDir)) == NULL) { if ((dir = opendir(musicDir)) == NULL) {
ERROR("cannot open %s \"%s\" (config line %i): %s\n", FATAL("cannot open %s \"%s\" (config line %i): %s\n",
CONF_MUSIC_DIR, musicParam->value, CONF_MUSIC_DIR, musicParam->value,
musicParam->line, strerror(errno)); musicParam->line, strerror(errno));
exit(EXIT_FAILURE);
} }
closedir(dir); closedir(dir);
...@@ -281,12 +279,12 @@ char *sanitizePathDup(char *path) ...@@ -281,12 +279,12 @@ char *sanitizePathDup(char *path)
len = 0; len = 0;
/* illeminate more than one '/' in a row, like "///" */ /* eliminate more than one '/' in a row, like "///" */
while (*path) { while (*path) {
while (*path == '/') while (*path == '/')
path++; path++;
if (*path == '.') { if (*path == '.') {
/* we dont want to have hidden directoires, or '.' or /* we don't want to have hidden directories, or '.' or
".." in our path */ ".." in our path */
free(ret); free(ret);
return NULL; return NULL;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -21,13 +21,14 @@ ...@@ -21,13 +21,14 @@
#include "mpd_types.h" #include "mpd_types.h"
#include "log.h" #include "log.h"
#include "utils.h" #include "utils.h"
#include "conf.h"
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
int volume) int volume)
{ {
mpd_sint32 temp32; mpd_sint32 temp32;
mpd_sint8 *buffer8 = (mpd_sint8 *) buffer; mpd_sint8 *buffer8 = (mpd_sint8 *) buffer;
...@@ -46,6 +47,9 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, ...@@ -46,6 +47,9 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
while (bufferSize > 0) { while (bufferSize > 0) {
temp32 = *buffer16; temp32 = *buffer16;
temp32 *= volume; temp32 *= volume;
temp32 += rand() & 511;
temp32 -= rand() & 511;
temp32 += 500;
temp32 /= 1000; temp32 /= 1000;
*buffer16 = temp32 > 32767 ? 32767 : *buffer16 = temp32 > 32767 ? 32767 :
(temp32 < -32768 ? -32768 : temp32); (temp32 < -32768 ? -32768 : temp32);
...@@ -57,6 +61,9 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, ...@@ -57,6 +61,9 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
while (bufferSize > 0) { while (bufferSize > 0) {
temp32 = *buffer8; temp32 = *buffer8;
temp32 *= volume; temp32 *= volume;
temp32 += rand() & 511;
temp32 -= rand() & 511;
temp32 += 500;
temp32 /= 1000; temp32 /= 1000;
*buffer8 = temp32 > 127 ? 127 : *buffer8 = temp32 > 127 ? 127 :
(temp32 < -128 ? -128 : temp32); (temp32 < -128 ? -128 : temp32);
...@@ -65,15 +72,14 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, ...@@ -65,15 +72,14 @@ void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
} }
break; break;
default: default:
ERROR("%i bits not supported by pcm_volumeChange!\n", FATAL("%i bits not supported by pcm_volumeChange!\n",
format->bits); format->bits);
exit(EXIT_FAILURE);
} }
} }
static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, int vol1, int vol2, size_t bufferSize2, int vol1, int vol2,
AudioFormat * format) AudioFormat * format)
{ {
mpd_sint32 temp32; mpd_sint32 temp32;
mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1; mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1;
...@@ -86,7 +92,11 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, ...@@ -86,7 +92,11 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1,
while (bufferSize1 > 0 && bufferSize2 > 0) { while (bufferSize1 > 0 && bufferSize2 > 0) {
temp32 = temp32 =
(vol1 * (*buffer16_1) + (vol1 * (*buffer16_1) +
vol2 * (*buffer16_2)) / 1000; vol2 * (*buffer16_2));
temp32 += rand() & 511;
temp32 -= rand() & 511;
temp32 += 500;
temp32 /= 1000;
*buffer16_1 = *buffer16_1 =
temp32 > 32767 ? 32767 : (temp32 < temp32 > 32767 ? 32767 : (temp32 <
-32768 ? -32768 : temp32); -32768 ? -32768 : temp32);
...@@ -101,7 +111,11 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, ...@@ -101,7 +111,11 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1,
case 8: case 8:
while (bufferSize1 > 0 && bufferSize2 > 0) { while (bufferSize1 > 0 && bufferSize2 > 0) {
temp32 = temp32 =
(vol1 * (*buffer8_1) + vol2 * (*buffer8_2)) / 1000; (vol1 * (*buffer8_1) + vol2 * (*buffer8_2));
temp32 += rand() & 511;
temp32 -= rand() & 511;
temp32 += 500;
temp32 /= 1000;
*buffer8_1 = *buffer8_1 =
temp32 > 127 ? 127 : (temp32 < temp32 > 127 ? 127 : (temp32 <
-128 ? -128 : temp32); -128 ? -128 : temp32);
...@@ -114,13 +128,12 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1, ...@@ -114,13 +128,12 @@ static void pcm_add(char *buffer1, char *buffer2, size_t bufferSize1,
memcpy(buffer8_1, buffer8_2, bufferSize2); memcpy(buffer8_1, buffer8_2, bufferSize2);
break; break;
default: default:
ERROR("%i bits not supported by pcm_add!\n", format->bits); FATAL("%i bits not supported by pcm_add!\n", format->bits);
exit(EXIT_FAILURE);
} }
} }
void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1) size_t bufferSize2, AudioFormat * format, float portion1)
{ {
int vol1; int vol1;
float s = sin(M_PI_2 * portion1); float s = sin(M_PI_2 * portion1);
...@@ -133,166 +146,306 @@ void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1, ...@@ -133,166 +146,306 @@ void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1,
format); format);
} }
/* outFormat bits must be 16 and channels must be 2! */ #ifdef HAVE_LIBSAMPLERATE
void pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, size_t static int pcm_getSampleRateConverter(void)
inSize, AudioFormat * outFormat, char *outBuffer)
{ {
static char *bitConvBuffer = NULL; const char *conf = getConfigParamValue(CONF_SAMPLERATE_CONVERTER);
static int bitConvBufferLength = 0; long convalgo;
static char *channelConvBuffer = NULL; char *test;
static int channelConvBufferLength = 0; size_t len;
char *dataChannelConv;
int dataChannelLen;
char *dataBitConv;
int dataBitLen;
assert(outFormat->bits == 16); if (!conf) {
assert(outFormat->channels == 2 || outFormat->channels == 1); convalgo = SRC_SINC_FASTEST;
goto out;
}
/* converts */ convalgo = strtol(conf, &test, 10);
switch (inFormat->bits) { if (*test == '\0' && src_get_name(convalgo))
case 8: goto out;
dataBitLen = inSize << 1;
if (dataBitLen > bitConvBufferLength) { len = strlen(conf);
bitConvBuffer = xrealloc(bitConvBuffer, dataBitLen); for (convalgo = 0 ; ; convalgo++) {
bitConvBufferLength = dataBitLen; test = (char *)src_get_name(convalgo);
if (!test) {
convalgo = SRC_SINC_FASTEST;
break;
}
if (strncasecmp(test, conf, len) == 0)
goto out;
}
ERROR("unknown samplerate converter \"%s\"\n", conf);
out:
DEBUG("selecting samplerate converter \"%s\"\n",
src_get_name(convalgo));
return convalgo;
}
#endif
#ifdef HAVE_LIBSAMPLERATE
static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate,
char *inBuffer, size_t inSize,
mpd_uint32 outSampleRate, char *outBuffer,
size_t outSize, ConvState *convState)
{
static int convalgo = -1;
SRC_DATA *data = &convState->data;
size_t dataInSize;
size_t dataOutSize;
int error;
if (convalgo < 0)
convalgo = pcm_getSampleRateConverter();
/* (re)set the state/ratio if the in or out format changed */
if ((channels != convState->lastChannels) ||
(inSampleRate != convState->lastInSampleRate) ||
(outSampleRate != convState->lastOutSampleRate)) {
convState->error = 0;
convState->lastChannels = channels;
convState->lastInSampleRate = inSampleRate;
convState->lastOutSampleRate = outSampleRate;
if (convState->state)
convState->state = src_delete(convState->state);
convState->state = src_new(convalgo, channels, &error);
if (!convState->state) {
ERROR("cannot create new libsamplerate state: %s\n",
src_strerror(error));
convState->error = 1;
return 0;
}
data->src_ratio = (double)outSampleRate / (double)inSampleRate;
DEBUG("setting samplerate conversion ratio to %.2lf\n",
data->src_ratio);
src_set_ratio(convState->state, data->src_ratio);
}
/* there was an error previously, and nothing has changed */
if (convState->error)
return 0;
data->input_frames = inSize / 2 / channels;
dataInSize = data->input_frames * sizeof(float) * channels;
if (dataInSize > convState->dataInSize) {
convState->dataInSize = dataInSize;
data->data_in = xrealloc(data->data_in, dataInSize);
}
data->output_frames = outSize / 2 / channels;
dataOutSize = data->output_frames * sizeof(float) * channels;
if (dataOutSize > convState->dataOutSize) {
convState->dataOutSize = dataOutSize;
data->data_out = xrealloc(data->data_out, dataOutSize);
}
src_short_to_float_array((short *)inBuffer, data->data_in,
data->input_frames * channels);
error = src_process(convState->state, data);
if (error) {
ERROR("error processing samples with libsamplerate: %s\n",
src_strerror(error));
convState->error = 1;
return 0;
}
src_float_to_short_array(data->data_out, (short *)outBuffer,
data->output_frames_gen * channels);
return data->output_frames_gen * 2 * channels;
}
#else /* !HAVE_LIBSAMPLERATE */
/* resampling code blatantly ripped from ESD */
static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate,
char *inBuffer, size_t inSize,
mpd_uint32 outSampleRate, char *outBuffer,
size_t outSize, ConvState *convState)
{
mpd_uint32 rd_dat = 0;
mpd_uint32 wr_dat = 0;
mpd_sint16 *in = (mpd_sint16 *)inBuffer;
mpd_sint16 *out = (mpd_sint16 *)outBuffer;
mpd_uint32 nlen = outSize / 2;
mpd_sint16 lsample, rsample;
switch (channels) {
case 1:
while (wr_dat < nlen) {
rd_dat = wr_dat * inSampleRate / outSampleRate;
lsample = in[rd_dat++];
out[wr_dat++] = lsample;
}
break;
case 2:
while (wr_dat < nlen) {
rd_dat = wr_dat * inSampleRate / outSampleRate;
rd_dat &= ~1;
lsample = in[rd_dat++];
rsample = in[rd_dat++];
out[wr_dat++] = lsample;
out[wr_dat++] = rsample;
}
break;
}
return outSize;
}
#endif /* !HAVE_LIBSAMPLERATE */
static char *pcm_convertChannels(mpd_sint8 channels, char *inBuffer,
size_t inSize, size_t *outSize)
{
static char *buf;
static size_t len;
char *outBuffer = NULL;;
mpd_sint16 *in;
mpd_sint16 *out;
int inSamples, i;
switch (channels) {
/* convert from 1 -> 2 channels */
case 1:
*outSize = (inSize >> 1) << 2;
if (*outSize > len) {
len = *outSize;
buf = xrealloc(buf, len);
} }
dataBitConv = bitConvBuffer; outBuffer = buf;
{
mpd_sint8 *in = (mpd_sint8 *) inBuffer; inSamples = inSize >> 1;
mpd_sint16 *out = (mpd_sint16 *) dataBitConv; in = (mpd_sint16 *)inBuffer;
int i; out = (mpd_sint16 *)outBuffer;
for (i = 0; i < inSize; i++) { for (i = 0; i < inSamples; i++) {
*out++ = (*in++) << 8; *out++ = *in;
} *out++ = *in++;
}
break;
/* convert from 2 -> 1 channels */
case 2:
*outSize = inSize >> 1;
if (*outSize > len) {
len = *outSize;
buf = xrealloc(buf, len);
}
outBuffer = buf;
inSamples = inSize >> 2;
in = (mpd_sint16 *)inBuffer;
out = (mpd_sint16 *)outBuffer;
for (i = 0; i < inSamples; i++) {
*out = (*in++) / 2;
*out++ += (*in++) / 2;
}
break;
default:
ERROR("only 1 or 2 channels are supported for conversion!\n");
}
return outBuffer;
}
static char *pcm_convertTo16bit(mpd_sint8 bits, char *inBuffer, size_t inSize,
size_t *outSize)
{
static char *buf;
static size_t len;
char *outBuffer = NULL;
mpd_sint8 *in;
mpd_sint16 *out;
int i;
switch (bits) {
case 8:
*outSize = inSize << 1;
if (*outSize > len) {
len = *outSize;
buf = xrealloc(buf, len);
} }
outBuffer = buf;
in = (mpd_sint8 *)inBuffer;
out = (mpd_sint16 *)outBuffer;
for (i = 0; i < inSize; i++)
*out++ = (*in++) << 8;
break; break;
case 16: case 16:
dataBitConv = inBuffer; *outSize = inSize;
dataBitLen = inSize; outBuffer = inBuffer;
break; break;
case 24: case 24:
/* put dithering code from mp3_decode here */ /* put dithering code from mp3_decode here */
default: default:
ERROR("only 8 or 16 bits are supported for conversion!\n"); ERROR("only 8 or 16 bits are supported for conversion!\n");
exit(EXIT_FAILURE);
} }
/* converts only between 16 bit audio between mono and stereo */ return outBuffer;
if (inFormat->channels == outFormat->channels) { }
dataChannelConv = dataBitConv;
dataChannelLen = dataBitLen;
} else {
switch (inFormat->channels) {
/* convert from 1 -> 2 channels */
case 1:
dataChannelLen = (dataBitLen >> 1) << 2;
if (dataChannelLen > channelConvBufferLength) {
channelConvBuffer = xrealloc(channelConvBuffer,
dataChannelLen);
channelConvBufferLength = dataChannelLen;
}
dataChannelConv = channelConvBuffer;
{
mpd_sint16 *in = (mpd_sint16 *) dataBitConv;
mpd_sint16 *out =
(mpd_sint16 *) dataChannelConv;
int i, inSamples = dataBitLen >> 1;
for (i = 0; i < inSamples; i++) {
*out++ = *in;
*out++ = *in++;
}
}
break;
/* convert from 2 -> 1 channels */
case 2:
dataChannelLen = dataBitLen >> 1;
if (dataChannelLen > channelConvBufferLength) {
channelConvBuffer = xrealloc(channelConvBuffer,
dataChannelLen);
channelConvBufferLength = dataChannelLen;
}
dataChannelConv = channelConvBuffer;
{
mpd_sint16 *in = (mpd_sint16 *) dataBitConv;
mpd_sint16 *out =
(mpd_sint16 *) dataChannelConv;
int i, inSamples = dataBitLen >> 2;
for (i = 0; i < inSamples; i++) {
*out = (*in++) / 2;
*out++ += (*in++) / 2;
}
}
break;
default:
ERROR
("only 1 or 2 channels are supported for conversion!\n");
exit(EXIT_FAILURE);
}
}
if (inFormat->sampleRate == outFormat->sampleRate) { /* outFormat bits must be 16 and channels must be 1 or 2! */
memcpy(outBuffer, dataChannelConv, dataChannelLen); size_t pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer,
} else { size_t inSize, AudioFormat * outFormat,
/* only works if outFormat is 16-bit stereo! */ char *outBuffer, ConvState *convState)
/* resampling code blatantly ripped from ESD */ {
mpd_uint32 rd_dat = 0; char *buf;
mpd_uint32 wr_dat = 0; size_t len;
mpd_sint16 lsample, rsample; size_t outSize = pcm_sizeOfConvBuffer(inFormat, inSize, outFormat);
mpd_sint16 *out = (mpd_sint16 *) outBuffer;
mpd_sint16 *in = (mpd_sint16 *) dataChannelConv;
const int shift = sizeof(mpd_sint16) * outFormat->channels;
mpd_uint32 nlen = (((dataChannelLen / shift) *
(mpd_uint32) (outFormat->sampleRate)) /
inFormat->sampleRate);
nlen *= outFormat->channels;
switch (outFormat->channels) {
case 1:
while (wr_dat < nlen) {
rd_dat = wr_dat * inFormat->sampleRate /
outFormat->sampleRate;
lsample = in[rd_dat++]; assert(outFormat->bits == 16);
assert(outFormat->channels == 2 || outFormat->channels == 1);
out[wr_dat++] = lsample; /* everything else supports 16 bit only, so convert to that first */
} buf = pcm_convertTo16bit(inFormat->bits, inBuffer, inSize, &len);
break; if (!buf)
case 2: exit(EXIT_FAILURE);
while (wr_dat < nlen) {
rd_dat = wr_dat * inFormat->sampleRate /
outFormat->sampleRate;
rd_dat &= ~1;
lsample = in[rd_dat++]; if (inFormat->channels != outFormat->channels) {
rsample = in[rd_dat++]; buf = pcm_convertChannels(inFormat->channels, buf, len, &len);
if (!buf)
exit(EXIT_FAILURE);
}
out[wr_dat++] = lsample; if (inFormat->sampleRate == outFormat->sampleRate) {
out[wr_dat++] = rsample; assert(outSize >= len);
} memcpy(outBuffer, buf, len);
break; } else {
} len = pcm_convertSampleRate(outFormat->channels,
inFormat->sampleRate, buf, len,
outFormat->sampleRate, outBuffer,
outSize, convState);
if (len == 0)
exit(EXIT_FAILURE);
} }
return; return len;
} }
size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, size_t pcm_sizeOfConvBuffer(AudioFormat * inFormat, size_t inSize,
size_t inSize, AudioFormat * outFormat)
AudioFormat * outFormat)
{ {
const int shift = sizeof(mpd_sint16) * outFormat->channels; const double ratio = (double)outFormat->sampleRate /
(double)inFormat->sampleRate;
const int shift = 2 * outFormat->channels;
size_t outSize = inSize; size_t outSize = inSize;
switch (inFormat->bits) { switch (inFormat->bits) {
case 8: case 8:
outSize = outSize << 1; outSize <<= 1;
break; break;
case 16: case 16:
break; break;
default: default:
ERROR("only 8 or 16 bits are supported for conversion!\n"); FATAL("only 8 or 16 bits are supported for conversion!\n");
exit(EXIT_FAILURE);
} }
if (inFormat->channels != outFormat->channels) { if (inFormat->channels != outFormat->channels) {
...@@ -303,12 +456,14 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, ...@@ -303,12 +456,14 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
case 2: case 2:
outSize >>= 1; outSize >>= 1;
break; break;
default:
FATAL("only 1 or 2 channels are supported "
"for conversion!\n");
} }
} }
outSize = (((outSize / shift) * (mpd_uint32) (outFormat->sampleRate)) / outSize /= shift;
inFormat->sampleRate); outSize = floor(0.5 + (double)outSize * ratio);
outSize *= shift; outSize *= shift;
return outSize; return outSize;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -25,16 +25,33 @@ ...@@ -25,16 +25,33 @@
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_LIBSAMPLERATE
#include <samplerate.h>
#endif
typedef struct _ConvState {
#ifdef HAVE_LIBSAMPLERATE
SRC_STATE *state;
SRC_DATA data;
size_t dataInSize;
size_t dataOutSize;
mpd_sint8 lastChannels;
mpd_sint32 lastInSampleRate;
mpd_sint32 lastOutSampleRate;
int error;
#endif
} ConvState;
void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format, void pcm_volumeChange(char *buffer, int bufferSize, AudioFormat * format,
int volume); int volume);
void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, char *buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1); size_t bufferSize2, AudioFormat * format, float portion1);
void pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer, size_t size_t pcm_convertAudioFormat(AudioFormat * inFormat, char *inBuffer,
inSize, AudioFormat * outFormat, char *outBuffer); size_t inSize, AudioFormat * outFormat,
char *outBuffer, ConvState *convState);
size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, size_t pcm_sizeOfConvBuffer(AudioFormat * inFormat, size_t inSize,
size_t inSize, AudioFormat * outFormat);
AudioFormat * outFormat);
#endif #endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -57,8 +57,7 @@ static int parsePermissions(char *string) ...@@ -57,8 +57,7 @@ static int parsePermissions(char *string)
} else if (strcmp(temp, PERMISSION_ADMIN_STRING) == 0) { } else if (strcmp(temp, PERMISSION_ADMIN_STRING) == 0) {
permission |= PERMISSION_ADMIN; permission |= PERMISSION_ADMIN;
} else { } else {
ERROR("unknown permission \"%s\"\n", temp); FATAL("unknown permission \"%s\"\n", temp);
exit(EXIT_FAILURE);
} }
temp = strtok_r(NULL, PERMISSION_SEPERATOR, &tok); temp = strtok_r(NULL, PERMISSION_SEPERATOR, &tok);
...@@ -87,19 +86,16 @@ void initPermissions(void) ...@@ -87,19 +86,16 @@ void initPermissions(void)
do { do {
if (!strstr(param->value, PERMISSION_PASSWORD_CHAR)) { if (!strstr(param->value, PERMISSION_PASSWORD_CHAR)) {
ERROR("\"%s\" not found in password string " FATAL("\"%s\" not found in password string "
"\"%s\", line %i\n", "\"%s\", line %i\n",
PERMISSION_PASSWORD_CHAR, PERMISSION_PASSWORD_CHAR,
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
if (!(temp = strtok_r(param->value, if (!(temp = strtok_r(param->value,
PERMISSION_PASSWORD_CHAR, PERMISSION_PASSWORD_CHAR,
&cp2))) { &cp2))) {
ERROR FATAL("something weird just happened in permission.c\n");
("something weird just happened in permission.c\n");
exit(EXIT_FAILURE);
} }
password = temp; password = temp;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -138,6 +138,8 @@ int playerInit(void) ...@@ -138,6 +138,8 @@ int playerInit(void)
decode(); decode();
else if (pc->stop) else if (pc->stop)
pc->stop = 0; pc->stop = 0;
else if (pc->seek)
pc->seek = 0;
else if (pc->pause) else if (pc->pause)
pc->pause = 0; pc->pause = 0;
else if (pc->closeAudio) { else if (pc->closeAudio) {
...@@ -297,12 +299,12 @@ int getPlayerError(void) ...@@ -297,12 +299,12 @@ int getPlayerError(void)
char *getPlayerErrorStr(void) char *getPlayerErrorStr(void)
{ {
static char *error = NULL; static char *error;
int errorlen = MAXPATHLEN + 1024; int errorlen = MAXPATHLEN + 1024;
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
error = xrealloc(error, errorlen + 1); error = xrealloc(error, errorlen);
memset(error, 0, errorlen + 1); error[0] = '\0';
switch (pc->error) { switch (pc->error) {
case PLAYER_ERROR_FILENOTFOUND: case PLAYER_ERROR_FILENOTFOUND:
...@@ -504,8 +506,8 @@ void playerCycleLogFiles(void) ...@@ -504,8 +506,8 @@ void playerCycleLogFiles(void)
/* this actually creates a dupe of the current metadata */ /* this actually creates a dupe of the current metadata */
Song *playerCurrentDecodeSong(void) Song *playerCurrentDecodeSong(void)
{ {
static Song *song = NULL; static Song *song;
static MetadataChunk *prev = NULL; static MetadataChunk *prev;
Song *ret = NULL; Song *ret = NULL;
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
int buffered_before_play; int buffered_before_play;
int buffered_chunks; int buffered_chunks;
#define DEFAULT_BUFFER_SIZE 2048 #define DEFAULT_BUFFER_SIZE 2048
#define DEFAULT_BUFFER_BEFORE_PLAY 0 #define DEFAULT_BUFFER_BEFORE_PLAY 10
static PlayerData *playerData_pd; static PlayerData *playerData_pd;
...@@ -53,9 +53,8 @@ void initPlayerData(void) ...@@ -53,9 +53,8 @@ void initPlayerData(void)
if (param) { if (param) {
bufferSize = strtol(param->value, &test, 10); bufferSize = strtol(param->value, &test, 10);
if (*test != '\0' || bufferSize <= 0) { if (*test != '\0' || bufferSize <= 0) {
ERROR("buffer size \"%s\" is not a positive integer, " FATAL("buffer size \"%s\" is not a positive integer, "
"line %i\n", param->value, param->line); "line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
} }
...@@ -64,8 +63,7 @@ void initPlayerData(void) ...@@ -64,8 +63,7 @@ void initPlayerData(void)
buffered_chunks = bufferSize / CHUNK_SIZE; buffered_chunks = bufferSize / CHUNK_SIZE;
if (buffered_chunks >= 1 << 15) { if (buffered_chunks >= 1 << 15) {
ERROR("buffer size \"%li\" is too big\n", (long)bufferSize); FATAL("buffer size \"%li\" is too big\n", (long)bufferSize);
exit(EXIT_FAILURE);
} }
param = getConfigParam(CONF_BUFFER_BEFORE_PLAY); param = getConfigParam(CONF_BUFFER_BEFORE_PLAY);
...@@ -73,10 +71,9 @@ void initPlayerData(void) ...@@ -73,10 +71,9 @@ void initPlayerData(void)
if (param) { if (param) {
perc = strtod(param->value, &test); perc = strtod(param->value, &test);
if (*test != '%' || perc < 0 || perc > 100) { if (*test != '%' || perc < 0 || perc > 100) {
ERROR("buffered before play \"%s\" is not a positive " FATAL("buffered before play \"%s\" is not a positive "
"percentage and less than 100 percent, line %i" "percentage and less than 100 percent, line %i"
"\n", param->value, param->line); "\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
} }
...@@ -97,25 +94,17 @@ void initPlayerData(void) ...@@ -97,25 +94,17 @@ void initPlayerData(void)
allocationSize += device_array_size; allocationSize += device_array_size;
if ((shmid = shmget(IPC_PRIVATE, allocationSize, IPC_CREAT | 0600)) < 0) if ((shmid = shmget(IPC_PRIVATE, allocationSize, IPC_CREAT | 0600)) < 0)
{ FATAL("problems shmget'ing\n");
ERROR("problems shmget'ing\n");
exit(EXIT_FAILURE);
}
if (!(playerData_pd = shmat(shmid, NULL, 0))) if (!(playerData_pd = shmat(shmid, NULL, 0)))
{ FATAL("problems shmat'ing\n");
ERROR("problems shmat'ing\n");
exit(EXIT_FAILURE);
}
if (shmctl(shmid, IPC_RMID, NULL) < 0) if (shmctl(shmid, IPC_RMID, NULL) < 0)
{ FATAL("problems shmctl'ing\n");
ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE);
}
playerData_pd->audioDeviceStates = (mpd_uint8 *)playerData_pd + playerData_pd->audioDeviceStates = (mpd_uint8 *)playerData_pd +
allocationSize - device_array_size; allocationSize - device_array_size;
buffer = &(playerData_pd->buffer); buffer = &(playerData_pd->buffer);
memset(&buffer->convState, 0, sizeof(ConvState));
buffer->chunks = ((char *)playerData_pd) + sizeof(PlayerData); buffer->chunks = ((char *)playerData_pd) + sizeof(PlayerData);
buffer->chunkSize = (mpd_uint16 *) (((char *)buffer->chunks) + buffer->chunkSize = (mpd_uint16 *) (((char *)buffer->chunks) +
buffered_chunks * CHUNK_SIZE); buffered_chunks * CHUNK_SIZE);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "utils.h" #include "utils.h"
#include "sig_handlers.h" #include "sig_handlers.h"
#include "state_file.h" #include "state_file.h"
#include "storedPlaylist.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -37,8 +38,6 @@ ...@@ -37,8 +38,6 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#define PLAYLIST_COMMENT '#'
#define PLAYLIST_STATE_STOP 0 #define PLAYLIST_STATE_STOP 0
#define PLAYLIST_STATE_PLAY 1 #define PLAYLIST_STATE_PLAY 1
...@@ -64,30 +63,15 @@ ...@@ -64,30 +63,15 @@
#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) #define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0 #define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0
typedef struct _Playlist {
Song **songs;
/* holds version a song was modified on */
mpd_uint32 *songMod;
int *order;
int *positionToId;
int *idToPosition;
int length;
int current;
int queued;
int repeat;
int random;
mpd_uint32 version;
} Playlist;
static Playlist playlist; static Playlist playlist;
static int playlist_state = PLAYLIST_STATE_STOP; static int playlist_state = PLAYLIST_STATE_STOP;
static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH; static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH;
static int playlist_stopOnError; static int playlist_stopOnError;
static int playlist_errorCount = 0; static int playlist_errorCount;
static int playlist_queueError; static int playlist_queueError;
static int playlist_noGoToNext = 0; static int playlist_noGoToNext;
static int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS; int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
static void swapOrder(int a, int b); static void swapOrder(int a, int b);
static int playPlaylistOrderNumber(int fd, int orderNum); static int playPlaylistOrderNumber(int fd, int orderNum);
...@@ -151,14 +135,13 @@ void initPlaylist(void) ...@@ -151,14 +135,13 @@ void initPlaylist(void)
if (param) { if (param) {
playlist_max_length = strtol(param->value, &test, 10); playlist_max_length = strtol(param->value, &test, 10);
if (*test != '\0') { if (*test != '\0') {
ERROR("max playlist length \"%s\" is not an integer, " FATAL("max playlist length \"%s\" is not an integer, "
"line %i\n", param->value, param->line); "line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
} }
playlist_saveAbsolutePaths = getBoolConfigParam(CONF_SAVE_ABSOLUTE_PATHS); playlist_saveAbsolutePaths = getBoolConfigParam(CONF_SAVE_ABSOLUTE_PATHS);
if (playlist_saveAbsolutePaths == -1) playlist_saveAbsolutePaths = 0; if (playlist_saveAbsolutePaths == -1) playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
else if (playlist_saveAbsolutePaths < 0) exit(EXIT_FAILURE); else if (playlist_saveAbsolutePaths < 0) exit(EXIT_FAILURE);
playlist.songs = xmalloc(sizeof(Song *) * playlist_max_length); playlist.songs = xmalloc(sizeof(Song *) * playlist_max_length);
...@@ -236,6 +219,12 @@ int clearPlaylist(int fd) ...@@ -236,6 +219,12 @@ int clearPlaylist(int fd)
return 0; return 0;
} }
int clearStoredPlaylist(int fd, char *utf8file)
{
removeAllFromStoredPlaylistByPath(fd, utf8file);
return 0;
}
int showPlaylist(int fd) int showPlaylist(int fd)
{ {
int i; int i;
...@@ -590,6 +579,34 @@ int addToPlaylist(int fd, char *url, int printId) ...@@ -590,6 +579,34 @@ int addToPlaylist(int fd, char *url, int printId)
return addSongToPlaylist(fd, song, printId); return addSongToPlaylist(fd, song, printId);
} }
int addToStoredPlaylist(int fd, char *url, char *utf8file)
{
Song *song;
DEBUG("add to stored playlist: %s\n", url);
song = getSongFromDB(url);
if (song) {
appendSongToStoredPlaylistByPath(fd, utf8file, song);
return 0;
}
if (!isValidRemoteUtf8Url(url))
goto fail;
song = newSong(url, SONG_TYPE_URL, NULL);
if (song) {
appendSongToStoredPlaylistByPath(fd, utf8file, song);
freeJustSong(song);
return 0;
}
fail:
commandError(fd, ACK_ERROR_NO_EXIST, "\"%s\" is not in the music db"
"or is not a valid url", url);
return -1;
}
int addSongToPlaylist(int fd, Song * song, int printId) int addSongToPlaylist(int fd, Song * song, int printId)
{ {
int id; int id;
...@@ -821,7 +838,7 @@ int stopPlaylist(int fd) ...@@ -821,7 +838,7 @@ int stopPlaylist(int fd)
return 0; return 0;
} }
int playPlaylistOrderNumber(int fd, int orderNum) static int playPlaylistOrderNumber(int fd, int orderNum)
{ {
if (playerStop(fd) < 0) if (playerStop(fd) < 0)
...@@ -838,8 +855,7 @@ int playPlaylistOrderNumber(int fd, int orderNum) ...@@ -838,8 +855,7 @@ int playPlaylistOrderNumber(int fd, int orderNum)
if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) { if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) {
stopPlaylist(fd); stopPlaylist(fd);
return -1; return -1;
} else }
playlist.current++;
playlist.current = orderNum; playlist.current = orderNum;
...@@ -1093,12 +1109,26 @@ int moveSongInPlaylist(int fd, int from, int to) ...@@ -1093,12 +1109,26 @@ int moveSongInPlaylist(int fd, int from, int to)
playlist.order[i] = to; playlist.order[i] = to;
} }
} }
} else if (playlist.current == from) }
playlist.current = to; else
else if (playlist.current > from && playlist.current <= to) { {
playlist.current--; if (playlist.current == from)
} else if (playlist.current >= to && playlist.current < from) { playlist.current = to;
playlist.current++; else if (playlist.current > from && playlist.current <= to) {
playlist.current--;
} else if (playlist.current >= to && playlist.current < from) {
playlist.current++;
}
/* this first if statement isn't necessary since the queue
* would have been cleared out if queued == from */
if (playlist.queued == from)
playlist.queued = to;
else if (playlist.queued > from && playlist.queued <= to) {
playlist.queued--;
} else if (playlist.queued>= to && playlist.queued < from) {
playlist.queued++;
}
} }
incrPlaylistVersion(); incrPlaylistVersion();
...@@ -1200,7 +1230,7 @@ int setPlaylistRandomStatus(int fd, int status) ...@@ -1200,7 +1230,7 @@ int setPlaylistRandomStatus(int fd, int status)
int previousSongInPlaylist(int fd) int previousSongInPlaylist(int fd)
{ {
static time_t lastTime = 0; static time_t lastTime;
time_t diff = time(NULL) - lastTime; time_t diff = time(NULL) - lastTime;
lastTime += diff; lastTime += diff;
...@@ -1292,59 +1322,17 @@ int deletePlaylist(int fd, char *utf8file) ...@@ -1292,59 +1322,17 @@ int deletePlaylist(int fd, char *utf8file)
int savePlaylist(int fd, char *utf8file) int savePlaylist(int fd, char *utf8file)
{ {
FILE *fileP; StoredPlaylist *sp = newStoredPlaylist(utf8file, fd, 0);
int i; if (!sp)
struct stat st;
char *file;
char *rfile;
char *actualFile;
if (strstr(utf8file, "/")) {
commandError(fd, ACK_ERROR_ARG,
"cannot save \"%s\", saving playlists to "
"subdirectories is not supported", utf8file);
return -1;
}
file = utf8ToFsCharset(utf8file);
rfile = xmalloc(strlen(file) + strlen(".") +
strlen(PLAYLIST_FILE_SUFFIX) + 1);
strcpy(rfile, file);
strcat(rfile, ".");
strcat(rfile, PLAYLIST_FILE_SUFFIX);
actualFile = rpp2app(rfile);
free(rfile);
if (0 == stat(actualFile, &st)) {
commandError(fd, ACK_ERROR_EXIST, "a file or directory already "
"exists with the name \"%s\"", utf8file);
return -1; return -1;
}
while (!(fileP = fopen(actualFile, "w")) && errno == EINTR) ; appendPlaylistToStoredPlaylist(sp, &playlist);
if (fileP == NULL) { if (writeStoredPlaylist(sp) != 0) {
commandError(fd, ACK_ERROR_SYSTEM, "problems opening file"); freeStoredPlaylist(sp);
return -1; return -1;
} }
for (i = 0; i < playlist.length; i++) { freeStoredPlaylist(sp);
if (playlist_saveAbsolutePaths &&
playlist.songs[i]->type == SONG_TYPE_FILE) {
fprintf(fileP, "%s\n",
rmp2amp(utf8ToFsCharset
((getSongUrl(playlist.songs[i])))));
} else {
fprintf(fileP, "%s\n",
utf8ToFsCharset(getSongUrl(playlist.songs[i])));
}
}
while (fclose(fileP) && errno == EINTR) ;
return 0; return 0;
} }
...@@ -1413,154 +1401,99 @@ int getPlaylistSongId(int song) ...@@ -1413,154 +1401,99 @@ int getPlaylistSongId(int song)
return playlist.positionToId[song]; return playlist.positionToId[song];
} }
static int PlaylistIterFunc(int fd, char *utf8file, int PlaylistInfo(int fd, char *utf8file, int detail)
void (*IterFunc) (int fd, char *utf8_file,
char **errored_File))
{ {
FILE *fileP; ListNode *node;
char s[MAXPATHLEN + 1]; StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd);
int slength = 0; if (sp == NULL)
char *temp = utf8ToFsCharset(utf8file);
char *rfile = xmalloc(strlen(temp) + strlen(".") +
strlen(PLAYLIST_FILE_SUFFIX) + 1);
char *actualFile;
char *parent = parentPath(temp);
int parentlen = strlen(parent);
char *erroredFile = NULL;
int tempInt;
int commentCharFound = 0;
strcpy(rfile, temp);
strcat(rfile, ".");
strcat(rfile, PLAYLIST_FILE_SUFFIX);
if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile))
free(rfile);
else {
free(rfile);
commandError(fd, ACK_ERROR_NO_EXIST,
"playlist \"%s\" not found", utf8file);
return -1; return -1;
}
while (!(fileP = fopen(actualFile, "r")) && errno == EINTR) ; node = sp->list->firstNode;
if (fileP == NULL) { while (node != NULL) {
commandError(fd, ACK_ERROR_SYSTEM, char *temp = node->data;
"problems opening file \"%s\"", utf8file); int wrote = 0;
return -1;
}
while ((tempInt = fgetc(fileP)) != EOF) { if (detail) {
s[slength] = tempInt; Song *song = getSongFromDB(temp);
if (s[slength] == '\n' || s[slength] == '\0') { if (song) {
commentCharFound = 0; printSongInfo(fd, song);
s[slength] = '\0'; wrote = 1;
if (s[0] == PLAYLIST_COMMENT) {
commentCharFound = 1;
}
if (strncmp(s, musicDir, strlen(musicDir)) == 0) {
strcpy(s, &(s[strlen(musicDir)]));
} else if (parentlen) {
temp = xstrdup(s);
memset(s, 0, MAXPATHLEN + 1);
strcpy(s, parent);
strncat(s, "/", MAXPATHLEN - parentlen);
strncat(s, temp, MAXPATHLEN - parentlen - 1);
if (strlen(s) >= MAXPATHLEN) {
commandError(fd,
ACK_ERROR_PLAYLIST_LOAD,
"\"%s\" too long", temp);
free(temp);
while (fclose(fileP)
&& errno == EINTR) ;
if (erroredFile)
free(erroredFile);
return -1;
}
free(temp);
}
slength = 0;
temp = fsCharsetToUtf8(s);
if (!temp)
continue;
if (!commentCharFound) {
/* using temp directly should be safe,
* for our current IterFunction set
* but just in case, we copy to s */
strcpy(s, temp);
IterFunc(fd, s, &erroredFile);
} }
} else if (slength == MAXPATHLEN) { }
s[slength] = '\0';
commandError(fd, ACK_ERROR_PLAYLIST_LOAD,
"line in \"%s\" is too long", utf8file);
ERROR("line \"%s\" in playlist \"%s\" is too long\n",
s, utf8file);
while (fclose(fileP) && errno == EINTR) ;
if (erroredFile)
free(erroredFile);
return -1;
} else if (s[slength] != '\r')
slength++;
}
while (fclose(fileP) && errno == EINTR) ; if (!wrote) {
fdprintf(fd, SONG_FILE "%s\n", temp);
}
if (erroredFile) { node = node->nextNode;
commandError(fd, ACK_ERROR_PLAYLIST_LOAD,
"can't add file \"%s\"", erroredFile);
free(erroredFile);
return -1;
} }
freeStoredPlaylist(sp);
return 0; return 0;
} }
static void PlaylistInfoPrintInfo(int fd, char *utf8file, char **erroredfile) int loadPlaylist(int fd, char *utf8file)
{
Song *song = getSongFromDB(utf8file);
if (song) {
printSongInfo(fd, song);
} else {
fdprintf(fd, "file: %s\n", utf8file);
}
}
static void PlaylistInfoPrint(int fd, char *utf8file, char **erroredfile)
{ {
fdprintf(fd, "file: %s\n", utf8file); ListNode *node;
} StoredPlaylist *sp = loadStoredPlaylist(utf8file, fd);
if (sp == NULL)
return -1;
static void PlaylistLoadIterFunc(int fd, char *temp, char **erroredFile) node = sp->list->firstNode;
{ while (node != NULL) {
if (!getSongFromDB(temp) && !isRemoteUrl(temp)) { char *temp = node->data;
if ((addToPlaylist(STDERR_FILENO, temp, 0)) < 0) {
} else if ((addToPlaylist(STDERR_FILENO, temp, 0)) < 0) { /* for windows compatibility, convert slashes */
/* for windows compatibilit, convert slashes */ char *temp2 = xstrdup(temp);
char *temp2 = xstrdup(temp); char *p = temp2;
char *p = temp2; while (*p) {
while (*p) { if (*p == '\\')
if (*p == '\\') *p = '/';
*p = '/'; p++;
p++; }
} if ((addToPlaylist(STDERR_FILENO, temp2, 0)) < 0) {
if ((addToPlaylist(STDERR_FILENO, temp2, 0)) < 0) { commandError(fd, ACK_ERROR_PLAYLIST_LOAD,
if (!*erroredFile) { "can't add file \"%s\"", temp2);
*erroredFile = xstrdup(temp);
} }
free(temp2);
} }
free(temp2);
node = node->nextNode;
} }
freeStoredPlaylist(sp);
return 0;
} }
int PlaylistInfo(int fd, char *utf8file, int detail) void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items)
{ {
if (detail) { int i;
return PlaylistIterFunc(fd, utf8file, PlaylistInfoPrintInfo); char **originalNeedles = xmalloc(numItems * sizeof(char *));
for (i = 0; i < numItems; i++) {
originalNeedles[i] = items[i].needle;
items[i].needle = strDupToUpper(originalNeedles[i]);
} }
return PlaylistIterFunc(fd, utf8file, PlaylistInfoPrint);
for (i = 0; i < playlist.length; i++) {
if (strstrSearchTags(playlist.songs[i], numItems, items))
printPlaylistSongInfo(fd, i);
}
for (i = 0; i < numItems; i++) {
free(items[i].needle);
items[i].needle = originalNeedles[i];
}
free(originalNeedles);
} }
int loadPlaylist(int fd, char *utf8file) void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items)
{ {
return PlaylistIterFunc(fd, utf8file, PlaylistLoadIterFunc); int i;
for (i = 0; i < playlist.length; i++) {
if (tagItemsFoundAndMatches(playlist.songs[i], numItems, items))
printPlaylistSongInfo(fd, i);
}
} }
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -21,14 +21,31 @@ ...@@ -21,14 +21,31 @@
#include "../config.h" #include "../config.h"
#include "song.h" #include "dbUtils.h"
#include "mpd_types.h"
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <sys/param.h>
#include <time.h> #include <time.h>
#define PLAYLIST_FILE_SUFFIX "m3u" #define PLAYLIST_FILE_SUFFIX "m3u"
#define PLAYLIST_COMMENT '#'
typedef struct _Playlist {
Song **songs;
/* holds version a song was modified on */
mpd_uint32 *songMod;
int *order;
int *positionToId;
int *idToPosition;
int length;
int current;
int queued;
int repeat;
int random;
mpd_uint32 version;
} Playlist;
extern int playlist_saveAbsolutePaths;
void initPlaylist(void); void initPlaylist(void);
...@@ -40,8 +57,12 @@ void savePlaylistState(FILE *); ...@@ -40,8 +57,12 @@ void savePlaylistState(FILE *);
int clearPlaylist(int fd); int clearPlaylist(int fd);
int clearStoredPlaylist(int fd, char *utf8file);
int addToPlaylist(int fd, char *file, int printId); int addToPlaylist(int fd, char *file, int printId);
int addToStoredPlaylist(int fd, char *file, char *utf8file);
int addSongToPlaylist(int fd, Song * song, int printId); int addSongToPlaylist(int fd, Song * song, int printId);
int showPlaylist(int fd); int showPlaylist(int fd);
...@@ -116,4 +137,8 @@ int playlistChangesPosId(int fd, mpd_uint32 version); ...@@ -116,4 +137,8 @@ int playlistChangesPosId(int fd, mpd_uint32 version);
int PlaylistInfo(int fd, char *utf8file, int detail); int PlaylistInfo(int fd, char *utf8file, int detail);
void searchForSongsInPlaylist(int fd, int numItems, LocateTagItem * items);
void findSongsInPlaylist(int fd, int numItems, LocateTagItem * items);
#endif #endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* (c)2004 replayGain code by AliasMrJones * (c)2004 replayGain code by AliasMrJones
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
...@@ -44,9 +44,8 @@ void initReplayGainState(void) ...@@ -44,9 +44,8 @@ void initReplayGainState(void)
} else if (strcmp(param->value, "album") == 0) { } else if (strcmp(param->value, "album") == 0) {
replayGainState = REPLAYGAIN_ALBUM; replayGainState = REPLAYGAIN_ALBUM;
} else { } else {
ERROR("replaygain value \"%s\" at line %i is invalid\n", FATAL("replaygain value \"%s\" at line %i is invalid\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
param = getConfigParam(CONF_REPLAYGAIN_PREAMP); param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
...@@ -56,15 +55,13 @@ void initReplayGainState(void) ...@@ -56,15 +55,13 @@ void initReplayGainState(void)
float f = strtod(param->value, &test); float f = strtod(param->value, &test);
if (*test != '\0') { if (*test != '\0') {
ERROR("Replaygain preamp \"%s\" is not a number at " FATAL("Replaygain preamp \"%s\" is not a number at "
"line %i\n", param->value, param->line); "line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
if (f < -15 || f > 15) { if (f < -15 || f > 15) {
ERROR("Replaygain preamp \"%s\" is not between -15 and" FATAL("Replaygain preamp \"%s\" is not between -15 and"
"15 at line %i\n", param->value, param->line); "15 at line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
} }
replayGainPreamp = pow(10, f / 20.0); replayGainPreamp = pow(10, f / 20.0);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* (c)2004 replayGain code by AliasMrJones * (c)2004 replayGain code by AliasMrJones
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* (c) 2004 Nick Welch (mack@incise.org) * (c) 2004 Nick Welch (mack@incise.org)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* (c)2004 by mackstann * (c)2004 by mackstann
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* (c)2004 by mackstann * (c)2004 by mackstann
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include "myfprintf.h" #include "myfprintf.h"
#define SONG_KEY "key: " #define SONG_KEY "key: "
#define SONG_FILE "file: "
#define SONG_TIME "Time: "
#define SONG_MTIME "mtime: " #define SONG_MTIME "mtime: "
#include <stdlib.h> #include <stdlib.h>
...@@ -253,10 +251,8 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) ...@@ -253,10 +251,8 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir)
song->type = SONG_TYPE_FILE; song->type = SONG_TYPE_FILE;
song->parentDir = parentDir; song->parentDir = parentDir;
} else if (0 == strncmp(SONG_FILE, buffer, strlen(SONG_FILE))) { } else if (0 == strncmp(SONG_FILE, buffer, strlen(SONG_FILE))) {
if (!song) { if (!song)
ERROR("Problems reading song info\n"); FATAL("Problems reading song info\n");
exit(EXIT_FAILURE);
}
/* we don't need this info anymore /* we don't need this info anymore
song->url = xstrdup(&(buffer[strlen(SONG_FILE)])); song->url = xstrdup(&(buffer[strlen(SONG_FILE)]));
*/ */
...@@ -275,10 +271,8 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) ...@@ -275,10 +271,8 @@ void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir)
song->mtime = atoi(&(buffer[strlen(SONG_MTIME)])); song->mtime = atoi(&(buffer[strlen(SONG_MTIME)]));
} }
/* ignore empty lines (starting with '\0') */ /* ignore empty lines (starting with '\0') */
else if (*buffer) { else if (*buffer)
ERROR("songinfo: unknown line in db: %s\n", buffer); FATAL("songinfo: unknown line in db: %s\n", buffer);
exit(EXIT_FAILURE);
}
} }
if (song) { if (song) {
...@@ -322,9 +316,9 @@ int updateSongInfo(Song * song) ...@@ -322,9 +316,9 @@ int updateSongInfo(Song * song)
* we free and recreate this memory we make sure to print it correctly*/ * we free and recreate this memory we make sure to print it correctly*/
char *getSongUrl(Song * song) char *getSongUrl(Song * song)
{ {
static char *buffer = NULL; static char *buffer;
static int bufferSize = 0; static int bufferSize;
static Song *lastSong = NULL; static Song *lastSong;
int slen; int slen;
int dlen; int dlen;
int size; int size;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#define SONG_TYPE_FILE 1 #define SONG_TYPE_FILE 1
#define SONG_TYPE_URL 2 #define SONG_TYPE_URL 2
#define SONG_FILE "file: "
#define SONG_TIME "Time: "
typedef struct _Song { typedef struct _Song {
char *url; char *url;
mpd_sint8 type; mpd_sint8 type;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -41,7 +41,7 @@ static struct _sf_cb { ...@@ -41,7 +41,7 @@ static struct _sf_cb {
{ readPlaylistState, savePlaylistState }, { readPlaylistState, savePlaylistState },
}; };
static const char *sfpath = NULL; static const char *sfpath;
static void get_state_file_path(void) static void get_state_file_path(void)
{ {
...@@ -87,16 +87,13 @@ void read_state_file(void) ...@@ -87,16 +87,13 @@ void read_state_file(void)
DEBUG("failed to stat state file: %s\n", sfpath); DEBUG("failed to stat state file: %s\n", sfpath);
return; return;
} }
if (!S_ISREG(st.st_mode)) { if (!S_ISREG(st.st_mode))
ERROR("state file \"%s\" is not a regular file\n", sfpath); FATAL("state file \"%s\" is not a regular file\n", sfpath);
exit(EXIT_FAILURE);
}
while (!(fp = fopen(sfpath, "r")) && errno == EINTR); while (!(fp = fopen(sfpath, "r")) && errno == EINTR);
if (mpd_unlikely(!fp)) { if (mpd_unlikely(!fp)) {
ERROR("problems opening state file \"%s\" for reading: %s\n", FATAL("problems opening state file \"%s\" for reading: %s\n",
sfpath, strerror(errno)); sfpath, strerror(errno));
exit(EXIT_FAILURE);
} }
for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++) { for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++) {
sf_callbacks[i].reader(fp); sf_callbacks[i].reader(fp);
...@@ -108,7 +105,7 @@ void read_state_file(void) ...@@ -108,7 +105,7 @@ void read_state_file(void)
void mpd_noreturn state_file_fatal(void) void mpd_noreturn state_file_fatal(void)
{ {
ERROR("error parsing state file \"%s\"\n", sfpath); FATAL("error parsing state file \"%s\"\n", sfpath);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD)
* Copyright (C) 2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "storedPlaylist.h"
#include "log.h"
#include "path.h"
#include "utils.h"
#include "playlist.h"
#include "ack.h"
#include "command.h"
#include "ls.h"
#include "directory.h"
#include <string.h>
#include <errno.h>
static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd)
{
char *file;
char *rfile;
char *actualFile;
if (strstr(utf8path, "/")) {
commandError(fd, ACK_ERROR_ARG, "playlist name \"%s\" is "
"invalid: playlist names may not contain slashes",
utf8path);
return NULL;
}
file = utf8ToFsCharset((char *)utf8path);
rfile = xmalloc(strlen(file) + strlen(".") +
strlen(PLAYLIST_FILE_SUFFIX) + 1);
strcpy(rfile, file);
strcat(rfile, ".");
strcat(rfile, PLAYLIST_FILE_SUFFIX);
actualFile = rpp2app(rfile);
free(rfile);
return actualFile;
}
static unsigned int lengthOfStoredPlaylist(StoredPlaylist *sp)
{
return sp->list->numberOfNodes;
}
static ListNode *nodeOfStoredPlaylist(StoredPlaylist *sp, int index)
{
int forward;
ListNode *node;
int i;
if (index >= lengthOfStoredPlaylist(sp) || index < 0)
return NULL;
if (index > lengthOfStoredPlaylist(sp)/2) {
forward = 0;
node = sp->list->lastNode;
i = lengthOfStoredPlaylist(sp) - 1;
} else {
forward = 1;
node = sp->list->firstNode;
i = 0;
}
while (node != NULL) {
if (i == index)
return node;
if (forward) {
i++;
node = node->nextNode;
} else {
i--;
node = node->prevNode;
}
}
return NULL;
}
static void appendSongToStoredPlaylist(StoredPlaylist *sp, Song *song)
{
insertInListWithoutKey(sp->list, xstrdup(getSongUrl(song)));
}
StoredPlaylist *newStoredPlaylist(const char *utf8name, int fd, int ignoreExisting)
{
struct stat buf;
char *filename = NULL;
StoredPlaylist *sp = calloc(1, sizeof(*sp));
if (!sp)
return NULL;
if (utf8name) {
filename = utf8pathToFsPathInStoredPlaylist(utf8name, fd);
if (filename && stat(filename, &buf) == 0 &&
ignoreExisting == 0) {
commandError(fd, ACK_ERROR_EXIST,
"a file or directory already exists with "
"the name \"%s\"", utf8name);
free(sp);
return NULL;
}
}
sp->list = makeList(DEFAULT_FREE_DATA_FUNC, 0);
sp->fd = fd;
if (filename)
sp->fspath = xstrdup(filename);
return sp;
}
StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd)
{
char *filename;
StoredPlaylist *sp;
FILE *file;
char s[MAXPATHLEN + 1];
int slength = 0;
char *temp = utf8ToFsCharset((char *)utf8path);
char *parent = parentPath(temp);
int parentlen = strlen(parent);
int tempInt;
int commentCharFound = 0;
Song *song;
filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd);
if (!filename)
return NULL;
while (!(file = fopen(filename, "r")) && errno == EINTR);
if (file == NULL) {
commandError(fd, ACK_ERROR_NO_EXIST, "could not open file "
"\"%s\": %s", filename, strerror(errno));
return NULL;
}
sp = newStoredPlaylist(utf8path, fd, 1);
if (!sp)
goto out;
while ((tempInt = fgetc(file)) != EOF) {
s[slength] = tempInt;
if (s[slength] == '\n' || s[slength] == '\0') {
commentCharFound = 0;
s[slength] = '\0';
if (s[0] == PLAYLIST_COMMENT)
commentCharFound = 1;
if (strncmp(s, musicDir, strlen(musicDir)) == 0) {
strcpy(s, &(s[strlen(musicDir)]));
} else if (parentlen) {
temp = xstrdup(s);
memset(s, 0, MAXPATHLEN + 1);
strcpy(s, parent);
strncat(s, "/", MAXPATHLEN - parentlen);
strncat(s, temp, MAXPATHLEN - parentlen - 1);
if (strlen(s) >= MAXPATHLEN) {
commandError(sp->fd,
ACK_ERROR_PLAYLIST_LOAD,
"\"%s\" is too long", temp);
free(temp);
freeStoredPlaylist(sp);
sp = NULL;
goto out;
}
free(temp);
}
slength = 0;
temp = fsCharsetToUtf8(s);
if (temp && !commentCharFound) {
song = getSongFromDB(temp);
if (song) {
appendSongToStoredPlaylist(sp, song);
continue;
}
if (!isValidRemoteUtf8Url(temp))
continue;
song = newSong(temp, SONG_TYPE_URL, NULL);
if (song) {
appendSongToStoredPlaylist(sp, song);
freeJustSong(song);
}
}
} else if (slength == MAXPATHLEN) {
s[slength] = '\0';
commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD,
"line \"%s\" in playlist \"%s\" "
"is too long", s, utf8path);
freeStoredPlaylist(sp);
sp = NULL;
goto out;
} else if (s[slength] != '\r') {
slength++;
}
}
out:
while (fclose(file) && errno == EINTR);
return sp;
}
void freeStoredPlaylist(StoredPlaylist *sp)
{
if (sp->list)
freeList(sp->list);
if (sp->fspath)
free(sp->fspath);
free(sp);
}
static int moveSongInStoredPlaylist(int fd, StoredPlaylist *sp, int src, int dest)
{
ListNode *srcNode, *destNode;
if (src >= lengthOfStoredPlaylist(sp) || dest >= lengthOfStoredPlaylist(sp) || src < 0 || dest < 0 || src == dest) {
commandError(fd, ACK_ERROR_ARG, "argument out of range");
return -1;
}
srcNode = nodeOfStoredPlaylist(sp, src);
if (!srcNode)
return -1;
destNode = nodeOfStoredPlaylist(sp, dest);
/* remove src */
if (srcNode->prevNode)
srcNode->prevNode->nextNode = srcNode->nextNode;
else
sp->list->firstNode = srcNode->nextNode;
if (srcNode->nextNode)
srcNode->nextNode->prevNode = srcNode->prevNode;
else
sp->list->lastNode = srcNode->prevNode;
/* this is all a bit complicated - but I tried to
* maintain the same order stuff is moved as in the
* real playlist */
if (dest == 0) {
sp->list->firstNode->prevNode = srcNode;
srcNode->nextNode = sp->list->firstNode;
srcNode->prevNode = NULL;
sp->list->firstNode = srcNode;
} else if ((dest + 1) == lengthOfStoredPlaylist(sp)) {
sp->list->lastNode->nextNode = srcNode;
srcNode->nextNode = NULL;
srcNode->prevNode = sp->list->lastNode;
sp->list->lastNode = srcNode;
} else {
if (destNode == NULL) {
/* this shouldn't be happening. */
return -1;
}
if (src > dest) {
destNode->prevNode->nextNode = srcNode;
srcNode->prevNode = destNode->prevNode;
srcNode->nextNode = destNode;
destNode->prevNode = srcNode;
} else {
destNode->nextNode->prevNode = srcNode;
srcNode->prevNode = destNode;
srcNode->nextNode = destNode->nextNode;
destNode->nextNode = srcNode;
}
}
return 0;
}
int moveSongInStoredPlaylistByPath(int fd, const char *utf8path, int src, int dest)
{
StoredPlaylist *sp = loadStoredPlaylist(utf8path, fd);
if (!sp) {
commandError(fd, ACK_ERROR_UNKNOWN, "could not open playlist");
return -1;
}
if (moveSongInStoredPlaylist(fd, sp, src, dest) != 0) {
freeStoredPlaylist(sp);
return -1;
}
if (writeStoredPlaylist(sp) != 0) {
commandError(fd, ACK_ERROR_UNKNOWN, "failed to save playlist");
freeStoredPlaylist(sp);
return -1;
}
freeStoredPlaylist(sp);
return 0;
}
/* Not used currently
static void removeAllFromStoredPlaylist(StoredPlaylist *sp)
{
freeList(sp->list);
sp->list = makeList(DEFAULT_FREE_DATA_FUNC, 0);
}
*/
int removeAllFromStoredPlaylistByPath(int fd, const char *utf8path)
{
char *filename;
FILE *file;
filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd);
if (!filename)
return -1;
while (!(file = fopen(filename, "w")) && errno == EINTR);
if (file == NULL) {
commandError(fd, ACK_ERROR_NO_EXIST, "could not open file "
"\"%s\": %s", filename, strerror(errno));
return -1;
}
while (fclose(file) != 0 && errno == EINTR);
return 0;
}
static int removeOneSongFromStoredPlaylist(int fd, StoredPlaylist *sp, int pos)
{
ListNode *node = nodeOfStoredPlaylist(sp, pos);
if (!node) {
commandError(fd, ACK_ERROR_ARG,
"could not find song at position");
return -1;
}
deleteNodeFromList(sp->list, node);
return 0;
}
int removeOneSongFromStoredPlaylistByPath(int fd, const char *utf8path, int pos)
{
StoredPlaylist *sp = loadStoredPlaylist(utf8path, fd);
if (!sp) {
commandError(fd, ACK_ERROR_UNKNOWN, "could not open playlist");
return -1;
}
if (removeOneSongFromStoredPlaylist(fd, sp, pos) != 0) {
freeStoredPlaylist(sp);
return -1;
}
if (writeStoredPlaylist(sp) != 0) {
commandError(fd, ACK_ERROR_UNKNOWN, "failed to save playlist");
freeStoredPlaylist(sp);
return -1;
}
freeStoredPlaylist(sp);
return 0;
}
static int writeStoredPlaylistToPath(StoredPlaylist *sp, const char *fspath)
{
ListNode *node;
FILE *file;
char *s;
if (fspath == NULL)
return -1;
while (!(file = fopen(fspath, "w")) && errno == EINTR);
if (file == NULL) {
commandError(sp->fd, ACK_ERROR_NO_EXIST, "could not open file "
"\"%s\": %s", fspath, strerror(errno));
return -1;
}
node = sp->list->firstNode;
while (node != NULL) {
s = (char *)node->data;
if (isValidRemoteUtf8Url(s) || !playlist_saveAbsolutePaths)
s = utf8ToFsCharset(s);
else
s = rmp2amp(utf8ToFsCharset(s));
fprintf(file, "%s\n", s);
node = node->nextNode;
}
while (fclose(file) != 0 && errno == EINTR);
return 0;
}
int writeStoredPlaylist(StoredPlaylist *sp)
{
return writeStoredPlaylistToPath(sp, sp->fspath);
}
int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song)
{
char *filename;
FILE *file;
char *s;
filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd);
if (!filename)
return -1;
while (!(file = fopen(filename, "a")) && errno == EINTR);
if (file == NULL) {
commandError(fd, ACK_ERROR_NO_EXIST, "could not open file "
"\"%s\": %s", filename, strerror(errno));
return -1;
}
if (playlist_saveAbsolutePaths && song->type == SONG_TYPE_FILE)
s = rmp2amp(utf8ToFsCharset(getSongUrl(song)));
else
s = utf8ToFsCharset(getSongUrl(song));
fprintf(file, "%s\n", s);
while (fclose(file) != 0 && errno == EINTR);
return 0;
}
void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist)
{
int i;
for (i = 0; i < playlist->length; i++)
appendSongToStoredPlaylist(sp, playlist->songs[i]);
}
int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to)
{
struct stat st;
char *from;
char *to;
int ret = 0;
from = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8from, fd));
if (!from)
return -1;
to = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8to, fd));
if (!to) {
free(from);
return -1;
}
if (stat(from, &st) != 0) {
commandError(fd, ACK_ERROR_NO_EXIST,
"no playlist named \"%s\"", utf8from);
ret = -1;
goto out;
}
if (stat(to, &st) == 0) {
commandError(fd, ACK_ERROR_EXIST, "a file or directory "
"already exists with the name \"%s\"", utf8to);
ret = -1;
goto out;
}
if (rename(from, to) < 0) {
commandError(fd, ACK_ERROR_UNKNOWN,
"could not rename playlist \"%s\" to \"%s\": %s",
utf8from, utf8to, strerror(errno));
ret = -1;
goto out;
}
out:
free(from);
free(to);
return ret;
}
/* the Music Player Daemon (MPD)
* Copyright (C) 2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef STORED_PLAYLIST_H
#define STORED_PLAYLIST_H
#include "song.h"
#include "list.h"
#include "playlist.h"
typedef struct _storedPlaylist {
List *list;
unsigned int length;
char *fspath;
int fd;
} StoredPlaylist;
StoredPlaylist *newStoredPlaylist(const char *filename, int fd, int ignoreExisting);
StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd);
void freeStoredPlaylist(StoredPlaylist *sp);
int moveSongInStoredPlaylistByPath(int fd, const char *utf8path, int src, int dest);
int removeAllFromStoredPlaylistByPath(int fd, const char *utf8path);
int removeOneSongFromStoredPlaylistByPath(int fd, const char *utf8path, int pos);
int writeStoredPlaylist(StoredPlaylist *sp);
int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song);
void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist);
int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to);
#endif
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "tagTracker.h" #include "tagTracker.h"
#include "mpd_types.h" #include "mpd_types.h"
#include "gcc.h" #include "gcc.h"
#include "song.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -41,6 +42,9 @@ ...@@ -41,6 +42,9 @@
# ifndef ID3_FRAME_COMPOSER # ifndef ID3_FRAME_COMPOSER
# define ID3_FRAME_COMPOSER "TCOM" # define ID3_FRAME_COMPOSER "TCOM"
# endif # endif
# ifndef ID3_FRAME_PERFORMER
# define ID3_FRAME_PERFORMER "TOPE"
# endif
# ifndef ID3_FRAME_DISC # ifndef ID3_FRAME_DISC
# define ID3_FRAME_DISC "TPOS" # define ID3_FRAME_DISC "TPOS"
# endif # endif
...@@ -99,9 +103,8 @@ void initTagConfig(void) ...@@ -99,9 +103,8 @@ void initTagConfig(void)
} }
} }
if (strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) { if (strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) {
ERROR("error parsing metadata item \"%s\" at " FATAL("error parsing metadata item \"%s\" at "
"line %i\n", c, param->line); "line %i\n", c, param->line);
exit(EXIT_FAILURE);
} }
s++; s++;
c = s; c = s;
...@@ -112,12 +115,22 @@ void initTagConfig(void) ...@@ -112,12 +115,22 @@ void initTagConfig(void)
free(temp); free(temp);
} }
void printTagTypes(int fd)
{
int i;
for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if (ignoreTagItems[i] == 0)
fdprintf(fd, "tagtype: %s\n", mpdTagItemKeys[i]);
}
}
void printMpdTag(int fd, MpdTag * tag) void printMpdTag(int fd, MpdTag * tag)
{ {
int i; int i;
if (tag->time >= 0) if (tag->time >= 0)
fdprintf(fd, "Time: %i\n", tag->time); fdprintf(fd, SONG_TIME "%i\n", tag->time);
for (i = 0; i < tag->numOfItems; i++) { for (i = 0; i < tag->numOfItems; i++) {
fdprintf(fd, "%s: %s\n", mpdTagItemKeys[tag->items[i].type], fdprintf(fd, "%s: %s\n", mpdTagItemKeys[tag->items[i].type],
...@@ -195,6 +208,7 @@ MpdTag *parseId3Tag(struct id3_tag * tag) ...@@ -195,6 +208,7 @@ MpdTag *parseId3Tag(struct id3_tag * tag)
ret = getID3Info(tag, ID3_FRAME_YEAR, TAG_ITEM_DATE, ret); ret = getID3Info(tag, ID3_FRAME_YEAR, TAG_ITEM_DATE, ret);
ret = getID3Info(tag, ID3_FRAME_GENRE, TAG_ITEM_GENRE, ret); ret = getID3Info(tag, ID3_FRAME_GENRE, TAG_ITEM_GENRE, ret);
ret = getID3Info(tag, ID3_FRAME_COMPOSER, TAG_ITEM_COMPOSER, ret); ret = getID3Info(tag, ID3_FRAME_COMPOSER, TAG_ITEM_COMPOSER, ret);
ret = getID3Info(tag, ID3_FRAME_PERFORMER, TAG_ITEM_PERFORMER, ret);
ret = getID3Info(tag, ID3_FRAME_COMMENT, TAG_ITEM_COMMENT, ret); ret = getID3Info(tag, ID3_FRAME_COMMENT, TAG_ITEM_COMMENT, ret);
ret = getID3Info(tag, ID3_FRAME_DISC, TAG_ITEM_DISC, ret); ret = getID3Info(tag, ID3_FRAME_DISC, TAG_ITEM_DISC, ret);
...@@ -421,6 +435,8 @@ MpdTag *apeDup(char *file) ...@@ -421,6 +435,8 @@ MpdTag *apeDup(char *file)
/* read tag into buffer */ /* read tag into buffer */
tagLen -= sizeof(footer); tagLen -= sizeof(footer);
if (tagLen <= 0)
goto fail;
buffer = xmalloc(tagLen); buffer = xmalloc(tagLen);
if (fread(buffer, 1, tagLen, fp) != tagLen) if (fread(buffer, 1, tagLen, fp) != tagLen)
goto fail; goto fail;
...@@ -483,9 +499,8 @@ MpdTag *newMpdTag(void) ...@@ -483,9 +499,8 @@ MpdTag *newMpdTag(void)
static void deleteItem(MpdTag * tag, int index) static void deleteItem(MpdTag * tag, int index)
{ {
tag->numOfItems--;
assert(index < tag->numOfItems); assert(index < tag->numOfItems);
tag->numOfItems--;
removeTagItemString(tag->items[index].type, tag->items[index].value); removeTagItemString(tag->items[index].type, tag->items[index].value);
/* free(tag->items[index].value); */ /* free(tag->items[index].value); */
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -78,6 +78,8 @@ void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len); ...@@ -78,6 +78,8 @@ void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char *value, int len);
#define addItemToMpdTag(tag, itemType, value) \ #define addItemToMpdTag(tag, itemType, value) \
addItemToMpdTagWithLen(tag, itemType, value, strlen(value)) addItemToMpdTagWithLen(tag, itemType, value, strlen(value))
void printTagTypes(int fd);
void printMpdTag(int fd, MpdTag * tag); void printMpdTag(int fd, MpdTag * tag);
MpdTag *mpdTagDup(MpdTag * tag); MpdTag *mpdTagDup(MpdTag * tag);
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -26,15 +26,7 @@ ...@@ -26,15 +26,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
static Tree *tagTrees[TAG_NUM_OF_ITEM_TYPES] = { static Tree *tagTrees[TAG_NUM_OF_ITEM_TYPES];
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
typedef struct tagTrackerItem { typedef struct tagTrackerItem {
int count; int count;
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2006-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2006-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -73,7 +73,7 @@ static int volume_ossControl = SOUND_MIXER_PCM; ...@@ -73,7 +73,7 @@ static int volume_ossControl = SOUND_MIXER_PCM;
#endif #endif
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
static snd_mixer_t *volume_alsaMixerHandle = NULL; static snd_mixer_t *volume_alsaMixerHandle;
static snd_mixer_elem_t *volume_alsaElem; static snd_mixer_elem_t *volume_alsaElem;
static long volume_alsaMin; static long volume_alsaMin;
static long volume_alsaMax; static long volume_alsaMax;
...@@ -430,9 +430,8 @@ void initVolume(void) ...@@ -430,9 +430,8 @@ void initVolume(void)
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT; volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
} else { } else {
ERROR("unknown mixer type %s at line %i\n", FATAL("unknown mixer type %s at line %i\n",
param->value, param->line); param->value, param->line);
exit(EXIT_FAILURE);
} }
} }
......
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
/* the Music Player Daemon (MPD)
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "zeroconf.h"
#include "conf.h"
#include "log.h"
#include "listen.h"
#include "ioops.h"
#include "utils.h"
/* The dns-sd service type qualifier to publish */
#define SERVICE_TYPE "_mpd._tcp"
/* The default service name to publish
* (overridden by 'zeroconf_name' config parameter)
*/
#define SERVICE_NAME "Music Player"
/* Here is the implementation for Avahi (http://avahi.org) Zeroconf support */
#ifdef HAVE_AVAHI
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/alternative.h>
#include <avahi-common/domain.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
/* Static avahi data */
static AvahiEntryGroup *avahiGroup;
static char *avahiName;
static AvahiClient* avahiClient;
static AvahiPoll avahiPoll;
static int avahiRunning;
static int avahiFdset( fd_set* rfds, fd_set* wfds, fd_set* efds );
static int avahiFdconsume( int fdCount, fd_set* rfds, fd_set* wfds, fd_set* efds );
static struct ioOps avahiIo = {
.fdset = avahiFdset,
.consume = avahiFdconsume,
};
/* Forward Declaration */
static void avahiRegisterService(AvahiClient *c);
struct AvahiWatch {
struct AvahiWatch* prev;
struct AvahiWatch* next;
int fd;
AvahiWatchEvent requestedEvent;
AvahiWatchEvent observedEvent;
AvahiWatchCallback callback;
void* userdata;
};
struct AvahiTimeout {
struct AvahiTimeout* prev;
struct AvahiTimeout* next;
struct timeval expiry;
int enabled;
AvahiTimeoutCallback callback;
void* userdata;
};
static AvahiWatch* avahiWatchList;
static AvahiTimeout* avahiTimeoutList;
static AvahiWatch* avahiWatchNew( const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata )
{
struct AvahiWatch* newWatch = xmalloc( sizeof(struct AvahiWatch) );
newWatch->fd = fd;
newWatch->requestedEvent = event;
newWatch->observedEvent = 0;
newWatch->callback = callback;
newWatch->userdata = userdata;
/* Insert at front of list */
newWatch->next = avahiWatchList;
avahiWatchList = newWatch;
newWatch->prev = NULL;
if( newWatch->next )
newWatch->next->prev = newWatch;
return newWatch;
}
static void avahiWatchUpdate( AvahiWatch *w, AvahiWatchEvent event )
{
assert( w != NULL );
w->requestedEvent = event;
}
static AvahiWatchEvent avahiWatchGetEvents( AvahiWatch *w )
{
assert( w != NULL );
return w->observedEvent;
}
static void avahiWatchFree( AvahiWatch *w )
{
assert( w != NULL );
if( avahiWatchList == w )
avahiWatchList = w->next;
else if( w->prev != NULL )
w->prev->next = w->next;
free( w );
}
static void avahiCheckExpiry( AvahiTimeout *t )
{
assert( t != NULL );
if( t->enabled ) {
struct timeval now;
gettimeofday( &now, NULL );
if( timercmp( &now, &(t->expiry), > ) ) {
t->enabled = 0;
t->callback( t, t->userdata );
}
}
}
static void avahiTimeoutUpdate( AvahiTimeout *t, const struct timeval *tv )
{
assert( t != NULL );
if( tv ) {
t->enabled = 1;
t->expiry.tv_sec = tv->tv_sec;
t->expiry.tv_usec = tv->tv_usec;
} else {
t->enabled = 0;
}
}
static void avahiTimeoutFree( AvahiTimeout *t )
{
assert( t != NULL );
if( avahiTimeoutList == t )
avahiTimeoutList = t->next;
else if( t->prev != NULL )
t->prev->next = t->next;
free( t );
}
static AvahiTimeout* avahiTimeoutNew( const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata )
{
struct AvahiTimeout* newTimeout = xmalloc( sizeof(struct AvahiTimeout) );
newTimeout->callback = callback;
newTimeout->userdata = userdata;
avahiTimeoutUpdate( newTimeout, tv );
/* Insert at front of list */
newTimeout->next = avahiTimeoutList;
avahiTimeoutList = newTimeout;
newTimeout->prev = NULL;
if( newTimeout->next )
newTimeout->next->prev = newTimeout;
return newTimeout;
}
/* Callback when the EntryGroup changes state */
static void avahiGroupCallback(
AvahiEntryGroup *g,
AvahiEntryGroupState state,
void *userdata)
{
assert(g);
DEBUG( "Avahi: Service group changed to state %d\n", state );
switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED :
/* The entry group has been established successfully */
LOG( "Avahi: Service '%s' successfully established.\n", avahiName );
break;
case AVAHI_ENTRY_GROUP_COLLISION : {
char *n;
/* A service name collision happened. Let's pick a new name */
n = avahi_alternative_service_name(avahiName);
avahi_free(avahiName);
avahiName = n;
LOG( "Avahi: Service name collision, renaming service to '%s'\n", avahiName );
/* And recreate the services */
avahiRegisterService(avahi_entry_group_get_client(g));
break;
}
case AVAHI_ENTRY_GROUP_FAILURE :
ERROR( "Avahi: Entry group failure: %s\n",
avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) );
/* Some kind of failure happened while we were registering our services */
avahiRunning = 0;
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
DEBUG( "Avahi: Service group is UNCOMMITED\n" );
break;
case AVAHI_ENTRY_GROUP_REGISTERING:
DEBUG( "Avahi: Service group is REGISTERING\n" );
;
}
}
/* Registers a new service with avahi */
static void avahiRegisterService(AvahiClient *c)
{
int ret;
assert(c);
DEBUG( "Avahi: Registering service %s/%s\n", SERVICE_TYPE, avahiName );
/* If this is the first time we're called, let's create a new entry group */
if (!avahiGroup) {
avahiGroup = avahi_entry_group_new(c, avahiGroupCallback, NULL);
if( !avahiGroup ) {
ERROR( "Avahi: Failed to create avahi EntryGroup: %s\n", avahi_strerror(avahi_client_errno(c)) );
goto fail;
}
}
/* Add the service */
/* TODO: This currently binds to ALL interfaces.
* We could maybe add a service per actual bound interface, if that's better. */
ret = avahi_entry_group_add_service(avahiGroup,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0,
avahiName, SERVICE_TYPE,
NULL, NULL,
getBoundPort(),
NULL);
if( ret < 0 ) {
ERROR( "Avahi: Failed to add service %s: %s\n", SERVICE_TYPE, avahi_strerror(ret) );
goto fail;
}
/* Tell the server to register the service group */
ret = avahi_entry_group_commit(avahiGroup);
if( ret < 0 ) {
ERROR( "Avahi: Failed to commit service group: %s\n", avahi_strerror(ret) );
goto fail;
}
return;
fail:
avahiRunning = 0;
}
/* Callback when avahi changes state */
static void avahiClientCallback(AvahiClient *c, AvahiClientState state, void *userdata)
{
assert(c);
/* Called whenever the client or server state changes */
DEBUG( "Avahi: Client changed to state %d\n", state );
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
DEBUG( "Avahi: Client is RUNNING\n" );
/* The server has startup successfully and registered its host
* name on the network, so it's time to create our services */
if (!avahiGroup)
avahiRegisterService(c);
break;
case AVAHI_CLIENT_FAILURE:
{
int reason = avahi_client_errno(c);
if( reason == AVAHI_ERR_DISCONNECTED ) {
LOG( "Avahi: Client Disconnected, will reconnect shortly\n");
avahi_entry_group_free( avahiGroup );
avahiGroup = NULL;
avahi_client_free( avahiClient );
avahiClient = NULL;
avahiClient = avahi_client_new( &avahiPoll, AVAHI_CLIENT_NO_FAIL,
avahiClientCallback, NULL, &reason );
if( !avahiClient ) {
ERROR( "Avahi: Could not reconnect: %s\n", avahi_strerror(reason) );
avahiRunning = 0;
}
} else {
ERROR( "Avahi: Client failure: %s (terminal)\n", avahi_strerror(reason));
avahiRunning = 0;
}
}
break;
case AVAHI_CLIENT_S_COLLISION:
DEBUG( "Avahi: Client is COLLISION\n" );
/* Let's drop our registered services. When the server is back
* in AVAHI_SERVER_RUNNING state we will register them
* again with the new host name. */
if (avahiGroup) {
DEBUG( "Avahi: Resetting group\n" );
avahi_entry_group_reset(avahiGroup);
}
case AVAHI_CLIENT_S_REGISTERING:
DEBUG( "Avahi: Client is REGISTERING\n" );
/* The server records are now being established. This
* might be caused by a host name change. We need to wait
* for our own records to register until the host name is
* properly esatblished. */
if (avahiGroup) {
DEBUG( "Avahi: Resetting group\n" );
avahi_entry_group_reset(avahiGroup);
}
break;
case AVAHI_CLIENT_CONNECTING:
DEBUG( "Avahi: Client is CONNECTING\n" );
;
}
}
static int avahiFdset( fd_set* rfds, fd_set* wfds, fd_set* efds )
{
AvahiWatch* w;
int maxfd = -1;
if( !avahiRunning )
return maxfd;
for( w = avahiWatchList; w != NULL; w = w->next ) {
if( w->requestedEvent & AVAHI_WATCH_IN ) {
FD_SET( w->fd, rfds );
}
if( w->requestedEvent & AVAHI_WATCH_OUT ) {
FD_SET( w->fd, wfds );
}
if( w->requestedEvent & AVAHI_WATCH_ERR ) {
FD_SET( w->fd, efds );
}
if( w->requestedEvent & AVAHI_WATCH_HUP ) {
ERROR( "Avahi: No support for HUP events! (ignoring)\n" );
}
if( w->fd > maxfd )
maxfd = w->fd;
}
return maxfd;
}
static int avahiFdconsume( int fdCount, fd_set* rfds, fd_set* wfds, fd_set* efds )
{
int retval = fdCount;
AvahiTimeout* t;
AvahiWatch* w = avahiWatchList;
while( w != NULL && retval > 0 ) {
AvahiWatch* current = w;
current->observedEvent = 0;
if( FD_ISSET( current->fd, rfds ) ) {
current->observedEvent |= AVAHI_WATCH_IN;
FD_CLR( current->fd, rfds );
retval--;
}
if( FD_ISSET( current->fd, wfds ) ) {
current->observedEvent |= AVAHI_WATCH_OUT;
FD_CLR( current->fd, wfds );
retval--;
}
if( FD_ISSET( current->fd, efds ) ) {
current->observedEvent |= AVAHI_WATCH_ERR;
FD_CLR( current->fd, efds );
retval--;
}
/* Advance to the next one right now, in case the callback
* removes itself
*/
w = w->next;
if( current->observedEvent && avahiRunning ) {
current->callback( current, current->fd,
current->observedEvent, current->userdata );
}
}
t = avahiTimeoutList;
while( t != NULL && avahiRunning ) {
AvahiTimeout* current = t;
/* Advance to the next one right now, in case the callback
* removes itself
*/
t = t->next;
avahiCheckExpiry( current );
}
return retval;
}
static void init_avahi(const char *serviceName)
{
int error;
DEBUG( "Avahi: Initializing interface\n" );
if( avahi_is_valid_service_name( serviceName ) ) {
avahiName = avahi_strdup( serviceName );
} else {
ERROR( "Invalid zeroconf_name \"%s\", defaulting to \"%s\" instead.\n", serviceName, SERVICE_NAME );
avahiName = avahi_strdup( SERVICE_NAME );
}
avahiRunning = 1;
avahiPoll.userdata = NULL;
avahiPoll.watch_new = avahiWatchNew;
avahiPoll.watch_update = avahiWatchUpdate;
avahiPoll.watch_get_events = avahiWatchGetEvents;
avahiPoll.watch_free = avahiWatchFree;
avahiPoll.timeout_new = avahiTimeoutNew;
avahiPoll.timeout_update = avahiTimeoutUpdate;
avahiPoll.timeout_free = avahiTimeoutFree;
avahiClient = avahi_client_new( &avahiPoll, AVAHI_CLIENT_NO_FAIL,
avahiClientCallback, NULL, &error );
if( !avahiClient ) {
ERROR( "Avahi: Failed to create client: %s\n", avahi_strerror(error) );
goto fail;
}
avahiIo.fdset = avahiFdset;
avahiIo.consume = avahiFdconsume;
registerIO( &avahiIo );
return;
fail:
finishZeroconf();
}
#else /* !HAVE_AVAHI */
static void init_avahi(const char *serviceName) { }
#endif /* HAVE_AVAHI */
void initZeroconf(void)
{
const char* serviceName = SERVICE_NAME;
ConfigParam *param;
param = getConfigParam(CONF_ZEROCONF_NAME);
if (param && strlen(param->value) > 0)
serviceName = param->value;
init_avahi(serviceName);
}
void finishZeroconf(void)
{
#ifdef HAVE_AVAHI
DEBUG( "Avahi: Shutting down interface\n" );
deregisterIO( &avahiIo );
if( avahiGroup ) {
avahi_entry_group_free( avahiGroup );
avahiGroup = NULL;
}
if( avahiClient ) {
avahi_client_free( avahiClient );
avahiClient = NULL;
}
avahi_free( avahiName );
avahiName = NULL;
#endif /* HAVE_AVAHI */
}
/* the Music Player Daemon (MPD)
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ZEROCONF_H
#define ZEROCONF_H
#include "../config.h"
void initZeroconf(void);
void finishZeroconf(void);
#endif
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