Commit f0be54b6 authored by Led's avatar Led

0.9.0

parent 80d767ba
ver 0.9.0 (2003/9/30)
1) Random play mode
2) Alsa Mixer Support
3) Save and Restore "state"
4) Default config file locations (.mpdconf and /etc/mpd.conf)
5) Make db file locations configurable
6) Move songs around in the playlist
7) Gapless playback
8) Use Xing tags for mp3's
9) Remove stop_on_error
10) Seeking support
11) Playlists can be loaded and deleted from subdirectories
12) Complete rewrite of player layer (fork()'s only once, opens and closes
audio device as needed).
13) Eliminate use and dependence of SIGIO
14) IPv6 support
15) Solaris compilations fixes
16) Support for different log levels
17) Timestamps for log entries
18) "user" config parameter for setuid (patch from Nagilum)
19) Other misc features and bug fixes
ver 0.8.7 (2003/9/3) ver 0.8.7 (2003/9/3)
1) Fix a memory leak. When closing a interface, was called close() on the fd 1) Fix a memory leak. When closing a interface, was called close() on the fd
instead of calling fclose() on the fp that was opened with fdopen(). instead of calling fclose() on the fp that was opened with fdopen().
......
...@@ -6,20 +6,20 @@ Requirements ...@@ -6,20 +6,20 @@ Requirements
libao - http://www.vorbis.com/download_unix.psp libao - http://www.vorbis.com/download_unix.psp
(This comes with most/all distributions. Make sure you have both (This comes with most/all distributions. Make sure you have both
the ao libs and development packages for your distribution installed. the ao libs and development packages for your distribution installed.
For Red Hat 8.0, the neccessary packages are: libao and libao-devel) For Red Hat 8.0, the necessary packages are: libao and libao-devel)
zlib - http://www.gzip.org/zlib zlib - http://www.gzip.org/zlib
(This comes with all distributions. Make sure you have bot the zlib libs (This comes with all distributions. Make sure you have bot the zlib libs
and development packages for your distribution installed. For Red hat, and development packages for your distribution installed. For Red hat,
the neccessary packages are: zlib and zlib-devel) the necessary packages are: zlib and zlib-devel)
Optional Optional
-------- --------
Ogg Vorbis - http://www.xiph.org/ogg/vorbis/ Ogg Vorbis - http://www.xiph.org/ogg/vorbis/
(This comes with most/all distrobutions. Make sure you have both the (This comes with most/all distributions. Make sure you have both the
ogg and vorbis libs as well as the development packages for your ogg and vorbis libs as well as the development packages for your
distrobution installed. For Red Hat 8.0, the neccessary packages are: distribution installed. For Red Hat 8.0, the necessary packages are:
libogg, libogg-devel, libvorbis, and libvorbis-devel). libogg, libogg-devel, libvorbis, and libvorbis-devel).
Flac - http://flac.sf.net Flac - http://flac.sf.net
...@@ -33,7 +33,7 @@ Get the latest release from of MPD from http://www.musicpd.org ...@@ -33,7 +33,7 @@ Get the latest release from of MPD from http://www.musicpd.org
Compile Compile
------- -------
1) unzip and untar the argchive 1) unzip and untar the archive
$ tar zxvf mpd-x.x.x.tar.gz $ tar zxvf mpd-x.x.x.tar.gz
...@@ -80,6 +80,8 @@ run mpd like this: ...@@ -80,6 +80,8 @@ run mpd like this:
$ mpd <config file> $ mpd <config file>
(if no config file is specified, mpd's looks for ~/.mpdconf then /etc/mpd.conf)
an example would be: an example would be:
$ mpd playlists/.mpdconf $ mpd playlists/.mpdconf
...@@ -92,4 +94,6 @@ Using MPD ...@@ -92,4 +94,6 @@ Using MPD
You can download a web interface (phpMp) to MPD at You can download a web interface (phpMp) to MPD at
http://www.musicpd.org . http://www.musicpd.org .
Also, several other clients can be found for MPD at http://www.musicpd.org .
MPD can be interfaced directly using telnet (see COMMANDS, if you are brave). MPD can be interfaced directly using telnet (see COMMANDS, if you are brave).
bin_PROGRAMS = mpd SUBDIRS = src doc debian
SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR)
man_MANS = mpd.1
pkgdata_DATA =
docdir = $(prefix)/share/doc/$(PACKAGE) docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README UPGRADING doc_DATA = README UPGRADING
EXTRA_DIST = mpdconf.example COMMANDS COPYING $(pkgdata_DATA) $(man_MANS) $(doc_DATA) EXTRA_DIST = COPYING $(doc_DATA)
mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
song.h list.h directory.h tables.h utils.h path.h flac_decode.h \
tag.h player.h listen.h conf.h ogg_decode.h volume.h mp3_decode.h \
audio.h buffer.h stats.h myfprintf.h sig_handlers.h
mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
song.c list.c directory.c tables.c utils.c path.c flac_decode.c\
tag.c player.c listen.c conf.c ogg_decode.c volume.c mp3_decode.c \
audio.c buffer.c stats.c myfprintf.c sig_handlers.c $(mpd_headers)
CFLAGS = @CFLAGS@ $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB)
0.10.0
------
1) store song times (possibly after playing) 1) store song times (possibly after playing)
2) seeking 2) possibly, crossfading
3) set flags (such as BAD MP3) 3) resample in software for sound cards that support a limited range of
sampling rate.
possibly: 4) Password protection
---------
reference songs by an id #
spawn a seperate process for db updates, that pipes updates through a socket
to the main process
Music Player Daemon (MPD) - UPGRADING Music Player Daemon (MPD) - UPGRADING
Upgrading to 0.8.0 Upgrading to 0.9.x
------------------ ------------------
If you have flacs, then to have them added to your list of available music, The "stop_on_error" config parameter was removed, so be sure to remove this
parameter from your config file.
Upgrading to 0.8.x
------------------
If you have FLACs, then to have them added to your list of available music,
just use "update". just use "update".
Upgrading from 0.5.x to 0.6.x Upgrading from 0.5.x to 0.6.x
----------------------------- -----------------------------
If you have not compiled MPD with "make ogg", then nothing is needed. If you have not compiled MPD with "make ogg", then nothing is needed.
If you compiled with "make ogg", just use "update" (availabe via the phpMp If you compiled with "make ogg", just use "update" (available via the phpMp
interface) to add your ogg's to MPD's list of available music. interface) to add your OGGs to MPD's list of available music.
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.
AC_INIT(main.c) AC_INIT(src/main.c)
AM_INIT_AUTOMAKE(mpd, 0.8.7) AM_INIT_AUTOMAKE(mpd, 0.9.0)
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
...@@ -26,19 +26,84 @@ AC_ARG_ENABLE(mpd_mad,[ --enable-mpd-mad use mpd libmad],use_mpd_mad=yes,) ...@@ -26,19 +26,84 @@ AC_ARG_ENABLE(mpd_mad,[ --enable-mpd-mad use mpd libmad],use_mpd_mad=yes,)
AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support],,enable_id3=yes) AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support],,enable_id3=yes)
AC_ARG_ENABLE(mpd_id3tag,[ --enable-mpd-id3tag use mpd libid3tag],use_mpd_id3tag=yes,) AC_ARG_ENABLE(mpd_id3tag,[ --enable-mpd-id3tag use mpd libid3tag],use_mpd_id3tag=yes,)
AC_ARG_WITH(id3tag,[ --with-id3tag=PFX Prefix where libid3tag is installed (optional)], id3tag_prefix="$withval", id3tag_prefix="")
AC_ARG_WITH(id3tag-libraries,[ --with-id3tag-libraries=DIR Directory where libid3tag library is installed (optional)], id3tag_libraries="$withval", id3tag_libraries="")
AC_ARG_WITH(id3tag-includes,[ --with-id3tag-includes=DIR Directory where libid3tag header files are installed (optional)], id3tag_includes="$withval", id3tag_includes="")
AC_ARG_WITH(mad,[ --with-mad=PFX Prefix where libmad is installed (optional)], mad_prefix="$withval", mad_prefix="")
AC_ARG_WITH(mad-libraries,[ --with-mad-libraries=DIR Directory where libmad library is installed (optional)], mad_libraries="$withval", mad_libraries="")
AC_ARG_WITH(mad-includes,[ --with-mad-includes=DIR Directory where mad header files are installed (optional)], mad_includes="$withval", mad_includes="")
AC_CHECK_LIB(socket,socket,MPD_LIBS="$MPD_LIBS -lsocket",)
AC_CHECK_LIB(nsl,gethostbyname,MPD_LIBS="$MPD_LIBS -lnsl",)
AC_MSG_CHECKING(for ipv6)
AC_EGREP_CPP([AP_maGiC_VALUE],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#ifdef PF_INET6
#ifdef AF_INET6
AP_maGiC_VALUE
#endif
#endif
],
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_IPV6"
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
)
XIPH_PATH_AO(MPD_LIBS="$MPD_LIBS $AO_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AO_CFLAGS",AC_MSG_ERROR(Must have libao installed!!!)) XIPH_PATH_AO(MPD_LIBS="$MPD_LIBS $AO_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AO_CFLAGS",AC_MSG_ERROR(Must have libao installed!!!))
AC_CHECK_HEADER(sys/soundcard.h,,[MPD_CFLAGS="$MPD_CFLAGS -DNO_OSS_MIXER";AC_MSG_WARN(Soundcard headers not found -- disabling mixer)]) AC_CHECK_HEADER(sys/soundcard.h,,[MPD_CFLAGS="$MPD_CFLAGS -DNO_OSS_MIXER";AC_MSG_WARN(Soundcard headers not found -- disabling mixer)])
AC_MSG_CHECKING(for alsa)
AC_EGREP_CPP([AP_maGiC_VALUE],
[
#include <alsa/asoundlib.h>
#if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR)
#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR>=6)
AP_maGiC_VALUE
#endif
#endif
],
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_ALSA"
MPD_LIBS="$MPD_LIBS -lasound"
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
)
ID3_SUBDIR="" ID3_SUBDIR=""
if test x$enable_id3 = xyes; then if test x$enable_id3 = xyes; then
if test x$use_mpd_id3tag = xyes; then if test x$use_mpd_id3tag = xyes; then
ID3_SUBDIR="libid3tag" ID3_SUBDIR="libid3tag"
else else
if test "x$id3tag_libraries" != "x" ; then
ID3TAG_LIBS="-L$id3tag_libraries"
elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_LIBS="-L$id3tag_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ID3TAG_LIBS="-L$libdir"
fi
ID3TAG_LIBS="$ID3TAG_LIBS -lid3tag -lz"
if test "x$id3tag_includes" != "x" ; then
ID3TAG_CFLAGS="-I$id3tag_includes"
elif test "x$id3tag_prefix" != "x" ; then
ID3TAG_CFLAGS="-I$id3tag_prefix/lib"
elif test "x$prefix" != "xNONE"; then
ID3TAG_CFLAGS="-I$libdir"
fi
ID3TAG_CFLAGS="$ID3TAG_CFLAGS"
oldcflags=$CFLAGS oldcflags=$CFLAGS
CFLAGS="$CFLAGS -lz" CFLAGS="$CFLAGS $ID3TAG_CFLAGS $ID3TAG_LIBS"
AC_CHECK_LIB(id3tag,id3_file_open,[ID3_LIB="-lid3tag -lz"; AC_CHECK_LIB(id3tag,id3_file_open,[ID3_LIB="$ID3TAG_LIBS";
use_libid3tag=yes], MPD_CFLAGS="$MPD_CFLAGS $ID3TAG_CFLAGS";
use_libid3tag=yes],
[use_libid3tag=no;use_mpd_id3tag=yes]) [use_libid3tag=no;use_mpd_id3tag=yes])
CFLAGS=$oldcflags CFLAGS=$oldcflags
fi fi
...@@ -46,7 +111,7 @@ if test x$enable_id3 = xyes; then ...@@ -46,7 +111,7 @@ if test x$enable_id3 = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -DUSE_MPD_ID3TAG" MPD_CFLAGS="$MPD_CFLAGS -DUSE_MPD_ID3TAG"
ID3_LIB="libid3tag/libid3tag.la" ID3_LIB="libid3tag/libid3tag.la"
ID3_SUBDIR="libid3tag" ID3_SUBDIR="libid3tag"
AC_CONFIG_SUBDIRS(libid3tag) AC_CONFIG_SUBDIRS(src/libid3tag)
fi fi
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_ID3TAG" MPD_CFLAGS="$MPD_CFLAGS -DHAVE_ID3TAG"
fi fi
...@@ -57,24 +122,94 @@ if test x$enable_mp3 = xyes; then ...@@ -57,24 +122,94 @@ if test x$enable_mp3 = xyes; then
if test x$use_mpd_mad = xyes; then if test x$use_mpd_mad = xyes; then
MAD_SUBDIR="libmad" MAD_SUBDIR="libmad"
else else
AC_CHECK_LIB(mad,mad_stream_init,[MAD_LIB=-lmad;use_libmad=yes], if test "x$mad_libraries" != "x" ; then
MAD_LIBS="-L$mad_libraries"
elif test "x$mad_prefix" != "x" ; then
MAD_LIBS="-L$mad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MAD_LIBS="-L$libdir"
fi
MAD_LIBS="$MAD_LIBS -lmad"
if test "x$mad_includes" != "x" ; then
MAD_CFLAGS="-I$mad_includes"
elif test "x$mad_prefix" != "x" ; then
MAD_CFLAGS="-I$mad_prefix/lib"
elif test "x$prefix" != "xNONE"; then
MAD_CFLAGS="-I$libdir"
fi
AC_CHECK_LIB(mad,mad_stream_init,[MAD_LIB="$MAD_LIBS";
MPD_CFLAGS="$MPD_CFLAGS $MAD_CFLAGS";use_libmad=yes],
[use_libmad=no;use_mpd_mad=yes]) [use_libmad=no;use_mpd_mad=yes])
fi fi
if test x$use_mpd_mad = xyes; then if test x$use_mpd_mad = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -DUSE_MPD_MAD" MPD_CFLAGS="$MPD_CFLAGS -DUSE_MPD_MAD"
MAD_LIB="libmad/libmad.la" MAD_LIB="libmad/libmad.la"
MAD_SUBDIR="libmad" MAD_SUBDIR="libmad"
AC_CONFIG_SUBDIRS(libmad) AC_CONFIG_SUBDIRS(src/libmad)
fi fi
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_MAD" MPD_CFLAGS="$MPD_CFLAGS -DHAVE_MAD"
fi fi
if test x$enable_ogg = xyes; then if test x$enable_ogg = xyes; then
XIPH_PATH_OGG(MPD_LIBS="$MPD_LIBS $OGG_LIBS" MPD_CFLAGS="$MPD_CFLAGS $OGG_CFLAGS" enable_vorbistest=no,enable_ogg=no) XIPH_PATH_OGG(MPD_LIBS="$MPD_LIBS $OGG_LIBS" MPD_CFLAGS="$MPD_CFLAGS $OGG_CFLAGS",enable_ogg=no)
fi fi
if test x$enable_ogg = xyes; then if test x$enable_ogg = xyes; then
XIPH_PATH_VORBIS(MPD_LIBS="$MPD_LIBS $VORBIS_LIBS $VORBISFILE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $VORBIS_CFLAGS $VORBISFILE_CFLAGS",enable_ogg=no) enable_vorbistest=no
XIPH_PATH_VORBIS(,enable_ogg=no)
if test x$enable_ogg = xyes; then
dnl
dnl Vorbis Test
dnl vorbistest in XIPH_PATH_OGG is broken on my debian system
dnl so here i used my own hacked up version till i get vorbis-dev gets
dnl upgraded in debian (hopefully when 1.0.1 comes out)
dnl
AC_MSG_CHECKING(that Vorbis is usable)
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $VORBIS_CFLAGS $OGG_CFLAGS"
LIBS="$LIBS $VORBIS_LIBS $VORBISENC_LIBS $OGG_LIBS"
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>
int main ()
{
vorbis_block vb;
vorbis_dsp_state vd;
vorbis_info vi;
vorbis_info_init (&vi);
vorbis_encode_init (&vi, 2, 44100, -1, 128, -1);
/*vorbis_analysis_init (&vd, &vi);
vorbis_block_init (&vd, &vb);*/
/* this function was added in 1.0rc3, so this is what we're testing for */
/*vorbis_bitrate_addblock (&vb);*/
return 0;
}
], AC_MSG_RESULT(yes), AC_MSG_RESULT(no) enable_ogg=no,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
dnl
dnl End of Vorbis Test
dnl
if test x$enable_ogg = xyes; then
MPD_LIBS="$MPD_LIBS $VORBIS_LIBS $VORBISFILE_LIBS"
MPD_CFLAGS="$MPD_CFLAGS $VORBIS_CFLAGS $VORBISFILE_CFLAGS"
fi
fi fi
if test x$enable_ogg = xyes; then if test x$enable_ogg = xyes; then
...@@ -107,4 +242,4 @@ if test x$enable_flac = xyes; then ...@@ -107,4 +242,4 @@ if test x$enable_flac = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_FLAC" MPD_CFLAGS="$MPD_CFLAGS -DHAVE_FLAC"
fi fi
AC_OUTPUT(Makefile) AC_OUTPUT(debian/Makefile doc/Makefile src/Makefile Makefile )
EXTRA_DIST = changelog compat control copyright dirs docs rules
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in 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.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AO_CFLAGS = @AO_CFLAGS@
AO_LIBS = @AO_LIBS@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EGREP = @EGREP@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
ID3_LIB = @ID3_LIB@
ID3_SUBDIR = @ID3_SUBDIR@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LIBFLAC_CFLAGS = @LIBFLAC_CFLAGS@
LIBFLAC_LIBS = @LIBFLAC_LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAD_LIB = @MAD_LIB@
MAD_SUBDIR = @MAD_SUBDIR@
MPD_CFLAGS = @MPD_CFLAGS@
MPD_LIBS = @MPD_LIBS@
OBJDUMP = @OBJDUMP@
OGG_CFLAGS = @OGG_CFLAGS@
OGG_LIBS = @OGG_LIBS@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@
VERSION = @VERSION@
VORBISENC_LIBS = @VORBISENC_LIBS@
VORBISFILE_LIBS = @VORBISFILE_LIBS@
VORBIS_CFLAGS = @VORBIS_CFLAGS@
VORBIS_LIBS = @VORBIS_LIBS@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
EXTRA_DIST = changelog compat control copyright dirs docs rules
subdir = debian
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DIST_COMMON = Makefile.am Makefile.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign debian/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
tags: TAGS
TAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
uninstall-am: uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool uninstall uninstall-am uninstall-info-am
# 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:
mpd (0.9.0-1) unstable; urgency=low
* Update to 0.9.0
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 29 Sep 2003 19:39:00 -0400
mpd (0.8.7-1) unstable; urgency=low
* Update to 0.8.7
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 03 Sep 2003 22:39:00 -0400
mpd (0.8.6-1) unstable; urgency=low
* Update to 0.8.6
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 25 Aug 2003 20:35:00 -0400
mpd (0.8.5-1) unstable; urgency=low
* Update to 0.8.5
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 17 Aug 2003 22:50:00 -0400
mpd (0.8.4-1) unstable; urgency=low
* Update to 0.8.4
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 12 Aug 2003 19:35:00 -0400
mpd (0.8.3-1) unstable; urgency=low
* Update to 0.8.3
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 12 Aug 2003 19:35:00 -0400
mpd (0.8.2-1) unstable; urgency=low
* Initial Release.
-- Warren Dukes <shank@mercury.chem.pitt.edu> Fri, 25 Jul 2003 10:28:30 -0400
Source: mpd
Section: sound
Priority: optional
Maintainer: Warren Dukes <shank@mercury.chem.pitt.edu>
Build-Depends: debhelper (>> 4.0.0), libao-dev (>=0.8.3-1), libogg-dev, libvorbis-dev, libflac-dev (>=1.1.0-4), libmad0-dev, libid3tag0-dev
Standards-Version: 3.5.8
Package: mpd
Architecture: any
Depends: ${shlibs:Depends}
Description: Music Player Daemon (MPD)
MPD is a server that allows remote access for playing
music (MP3, Ogg Vorbis, and Flac) and managing playlists. The design focus is
on integrating a computer into a stereo system that provides control for music
playback over a local network. Currently, it includes a Web interface, phpMp;
a command line tool, mpc; and a dock app, WMmp. The goals are to be easy to
install and use, to have minimal resource requirements, and to be stable and
flexible.
This package was debianized by Warren Dukes <shank@mercury.chem.pitt.edu> on
Fri, 25 Jul 2003 10:28:30 -0400.
It was downloaded from http://musicpd.sf.net
Upstream Author: Warren Dukes <shank@mercury.chem.pitt.edu>
This software is copyright (c) 2003 by Warren Dukes
You are free to distribute this software under the terms of
the GNU General Public License.
On Debian systems, the complete text of the GNU General Public
License can be found in the file `/usr/share/common-licenses/GPL'.
usr/bin
usr/share/man/man1
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
config.status: configure
dh_testdir
# Add here commands to configure the package.
./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
#/usr/bin/docbook-to-man debian/mpd.sgml > mpd.1
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
-$(MAKE) distclean
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/mpd.
$(MAKE) install DESTDIR=$(CURDIR)/debian/mpd
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples doc/mpdconf.example
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
# dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
...@@ -14,7 +14,7 @@ command <type arg1> <type arg2> ... ...@@ -14,7 +14,7 @@ command <type arg1> <type arg2> ...
Command Completion: Command Completion:
------------------- -------------------
A command returns "OK\n" on completeion or "ACK some error\n" on failure. A command returns "OK\n" on completion or "ACK some error\n" on failure.
These denote the end of command execution. These denote the end of command execution.
Commands: Commands:
...@@ -31,7 +31,7 @@ clearerror ...@@ -31,7 +31,7 @@ clearerror
(this is also accomplished by any command that starts playback) (this is also accomplished by any command that starts playback)
close close
close the connection with the mpd close the connection with the MPD
delete <int song> delete <int song>
delete _song_ from playlist delete _song_ from playlist
...@@ -42,12 +42,12 @@ find <string type> <string what> ...@@ -42,12 +42,12 @@ find <string type> <string what>
_what_ is what to find _what_ is what to find
kill kill
kill mpd kill MPD
list <string type> <string arg1> list <string type> <string arg1>
list all tags of _type_ list all tags of _type_
_type_ should be "album" or "artist" _type_ should be "album" or "artist"
_arg1_ is an optional paramter when type is album, this specifies _arg1_ is an optional parameter when type is album, this specifies
to list albums by a artist, where artist is specified with to list albums by a artist, where artist is specified with
arg1 arg1
...@@ -66,6 +66,9 @@ ls <string directory> ...@@ -66,6 +66,9 @@ ls <string directory>
lsinfo <string directory> lsinfo <string directory>
list contents of _directory_, from the db. _directory_ is optional list contents of _directory_, from the db. _directory_ is optional
move <int from> <int to>
move song at _from_ to _to_ in the playlist
next next
plays next song in playlist plays next song in playlist
...@@ -73,7 +76,7 @@ pause ...@@ -73,7 +76,7 @@ pause
pause/resume playing pause/resume playing
play <int song> play <int song>
begin playling playlist at song number _song_, _song_ is optiional begin playing playlist at song number _song_, _song_ is optional
playlist playlist
displays the current playlist displays the current playlist
...@@ -85,19 +88,23 @@ playlistinfo ...@@ -85,19 +88,23 @@ playlistinfo
previous previous
plays previous song in playlist plays previous song in playlist
repeat <int state>
set repeat state to _state_, _state_ should be 0 or 1
rm <string name> rm <string name>
removes the playlist <name>.m3u from the playlist directory removes the playlist <name>.m3u from the playlist directory
save <string name> save <string name>
saves the current playlist to _name_.m3u in the playlist directory saves the current playlist to _name_.m3u in the playlist directory
repeat <int state>
set repeat state to _state_, _state_ should be 0 or 1
search <string type> <string what> search <string type> <string what>
same as "find" but searches for any song that contain _what_ same as "find" but searches for any song that contain _what_
search is not case sensitive search is not case sensitive
seek <int song> <int time>
seeks to the position _time_ (in seconds) of entry _song_ in the
playlist
shuffle shuffle
shuffles the current playlist shuffles the current playlist
...@@ -107,15 +114,16 @@ stats ...@@ -107,15 +114,16 @@ stats
albums: number of albums albums: number of albums
songs: number of songs songs: number of songs
uptime: daemon uptime in seconds uptime: daemon uptime in seconds
db_update: last db update in unix time db_update: last db update in UNIX time
playtime: time length of music played playtime: time length of music played
songs_played: total number of songs played songs_played: total number of songs played
status status
reports current status of player, and volume level. reports current status of player, and volume level.
volume: (0-100). volume: (0-100).
repat: (0 or 1) repeat: (0 or 1)
playlist: (31-bit unsigned integer, the playlist version number) playlist: (31-bit unsigned integer, the playlist version number)
playlistlength: (integer, the length of the playlist)
state: ("play", "stop", or "pause") state: ("play", "stop", or "pause")
song: (current song playing/paused, playlist song number) song: (current song playing/paused, playlist song number)
time: <int elapsed>:<time total> (of current playing/paused song) time: <int elapsed>:<time total> (of current playing/paused song)
...@@ -124,6 +132,9 @@ status ...@@ -124,6 +132,9 @@ status
stop stop
stop playing stop playing
swap <int song1> <int song2>
swap positions of _song1_ and _song2_
update update
searches mp3 directory for new music and removes old music from the db searches mp3 directory for new music and removes old music from the db
...@@ -133,7 +144,7 @@ volume <int change> ...@@ -133,7 +144,7 @@ volume <int change>
COMMAND LIST COMMAND LIST
------------ ------------
To faciliate faster adding of files, etc, you can pass a list of commands all 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: at once using a command list. The command list beings with:
command_list_begin command_list_begin
......
man_MANS = mpd.1
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = COMMANDS
EXTRA_DIST = mpdconf.example $(man_MANS) $(doc_DATA)
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in 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.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AO_CFLAGS = @AO_CFLAGS@
AO_LIBS = @AO_LIBS@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EGREP = @EGREP@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
ID3_LIB = @ID3_LIB@
ID3_SUBDIR = @ID3_SUBDIR@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LIBFLAC_CFLAGS = @LIBFLAC_CFLAGS@
LIBFLAC_LIBS = @LIBFLAC_LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAD_LIB = @MAD_LIB@
MAD_SUBDIR = @MAD_SUBDIR@
MPD_CFLAGS = @MPD_CFLAGS@
MPD_LIBS = @MPD_LIBS@
OBJDUMP = @OBJDUMP@
OGG_CFLAGS = @OGG_CFLAGS@
OGG_LIBS = @OGG_LIBS@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@
VERSION = @VERSION@
VORBISENC_LIBS = @VORBISENC_LIBS@
VORBISFILE_LIBS = @VORBISFILE_LIBS@
VORBIS_CFLAGS = @VORBIS_CFLAGS@
VORBIS_LIBS = @VORBIS_LIBS@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
man_MANS = mpd.1
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = COMMANDS
EXTRA_DIST = mpdconf.example $(man_MANS) $(doc_DATA)
subdir = doc
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_SOURCES =
NROFF = nroff
MANS = $(man_MANS)
DATA = $(doc_DATA)
DIST_COMMON = Makefile.am Makefile.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign doc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
man1dir = $(mandir)/man1
install-man1: $(man1_MANS) $(man_MANS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(man1dir)
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.1*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
else file=$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
1*) ;; \
*) ext='1' ;; \
esac; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
done
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.1*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
rm -f $(DESTDIR)$(man1dir)/$$inst; \
done
docDATA_INSTALL = $(INSTALL_DATA)
install-docDATA: $(doc_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(docdir)
@list='$(doc_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f"; \
$(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f; \
done
uninstall-docDATA:
@$(NORMAL_UNINSTALL)
@list='$(doc_DATA)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(docdir)/$$f"; \
rm -f $(DESTDIR)$(docdir)/$$f; \
done
tags: TAGS
TAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(MANS) $(DATA)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(man1dir) $(DESTDIR)$(docdir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-docDATA install-man
install-exec-am:
install-info: install-info-am
install-man: install-man1
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
uninstall-am: uninstall-docDATA uninstall-info-am uninstall-man
uninstall-man: uninstall-man1
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am info info-am install install-am install-data \
install-data-am install-docDATA install-exec install-exec-am \
install-info install-info-am install-man install-man1 \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool uninstall uninstall-am \
uninstall-docDATA uninstall-info-am uninstall-man \
uninstall-man1
# 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:
.TH "Music Player Daemon" 1
.SH NAME
MPD \- A daemon for playing music (mp3, ogg vorbis, and flac)
.SH SYNOPSIS
.B mpd
.RI [ options ]
.RI [ CONF_FILE ]
.br
.B mpd
.RI [ options ]
.I PORT MUSIC_DIR PLAYLIST_DIR LOG_FILE ERROR_FILE
.br
.SH DESCRIPTION
MPD is a daemon for playing music (mp3, ogg vorbis, and flac). Music is played
through the server's audio device. The daemon stores info about all available
music, and this info can be easily searched and retrieved. Player control, info
retrieval, and playlist management can all be managed remotely.
MPD searches for a config file in ~/.mpdconf then /etc/mpd.conf or uses
CONF_FILE. Instead of using a config file, the minimal configuration paramters
can be specified on the command line: PORT, MUSIC_DIR, PLAYLIST_DIR, LOG_FILE,
and ERROR_FILE.
Read more about MPD on http://www.musicpd.org
.SH OPTIONS
.TP
.B --create-db
(Re)Crete the db file for mpd.
.TP
.BI --help
Output a brief help message.
.br
.TP
.BI --no-daemon
Don't detach from console or redirect output to log files.
.TP
.BI --verbose
Output verbose amounts of information to the logs
.TP
.BI --version
Print version information.
.SH PARAMETERS
Below are a list of parameters that can be specified in the config file. Each line in the config file should be of the form:
.br
parameter "value"
.TP
.B port <port>
This specifies the port that MPD listens on. This parameter is required. This is typically 2100.
.TP
.B music_directory <directory>
This specifies the directory where music is located. This parameter is required. The directory path should be an absolute path.
.TP
.B playlist_directory <directory>
This specifies the directory where saved playlists are stored. This parameter is required. The directory path should be an absolute path.
.TP
.B log_file <file>
This specifies where the log file should be located. This parameter is required. The file path should be an absolute path.
.TP
.B error_file <file>
This specifies where the error file should be located. This parameter is required. The file path should be an absolute path.
.TP
.B log_level <default, secure, or verbose>
This specifies how verbose logs are. "default" is minimal logging, "secure" reports from what address a connection is opened, and when it is closed, and "verbose" records excessive amounts of information for debugging purposes. The default is "default".
.TP
.B db_file <file>
This specifies where the db file will be stored. The file path should be an
absolute path. The default is ".mpddb" in the playlist directory.
.TP
.B state_file <file>
This specifies if a state file is used and where it is located. The file path should be an absolute path. The state of mpd will be saved to this file when mpd is terminated by a TERM signal or by the "kill" command.
.TP
.B user <user>
This specifies the user that mpd will run as, if set.
.TP
.B connection_timeout <seconds>
If a client does not send any new data in this time period, the connection is closed. The default is 60 seconds.
.TP
.B max_connections <int>
This specifies the maximum number of clients that can be connected to MPD. The default is 5 connections.
.TP
.B mixer_device <mixer dev>
This specifies which mixer to use. The default for oss is /dev/mixer;
the default for alsa is "hw:0".
.TP
.B mixer_type <oss or alsa>
This specifies which mixer to use. The default is oss.
.TP
.B max_playlist_length <int>
This specifies the maximum number of songs that can be in the playlist. The default is 4096 songs.
.TP
.B buffer_before play <0-100%>
This specifies the amount of buffer that will be filled before a song begins playing. The default is 25%.
.TP
.B stop_on_error <yes or no>
This specifies whether playback should stop or goto the next song when an error occurs. The default is no.
.TP
.B max_command_list_size <size in KB>
This specifies the maximum size a command list can be (in kilobytes). The default is 2048 kilobytes.
.TP
.B max_output_buffer_size <size in KB>
This specifies the maximum size of the output buffer to a client (in kilobytes).
The default is 2048 kilobytes.
.TP
.B ao_driver <ao plug-in>
This specifies the ao plug-in to use for audio output. Typical values for
Linux include "oss" and "alsa09". The default value is "default".
.TP
.B ao_driver_options <ao plug-in options>
This specifies the options to use for the selected ao_driver. For oss, the
only option available is "dsp". For alsa09, the available options are:
"dev", "buf_size", and "periods". Options are assigned using "=" and ";" is
used to separate options. An example for oss: "dsp=/dev/dsp". An example for
alsa09: "dev=hw:0,0;buf_size=4096". The default value is "".
.TP
.B save_absolute_paths_in_playlists <yes or no>
This specifies whether relative or absolute paths for song filenames are
used when saving playlists. The default value is "no".
.TP
.B bind_to_address <ip address or hostname or any>
This specifies which address MPD binds to and listens on. The default is "any",
which binds to all available addresses.
.SH EXAMPLES
.TP
Below is an example config file.
.br
.br
# required
.br
port "2100"
.br
music_directory "/home/shank/mp3"
.br
playlist_directory "/home/shank/playlists"
.br
log_file "/home/shank/mpd.log"
.br
error_file "/home/shank/mpd.error"
.br
.br
# optional
.br
mixer_type "oss"
.br
mixer_device "/dev/mixer"
.br
#mixer_type "alsa"
.br
#mixer_device "default"
.br
#ao_driver "oss"
.br
#ao_driver_options "dsp=/dev/dsp"
.br
max_playlist_length "4096"
.br
buffer_before_play "25%"
.br
#db_file "/home/shank/playlists/.mpddb"
.br
#state_file "/home/shank/playlists/.mpdstate"
.br
#user "shank"
.br
connection_timeout "60"
.br
max_connections "5"
.br
max_command_list_size "2048"
.br
max_output_buffer_size "2048"
.br
save_absolute_paths_in_playlists "no"
.br
# log_level can be "default", "secure", "verbose"
.br
log_level "default"
.br
# if bind_to_address is "any", MPD binds all addresses
.br
bind_to_address "any"
.SH SEE ALSO
mpc(1)
...@@ -6,16 +6,23 @@ log_file "/home/shank/mpd.log" ...@@ -6,16 +6,23 @@ log_file "/home/shank/mpd.log"
error_file "/home/shank/mpd.error" error_file "/home/shank/mpd.error"
# optional # optional
connection_timeout "60" mixer_type "oss"
mixer_device "/dev/mixer" mixer_device "/dev/mixer"
max_connections "5" #mixer_type "alsa"
#mixer_device "default"
#ao_driver "oss"
#ao_driver_options "dsp=/dev/dsp"
max_playlist_length "4096" max_playlist_length "4096"
buffer_before_play "25%" buffer_before_play "25%"
stop_on_error "yes" #db_file "/home/shank/playlists/.mpddb"
#state_file "/home/shank/playlists/.mpdstate"
#user "shank"
connection_timeout "60"
max_connections "5"
max_command_list_size "2048" max_command_list_size "2048"
max_output_buffer_size "2048" max_output_buffer_size "2048"
ao_driver "oss"
ao_driver_options "dsp=/dev/dsp"
save_absolute_paths_in_playlists "no" save_absolute_paths_in_playlists "no"
# when bind_to_address is set to "any", mpd binds all availabe addresses # log_level can be "default", "secure", "verbose"
log_level "default"
# when bind_to_address is set to "any", MPD binds all available addresses
bind_to_address "any" bind_to_address "any"
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_FLAC
#include "flac_decode.h"
#include "player.h"
#include "command.h"
#include "utils.h"
#include "audio.h"
#include "buffer.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <ao/ao.h>
#include <FLAC/file_decoder.h>
#include <FLAC/metadata.h>
#define INPUT_BUFFER_SIZE 80
#define CHECK_INPUT_FREQ 300 /* about once very 0.1 seconds */
#define TIME_TELL_INTERVAL 0.2
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
typedef struct {
unsigned char chunk[CHUNK_SIZE];
int chunk_length;
float time;
Buffer * cb;
ao_sample_format * format;
} FlacData;
int flac_decode_pid = 0;
int flac_decode_done = 0;
ao_device * flac_device = NULL;
/* this code is based on flac123, from flac-tools */
void flacPlayfile(const char * file, Buffer * cb, ao_sample_format * format);
void flacError(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *);
void flacMetadata(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *);
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const buf[], void *);
void flacPlayFile(const char *file, Buffer * cb, ao_sample_format * format)
{
FLAC__FileDecoder * flacDec;
FlacData data;
data.chunk_length = 0;
data.time = 0;
data.cb = cb;
data.format = format;
flacDec = FLAC__file_decoder_new();
FLAC__file_decoder_set_md5_checking(flacDec,TRUE);
FLAC__file_decoder_set_filename(flacDec,file);
FLAC__file_decoder_set_write_callback(flacDec,flacWrite);
FLAC__file_decoder_set_metadata_callback(flacDec,flacMetadata);
FLAC__file_decoder_set_error_callback(flacDec,flacError);
FLAC__file_decoder_set_client_data(flacDec, (void *)&data);
FLAC__file_decoder_init(flacDec);
FLAC__file_decoder_process_until_end_of_file(flacDec);
FLAC__file_decoder_finish(flacDec);
FLAC__file_decoder_delete(flacDec);
}
void flacError(const FLAC__FileDecoder *dec, FLAC__StreamDecoderErrorStatus status, void *data) {
}
void flacMetadata(const FLAC__FileDecoder *dec, const FLAC__StreamMetadata *meta, void *data) {
}
void flacSendChunk(FlacData * data) {
while(data->cb->begin==data->cb->end && data->cb->wrap)
usleep(100);
memcpy(data->cb->chunks[data->cb->end],data->chunk,CHUNK_SIZE);
data->cb->times[data->cb->end] = data->time;
data->cb->end++;
if(data->cb->end>=BUFFERED_CHUNKS) {
data->cb->end = 0;
data->cb->wrap = 1;
}
}
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *dec, const FLAC__Frame *frame, const FLAC__int32 * const buf[], void * vdata) {
FlacData * data = (FlacData *)vdata;
uint_32 dataSize = frame->header.blocksize * frame->header.channels
* (data->format->bits / 8);
uint_32 samples = frame->header.blocksize;
uint_16 ldb[samples*frame->header.channels];
int c_samp, c_chan, d_samp;
unsigned char * ldbuc = (unsigned char *)ldb;
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
for(c_chan = 0; c_chan < frame->header.channels;
c_chan++, d_samp++) {
ldb[d_samp] = buf[c_chan][c_samp];
}
}
data->time+=((float)samples)/frame->header.sample_rate;
while(dataSize>0) {
if(data->chunk_length>=CHUNK_SIZE) {
flacSendChunk(data);
data->chunk_length = 0;
}
data->chunk[data->chunk_length++] = *(ldbuc++);
dataSize--;
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
int flac_getAoDataAndTime(char * file, ao_sample_format * format, float * time) {
FLAC__Metadata_SimpleIterator * it;
FLAC__StreamMetadata * block = NULL;
int found = 0;
int ret = -1;
it = FLAC__metadata_simple_iterator_new();
if(!FLAC__metadata_simple_iterator_init(it,file,1,0)) {
FLAC__metadata_simple_iterator_delete(it);
return -1;
}
do {
if(block) FLAC__metadata_object_delete(block);
block = FLAC__metadata_simple_iterator_get_block(it);
if(block->type == FLAC__METADATA_TYPE_STREAMINFO) found=1;
} while(!found && FLAC__metadata_simple_iterator_next(it));
if(found) {
format->bits = block->data.stream_info.bits_per_sample;
format->rate = block->data.stream_info.sample_rate;
format->channels = block->data.stream_info.channels;
format->byte_format = AO_FMT_LITTLE;
*time = ((float)block->data.stream_info.total_samples)/format->rate;
ret = 0;
}
if(block) FLAC__metadata_object_delete(block);
FLAC__metadata_simple_iterator_delete(it);
return ret;
}
void flac_decode_parentSigHandler(int sig) {
if(sig==SIGCHLD) {
if(flac_decode_pid==wait3(NULL,WNOHANG,NULL)) {
flac_decode_pid = 0;
flac_decode_done = 1;
}
}
if(sig==SIGTERM) {
int pid = flac_decode_pid;
if(pid>0) kill(pid,SIGTERM);
if(flac_device) ao_close(flac_device);
exit(0);
}
}
/* flac_decode w/ buffering
* this will fork another process
* child process does decoding
* parent process does buffering && playing audio
*/
int flac_decode(char * file, FILE * in, FILE * out) {
Buffer * cb;
ao_sample_format format;
float total_time;
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE,&sa,NULL);
sa.sa_handler = flac_decode_parentSigHandler;
sigaction(SIGCHLD,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
cb = getBuffer();
cb->begin = 0;
cb->end = 0;
cb->wrap = 0;
cb->finished = 0;
if(flac_getAoDataAndTime(file,&format,&total_time)<0) {
fprintf(stderr,"%s \"%s\" doesn't seem to be a flac\n",COMMAND_RESPOND_ERROR,file);
return PLAYER_EXIT_ERROR_FILE;
}
fflush(NULL);
flac_decode_pid = fork();
if(flac_decode_pid==0) {
/* CHILD */
fclose(in);
fclose(out);
flacPlayFile(file,cb,&format);
cb->finished = 1;
exit(0);
/* END OF CHILD */
}
else if(flac_decode_pid<0) {
fprintf(stderr,"%s flac_decode Problems fork'ing\n",COMMAND_RESPOND_ERROR);
return PLAYER_EXIT_ERROR_SYSTEM;
}
{
/* PARENT */
float elapsed = 0;
float last_tell = 0;
int pause = 0;
char input[INPUT_BUFFER_SIZE+1];
int playsPerChunk = CHUNK_SIZE/PLAY_SIZE;
int currentPlayChunk = 0;
int quit = 0;
fd_set fds;
struct timeval tv;
int checkInput = 0;
int pid;
tv.tv_sec = 0;
tv.tv_usec = 0;
initAudio();
flac_device = ao_open_live(audio_ao_driver_id,&format,
audio_ao_options);
if(flac_device == NULL) {
audioError();
pid = flac_decode_pid;
if(pid>0) kill(pid,SIGTERM);
return PLAYER_EXIT_ERROR_AUDIO;
}
fprintf(out,"%s\n",PLAYER_START);
fprintf(out,"%s %f %f\n",PLAYER_TIME,last_tell,total_time);
fflush(out);
while(flac_decode_pid>0 && !cb->wrap && cb->end-cb->begin<buffered_before_play && !cb->finished) {
usleep(1000);
}
while(!quit) {
if(pause || checkInput%CHECK_INPUT_FREQ==0) {
FD_ZERO(&fds);
FD_SET(fileno(in),&fds);
fflush(in);
if(select(fileno(in)+1,&fds,NULL,NULL,&tv)) {
myFgets(input,INPUT_BUFFER_SIZE,in);
if(strcasecmp(PLAYER_PAUSE,input)==0) {
fprintf(out,"%s\n",PLAYER_PAUSE_GOT);
fflush(out);
pause = !pause;
}
}
checkInput = 1;
}
checkInput++;
if(pause) usleep(100);
else if(cb->begin!=cb->end || cb->wrap) {
if(currentPlayChunk==0) elapsed = cb->times[cb->begin];
ao_play(flac_device,cb->chunks[cb->begin]+currentPlayChunk*PLAY_SIZE,PLAY_SIZE);
currentPlayChunk++;
if(currentPlayChunk>=playsPerChunk) {
currentPlayChunk=0;
cb->begin++;
if(cb->begin>=BUFFERED_CHUNKS) {
cb->begin = 0;
cb->wrap = 0;
}
}
if(elapsed-last_tell>=TIME_TELL_INTERVAL) {
last_tell = elapsed;
fprintf(out,"%s %f %f\n",PLAYER_TIME,last_tell,total_time);
fflush(out);
}
}
else if(flac_decode_pid<=0 || cb->finished) {
quit = 1;
}
else usleep(200);
}
pid = flac_decode_pid;
if(pid>0) kill(pid,SIGTERM);
ao_close(flac_device);
finishAudio();
/* END OF PARENT */
}
return 0;
}
#endif
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.
/* the Music Player Daemon (MPD)
* (c)2002 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "listen.h"
#include "interface.h"
#include "conf.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <resolv.h>
#include <fcntl.h>
#define MAXHOSTNAME 1024
#define ALLOW_REUSE 1
int listenSocket;
int establish(unsigned short port) {
int allowReuse = ALLOW_REUSE;
int sock;
struct sockaddr_in sockAddr;
struct hostent * he;
memset(&sockAddr, 0, sizeof(struct sockaddr_in));
sockAddr.sin_port = htons(port);
if(strcmp((getConf())[CONF_BIND_TO_ADDRESS],"any")==0) {
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = INADDR_ANY;
}
else {
if(!(he = gethostbyname((getConf())[CONF_BIND_TO_ADDRESS]))) {
fprintf(stderr,"can't lookup host \"%s\"\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
exit(-1);
}
sockAddr.sin_family = he->h_addrtype;
bcopy((char *)he->h_addr,(char *)&sockAddr.sin_addr.s_addr,
he->h_length);
}
if((sock = socket(sockAddr.sin_family,SOCK_STREAM,0)) < 0) {
fprintf(stderr,"socket < 0\n");
return -1;
}
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&allowReuse,sizeof(allowReuse))<0) {
close(sock);
fprintf(stderr,"problems setsockopt'ing\n");
return -1;
}
if(bind(sock,(struct sockaddr *)&sockAddr,sizeof(struct sockaddr_in))<0) {
fprintf(stderr,"unable to bind port %i, maybe mpd is still running?\n",port);
close(sock);
return -1;
}
listen(sock,5);
fcntl(sock,F_SETOWN,(int)getpid());
fcntl(sock,F_SETFL,fcntl(sock,F_GETFL) | O_ASYNC);
return sock;
}
void getConnections(int sock) {
fd_set fdsr;
int fd = 0;
struct timeval tv;
tv.tv_sec = tv.tv_usec = 0;
fflush(NULL);
FD_ZERO(&fdsr);
FD_SET(sock,&fdsr);
if(select(sock+1,&fdsr,NULL,NULL,&tv)==1 &&
((fd = accept(sock,NULL,NULL)) >= 0)) {
openAInterface(fd);
}
else if(fd<0) {
fprintf(stderr,"Problems accept()'ing\n");
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/* the Music Player Daemon (MPD)
* (c)2002 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "interface.h"
#include "command.h"
#include "playlist.h"
#include "directory.h"
#include "tables.h"
#include "player.h"
#include "listen.h"
#include "conf.h"
#include "path.h"
#include "buffer.h"
#include "stats.h"
#include "sig_handlers.h"
#include "audio.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
void usage(char * argv[]) {
fprintf(stderr,"usage: %s <port> <mp3/ogg dir> <playlist dir> <log file> <error file>\n",argv[0]);
fprintf(stderr,"or: %s <conf file>\n",argv[0]);
}
int main(int argc, char * argv[]) {
int port;
struct stat st;
FILE * out;
FILE * err;
char * portStr;
char * musicDirArg;
char * playlistDirArg;
char * logFile;
char * errorFile;
initConf();
if(argc==6) {
portStr = argv[1];
musicDirArg = argv[2];
playlistDirArg = argv[3];
logFile = argv[4];
errorFile = argv[5];
}
else if(argc==2) {
char ** conf = readConf(argv[1]);
portStr = conf[CONF_PORT];
musicDirArg = conf[CONF_MUSIC_DIRECTORY];
playlistDirArg = conf[CONF_PLAYLIST_DIRECTORY];
logFile = conf[CONF_LOG_FILE];
errorFile = conf[CONF_ERROR_FILE];
}
else {
usage(argv);
return -1;
}
if((port = atoi(portStr))<0) {
fprintf(stderr,"problem with port number\n");
return -1;
}
if(NULL==(out=fopen(logFile,"a"))) {
fprintf(stderr,"problem opening file \"%s\" for writing\n",logFile);
return -1;
}
if(NULL==(err=fopen(errorFile,"a"))) {
fprintf(stderr,"problem opening file \"%s\" for writing\n",errorFile);
return -1;
}
if(playlistDirArg[0]=='/') {
strcpy(playlistDir,playlistDirArg);
}
else {
getcwd(playlistDir,MAXPATHLEN-strlen(playlistDirArg)-1);
if(playlistDir[strlen(playlistDir)-1]!='/') {
strcat(playlistDir,"/");
}
strcat(playlistDir,playlistDirArg);
}
if(playlistDir[strlen(playlistDir)-1]!='/') {
strcat(playlistDir,"/");
}
if((stat(playlistDir,&st))<0) {
fprintf(stderr,"problem stat'ing \"%s\"\n",playlistDirArg);
return -1;
}
if(!S_ISDIR(st.st_mode)) {
fprintf(stderr,"\"%s\" is not a directory\n",playlistDirArg);
return -1;
}
if(musicDirArg[0]=='/') {
strcpy(musicDir,musicDirArg);
}
else {
getcwd(musicDir,MAXPATHLEN-strlen(musicDirArg)-1);
if(musicDir[strlen(musicDir)-1]!='/') strcat(musicDir,"/");
strcat(musicDir,musicDirArg);
}
if(musicDir[strlen(musicDir)-1]!='/') strcat(musicDir,"/");
if((stat(musicDir,&st))<0) {
fprintf(stderr,"problem stat'ing \"%s\"\n",musicDirArg);
return -1;
}
if(!S_ISDIR(st.st_mode)) {
fprintf(stderr,"\"%s\" is not a directory\n",musicDirArg);
return -1;
}
initTables();
strcpy(directorydb,playlistDir);
strcat(directorydb,"/");
strcat(directorydb,".mpddb");
if(readDirectoryDB()<0) {
initMp3Directory();
if(writeDirectoryDB()<0) {
fprintf(stderr,"problem opening db for reading or writing\n");
exit(-1);
}
}
initAudioDriver();
initSigHandlers();
initInterfaces();
if((listenSocket = establish(port))<0) {
fprintf(stderr,"error binding port\n");
return -1;
}
initPlaylist();
initStats();
initBuffer();
daemon(0,0);
dup2(fileno(out),STDOUT_FILENO);
dup2(fileno(err),STDERR_FILENO);
fclose(stdin);
while(COMMAND_RETURN_KILL!=doIOForInterfaces()) {
nextSongInPlaylistIfPlayerStopped();
playerProcessMessages();
closeOldInterfaces();
}
playerStop(stderr);
clearPlaylist(stderr);
freeAllInterfaces();
close(listenSocket);
closeMp3Directory();
closeTables();
freeBuffer();
finishAudioDriver();
return 0;
}
.TH "Music Player Daemon" 1
.SH NAME
mpd \- A daemon for playing music (mp3, ogg vorbis, and flac)
.SH SYNOPSIS
.B mpd
<port> <music dir> <playlist dir> <log file> <error file>
.br
.B mpd
<config file>
.SH DESCRIPTION
A daemon for playing music (mp3, ogg vorbis, and flac). Music is played
through the server's audio device. The daemon stores info about all available
music, and this info can be easily searched and retrieved. Player control, info
retrieval, and playlist management can all be managed remotely.
Read more about MPD on http://www.musicpd.org
.SH PARAMETERS
Below are a list of paramters that can be specified in the config file. Each line in the config file should be of the form:
.br
parameter "value"
.TP
.B port <port>
This specifies the port that MPD listens on. This parameter is required. This is typically 2100.
.TP
.B music_directory <directory>
This specifies the directory where music is located. This paramter is required. The directory path should be an absolute path.
.TP
.B playlist_directory <directory>
This specifies the directory where saved playlists are stored. This paramter is required. The directory path should be an absolute path.
.TP
.B log_file <file>
This specifies where the log file should be located. This paramter is required. The file path should be an absolute path.
.TP
.B error_file <file>
This specifies where the error file should be located. This paramter is required. The file path should be an absolute path.
.TP
.B connection_timeout <seconds>
If a client does not send any new data in this time period, the connection is closed. The default is 60 seconds.
.TP
.B max_connections <int>
This specifies the maximum number of clients that can be connected to MPD. The default is 5 connections.
.TP
.B mixer_device <mixer dev>
This specifies which mixer to use. The default is /dev/mixer.
.TP
.B max_playlist_length <int>
This specifies the maximum number of songs that can be in the playlist. The default is 4096 songs.
.TP
.B buffer_before play <0-100%>
This specifies the amount of buffer that will be filled before a song begins playing. The default is 25%.
.TP
.B stop_on_error <yes or no>
This specifies wether playback should stop or goto the next song when an error occurs. The default is no.
.TP
.B max_command_list_size <size in kB>
This specifies the maximum size a command list can be (in kilobytes). The default is 2048 kilobytes.
.TP
.B max_output_buffer_size <size in kB>
This specifies the maximum size of the output buffer to a client (in kilobytes).
The default is 2048 kilobytes.
.TP
.B ao_driver <ao plugin>
This specifies the ao plugin to use for audio output. Typical values for
linux include "oss" and "alsa09". The default value is "default".
.TP
.B ao_driver_options <ao plugin options>
This specifies the options to use for the selected ao_driver. For oss, the
only option available is "dsp". For alsa09, the available options are:
"dev", "buf_size", and "periods". Options are assigned using "=" and ";" is
used to seperate options. An example for oss: "dsp=/dev/dsp". An example for
alsa09: "dev=hw:0,0;buf_size=4096". The default value is "".
.TP
.B save_absolute_paths_in_playlists <yes or no>
This specifies whether relative or absolute paths for song filenames are
used when saving playlists. The default value is "no".
.TP
.B bind_to_address <ip address or hostname or any>
This specifies which address mpd binds to and listens on. The default is "any",
which binds to all available addresses.
.SH FILES
A file is created in the playlist directory called ".mpddb". This file is used to store information about songs located in the music directory.
#include "myfprintf.h"
#include "interface.h"
#include <stdarg.h>
#include <sys/param.h>
#include <unistd.h>
#include <sys/select.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define BUFFER_LENGTH MAXPATHLEN+1024
void myfprintf(FILE * fp, char * format, ... ) {
va_list arglist;
va_start(arglist,format);
if(fcntl(fileno(fp),F_GETFL) & O_NONBLOCK) {
char buffer[BUFFER_LENGTH+1];
vsnprintf(buffer,BUFFER_LENGTH,format,arglist);
interfacePrintWithFD(fileno(fp),buffer);
}
else {
vfprintf(fp,format,arglist);
}
va_end(arglist);
}
#ifndef MYFPRINTF_H
#define MYFPRINTF_H
#include <stdio.h>
void myfprintf(FILE * fp, char * format, ... );
#endif
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_OGG
#include "ogg_decode.h"
#include "player.h"
#include "command.h"
#include "utils.h"
#include "audio.h"
#include "buffer.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <vorbis/vorbisfile.h>
#include <time.h>
#include <ao/ao.h>
#define TIME_TELL_INTERVAL 0.2
#define CHECK_INPUT_FREQ 300 /* about once very 0.1 seconds */
#define INPUT_BUFFER_SIZE 80
int ogg_decode_pid = 0;
int ogg_decode_done = 0;
ao_device * ogg_device = NULL;
void ogg_decode_parentSigHandler(int sig) {
if(sig==SIGCHLD) {
if(ogg_decode_pid==wait3(NULL,WNOHANG,NULL)) {
ogg_decode_pid = 0;
ogg_decode_done = 1;
}
}
else if(sig==SIGTERM) {
int pid = ogg_decode_pid;
if(pid>0) kill(pid,SIGTERM);
if(ogg_device) ao_close(ogg_device);
exit(0);
}
}
/* ogg_decode w/ buffering
* this will fork another process
* child process does decoding
* parent process does buffering && playing audio
*/
int ogg_decode(char * file, FILE * in, FILE * out) {
OggVorbis_File vf;
ao_sample_format format;
float time_total;
FILE * oggfp;
Buffer * cb;
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if(!(oggfp = fopen(file,"r")) || ov_open(oggfp, &vf, NULL, 0) < 0) {
fprintf(stderr,"%s Input does not appear to be an Ogg bitstream.\n",PLAYER_ERROR);
fflush(stderr);
return PLAYER_EXIT_ERROR_FILE;
}
{
vorbis_info *vi=ov_info(&vf,-1);
format.bits = 16;
format.channels = vi->channels;
format.rate = vi->rate;
format.byte_format = AO_FMT_LITTLE;
}
time_total = ov_time_total(&vf,-1);
cb = getBuffer();
cb->begin = 0;
cb->end = 0;
cb->wrap = 0;
cb->finished = 0;
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE,&sa,NULL);
sa.sa_handler = ogg_decode_parentSigHandler;
sigaction(SIGCHLD,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
fflush(NULL);
ogg_decode_pid = fork();
if(ogg_decode_pid==0) {
/* CHILD */
int current_section;
int eof = 0;
struct timeval tv;
long ret;
tv.tv_sec = 0;
tv.tv_usec = 0;
fclose(in);
fclose(out);
while(!eof) {
if(cb->begin!=cb->end || !cb->wrap) {
ret = ov_read(&vf,cb->chunks[cb->end],CHUNK_SIZE,0,2,1,&current_section);
cb->times[cb->end] = ov_time_tell(&vf);
if(ret==0) eof = 1;
cb->end++;
if(cb->end>=BUFFERED_CHUNKS) {
cb->end = 0;
cb->wrap = 1;
}
}
else usleep(100);
}
ov_clear(&vf);
cb->finished = 1;
exit(0);
/* END OF CHILD */
}
else if(ogg_decode_pid<0) {
fprintf(stderr,"%s ogg_decode Problems fork'ing\n",COMMAND_RESPOND_ERROR);
return PLAYER_EXIT_ERROR_SYSTEM;
}
{
/* PARENT */
float elapsed = 0;
float last_tell = 0;
int pause = 0;
char input[INPUT_BUFFER_SIZE+1];
int playsPerChunk = CHUNK_SIZE/PLAY_SIZE;
int currentPlayChunk = 0;
int quit = 0;
fd_set fds;
struct timeval tv;
int checkInput = 0;
int pid;
tv.tv_sec = 0;
tv.tv_usec = 0;
ov_clear(&vf);
initAudio();
ogg_device = ao_open_live(audio_ao_driver_id,&format,
audio_ao_options);
if(ogg_device == NULL) {
audioError();
pid = ogg_decode_pid;
if(pid>0) kill(pid,SIGTERM);
return PLAYER_EXIT_ERROR_AUDIO;
}
fprintf(out,"%s\n",PLAYER_START);
fprintf(out,"%s %f %f\n",PLAYER_TIME,last_tell,time_total);
fflush(out);
while(ogg_decode_pid>0 && !cb->wrap && cb->end-cb->begin<buffered_before_play && !cb->finished) {
usleep(1000);
}
while(!quit) {
if(pause || checkInput%CHECK_INPUT_FREQ==0) {
FD_ZERO(&fds);
FD_SET(fileno(in),&fds);
fflush(in);
if(select(fileno(in)+1,&fds,NULL,NULL,&tv)) {
myFgets(input,INPUT_BUFFER_SIZE,in);
if(strcasecmp(PLAYER_PAUSE,input)==0) {
fprintf(out,"%s\n",PLAYER_PAUSE_GOT);
fflush(out);
pause = !pause;
}
}
checkInput = 1;
}
checkInput++;
if(pause) usleep(100);
else if(cb->begin!=cb->end || cb->wrap) {
if(currentPlayChunk==0) elapsed = cb->times[cb->begin];
ao_play(ogg_device,cb->chunks[cb->begin]+currentPlayChunk*PLAY_SIZE,PLAY_SIZE);
currentPlayChunk++;
if(currentPlayChunk>=playsPerChunk) {
currentPlayChunk=0;
cb->begin++;
if(cb->begin>=BUFFERED_CHUNKS) {
cb->begin = 0;
cb->wrap = 0;
}
}
if(elapsed-last_tell>=TIME_TELL_INTERVAL) {
last_tell = elapsed;
fprintf(out,"%s %f %f\n",PLAYER_TIME,last_tell,time_total);
fflush(out);
}
}
else if(ogg_decode_pid<=0 || cb->finished) {
quit = 1;
}
else usleep(200);
}
pid = ogg_decode_pid;
if(pid>0) kill(pid,SIGTERM);
ao_close(ogg_device);
finishAudio();
/* END OF PARENT */
}
return 0;
}
#endif
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "player.h"
#ifdef HAVE_MAD
#include "mp3_decode.h"
#endif
#ifdef HAVE_OGG
#include "ogg_decode.h"
#endif
#ifdef HAVE_OGG
#include "flac_decode.h"
#endif
#include "command.h"
#include "interface.h"
#include "playlist.h"
#include "ls.h"
#include "listen.h"
#include "path.h"
#include "myfprintf.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#define PLAYER_TYPE_MP3 0
#define PLAYER_TYPE_OGG 1
#define PLAYER_TYPE_FLAC 2
#define MAX_BUFFER_LENGTH 1024
int player_pid = 0;
int player_state = PLAYER_STATE_STOP;
int player_elapsedTime = 0;
int player_totalTime = 0;
int player_send = -1;
int player_recv = -1;
int player_leavePause = 1;
int player_leavePlay = 1;
char player_buffer[MAX_BUFFER_LENGTH+1];
int player_bufferLength = 0;
char player_currentSong[MAXPATHLEN+2] = "\0";
char player_error[2*MAXPATHLEN] = "\0";
void playerReset() {
player_pid = 0;
close(player_recv);
close(player_send);
player_leavePause = 1;
player_leavePlay = 1;
player_state = PLAYER_STATE_STOP;
player_currentSong[0] = '\0';
player_bufferLength = 0;
}
void player_sigHandler(int signal) {
if(signal==SIGCHLD) {
int status;
if(player_pid==wait3(&status,WNOHANG,NULL)) {
if(WEXITSTATUS(status)==PLAYER_EXIT_ERROR_FILE) {
strcpy(player_error,"problem with file: ");
strcat(player_error,player_currentSong);
}
else if(WEXITSTATUS(status)==PLAYER_EXIT_ERROR_AUDIO) {
strcpy(player_error,"problem opening audio device");
}
else if(WEXITSTATUS(status)==PLAYER_EXIT_ERROR_SYSTEM) {
strcpy(player_error,"system error while playing: ");
strcat(player_error,player_currentSong);
}
else if(WEXITSTATUS(status)) {
strcpy(player_error,"unkown error while playing: ");
strcat(player_error,player_currentSong);
}
playerReset();
}
}
}
int playerInit(char * file, int playerType) {
int fd_send[2], fd_recv[2];
player_elapsedTime = 0;
if(socketpair(AF_UNIX,SOCK_STREAM,0,fd_send)<0) {
fprintf(stderr,"%s player Problems socketpair'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,fd_recv)<0) {
fprintf(stderr,"%s player Problems socketpair()'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
fflush(NULL);
player_pid = fork();
fcntl(player_recv,F_SETOWN,(int)getpid());
fcntl(player_recv,F_SETFL,fcntl(player_recv,F_GETFL) | O_ASYNC);
if(player_pid==0) {
FILE * in;
FILE * out;
int ret = 0;
close(listenSocket);
freeAllInterfaces();
close(fd_send[0]);
close(fd_recv[0]);
in = fdopen(fd_send[1],"r");
out = fdopen(fd_recv[1],"w");
#ifdef HAVE_MAD
if(playerType==PLAYER_TYPE_MP3 && (ret=mp3_decode(rmp2amp(file),in,out))!=0) {
fclose(in);
fclose(out);
exit(ret);
}
#endif
#ifdef HAVE_OGG
if(playerType==PLAYER_TYPE_OGG && (ret=ogg_decode(rmp2amp(file),in,out))!=0) {
fclose(in);
fclose(out);
exit(ret);
}
#endif
#ifdef HAVE_FLAC
if(playerType==PLAYER_TYPE_FLAC && (ret=flac_decode(rmp2amp(file),in,out)!=0)) {
fclose(in);
fclose(out);
exit(ret);
}
#endif
fclose(in);
fclose(out);
exit(0);
}
else if(player_pid<0) {
fprintf(stderr,"%s player Problems fork()'ing\n",COMMAND_RESPOND_ERROR);
player_pid = 0;
player_leavePlay = 1;
close(fd_send[0]);
close(fd_send[1]);
close(fd_recv[0]);
close(fd_recv[1]);
return -1;
}
close(fd_send[1]);
close(fd_recv[1]);
player_send = fd_send[0];
player_recv = fd_recv[0];
return 0;
}
int playerPlay(FILE * fp, char * file) {
int playerType;
if(fp==NULL) fp=stderr;
if(0);
#ifdef HAVE_MAD
else if(isMp3(file)) playerType = PLAYER_TYPE_MP3;
#endif
#ifdef HAVE_OGG
else if(isOgg(file)) playerType = PLAYER_TYPE_OGG;
#endif
#ifdef HAVE_FLAC
else if(isFlac(file)) playerType = PLAYER_TYPE_FLAC;
#endif
else {
snprintf(player_error,sizeof(player_error),"\"%s\" is not a file or unknown file type",file);
return 0;
}
if(playerStop(fp)<0) return -1;
player_state = PLAYER_STATE_PLAY;
player_currentSong[0] = '\0';
strcpy(player_currentSong,file);
player_leavePlay = 0;
if(playerInit(file,playerType)<0) {
myfprintf(fp,"%s problems init'ing player\n",COMMAND_RESPOND_ERROR);
return -1;
}
while(player_pid>0) {
playerProcessMessages();
if(player_leavePlay) break;
usleep(1);
}
return 0;
}
int playerStop(FILE * fp) {
int pid = player_pid;
if(pid>0) {
kill(pid,SIGTERM);
while(player_pid>0) usleep(1);
}
player_state = PLAYER_STATE_STOP;
return 0;
}
int playerPause(FILE * fp) {
char string[1024];
if(player_pid>0) {
player_leavePause = 0;
sprintf(string,"%s\n",PLAYER_PAUSE);
if(write(player_send,string,strlen(string))<0) {
myfprintf(fp,"%s problems write'ing\n",COMMAND_RESPOND_ERROR);
}
if(player_state==PLAYER_STATE_PLAY) {
player_state = PLAYER_STATE_PAUSE;
}
else if(player_state==PLAYER_STATE_PAUSE) {
player_state = PLAYER_STATE_PLAY;
}
while(!player_leavePause) {
playerProcessMessages();
usleep(1);
}
}
return 0;
}
int playerReadline() {
fd_set fdsr;
struct timeval tv;
FD_ZERO(&fdsr);
FD_SET(player_recv,&fdsr);
tv.tv_sec = tv.tv_usec = 0;
if(select(player_recv+1,&fdsr,NULL,NULL,&tv)==1) {
int rc;
while(1) {
rc = read(player_recv,player_buffer+player_bufferLength,1);
if(rc<=0) return 0;
player_buffer[player_bufferLength+1] = '\0';
if(player_buffer[player_bufferLength]=='\0' || player_buffer[player_bufferLength]=='\n' || player_bufferLength == MAX_BUFFER_LENGTH) {
player_buffer[player_bufferLength] = '\0';
player_bufferLength = 0;
return -1;
}
player_bufferLength++;
}
}
return 0;
}
void playerProcessMessages() {
if(player_pid>0) {
while(playerReadline()) {
char * c[4];
c[0] = strtok(player_buffer," ");
if(c[0]) {
if(0==strcmp(c[0],PLAYER_TIME)) {
c[1] = strtok(NULL," ");
c[2] = strtok(NULL," ");
player_totalTime = atof(c[2])+0.5;
player_elapsedTime = atof(c[1])+0.5;
player_leavePlay = 1;
}
else if(0==strcmp(c[0],PLAYER_ERROR)) {
myfprintf(stderr,"player error: file \"%s\" : %s\n",player_currentSong,c[1]);
player_leavePlay = 1;
}
else if(0==strcmp(c[0],PLAYER_PAUSE_GOT)) {
player_leavePause = 1;
}
}
}
}
}
int getPlayerElapsedTime() {
return player_elapsedTime;
}
int getPlayerTotalTime() {
return player_totalTime;
}
int getPlayerState() {
return player_state;
}
void clearPlayerError() {
player_error[0] = '\0';
}
char * getPlayerError() {
return player_error;
}
#include "sig_handlers.h"
#include "player.h"
#include <signal.h>
void initSigHandlers() {
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE,&sa,NULL);
sigaction(SIGIO,&sa,NULL);
sa.sa_handler = player_sigHandler;
sigaction(SIGCHLD,&sa,NULL);
}
#ifndef SIG_HANDLERS_H
#define SIG_HANDLERS_H
void initSigHandlers();
#endif
bin_PROGRAMS = mpd
SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR)
mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
song.h list.h directory.h tables.h utils.h path.h mp3_decode.h \
tag.h player.h listen.h conf.h ogg_decode.h volume.h flac_decode.h \
audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h
mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
song.c list.c directory.c tables.c utils.c path.c mp3_decode.c \
tag.c player.c listen.c conf.c ogg_decode.c volume.c flac_decode.c \
audio.c playerData.c stats.c myfprintf.c sig_handlers.c decode.c log.c \
$(mpd_headers)
CFLAGS = @CFLAGS@ $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB)
This diff is collapsed. Click to expand it.
...@@ -18,12 +18,19 @@ ...@@ -18,12 +18,19 @@
#include "audio.h" #include "audio.h"
#include "conf.h" #include "conf.h"
#include "log.h"
#include "sig_handlers.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <signal.h>
int audio_ao_driver_id; int audio_ao_driver_id;
ao_option * audio_ao_options; ao_option * audio_ao_options;
AudioFormat audio_format;
ao_device * audio_device = NULL;
void initAudioDriver() { void initAudioDriver() {
ao_info * ai; ao_info * ai;
char * dup; char * dup;
...@@ -43,13 +50,13 @@ void initAudioDriver() { ...@@ -43,13 +50,13 @@ void initAudioDriver() {
} }
else if((audio_ao_driver_id = else if((audio_ao_driver_id =
ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) { ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) {
fprintf(stderr,"\"%s\" is not a valid ao driver\n", ERROR1("\"%s\" is not a valid ao driver\n",
(getConf())[CONF_AO_DRIVER]); (getConf())[CONF_AO_DRIVER]);
exit(-1); exit(-1);
} }
if((ai = ao_driver_info(audio_ao_driver_id))==NULL) { if((ai = ao_driver_info(audio_ao_driver_id))==NULL) {
fprintf(stderr,"problems getting ao_driver_info\n"); ERROR0("problems getting ao_driver_info\n");
exit(-1); exit(-1);
} }
...@@ -61,27 +68,26 @@ void initAudioDriver() { ...@@ -61,27 +68,26 @@ void initAudioDriver() {
stk2 = NULL; stk2 = NULL;
key = strtok_r(n1,"=",&stk2); key = strtok_r(n1,"=",&stk2);
if(!key) { if(!key) {
fprintf(stderr,"problems parsing " ERROR1("problems parsing "
"ao_driver_options \"%s\"\n", n1); "ao_driver_options \"%s\"\n", n1);
exit(-1); exit(-1);
} }
/*found = 0; /*found = 0;
for(i=0;i<ai->option_count;i++) { for(i=0;i<ai->option_count;i++) {
printf("option: %s\n",ai->options[i]);
if(strcmp(ai->options[i],key)==0) { if(strcmp(ai->options[i],key)==0) {
found = 1; found = 1;
break; break;
} }
} }
if(!found) { if(!found) {
fprintf(stderr,"\"%s\" is not an option for " ERROR2("\"%s\" is not an option for "
"\"%s\" ao driver\n",key, "\"%s\" ao driver\n",key,
ai->short_name); ai->short_name);
exit(-1); exit(-1);
}*/ }*/
value = strtok_r(NULL,"",&stk2); value = strtok_r(NULL,"",&stk2);
if(!value) { if(!value) {
fprintf(stderr,"problems parsing " ERROR1("problems parsing "
"ao_driver_options \"%s\"\n", n1); "ao_driver_options \"%s\"\n", n1);
exit(-1); exit(-1);
} }
...@@ -90,33 +96,75 @@ void initAudioDriver() { ...@@ -90,33 +96,75 @@ void initAudioDriver() {
} }
} }
free(dup); free(dup);
ao_shutdown();
} }
void finishAudioDriver() { void finishAudioDriver() {
ao_free_options(audio_ao_options); ao_free_options(audio_ao_options);
ao_shutdown();
} }
void initAudio() { int initAudio(AudioFormat * audioFormat) {
ao_initialize(); ao_sample_format format;
if(audio_device) {
if(audio_format.bits!=audioFormat->bits ||
audio_format.sampleRate!=audioFormat->sampleRate ||
audio_format.channels!=audioFormat->channels) {
finishAudio();
}
}
if(!audio_device) {
format.bits = audioFormat->bits;
format.rate = audioFormat->sampleRate;
format.byte_format = AO_FMT_LITTLE;
format.channels = audioFormat->channels;
audio_format.bits = format.bits;
audio_format.sampleRate = format.rate;
audio_format.channels = format.channels;
blockSignals();
audio_device = ao_open_live(audio_ao_driver_id, &format,
audio_ao_options);
if(audio_device==NULL) {
unblockSignals();
audioError();
return -1;
}
unblockSignals();
}
return 0;
}
void playAudio(char * playChunk, int size) {
assert(audio_device!=NULL);
ao_play(audio_device,playChunk,size);
} }
void finishAudio() { void finishAudio() {
ao_shutdown(); if(audio_device) {
blockSignals();
ao_close(audio_device);
audio_device = NULL;
unblockSignals();
}
} }
void audioError() { void audioError() {
fprintf(stderr,"Error opening audio device\n"); ERROR0("Error opening audio device\n");
if(errno==AO_ENOTLIVE) { if(errno==AO_ENOTLIVE) {
fprintf(stderr,"not a live ao device\n"); ERROR0("not a live ao device\n");
} }
else if(errno==AO_EOPENDEVICE) { else if(errno==AO_EOPENDEVICE) {
fprintf(stderr,"not able to open audio device\n"); ERROR0("not able to open audio device\n");
} }
else if(errno==AO_EBADOPTION) { else if(errno==AO_EBADOPTION) {
fprintf(stderr,"bad driver option\n"); ERROR0("bad driver option\n");
} }
perror("ao error");
fflush(stderr);
} }
...@@ -19,11 +19,17 @@ ...@@ -19,11 +19,17 @@
#ifndef AUDIO_H #ifndef AUDIO_H
#define AUDIO_H #define AUDIO_H
#define AUDIO_AO_DRIVER_DEFAULT "default"
#include <stdio.h> #include <stdio.h>
#include <ao/ao.h> #include <ao/ao.h>
#define AUDIO_AO_DRIVER_DEFAULT "default"
typedef struct _AudioFormat {
int channels;
int sampleRate;
int bits;
} AudioFormat;
extern int audio_ao_driver_id; extern int audio_ao_driver_id;
extern ao_option * audio_ao_options; extern ao_option * audio_ao_options;
...@@ -31,7 +37,9 @@ void initAudioDriver(); ...@@ -31,7 +37,9 @@ void initAudioDriver();
void finishAudioDriver(); void finishAudioDriver();
void initAudio(); int initAudio(AudioFormat * audioFormat);
void playAudio(char * playChunk,int size);
void finishAudio(); void finishAudio();
......
...@@ -56,20 +56,24 @@ ...@@ -56,20 +56,24 @@
#define COMMAND_LISTALL "listall" #define COMMAND_LISTALL "listall"
#define COMMAND_VOLUME "volume" #define COMMAND_VOLUME "volume"
#define COMMAND_REPEAT "repeat" #define COMMAND_REPEAT "repeat"
#define COMMAND_RANDOM "random"
#define COMMAND_STATS "stats" #define COMMAND_STATS "stats"
#define COMMAND_CLEAR_ERROR "clearerror" #define COMMAND_CLEAR_ERROR "clearerror"
#define COMMAND_LIST "list" #define COMMAND_LIST "list"
#define COMMAND_MOVE "move"
#define COMMAND_SWAP "swap"
#define COMMAND_SEEK "seek"
#define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_STATE "state"
#define COMMAND_STATUS_REPEAT "repeat" #define COMMAND_STATUS_REPEAT "repeat"
#define COMMAND_STATUS_RANDOM "random"
#define COMMAND_STATUS_PLAYLIST "playlist" #define COMMAND_STATUS_PLAYLIST "playlist"
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
#define COMMAND_STATUS_SONG "song" #define COMMAND_STATUS_SONG "song"
#define COMMAND_STATUS_TIME "time" #define COMMAND_STATUS_TIME "time"
#define COMMAND_STATUS_ERROR "error" #define COMMAND_STATUS_ERROR "error"
extern Playlist playlist;
int commandStatus(FILE * fp,int argArrayLength, char ** argArray) { int commandStatus(FILE * fp,int argArrayLength, char ** argArray) {
char * state = NULL; char * state = NULL;
if(argArrayLength!=1) { if(argArrayLength!=1) {
...@@ -77,6 +81,7 @@ int commandStatus(FILE * fp,int argArrayLength, char ** argArray) { ...@@ -77,6 +81,7 @@ int commandStatus(FILE * fp,int argArrayLength, char ** argArray) {
return -1; return -1;
} }
playPlaylistIfPlayerStopped();
switch(getPlayerState()) { switch(getPlayerState()) {
case PLAYER_STATE_STOP: case PLAYER_STATE_STOP:
state = strdup(COMMAND_STOP); state = strdup(COMMAND_STOP);
...@@ -91,16 +96,18 @@ int commandStatus(FILE * fp,int argArrayLength, char ** argArray) { ...@@ -91,16 +96,18 @@ int commandStatus(FILE * fp,int argArrayLength, char ** argArray) {
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_VOLUME,getVolumeLevel()); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_VOLUME,getVolumeLevel());
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_REPEAT,getPlaylistRepeatStatus()); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_REPEAT,getPlaylistRepeatStatus());
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_PLAYLIST,playlist.version); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_RANDOM,getPlaylistRandomStatus());
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_PLAYLIST,getPlaylistVersion());
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_PLAYLIST_LENGTH,getPlaylistLength());
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_STATE,state); myfprintf(fp,"%s: %s\n",COMMAND_STATUS_STATE,state);
if(getPlayerState()>0) { if(getPlayerState()!=PLAYER_STATE_STOP) {
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_SONG,playlist.current); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_SONG,getPlaylistCurrentSong());
myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime()); myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime());
} }
if(strlen(getPlayerError())) { if(getPlayerError()!=PLAYER_ERROR_NOERROR) {
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_ERROR,getPlayerError()); myfprintf(fp,"%s: %s\n",COMMAND_STATUS_ERROR,getPlayerErrorStr());
} }
free(state); free(state);
...@@ -114,7 +121,7 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -114,7 +121,7 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
} }
if(0==strcmp(argArray[0],COMMAND_PLAY)) { if(0==strcmp(argArray[0],COMMAND_PLAY)) {
int song = 0; int song = -1;
char * test; char * test;
if(argArrayLength>2) { if(argArrayLength>2) {
myfprintf(fp,"%s too many arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); myfprintf(fp,"%s too many arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
...@@ -127,7 +134,7 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -127,7 +134,7 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
return -1; return -1;
} }
} }
return playPlaylist(fp,song); return playPlaylist(fp,song,1);
} }
else if(0==strcmp(argArray[0],COMMAND_STOP)) { else if(0==strcmp(argArray[0],COMMAND_STOP)) {
if(argArrayLength!=1) { if(argArrayLength!=1) {
...@@ -160,42 +167,18 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -160,42 +167,18 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
return addToPlaylist(fp,argArray[1]); return addToPlaylist(fp,argArray[1]);
} }
else if(0==strcmp(argArray[0],COMMAND_SAVE)) { else if(0==strcmp(argArray[0],COMMAND_SAVE)) {
char * file;
int ret;
if(argArrayLength!=2) { if(argArrayLength!=2) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1; return -1;
} }
if(strstr(argArray[1],"/")) { return savePlaylist(fp,argArray[1]);
myfprintf(fp,"%s \"%s\" contains \"/\"\n",COMMAND_RESPOND_ERROR,argArray[1]);
return -1;
}
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
ret = savePlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX));
free(file);
return ret;
} }
else if(0==strcmp(argArray[0],COMMAND_RM)) { else if(0==strcmp(argArray[0],COMMAND_RM)) {
char * file;
int ret;
if(argArrayLength!=2) { if(argArrayLength!=2) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1; return -1;
} }
if(strstr(argArray[1],"/")) { return deletePlaylist(fp,argArray[1]);
myfprintf(fp,"%s \"%s\" contains \"/\"\n",COMMAND_RESPOND_ERROR,argArray[1]);
return -1;
}
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
ret = deletePlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX));
free(file);
return ret;
} }
else if(0==strcmp(argArray[0],COMMAND_DELETE)) { else if(0==strcmp(argArray[0],COMMAND_DELETE)) {
int song; int song;
...@@ -211,6 +194,72 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -211,6 +194,72 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
} }
return deleteFromPlaylist(fp,song); return deleteFromPlaylist(fp,song);
} }
else if(0==strcmp(argArray[0],COMMAND_MOVE)) {
int from;
int to;
char * test;
if(argArrayLength!=3) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
from = strtol(argArray[1],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[1]);
return -1;
}
to = strtol(argArray[2],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[2]);
return -1;
}
return moveSongInPlaylist(fp,from,to);
}
else if(0==strcmp(argArray[0],COMMAND_SWAP)) {
int song1;
int song2;
char * test;
if(argArrayLength!=3) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
song1 = strtol(argArray[1],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[1]);
return -1;
}
song2 = strtol(argArray[2],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[2]);
return -1;
}
return swapSongsInPlaylist(fp,song1,song2);
}
else if(0==strcmp(argArray[0],COMMAND_SEEK)) {
int song;
int time;
char * test;
if(argArrayLength!=3) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
song = strtol(argArray[1],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[1]);
return -1;
}
time = strtol(argArray[2],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s \"%s\" is not a integer\n",
COMMAND_RESPOND_ERROR,argArray[2]);
return -1;
}
return seekSongInPlaylist(fp,song,time);
}
else if(0==strcmp(argArray[0],COMMAND_VOLUME)) { else if(0==strcmp(argArray[0],COMMAND_VOLUME)) {
int change; int change;
char * test; char * test;
...@@ -239,6 +288,20 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -239,6 +288,20 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
} }
return setPlaylistRepeatStatus(fp,status); return setPlaylistRepeatStatus(fp,status);
} }
else if(0==strcmp(argArray[0],COMMAND_RANDOM)) {
int status;
char * test;
if(argArrayLength!=2) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
status = strtol(argArray[1],&test,10);
if(*test!='\0') {
myfprintf(fp,"%s need a integer\n",COMMAND_RESPOND_ERROR);
return -1;
}
return setPlaylistRandomStatus(fp,status);
}
else if(0==strcmp(argArray[0],COMMAND_PLAYLISTINFO)) { else if(0==strcmp(argArray[0],COMMAND_PLAYLISTINFO)) {
int song = -1; int song = -1;
char * test; char * test;
...@@ -277,19 +340,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -277,19 +340,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
return clearPlaylist(fp); return clearPlaylist(fp);
} }
else if(0==strcmp(argArray[0],COMMAND_LOAD)) { else if(0==strcmp(argArray[0],COMMAND_LOAD)) {
char * file;
int ret = 0;
if(argArrayLength!=2) { if(argArrayLength!=2) {
myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); myfprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1; return -1;
} }
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2); return loadPlaylist(fp,argArray[1]);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
if(loadPlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX))<0) ret=-1;
free(file);
return ret;
} }
else if(0==strcmp(argArray[0],COMMAND_LS)) { else if(0==strcmp(argArray[0],COMMAND_LS)) {
if(argArrayLength>2) { if(argArrayLength>2) {
...@@ -298,10 +353,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -298,10 +353,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
} }
if(argArrayLength==1) { if(argArrayLength==1) {
if(ls(fp,NULL)<0) return -1; if(ls(fp,NULL)<0) return -1;
else return lsPlaylists(fp); else return lsPlaylists(fp,"");
} }
else { else {
return ls(fp,argArray[1]); if(ls(fp,argArray[1])<0) return -1;
else return lsPlaylists(fp,argArray[1]);
} }
} }
else if(0==strcmp(argArray[0],COMMAND_LSINFO)) { else if(0==strcmp(argArray[0],COMMAND_LSINFO)) {
...@@ -311,10 +367,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) { ...@@ -311,10 +367,11 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
} }
if(argArrayLength==1) { if(argArrayLength==1) {
if(printDirectoryInfo(fp,NULL)<0) return -1; if(printDirectoryInfo(fp,NULL)<0) return -1;
else return lsPlaylists(fp); else return lsPlaylists(fp,"");
} }
else { else {
return printDirectoryInfo(fp,argArray[1]); if(printDirectoryInfo(fp,argArray[1])<0) return -1;
else return lsPlaylists(fp,argArray[1]);
} }
} }
else if(0==strcmp(argArray[0],COMMAND_FIND)) { else if(0==strcmp(argArray[0],COMMAND_FIND)) {
......
...@@ -18,9 +18,12 @@ ...@@ -18,9 +18,12 @@
#include "conf.h" #include "conf.h"
#include "log.h"
#include "utils.h" #include "utils.h"
#include "buffer2array.h" #include "buffer2array.h"
#include "audio.h" #include "audio.h"
#include "volume.h"
#include <sys/param.h> #include <sys/param.h>
#include <stdio.h> #include <stdio.h>
...@@ -31,22 +34,35 @@ ...@@ -31,22 +34,35 @@
#define CONF_COMMENT '#' #define CONF_COMMENT '#'
#define CONF_NUMBER_OF_PARAMS 17 #define CONF_NUMBER_OF_PARAMS 21
#define CONF_NUMBER_OF_PATHS 4 #define CONF_NUMBER_OF_PATHS 6
#define CONF_NUMBER_OF_REQUIRED 5 #define CONF_NUMBER_OF_REQUIRED 5
#define CONF_CONNECTION_TIMEOUT_DEFAULT "60" #define CONF_CONNECTION_TIMEOUT_DEFAULT "60"
#define CONF_MIXER_DEVICE_DEFAULT "/dev/mixer"
#define CONF_MAX_CONNECTIONS_DEFAULT "5" #define CONF_MAX_CONNECTIONS_DEFAULT "5"
#define CONF_MAX_PLAYLIST_LENGTH_DEFAULT "4096" #define CONF_MAX_PLAYLIST_LENGTH_DEFAULT "4096"
#define CONF_BUFFER_BEFORE_PLAY_DEFAULT "25%" #define CONF_BUFFER_BEFORE_PLAY_DEFAULT "25%"
#define CONF_STOP_ON_ERROR_DEFAULT "yes"
#define CONF_MAX_COMMAND_LIST_SIZE_DEFAULT "2048" #define CONF_MAX_COMMAND_LIST_SIZE_DEFAULT "2048"
#define CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT "2048" #define CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT "2048"
#define CONF_AO_DRIVER_DEFAULT AUDIO_AO_DRIVER_DEFAULT #define CONF_AO_DRIVER_DEFAULT AUDIO_AO_DRIVER_DEFAULT
#define CONF_AO_DRIVER_OPTIONS_DEFAULT "" #define CONF_AO_DRIVER_OPTIONS_DEFAULT ""
#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT "no" #define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT "no"
#define CONF_BIND_TO_ADDRESS_DEFAULT "any" #define CONF_BIND_TO_ADDRESS_DEFAULT "any"
#define CONF_USER_DEFAULT ""
#define CONF_LOG_LEVEL_DEFAULT "default"
#ifndef NO_OSS_MIXER
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_OSS
#define CONF_MIXER_DEVICE_DEFAULT ""
#else
#ifdef HAVE_ALSA
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_ALSA
#define CONF_MIXER_DEVICE_DEFAULT ""
#else
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_NULL
#define CONF_MIXER_DEVICE_DEFAULT ""
#endif
#endif
char * conf_strings[CONF_NUMBER_OF_PARAMS] = { char * conf_strings[CONF_NUMBER_OF_PARAMS] = {
"port", "port",
...@@ -59,20 +75,26 @@ char * conf_strings[CONF_NUMBER_OF_PARAMS] = { ...@@ -59,20 +75,26 @@ char * conf_strings[CONF_NUMBER_OF_PARAMS] = {
"max_connections", "max_connections",
"max_playlist_length", "max_playlist_length",
"buffer_before_play", "buffer_before_play",
"stop_on_error",
"max_command_list_size", "max_command_list_size",
"max_output_buffer_size", "max_output_buffer_size",
"ao_driver", "ao_driver",
"ao_driver_options", "ao_driver_options",
"save_absolute_paths_in_playlists", "save_absolute_paths_in_playlists",
"bind_to_address" "bind_to_address",
"mixer_type",
"state_file",
"user",
"db_file",
"log_level"
}; };
int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = { int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
CONF_MUSIC_DIRECTORY, CONF_MUSIC_DIRECTORY,
CONF_PLAYLIST_DIRECTORY, CONF_PLAYLIST_DIRECTORY,
CONF_LOG_FILE, CONF_LOG_FILE,
CONF_ERROR_FILE CONF_ERROR_FILE,
CONF_STATE_FILE,
CONF_DB_FILE
}; };
int conf_required[CONF_NUMBER_OF_REQUIRED] = { int conf_required[CONF_NUMBER_OF_REQUIRED] = {
...@@ -96,13 +118,15 @@ void initConf() { ...@@ -96,13 +118,15 @@ void initConf() {
conf_params[CONF_MAX_CONNECTIONS] = strdup(CONF_MAX_CONNECTIONS_DEFAULT); conf_params[CONF_MAX_CONNECTIONS] = strdup(CONF_MAX_CONNECTIONS_DEFAULT);
conf_params[CONF_MAX_PLAYLIST_LENGTH] = strdup(CONF_MAX_PLAYLIST_LENGTH_DEFAULT); conf_params[CONF_MAX_PLAYLIST_LENGTH] = strdup(CONF_MAX_PLAYLIST_LENGTH_DEFAULT);
conf_params[CONF_BUFFER_BEFORE_PLAY] = strdup(CONF_BUFFER_BEFORE_PLAY_DEFAULT); conf_params[CONF_BUFFER_BEFORE_PLAY] = strdup(CONF_BUFFER_BEFORE_PLAY_DEFAULT);
conf_params[CONF_STOP_ON_ERROR] = strdup(CONF_STOP_ON_ERROR_DEFAULT);
conf_params[CONF_MAX_COMMAND_LIST_SIZE] = strdup(CONF_MAX_COMMAND_LIST_SIZE_DEFAULT); conf_params[CONF_MAX_COMMAND_LIST_SIZE] = strdup(CONF_MAX_COMMAND_LIST_SIZE_DEFAULT);
conf_params[CONF_MAX_OUTPUT_BUFFER_SIZE] = strdup(CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT); conf_params[CONF_MAX_OUTPUT_BUFFER_SIZE] = strdup(CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT);
conf_params[CONF_AO_DRIVER] = strdup(CONF_AO_DRIVER_DEFAULT); conf_params[CONF_AO_DRIVER] = strdup(CONF_AO_DRIVER_DEFAULT);
conf_params[CONF_AO_DRIVER_OPTIONS] = strdup(CONF_AO_DRIVER_OPTIONS_DEFAULT); conf_params[CONF_AO_DRIVER_OPTIONS] = strdup(CONF_AO_DRIVER_OPTIONS_DEFAULT);
conf_params[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS] = strdup(CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT); conf_params[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS] = strdup(CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT);
conf_params[CONF_BIND_TO_ADDRESS] = strdup(CONF_BIND_TO_ADDRESS_DEFAULT); conf_params[CONF_BIND_TO_ADDRESS] = strdup(CONF_BIND_TO_ADDRESS_DEFAULT);
conf_params[CONF_MIXER_TYPE] = strdup(CONF_MIXER_TYPE_DEFAULT);
conf_params[CONF_USER] = strdup(CONF_USER_DEFAULT);
conf_params[CONF_LOG_LEVEL] = strdup(CONF_LOG_LEVEL_DEFAULT);
} }
char ** readConf(char * file) { char ** readConf(char * file) {
...@@ -113,7 +137,7 @@ char ** readConf(char * file) { ...@@ -113,7 +137,7 @@ char ** readConf(char * file) {
int numberOfArgs; int numberOfArgs;
if(!(fp=fopen(file,"r"))) { if(!(fp=fopen(file,"r"))) {
fprintf(stderr,"problems opening file %s for reading\n",file); ERROR1("problems opening file %s for reading\n",file);
exit(-1); exit(-1);
} }
...@@ -122,13 +146,13 @@ char ** readConf(char * file) { ...@@ -122,13 +146,13 @@ char ** readConf(char * file) {
numberOfArgs = buffer2array(string,&array); numberOfArgs = buffer2array(string,&array);
if(numberOfArgs==0) continue; if(numberOfArgs==0) continue;
if(2!=numberOfArgs) { if(2!=numberOfArgs) {
fprintf(stderr,"need two args in conf at: %s\n",string); ERROR1("need two args in conf at: %s\n",string);
exit(-1); exit(-1);
} }
i = 0; i = 0;
while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++; while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++;
if(i>=CONF_NUMBER_OF_PARAMS) { if(i>=CONF_NUMBER_OF_PARAMS) {
fprintf(stderr,"unrecognized line in conf: %s\n",string); ERROR1("unrecognized line in conf: %s\n",string);
exit(-1); exit(-1);
} }
if(conf_params[i]!=NULL) { if(conf_params[i]!=NULL) {
...@@ -144,14 +168,17 @@ char ** readConf(char * file) { ...@@ -144,14 +168,17 @@ char ** readConf(char * file) {
for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) { for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) {
if(conf_params[conf_required[i]] == NULL) { if(conf_params[conf_required[i]] == NULL) {
fprintf(stderr,"%s is unassinged in conf file\n",conf_strings[conf_required[i]]); ERROR1("%s is unassigned in conf file\n",
conf_strings[conf_required[i]]);
exit(-1); exit(-1);
} }
} }
for(i=0;i<CONF_NUMBER_OF_PATHS;i++) { for(i=0;i<CONF_NUMBER_OF_PATHS;i++) {
if(conf_params[conf_absolutePaths[i]][0]!='/') { if(conf_params[conf_absolutePaths[i]] &&
fprintf(stderr,"\"%s\" is not an absolute path\n",conf_params[conf_absolutePaths[i]]); conf_params[conf_absolutePaths[i]][0]!='/') {
ERROR1("\"%s\" is not an absolute path\n",
conf_params[conf_absolutePaths[i]]);
exit(-1); exit(-1);
} }
} }
...@@ -168,12 +195,12 @@ void writeConf(char * file) { ...@@ -168,12 +195,12 @@ void writeConf(char * file) {
FILE * fp; FILE * fp;
if(!(fp=fopen(file,"w"))) { if(!(fp=fopen(file,"w"))) {
fprintf(stderr, "problems open file %s for writing\n",file); ERROR1("problems open file %s for writing\n",file);
exit(-1); exit(-1);
} }
for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) { for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) {
fprintf(fp,"%s \"%s\"\n",conf_strings[i],conf_params[i]); myfprintf(fp,"%s \"%s\"\n",conf_strings[i],conf_params[i]);
} }
fclose(fp); fclose(fp);
......
...@@ -29,13 +29,17 @@ ...@@ -29,13 +29,17 @@
#define CONF_MAX_CONNECTIONS 7 #define CONF_MAX_CONNECTIONS 7
#define CONF_MAX_PLAYLIST_LENGTH 8 #define CONF_MAX_PLAYLIST_LENGTH 8
#define CONF_BUFFER_BEFORE_PLAY 9 #define CONF_BUFFER_BEFORE_PLAY 9
#define CONF_STOP_ON_ERROR 10 #define CONF_MAX_COMMAND_LIST_SIZE 10
#define CONF_MAX_COMMAND_LIST_SIZE 11 #define CONF_MAX_OUTPUT_BUFFER_SIZE 11
#define CONF_MAX_OUTPUT_BUFFER_SIZE 12 #define CONF_AO_DRIVER 12
#define CONF_AO_DRIVER 13 #define CONF_AO_DRIVER_OPTIONS 13
#define CONF_AO_DRIVER_OPTIONS 14 #define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS 14
#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS 15 #define CONF_BIND_TO_ADDRESS 15
#define CONF_BIND_TO_ADDRESS 16 #define CONF_MIXER_TYPE 16
#define CONF_STATE_FILE 17
#define CONF_USER 18
#define CONF_DB_FILE 19
#define CONF_LOG_LEVEL 20
/* do not free the return value, it is a static variable */ /* do not free the return value, it is a static variable */
char ** readConf(char * file); char ** readConf(char * file);
......
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "decode.h"
#include "player.h"
#include "utils.h"
#include "audio.h"
#ifdef HAVE_MAD
#include "mp3_decode.h"
#endif
#ifdef HAVE_OGG
#include "ogg_decode.h"
#endif
#ifdef HAVE_FLAC
#include "flac_decode.h"
#endif
#include "path.h"
#include "log.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
int decode_pid = 0;
void decodeSigHandler(int sig) {
if(sig==SIGCHLD) {
int status;
if(decode_pid==wait3(&status,WNOHANG,NULL)) {
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR1("decode process died from a "
"non-TERM signal: %i\n",
WTERMSIG(status));
}
decode_pid = 0;
}
}
else if(sig==SIGTERM) {
int pid = decode_pid;
if(pid>0) kill(pid,SIGTERM);
exit(0);
}
}
void stopDecode(DecoderControl * dc) {
if(decode_pid>0 && (dc->start || dc->state==DECODE_STATE_DECODE)) {
dc->stop = 1;
while(decode_pid>0 && dc->stop) usleep(10);
}
}
void quitDecode(PlayerControl * pc, DecoderControl * dc) {
stopDecode(dc);
pc->state = PLAYER_STATE_STOP;
pc->play = 0;
pc->stop = 0;
pc->pause = 0;
kill(getppid(),SIGUSR1);
}
int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
Buffer * cb)
{
while(decode_pid>0 && dc->start) usleep(10);
if(dc->start || dc->error!=DECODE_ERROR_NOERROR) {
strcpy(pc->erroredFile,pc->file);
pc->error = PLAYER_ERROR_FILE;
quitDecode(pc,dc);
return -1;
}
if(initAudio(af)<0) {
strcpy(pc->erroredFile,pc->file);
pc->error = PLAYER_ERROR_AUDIO;
quitDecode(pc,dc);
return -1;
}
pc->elapsedTime = 0;
pc->totalTime = cb->totalTime;
return 0;
}
void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
Buffer * cb)
{
if(decode_pid>0) {
cb->next = -1;
if(dc->state!=DECODE_STATE_DECODE || dc->error ||
strcmp(dc->file,pc->file)!=0)
{
stopDecode(dc);
cb->end = 0;
dc->error = 0;
dc->start = 1;
dc->error = 0;
waitOnDecode(pc,af,dc,cb);
}
if(decode_pid>0 && dc->state==DECODE_STATE_DECODE) {
dc->seekWhere = pc->seekWhere > pc->totalTime-1 ?
pc->totalTime-1 : pc->seekWhere;
dc->seekWhere = 1 > dc->seekWhere ? 1 : dc->seekWhere;
cb->begin = 0;
dc->seek = 1;
pc->elapsedTime = dc->seekWhere;
while(decode_pid>0 && dc->seek) usleep(10);
}
}
pc->seek = 0;
}
#define processDecodeInput() \
if(pc->lockQueue) { \
pc->queueLockState = PLAYER_QUEUE_LOCKED; \
pc->lockQueue = 0; \
} \
if(pc->unlockQueue) { \
pc->queueLockState = PLAYER_QUEUE_UNLOCKED; \
pc->unlockQueue = 0; \
} \
if(pc->pause) { \
pause = !pause; \
if(pause) pc->state = PLAYER_STATE_PAUSE; \
else pc->state = PLAYER_STATE_PLAY; \
pc->pause = 0; \
kill(getppid(),SIGUSR1); \
} \
if(pc->seek) { \
decodeSeek(pc,af,dc,cb); \
bbp = 0; \
} \
if(pc->stop) { \
quitDecode(pc,dc); \
return; \
}
int decoderInit(PlayerControl * pc, Buffer * cb, AudioFormat *af,
DecoderControl * dc) {
decode_pid = fork();
if(decode_pid==0) {
/* CHILD */
while(1) {
if(dc->start) {
strcpy(dc->file,pc->file);
switch(pc->decodeType) {
#ifdef HAVE_MAD
case DECODE_TYPE_MP3:
dc->error = mp3_decode(cb,af,dc);
break;
#endif
#ifdef HAVE_OGG
case DECODE_TYPE_OGG:
dc->error = ogg_decode(cb,af,dc);
break;
#endif
#ifdef HAVE_FLAC
case DECODE_TYPE_FLAC:
dc->error = flac_decode(cb,af,dc);
break;
#endif
default:
dc->error = DECODE_ERROR_UNKTYPE;
}
if(dc->error!=DECODE_ERROR_NOERROR) {
dc->start = 0;
dc->stop = 0;
dc->state = DECODE_STATE_STOP;
}
}
else if(dc->stop) {
dc->state = DECODE_STATE_STOP;
dc->stop = 0;
}
else if(dc->seek) dc->start = 1;
else usleep(10);
}
exit(0);
/* END OF CHILD */
}
else if(decode_pid<0) {
strcpy(pc->erroredFile,pc->file);
pc->error = PLAYER_ERROR_SYSTEM;
return -1;
}
return 0;
}
/* decode w/ buffering
* this will fork another process
* child process does decoding
* parent process does playing audio
*/
void decode() {
Buffer * cb;
PlayerControl * pc;
AudioFormat * af;
DecoderControl * dc;
cb = &(getPlayerData()->buffer);
cb->begin = 0;
cb->end = 0;
cb->wrap = 0;
pc = &(getPlayerData()->playerControl);
dc = &(getPlayerData()->decoderControl);
af = &(getPlayerData()->audioFormat);
dc->error = 0;
dc->start = 1;
cb->next = -1;
if(decode_pid<=0) {
if(decoderInit(pc,cb,af,dc)<0) return;
}
{
/* PARENT */
char silence[CHUNK_SIZE];
int pause = 0;
int quit = 0;
int bbp = buffered_before_play;
memset(silence,0,CHUNK_SIZE);
if(waitOnDecode(pc,af,dc,cb)<0) return;
pc->state = PLAYER_STATE_PLAY;
pc->play = 0;
kill(getppid(),SIGUSR1);
while(decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp &&
dc->state==DECODE_STATE_DECODE)
{
processDecodeInput();
if(quit) return;
usleep(100);
}
while(!quit) {
processDecodeInput();
if(dc->state==DECODE_STATE_STOP &&
pc->queueState==PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
{
cb->next = cb->end;
dc->start = 1;
pc->queueState = PLAYER_QUEUE_DECODE;
kill(getppid(),SIGUSR1);
}
if(pause) {
playAudio(silence,CHUNK_SIZE);
}
else if((cb->begin!=cb->end || cb->wrap) &&
cb->begin!=cb->next)
{
pc->elapsedTime = cb->times[cb->begin];
playAudio(cb->chunks[cb->begin],
cb->chunkSize[cb->begin]);
cb->begin++;
if(cb->begin>=BUFFERED_CHUNKS) {
cb->begin = 0;
cb->wrap = 0;
}
}
else if(cb->next==cb->begin) {
while(pc->queueState==PLAYER_QUEUE_DECODE ||
pc->queueLockState==PLAYER_QUEUE_LOCKED)
{
processDecodeInput();
if(quit) {
quitDecode(pc,dc);
return;
}
usleep(10);
}
if(pc->queueState!=PLAYER_QUEUE_PLAY) {
quit = 1;
break;
}
else {
cb->next = -1;
if(waitOnDecode(pc,af,dc,cb)<0) return;
pc->queueState = PLAYER_QUEUE_EMPTY;
kill(getppid(),SIGUSR1);
}
}
else if(decode_pid<=0 ||
(dc->state==DECODE_STATE_STOP && !dc->start))
{
quit = 1;
break;
}
else usleep(10);
}
quitDecode(pc,dc);
/* END OF PARENT */
}
return;
}
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DECODE_H
#define DECODE_H
#include <stdio.h>
#include <sys/param.h>
#define DECODE_TYPE_MP3 0
#define DECODE_TYPE_OGG 1
#define DECODE_TYPE_FLAC 2
#define DECODE_STATE_STOP 0
#define DECODE_STATE_DECODE 1
#define DECODE_ERROR_NOERROR 0
#define DECODE_ERROR_UNKTYPE 1
typedef struct _DecoderControl {
int state;
int stop;
int start;
int error;
int seek;
double seekWhere;
char file[MAXPATHLEN+1];
} DecoderControl;
void decodeSigHandler(int sig);
void decode();
#endif
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "tables.h" #include "tables.h"
#include "utils.h" #include "utils.h"
#include "path.h" #include "path.h"
#include "myfprintf.h" #include "log.h"
#include "playlist.h" #include "playlist.h"
#include <string.h> #include <string.h>
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#define DIRECTORY_DIR "directory: " #define DIRECTORY_DIR "directory: "
#define DIRECTORY_MTIME "mtime: " #define DIRECTORY_MTIME "mtime: "
...@@ -66,7 +67,7 @@ int updateDirectory(Directory * directory); ...@@ -66,7 +67,7 @@ int updateDirectory(Directory * directory);
int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name); int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name);
Directory * newDirectory(Directory * parentDirectory, char * dirname) { Directory * newDirectory(Directory * parentDirectory, char * dirname, time_t mtime) {
Directory * directory; Directory * directory;
directory = malloc(sizeof(Directory)); directory = malloc(sizeof(Directory));
...@@ -76,8 +77,8 @@ Directory * newDirectory(Directory * parentDirectory, char * dirname) { ...@@ -76,8 +77,8 @@ Directory * newDirectory(Directory * parentDirectory, char * dirname) {
directory->parentDirectory = parentDirectory; directory->parentDirectory = parentDirectory;
directory->subDirectories = newDirectoryList(); directory->subDirectories = newDirectoryList();
directory->songs = newSongList(); directory->songs = newSongList();
if(dirname!=NULL) directory->mtime = isDir(dirname); if(mtime<0) directory->mtime = isDir(dirname);
else directory->mtime = 0; else directory->mtime = mtime;
return directory; return directory;
} }
...@@ -116,7 +117,7 @@ int updateInDirectory(Directory * directory, char * shortname, char * name) { ...@@ -116,7 +117,7 @@ int updateInDirectory(Directory * directory, char * shortname, char * name) {
if((mtime = isMusic(name))) { if((mtime = isMusic(name))) {
if(0==findInList(directory->songs,shortname,&song)) { if(0==findInList(directory->songs,shortname,&song)) {
printf("adding %s\n",name); LOG1("adding %s\n",name);
addToDirectory(directory,shortname,name); addToDirectory(directory,shortname,name);
} }
else if(mtime>((Song *)song)->mtime) { else if(mtime>((Song *)song)->mtime) {
...@@ -243,7 +244,7 @@ int exploreDirectory(Directory * directory) { ...@@ -243,7 +244,7 @@ int exploreDirectory(Directory * directory) {
if((dir = opendir(rmp2amp(dirname)))==NULL) return -1; if((dir = opendir(rmp2amp(dirname)))==NULL) return -1;
printf("explore: %s\n",dirname); LOG1("explore: %s\n",dirname);
while((ent = readdir(dir))) { while((ent = readdir(dir))) {
if(ent->d_name[0]=='.') continue; /* hide hidden stuff */ if(ent->d_name[0]=='.') continue; /* hide hidden stuff */
if(directory->name) { if(directory->name) {
...@@ -261,7 +262,7 @@ int exploreDirectory(Directory * directory) { ...@@ -261,7 +262,7 @@ int exploreDirectory(Directory * directory) {
} }
int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name) { int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name) {
Directory * subDirectory = newDirectory(directory,name); Directory * subDirectory = newDirectory(directory,name,-1);
insertInList(directory->subDirectories,shortname,subDirectory); insertInList(directory->subDirectories,shortname,subDirectory);
exploreDirectory(subDirectory); exploreDirectory(subDirectory);
...@@ -294,6 +295,10 @@ Directory * findSubDirectory(Directory * directory,char * name) { ...@@ -294,6 +295,10 @@ Directory * findSubDirectory(Directory * directory,char * name) {
char * key; char * key;
key = strtok(dup,"/"); key = strtok(dup,"/");
if(!key) {
free(dup);
return NULL;
}
if(findInList(directory->subDirectories,key,&subDirectory)) { if(findInList(directory->subDirectories,key,&subDirectory)) {
free(dup); free(dup);
...@@ -338,7 +343,7 @@ int printDirectoryList(FILE * fp, DirectoryList * directoryList) { ...@@ -338,7 +343,7 @@ int printDirectoryList(FILE * fp, DirectoryList * directoryList) {
return 0; return 0;
} }
int printDirectoryInfo(FILE * fp,char * name) { int printDirectoryInfo(FILE * fp, char * name) {
Directory * directory; Directory * directory;
if((directory = getDirectory(name))==NULL) { if((directory = getDirectory(name))==NULL) {
...@@ -356,19 +361,19 @@ void writeDirectoryInfo(FILE * fp, Directory * directory) { ...@@ -356,19 +361,19 @@ void writeDirectoryInfo(FILE * fp, Directory * directory) {
ListNode * node = (directory->subDirectories)->firstNode; ListNode * node = (directory->subDirectories)->firstNode;
Directory * subDirectory; Directory * subDirectory;
if(directory->name) fprintf(fp,"%s%s\n",DIRECTORY_BEGIN,directory->name); if(directory->name) myfprintf(fp,"%s%s\n",DIRECTORY_BEGIN,directory->name);
while(node!=NULL) { while(node!=NULL) {
subDirectory = (Directory *)node->data; subDirectory = (Directory *)node->data;
fprintf(fp,"%s%s\n",DIRECTORY_DIR,node->key); myfprintf(fp,"%s%s\n",DIRECTORY_DIR,node->key);
fprintf(fp,"%s%li\n",DIRECTORY_MTIME,(long)subDirectory->mtime); myfprintf(fp,"%s%li\n",DIRECTORY_MTIME,(long)subDirectory->mtime);
writeDirectoryInfo(fp,subDirectory); writeDirectoryInfo(fp,subDirectory);
node = node->nextNode; node = node->nextNode;
} }
writeSongInfoFromList(fp,directory->songs); writeSongInfoFromList(fp,directory->songs);
if(directory->name) fprintf(fp,"%s%s\n",DIRECTORY_END,directory->name); if(directory->name) myfprintf(fp,"%s%s\n",DIRECTORY_END,directory->name);
} }
void readDirectoryInfo(FILE * fp,Directory * directory) { void readDirectoryInfo(FILE * fp,Directory * directory) {
...@@ -383,25 +388,25 @@ void readDirectoryInfo(FILE * fp,Directory * directory) { ...@@ -383,25 +388,25 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
if(0==strncmp(DIRECTORY_DIR,buffer,strlen(DIRECTORY_DIR))) { if(0==strncmp(DIRECTORY_DIR,buffer,strlen(DIRECTORY_DIR))) {
key = strdup(&(buffer[strlen(DIRECTORY_DIR)])); key = strdup(&(buffer[strlen(DIRECTORY_DIR)]));
if(myFgets(buffer,bufferSize,fp)<0) { if(myFgets(buffer,bufferSize,fp)<0) {
fprintf(stderr,"Error reading db\n"); ERROR0("Error reading db\n");
exit(-1); exit(-1);
} }
if(strncmp(DIRECTORY_MTIME,buffer,strlen(DIRECTORY_MTIME))) { if(strncmp(DIRECTORY_MTIME,buffer,strlen(DIRECTORY_MTIME))) {
fprintf(stderr,"Error reading db\n"); ERROR0("Error reading db\n");
printf("%s\n",buffer); ERROR1("%s\n",buffer);
exit(-1); exit(-1);
} }
mtime = atoi(&(buffer[strlen(DIRECTORY_BEGIN)])); mtime = atoi(&(buffer[strlen(DIRECTORY_BEGIN)]));
if(myFgets(buffer,bufferSize,fp)<0) { if(myFgets(buffer,bufferSize,fp)<0) {
fprintf(stderr,"Error reading db\n"); ERROR0("Error reading db\n");
exit(-1); exit(-1);
} }
if(strncmp(DIRECTORY_BEGIN,buffer,strlen(DIRECTORY_BEGIN))) { if(strncmp(DIRECTORY_BEGIN,buffer,strlen(DIRECTORY_BEGIN))) {
fprintf(stderr,"Error reading db\n"); ERROR0("Error reading db\n");
exit(-1); exit(-1);
} }
name = strdup(&(buffer[strlen(DIRECTORY_BEGIN)])); name = strdup(&(buffer[strlen(DIRECTORY_BEGIN)]));
subDirectory = newDirectory(directory,name); subDirectory = newDirectory(directory,name,mtime);
insertInList(directory->subDirectories,key,(void *)subDirectory); insertInList(directory->subDirectories,key,(void *)subDirectory);
free(key); free(key);
free(name); free(name);
...@@ -411,7 +416,7 @@ void readDirectoryInfo(FILE * fp,Directory * directory) { ...@@ -411,7 +416,7 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
readSongInfoIntoList(fp,directory->songs); readSongInfoIntoList(fp,directory->songs);
} }
else { else {
fprintf(stderr,"Unknown line in db: %s\n",buffer); ERROR1("Unknown line in db: %s\n",buffer);
exit(-1); exit(-1);
} }
} }
...@@ -436,10 +441,10 @@ int writeDirectoryDB() { ...@@ -436,10 +441,10 @@ int writeDirectoryDB() {
sortDirectory(mp3rootDirectory); sortDirectory(mp3rootDirectory);
if(!(fp=fopen(directorydb,"w"))) return -1; while(!(fp=fopen(directorydb,"w")) && errno==EINTR);
if(!fp) return -1;
writeDirectoryInfo(fp,mp3rootDirectory); writeDirectoryInfo(fp,mp3rootDirectory);
fclose(fp); while(fclose(fp) && errno==EINTR);
return 0; return 0;
} }
...@@ -447,10 +452,11 @@ int writeDirectoryDB() { ...@@ -447,10 +452,11 @@ int writeDirectoryDB() {
int readDirectoryDB() { int readDirectoryDB() {
FILE * fp; FILE * fp;
mp3rootDirectory = newDirectory(NULL,NULL); mp3rootDirectory = newDirectory(NULL,NULL,0);
if(!(fp=fopen(directorydb,"r"))) return -1; while(!(fp=fopen(directorydb,"r")) && errno==EINTR);
if(!fp) return -1;
readDirectoryInfo(fp,mp3rootDirectory); readDirectoryInfo(fp,mp3rootDirectory);
fclose(fp); while(fclose(fp) && errno==EINTR);
sortDirectory(mp3rootDirectory); sortDirectory(mp3rootDirectory);
...@@ -512,7 +518,7 @@ int printAllIn(FILE * fp, char * name) { ...@@ -512,7 +518,7 @@ int printAllIn(FILE * fp, char * name) {
} }
void initMp3Directory() { void initMp3Directory() {
mp3rootDirectory = newDirectory(NULL,NULL); mp3rootDirectory = newDirectory(NULL,NULL,0);
exploreDirectory(mp3rootDirectory); exploreDirectory(mp3rootDirectory);
sortDirectory(mp3rootDirectory); sortDirectory(mp3rootDirectory);
} }
......
...@@ -36,8 +36,6 @@ int writeDirectoryDB(); ...@@ -36,8 +36,6 @@ int writeDirectoryDB();
int readDirectoryDB(); int readDirectoryDB();
size_t getDirectoryLine(char ** buffer, int * size, FILE * fp);
int updateMp3Directory(FILE * fp); int updateMp3Directory(FILE * fp);
int printAllIn(FILE * fp, char * name); int printAllIn(FILE * fp, char * name);
......
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_FLAC
#include "flac_decode.h"
#include "utils.h"
#include "log.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <FLAC/file_decoder.h>
#include <FLAC/metadata.h>
typedef struct {
unsigned char chunk[CHUNK_SIZE];
int chunk_length;
float time;
Buffer * cb;
AudioFormat * af;
DecoderControl * dc;
char * file;
} FlacData;
/* this code is based on flac123, from flac-tools */
int flacSendChunk(FlacData * data);
void flacPlayfile(const char * file, Buffer * cb, ao_sample_format * format);
void flacError(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *);
void flacPrintErroredState(FLAC__FileDecoderState state, char * file);
void flacMetadata(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *);
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const buf[], void *);
void flacPlayFile(char *file, Buffer * cb, AudioFormat * af,
DecoderControl *dc)
{
FLAC__FileDecoder * flacDec;
FlacData data;
int status = 1;
data.chunk_length = 0;
data.time = 0;
data.cb = cb;
data.af = af;
data.dc = dc;
data.file = file;
if(!(flacDec = FLAC__file_decoder_new())) return;
/*status&=FLAC__file_decoder_set_md5_checking(flacDec,1);*/
status&=FLAC__file_decoder_set_filename(flacDec,file);
status&=FLAC__file_decoder_set_write_callback(flacDec,flacWrite);
status&=FLAC__file_decoder_set_metadata_callback(flacDec,flacMetadata);
status&=FLAC__file_decoder_set_error_callback(flacDec,flacError);
status&=FLAC__file_decoder_set_client_data(flacDec, (void *)&data);
if(!status) {
ERROR1("flac problem before init(): %s\n",file);
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file);
FLAC__file_decoder_delete(flacDec);
return;
}
if(FLAC__file_decoder_init(flacDec)!=
FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
{
ERROR1("flac problem doing init(): %s\n",file);
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file);
FLAC__file_decoder_delete(flacDec);
return;
}
if(!FLAC__file_decoder_process_until_end_of_metadata(flacDec)) {
ERROR1("flac problem reading metadata: %s\n",file);
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file);
FLAC__file_decoder_delete(flacDec);
return;
}
while(1) {
FLAC__file_decoder_process_single(flacDec);
if(FLAC__file_decoder_get_state(flacDec)!=
FLAC__FILE_DECODER_OK)
{
break;
}
if(dc->seek) {
FLAC__uint64 sampleToSeek = dc->seekWhere*
af->sampleRate+0.5;
cb->end = 0;
cb->wrap = 0;
if(FLAC__file_decoder_seek_absolute(flacDec,
sampleToSeek))
{
data.time = ((float)sampleToSeek)/
af->sampleRate;
}
dc->seek = 0;
}
}
FLAC__file_decoder_process_until_end_of_file(flacDec);
if(!dc->stop) {
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),
file);
FLAC__file_decoder_finish(flacDec);
}
FLAC__file_decoder_delete(flacDec);
/* send last little bit */
if(data.chunk_length>0 && !dc->stop) flacSendChunk(&data);
}
void flacError(const FLAC__FileDecoder *dec, FLAC__StreamDecoderErrorStatus status, void *fdata) {
FlacData * data = (FlacData *) fdata;
if(data->dc->stop) return;
switch(status) {
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
ERROR1("flac lost sync: %s\n",data->file);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
ERROR1("bad header %s\n",data->file);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
ERROR1("crc mismatch %s\n",data->file);
break;
default:
ERROR1("unknow flac error %s\n",data->file);
}
}
void flacPrintErroredState(FLAC__FileDecoderState state, char * file) {
switch(state) {
case FLAC__FILE_DECODER_ERROR_OPENING_FILE:
ERROR1("error opening flac: %s\n",file);
break;
case FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR0("flac allocation error\n");
break;
case FLAC__FILE_DECODER_SEEK_ERROR:
ERROR1("flac seek error: %s\n",file);
break;
case FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR:
ERROR1("flac seekable stream error: %s\n",file);
break;
case FLAC__FILE_DECODER_ALREADY_INITIALIZED:
ERROR1("flac decoder already initilaized: %s\n",file);
break;
case FLAC__FILE_DECODER_INVALID_CALLBACK:
ERROR0("invalid flac callback\n");
break;
case FLAC__FILE_DECODER_UNINITIALIZED:
ERROR1("flac decoder uninitialized: %s\n",file);
break;
case FLAC__FILE_DECODER_OK:
case FLAC__FILE_DECODER_END_OF_FILE:
break;
}
}
void flacMetadata(const FLAC__FileDecoder *dec, const FLAC__StreamMetadata *meta, void *data) {
}
int flacSendChunk(FlacData * data) {
while(data->cb->begin==data->cb->end && data->cb->wrap &&
!data->dc->stop && !data->dc->seek)
{
usleep(10);
}
if(data->dc->stop) return -1;
if(data->dc->seek) return 0;
memcpy(data->cb->chunks[data->cb->end],data->chunk,CHUNK_SIZE);
data->cb->chunkSize[data->cb->end] = data->chunk_length;
data->cb->times[data->cb->end] = data->time;
data->cb->end++;
if(data->cb->end>=BUFFERED_CHUNKS) {
data->cb->end = 0;
data->cb->wrap = 1;
}
return 0;
}
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__FileDecoder *dec, const FLAC__Frame *frame, const FLAC__int32 * const buf[], void * vdata) {
FlacData * data = (FlacData *)vdata;
uint_32 samples = frame->header.blocksize;
uint_16 u16;
unsigned char * uc;
int c_samp, c_chan, d_samp;
int i;
data->time+=((float)samples)/frame->header.sample_rate;
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
for(c_chan = 0; c_chan < frame->header.channels;
c_chan++, d_samp++) {
u16 = buf[c_chan][c_samp];
uc = (unsigned char *)&u16;
for(i=0;i<(data->af->bits/8);i++) {
if(data->chunk_length>=CHUNK_SIZE) {
if(flacSendChunk(data)<0) {
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
data->chunk_length = 0;
if(data->dc->seek) {
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
}
data->chunk[data->chunk_length++] = *(uc++);
}
}
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
int flac_getAudioFormatAndTime(char * file, AudioFormat * format, float * time) {
FLAC__Metadata_SimpleIterator * it;
FLAC__StreamMetadata * block = NULL;
int found = 0;
int ret = -1;
if(!(it = FLAC__metadata_simple_iterator_new())) return -1;
if(!FLAC__metadata_simple_iterator_init(it,file,1,0)) {
FLAC__metadata_simple_iterator_delete(it);
return -1;
}
do {
if(block) FLAC__metadata_object_delete(block);
block = FLAC__metadata_simple_iterator_get_block(it);
if(block->type == FLAC__METADATA_TYPE_STREAMINFO) found=1;
} while(!found && FLAC__metadata_simple_iterator_next(it));
if(found) {
format->bits = block->data.stream_info.bits_per_sample;
format->bits = 16;
format->sampleRate = block->data.stream_info.sample_rate;
format->channels = block->data.stream_info.channels;
*time = ((float)block->data.stream_info.total_samples)/
format->sampleRate;
ret = 0;
}
if(block) FLAC__metadata_object_delete(block);
FLAC__metadata_simple_iterator_delete(it);
return ret;
}
int flac_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc) {
if(flac_getAudioFormatAndTime(dc->file,af,&(cb->totalTime))<0) {
ERROR1("\"%s\" doesn't seem to be a flac\n",dc->file);
return -1;
}
dc->state = DECODE_STATE_DECODE;
dc->start = 0;
flacPlayFile(dc->file,cb,af,dc);
if(dc->seek) dc->seek = 0;
if(dc->stop) {
dc->state = DECODE_STATE_STOP;
dc->stop = 0;
}
else dc->state = DECODE_STATE_STOP;
return 0;
}
#endif
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
#ifndef FLAC_DECODE_H #ifndef FLAC_DECODE_H
#define FLAC_DECODE_H #define FLAC_DECODE_H
#include "playerData.h"
#include <stdio.h> #include <stdio.h>
int flac_decode(char * file, FILE * in, FILE * out); int flac_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc);
#endif #endif
...@@ -21,15 +21,17 @@ ...@@ -21,15 +21,17 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
void initInterfaces(); void initInterfaces();
void openAInterface(int fd); void openAInterface(int fd, struct sockaddr * addr);
void closeAllInterfaces(); void closeAllInterfaces();
void freeAllInterfaces(); void freeAllInterfaces();
void closeOldInterfaces(); void closeOldInterfaces();
void closeInterfaceWithFD(int fd); void closeInterfaceWithFD(int fd);
void flushAllInterfaceBuffers(); void flushAllInterfaceBuffers();
void interfacePrintWithFD(int fd, char * buffer); int interfacePrintWithFD(int fd, char * buffer);
int doIOForInterfaces(); int doIOForInterfaces();
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
libid3tag - ID3 tag manipulation library libid3tag - ID3 tag manipulation library
Copyright (C) 2000-2003 Underbit Technologies, Inc. Copyright (C) 2000-2003 Underbit Technologies, Inc.
$Id: CHANGES,v 1.2 2003/07/05 05:18:51 shank Exp $ $Id: CHANGES,v 1.1 2003/08/14 03:57:13 shank Exp $
=============================================================================== ===============================================================================
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
libid3tag - ID3 tag manipulation library libid3tag - ID3 tag manipulation library
Copyright (C) 2000-2003 Underbit Technologies, Inc. Copyright (C) 2000-2003 Underbit Technologies, Inc.
$Id: CREDITS,v 1.2 2003/07/05 05:18:51 shank Exp $ $Id: CREDITS,v 1.1 2003/08/14 03:57:13 shank Exp $
=============================================================================== ===============================================================================
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
## along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## ##
## $Id: Makefile.am,v 1.3 2003/07/05 06:12:40 shank Exp $ ## $Id: Makefile.am,v 1.1 2003/08/14 03:57:13 shank Exp $
## ##
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
......
...@@ -66,12 +66,19 @@ EXEEXT = @EXEEXT@ ...@@ -66,12 +66,19 @@ EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@ OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@ AMTAR = @AMTAR@
AR = @AR@
AS = @AS@ AS = @AS@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
CXX = @CXX@
CXXCPP = @CXXCPP@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
ECHO = @ECHO@ ECHO = @ECHO@
EGREP = @EGREP@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LIBTOOL = @LIBTOOL@ LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIBTOOL_DEPS = @LIBTOOL_DEPS@
...@@ -79,6 +86,7 @@ LN_S = @LN_S@ ...@@ -79,6 +86,7 @@ LN_S = @LN_S@
OBJDUMP = @OBJDUMP@ OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@ STRIP = @STRIP@
VERSION = @VERSION@ VERSION = @VERSION@
am__include = @am__include@ am__include = @am__include@
...@@ -123,7 +131,7 @@ libid3tag_la_LDFLAGS = -version-info $(version_info) ...@@ -123,7 +131,7 @@ libid3tag_la_LDFLAGS = -version-info $(version_info)
BUILT_SOURCES = frametype.c compat.c genre.dat BUILT_SOURCES = frametype.c compat.c genre.dat
subdir = . subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
CONFIG_HEADER = config.h CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = libid3tag.list CONFIG_CLEAN_FILES = libid3tag.list
LTLIBRARIES = $(noinst_LTLIBRARIES) LTLIBRARIES = $(noinst_LTLIBRARIES)
...@@ -141,7 +149,7 @@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I. ...@@ -141,7 +149,7 @@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/../depcomp depcomp = $(SHELL) $(top_srcdir)/../../depcomp
am__depfiles_maybe = depfiles am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/compat.Plo ./$(DEPDIR)/crc.Plo \ @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/compat.Plo ./$(DEPDIR)/crc.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/field.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/field.Plo \
...@@ -168,10 +176,11 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ ...@@ -168,10 +176,11 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
uninstall-info-recursive all-recursive install-data-recursive \ uninstall-info-recursive all-recursive install-data-recursive \
install-exec-recursive installdirs-recursive install-recursive \ install-exec-recursive installdirs-recursive install-recursive \
uninstall-recursive check-recursive installcheck-recursive uninstall-recursive check-recursive installcheck-recursive
DIST_COMMON = README $(noinst_HEADERS) ../config.guess ../config.sub \ DIST_COMMON = README $(noinst_HEADERS) ../../config.guess \
../depcomp ../install-sh ../ltmain.sh ../missing \ ../../config.sub ../../depcomp ../../install-sh ../../ltmain.sh \
../mkinstalldirs COPYING INSTALL Makefile.am Makefile.in TODO \ ../../missing ../../mkinstalldirs COPYING INSTALL Makefile.am \
aclocal.m4 config.h.in configure configure.ac libid3tag.list.in Makefile.in TODO aclocal.m4 config.h.in configure configure.ac \
libid3tag.list.in
DIST_SUBDIRS = $(SUBDIRS) DIST_SUBDIRS = $(SUBDIRS)
SOURCES = $(libid3tag_la_SOURCES) $(EXTRA_libid3tag_la_SOURCES) SOURCES = $(libid3tag_la_SOURCES) $(EXTRA_libid3tag_la_SOURCES)
...@@ -394,7 +403,7 @@ distcleancheck_listfiles = find . -type f -print ...@@ -394,7 +403,7 @@ distcleancheck_listfiles = find . -type f -print
distdir: $(DISTFILES) distdir: $(DISTFILES)
$(am__remove_distdir) $(am__remove_distdir)
mkdir $(distdir) mkdir $(distdir)
$(mkinstalldirs) $(distdir)/. $(distdir)/.. $(mkinstalldirs) $(distdir)/. $(distdir)/../..
@list='$(DISTFILES)'; for file in $$list; do \ @list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
libid3tag - ID3 tag manipulation library libid3tag - ID3 tag manipulation library
Copyright (C) 2000-2003 Underbit Technologies, Inc. Copyright (C) 2000-2003 Underbit Technologies, Inc.
$Id: README,v 1.2 2003/07/05 05:18:51 shank Exp $ $Id: README,v 1.1 2003/08/14 03:57:13 shank Exp $
=============================================================================== ===============================================================================
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
libid3tag - ID3 tag manipulation library libid3tag - ID3 tag manipulation library
Copyright (C) 2000-2003 Underbit Technologies, Inc. Copyright (C) 2000-2003 Underbit Technologies, Inc.
$Id: TODO,v 1.2 2003/07/05 05:18:51 shank Exp $ $Id: TODO,v 1.1 2003/08/14 03:57:13 shank Exp $
=============================================================================== ===============================================================================
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* C code produced by gperf version 3.0 */ /* C code produced by gperf version 3.0.1 */
/* Command-line: gperf -tCcTonD -K id -N id3_compat_lookup -s -3 -k '*' compat.gperf */ /* Command-line: gperf -tCcTonD -K id -N id3_compat_lookup -s -3 -k '*' compat.gperf */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
...@@ -48,7 +48,7 @@ error "gperf generated tables don't work with this execution character set. Plea ...@@ -48,7 +48,7 @@ error "gperf generated tables don't work with this execution character set. Plea
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Id: compat.gperf,v 1.2 2003/07/05 05:18:51 shank Exp * Id: compat.gperf,v 1.1 2003/08/14 03:57:13 shank Exp
*/ */
# ifdef HAVE_CONFIG_H # ifdef HAVE_CONFIG_H
......
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.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
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