Commit 1e5f57f4 authored by Led's avatar Led

0.14-beta1

parent 1a029af0
......@@ -27,6 +27,9 @@ Patrik Weiskircher <pat@icore.at>
Laszlo Ashin <kodest@gmail.com>
WavPack support
Viliam Mateicka <viliam.mateicka@gmail.com>
FFmpeg support
Former Developers
-----------------
tw-nym
......
......@@ -39,8 +39,7 @@ host_triplet = @host@
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/configure AUTHORS COPYING INSTALL NEWS TODO \
compile config.guess config.sub depcomp install-sh ltmain.sh \
missing
compile config.guess config.sub depcomp install-sh missing
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
......@@ -178,6 +177,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
......@@ -235,6 +236,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
......
......@@ -84,29 +84,6 @@ do
fi
done
if test -n "$LIBTOOLIZE"
then
echo "LIBTOOLIZE=$LIBTOOLIZE in environment," \
"will not attempt to auto-detect"
else
printf "checking for libtoolize ... "
for x in libtoolize glibtoolize
do
($x --version < /dev/null > /dev/null 2>&1) > /dev/null 2>&1
if test $? -eq 0
then
echo $x
LIBTOOLIZE=$x
break
fi
done
fi
if test -z "$LIBTOOLIZE"
then
DIE="$DIE libtoolize(libtool)"
fi
if test -n "$DIE"
then
echo "You must have the following installed to compile $package:"
......@@ -148,9 +125,6 @@ $ACLOCAL $ACLOCAL_FLAGS || exit 1
echo " $AUTOHEADER"
$AUTOHEADER || exit 1
echo " $LIBTOOLIZE --automake"
$LIBTOOLIZE --automake || exit 1
echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
......
......@@ -37,6 +37,9 @@
/* Define if FAAD2 uses buflen in function calls */
#undef HAVE_FAAD_BUFLEN_FUNCS
/* Define if faad.h uses the broken "unsigned long" pointers */
#undef HAVE_FAAD_LONG
/* Define for FFMPEG support */
#undef HAVE_FFMPEG
......
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.63 for mpd 0.14~alpha3.
# Generated by GNU Autoconf 2.63 for mpd 0.14~beta1.
#
# Report bugs to <musicpd-dev-team@lists.sourceforge.net>.
#
......@@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='mpd'
PACKAGE_TARNAME='mpd'
PACKAGE_VERSION='0.14~alpha3'
PACKAGE_STRING='mpd 0.14~alpha3'
PACKAGE_VERSION='0.14~beta1'
PACKAGE_STRING='mpd 0.14~beta1'
PACKAGE_BUGREPORT='musicpd-dev-team@lists.sourceforge.net'
ac_unique_file="src/main.c"
......@@ -639,6 +639,9 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
HAVE_XMLTO_FALSE
HAVE_XMLTO_TRUE
XMLTO
HAVE_ZEROCONF_FALSE
HAVE_ZEROCONF_TRUE
AVAHI_LIBS
......@@ -1478,7 +1481,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures mpd 0.14~alpha3 to adapt to many kinds of systems.
\`configure' configures mpd 0.14~beta1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
......@@ -1548,7 +1551,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of mpd 0.14~alpha3:";;
short | recursive ) echo "Configuration of mpd 0.14~beta1:";;
esac
cat <<\_ACEOF
......@@ -1746,7 +1749,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
mpd configure 0.14~alpha3
mpd configure 0.14~beta1
generated by GNU Autoconf 2.63
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
......@@ -1760,7 +1763,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by mpd $as_me 0.14~alpha3, which was
It was created by mpd $as_me 0.14~beta1, which was
generated by GNU Autoconf 2.63. Invocation command line was
$ $0 $@
......@@ -2457,7 +2460,7 @@ fi
# Define the identity of the package.
PACKAGE='mpd'
VERSION='0.14~alpha3'
VERSION='0.14~beta1'
cat >>confdefs.h <<_ACEOF
......@@ -9989,6 +9992,71 @@ fi
if test x$enable_aac = xyes; then
oldcflags=$CFLAGS
oldlibs=$LIBS
oldcppflags=$CPPFLAGS
CFLAGS="$CFLAGS $MPD_CFLAGS $FAAD_CFLAGS -Werror"
LIBS="$LIBS $MPD_LIBS $FAAD_LIBS"
CPPFLAGS=$CFLAGS
{ $as_echo "$as_me:$LINENO: checking for broken libfaad headers" >&5
$as_echo_n "checking for broken libfaad headers... " >&6; }
cat >conftest.$ac_ext <<_ACEOF
#include <faad.h>
#include <stddef.h>
#include <stdint.h>
int main() {
unsigned char channels;
uint32_t sample_rate;
faacDecInit2(NULL, NULL, 0, &sample_rate, &channels);
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
{ $as_echo "$as_me:$LINENO: result: correct" >&5
$as_echo "correct" >&6; }
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ $as_echo "$as_me:$LINENO: result: broken" >&5
$as_echo "broken" >&6; };
cat >>confdefs.h <<\_ACEOF
#define HAVE_FAAD_LONG 1
_ACEOF
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$oldcflags
LIBS=$oldlibs
CPPFLAGS=$oldcppflags
fi
if test x$enable_aac = xyes; then
enable_mp4=yes
MP4FF_LIBS="-lmp4ff"
......@@ -11678,6 +11746,70 @@ fi
{ $as_echo "$as_me:$LINENO: checking for xmlto (DocBook processing)" >&5
$as_echo_n "checking for xmlto (DocBook processing)... " >&6; }
# Extract the first word of "xmlto", so it can be a program name with args.
set dummy xmlto; ac_word=$2
{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_path_XMLTO+set}" = set; then
$as_echo_n "(cached) " >&6
else
case $XMLTO in
[\\/]* | ?:[\\/]*)
ac_cv_path_XMLTO="$XMLTO" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_XMLTO="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
XMLTO=$ac_cv_path_XMLTO
if test -n "$XMLTO"; then
{ $as_echo "$as_me:$LINENO: result: $XMLTO" >&5
$as_echo "$XMLTO" >&6; }
else
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$XMLTO != x; then
{ $as_echo "$as_me:$LINENO: result: $XMLTO" >&5
$as_echo "$XMLTO" >&6; }
else
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$XMLTO != x; then
HAVE_XMLTO_TRUE=
HAVE_XMLTO_FALSE='#'
else
HAVE_XMLTO_TRUE='#'
HAVE_XMLTO_FALSE=
fi
if test "x$ENABLE_WERROR" = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -Werror -pedantic-errors"
fi
......@@ -12615,6 +12747,13 @@ $as_echo "$as_me: error: conditional \"HAVE_ZEROCONF\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
if test -z "${HAVE_XMLTO_TRUE}" && test -z "${HAVE_XMLTO_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"HAVE_XMLTO\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
$as_echo "$as_me: error: conditional \"HAVE_XMLTO\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
: ${CONFIG_STATUS=./config.status}
ac_write_fail=0
......@@ -12937,7 +13076,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by mpd $as_me 0.14~alpha3, which was
This file was extended by mpd $as_me 0.14~beta1, which was
generated by GNU Autoconf 2.63. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
......@@ -13000,7 +13139,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
mpd config.status 0.14~alpha3
mpd config.status 0.14~beta1
configured by $0, generated by GNU Autoconf 2.63,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
......
AC_PREREQ(2.60)
AC_INIT(mpd, 0.14~alpha3, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.14~beta1, musicpd-dev-team@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
AM_CONFIG_HEADER(config.h)
......@@ -623,6 +623,37 @@ fi
AM_CONDITIONAL(HAVE_FAAD, test x$enable_aac = xyes)
if test x$enable_aac = xyes; then
oldcflags=$CFLAGS
oldlibs=$LIBS
oldcppflags=$CPPFLAGS
CFLAGS="$CFLAGS $MPD_CFLAGS $FAAD_CFLAGS -Werror"
LIBS="$LIBS $MPD_LIBS $FAAD_LIBS"
CPPFLAGS=$CFLAGS
AC_MSG_CHECKING(for broken libfaad headers)
AC_COMPILE_IFELSE([
#include <faad.h>
#include <stddef.h>
#include <stdint.h>
int main() {
unsigned char channels;
uint32_t sample_rate;
faacDecInit2(NULL, NULL, 0, &sample_rate, &channels);
return 0;
}
],
[AC_MSG_RESULT(correct)],
[AC_MSG_RESULT(broken);
AC_DEFINE(HAVE_FAAD_LONG, 1, [Define if faad.h uses the broken "unsigned long" pointers])])
CFLAGS=$oldcflags
LIBS=$oldlibs
CPPFLAGS=$oldcppflags
fi
if test x$enable_aac = xyes; then
enable_mp4=yes
MP4FF_LIBS="-lmp4ff"
......@@ -822,6 +853,22 @@ AM_CONDITIONAL(HAVE_ZEROCONF, test x$with_zeroconf != xno)
dnl
dnl Documentation
dnl
AC_MSG_CHECKING([for xmlto (DocBook processing)])
AC_PATH_PROG(XMLTO, xmlto)
if test x$XMLTO != x; then
AC_SUBST(XMLTO)
AC_MSG_RESULT($XMLTO)
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(HAVE_XMLTO, test x$XMLTO != x)
dnl
dnl build options
dnl
......
Music Player Daemon - Commands
WARNING
This document has not been updated to reflect recent changes in
the MPD protocol. It does not contain all supported commands,
and some commands may now take additional arguments. However,
clients conforming to this specification should still be
compatible with the latest release of MPD. For more up to date
documentation, please see the protocol reference on the wiki at
<http://mpd.wikia.com/wiki/Protocol_Reference>.
This document is intended for client developers, not end users.
Format:
-------
If arguments contain spaces, they should be surrounded by double quotation
marks, ".
command <type arg1> <type arg2> ...
explanation: w/ arg1 and arg2
All data between the client and server is encoded in UTF-8. (Note,
that in UTF-8 all standard ansi characters, 0-127, are the same as a standard
ansi encoding. Also, no ansi character appears in any multi-byte
characters. So, you can use standard C functions like strlen, and strcpy
just fine with UTF-8 encoded strings. For example: "OK\n" encoded in UTF-8 is
simply "OK\n". For more information on UTF=8:
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 )
Command Completion:
-------------------
A command returns "OK\n" on completion or "ACK some error\n" on failure.
These denote the end of command execution.
NOTE:
-----
For manipulating playlists and playing, there are two sets of commands. One
set uses the song id of a song in the playlist, while another set uses the
playlist position of the song. The commands using song id's should be used
instead of the commands that manipulate and control playback based on playlist
position. Using song id's is a safer method when multiple clients are
interacting with MPD.
Commands:
---------
add <string path>
add the file _path_ to the playlist (directories add recursively)
_path_ can also be a single file
increments playlist version by for each song added
addid <string path> <int position>
_path_ is always a single file or URL
_position_ is optional, a negative number means it is relative
to the currently playing song in the playlist (if there is one)
adds a song to the playlist (non-recursive) and returns the song id;
example:
addid "foo.mp3"
Id: 999
OK
clear
clears the current playlist
increments playlist version by 1
clearerror
clear the current error message in status
(this is also accomplished by any command that starts playback)
close
close the connection with the MPD
crossfade <int seconds>
sets crossfading between songs
currentsong
displays the song info of current song (same song that is identified
in status)
delete <int song>
delete _song_ from playlist
increments playlist version by 1
deleteid <int songid>
delete song with _songid_ from playlist
increments playlist version by 1
find <string type> <string what>
finds songs in the db that are exactly _what_
_type_ should be "album", "artist", or "title"
_what_ is what to find
kill
kill MPD
list <string type> <string arg1>
list all tags of _type_
_type_ should be "album" or "artist"
_arg1_ is an optional parameter when type is album, this specifies
to list albums by a artist, where artist is specified with
arg1
listall <string path>
lists all songs and directories in _path_ (recursively)
_path_ is optional and maybe a directory or path
listallinfo <string path>
same as listall command, except it also returns metadata info
in the same format as lsinfo
load <string name>
loads the playlist _name_.m3u from the playlist directory
increments playlist version by the number of songs added
lsinfo <string directory>
list contents of _directory_, from the db. _directory_ is optional
When listing the root directory, this currently returns the
list of stored playlists. This behavior is deprecated; use
"listplaylists" instead.
move <int from> <int to>
move song at _from_ to _to_ in the playlist
increments playlist version by 1
moveid <int songid> <int to>
move song with _songid_ to _to_ in the playlist
increments playlist version by 1
if _to_ is negative, it is relative to the current song in
the playlist (if there is one).
next
plays next song in playlist
pause <bool pause>
toggle pause/resume playing
_pause_ is required and should be 0 or 1
NOTE: use of pause command w/o the _pause_ argument is deprecated
password <string password>
this is used for authentication with the server.
_password_ is simply the plaintext password
ping
does nothing but return "OK"
play <int song>
begin playing playlist at song number _song_, _song_ is optional
playid <int songid>
begin playing playlist at song with _songid_, _songid_ is optional
playlist
displays the current playlist
NOTE: do not use this, instead use 'playlistinfo'
playlistinfo <int song>
displays list of songs in the playlist
_song_ is optional and specifies a single song to display info for
playlistid <int songid>
displays list of songs in the playlist
_songid_ is optional and specifies a single song to display info for
plchanges <playlist version>
displays changed songs currently in the playlist since
_playlist version_
NOTE: to detect songs that were deleted at the end of the playlist,
use playlistlength returned by status command.
plchangesposid <playlist version>
displays changed songs currently in the playlist since
_playlist version_
This function only returns the position and the id of the changed song, not the complete metadata. This is more bandwidth efficient.
NOTE: to detect songs that were deleted at the end of the playlist,
use playlistlength returned by status command.
previous
plays previous song in playlist
random <int state>
set random state to _state_, _state_ should be 0 or 1
repeat <int state>
set repeat state to _state_, _state_ should be 0 or 1
listplaylists
prints a list of the playlist directory
After each playlist name, the server sends its last
modification time as attribute "Last-Modified" in ISO 8601
format. To avoid problems due to clock differences between
clients and the server, clients should not compare this value
with their local clock.
rm <string name>
removes the playlist <name>.m3u from the playlist directory
save <string name>
saves the current playlist to _name_.m3u in the playlist directory
search <string type> <string what>
searches for any song that contain _what_
_type_ can be "title","artist","album", or "filename"
search is not case sensitive
seek <int song> <int time>
seeks to the position _time_ (in seconds) of entry _song_ in the
playlist
seekid <int songid> <int time>
seeks to the position _time_ (in seconds) of song with _songid_
setvol <int vol>
set volume to _vol_
_vol_ the range of volume is 0-100
shuffle
shuffles the current playlist
increments playlist version by 1
stats
display stats
artists: number of artists
albums: number of albums
songs: number of songs
uptime: daemon uptime in seconds
db_playtime: sum of all song times in db
db_update: last db update in UNIX time
playtime: time length of music played
status
reports current status of player, and volume level.
volume: (0-100).
repeat: (0 or 1)
playlist: (31-bit unsigned integer, the playlist version number)
playlistlength: (integer, the length of the playlist)
state: ("play", "stop", or "pause")
song: (current song stopped on or playing, playlist song number)
songid: (current song stopped on or playing, playlist songid)
time: <int elapsed>:<time total> (of current playing/paused song)
bitrate: <int bitrate> (instantaneous bitrate in kbps)
xfade: <int seconds> (crossfade in seconds)
audio: <int sampleRate>:<int bits>:<int channels>
updatings_db: <int job id>
error: if there is an error, returns message here
stop
stop playing
swap <int song1> <int song2>
swap positions of _song1_ and _song2_
increments playlist version by 1
swapid <int songid1> <int songid2>
swap positions of of songs with song id's of _songid1_ and _songid2_
increments playlist version by 1
update <string path>
searches mp3 directory for new music and removes old music from the db
_path_ is an optional argument that maybe a particular directory or
song/file to update.
returned:
updating_db: <int job id>
where job id, is the job id requested for your update, and is displayed
in status, while the requested update is happening
increments playlist version by 1
NOTE: To update a number of paths/songs at once, use command_list,
it will be much more faster/efficient. Also, if you use a
command_list for updating, only one update_db job id will be returned
per sequence of updates.
volume <int change>
change volume by amount _change_
NOTE: volume command is deprecated, use setvol instead
idle
Waits until there is a noteworthy change in one or more of
MPD's subsystems. As soon as there is one, it lists all
changed systems in a line in the format "changed: SUBSYSTEM",
where SUBSYSTEM is one of the following:
database: the song database has been updated
stored_playlist: a stored playlist has been modified, renamed,
created or deleted
playlist: the current playlist has been modified
player: the player has been started, stopped or seeked
mixer: the volume has been changed
output: an audio output has been enabled or disabled
options: options like "repeat", "random", "crossfade"
While a client waits for "idle" results, the server disables
timeouts, allowing a client to wait for events as long as mpd
runs. The "idle" command can be canceled by sending the
command "noidle" (no other commands are allowed). MPD will
then leave "idle" mode and print results immediately; might be
empty at this time.
COMMAND LIST
------------
To facilitate faster adding of files, etc, you can pass a list of commands all
at once using a command list. The command list beings with:
command_list_begin
or:
command_list_ok_begin
And ends with:
command_list_end
It does not execute any commands until the list has ended. The return
value is whatever the return for a list of commands is. On success
for all commands, OK is returned. If a command fails, no more commands
are executed and the appropriate ACK error is returned. If
"command_list_ok_begin is used", "list_OK\n" is returned for each
successful command executed in the command list.
DOCBOOK_FILES = protocol.xml
DOCBOOK_HTML = $(patsubst %.xml,%.html,$(DOCBOOK_FILES))
man_MANS = mpd.1 mpd.conf.5
doc_DATA = COMMANDS mpdconf.example
EXTRA_DIST = $(man_MANS) $(doc_DATA)
doc_DATA = mpdconf.example
EXTRA_DIST = $(man_MANS) $(DOCBOOK_FILES) mpdconf.example
MOSTLYCLEANFILES = $(DOCBOOK_HTML)
if HAVE_XMLTO
doc_DATA += $(DOCBOOK_HTML)
$(DOCBOOK_HTML): %.html: %.xml
$(XMLTO) html-nochunks $<
endif
......@@ -36,6 +36,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@HAVE_XMLTO_TRUE@am__append_1 = $(DOCBOOK_HTML)
subdir = doc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
......@@ -158,6 +159,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
......@@ -215,6 +218,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
......@@ -259,9 +263,12 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
DOCBOOK_FILES = protocol.xml
DOCBOOK_HTML = $(patsubst %.xml,%.html,$(DOCBOOK_FILES))
man_MANS = mpd.1 mpd.conf.5
doc_DATA = COMMANDS mpdconf.example
EXTRA_DIST = $(man_MANS) $(doc_DATA)
doc_DATA = mpdconf.example $(am__append_1)
EXTRA_DIST = $(man_MANS) $(DOCBOOK_FILES) mpdconf.example
MOSTLYCLEANFILES = $(DOCBOOK_HTML)
all: all-am
.SUFFIXES:
......@@ -458,6 +465,7 @@ install-strip:
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
......@@ -526,6 +534,9 @@ uninstall-man: uninstall-man1 uninstall-man5
uninstall-docDATA uninstall-info-am uninstall-man \
uninstall-man1 uninstall-man5
@HAVE_XMLTO_TRUE@$(DOCBOOK_HTML): %.html: %.xml
@HAVE_XMLTO_TRUE@ $(XMLTO) html-nochunks $<
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"docbook/dtd/xml/4.2/docbookx.dtd">
<book>
<title>The Music Player Daemon protocol</title>
<chapter>
<title>General protocol syntax</title>
<section>
<title>Requests</title>
<para>
If arguments contain spaces, they should be surrounded by double quotation
marks.
</para>
<cmdsynopsis>
<command>COMMAND</command>
<arg rep="repeat"><replaceable>ARG</replaceable></arg>
</cmdsynopsis>
<para>
All data between the client and the server is encoded in
UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are
the same as a standard ansi encoding. Also, no ansi character
appears in any multi-byte characters. So, you can use
standard C functions like <function>strlen</function>, and
<function>strcpy</function> just fine with UTF-8 encoded
strings. For example: <returnvalue>OK</returnvalue> encoded in
UTF-8 is simply <returnvalue>OK</returnvalue>. For more
information on UTF=8:
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
</para>
</section>
<section>
<title>Responses</title>
<para>
A command returns <returnvalue>OK</returnvalue> on completion
or <returnvalue>ACK some error</returnvalue> on failure.
These denote the end of command execution.
</para>
</section>
<section>
<title>Command lists</title>
<para>
To facilitate faster adding of files etc. you can pass a list
of commands all at once using a command list. The command
list beings with <command>command_list_begin</command> or
<command>command_list_ok_begin</command> and ends with
<command>command_list_end</command>.
</para>
<para>
It does not execute any commands until the list has ended.
The return value is whatever the return for a list of commands
is. On success for all commands,
<returnvalue>OK</returnvalue> is returned. If a command
fails, no more commands are executed and the appropriate
<returnvalue>ACK</returnvalue> error is returned. If
<command>command_list_begin</command> is used,
<returnvalue>list_OK</returnvalue> is returned for each
successful command executed in the command list.
</para>
</section>
</chapter>
<chapter>
<title>Command reference</title>
<note>
<para>
For manipulating playlists and playing, there are two sets of
commands. One set uses the song id of a song in the playlist,
while another set uses the playlist position of the song. The
commands using song ids should be used instead of the commands
that manipulate and control playback based on playlist
position. Using song ids is a safer method when multiple
clients are interacting with MPD.
</para>
</note>
<section>
<title>Querying MPD's status</title>
<variablelist>
<varlistentry id="command_clearerror">
<term>
<cmdsynopsis>
<command>clearerror</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Clears the current error message in status (this is also
accomplished by any command that starts playback).
</para>
</listitem>
</varlistentry>
<varlistentry id="command_currentsong">
<term>
<cmdsynopsis>
<command>currentsong</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays the song info of the current song (same song that
is identified in status).
</para>
</listitem>
</varlistentry>
<varlistentry id="command_idle">
<term>
<cmdsynopsis>
<command>idle</command>
<arg choice="opt" rep="repeat"><replaceable>SUBSYSTEMS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Waits until there is a noteworthy change in one or more
of MPD's subsystems. As soon as there is one, it lists
all changed systems in a line in the format
<returnvalue>changed: SUBSYSTEM</returnvalue>, where
SUBSYSTEM is one of the following:
</para>
<itemizedlist>
<listitem>
<para>
<returnvalue>database</returnvalue>: the song database
has been updated
</para>
</listitem>
<listitem>
<para>
<returnvalue>stored_playlist</returnvalue>: a stored
playlist has been modified, renamed, created or
deleted
</para>
</listitem>
<listitem>
<para>
<returnvalue>playlist</returnvalue>: the current
playlist has been modified
</para>
</listitem>
<listitem>
<para>
<returnvalue>player</returnvalue>: the player has been
started, stopped or seeked
</para>
</listitem>
<listitem>
<para>
<returnvalue>mixer</returnvalue>: the volume has been
changed
</para>
</listitem>
<listitem>
<para>
<returnvalue>output</returnvalue>: an audio output has
been enabled or disabled
</para>
</listitem>
<listitem>
<para>
<returnvalue>options</returnvalue>: options like
<option>repeat</option>, <option>random</option>,
<option>crossfade</option>
</para>
</listitem>
</itemizedlist>
<para>
While a client is waiting for <command>idle</command>
results, the server disables timeouts, allowing a client
to wait for events as long as mpd runs. The
<command>idle</command> command can be canceled by
sending the command <command>noidle</command> (no other
commands are allowed). MPD will then leave
<command>idle</command> mode and print results
immediately; might be empty at this time.
</para>
<para>
If the optional <varname>SUBSYSTEMS</varname> argument is used,
MPD will only send notifications when something changed in
one of the specified subsytems.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_status">
<term>
<cmdsynopsis>
<command>status</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Reports the current status of the player and the volume
level.
</para>
<itemizedlist>
<listitem>
<para>
<varname>volume</varname>:
<returnvalue>0-100</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>repeat</varname>:
<returnvalue>0 or 1</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>playlist</varname>:
<returnvalue>31-bit unsigned integer, the playlist
version number</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>playlistlength</varname>:
<returnvalue>integer, the length of the
playlist</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>state</varname>:
<returnvalue>play, stop, or pause</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>song</varname>:
<returnvalue> playlist song number of the current
song stopped on or playing
</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>songid</varname>:
<returnvalue>playlist songid of the current song
stopped on or playing
</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>time</varname>:
<returnvalue>total time elapsed (of current
playing/paused song)</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>bitrate</varname>:
<returnvalue>instantaneous bitrate in
kbps</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>xfade</varname>:
<returnvalue>crossfade in seconds</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>audio</varname>:
<returnvalue>sampleRate:bits:channels</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>updatings_db</varname>:
<returnvalue>job id</returnvalue>
</para>
</listitem>
<listitem>
<para>
<varname>error</varname>:
<returnvalue>if there is an error, returns message
here</returnvalue>
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry id="command_stats">
<term>
<cmdsynopsis>
<command>stats</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays statistics.
</para>
<itemizedlist>
<listitem>
<para>
<varname>artists</varname>: number of artists
</para>
</listitem>
<listitem>
<para>
<varname>songs</varname>: number of albums
</para>
</listitem>
<listitem>
<para>
<varname>uptime</varname>: daemon uptime in seconds
</para>
</listitem>
<listitem>
<para>
<varname>db_playtime</varname>: sum of all song
times in the db
</para>
</listitem>
<listitem>
<para>
<varname>db_update</varname>: last db update in UNIX
time
</para>
</listitem>
<listitem>
<para>
<varname>playtime</varname>: time length of music played
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Playback options</title>
<variablelist>
<varlistentry id="command_crossfade">
<term>
<cmdsynopsis>
<command>crossfade</command>
<arg choice="req"><replaceable>SECONDS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Sets crossfading between songs.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_random">
<term>
<cmdsynopsis>
<command>random</command>
<arg choice="req"><replaceable>STATE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Sets random state to <varname>STATE</varname>,
<varname>STATE</varname> should be 0 or 1.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_repeat">
<term>
<cmdsynopsis>
<command>repeat</command>
<arg choice="req"><replaceable>STATE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Sets repeat state to <varname>STATE</varname>,
<varname>STATE</varname> should be 0 or 1.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_setvol">
<term>
<cmdsynopsis>
<command>setvol</command>
<arg choice="req"><replaceable>VOL</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Sets volume to <varname>VOL</varname>, the range of
volume is 0-100.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_volume">
<term>
<cmdsynopsis>
<command>volume</command>
<arg choice="req"><replaceable>CHANGE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Changes volume by amount <varname>CHANGE</varname>.
</para>
<note>
<para>
<command>volume</command> is deprecated, use
<command>setvol</command> instead.
</para>
</note>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Controlling playback</title>
<variablelist>
<varlistentry id="command_next">
<term>
<cmdsynopsis>
<command>next</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Plays next song in the playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_pause">
<term>
<cmdsynopsis>
<command>pause</command>
<arg choice="req"><replaceable>PAUSE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Toggles pause/resumes playing, <varname>PAUSE</varname> is 0 or 1.
</para>
<note>
<para>
The use of pause command w/o the PAUSE argument is
deprecated.
</para>
</note>
</listitem>
</varlistentry>
<varlistentry id="command_play">
<term>
<cmdsynopsis>
<command>play</command>
<arg><replaceable>SONGPOS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Begins playing the playlist at song number
<varname>SONGPOS</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playid">
<term>
<cmdsynopsis>
<command>playid</command>
<arg><replaceable>SONGID</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Begins playing the playlist at song
<varname>SONGID</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_previous">
<term>
<cmdsynopsis>
<command>previous</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Plays previous song in the playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_seek">
<term>
<cmdsynopsis>
<command>seek</command>
<arg choice="req"><replaceable>SONGPOS</replaceable></arg>
<arg choice="req"><replaceable>TIME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Seeks to the position <varname>TIME</varname> (in
seconds) of entry <varname>SONGPOS</varname> in the
playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_seekid">
<term>
<cmdsynopsis>
<command>seekid</command>
<arg choice="req"><replaceable>SONGID</replaceable></arg>
<arg choice="req"><replaceable>TIME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Seeks to the position <varname>TIME</varname> (in
seconds) of song <varname>SONGID</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_stop">
<term>
<cmdsynopsis>
<command>stop</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Stops playing.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>The current playlist</title>
<variablelist>
<varlistentry id="command_add">
<term>
<cmdsynopsis>
<command>add</command>
<arg choice="req"><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Adds the file <varname>URI</varname> to the playlist
(directories add recursively). <varname>URI</varname>
can also be a single file.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_addid">
<term>
<cmdsynopsis>
<command>addid</command>
<arg choice="req"><replaceable>URI</replaceable></arg>
<arg><replaceable>POSITION</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Adds a song to the playlist (non-recursive) and returns the song id.
</para>
<para>
<varname>URI</varname> is always a single file or
URL. <varname>POSITION</varname> is optional, a
negative number means it is relative to the currently
playing song in the playlist (if there is one).
For example:
</para>
<screen>
addid "foo.mp3"
Id: 999
OK
</screen>
</listitem>
</varlistentry>
<varlistentry id="command_clear">
<term>
<cmdsynopsis>
<command>clear</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Clears the current playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_delete">
<term>
<cmdsynopsis>
<command>delete</command>
<arg choice="req"><replaceable>SONGPOS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Deletes a song from the playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_deleteid">
<term>
<cmdsynopsis>
<command>deleteid</command>
<arg choice="req"><replaceable>SONGID</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Deletes the song <varname>SONGID</varname> from the
playlist
</para>
</listitem>
</varlistentry>
<varlistentry id="command_move">
<term>
<cmdsynopsis>
<command>move</command>
<arg choice="req"><replaceable>FROM</replaceable></arg>
<arg choice="req"><replaceable>TO</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Moves the song at <varname>FROM</varname> to
<varname>TO</varname> in the playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_moveid">
<term>
<cmdsynopsis>
<command>moveid</command>
<arg choice="req"><replaceable>FROM</replaceable></arg>
<arg choice="req"><replaceable>TO</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Moves the song with <varname>FROM</varname> to
<varname>TO</varname> (both song ids) in the
playlist. If <varname>TO</varname> is negative, it
is relative to the current song in the playlist (if
there is one).
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlist">
<term>
<cmdsynopsis>
<command>playlist</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays the current playlist.
</para>
<note>
<para>
Do not use this, instead use <command>playlistinfo</command>.
</para>
</note>
</listitem>
</varlistentry>
<varlistentry id="command_playlistfind">
<term>
<cmdsynopsis>
<command>playlistfind</command>
<arg choice="req"><replaceable>TAG</replaceable></arg>
<arg choice="req"><replaceable>NEEDLE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Finds songs in the current playlist with strict
matching.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistid">
<term>
<cmdsynopsis>
<command>playlistid</command>
<arg choice="req"><replaceable>SONGID</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays a list of songs in the playlist.
<varname>SONGID</varname> is optional and specifies a
single song to display info for.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistinfo">
<term>
<cmdsynopsis>
<command>playlistinfo</command>
<arg><replaceable>SONGPOS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays a list of songs in the playlist.
<varname>SONGPOS</varname> is optional and specifies
a single song to display info for.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistsearch">
<term>
<cmdsynopsis>
<command>playlistsearch</command>
<arg choice="req"><replaceable>TAG</replaceable></arg>
<arg choice="req"><replaceable>NEEDLE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Searches case-sensitively for partial matches in the
current playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_plchanges">
<term>
<cmdsynopsis>
<command>plchanges</command>
<arg choice="req"><replaceable>VERSION</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays changed songs currently in the playlist since
<varname>VERSION</varname>.
</para>
<para>
To detect songs that were deleted at the end of the
playlist, use playlistlength returned by status command.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_plchangesposid">
<term>
<cmdsynopsis>
<command>plchangesposid</command>
<arg choice="req"><replaceable>VERSION</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Displays changed songs currently in the playlist since
<varname>VERSION</varname>. This function only
returns the position and the id of the changed song, not
the complete metadata. This is more bandwidth efficient.
</para>
<para>
To detect songs that were deleted at the end of the
playlist, use playlistlength returned by status command.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_shuffle">
<term>
<cmdsynopsis>
<command>shuffle</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Shuffles the current playlist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_swap">
<term>
<cmdsynopsis>
<command>swap</command>
<arg choice="req"><replaceable>SONG1</replaceable></arg>
<arg choice="req"><replaceable>SONG2</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Swaps the positions of <varname>SONG1</varname> and
<varname>SONG2</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_swapid">
<term>
<cmdsynopsis>
<command>swapid</command>
<arg choice="req"><replaceable>SONG1</replaceable></arg>
<arg choice="req"><replaceable>SONG2</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Swaps the positions of <varname>SONG1</varname> and
<varname>SONG2</varname> (both song ids).
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Stored playlists</title>
<variablelist>
<varlistentry id="command_listplaylist">
<term>
<cmdsynopsis>
<command>listplaylist</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Lists the files in the playlist
<filename>NAME.m3u</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_listplaylistinfo">
<term>
<cmdsynopsis>
<command>listplaylistinfo</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Lists songs in the playlist <filename>NAME.m3u</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_listplaylists">
<term>
<cmdsynopsis>
<command>listplaylists</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Prints a list of the playlist directory.
</para>
<para>
After each playlist name the server sends its last
modification time as attribute "Last-Modified" in ISO
8601 format. To avoid problems due to clock differences
between clients and the server, clients should not
compare this value with their local clock.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_load">
<term>
<cmdsynopsis>
<command>load</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Loads the playlist <filename>NAME.m3u</filename> from
the playlist directory.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistadd">
<term>
<cmdsynopsis>
<command>playlistadd</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
<arg choice="req"><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Adds <varname>URI</varname> to the playlist
<filename>NAME.m3u</filename>.
</para>
<para>
<filename>NAME.m3u</filename> will be created if it does
not exist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistclear">
<term>
<cmdsynopsis>
<command>playlistclear</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Clears the playlist <filename>NAME.m3u</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistdelete">
<term>
<cmdsynopsis>
<command>playlistdelete</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
<arg choice="req"><replaceable>SONGID</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Deletes <varname>SONGID</varname> from the
playlist <filename>NAME.m3u</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_playlistmove">
<term>
<cmdsynopsis>
<command>playlistmove</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
<arg choice="req"><replaceable>SONGID</replaceable></arg>
<arg choice="req"><replaceable>SONGPOS</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Moves <varname>SONGID</varname> in the playlist
<filename>NAME.m3u</filename> to the position
<varname>SONGPOS</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_rename">
<term>
<cmdsynopsis>
<command>rename</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
<arg choice="req"><replaceable>NEW_NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Renames the playlist <filename>NAME.m3u</filename> to <filename>NEW_NAME.m3u</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_rm">
<term>
<cmdsynopsis>
<command>rm</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Removes the playlist <filename>NAME.m3u</filename> from
the playlist directory.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_save">
<term>
<cmdsynopsis>
<command>save</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Saves the current playlist to
<filename>NAME.m3u</filename> in the playlist directory.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>The music database</title>
<variablelist>
<varlistentry id="command_count">
<term>
<cmdsynopsis>
<command>count</command>
<arg choice="req"><replaceable>TAG</replaceable></arg>
<arg choice="req"><replaceable>NEEDLE</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Counts the number of songs and their total playtime in
the db matching <varname>TAG</varname> exactly.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_find">
<term>
<cmdsynopsis>
<command>find</command>
<arg choice="req"><replaceable>TYPE</replaceable></arg>
<arg choice="req"><replaceable>WHAT</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Finds songs in the db that are exactly
<varname>WHAT</varname>. <varname>TYPE</varname> should
be <parameter>album</parameter>,
<parameter>artist</parameter>, or
<parameter>title</parameter>. <varname>WHAT</varname>
is what to find.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_list">
<term>
<cmdsynopsis>
<command>list</command>
<arg choice="req"><replaceable>TYPE</replaceable></arg>
<arg><replaceable>ARTIST</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Lists all tags of the specified type.
<varname>TYPE</varname> should be album or artist.
</para>
<para>
<varname>ARTIST</varname> is an optional parameter when
type is album, this specifies to list albums by an
artist.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_listall">
<term>
<cmdsynopsis>
<command>listall</command>
<arg><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Lists all songs and directories in
<varname>URI</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_listallinfo">
<term>
<cmdsynopsis>
<command>listallinfo</command>
<arg><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Same as <command>listall</command>, except it also
returns metadata info in the same format as
<command>lsinfo</command>.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_lsinfo">
<term>
<cmdsynopsis>
<command>lsinfo</command>
<arg><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Lists the contents of the directory
<varname>URI</varname>.
</para>
<para>
When listing the root directory, this currently returns
the list of stored playlists. This behavior is
deprecated; use "listplaylists" instead.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_search">
<term>
<cmdsynopsis>
<command>search</command>
<arg choice="req"><replaceable>TYPE</replaceable></arg>
<arg choice="req"><replaceable>WHAT</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Searches for any song that contains
<varname>WHAT</varname>. <varname>TYPE</varname> can be
<parameter>title</parameter>,
<parameter>artist</parameter>,
<parameter>album</parameter> or
<parameter>filename</parameter>. Search is not case
sensitive.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_update">
<term>
<cmdsynopsis>
<command>update</command>
<arg><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Updates the music database.
</para>
<para>
<varname>URI</varname> is a particular directory or
song/file to update.
</para>
<para>
Prints "updating_db: JOBID" where
<varname>JOBID</varname> is the job id requested for
your update, and is displayed in status, while the
requested update is happening.
</para>
<para>
To update a number of paths/songs at once, use
command_list, it will be much more faster/efficient.
Also, if you use a command_list for updating, only one
<command>update</command> job id will be returned per
sequence of updates.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Connection settings</title>
<variablelist>
<varlistentry id="command_close">
<term>
<cmdsynopsis>
<command>close</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Closes the connection to MPD.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_kill">
<term>
<cmdsynopsis>
<command>kill</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Kills MPD.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_password">
<term>
<cmdsynopsis>
<command>password</command>
<arg choice="req"><replaceable>PASSWORD</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
This is used for authentication with the server.
<varname>PASSWORD</varname> is simply the plaintext
password.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_ping">
<term>
<cmdsynopsis>
<command>ping</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Does nothing but return "OK".
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Audio output devices</title>
<variablelist>
<varlistentry id="command_disableoutput">
<term>
<cmdsynopsis>
<command>disableoutput</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Turns an output off.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_enableoutput">
<term>
<cmdsynopsis>
<command>enableoutput</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Turns an output on.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_outputs">
<term>
<cmdsynopsis>
<command>outputs</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Shows information about all outputs.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Reflection</title>
<variablelist>
<varlistentry id="command_commands">
<term>
<cmdsynopsis>
<command>commands</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Shows which commands the current user has access to.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_notcommands">
<term>
<cmdsynopsis>
<command>notcommands</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Shows which commands the current user does not have
access to.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_tagtypes">
<term>
<cmdsynopsis>
<command>tagtypes</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Shows a list of available song metadata.
</para>
</listitem>
</varlistentry>
<varlistentry id="command_urlhandlers">
<term>
<cmdsynopsis>
<command>urlhandlers</command>
</cmdsynopsis>
</term>
<listitem>
<para>
Gets a list of available URL handlers.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</chapter>
</book>
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [0], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[pic_mode="$withval"],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# Generated from ltversion.in.
# serial 3012 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.2.6])
m4_define([LT_PACKAGE_REVISION], [1.3012])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.2.6'
macro_revision='1.3012'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 4 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
......@@ -315,6 +315,8 @@ HAVE_SHOUT_OGG_TRUE = @HAVE_SHOUT_OGG_TRUE@
HAVE_SHOUT_TRUE = @HAVE_SHOUT_TRUE@
HAVE_WAVPACK_FALSE = @HAVE_WAVPACK_FALSE@
HAVE_WAVPACK_TRUE = @HAVE_WAVPACK_TRUE@
HAVE_XMLTO_FALSE = @HAVE_XMLTO_FALSE@
HAVE_XMLTO_TRUE = @HAVE_XMLTO_TRUE@
HAVE_ZEROCONF_FALSE = @HAVE_ZEROCONF_FALSE@
HAVE_ZEROCONF_TRUE = @HAVE_ZEROCONF_TRUE@
ID3TAG_CFLAGS = @ID3TAG_CFLAGS@
......@@ -372,6 +374,7 @@ VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
VORBISENC_LIBS = @VORBISENC_LIBS@
WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
WAVPACK_LIBS = @WAVPACK_LIBS@
XMLTO = @XMLTO@
ac_ct_CC = @ac_ct_CC@
acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
......
......@@ -40,6 +40,17 @@ static inline bool audio_format_defined(const struct audio_format *af)
return af->sample_rate != 0;
}
/**
* Returns false if the format is not valid for playback with MPD.
* This function performs some basic validity checks.
*/
static inline bool audio_format_valid(const struct audio_format *af)
{
return af->sample_rate > 0 &&
(af->bits == 8 || af->bits == 16 || af->bits == 24) &&
af->channels >= 1;
}
static inline bool audio_format_equals(const struct audio_format *a,
const struct audio_format *b)
{
......
......@@ -91,6 +91,9 @@ struct client {
/** idle flags pending on this client, to be sent as soon as
the client enters "idle" */
unsigned idle_flags;
/** idle flags that the client wants to receive */
unsigned idle_subscriptions;
};
static LIST_HEAD(clients);
......@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...)
va_end(args);
}
static const char *const idle_names[] = {
"database",
"stored_playlist",
"playlist",
"player",
"mixer",
"output",
"options",
};
/**
* Send "idle" response to this client.
*/
......@@ -783,6 +776,7 @@ static void
client_idle_notify(struct client *client)
{
unsigned flags, i;
const char *const* idle_names;
assert(client->idle_waiting);
assert(client->idle_flags != 0);
......@@ -791,10 +785,9 @@ client_idle_notify(struct client *client)
client->idle_flags = 0;
client->idle_waiting = false;
for (i = 0; i < sizeof(idle_names) / sizeof(idle_names[0]); ++i) {
assert(idle_names[i] != NULL);
if (flags & (1 << i))
idle_names = idle_get_names();
for (i = 0; idle_names[i]; ++i) {
if (flags & (1 << i) & client->idle_subscriptions)
client_printf(client, "changed: %s\n",
idle_names[i]);
}
......@@ -814,20 +807,22 @@ void client_manager_idle_add(unsigned flags)
continue;
client->idle_flags |= flags;
if (client->idle_waiting) {
if (client->idle_waiting
&& (client->idle_flags & client->idle_subscriptions)) {
client_idle_notify(client);
client_write_output(client);
}
}
}
bool client_idle_wait(struct client *client)
bool client_idle_wait(struct client *client, unsigned flags)
{
assert(!client->idle_waiting);
client->idle_waiting = true;
client->idle_subscriptions = flags;
if (client->idle_flags != 0) {
if (client->idle_flags & client->idle_subscriptions) {
client_idle_notify(client);
return true;
} else
......
......@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags);
* sent immediately and "true" is returned". If no, it puts the
* client into waiting mode and returns false.
*/
bool client_idle_wait(struct client *client);
bool client_idle_wait(struct client *client, unsigned flags);
#endif
......@@ -39,6 +39,7 @@
#include "tag_print.h"
#include "path.h"
#include "os_compat.h"
#include "idle.h"
#define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state"
......@@ -204,7 +205,7 @@ print_playlist_result(struct client *client,
return COMMAND_RETURN_OK;
case PLAYLIST_RESULT_ERRNO:
command_error(client, ACK_ERROR_SYSTEM, strerror(errno));
command_error(client, ACK_ERROR_SYSTEM, "%s", strerror(errno));
return COMMAND_RETURN_ERROR;
case PLAYLIST_RESULT_DENIED:
......@@ -1253,8 +1254,28 @@ static enum command_return
handle_idle(struct client *client,
mpd_unused int argc, mpd_unused char *argv[])
{
unsigned flags = 0, j;
int i;
const char *const* idle_names;
idle_names = idle_get_names();
for (i = 1; i < argc; ++i) {
if (!argv[i])
continue;
for (j = 0; idle_names[j]; ++j) {
if (!strcasecmp(argv[i], idle_names[j])) {
flags |= (1 << j);
}
}
}
/* No argument means that the client wants to receive everything */
if (flags == 0)
flags = ~0;
/* enable "idle" mode on this client */
client_idle_wait(client);
client_idle_wait(client, flags);
/* return value is "1" so the caller won't print "OK" */
return 1;
......@@ -1280,7 +1301,7 @@ static const struct command commands[] = {
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
{ "find", PERMISSION_READ, 2, -1, handle_find },
{ "idle", PERMISSION_READ, 0, 0, handle_idle },
{ "idle", PERMISSION_READ, 0, -1, handle_idle },
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
{ "list", PERMISSION_READ, 1, -1, handle_list },
{ "listall", PERMISSION_READ, 0, 1, handle_listall },
......
......@@ -20,7 +20,6 @@
*/
#include "_flac_common.h"
#include "../log.h"
#include <FLAC/format.h>
#include <FLAC/metadata.h>
......@@ -177,16 +176,16 @@ void flac_error_common_cb(const char *plugin,
switch (status) {
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
ERROR("%s lost sync\n", plugin);
g_warning("%s lost sync\n", plugin);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
ERROR("bad %s header\n", plugin);
g_warning("bad %s header\n", plugin);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
ERROR("%s crc mismatch\n", plugin);
g_warning("%s crc mismatch\n", plugin);
break;
default:
ERROR("unknown %s error\n", plugin);
g_warning("unknown %s error\n", plugin);
}
}
......
......@@ -24,6 +24,11 @@
#include "../decoder_api.h"
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "flac"
#include <FLAC/export.h>
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# include <FLAC/seekable_stream_decoder.h>
......
......@@ -20,11 +20,13 @@
#define AAC_MAX_CHANNELS 6
#include "../utils.h"
#include "../log.h"
#include <assert.h>
#include <unistd.h>
#include <faad.h>
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "aac"
/* all code here is either based on or copied from FAAD2's frontend code */
typedef struct {
......@@ -186,7 +188,7 @@ static void aac_parse_header(AacBuffer * b, float *length)
if (length)
*length = -1;
fileread = b->inStream->size;
fileread = b->inStream->size >= 0 ? b->inStream->size : 0;
fillAacBuffer(b);
......@@ -252,6 +254,14 @@ static float getAacFloatTotalTime(const char *file)
faacDecHandle decoder;
faacDecConfigurationPtr config;
uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels;
struct input_stream inStream;
long bread;
......@@ -272,9 +282,9 @@ static float getAacFloatTotalTime(const char *file)
fillAacBuffer(&b);
#ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sample_rate, &channels);
sample_rate_r, &channels);
#else
bread = faacDecInit(decoder, b.buffer, &sample_rate, &channels);
bread = faacDecInit(decoder, b.buffer, sample_rate_r, &channels);
#endif
if (bread >= 0 && sample_rate > 0 && channels > 0)
length = 0;
......@@ -282,8 +292,6 @@ static float getAacFloatTotalTime(const char *file)
faacDecClose(decoder);
}
if (b.buffer)
free(b.buffer);
input_stream_close(&inStream);
return length;
......@@ -310,6 +318,14 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
faacDecConfigurationPtr config;
long bread;
uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels;
unsigned int sampleCount;
char *sampleBuffer;
......@@ -340,20 +356,17 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
fillAacBuffer(&b);
adts_find_frame(&b);
fillAacBuffer(&b);
my_usleep(10000);
}
#ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sample_rate, &channels);
sample_rate_r, &channels);
#else
bread = faacDecInit(decoder, b.buffer, &sample_rate, &channels);
bread = faacDecInit(decoder, b.buffer, sample_rate_r, &channels);
#endif
if (bread < 0) {
ERROR("Error not a AAC stream.\n");
g_warning("Error not a AAC stream.\n");
faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
return;
}
......@@ -377,9 +390,8 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
#endif
if (frameInfo.error > 0) {
ERROR("error decoding AAC stream\n");
ERROR("faad2 error: %s\n",
faacDecGetErrorMessage(frameInfo.error));
g_warning("error decoding AAC stream: %s\n",
faacDecGetErrorMessage(frameInfo.error));
break;
}
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
......@@ -393,6 +405,11 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
.sample_rate = sample_rate,
};
if (!audio_format_valid(&audio_format)) {
g_warning("aac: invalid audio format\n");
break;
}
decoder_initialized(mpd_decoder, &audio_format,
false, totalTime);
initialized = true;
......@@ -433,8 +450,8 @@ static struct tag *aacTagDup(const char *file)
ret = tag_new();
ret->time = file_time;
} else {
DEBUG("aacTagDup: Failed to get total song time from: %s\n",
file);
g_debug("aacTagDup: Failed to get total song time from: %s\n",
file);
}
return ret;
......
......@@ -19,10 +19,13 @@
*/
#include "../decoder_api.h"
#include "../log.h"
#include <sys/stat.h>
#include <audiofile.h>
#include <glib.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "audiofile"
/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */
#define CHUNK_SIZE 1020
......@@ -55,13 +58,13 @@ audiofile_decode(struct decoder *decoder, const char *path)
char chunk[CHUNK_SIZE];
if (stat(path, &st) < 0) {
ERROR("failed to stat: %s\n", path);
g_warning("failed to stat: %s\n", path);
return;
}
af_fp = afOpenFile(path, "r", NULL);
if (af_fp == AF_NULL_FILEHANDLE) {
ERROR("failed to open: %s\n", path);
g_warning("failed to open: %s\n", path);
return;
}
......@@ -74,19 +77,20 @@ audiofile_decode(struct decoder *decoder, const char *path)
audio_format.channels =
(uint8_t)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK);
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
afCloseFile(af_fp);
return;
}
frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
total_time = ((float)frame_count / (float)audio_format.sample_rate);
bitRate = (uint16_t)(st.st_size * 8.0 / total_time / 1000.0 + 0.5);
if (audio_format.bits != 8 && audio_format.bits != 16) {
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
path, audio_format.bits);
afCloseFile(af_fp);
return;
}
fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
decoder_initialized(decoder, &audio_format, true, total_time);
......@@ -120,13 +124,11 @@ static struct tag *audiofileTagDup(const char *file)
int total_time = getAudiofileTotalTime(file);
if (total_time >= 0) {
if (!ret)
ret = tag_new();
ret = tag_new();
ret->time = total_time;
} else {
DEBUG
("audiofileTagDup: Failed to get total song time from: %s\n",
file);
g_debug("Failed to get total song time from: %s\n",
file);
}
return ret;
......
......@@ -17,7 +17,6 @@
*/
#include "../decoder_api.h"
#include "../log.h"
#include <assert.h>
#include <stdio.h>
......@@ -27,6 +26,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>
#ifdef OLD_FFMPEG_INCLUDES
#include <avcodec.h>
......@@ -38,6 +38,9 @@
#include <libavformat/avio.h>
#endif
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "ffmpeg"
struct ffmpeg_context {
int audio_stream;
AVFormatContext *format_context;
......@@ -89,9 +92,15 @@ static int mpd_ffmpeg_read(URLContext *h, unsigned char *buf, int size)
static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence)
{
struct ffmpeg_stream *stream = (struct ffmpeg_stream *) h->priv_data;
if (whence != AVSEEK_SIZE) { //only ftell
(void) input_stream_seek(stream->input, pos, whence);
}
bool ret;
if (whence == AVSEEK_SIZE)
return stream->input->size;
ret = input_stream_seek(stream->input, pos, whence);
if (!ret)
return -1;
return stream->input->offset;
}
......@@ -150,18 +159,18 @@ ffmpeg_helper(struct input_stream *input,
//ffmpeg works with ours "fileops" helper
if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) {
ERROR("Open failed!\n");
g_warning("Open failed\n");
return false;
}
if (av_find_stream_info(format_context)<0) {
ERROR("Couldn't find stream info!\n");
g_warning("Couldn't find stream info\n");
return false;
}
audio_stream = ffmpeg_find_audio_stream(format_context);
if (audio_stream == -1) {
ERROR("No audio stream inside!\n");
g_warning("No audio stream inside\n");
return false;
}
......@@ -169,12 +178,12 @@ ffmpeg_helper(struct input_stream *input,
codec = avcodec_find_decoder(codec_context->codec_id);
if (!codec) {
ERROR("Unsupported audio codec!\n");
g_warning("Unsupported audio codec\n");
return false;
}
if (avcodec_open(codec_context, codec)<0) {
ERROR("Could not open codec!\n");
g_warning("Could not open codec\n");
return false;
}
......@@ -213,7 +222,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
packet->data, packet->size);
if (len < 0) {
WARNING("skipping frame!\n");
g_message("skipping frame\n");
return decoder_get_command(decoder);
}
......@@ -246,6 +255,13 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
audio_format.sample_rate = (unsigned int)codec_context->sample_rate;
audio_format.channels = codec_context->channels;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
return false;
}
//there is some problem with this on some demux (mp3 at least)
if (format_context->duration != (int)AV_NOPTS_VALUE) {
total_time = format_context->duration / AV_TIME_BASE;
......@@ -295,11 +311,22 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
{
struct tag *tag = (struct tag *) ctx->tag;
if (ctx->format_context->duration != (int)AV_NOPTS_VALUE) {
tag->time = ctx->format_context->duration / AV_TIME_BASE;
} else {
tag->time = 0;
const AVFormatContext *f = ctx->format_context;
tag->time = 0;
if (f->duration != (int)AV_NOPTS_VALUE)
tag->time = f->duration / AV_TIME_BASE;
if (f->author[0])
tag_add_item(tag, TAG_ITEM_ARTIST, f->author);
if (f->title[0])
tag_add_item(tag, TAG_ITEM_TITLE, f->title);
if (f->album[0])
tag_add_item(tag, TAG_ITEM_ALBUM, f->album);
if (f->track > 0) {
char buffer[16];
snprintf(buffer, sizeof(buffer), "%d", f->track);
tag_add_item(tag, TAG_ITEM_TRACK, buffer);
}
return true;
......@@ -313,7 +340,7 @@ static struct tag *ffmpeg_tag(const char *file)
bool ret;
if (!input_stream_open(&input, file)) {
ERROR("failed to open %s\n", file);
g_warning("failed to open %s\n", file);
return NULL;
}
......
......@@ -17,8 +17,6 @@
*/
#include "_flac_common.h"
#include "../utils.h"
#include "../log.h"
#include <assert.h>
......@@ -75,6 +73,9 @@ static flac_length_status flacLength(mpd_unused const flac_decoder * flacDec,
{
FlacData *data = (FlacData *) fdata;
if (data->inStream->size < 0)
return flac_length_status_unsupported;
*length = (size_t) (data->inStream->size);
return flac_length_status_ok;
......@@ -125,7 +126,8 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
str = "decoder uninitialized";
}
ERROR("flac %s\n", str);
g_warning("%s\n", str);
}
static int flac_init(FLAC__SeekableStreamDecoder *dec,
......@@ -183,7 +185,8 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state)
case FLAC__STREAM_DECODER_UNINITIALIZED:
str = "decoder uninitialized";
}
ERROR("flac %s\n", str);
g_warning("%s\n", str);
}
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
......@@ -248,9 +251,8 @@ flacMetadataDup(const char *file, bool *vorbisCommentFound)
default:
err = FLAC__Metadata_SimpleIteratorStatusString[s];
}
DEBUG("flacMetadataDup: Reading '%s' "
"metadata gave the following error: %s\n",
file, err);
g_debug("Reading '%s' metadata gave the following error: %s\n",
file, err);
FLAC__metadata_simple_iterator_delete(it);
return ret;
}
......@@ -285,8 +287,7 @@ static struct tag *flacTagDup(const char *file)
ret = flacMetadataDup(file, &foundVorbisComment);
if (!ret) {
DEBUG("flacTagDup: Failed to grab information from: %s\n",
file);
g_debug("Failed to grab information from: %s\n", file);
return NULL;
}
if (!foundVorbisComment) {
......@@ -316,7 +317,7 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
if(!FLAC__stream_decoder_set_metadata_respond(flacDec, FLAC__METADATA_TYPE_VORBIS_COMMENT))
{
DEBUG(__FILE__": Failed to set metadata respond\n");
g_debug("Failed to set metadata respond\n");
}
#endif
......@@ -342,6 +343,14 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
goto fail;
}
if (!audio_format_valid(&data.audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
data.audio_format.sample_rate,
data.audio_format.bits,
data.audio_format.channels);
goto fail;
}
decoder_initialized(decoder, &data.audio_format,
inStream->seekable, data.total_time);
......@@ -373,11 +382,8 @@ fail:
if (flacDec)
flac_delete(flacDec);
if (err) {
ERROR("flac %s\n", err);
return;
}
return;
if (err)
g_warning("%s\n", err);
}
static void
......
......@@ -112,6 +112,14 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
unsigned char *mp4_buffer;
unsigned int mp4_buffer_size;
uint32_t sample_rate;
#ifdef HAVE_FAAD_LONG
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long*)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
#endif
unsigned char channels;
long sample_id;
long num_samples;
......@@ -160,7 +168,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
mp4ff_get_decoder_config(mp4fh, track, &mp4_buffer, &mp4_buffer_size);
if (faacDecInit2(decoder, mp4_buffer, mp4_buffer_size,
&sample_rate, &channels) < 0) {
sample_rate_r, &channels) < 0) {
g_warning("Not an AAC stream.\n");
faacDecClose(decoder);
mp4ff_close(mp4fh);
......@@ -267,6 +275,15 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
scale = frame_info.samplerate;
#endif
audio_format.sample_rate = scale;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
break;
}
decoder_initialized(mpd_decoder, &audio_format,
input_stream->seekable,
total_time);
......
......@@ -155,6 +155,14 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
audio_format.channels = info.channels;
audio_format.sample_rate = info.sample_freq;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
return;
}
replayGainInfo = replay_gain_info_new();
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01;
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0;
......
......@@ -22,9 +22,6 @@
#include "_flac_common.h"
#include "_ogg_common.h"
#include "../utils.h"
#include "../log.h"
#include <OggFLAC/seekable_stream_decoder.h>
static void oggflac_cleanup(FlacData * data,
......@@ -92,6 +89,9 @@ static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(mpd_unused const
{
FlacData *data = (FlacData *) fdata;
if (data->inStream->size < 0)
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
*length = (size_t) (data->inStream->size);
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
......@@ -117,25 +117,25 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
{
switch (state) {
case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR("oggflac allocation error\n");
g_warning("oggflac allocation error\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR:
ERROR("oggflac read error\n");
g_warning("oggflac read error\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR:
ERROR("oggflac seek error\n");
g_warning("oggflac seek error\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR:
ERROR("oggflac seekable stream error\n");
g_warning("oggflac seekable stream error\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED:
ERROR("oggflac decoder already initialized\n");
g_warning("oggflac decoder already initialized\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK:
ERROR("invalid oggflac callback\n");
g_warning("invalid oggflac callback\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
ERROR("oggflac decoder uninitialized\n");
g_warning("oggflac decoder uninitialized\n");
break;
case OggFLAC__SEEKABLE_STREAM_DECODER_OK:
case OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING:
......@@ -230,17 +230,17 @@ static OggFLAC__SeekableStreamDecoder
(void *)data);
if (!s) {
ERROR("oggflac problem before init()\n");
g_warning("oggflac problem before init()\n");
goto fail;
}
if (OggFLAC__seekable_stream_decoder_init(decoder) !=
OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
ERROR("oggflac problem doing init()\n");
g_warning("oggflac problem doing init()\n");
goto fail;
}
if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata
(decoder)) {
ERROR("oggflac problem reading metadata\n");
g_warning("oggflac problem reading metadata\n");
goto fail;
}
......@@ -294,6 +294,14 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream)
goto fail;
}
if (!audio_format_valid(&data.audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
data.audio_format.sample_rate,
data.audio_format.bits,
data.audio_format.channels);
goto fail;
}
decoder_initialized(mpd_decoder, &data.audio_format,
inStream->seekable, data.total_time);
......
......@@ -214,7 +214,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
long test;
struct replay_gain_info *replayGainInfo = NULL;
char **comments;
const char *errorStr;
bool initialized = false;
enum decoder_command cmd = DECODE_COMMAND_NONE;
......@@ -233,6 +232,8 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
callbacks.close_func = ogg_close_cb;
callbacks.tell_func = ogg_tell_cb;
if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
const char *errorStr;
if (decoder_get_command(decoder) != DECODE_COMMAND_NONE)
return;
......@@ -274,6 +275,12 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
ret = ov_read(&vf, chunk, sizeof(chunk),
OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
if (ret == OV_HOLE) /* bad packet */
ret = 0;
else if (ret <= 0)
/* break on EOF or other error */
break;
if (current_section != prev_section) {
/*printf("new song!\n"); */
vorbis_info *vi = ov_info(&vf, -1);
......@@ -281,6 +288,15 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
audio_format.channels = vi->channels;
audio_format.sample_rate = vi->rate;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
break;
}
if (!initialized) {
float total_time = ov_time_total(&vf, -1);
if (total_time < 0)
......@@ -303,13 +319,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
prev_section = current_section;
if (ret <= 0) {
if (ret == OV_HOLE) /* bad packet */
ret = 0;
else /* break on EOF or other error */
break;
}
if ((test = ov_bitrate_instant(&vf)) > 0)
bitRate = test / 1000;
......
......@@ -20,6 +20,7 @@
#include "../decoder_api.h"
#include "../path.h"
#include "../utils.h"
#include <wavpack/wavpack.h>
#include <glib.h>
......@@ -71,7 +72,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
* of the output samples never can be greater than the size
* of the input ones. Otherwise we would have an overflow.
*/
assert(sizeof(uchar) <= sizeof(uint32_t));
assert_static(sizeof(*dst) <= sizeof(*src));
/* pass through and align 8-bit samples */
while (count--) {
......@@ -81,7 +82,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
}
case 2: {
uint16_t *dst = buffer;
assert(sizeof(uint16_t) <= sizeof(uint32_t));
assert_static(sizeof(*dst) <= sizeof(*src));
/* pass through and align 16-bit samples */
while (count--) {
......@@ -94,7 +95,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
break;
case 4: {
uint32_t *dst = buffer;
assert(sizeof(uint32_t) <= sizeof(uint32_t));
assert_static(sizeof(*dst) <= sizeof(*src));
/* downsample to 24-bit */
while (count--) {
......@@ -114,7 +115,7 @@ format_samples_float(mpd_unused int bytes_per_sample, void *buffer,
{
int32_t *dst = buffer;
float *src = buffer;
assert(sizeof(int32_t) <= sizeof(float));
assert_static(sizeof(*dst) <= sizeof(*src));
while (count--) {
*dst++ = (int32_t)(*src++ + 0.5f);
......@@ -148,6 +149,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
audio_format.bits = 24;
}
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
return;
}
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) {
format_samples = format_samples_float;
} else {
......@@ -157,12 +166,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
total_time = WavpackGetNumSamples(wpc);
total_time /= audio_format.sample_rate;
bytes_per_sample = WavpackGetBytesPerSample(wpc);
output_sample_size = bytes_per_sample;
if (output_sample_size == 3) {
output_sample_size = 4;
}
output_sample_size *= audio_format.channels;
output_sample_size = audio_format_frame_size(&audio_format);
/* wavpack gives us all kind of samples in a 32-bit space */
samples_requested = sizeof(chunk) / (4 * audio_format.channels);
......@@ -410,6 +414,9 @@ wavpack_input_push_back_byte(void *id, int c)
static uint32_t
wavpack_input_get_length(void *id)
{
if (wpin(id)->is->size < 0)
return 0;
return wpin(id)->is->size;
}
......
......@@ -40,6 +40,7 @@ void decoder_initialized(struct decoder * decoder,
assert(!decoder->seeking);
assert(audio_format != NULL);
assert(audio_format_defined(audio_format));
assert(audio_format_valid(audio_format));
pcm_convert_init(&decoder->conv_state);
......@@ -106,6 +107,9 @@ size_t decoder_read(struct decoder *decoder,
assert(is != NULL);
assert(buffer != NULL);
if (length == 0)
return 0;
while (true) {
/* XXX don't allow decoder==NULL */
if (decoder != NULL &&
......@@ -191,7 +195,8 @@ decoder_data(struct decoder *decoder,
assert(dc.state == DECODE_STATE_DECODE);
if (dc.command == DECODE_COMMAND_STOP ||
dc.command == DECODE_COMMAND_SEEK)
dc.command == DECODE_COMMAND_SEEK ||
length == 0)
return dc.command;
if (is != NULL && !decoder->stream_tag_sent) {
......@@ -229,13 +234,14 @@ decoder_data(struct decoder *decoder,
if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
data = _data;
} else {
length = pcm_convert_size(&dc.in_audio_format, length,
&dc.out_audio_format);
if (length > conv_buffer_size) {
size_t out_length =
pcm_convert_size(&dc.in_audio_format, length,
&dc.out_audio_format);
if (out_length > conv_buffer_size) {
if (conv_buffer != NULL)
free(conv_buffer);
conv_buffer = xmalloc(length);
conv_buffer_size = length;
conv_buffer = xmalloc(out_length);
conv_buffer_size = out_length;
}
data = conv_buffer;
......
......@@ -109,7 +109,7 @@ static void decoder_run(void)
will be available then */
while (!input_stream.ready) {
if (dc.command != DECODE_COMMAND_NONE) {
if (dc.command == DECODE_COMMAND_STOP) {
input_stream_close(&input_stream);
dc.state = DECODE_STATE_STOP;
return;
......
......@@ -30,6 +30,18 @@
static unsigned idle_flags;
static pthread_mutex_t idle_mutex = PTHREAD_MUTEX_INITIALIZER;
static const char *const idle_names[] = {
"database",
"stored_playlist",
"playlist",
"player",
"mixer",
"output",
"options",
"elapsed",
NULL
};
void
idle_add(unsigned flags)
{
......@@ -54,3 +66,9 @@ idle_get(void)
return flags;
}
const char*const*
idle_get_names(void)
{
return idle_names;
}
......@@ -61,4 +61,10 @@ idle_add(unsigned flags);
unsigned
idle_get(void);
/**
* Get idle names
*/
const char*const*
idle_get_names(void);
#endif
......@@ -155,12 +155,14 @@ input_curl_multi_info_read(struct input_stream *is)
while ((msg = curl_multi_info_read(c->multi,
&msgs_in_queue)) != NULL) {
if (msg->msg == CURLMSG_DONE &&
msg->data.result != CURLE_OK) {
g_warning("curl failed: %s\n", c->error);
is->error = -1;
if (msg->msg == CURLMSG_DONE) {
c->eof = true;
return false;
if (msg->data.result != CURLE_OK) {
g_warning("curl failed: %s\n", c->error);
is->error = -1;
return false;
}
}
}
......@@ -205,6 +207,31 @@ input_curl_select(struct input_curl *c)
return ret;
}
/**
* Mark a part of the buffer object as consumed.
*/
static void
consume_buffer(struct buffer *buffer, size_t length,
struct list_head *rewind_head)
{
assert(buffer != NULL);
assert(buffer->consumed < buffer->size);
buffer->consumed += length;
if (buffer->consumed < buffer->size)
return;
assert(buffer->consumed == buffer->size);
list_del(&buffer->siblings);
if (rewind_head != NULL)
/* append this buffer to the rewind buffer list */
list_add_tail(&buffer->siblings, rewind_head);
else
g_free(buffer);
}
static size_t
read_from_buffer(struct buffer *buffer, void *dest, size_t length,
struct list_head *rewind_head)
......@@ -216,18 +243,7 @@ read_from_buffer(struct buffer *buffer, void *dest, size_t length,
length = buffer->size - buffer->consumed;
memcpy(dest, buffer->data + buffer->consumed, length);
buffer->consumed += length;
if (buffer->consumed == buffer->size) {
list_del(&buffer->siblings);
if (rewind_head != NULL)
/* append this buffer to the rewind buffer list */
list_add_tail(&buffer->siblings, rewind_head);
else
g_free(buffer);
}
consume_buffer(buffer, length, rewind_head);
return length;
}
......@@ -266,8 +282,6 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size)
bret = input_curl_multi_info_read(is);
if (!bret)
return 0;
c->eof = running_handles == 0;
}
/* send buffer contents */
......@@ -345,8 +359,6 @@ input_curl_buffer(struct input_stream *is)
if (!ret)
return -1;
c->eof = running_handles == 0;
return c->buffered;
}
......@@ -480,8 +492,6 @@ input_curl_send_request(struct input_curl *c)
mcode = curl_multi_perform(c->multi, &running_handles);
} while (mcode == CURLM_CALL_MULTI_PERFORM);
c->eof = running_handles == 0;
if (mcode != CURLM_OK) {
g_warning("curl_multi_perform() failed: %s\n",
curl_multi_strerror(mcode));
......@@ -573,28 +583,66 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence)
switch (whence) {
case SEEK_SET:
is->offset = offset;
break;
case SEEK_CUR:
is->offset += offset;
offset += is->offset;
break;
case SEEK_END:
is->offset = is->size + offset;
if (is->size < 0)
/* stream size is not known */
return false;
offset += is->size;
break;
default:
return false;
}
if (is->offset < 0)
if (offset < 0)
return false;
/* check if we can fast-forward the buffer */
while (offset > is->offset && !list_empty(&c->buffers)) {
struct list_head *rewind_head;
struct buffer *buffer = (struct buffer *)c->buffers.next;
size_t length;
if (!list_empty(&c->rewind) || is->offset == 0)
/* at the beginning or already writing the rewind
buffer list */
rewind_head = &c->rewind;
else
/* we don't need the rewind buffers anymore */
rewind_head = NULL;
length = buffer->size - buffer->consumed;
if (offset - is->offset < (off_t)length)
length = offset - is->offset;
consume_buffer(buffer, length, rewind_head);
is->offset += length;
}
if (offset == is->offset)
return true;
/* close the old connection and open a new one */
input_curl_easy_free(c);
is->offset = offset;
if (is->offset == is->size) {
/* seek to EOF: simulate empty result; avoid
triggering a "416 Requested Range Not Satisfiable"
response */
c->eof = true;
return true;
}
ret = input_curl_easy_init(is);
if (!ret)
return false;
......@@ -610,7 +658,7 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence)
if (!ret)
return false;
return true;
return input_curl_multi_info_read(is);
}
static bool
......
......@@ -26,6 +26,7 @@
#endif
#include <glib.h>
#include <assert.h>
static const struct input_plugin *const input_plugins[] = {
&input_plugin_file,
......@@ -57,7 +58,7 @@ input_stream_open(struct input_stream *is, const char *url)
is->seekable = false;
is->ready = false;
is->offset = 0;
is->size = 0;
is->size = -1;
is->error = 0;
is->mime = NULL;
is->meta_name = NULL;
......@@ -84,6 +85,9 @@ input_stream_seek(struct input_stream *is, off_t offset, int whence)
size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size)
{
assert(ptr != NULL);
assert(size > 0);
return is->plugin->read(is, ptr, size);
}
......
......@@ -67,7 +67,7 @@ static const char *log_date(void)
}
static void
mpd_log_func(G_GNUC_UNUSED const gchar *log_domain,
mpd_log_func(const gchar *log_domain,
G_GNUC_UNUSED GLogLevelFlags log_level,
const gchar *message, G_GNUC_UNUSED gpointer user_data)
{
......@@ -87,8 +87,12 @@ mpd_log_func(G_GNUC_UNUSED const gchar *log_domain,
} else
converted = NULL;
fprintf(file, "%s%s",
if (log_domain == NULL)
log_domain = "";
fprintf(file, "%s%s%s%s",
stdout_mode ? "" : log_date(),
log_domain, *log_domain == 0 ? "" : ": ",
message);
g_free(converted);
......
......@@ -383,6 +383,7 @@ int main(int argc, char *argv[])
{
Options options;
clock_t start;
GTimer *save_state_timer;
#ifdef HAVE_LOCALE
/* initialize locale */
......@@ -446,6 +447,8 @@ int main(int argc, char *argv[])
player_create();
read_state_file();
save_state_timer = g_timer_new();
while (COMMAND_RETURN_KILL != client_manager_io() &&
COMMAND_RETURN_KILL != handlePendingSignals()) {
unsigned flags;
......@@ -459,6 +462,12 @@ int main(int argc, char *argv[])
flags = idle_get();
if (flags != 0)
client_manager_idle_add(flags);
if (g_timer_elapsed(save_state_timer, NULL) >= 5 * 60) {
g_debug("Saving state file\n");
write_state_file();
g_timer_start(save_state_timer);
}
}
write_state_file();
......
......@@ -109,7 +109,7 @@ map_directory_child_fs(const struct directory *directory, const char *name,
if (parent_fs == NULL)
return NULL;
utf8_to_fs_charset(buffer, name);
name = utf8_to_fs_charset(buffer, name);
pfx_dir(buffer, name, strlen(name),
parent_fs, strlen(parent_fs));
return buffer;
......
......@@ -33,7 +33,7 @@ char *fs_charset_to_utf8(char *dst, const char *str)
GError *error = NULL;
p = g_convert(str, -1,
fs_charset, "utf-8",
"utf-8", fs_charset,
NULL, NULL, &error);
if (p == NULL) {
/* no fallback */
......@@ -52,7 +52,7 @@ char *utf8_to_fs_charset(char *dst, const char *str)
GError *error = NULL;
p = g_convert(str, -1,
"utf-8", fs_charset,
fs_charset, "utf-8",
NULL, NULL, &error);
if (p == NULL) {
/* fall back to UTF-8 */
......
......@@ -67,7 +67,7 @@ void music_pipe_free(void)
/** return the index of the chunk after i */
static inline unsigned successor(unsigned i)
{
assert(i <= music_pipe.num_chunks);
assert(i < music_pipe.num_chunks);
++i;
return i == music_pipe.num_chunks ? 0 : i;
......
......@@ -389,12 +389,11 @@ updateDirectory(struct directory *directory, const struct stat *st)
char *utf8;
struct stat st2;
if (skip_path(ent->d_name) ||
skip_symlink(directory, ent->d_name))
if (skip_path(ent->d_name))
continue;
utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name);
if (!utf8)
if (utf8 == NULL || skip_symlink(directory, utf8))
continue;
if (stat_directory_child(directory, utf8, &st2) == 0)
......@@ -413,7 +412,7 @@ static struct directory *
directory_make_child_checked(struct directory *parent, const char *path)
{
struct directory *directory;
char *basename;
char *base;
struct stat st;
struct song *conflicting;
......@@ -421,21 +420,21 @@ directory_make_child_checked(struct directory *parent, const char *path)
if (directory != NULL)
return directory;
basename = g_path_get_basename(path);
base = g_path_get_basename(path);
if (stat_directory_child(parent, basename, &st) < 0 ||
if (stat_directory_child(parent, base, &st) < 0 ||
inodeFoundInParent(parent, st.st_ino, st.st_dev)) {
g_free(basename);
g_free(base);
return NULL;
}
/* if we're adding directory paths, make sure to delete filenames
with potentially the same name */
conflicting = songvec_find(&parent->songs, basename);
conflicting = songvec_find(&parent->songs, base);
if (conflicting)
delete_song(parent, conflicting);
g_free(basename);
g_free(base);
directory = directory_new_child(parent, path);
directory_set_stat(directory, &st);
......
......@@ -29,6 +29,15 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#ifndef assert_static
/* Compile time assertion developed by Ralf Holly */
/* http://pera-software.com/articles/compile-time-assertions.pdf */
#define assert_static(e) \
do { \
enum { assert_static__ = 1/(e) }; \
} while (0)
#endif /* !assert_static */
char *myFgets(char *buffer, int bufferSize, FILE * fp);
void stripReturnChar(char *string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment