Commit 88831267 authored by Led's avatar Led

0.10.0-rc1

parent c3cb1cf2
......@@ -3,3 +3,4 @@ Developer -> tw-nym
wave File Support -> normalperson
setuid patch -> Nagilum
'next' and 'previous' patch -> Niklas Hofer
command.c cleanup -> mackstann
ver 0.10.0 (2004/3/3)
1) Use UTF-8 for all client communications
2) Crossfading support
3) Password Authentication (all in plaintext)
4) Software mixer
5) Buffer Size is configurable
6) Reduced Memory consumption (use directory tree for search and find)
7) Bitrate support for Flac
8) setvol command (deprecates volume command)
9) add command takes directories
10) Path's in config file now work with ~
11) Add samplerate,bits, and channels to status
12) Reenable playTime in stats display
13) Fix a segfault when doing: add ""
14) Fix a segfault with flac vorbis comments simply being "="
15) Fix a segfault/bug in queueNextSong with repeat+random
16) Fix a bug, where one process may segfault, and cause more processes to spawn w/o killing ones that lost their parent.
17) Fix a bug when the OSS device was unable to fetch the current volume,
it would close the device (when it maybe previously closed by the exact same code)
ver 0.9.4 (2004/1/21)
1) Fix a bug where updated tag info wasn't being detected
2) Set the default audio write size to 1024 bytes (should decrease cpu load a bit on some machines).
......
......@@ -25,6 +25,9 @@ libogg, libogg-devel, libvorbis, and libvorbis-devel).
Flac - http://flac.sf.net
For Flac support, you need Flac 1.1.0 or greater.
Audiofile - http://www.68k.org/~michael/audiofile/
For wave support.
Download
--------
......
SUBDIRS = src doc debian
SUBDIRS = src doc
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README UPGRADING
EXTRA_DIST = COPYING $(doc_DATA)
0.10.0
------
1) store song times (possibly after playing)
2) possibly, crossfading
3) resample in software for sound cards that support a limited range of
sampling rate.
4) Password protection
1) 24-bit pcm-tools (this may just wait since almost no one uses it)
2?) put software mixer settings in state file
Music Player Daemon (MPD) - UPGRADING
Upgrading to 0.10.0
-------------------
All information is now stored in the db in UTF-8 format, and the character
set used for the filesystem is stored in the db. Thus, it is highly
recommended that you recreate the db. To do so, run mpd with the
"--create-db" command line option. Also, note that the filesystem
character set will be determined from your current locale settings.
If your locale settings are not the same as those used for the filesystem,
then use the config file parameter "filesystem_charset" to specify the
correct character set (this maybe neccessary if you create the db with root).
Upgrading to 0.9.3
------------------
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -28,14 +28,6 @@
# compile PROGRAM [ARGS]...
# `-o FOO.o' is removed from the args passed to the actual compile.
# Usage statement added by Billy Biggs <vektor@dumbterm.net>.
if [ -z $1 ]; then
echo "Wrapper for compilers which do not understand '-c -o'."
echo "usage: compile PROGRAM [ARGS]..."
echo "'-o FOO.o' is removed from the args passed to the actual compile."
exit 1
fi
prog=$1
shift
......
This source diff could not be displayed because it is too large. You can view the blob instead.
AC_INIT(src/main.c)
AM_INIT_AUTOMAKE(mpd, 0.9.5)
dnl AC_INIT(src/main.c)
dnl AM_INIT_AUTOMAKE(mpd, 0.10.0)
AC_PREREQ(2.52)
AC_INIT(mpd, 0.10.0, shank@mercury.chem.pitt.edu)
AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
AC_PROG_CC
AC_PROG_INSTALL
......@@ -20,6 +24,7 @@ MPD_CFLAGS="-Wall"
MPD_LIBS=""
AC_ARG_ENABLE(iconv,[ --disable-iconv disable iconv support],,enable_iconv=yes)
AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support],,enable_ipv6=yes)
AC_ARG_ENABLE(ogg,[ --disable-ogg disable ogg support],,enable_ogg=yes)
AC_ARG_ENABLE(flac,[ --disable-flac disable flac support],,enable_flac=yes)
AC_ARG_ENABLE(mp3,[ --disable-mp3 disable mp3 support],,enable_mp3=yes)
......@@ -36,9 +41,19 @@ AC_ARG_WITH(mad,[ --with-mad=PFX Prefix where libmad is installed (optional)]
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_C_BIGENDIAN
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_CHECK_LIB(socket,socket,MPD_LIBS="$MPD_LIBS -lsocket",)
AC_CHECK_LIB(nsl,gethostbyname,MPD_LIBS="$MPD_LIBS -lnsl",)
AC_CHECK_HEADER(langinfo.h,MPD_CFLAGS="$MPD_CFLAGS -DHAVE_LANGINFO",)
AC_CHECK_HEADER(locale.h,MPD_CFLAGS="$MPD_CFLAGS -DHAVE_LOCALE",)
if test x$enable_iconv = xyes; then
AC_CHECK_HEADER(iconv.h,MPD_CFLAGS="$MPD_CFLAGS -DHAVE_ICONV",enable_iconv=no)
if test x$enable_iconv = xyes; then
......@@ -46,9 +61,10 @@ if test x$enable_iconv = xyes; then
fi
fi
AC_MSG_CHECKING(for ipv6)
AC_EGREP_CPP([AP_maGiC_VALUE],
[
if test x$enable_ipv6 = xyes; then
AC_MSG_CHECKING(for ipv6)
AC_EGREP_CPP([AP_maGiC_VALUE],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
......@@ -57,11 +73,12 @@ AC_EGREP_CPP([AP_maGiC_VALUE],
AP_maGiC_VALUE
#endif
#endif
],
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_IPV6"
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
],
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_IPV6"
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
)
fi
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)])
......@@ -256,4 +273,4 @@ if test x$enable_audiofile = xyes; then
[enable_audiofile=no;AC_MSG_WARN(You need audiofile -- disabling audiofile support)])
fi
AC_OUTPUT(debian/Makefile doc/Makefile src/Makefile Makefile )
AC_OUTPUT(doc/Makefile src/Makefile Makefile )
EXTRA_DIST = changelog compat control copyright dirs docs rules config \
init postinst postrm prerm templates conffiles
# 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@
AUDIOFILE_CFLAGS = @AUDIOFILE_CFLAGS@
AUDIOFILE_CONFIG = @AUDIOFILE_CONFIG@
AUDIOFILE_LIBS = @AUDIOFILE_LIBS@
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 config \
init postinst postrm prerm templates conffiles
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.4-1) unstable; urgency=low
* Update to 0.9.4
-- Warren Dukes (aka shank) <shank@mercury.chem.pitt.edu> Tue, 20 Jan 2004 22:24:00 -0500
mpd (0.9.3-1) unstable; urgency=low
* Update to 0.9.3
* Switch to cdbs
* Use debconf for configure music_directory, playlist_directory, port
* Add /etc/mpd.conf and /etc/mpd/conf
* Add initd script
-- Warren Dukes (aka shank) <shank@mercury.chem.pitt.edu> Tue, 31 Oct 2003 18:16:00 -0400
mpd (0.9.2-1) unstable; urgency=low
* Update to 0.9.2
-- Warren Dukes (aka shank) <shank@mercury.chem.pitt.edu> Tue, 06 Oct 2003 22:04:00 -0400
mpd (0.9.1-1) unstable; urgency=low
* Update to 0.9.1
-- Warren Dukes <shank@mercury.chem.pitt.edu> Tue, 30 Sep 2003 09:09:00 -0400
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
#!/bin/sh -e
# Source debconf library.
. /usr/share/debconf/confmodule
# Do you like debian?
db_input medium mpd/systemwide || true
db_go
db_get mpd/systemwide || true
if [ "$RET" = "true" ] ; then
db_input medium mpd/music_directory || true
db_go
db_input medium mpd/playlist_directory || true
db_go
db_input low mpd/port || true
db_go
fi
Source: mpd
Section: sound
Priority: optional
Maintainer: Warren Dukes (aka shank) <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, debconf, cdbs, libaudiofile-dev
Standards-Version: 3.5.8
Package: mpd
Architecture: any
Depends: ${shlibs:Depends}, ${misc: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
#! /bin/sh
set -e
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/mpd
DBFILE=/var/run/mpd/mpddb
test -x $DAEMON || exit 0
case "$1" in
start)
if test -f $DBFILE; then
echo -n "Starting Music Player Daemon: mpd"
start-stop-daemon --start --quiet --exec $DAEMON
echo "."
else
echo "MPD db not found, run: $DAEMON --create-db."
fi
;;
stop)
echo -n "Stopping Music Player Daemon: mpd"
start-stop-daemon --stop --quiet --exec $DAEMON || echo -n " ... mpd not running"
echo "."
;;
restart|force-reload)
$0 stop
$0 start
;;
*)
echo "Usage: /etc/init.d/mpd {start|stop|restart|force-reload}"
exit 1
;;
esac
exit 0
#!/bin/sh -e
# Source debconf library.
. /usr/share/debconf/confmodule
db_get mpd/systemwide || true
if [ "$RET" = "true" ] ; then
echo "# BEGIN - GENERTATED BY DEBCONF" > /etc/mpd.conf
db_get mpd/music_directory || true
echo "music_directory \"$RET\"" >> /etc/mpd.conf
db_get mpd/playlist_directory || true
echo "playlist_directory \"$RET\"" >> /etc/mpd.conf
db_get mpd/port || true
echo "port \"$RET\"" >> /etc/mpd.conf
echo "# END - GENERTATED BY DEBCONF" >> /etc/mpd.conf
echo "" >> /etc/mpd.conf
echo "# Rest included from /etc/mpd/conf" >> /etc/mpd.conf
cat /etc/mpd/conf >> /etc/mpd.conf
chmod 600 /etc/mpd.conf
groupadd mpd > /dev/null 2>&1 || true
useradd -M -g mpd -G mpd,audio mpd > /dev/null 2>&1 || true
mkdir -p /var/log/mpd
chown mpd.mpd /var/log/mpd
chmod 700 /var/log/mpd
mkdir -p /var/lib/mpd
chown mpd.mpd /var/lib/mpd
chmod 700 /var/lib/mpd
# Automatically added by dh_installinit
if [ -x "/etc/init.d/mpd" ]; then
update-rc.d mpd defaults >/dev/null
if [ -x /usr/sbin/invoke-rc.d ]; then
invoke-rc.d mpd start
else
/etc/init.d/mpd start
fi
fi
# End automatically added section
fi
#!/bin/sh -e
rm -r /var/log/mpd > /dev/null 2>&1 || true
rm -r /var/lib/mpd > /dev/null 2>&1 || true
# Automatically added by dh_installinit
if [ "$1" = "purge" ] ; then
update-rc.d mpd remove defaults >/dev/null
rm -rf /var/log/mpd
rm -rf /var/lib/mpd
rm -f /etc/mpd.conf
fi
# Automatically added by dh_installdebconf
if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
db_purge
fi
# End automatically added section
#!/bin/sh -e
# Automatically added by dh_installinit
if [ -x "/etc/init.d/mpd" ]; then
if [ -x /usr/sbin/invoke-rc.d ] ; then
invoke-rc.d mpd stop
else
/etc/init.d/mpd stop
fi
fi
# End automatically added section
#!/usr/bin/make -f
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/autotools.mk
binary-post-install/mpd::
mkdir -p debian/mpd/usr/share/doc/mpd/examples
cp doc/mpdconf.example debian/mpd/usr/share/doc/mpd/examples
mkdir -p debian/mpd/etc/mpd
echo "#see manpage for mpd for all config options" > debian/mpd/etc/mpd/conf
echo "log_file \"/var/log/mpd/mpd_log\"" >> debian/mpd/etc/mpd/conf
echo "error_file \"/var/log/mpd/mpd_errors\"" >> debian/mpd/etc/mpd/conf
echo "db_file \"/var/lib/mpd/mpddb\"" >> debian/mpd/etc/mpd/conf
echo "user \"mpd\"" >> debian/mpd/etc/mpd/conf
Template: mpd/systemwide
Type: boolean
Default: false
Description: Install system mpd service?
You can install mpd as a system daemon. This will create a mpd user and
config file (/etc/mpd.conf). The mpd service will be
started on boot.
Template: mpd/music_directory
Type: string
Default: /usr/share/mpd/music
Description: Music directory for MPD
Which directory do you want MPD to search in for music files?
Template: mpd/playlist_directory
Type: string
Default: /usr/share/mpd/playlists
Description: Music directory for MPD
Which directory do you want MPD to search in for music files?
Template: mpd/port
Type: string
Default: 2100
Description: Port MPD listens on
Which port number do you want MPD to listen on?
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
# Copyright 1999, 2000 Free Software Foundation, Inc.
# Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -172,19 +172,25 @@ sgi)
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. This file always lives in the current directory.
# Also, the AIX compiler puts `$object:' at the start of each line;
# $object doesn't have directory information.
stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
outname="$stripped.o"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test -f "$tmpdepfile"; then :
else
stripped=`echo "$stripped" | sed 's,^.*/,,'`
tmpdepfile="$stripped.u"
fi
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
......@@ -192,6 +198,7 @@ aix)
fi
if test -f "$tmpdepfile"; then
outname="$stripped.o"
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
......@@ -206,6 +213,44 @@ aix)
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
......@@ -240,8 +285,8 @@ tru64)
fi
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a space and a tab in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
......@@ -254,7 +299,7 @@ tru64)
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout, regardless of -o.
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
......@@ -265,9 +310,7 @@ dashmstdout)
shift
fi
# Remove `-o $object'. We will use -o /dev/null later,
# however we can't do the remplacement now because
# `-o $object' might simply not be used
# Remove `-o $object'.
IFS=" "
for arg
do
......@@ -287,7 +330,11 @@ dashmstdout)
done
test -z "$dashmflag" && dashmflag=-M
"$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
......@@ -306,6 +353,13 @@ dashXmstdout)
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
......@@ -318,7 +372,9 @@ makedepend)
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
-*)
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
......@@ -339,7 +395,7 @@ makedepend)
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout.
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
......@@ -381,7 +437,7 @@ cpp)
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout, regardless of -o,
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
......
......@@ -20,11 +20,14 @@ These denote the end of command execution.
Commands:
---------
add <string file>
add the file _file_ to the playlist
add <string path>
add the file _path_ to the playlist (directories add recursively)
_path_ can also be a single file
increments playlist version by for each song added
clear
clears the current playlist
increments playlist version by 1
clearerror
clear the current error message in status
......@@ -33,8 +36,12 @@ clearerror
close
close the connection with the MPD
crossfade <int seconds>
sets crossfading between songs
delete <int song>
delete _song_ from playlist
increments playlist version by 1
find <string type> <string what>
finds songs in the db that are exactly _what_
......@@ -51,29 +58,38 @@ list <string type> <string arg1>
to list albums by a artist, where artist is specified with
arg1
listall <string directory>
lists all songs and directories in _directory_ (recursively)
_directory_ is optional
listall <string path>
lists all songs and directories in _path_ (recursively)
_path_ is optional and maybe a directory or path
listallinfo <string path>
same as listall command, except it also returns metadata info
in the same format as lsinfo
load <string name>
loads the playlist _name_.m3u from the playlist directory
ls <string directory>
list files in _directory_. _directory_ is optional.
NOTE: us this only for debugging, not meant to be used by a client.
instead use 'lsinfo'
increments playlist version by the number of songs added
lsinfo <string directory>
list contents of _directory_, from the db. _directory_ is optional
move <int from> <int to>
move song at _from_ to _to_ in the playlist
increments playlist version by 1
next
plays next song in playlist
pause
pause/resume playing
pause <bool pause>
toggle pause/resume playing
_pause_ is optional and should be 0 or 1
password <string password>
this is used for authentication with the server.
_password_ is simply the plaintext password
ping
does nothing but return "OK"
play <int song>
begin playing playlist at song number _song_, _song_ is optional
......@@ -108,8 +124,13 @@ seek <int song> <int time>
seeks to the position _time_ (in seconds) of entry _song_ in the
playlist
setvol <int vol>
set volume to _vol_
_vol_ the range of volume is 0-100
shuffle
shuffles the current playlist
increments playlist version by 1
stats
display stats
......@@ -117,9 +138,9 @@ stats
albums: number of albums
songs: number of songs
uptime: daemon uptime in seconds
db_playtime: sum of all song times in db
db_update: last db update in UNIX time
playtime: time length of music played
songs_played: total number of songs played
status
reports current status of player, and volume level.
......@@ -131,6 +152,8 @@ status
song: (current song playing/paused, playlist song number)
time: <int elapsed>:<time total> (of current playing/paused song)
bitrate: <int bitrate> (instantaneous bitrate in kbps)
xfade: <int seconds> (crossfade in seconds)
audio: <int sampleRate>:<int bits>:<int channels>
error: if there is an error, returns message here
stop
......@@ -138,12 +161,14 @@ stop
swap <int song1> <int song2>
swap positions of _song1_ and _song2_
increments playlist version by 1
update
searches mp3 directory for new music and removes old music from the db
volume <int change>
change volume by amount _change_
NOTE: volume command is deprecated, use setvol instead
COMMAND LIST
------------
......
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# Makefile.in generated by automake 1.7.8 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -13,110 +13,138 @@
# 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@
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@
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AO_CFLAGS = @AO_CFLAGS@
AO_LIBS = @AO_LIBS@
AR = @AR@
AS = @AS@
AUDIOFILE_CFLAGS = @AUDIOFILE_CFLAGS@
AUDIOFILE_CONFIG = @AUDIOFILE_CONFIG@
AUDIOFILE_LIBS = @AUDIOFILE_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
EXEEXT = @EXEEXT@
ID3_LIB = @ID3_LIB@
ID3_SUBDIR = @ID3_SUBDIR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBFLAC_CFLAGS = @LIBFLAC_CFLAGS@
LIBFLAC_LIBS = @LIBFLAC_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAD_LIB = @MAD_LIB@
MAD_SUBDIR = @MAD_SUBDIR@
MAKEINFO = @MAKEINFO@
MPD_CFLAGS = @MPD_CFLAGS@
MPD_LIBS = @MPD_LIBS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OGG_CFLAGS = @OGG_CFLAGS@
OGG_LIBS = @OGG_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
RC = @RC@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
VORBISENC_LIBS = @VORBISENC_LIBS@
VORBISFILE_LIBS = @VORBISFILE_LIBS@
VORBIS_CFLAGS = @VORBIS_CFLAGS@
VORBIS_LIBS = @VORBIS_LIBS@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
man_MANS = mpd.1
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = COMMANDS
EXTRA_DIST = mpdconf.example $(man_MANS) $(doc_DATA)
subdir = doc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_SOURCES =
......@@ -125,11 +153,11 @@ NROFF = nroff
MANS = $(man_MANS)
DATA = $(doc_DATA)
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign doc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
......@@ -181,6 +209,10 @@ uninstall-man1:
done; \
for i in $$list; do \
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; \
......@@ -208,13 +240,22 @@ uninstall-docDATA:
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
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 \
......@@ -240,7 +281,6 @@ all-am: Makefile $(MANS) $(DATA)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(man1dir) $(DESTDIR)$(docdir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
......@@ -260,7 +300,7 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
......@@ -270,7 +310,7 @@ clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
......@@ -292,13 +332,21 @@ install-man: install-man1
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-docDATA uninstall-info-am uninstall-man
uninstall-man: uninstall-man1
......@@ -310,9 +358,9 @@ uninstall-man: uninstall-man1
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
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
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.
......
......@@ -66,19 +66,44 @@ This specifies how verbose logs are. "default" is minimal logging, "secure" rep
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.
.B filesystem_charset <charset>
This specifies the character set used for the filesystem. A list of supported
character sets can be obtained by running "iconv -l". The default is
determined from the locale when the db was originally created.
.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.
.TP
.B user <user>
This specifies the user that mpd will run as, if set.
.TP
.B password <password@permissions>
This specifies a password for access to mpd. The format is
"password@permissions" where permissions is a comma delimmitted list composed
of "read","add","control", and/or "admin". "read" allows for reading of
the database, displaying the current playlist, and current status of mpd.
"add" allows for adding songs and loading playlists. "control" allows
for all other player and playlist manipulations. "admin" allows the db
to be updated and for the client to kill mpd. More than one password can
be specified. An example of a password is "somePassword@read,add".
.TP
.B default_permissions <permissions>
This specifies the permissions of a client that has not been authenticated using
a password. The format of permissions is specified n the description of the
"password" config paramter. If not passwords are specified, the default is
"read,add,control,admin", otherwise it is "" (no permissions).
.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 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_type <oss or alsa>
.B mixer_type <oss, alsa, or software>
This specifies which mixer to use. The default is oss.
.TP
.B mixer_device <mixer dev>
......@@ -91,12 +116,11 @@ This specifies which mixer control to use (sometimes referred to as the "device"
.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_size <size in KB>
This specifies the size of the buffer that mpd uses. The default is 2048 kilobytes.
.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
......@@ -109,23 +133,23 @@ 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
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 audio_write_size <size in bytes>
This specifies how many bytes mpd writes to the audio device at once. The
default is 1024. This options is to work around a bug in older versions
of libao on sound cards with very small buffers.
.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. (Note: '#' at the beginning of a line denotes
a comment. The '#' must be the first character/symbol on that line.)
Below is an example config file. (Note: '#' at the beginning of a line denotes a comment. The '#' must be the first character/symbol on that line.)
.br
.br
......@@ -133,56 +157,74 @@ a comment. The '#' must be the first character/symbol on that line.)
.br
port "2100"
.br
music_directory "/home/shank/mp3"
music_directory "~/mp3"
.br
playlist_directory "/home/shank/playlists"
playlist_directory "~/playlists"
.br
log_file "/home/shank/mpd.log"
log_file "~/mpd.log"
.br
error_file "/home/shank/mpd.error"
error_file "~/mpd.error"
.br
.br
# optional
.br
mixer_type "oss"
mixer_type "oss"
.br
mixer_device "/dev/mixer"
.br
#mixer_control "Pcm"
.br
# mixer_type is typically "oss", "alsa", or "software"
.br
mixer_device "/dev/mixer"
#mixer_type "alsa"
.br
#mixer_type "alsa"
#mixer_device "default"
.br
#mixer_device "default"
#mixer_control "PCM"
.br
#ao_driver "oss"
# ao_driver is typically "oss" or "alsa09"
.br
#ao_driver_options "dsp=/dev/dsp"
#ao_driver "oss"
.br
max_playlist_length "4096"
#ao_driver_options "dsp=/dev/dsp"
.br
buffer_before_play "25%"
#audio_write_size "1024"
.br
#db_file "/home/shank/playlists/.mpddb"
max_playlist_length "4096"
.br
#state_file "/home/shank/playlists/.mpdstate"
buffer_before_play "25%"
.br
#user "shank"
buffer_size "2048"
.br
connection_timeout "60"
#db_file "~/playlists/.mpddb"
.br
max_connections "5"
#state_file "~/playlists/.mpdstate"
.br
max_command_list_size "2048"
#user "shank"
.br
max_output_buffer_size "2048"
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"
log_level "default"
.br
# when bind_to_address is set to "any", MPD binds all available addresses
.br
bind_to_address "any"
.br
#passwd "passwd@read,add,control,admin"
.br
# if bind_to_address is "any", MPD binds all addresses
#default_permissions "read,add,control,admin"
.br
bind_to_address "any"
#filesystem_charset "UTF-8"
.SH SEE ALSO
mpc(1)
# required
port "2100"
music_directory "/home/shank/mp3"
playlist_directory "/home/shank/playlists"
log_file "/home/shank/mpd.log"
error_file "/home/shank/mpd.error"
music_directory "~/mp3"
playlist_directory "~/playlists"
log_file "~/mpd.log"
error_file "~/mpd.error"
# optional
mixer_type "oss"
mixer_device "/dev/mixer"
#mixer_control "Pcm"
# mixer_type is typically "oss", "alsa", or "software"
#mixer_type "alsa"
#mixer_device "default"
#mixer_control "PCM"
# ao_driver is typically "oss" or "alsa09"
#ao_driver "oss"
#ao_driver_options "dsp=/dev/dsp"
#audio_write_size "1024"
max_playlist_length "4096"
buffer_before_play "25%"
#db_file "/home/shank/playlists/.mpddb"
#state_file "/home/shank/playlists/.mpdstate"
buffer_size "2048"
#db_file "~/playlists/.mpddb"
#state_file "~/playlists/.mpdstate"
#user "shank"
connection_timeout "60"
max_connections "5"
......@@ -28,3 +32,6 @@ save_absolute_paths_in_playlists "no"
log_level "default"
# when bind_to_address is set to "any", MPD binds all available addresses
bind_to_address "any"
#passwd "passwd@read,add,control,admin"
#default_permissions "read,add,control,admin"
#filesystem_charset "UTF-8"
......@@ -74,7 +74,7 @@ dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
-c) instcmd=$cpprog
shift
continue;;
......@@ -97,7 +97,7 @@ while [ x"$1" != x ]; do
shift
continue;;
-s) stripcmd="$stripprog"
-s) stripcmd=$stripprog
shift
continue;;
......@@ -124,7 +124,7 @@ done
if [ x"$src" = x ]
then
echo "install: no input file specified"
echo "$0: no input file specified" >&2
exit 1
else
:
......@@ -133,8 +133,8 @@ fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
if [ -d "$dst" ]; then
instcmd=:
chmodcmd=""
else
......@@ -143,20 +143,20 @@ if [ x"$dir_arg" != x ]; then
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "install: $src does not exist"
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
echo "$0: no destination specified" >&2
exit 1
else
:
......@@ -165,16 +165,16 @@ else
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
if [ -d "$dst" ]
then
dst="$dst"/`basename $src`
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
......@@ -183,69 +183,73 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
IFS="${IFS-$defaultIFS}"
oIFS="${IFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
pathcomp=$pathcomp$1
shift
if [ ! -d "${pathcomp}" ] ;
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "${pathcomp}"
$mkdirprog "$pathcomp"
else
:
fi
pathcomp="${pathcomp}/"
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
dstfile=`basename "$dst"`
else
dstfile=`basename $dst $transformbasename |
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
dstfile=`basename "$dst"`
else
:
fi
# Make a temp file name in the proper directory.
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/#inst.$$#
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Move or copy the file name to the temp name
# Trap to clean up temp files at exit.
$doit $instcmd $src $dsttmp &&
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
trap "rm -f ${dsttmp}" 0 &&
# Move or copy the file name to the temp name
$doit $instcmd "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits
......@@ -253,17 +257,38 @@ else
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# Now remove or move aside any old file at destination location. We try this
# two ways since rm can't unlink itself on some systems and the destination
# file might be busy for other reasons. In this case, the final cleanup
# might fail but the new file should still install successfully.
{
if [ -f "$dstdir/$dstfile" ]
then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
{
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
# The final little trick to "correctly" pass the exit status to the exit trap.
exit 0
{
(exit 0); exit
}
This source diff could not be displayed because it is too large. You can view the blob instead.
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
......@@ -165,7 +165,7 @@ WARNING: \`$1' is missing on your system. You should only need it if
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them.
You can get \`$1Help2man' as part of \`Autoconf' from any GNU
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
......@@ -326,7 +326,7 @@ WARNING: I can't seem to be able to run \`tar' with the given arguments.
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
......
......@@ -12,18 +12,29 @@ Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case "${1}" in
-h | --help | --h* ) # -h for help
echo "${usage}" 1>&2; exit 0 ;;
-m ) # -m PERM arg
shift
test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
dirmode="${1}"
shift ;;
-- ) shift; break ;; # stop option processing
-* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
* ) break ;; # first non-opt arg
esac
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
......@@ -36,64 +47,65 @@ do
done
case $# in
0) exit 0 ;;
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi ;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi ;;
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 3
# sh-indentation: 2
# End:
# mkinstalldirs ends here
......@@ -4,12 +4,12 @@ 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 \
char_conv.h audiofile_decode.h
audiofile_decode.h charConv.h permission.h mpd_types.h pcm_utils.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 \
char_conv.c audiofile_decode.c $(mpd_headers)
audiofile_decode.c charConv.c permission.c pcm_utils.c $(mpd_headers)
mpd_CFLAGS = $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB)
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -47,7 +47,7 @@ void initAudioDriver() {
audio_write_size = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10);
if (*test!='\0') {
ERROR1("\"%s\" is not a valid write size",
ERROR("\"%s\" is not a valid write size",
(getConf())[CONF_AUDIO_WRITE_SIZE]);
exit(-1);
}
......@@ -60,14 +60,14 @@ void initAudioDriver() {
}
else if((audio_ao_driver_id =
ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) {
ERROR1("\"%s\" is not a valid ao driver\n",
ERROR("\"%s\" is not a valid ao driver\n",
(getConf())[CONF_AO_DRIVER]);
exit(-1);
}
if((ai = ao_driver_info(audio_ao_driver_id))==NULL) {
ERROR0("problems getting ao_driver_info\n");
ERROR0("you may not have permission to the audio device\n");
ERROR("problems getting ao_driver_info\n");
ERROR("you may not have permission to the audio device\n");
exit(-1);
}
......@@ -79,7 +79,7 @@ void initAudioDriver() {
stk2 = NULL;
key = strtok_r(n1,"=",&stk2);
if(!key) {
ERROR1("problems parsing "
ERROR("problems parsing "
"ao_driver_options \"%s\"\n", n1);
exit(-1);
}
......@@ -91,14 +91,14 @@ void initAudioDriver() {
}
}
if(!found) {
ERROR2("\"%s\" is not an option for "
ERROR("\"%s\" is not an option for "
"\"%s\" ao driver\n",key,
ai->short_name);
exit(-1);
}*/
value = strtok_r(NULL,"",&stk2);
if(!value) {
ERROR1("problems parsing "
ERROR("problems parsing "
"ao_driver_options \"%s\"\n", n1);
exit(-1);
}
......@@ -115,56 +115,70 @@ void finishAudioDriver() {
ao_shutdown();
}
int isCurrentAudioFormat(AudioFormat * audioFormat) {
if(!audio_device) return 0;
if(audio_format.bits!=audioFormat->bits ||
audio_format.sampleRate!=audioFormat->sampleRate ||
audio_format.channels!=audioFormat->channels)
{
return 0;
}
return 1;
}
int initAudio(AudioFormat * audioFormat) {
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 && !isCurrentAudioFormat(audioFormat)) {
finishAudio();
}
if(!audio_device) {
format.bits = audioFormat->bits;
format.rate = audioFormat->sampleRate;
format.byte_format = AO_FMT_LITTLE;
format.byte_format = AO_FMT_NATIVE;
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();
if(audio_device==NULL) return -1;
}
return 0;
}
void playAudio(char * playChunk, int size) {
int playAudio(char * playChunk, int size) {
int send;
assert(audio_device!=NULL);
if(audio_device==NULL) {
ERROR("trying to play w/ the audio device being open!\n");
return -1;
}
while(size>0) {
send = audio_write_size>size?size:audio_write_size;
ao_play(audio_device,playChunk,send);
if(ao_play(audio_device,playChunk,send)==0) {
audioError();
ERROR("closing audio device due to write error\n");
finishAudio();
return -1;
}
playChunk+=send;
size-=send;
}
return 0;
}
void finishAudio() {
......@@ -177,14 +191,14 @@ void finishAudio() {
}
void audioError() {
ERROR0("Error opening audio device\n");
ERROR("Error opening audio device\n");
if(errno==AO_ENOTLIVE) {
ERROR0("not a live ao device\n");
ERROR("not a live ao device\n");
}
else if(errno==AO_EOPENDEVICE) {
ERROR0("not able to open audio device\n");
ERROR("not able to open audio device\n");
}
else if(errno==AO_EBADOPTION) {
ERROR0("bad driver option\n");
ERROR("bad driver option\n");
}
}
......@@ -19,15 +19,17 @@
#ifndef AUDIO_H
#define AUDIO_H
#include "mpd_types.h"
#include <stdio.h>
#include <ao/ao.h>
#define AUDIO_AO_DRIVER_DEFAULT "default"
typedef struct _AudioFormat {
int channels;
int sampleRate;
int bits;
mpd_sint8 channels;
mpd_uint32 sampleRate;
mpd_sint8 bits;
} AudioFormat;
extern int audio_ao_driver_id;
......@@ -39,10 +41,12 @@ void finishAudioDriver();
int initAudio(AudioFormat * audioFormat);
void playAudio(char * playChunk,int size);
int playAudio(char * playChunk,int size);
void finishAudio();
void audioError();
int isCurrentAudioFormat(AudioFormat * audioFormat);
#endif
......@@ -21,10 +21,12 @@
#ifdef HAVE_AUDIOFILE
#include "audiofile_decode.h"
#include "command.h"
#include "utils.h"
#include "audio.h"
#include "log.h"
#include "pcm_utils.h"
#include <stdio.h>
#include <unistd.h>
......@@ -50,15 +52,17 @@ int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
{
int fs, frame_count;
AFfilehandle af_fp;
int bits;
af_fp = afOpenFile(dc->file,"r", NULL);
if(af_fp == AF_NULL_FILEHANDLE) {
ERROR1("failed to open %s\n",dc->file);
ERROR("failed to open %s\n",dc->file);
return -1;
}
afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &af->bits);
af->sampleRate = (int)afGetRate(af_fp, AF_DEFAULT_TRACK);
afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
af->bits = bits;
af->sampleRate = afGetRate(af_fp, AF_DEFAULT_TRACK);
af->channels = afGetChannels(af_fp,AF_DEFAULT_TRACK);
frame_count = afGetFrameCount(af_fp,AF_DEFAULT_TRACK);
......@@ -66,7 +70,7 @@ int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
cb->totalTime = ((float)frame_count/(float)af->sampleRate);
if (af->bits != 8 && af->bits != 16) {
ERROR2("Only 8 and 16-bit files are supported. %s is %i-bit\n",
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
dc->file,af->bits);
afCloseFile(af_fp);
return -1;
......@@ -100,7 +104,12 @@ int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
if(dc->stop) break;
else if(dc->seek) continue;
memcpy(cb->chunks[cb->end],chunk,CHUNK_SIZE);
#ifdef WORDS_BIGENDIAN
pcm_changeBufferEndianness(chunk,CHUNK_SIZE,
af->bits);
#endif
memcpy(cb->chunks+cb->end*CHUNK_SIZE,chunk,
CHUNK_SIZE);
cb->chunkSize[cb->end] = CHUNK_SIZE;
current += ret;
......@@ -108,7 +117,7 @@ int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
++cb->end;
if(cb->end>=BUFFERED_CHUNKS) {
if(cb->end>=buffered_chunks) {
cb->end = 0;
cb->wrap = 1;
}
......
......@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "char_conv.h"
#include "charConv.h"
#include <stdlib.h>
#include <errno.h>
......@@ -54,16 +54,17 @@ int setCharSetConversion(char * to, char * from) {
char * convStrDup(char * string) {
#ifdef HAVE_ICONV
char buffer[BUFFER_SIZE];
int inleft = strlen(string);
size_t inleft = strlen(string);
char * ret;
int outleft;
int retlen = 0;
size_t outleft;
size_t retlen = 0;
size_t err;
char * bufferPtr;
if(!char_conv_to) return NULL;
ret = strdup("");
ret = malloc(1);
ret[0] = '\0';
while(inleft) {
bufferPtr = buffer;
......@@ -76,7 +77,7 @@ char * convStrDup(char * string) {
}
ret = realloc(ret,retlen+BUFFER_SIZE-outleft+1);
strncpy(&(ret[retlen]),buffer,BUFFER_SIZE-outleft);
memcpy(ret+retlen,buffer,BUFFER_SIZE-outleft);
retlen+=BUFFER_SIZE-outleft;
ret[retlen] = '\0';
}
......
......@@ -27,6 +27,11 @@
#define COMMAND_RESPOND_ERROR "ACK"
#define COMMAND_RESPOND_OK "OK"
int processCommand(FILE * fp, int argArrayLength, char ** argArray);
int processCommand(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray);
void initCommands();
void finishCommands();
#endif
......@@ -29,14 +29,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#define MAX_STRING_SIZE MAXPATHLEN+80
#define CONF_COMMENT '#'
#define CONF_NUMBER_OF_PARAMS 23
#define CONF_NUMBER_OF_PATHS 6
#define CONF_NUMBER_OF_REQUIRED 5
#define CONF_NUMBER_OF_PARAMS 27
#define CONF_NUMBER_OF_PATHS 6
#define CONF_NUMBER_OF_REQUIRED 5
#define CONF_NUMBER_OF_ALLOW_CATS 1
#define CONF_CONNECTION_TIMEOUT_DEFAULT "60"
#define CONF_MAX_CONNECTIONS_DEFAULT "5"
......@@ -51,6 +55,7 @@
#define CONF_USER_DEFAULT ""
#define CONF_LOG_LEVEL_DEFAULT "default"
#define CONF_AUDIO_WRITE_SIZE_DEFAULT "1024"
#define CONF_BUFFER_SIZE_DEFAULT "2048"
#ifndef NO_OSS_MIXER
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_OSS
#define CONF_MIXER_DEVICE_DEFAULT ""
......@@ -64,50 +69,6 @@
#endif
#endif
char * conf_strings[CONF_NUMBER_OF_PARAMS] = {
"port",
"music_directory",
"playlist_directory",
"log_file",
"error_file",
"connection_timeout",
"mixer_device",
"max_connections",
"max_playlist_length",
"buffer_before_play",
"max_command_list_size",
"max_output_buffer_size",
"ao_driver",
"ao_driver_options",
"save_absolute_paths_in_playlists",
"bind_to_address",
"mixer_type",
"state_file",
"user",
"db_file",
"log_level",
"mixer_control",
"audio_write_size"
};
int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
CONF_MUSIC_DIRECTORY,
CONF_PLAYLIST_DIRECTORY,
CONF_LOG_FILE,
CONF_ERROR_FILE,
CONF_STATE_FILE,
CONF_DB_FILE
};
int conf_required[CONF_NUMBER_OF_REQUIRED] = {
CONF_MUSIC_DIRECTORY,
CONF_PLAYLIST_DIRECTORY,
CONF_LOG_FILE,
CONF_ERROR_FILE,
CONF_PORT
};
char * conf_params[CONF_NUMBER_OF_PARAMS];
void initConf() {
......@@ -131,17 +92,74 @@ void initConf() {
conf_params[CONF_USER] = strdup(CONF_USER_DEFAULT);
conf_params[CONF_LOG_LEVEL] = strdup(CONF_LOG_LEVEL_DEFAULT);
conf_params[CONF_AUDIO_WRITE_SIZE] = strdup(CONF_AUDIO_WRITE_SIZE_DEFAULT);
conf_params[CONF_BUFFER_SIZE] = strdup(CONF_BUFFER_SIZE_DEFAULT);
}
char ** readConf(char * file) {
char * conf_strings[CONF_NUMBER_OF_PARAMS] = {
"port",
"music_directory",
"playlist_directory",
"log_file",
"error_file",
"connection_timeout",
"mixer_device",
"max_connections",
"max_playlist_length",
"buffer_before_play",
"max_command_list_size",
"max_output_buffer_size",
"ao_driver",
"ao_driver_options",
"save_absolute_paths_in_playlists",
"bind_to_address",
"mixer_type",
"state_file",
"user",
"db_file",
"log_level",
"mixer_control",
"audio_write_size",
"filesystem_charset",
"password",
"default_permissions",
"buffer_size"
};
int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
CONF_MUSIC_DIRECTORY,
CONF_PLAYLIST_DIRECTORY,
CONF_LOG_FILE,
CONF_ERROR_FILE,
CONF_STATE_FILE,
CONF_DB_FILE
};
int conf_required[CONF_NUMBER_OF_REQUIRED] = {
CONF_MUSIC_DIRECTORY,
CONF_PLAYLIST_DIRECTORY,
CONF_LOG_FILE,
CONF_ERROR_FILE,
CONF_PORT
};
short conf_allowCat[CONF_NUMBER_OF_ALLOW_CATS] = {
CONF_PASSWORD
};
FILE * fp;
char string[MAX_STRING_SIZE+1];
char ** array;
int i;
int numberOfArgs;
short allowCat[CONF_NUMBER_OF_PARAMS];
for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) allowCat[i] = 0;
for(i=0;i<CONF_NUMBER_OF_ALLOW_CATS;i++) allowCat[conf_allowCat[i]] = 1;
if(!(fp=fopen(file,"r"))) {
ERROR1("problems opening file %s for reading\n",file);
ERROR("problems opening file %s for reading\n",file);
exit(-1);
}
......@@ -150,19 +168,30 @@ char ** readConf(char * file) {
numberOfArgs = buffer2array(string,&array);
if(numberOfArgs==0) continue;
if(2!=numberOfArgs) {
ERROR1("need two args in conf at: %s\n",string);
ERROR("need two args in conf at: %s\n",string);
exit(-1);
}
i = 0;
while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++;
if(i>=CONF_NUMBER_OF_PARAMS) {
ERROR1("unrecognized line in conf: %s\n",string);
ERROR("unrecognized line in conf: %s\n",string);
exit(-1);
}
if(conf_params[i]!=NULL) {
free(conf_params[i]);
if(allowCat[i]) {
conf_params[i] = realloc(conf_params[i],
strlen(conf_params[i])+
strlen(CONF_CAT_CHAR)+
strlen(array[1])+1);
strcat(conf_params[i],CONF_CAT_CHAR);
strcat(conf_params[i],array[1]);
}
else {
free(conf_params[i]);
conf_params[i] = strdup(array[1]);
}
}
conf_params[i] = strdup(array[1]);
else conf_params[i] = strdup(array[1]);
free(array[0]);
free(array[1]);
free(array);
......@@ -172,7 +201,7 @@ char ** readConf(char * file) {
for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) {
if(conf_params[conf_required[i]] == NULL) {
ERROR1("%s is unassigned in conf file\n",
ERROR("%s is unassigned in conf file\n",
conf_strings[conf_required[i]]);
exit(-1);
}
......@@ -180,11 +209,57 @@ char ** readConf(char * file) {
for(i=0;i<CONF_NUMBER_OF_PATHS;i++) {
if(conf_params[conf_absolutePaths[i]] &&
conf_params[conf_absolutePaths[i]][0]!='/') {
ERROR1("\"%s\" is not an absolute path\n",
conf_params[conf_absolutePaths[i]][0]!='/' &&
conf_params[conf_absolutePaths[i]][0]!='~')
{
ERROR("\"%s\" is not an absolute path\n",
conf_params[conf_absolutePaths[i]]);
exit(-1);
}
/* Parse ~ in path */
else if(conf_params[conf_absolutePaths[i]] &&
conf_params[conf_absolutePaths[i]][0]=='~')
{
struct passwd * pwd = NULL;
char * path;
int pos = 1;
if(conf_params[conf_absolutePaths[i]][1]=='/' ||
conf_params[conf_absolutePaths[i]][1]=='\0')
{
uid_t uid = geteuid();
if((pwd = getpwuid(uid)) == NULL) {
ERROR("problems getting passwd entry "
"for current user\n");
exit(-1);
}
}
else {
int foundSlash = 0;
char * ch = &(
conf_params[conf_absolutePaths[i]][1]);
for(;*ch!='\0' && *ch!='/';ch++);
if(*ch=='/') foundSlash = 1;
* ch = '\0';
pos+= ch-
&(conf_params[
conf_absolutePaths[i]][1]);
if((pwd = getpwnam(&(conf_params[
conf_absolutePaths[i]][1]))) == NULL)
{
ERROR("user \"%s\" not found\n",
&(conf_params[
conf_absolutePaths[i]][1]));
exit(-1);
}
if(foundSlash) *ch = '/';
}
path = malloc(strlen(pwd->pw_dir)+strlen(
&(conf_params[conf_absolutePaths[i]][pos]))+1);
strcpy(path,pwd->pw_dir);
strcat(path,&(conf_params[conf_absolutePaths[i]][pos]));
free(conf_params[conf_absolutePaths[i]]);
conf_params[conf_absolutePaths[i]] = path;
}
}
return conf_params;
......@@ -193,22 +268,3 @@ char ** readConf(char * file) {
char ** getConf() {
return conf_params;
}
void writeConf(char * file) {
int i;
FILE * fp;
if(!(fp=fopen(file,"w"))) {
ERROR1("problems open file %s for writing\n",file);
exit(-1);
}
for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) {
if(conf_params[i]) {
myfprintf(fp,"%s \"%s\"\n",conf_strings[i],
conf_params[i]);
}
}
fclose(fp);
}
......@@ -42,6 +42,12 @@
#define CONF_LOG_LEVEL 20
#define CONF_MIXER_CONTROL 21
#define CONF_AUDIO_WRITE_SIZE 22
#define CONF_FS_CHARSET 23
#define CONF_PASSWORD 24
#define CONF_DEFAULT_PERMISSIONS 25
#define CONF_BUFFER_SIZE 26
#define CONF_CAT_CHAR "\n"
/* do not free the return value, it is a static variable */
char ** readConf(char * file);
......
......@@ -17,11 +17,15 @@
*/
#include "decode.h"
#include "player.h"
#include "playerData.h"
#include "utils.h"
#include "pcm_utils.h"
#include "audio.h"
#include "path.h"
#include "log.h"
#ifdef HAVE_MAD
#include "mp3_decode.h"
#endif
......@@ -34,8 +38,6 @@
#ifdef HAVE_AUDIOFILE
#include "audiofile_decode.h"
#endif
#include "path.h"
#include "log.h"
#include <signal.h>
#include <sys/types.h>
......@@ -45,31 +47,37 @@
#include <unistd.h>
#include <string.h>
int decode_pid = 0;
#define FADE_CHUNKS 1024
int * decode_pid = NULL;
void decodeSigHandler(int sig) {
if(sig==SIGCHLD) {
int status;
if(decode_pid==wait3(&status,WNOHANG,NULL)) {
if(decode_pid && *decode_pid==wait3(&status,WNOHANG,NULL)) {
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR1("decode process died from a "
ERROR("decode process died from a "
"non-TERM signal: %i\n",
WTERMSIG(status));
}
decode_pid = 0;
*decode_pid = 0;
}
}
else if(sig==SIGTERM) {
int pid = decode_pid;
if(pid>0) kill(pid,SIGTERM);
if(decode_pid) {
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)) {
if(decode_pid && *decode_pid>0 &&
(dc->start || dc->state==DECODE_STATE_DECODE))
{
dc->stop = 1;
while(decode_pid>0 && dc->stop) usleep(10);
while(decode_pid && *decode_pid>0 && dc->stop) usleep(10);
}
}
......@@ -82,20 +90,39 @@ void quitDecode(PlayerControl * pc, DecoderControl * dc) {
kill(getppid(),SIGUSR1);
}
int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
int chunks;
if(pc->crossFade<=0) return 0;
chunks = (af->sampleRate*af->bits*af->channels/8.0/CHUNK_SIZE);
chunks = (chunks*pc->crossFade+0.5);
if(chunks>(buffered_chunks-buffered_before_play)) {
chunks = buffered_chunks-buffered_before_play;
}
if(chunks<0) chunks = 0;
return chunks;
}
int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
Buffer * cb)
{
while(decode_pid>0 && dc->start) usleep(10);
while(decode_pid && *decode_pid>0 && dc->start) usleep(10);
if(dc->start || dc->error!=DECODE_ERROR_NOERROR) {
strcpy(pc->erroredFile,pc->file);
strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
printf("error: %i, start: %i, decode_pid: %i\n",dc->error,
dc->start,*decode_pid);
pc->error = PLAYER_ERROR_FILE;
quitDecode(pc,dc);
return -1;
}
if(initAudio(af)<0) {
strcpy(pc->erroredFile,pc->file);
strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
pc->error = PLAYER_ERROR_AUDIO;
quitDecode(pc,dc);
return -1;
......@@ -103,6 +130,9 @@ int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
pc->elapsedTime = 0;
pc->bitRate = 0;
pc->sampleRate = af->sampleRate;
pc->bits = af->bits;
pc->channels = af->channels;
pc->totalTime = cb->totalTime;
return 0;
......@@ -111,7 +141,7 @@ int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
Buffer * cb)
{
if(decode_pid>0) {
if(decode_pid && *decode_pid>0) {
cb->next = -1;
if(dc->state!=DECODE_STATE_DECODE || dc->error ||
strcmp(dc->file,pc->file)!=0)
......@@ -123,7 +153,7 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
dc->error = 0;
waitOnDecode(pc,af,dc,cb);
}
if(decode_pid>0 && dc->state==DECODE_STATE_DECODE) {
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;
......@@ -131,7 +161,7 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
dc->seek = 1;
pc->elapsedTime = dc->seekWhere;
pc->bitRate = 0;
while(decode_pid>0 && dc->seek) usleep(10);
while(*decode_pid>0 && dc->seek) usleep(10);
}
}
pc->seek = 0;
......@@ -154,24 +184,30 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
kill(getppid(),SIGUSR1); \
} \
if(pc->seek) { \
pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
decodeSeek(pc,af,dc,cb); \
pc->beginTime = pc->elapsedTime; \
doCrossFade = 0; \
nextChunk = -1; \
bbp = 0; \
} \
if(pc->stop) { \
pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
quitDecode(pc,dc); \
return; \
}
int decoderInit(PlayerControl * pc, Buffer * cb, AudioFormat *af,
DecoderControl * dc) {
decode_pid = fork();
decode_pid = &(pc->decode_pid);
int pid = fork();
if(decode_pid==0) {
if(pid==0) {
/* CHILD */
while(1) {
if(dc->start) {
strcpy(dc->file,pc->file);
strncpy(dc->file,pc->file,MAXPATHLEN);
switch(pc->decodeType) {
#ifdef HAVE_MAD
case DECODE_TYPE_MP3:
......@@ -213,11 +249,12 @@ int decoderInit(PlayerControl * pc, Buffer * cb, AudioFormat *af,
exit(0);
/* END OF CHILD */
}
else if(decode_pid<0) {
strcpy(pc->erroredFile,pc->file);
else if(pid<0) {
strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
pc->error = PLAYER_ERROR_SYSTEM;
return -1;
}
else *decode_pid = pid;
return 0;
}
......@@ -245,7 +282,7 @@ void decode() {
dc->start = 1;
cb->next = -1;
if(decode_pid<=0) {
if(decode_pid==NULL || *decode_pid<=0) {
if(decoderInit(pc,cb,af,dc)<0) return;
}
......@@ -255,6 +292,11 @@ void decode() {
int pause = 0;
int quit = 0;
int bbp = buffered_before_play;
int doCrossFade = 0;
int crossFadeChunks = 0;
int fadePosition;
int nextChunk = -1;
int test;
memset(silence,0,CHUNK_SIZE);
......@@ -262,9 +304,10 @@ void decode() {
pc->state = PLAYER_STATE_PLAY;
pc->play = 0;
pc->beginTime = pc->elapsedTime;
kill(getppid(),SIGUSR1);
while(decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp &&
while(*decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp &&
dc->state==DECODE_STATE_DECODE)
{
processDecodeInput();
......@@ -283,23 +326,111 @@ void decode() {
pc->queueState = PLAYER_QUEUE_DECODE;
kill(getppid(),SIGUSR1);
}
if(cb->next>=0 && doCrossFade==0 && !dc->start) {
nextChunk = -1;
if(isCurrentAudioFormat(af)) {
doCrossFade = 1;
crossFadeChunks =
calculateCrossFadeChunks(pc,af);
if(!crossFadeChunks ||
pc->crossFade>=cb->totalTime)
{
doCrossFade = -1;
}
}
else doCrossFade = -1;
}
if(pause) {
playAudio(silence,CHUNK_SIZE);
if(playAudio(silence,CHUNK_SIZE)<0) quit = 1;
}
else if((cb->begin!=cb->end || cb->wrap) &&
cb->begin!=cb->next)
{
if(doCrossFade==1 && cb->next>=0 &&
((cb->next>cb->begin &&
(fadePosition=cb->next-cb->begin)
<=crossFadeChunks) ||
(cb->begin>cb->next &&
(fadePosition=cb->next-cb->begin+
buffered_chunks)<=crossFadeChunks)))
{
if(nextChunk<0) {
crossFadeChunks = fadePosition;
}
nextChunk = cb->begin+crossFadeChunks;
test = cb->end;
if(cb->wrap) test+=buffered_chunks;
if(nextChunk<test) {
if(nextChunk>=buffered_chunks)
{
nextChunk-=
buffered_chunks;
}
pcm_mix(cb->chunks+cb->begin*
CHUNK_SIZE,
cb->chunks+nextChunk*
CHUNK_SIZE,
cb->chunkSize[
cb->begin],
cb->chunkSize[
nextChunk],
af,
((float)fadePosition)/
crossFadeChunks);
if(cb->chunkSize[nextChunk]>
cb->chunkSize[cb->begin]
)
{
cb->chunkSize[cb->begin]
= cb->chunkSize
[nextChunk];
}
}
else {
if(dc->state==DECODE_STATE_STOP)
{
doCrossFade = -1;
}
else {
usleep(10);
continue;
}
}
}
pc->elapsedTime = cb->times[cb->begin];
pc->bitRate = cb->bitRate[cb->begin];
playAudio(cb->chunks[cb->begin],
cb->chunkSize[cb->begin]);
pcm_volumeChange(cb->chunks+cb->begin*
CHUNK_SIZE,
cb->chunkSize[cb->begin],
af,
pc->softwareVolume);
if(playAudio(cb->chunks+cb->begin*CHUNK_SIZE,
cb->chunkSize[cb->begin])<0)
{
quit = 1;
}
cb->begin++;
if(cb->begin>=BUFFERED_CHUNKS) {
if(cb->begin>=buffered_chunks) {
cb->begin = 0;
cb->wrap = 0;
}
}
else if(cb->next==cb->begin) {
pc->totalPlayTime+= pc->elapsedTime-
pc->beginTime;
if(doCrossFade==1 && nextChunk>=0) {
nextChunk = cb->begin+crossFadeChunks;
test = cb->end;
if(cb->wrap) test+=buffered_chunks;
if(nextChunk<test) {
if(nextChunk>=buffered_chunks)
{
nextChunk-=
buffered_chunks;
}
cb->begin = nextChunk;
}
}
while(pc->queueState==PLAYER_QUEUE_DECODE ||
pc->queueLockState==PLAYER_QUEUE_LOCKED)
{
......@@ -317,11 +448,15 @@ void decode() {
else {
cb->next = -1;
if(waitOnDecode(pc,af,dc,cb)<0) return;
nextChunk = -1;
doCrossFade = 0;
crossFadeChunks = 0;
pc->queueState = PLAYER_QUEUE_EMPTY;
kill(getppid(),SIGUSR1);
}
pc->beginTime = cb->times[cb->begin];
}
else if(decode_pid<=0 ||
else if(*decode_pid<=0 ||
(dc->state==DECODE_STATE_STOP && !dc->start))
{
quit = 1;
......@@ -330,6 +465,7 @@ void decode() {
else usleep(10);
}
pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
quitDecode(pc,dc);
/* END OF PARENT */
......
......@@ -40,6 +40,18 @@ int updateMp3Directory(FILE * fp);
int printAllIn(FILE * fp, char * name);
int addAllIn(FILE * fp, char * name);
int printInfoForAllIn(FILE * fp, char * name);
int searchForSongsIn(FILE * fp, char * name, char * item, char * string);
int findSongsIn(FILE * fp, char * name, char * item, char * string);
int countSongsIn(FILE * fp, char * name);
unsigned long sumSongTimesIn(FILE * fp, char * name);
Song * getSong(char * file);
time_t getDbModTime();
......
......@@ -21,6 +21,7 @@
#include "utils.h"
#include "log.h"
#include "pcm_utils.h"
#include <stdio.h>
#include <string.h>
......@@ -32,6 +33,8 @@ typedef struct {
unsigned char chunk[CHUNK_SIZE];
int chunk_length;
float time;
int bitRate;
FLAC__uint64 position;
Buffer * cb;
AudioFormat * af;
DecoderControl * dc;
......@@ -56,6 +59,8 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af,
data.chunk_length = 0;
data.time = 0;
data.position = 0;
data.bitRate = 0;
data.cb = cb;
data.af = af;
data.dc = dc;
......@@ -69,7 +74,7 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af,
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);
ERROR("flac problem before init(): %s\n",file);
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file);
FLAC__file_decoder_delete(flacDec);
return;
......@@ -77,13 +82,13 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af,
if(FLAC__file_decoder_init(flacDec)!=
FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
{
ERROR1("flac problem doing init(): %s\n",file);
ERROR("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);
ERROR("flac problem reading metadata: %s\n",file);
flacPrintErroredState(FLAC__file_decoder_get_state(flacDec),file);
FLAC__file_decoder_delete(flacDec);
return;
......@@ -105,6 +110,7 @@ void flacPlayFile(char *file, Buffer * cb, AudioFormat * af,
{
data.time = ((float)sampleToSeek)/
af->sampleRate;
data.position = 0;
}
dc->seek = 0;
}
......@@ -126,41 +132,41 @@ void flacError(const FLAC__FileDecoder *dec, FLAC__StreamDecoderErrorStatus stat
switch(status) {
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
ERROR1("flac lost sync: %s\n",data->file);
ERROR("flac lost sync: %s\n",data->file);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
ERROR1("bad header %s\n",data->file);
ERROR("bad header %s\n",data->file);
break;
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
ERROR1("crc mismatch %s\n",data->file);
ERROR("crc mismatch %s\n",data->file);
break;
default:
ERROR1("unknow flac error %s\n",data->file);
ERROR("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);
ERROR("error opening flac: %s\n",file);
break;
case FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR:
ERROR0("flac allocation error\n");
ERROR("flac allocation error\n");
break;
case FLAC__FILE_DECODER_SEEK_ERROR:
ERROR1("flac seek error: %s\n",file);
ERROR("flac seek error: %s\n",file);
break;
case FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR:
ERROR1("flac seekable stream error: %s\n",file);
ERROR("flac seekable stream error: %s\n",file);
break;
case FLAC__FILE_DECODER_ALREADY_INITIALIZED:
ERROR1("flac decoder already initilaized: %s\n",file);
ERROR("flac decoder already initilaized: %s\n",file);
break;
case FLAC__FILE_DECODER_INVALID_CALLBACK:
ERROR0("invalid flac callback\n");
ERROR("invalid flac callback\n");
break;
case FLAC__FILE_DECODER_UNINITIALIZED:
ERROR1("flac decoder uninitialized: %s\n",file);
ERROR("flac decoder uninitialized: %s\n",file);
break;
case FLAC__FILE_DECODER_OK:
case FLAC__FILE_DECODER_END_OF_FILE:
......@@ -181,13 +187,17 @@ int flacSendChunk(FlacData * data) {
if(data->dc->stop) return -1;
if(data->dc->seek) return 0;
memcpy(data->cb->chunks[data->cb->end],data->chunk,CHUNK_SIZE);
#ifdef WORDS_BIGENDIAN
pcm_changeBufferEndianness(chunk,CHUNK_SIZE,data->af->bits);
#endif
memcpy(data->cb->chunks+data->cb->end*CHUNK_SIZE,data->chunk,
CHUNK_SIZE);
data->cb->chunkSize[data->cb->end] = data->chunk_length;
data->cb->times[data->cb->end] = data->time;
data->cb->bitRate[data->cb->end] = 0;
data->cb->bitRate[data->cb->end] = data->bitRate;
data->cb->end++;
if(data->cb->end>=BUFFERED_CHUNKS) {
if(data->cb->end>=buffered_chunks) {
data->cb->end = 0;
data->cb->wrap = 1;
}
......@@ -197,13 +207,23 @@ int flacSendChunk(FlacData * data) {
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;
FLAC__uint32 samples = frame->header.blocksize;
FLAC__uint16 u16;
unsigned char * uc;
int c_samp, c_chan, d_samp;
int i;
float timeChange;
FLAC__uint64 newPosition = 0;
data->time+=((float)samples)/frame->header.sample_rate;
timeChange = ((float)samples)/frame->header.sample_rate;
data->time+= timeChange;
FLAC__file_decoder_get_decode_position(dec,&newPosition);
if(data->position) {
data->bitRate = ((newPosition-data->position)*8.0/timeChange)
/1024+0.5;
}
data->position = newPosition;
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
for(c_chan = 0; c_chan < frame->header.channels;
......@@ -264,7 +284,7 @@ int flac_getAudioFormatAndTime(char * file, AudioFormat * format, float * time)
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);
ERROR("\"%s\" doesn't seem to be a flac\n",dc->file);
return -1;
}
......
......@@ -25,6 +25,7 @@
#include "listen.h"
#include "sig_handlers.h"
#include "playlist.h"
#include "permission.h"
#include <unistd.h>
#include <stdio.h>
......@@ -58,6 +59,7 @@ typedef struct _Interface {
int fd; /* file descriptor */
FILE * fp; /* file pointer */
int open; /* open/used */
unsigned int permission;
time_t lastTime;
List * commandList; /* for when in list mode */
unsigned long long commandListSize; /* mem commandList consumes */
......@@ -98,6 +100,8 @@ void openInterface(Interface * interface, int fd) {
interface->outputBufferSize = 0;
interface->outBuflen = 0;
interface->permission = getDefaultPermissions();
interface->outBufSize = INTERFACE_DEFAULT_OUT_BUFFER_SIZE;
#ifdef SO_SNDBUF
{
......@@ -107,10 +111,10 @@ void openInterface(Interface * interface, int fd) {
if(getsockopt(interface->fd,SOL_SOCKET,SO_SNDBUF,
(char *)&getSize,&sockOptLen) < 0)
{
DEBUG0("problem getting sockets send buffer size\n");
DEBUG("problem getting sockets send buffer size\n");
}
else if(getSize<=0) {
DEBUG0("sockets send buffer size is not positive\n");
DEBUG("sockets send buffer size is not positive\n");
}
else interface->outBufSize = getSize;
}
......@@ -136,7 +140,7 @@ void closeInterface(Interface * interface) {
free(interface->outBuffer);
SECURE1("interface %i: closed\n",interface->num);
SECURE("interface %i: closed\n",interface->num);
}
void openAInterface(int fd, struct sockaddr * addr) {
......@@ -145,33 +149,47 @@ void openAInterface(int fd, struct sockaddr * addr) {
for(i=0;i<interface_max_connections && interfaces[i].open;i++);
if(i==interface_max_connections) {
ERROR0("Max Connections Reached!\n");
ERROR("Max Connections Reached!\n");
while(close(fd) && errno==EINTR);
}
else {
SECURE1("interface %i: opened from ",i);
SECURE("interface %i: opened from ",i);
switch(addr->sa_family) {
case AF_INET:
SECURE1("%s\n",inet_ntoa(
{
char * host = inet_ntoa(
((struct sockaddr_in *)addr)->
sin_addr));
sin_addr);
if(host) {
SECURE("%s\n",host);
}
else {
SECURE("error getting ipv4 address\n");
}
}
break;
#ifdef HAVE_IPV6
case AF_INET6:
{
char host[INET6_ADDRSTRLEN+1];
memset(host,0,INET6_ADDRSTRLEN+1);
SECURE1("%s\n",inet_ntop(AF_INET6,(void *)
if(inet_ntop(AF_INET6,(void *)
&(((struct sockaddr_in6 *)addr)->
sin6_addr),host,INET6_ADDRSTRLEN));
sin6_addr),host,INET6_ADDRSTRLEN))
{
SECURE("%s\n",host);
}
else {
SECURE("error getting ipv6 address\n");
}
}
break;
#endif
case AF_UNIX:
SECURE0("local connection\n");
SECURE("local connection\n");
break;
default:
SECURE0("unknown\n");
SECURE("unknown\n");
}
openInterface(&(interfaces[i]),fd);
}
......@@ -198,7 +216,7 @@ int interfaceReadInput(Interface * interface) {
}
unblockSignals();
if(interface->bufferLength>=INTERFACE_MAX_BUFFER_LENGTH) {
ERROR1("interface %i: buffer overflow\n",
ERROR("interface %i: buffer overflow\n",
interface->num);
closeInterface(interface);
}
......@@ -219,9 +237,9 @@ int interfaceReadInput(Interface * interface) {
char ** argArray;
int argArrayLength;
argArrayLength = buffer2array((char *)node->data,&argArray);
DEBUG2("interface %i: process command \"%s\"\n",interface->num,node->data);
ret = processCommand(interface->fp,argArrayLength,argArray);
DEBUG2("interface %i: command returned %i\n",interface->num,ret);
DEBUG("interface %i: process command \"%s\"\n",interface->num,node->data);
ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray);
DEBUG("interface %i: command returned %i\n",interface->num,ret);
freeArgArray(argArray,argArrayLength);
node = node->nextNode;
if(ret!=0 ||
......@@ -245,7 +263,7 @@ int interfaceReadInput(Interface * interface) {
interface->commandListSize+=sizeof(ListNode);
interface->commandListSize+=strlen(interface->buffer)+1;
if(interface->commandListSize>interface_max_command_list_size) {
ERROR3("interface %i: command list size (%lli) is larger than the max (%lli)\n",interface->num,interface->commandListSize,interface_max_command_list_size);
ERROR("interface %i: command list size (%lli) is larger than the max (%lli)\n",interface->num,interface->commandListSize,interface_max_command_list_size);
closeInterface(interface);
}
......@@ -267,9 +285,9 @@ int interfaceReadInput(Interface * interface) {
ret = -1;
}
else {
DEBUG2("interface %i: process command \"%s\"\n",interface->num,interface->buffer);
ret = processCommand(interface->fp,argArrayLength,argArray);
DEBUG2("interface %i: command returned %i\n",interface->num,ret);
DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer);
ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray);
DEBUG("interface %i: command returned %i\n",interface->num,ret);
}
if(ret==0) {
myfprintf(interface->fp,"%s\n",COMMAND_RESPOND_OK);
......@@ -390,25 +408,25 @@ void initInterfaces() {
interface_timeout = strtol((getConf())[CONF_CONNECTION_TIMEOUT],&test,10);
if(*test!='\0' || interface_timeout<=0) {
ERROR1("connection timeout \"%s\" is not a positive integer\n",(getConf())[CONF_CONNECTION_TIMEOUT]);
ERROR("connection timeout \"%s\" is not a positive integer\n",(getConf())[CONF_CONNECTION_TIMEOUT]);
exit(-1);
}
interface_max_connections = strtol((getConf())[CONF_MAX_CONNECTIONS],&test,10);
if(*test!='\0' || interface_max_connections<=0) {
ERROR1("max connections \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_CONNECTIONS]);
ERROR("max connections \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_CONNECTIONS]);
exit(-1);
}
interface_max_command_list_size = strtoll((getConf())[CONF_MAX_COMMAND_LIST_SIZE],&test,10);
if(*test!='\0' || interface_max_command_list_size<=0) {
ERROR1("max command list size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_COMMAND_LIST_SIZE]);
ERROR("max command list size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_COMMAND_LIST_SIZE]);
exit(-1);
}
interface_max_output_buffer_size = strtoll((getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE],&test,10);
if(*test!='\0' || interface_max_output_buffer_size<=0) {
ERROR1("max output buffer size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE]);
ERROR("max output buffer size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE]);
exit(-1);
}
......@@ -446,7 +464,7 @@ void closeOldInterfaces() {
for(i=0;i<interface_max_connections;i++) {
if(interfaces[i].open && (interfaces[i].expired || (time(NULL)-interfaces[i].lastTime>interface_timeout))) {
DEBUG1("interface %i: timeout\n",i);
DEBUG("interface %i: timeout\n",i);
closeInterface(&(interfaces[i]));
}
}
......@@ -485,13 +503,13 @@ void flushInterfaceBuffer(Interface * interface) {
}
if(!interface->bufferList->firstNode) {
DEBUG1("interface %i: buffer empty\n",interface->num);
DEBUG("interface %i: buffer empty\n",interface->num);
freeList(interface->bufferList);
interface->bufferList = NULL;
}
else if(ret<0 && errno!=EAGAIN && errno!=EINTR) {
/* cause interface to close */
DEBUG1("interface %i: problems flushing buffer\n",
DEBUG("interface %i: problems flushing buffer\n",
interface->num);
freeList(interface->bufferList);
interface->bufferList = NULL;
......@@ -559,7 +577,7 @@ void printInterfaceOutBuffer(Interface * interface) {
if(interface->outputBufferSize>
interface_max_output_buffer_size)
{
ERROR3("interface %i: output buffer size (%lli) is "
ERROR("interface %i: output buffer size (%lli) is "
"larger than the max (%lli)\n",
interface->num,
interface->outputBufferSize,
......@@ -591,7 +609,7 @@ void printInterfaceOutBuffer(Interface * interface) {
(void *)buffer);
}
else {
DEBUG1("interface %i: problems writing\n",
DEBUG("interface %i: problems writing\n",
interface->num);
interface->expired = 1;
return;
......@@ -607,7 +625,7 @@ void printInterfaceOutBuffer(Interface * interface) {
}
/* if we needed to create buffer, initialize bufferSize info */
if(interface->bufferList) {
DEBUG1("interface %i: buffer created\n",interface->num);
DEBUG("interface %i: buffer created\n",interface->num);
interface->outputBufferSize = sizeof(List);
interface->outputBufferSize+=sizeof(ListNode);
interface->outputBufferSize+=strlen(
......
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 source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -24,12 +24,12 @@
extern "C" {
# endif
# define FPM_INTEL
# define FPM_DEFAULT
# define SIZEOF_INT 4
# define SIZEOF_LONG 4
# define SIZEOF_LONG 8
# define SIZEOF_LONG_LONG 8
......
......@@ -88,7 +88,7 @@ int establish(unsigned short port) {
else {
struct hostent * he;
if(!(he = gethostbyname((getConf())[CONF_BIND_TO_ADDRESS]))) {
ERROR1("can't lookup host \"%s\"\n",
ERROR("can't lookup host \"%s\"\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
exit(-1);
}
......@@ -96,7 +96,7 @@ int establish(unsigned short port) {
#ifdef HAVE_IPV6
case AF_INET6:
if(!ipv6Supported()) {
ERROR1("no IPv6 support, but a IPv6 address "
ERROR("no IPv6 support, but a IPv6 address "
"found for \"%s\"\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
exit(-1);
......@@ -114,7 +114,7 @@ int establish(unsigned short port) {
addrlen = sizeof(struct sockaddr_in);
break;
default:
ERROR1("address type for \"%s\" is not IPv4 or IPv6\n",
ERROR("address type for \"%s\" is not IPv4 or IPv6\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
exit(-1);
}
......@@ -133,12 +133,12 @@ int establish(unsigned short port) {
pf = PF_UNIX;
break;
default:
ERROR1("unknown address family: %i\n",addrp->sa_family);
ERROR("unknown address family: %i\n",addrp->sa_family);
return -1;
}
if((sock = socket(pf,SOCK_STREAM,0)) < 0) {
ERROR0("socket < 0\n");
ERROR("socket < 0\n");
return -1;
}
......@@ -146,12 +146,12 @@ int establish(unsigned short port) {
sizeof(allowReuse))<0)
{
close(sock);
ERROR0("problems setsockopt'ing\n");
ERROR("problems setsockopt'ing\n");
return -1;
}
if(bind(sock,addrp,addrlen)<0) {
ERROR1("unable to bind port %i, maybe MPD is still running?\n",
ERROR("unable to bind port %i, maybe MPD is still running?\n",
port);
close(sock);
return -1;
......@@ -159,7 +159,7 @@ int establish(unsigned short port) {
if(listen(sock,5)<0) {
close(sock);
ERROR0("problems listen'ing\n");
ERROR("problems listen'ing\n");
return -1;
}
......@@ -182,5 +182,5 @@ void getConnections(int sock) {
((fd = accept(sock,&sockAddr,&socklen)) >= 0)) {
openAInterface(fd,&sockAddr);
}
else if(fd<0) ERROR0("Problems accept()'ing\n");
else if(fd<0) ERROR("Problems accept()'ing\n");
}
......@@ -35,5 +35,5 @@ void initLog() {
else if(strcmp(getConf()[CONF_LOG_LEVEL],"verbose")==0) {
if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG;
}
else ERROR1("unknown log level \"%s\"\n",getConf()[CONF_LOG_LEVEL]);
else ERROR("unknown log level \"%s\"\n",getConf()[CONF_LOG_LEVEL]);
}
......@@ -27,21 +27,16 @@
extern int logLevel;
#define ERROR0(x) myfprintf(stderr,x);
#define ERROR1(x,a) myfprintf(stderr,x,a);
#define ERROR2(x,a,b) myfprintf(stderr,x,a,b);
#define ERROR3(x,a,b,c) myfprintf(stderr,x,a,b,c);
#define ERROR(x, arg...) myfprintf(stderr, x , ##arg)
#define LOG0(x) myfprintf(stdout,x);
#define LOG1(x,a) myfprintf(stdout,x,a);
#define LOG(x, arg...) myfprintf(stdout, x , ##arg)
#define SECURE0(x) if(logLevel>=LOG_LEVEL_SECURE) myfprintf(stdout,x);
#define SECURE1(x,a) if(logLevel>=LOG_LEVEL_SECURE) myfprintf(stdout,x,a);
#define SECURE2(x,a,b) if(logLevel>=LOG_LEVEL_SECURE) myfprintf(stdout,x,a,b);
#define SECURE(x, arg...) if(logLevel>=LOG_LEVEL_SECURE) \
myfprintf(stdout, x , ##arg)
#define DEBUG0(x) if(logLevel>=LOG_LEVEL_DEBUG) myfprintf(stdout,x);
#define DEBUG1(x,a) if(logLevel>=LOG_LEVEL_DEBUG) myfprintf(stdout,x,a);
#define DEBUG2(x,a,b) if(logLevel>=LOG_LEVEL_DEBUG) myfprintf(stdout,x,a,b);
#define DEBUG(x, arg...) if(logLevel>=LOG_LEVEL_DEBUG) \
myfprintf(stdout, x , ##arg)
void initLog();
......
......@@ -32,7 +32,7 @@
#include <stdlib.h>
char * dupAndStripPlaylistSuffix(char * file) {
int size = strlen(file)-strlen(PLAYLIST_FILE_SUFFIX)-1;
size_t size = strlen(file)-strlen(PLAYLIST_FILE_SUFFIX)-1;
char * ret = malloc(size+1);
strncpy(ret,file,size);
......@@ -41,45 +41,7 @@ char * dupAndStripPlaylistSuffix(char * file) {
return ret;
}
int ls(FILE * fp, char * dirname) {
DIR * dir;
char cwd[2];
char c;
struct stat st;
struct dirent * ent;
char s[MAXPATHLEN+1];
cwd[0] = '.';
cwd[1] = '\0';
if(dirname==NULL) dirname=cwd;
if((dir = opendir(rmp2amp(dirname)))==NULL) {
myfprintf(fp,"%s problems opening directory\n",COMMAND_RESPOND_ERROR);
return -1;
}
while((ent = readdir(dir))) {
if(ent->d_name[0]=='.') continue; /* hide hidden stuff */
sprintf(s,"%s/%s/%s",musicDir,dirname,ent->d_name);
if(stat(s,&st)==0) {
c = 0;
if(S_ISDIR(st.st_mode)) c = 'd';
else if(isMusic(s)) c = 'm';
if(c && dirname==cwd) {
myfprintf(fp,"%c \"%s\"\n",c,ent->d_name);
}
else if(c) {
myfprintf(fp,"%c \"%s/%s\"\n",c,dirname,ent->d_name);
}
}
}
closedir(dir);
return 0;
}
int lsPlaylists(FILE * fp, char * path) {
int lsPlaylists(FILE * fp, char * utf8path) {
DIR * dir;
struct stat st;
struct dirent * ent;
......@@ -87,15 +49,17 @@ int lsPlaylists(FILE * fp, char * path) {
char s[MAXPATHLEN+1];
List * list = NULL;
ListNode * node = NULL;
char * path = strdup(utf8ToFsCharset(utf8path));
char * actualPath = rpp2app(path);
int actlen = strlen(actualPath)+1;
int maxlen = MAXPATHLEN-actlen;
int suflen = strlen(PLAYLIST_FILE_SUFFIX)+1;
int suff;
if(actlen>MAXPATHLEN-1) return 0;
if((dir = opendir(actualPath))==NULL) return 0;
if(actlen>MAXPATHLEN-1 || (dir = opendir(actualPath))==NULL) {
free(path);
return 0;
}
s[MAXPATHLEN] = '\0';
strcpy(s,actualPath);
......@@ -114,7 +78,8 @@ int lsPlaylists(FILE * fp, char * path) {
if(list==NULL) list = makeList(NULL);
dup = strdup(ent->d_name);
dup[suff] = '\0';
insertInList(list,dup,NULL);
insertInList(list,
fsCharsetToUtf8(dup),NULL);
free(dup);
}
}
......@@ -122,12 +87,13 @@ int lsPlaylists(FILE * fp, char * path) {
}
closedir(dir);
free(path);
if(list) {
sortList(list);
dup = malloc(strlen(path)+2);
strcpy(dup,path);
dup = malloc(strlen(utf8path)+2);
strcpy(dup,utf8path);
while(dup[strlen(dup)-1]=='/') dup[strlen(dup)-1] = '\0';
if(strlen(dup)) strcat(dup,"/");
......@@ -144,27 +110,28 @@ int lsPlaylists(FILE * fp, char * path) {
return 0;
}
time_t isMusic(char * file) {
time_t isMusic(char * utf8file) {
time_t ret = 0;
#ifdef HAVE_OGG
if((ret = isOgg(file))) return ret;
if((ret = isOgg(utf8file))) return ret;
#endif
#ifdef HAVE_FLAC
if((ret = isFlac(file))) return ret;
if((ret = isFlac(utf8file))) return ret;
#endif
#ifdef HAVE_MAD
if((ret = isMp3(file))) return ret;
if((ret = isMp3(utf8file))) return ret;
#endif
#ifdef HAVE_AUDIOFILE
if((ret = isWave(file))) return ret;
if((ret = isWave(utf8file))) return ret;
#endif
return ret;
}
time_t isPlaylist(char * file) {
time_t isPlaylist(char * utf8file) {
struct stat st;
char * file = utf8ToFsCharset(utf8file);
char * actualFile = file;
char * temp = NULL;
......@@ -192,8 +159,9 @@ time_t isPlaylist(char * file) {
return 0;
}
time_t isWave(char * file) {
time_t isWave(char * utf8file) {
struct stat st;
char * file = utf8ToFsCharset(utf8file);
char * actualFile = file;
if(actualFile[0]!='/') actualFile = rmp2amp(file);
......@@ -219,8 +187,9 @@ time_t isWave(char * file) {
return 0;
}
time_t isFlac(char * file) {
time_t isFlac(char * utf8file) {
struct stat st;
char * file = utf8ToFsCharset(utf8file);
char * actualFile = file;
if(actualFile[0]!='/') actualFile = rmp2amp(file);
......@@ -246,8 +215,9 @@ time_t isFlac(char * file) {
return 0;
}
time_t isOgg(char * file) {
time_t isOgg(char * utf8file) {
struct stat st;
char * file = utf8ToFsCharset(utf8file);
char * actualFile = file;
if(actualFile[0]!='/') actualFile = rmp2amp(file);
......@@ -273,8 +243,9 @@ time_t isOgg(char * file) {
return 0;
}
time_t isMp3(char * file) {
time_t isMp3(char * utf8file) {
struct stat st;
char * file = utf8ToFsCharset(utf8file);
char * actualFile = file;
if(actualFile[0]!='/') actualFile = rmp2amp(file);
......@@ -300,12 +271,16 @@ time_t isMp3(char * file) {
return 0;
}
time_t isDir(char * name) {
time_t isDir(char * utf8name) {
struct stat st;
if(stat(rmp2amp(name),&st)==0) {
if(stat(rmp2amp(utf8ToFsCharset(utf8name)),&st)==0) {
if(S_ISDIR(st.st_mode)) return st.st_mtime;
}
else {
DEBUG("isDir: unable to stat: %s (%s)\n",utf8name,
rmp2amp(utf8ToFsCharset(utf8name)));
}
return 0;
}
......@@ -22,23 +22,21 @@
#include <stdio.h>
#include <time.h>
int ls(FILE * fp, char * dir);
int lsPlaylists(FILE * fp, char * utf8path);
int lsPlaylists(FILE * fp, char * path);
time_t isMp3(char * utf8file);
time_t isMp3(char * file);
time_t isOgg(char * utf8file);
time_t isOgg(char * file);
time_t isFlac(char * utf8file);
time_t isFlac(char * file);
time_t isWave(char * utf8file);
time_t isWave(char * file);
time_t isMusic(char * utf8file);
time_t isMusic(char * file);
time_t isDir(char * utf8name);
time_t isDir(char * name);
time_t isPlaylist(char * file);
time_t isPlaylist(char * utf8file);
char * dupAndStripPlaylistSuffix(char * file);
......
......@@ -19,6 +19,7 @@
#ifdef HAVE_MAD
#include "mp3_decode.h"
#include "pcm_utils.h"
#ifdef USE_MPD_MAD
#include "libmad/mad.h"
#else
......@@ -184,7 +185,7 @@ int decodeNextFrameHeader(mp3DecodeData * data) {
if((data->stream).error==MAD_ERROR_BUFLEN) return DECODE_CONT;
else
{
ERROR1("unrecoverable frame level error "
ERROR("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
data->flush = 0;
......@@ -208,7 +209,7 @@ int decodeNextFrame(mp3DecodeData * data) {
if((data->stream).error==MAD_ERROR_BUFLEN) return DECODE_CONT;
else
{
ERROR1("unrecoverable frame level error "
ERROR("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
data->flush = 0;
......@@ -344,7 +345,7 @@ int getMp3TotalTime(char * file) {
int openMp3(char * file, mp3DecodeData * data) {
if((data->fp = fopen(file,"r"))<=0) {
ERROR1("problems opening \"%s\"\n",file);
ERROR("problems opening \"%s\"\n",file);
return -1;
}
initMp3DecodeData(data);
......@@ -364,13 +365,16 @@ int mp3ChildSendData(mp3DecodeData * data, Buffer * cb, DecoderControl * dc) {
if(dc->seek) return 0;
/* be sure to remove this! */
memcpy(cb->chunks[cb->end],data->outputBuffer,CHUNK_SIZE);
#ifdef WORDS_BIGENDIAN
pcm_changeBufferEndianness(data->outputBuffer,CHUNK_SIZE,16);
#endif
memcpy(cb->chunks+cb->end*CHUNK_SIZE,data->outputBuffer,CHUNK_SIZE);
cb->chunkSize[cb->end] = data->outputPtr-data->outputBuffer;
cb->bitRate[cb->end] = data->bitRate/1000;
cb->times[cb->end] = data->elapsedTime;
cb->end++;
if(cb->end>=BUFFERED_CHUNKS) {
if(cb->end>=buffered_chunks) {
cb->end = 0;
cb->wrap = 1;
}
......@@ -475,9 +479,9 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) {
int mp3_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc) {
mp3DecodeData data;
if(openMp3(dc->file,&data) < 0) {
ERROR0("Input does not appear to be a mp3 bit stream.\n");
ERROR("Input does not appear to be a mp3 bit stream.\n");
return -1;
}
......
/* the Music Player Daemon (MPD)
* (c)2003-2004 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 MPD_TYPES_H
#define MPD_TYPES_H
typedef unsigned char mpd_uint8;
typedef signed char mpd_sint8;
#if SIZEOF_SHORT == 2
typedef unsigned short mpd_uint16;
typedef signed short mpd_sint16;
#elif SIZEOF_INT == 2
typedef unsigned int mpd_uint16;
typedef signed int mpd_sint16;
#endif
#if SIZEOF_INT == 4
typedef unsigned int mpd_uint32;
typedef signed int mpd_sint32;
#elif SIZEOF_LONG == 4
typedef unsigned long mpd_uint32;
typedef signed long mpd_sint32;
#endif
#endif
......@@ -18,10 +18,12 @@
#ifdef HAVE_OGG
#include "ogg_decode.h"
#include "command.h"
#include "utils.h"
#include "audio.h"
#include "log.h"
#include "pcm_utils.h"
#include <stdio.h>
#include <unistd.h>
......@@ -35,12 +37,12 @@ int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
FILE * oggfp;
if(!(oggfp = fopen(dc->file,"r"))) {
ERROR0("failed to open ogg\n");
ERROR("failed to open ogg\n");
return -1;
}
if(ov_open(oggfp, &vf, NULL, 0) < 0) {
ERROR0("Input does not appear to be an Ogg bit stream.\n");
ERROR("Input does not appear to be an Ogg bit stream.\n");
fclose(oggfp);
return -1;
}
......@@ -82,7 +84,12 @@ int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
}
if(dc->stop) break;
else if(dc->seek) continue;
memcpy(cb->chunks[cb->end],chunk,CHUNK_SIZE);
#ifdef WORDS_BIGENDIAN
pcm_changeBufferEndianness(chunk,CHUNK_SIZE,
af->bits);
#endif
memcpy(cb->chunks+cb->end*CHUNK_SIZE,
chunk,CHUNK_SIZE);
cb->chunkSize[cb->end] = ret;
cb->times[cb->end] = ov_time_tell(&vf);
if((test = ov_bitrate_instant(&vf))>0) {
......@@ -90,7 +97,7 @@ int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
}
cb->bitRate[cb->end] = bitRate;
cb->end++;
if(cb->end>=BUFFERED_CHUNKS) {
if(cb->end>=buffered_chunks) {
cb->end = 0;
cb->wrap = 1;
}
......
......@@ -17,18 +17,124 @@
*/
#include "path.h"
#include "log.h"
#include "charConv.h"
#include "conf.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_LOCALE
#ifdef HAVE_LANGINFO
#include <locale.h>
#include <langinfo.h>
#endif
#endif
char musicDir[MAXPATHLEN+1];
char playlistDir[MAXPATHLEN+1];
char * fsCharset = NULL;
char * pathConvCharset(char * to, char * from, char * str, char * ret) {
if(ret) {
free(ret);
ret = NULL;
}
if(setCharSetConversion(to,from)==0) {
ret = convStrDup(str);
}
if(!ret) ret = strdup(str);
return ret;
}
char * fsCharsetToUtf8(char * str) {
static char * ret = NULL;
return ret = pathConvCharset("UTF-8",fsCharset,str,ret);
}
char * utf8ToFsCharset(char * str) {
static char * ret = NULL;
return ret = pathConvCharset(fsCharset,"UTF-8",str,ret);
}
void setFsCharset(char * charset) {
if(fsCharset) free(fsCharset);
fsCharset = strdup(charset);
DEBUG("setFsCharset: fs charset is: %s\n",fsCharset);
if(setCharSetConversion("UTF-8",fsCharset)!=0) {
ERROR("fs charset conversion problem: "
"not able to convert from \"%s\" to \"%s\"\n",
fsCharset,"UTF-8");
}
if(setCharSetConversion(fsCharset,"UTF-8")!=0) {
ERROR("fs charset conversion problem: "
"not able to convert from \"%s\" to \"%s\"\n",
"UTF-8",fsCharset);
}
}
char * getFsCharset() {
return fsCharset;
}
void initPaths() {
#ifdef HAVE_LOCALE
#ifdef HAVE_LANGINFO
char * originalLocale;
#endif
#endif
char * charset = NULL;
if(getConf()[CONF_FS_CHARSET]) {
charset = strdup(getConf()[CONF_FS_CHARSET]);
}
#ifdef HAVE_LOCALE
#ifdef HAVE_LANGINFO
else if((originalLocale = setlocale(LC_ALL,""))) {
char * temp;
if((temp = nl_langinfo(CODESET))) {
charset = strdup(temp);
}
else ERROR("problems getting charset for locale\n");
if(!setlocale(LC_ALL,originalLocale)) {
ERROR("problems resetting locale with setlocale()\n");
}
}
#endif
#endif
else ERROR("problems getting locale with setlocale()\n");
if(charset) {
setFsCharset(charset);
free(charset);
}
else {
ERROR("setting filesystem charset to UTF-8\n");
setFsCharset("UTF-8");
}
}
void finishPaths() {
free(fsCharset);
fsCharset = NULL;
}
char * rmp2amp(char * relativePath) {
static char absolutePath[MAXPATHLEN+1];
memset(absolutePath,0,MAXPATHLEN+1);
strcpy(absolutePath,musicDir);
strncpy(absolutePath,musicDir,MAXPATHLEN);
strncat(absolutePath,relativePath,MAXPATHLEN-strlen(musicDir));
return absolutePath;
......@@ -39,7 +145,7 @@ char * rpp2app(char * relativePath) {
memset(absolutePath,0,MAXPATHLEN+1);
strcpy(absolutePath,playlistDir);
strncpy(absolutePath,playlistDir,MAXPATHLEN);
strncat(absolutePath,relativePath,MAXPATHLEN-strlen(musicDir));
return absolutePath;
......
......@@ -24,6 +24,18 @@
extern char musicDir[MAXPATHLEN+1];
extern char playlistDir[MAXPATHLEN+1];
void initPaths();
void finishPaths();
char * utf8ToFsCharset(char * str);
char * fsCharsetToUtf8(char * str);
void setFsCharset(char * charset);
char * getFsCharset();
/* relative music path to absolute music path
* char * passed is a static variable, so don't free it
*/
......
/* the Music Player Daemon (MPD)
* (c)2003-2004 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 "pcm_utils.h"
#include "mpd_types.h"
#include "log.h"
#include <string.h>
#include <math.h>
void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits) {
char temp;
switch(bits) {
case 16:
while(bufferSize) {
temp = *buffer;
*buffer = *(buffer+1);
*(buffer+1) = temp;
bufferSize-=2;
}
break;
}
}
void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
int volume)
{
mpd_sint32 temp32;
mpd_sint8 * buffer8 = (mpd_sint8 *)buffer;
mpd_sint16 * buffer16 = (mpd_sint16 *)buffer;
if(volume>=100) return;
if(volume<=0) {
memset(buffer,0,bufferSize);
return;
}
switch(format->bits) {
case 16:
while(bufferSize>0) {
temp32 = *buffer16;
temp32*= volume;
temp32/=100;
*buffer16 = temp32>32767 ? 32767 :
(temp32<-32768 ? -32768 : temp32);
buffer16++;
bufferSize-=2;
}
break;
case 8:
while(bufferSize>0) {
temp32 = *buffer8;
temp32*= volume;
temp32/=100;
*buffer8 = temp32>127 ? 127 :
(temp32<-128 ? -128 : temp32);
buffer8++;
bufferSize--;
}
break;
default:
ERROR("%i bits not supported by pcm_volumeChange!\n",
format->bits);
exit(-1);
}
}
void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format)
{
mpd_sint32 temp32;
mpd_sint8 * buffer8_1 = (mpd_sint8 *)buffer1;
mpd_sint8 * buffer8_2 = (mpd_sint8 *)buffer2;
mpd_sint16 * buffer16_1 = (mpd_sint16 *)buffer1;
mpd_sint16 * buffer16_2 = (mpd_sint16 *)buffer2;
switch(format->bits) {
case 16:
while(bufferSize1>0 && bufferSize2>0) {
temp32 = *buffer16_1;
temp32+= *buffer16_2;
*buffer16_1 = temp32>32767 ? 32767 :
(temp32<-32768 ? -32768 : temp32);
buffer16_1++;
buffer16_2++;
bufferSize1-=2;
bufferSize2-=2;
}
if(bufferSize2>0) memcpy(buffer8_1,buffer8_2,bufferSize2);
break;
case 8:
while(bufferSize1>0 && bufferSize2>0) {
temp32 = *buffer8_1;
temp32+= *buffer8_2;
*buffer8_1 = temp32>127 ? 127 :
(temp32<-128 ? -128 : temp32);
buffer8_1++;
buffer8_2++;
bufferSize1--;
bufferSize2--;
}
if(bufferSize2>0) memcpy(buffer8_1,buffer8_2,bufferSize2);
break;
default:
ERROR("%i bits not supported by pcm_add!\n",format->bits);
exit(-1);
}
}
void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1)
{
float s = sin(M_PI_2*portion1);
s*=s;
pcm_volumeChange(buffer1,bufferSize1,format,(int)(s*100));
pcm_volumeChange(buffer2,bufferSize2,format,(int)((1-s)*100));
pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,format);
}
/* the Music Player Daemon (MPD)
* (c)2003-2004 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 PCM_UTILS_H
#define PMC_UTILS_H
#include "audio.h"
#include <stdlib.h>
void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits);
void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
int volume);
void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1,
size_t bufferSize2, AudioFormat * format, float portion1);
#endif
/* the Music Player Daemon (MPD)
* (c)2003-2004 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 "permission.h"
#include "conf.h"
#include "list.h"
#include "log.h"
#include <string.h>
#define PERMISSION_PASSWORD_CHAR "@"
#define PERMISSION_SEPERATOR ","
#define PERMISSION_READ_STRING "read"
#define PERMISSION_ADD_STRING "add"
#define PERMISSION_CONTROL_STRING "control"
#define PERMISSION_ADMIN_STRING "admin"
List * permission_passwords;
unsigned int permission_default;
unsigned int parsePermissions(char * string) {
unsigned int permission = 0;
char * temp;
char * tok;
if(!string) return 0;
temp = strtok_r(string,PERMISSION_SEPERATOR,&tok);
while(temp) {
if(strcmp(temp,PERMISSION_READ_STRING)==0) {
permission |= PERMISSION_READ;
}
else if(strcmp(temp,PERMISSION_ADD_STRING)==0) {
permission |= PERMISSION_ADD;
}
else if(strcmp(temp,PERMISSION_CONTROL_STRING)==0) {
permission |= PERMISSION_CONTROL;
}
else if(strcmp(temp,PERMISSION_ADMIN_STRING)==0) {
permission |= PERMISSION_ADMIN;
}
else {
ERROR("uknown permission \"%s\"\n",temp);
exit(-1);
}
temp = strtok_r(NULL,PERMISSION_SEPERATOR,&tok);
}
return permission;
}
void initPermissions() {
permission_passwords = makeList(free);
char * passwordSets;
char * nextSet;
char * temp;
char * cp1;
char * cp2;
char * password;
unsigned int * permission;
permission_default = PERMISSION_READ | PERMISSION_ADD |
PERMISSION_CONTROL | PERMISSION_ADMIN;
if(getConf()[CONF_DEFAULT_PERMISSIONS]) {
permission_default = parsePermissions(
getConf()[CONF_DEFAULT_PERMISSIONS]);
}
if(!getConf()[CONF_PASSWORD]) return;
if(!getConf()[CONF_DEFAULT_PERMISSIONS]) permission_default = 0;
passwordSets = strdup(getConf()[CONF_PASSWORD]);
nextSet = strtok_r(passwordSets,CONF_CAT_CHAR,&cp1);
while(nextSet && strlen(nextSet)) {
if(!strstr(nextSet,PERMISSION_PASSWORD_CHAR)) {
ERROR("\"%s\" not found in password string \"%s\"\n",
PERMISSION_PASSWORD_CHAR,
nextSet);
exit(-1);
}
if(!(temp = strtok_r(nextSet,PERMISSION_PASSWORD_CHAR,&cp2))) {
ERROR("something weird just happend in permission.c\n");
exit(-1);
}
password = temp;
permission = malloc(sizeof(unsigned int));
*permission = parsePermissions(strtok_r(NULL,"",&cp2));
insertInList(permission_passwords,password,permission);
nextSet = strtok_r(NULL,CONF_CAT_CHAR,&cp1);
}
sortList(permission_passwords);
free(passwordSets);
}
int getPermissionFromPassword(char * password, unsigned int * permission) {
void * foundPermission;
if(findInList(permission_passwords,password,&foundPermission)) {
*permission = *((unsigned int *)foundPermission);
return 0;
}
return -1;
}
void finishPermissions() {
freeList(permission_passwords);
}
unsigned int getDefaultPermissions() {
return permission_default;
}
/* the Music Player Daemon (MPD)
* (c)2003-2004 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 PERMISSION_H
#define PERMISSION_H
#define PERMISSION_READ 1
#define PERMISSION_ADD 2
#define PERMISSION_CONTROL 4
#define PERMISSION_ADMIN 8
void initPermissions();
int getPermissionFromPassword(char * password, unsigned int * permission);
void finishPermissions();
unsigned int getDefaultPermissions();
#endif
......@@ -30,7 +30,7 @@
#include "directory.h"
#include "volume.h"
#include "playerData.h"
#include "char_conv.h"
#include "permission.h"
#include <stdio.h>
#include <sys/types.h>
......@@ -44,13 +44,12 @@
#include <errno.h>
#include <fcntl.h>
#define MAX_BUFFER_LENGTH 1024
#define INPUT_BUFFER_SIZE 2*MAXPATHLEN
int player_pid = 0;
int player_termSent = 0;
void resetPlayer() {
int pid;
player_pid = 0;
player_termSent = 0;
getPlayerData()->playerControl.stop = 0;
......@@ -59,21 +58,37 @@ void resetPlayer() {
getPlayerData()->playerControl.lockQueue = 0;
getPlayerData()->playerControl.unlockQueue = 0;
getPlayerData()->playerControl.state = PLAYER_STATE_STOP;
getPlayerData()->playerControl.state = PLAYER_QUEUE_UNLOCKED;
getPlayerData()->playerControl.queueState = PLAYER_QUEUE_UNLOCKED;
getPlayerData()->playerControl.seek = 0;
/* kill decode process if it got left running */
pid = getPlayerData()->playerControl.decode_pid;
if(pid>0) kill(pid,SIGTERM);
getPlayerData()->playerControl.decode_pid = 0;
}
void player_sigHandler(int signal) {
if(signal==SIGCHLD) {
int status;
if(player_pid==wait3(&status,WNOHANG,NULL)) {
int pid = wait3(&status,WNOHANG,NULL);
if(player_pid==pid) {
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR1("player process died from a "
ERROR("player process died from a "
"non-TERM signal: %i\n",
WTERMSIG(status));
}
resetPlayer();
}
else if(pid==getPlayerData()->playerControl.decode_pid &&
player_pid<=0)
{
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR("(caught by master parent) "
"decode process died from a "
"non-TERM signal: %i\n",
WTERMSIG(status));
}
getPlayerData()->playerControl.decode_pid = 0;
}
}
}
......@@ -97,8 +112,10 @@ int playerInit() {
freeAllInterfaces();
closeMp3Directory();
closeTables();
finishPaths();
finishPermissions();
finishCommands();
finishVolume();
closeCharSetConversion();
while(1) {
if(pc->play) decode();
......@@ -123,7 +140,7 @@ int playerInit() {
exit(0);
}
else if(player_pid<0) {
ERROR0("player Problems fork()'ing\n");
ERROR("player Problems fork()'ing\n");
player_pid = 0;
return -1;
......@@ -132,7 +149,7 @@ int playerInit() {
return 0;
}
int playerPlay(FILE * fp, char * file) {
int playerPlay(FILE * fp, char * utf8file) {
PlayerControl * pc = &(getPlayerData()->playerControl);
if(fp==NULL) fp = stderr;
......@@ -140,8 +157,8 @@ int playerPlay(FILE * fp, char * file) {
{
struct stat st;
if(stat(rmp2amp(file),&st)<0) {
strcpy(pc->erroredFile,pc->file);
if(stat(rmp2amp(utf8ToFsCharset(utf8file)),&st)<0) {
strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
pc->error = PLAYER_ERROR_FILENOTFOUND;
return 0;
}
......@@ -149,24 +166,24 @@ int playerPlay(FILE * fp, char * file) {
if(0);
#ifdef HAVE_MAD
else if(isMp3(file)) pc->decodeType = DECODE_TYPE_MP3;
else if(isMp3(utf8file)) pc->decodeType = DECODE_TYPE_MP3;
#endif
#ifdef HAVE_OGG
else if(isOgg(file)) pc->decodeType = DECODE_TYPE_OGG;
else if(isOgg(utf8file)) pc->decodeType = DECODE_TYPE_OGG;
#endif
#ifdef HAVE_FLAC
else if(isFlac(file)) pc->decodeType = DECODE_TYPE_FLAC;
else if(isFlac(utf8file)) pc->decodeType = DECODE_TYPE_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
else if(isWave(file)) pc->decodeType = DECODE_TYPE_AUDIOFILE;
else if(isWave(utf8file)) pc->decodeType = DECODE_TYPE_AUDIOFILE;
#endif
else {
strcpy(pc->erroredFile,pc->file);
strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
pc->error = PLAYER_ERROR_UNKTYPE;
return 0;
}
strcpy(pc->file,rmp2amp(file));
strncpy(pc->file,rmp2amp(utf8ToFsCharset(utf8file)),MAXPATHLEN);
pc->play = 1;
if(player_pid==0 && playerInit()<0) {
......@@ -216,6 +233,23 @@ int playerPause(FILE * fp) {
return 0;
}
int playerSetPause(FILE * fp, int pause) {
PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid<=0) return 0;
switch(pc->state) {
case PLAYER_STATE_PLAY:
if(pause) playerPause(fp);
break;
case PLAYER_STATE_PAUSE:
if(!pause) playerPause(fp);
break;
}
return 0;
}
int getPlayerElapsedTime() {
return (int)(getPlayerData()->playerControl.elapsedTime+0.5);
}
......@@ -275,24 +309,26 @@ void playerCloseAudio() {
}
}
int queueSong(char * file) {
int queueSong(char * utf8file) {
PlayerControl * pc = &(getPlayerData()->playerControl);
if(pc->queueState==PLAYER_QUEUE_BLANK) {
strcpy(pc->file,rmp2amp(file));
strncpy(pc->file,rmp2amp(utf8ToFsCharset(utf8file)),MAXPATHLEN);
if(0);
#ifdef HAVE_MAD
else if(isMp3(file)) pc->decodeType = DECODE_TYPE_MP3;
else if(isMp3(utf8file)) pc->decodeType = DECODE_TYPE_MP3;
#endif
#ifdef HAVE_OGG
else if(isOgg(file)) pc->decodeType = DECODE_TYPE_OGG;
else if(isOgg(utf8file)) pc->decodeType = DECODE_TYPE_OGG;
#endif
#ifdef HAVE_FLAC
else if(isFlac(file)) pc->decodeType = DECODE_TYPE_FLAC;
else if(isFlac(utf8file)) pc->decodeType = DECODE_TYPE_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
else if(isWave(file)) pc->decodeType = DECODE_TYPE_AUDIOFILE;
else if(isWave(utf8file)) {
pc->decodeType = DECODE_TYPE_AUDIOFILE;
}
#endif
else return -1;
pc->queueState = PLAYER_QUEUE_FULL;
......@@ -334,8 +370,9 @@ void playerQueueUnlock() {
}
}
int playerSeek(FILE * fp, char * file, float time) {
int playerSeek(FILE * fp, char * utf8file, float time) {
PlayerControl * pc = &(getPlayerData()->playerControl);
char * file;
if(pc->state==PLAYER_STATE_STOP) {
myfprintf(fp,"%s player not currently playing\n",
......@@ -343,7 +380,8 @@ int playerSeek(FILE * fp, char * file, float time) {
return -1;
}
if(strcmp(pc->file,rmp2amp(file))!=0) strcpy(pc->file,rmp2amp(file));
file = rmp2amp(utf8ToFsCharset(utf8file));
if(strcmp(pc->file,file)!=0) strncpy(pc->file,file,MAXPATHLEN);
/*if(playerStop(fp)<0) return -1;
if(playerPlay(stderr,file)<0) return -1;*/
/*}*/
......@@ -356,3 +394,59 @@ int playerSeek(FILE * fp, char * file, float time) {
return 0;
}
float getPlayerCrossFade() {
PlayerControl * pc = &(getPlayerData()->playerControl);
return pc->crossFade;
}
void setPlayerCrossFade(float crossFadeInSeconds) {
if(crossFadeInSeconds<0) crossFadeInSeconds = 0;
PlayerControl * pc = &(getPlayerData()->playerControl);
pc->crossFade = crossFadeInSeconds;
}
void setPlayerSoftwareVolume(int volume) {
volume = (volume>100) ? 100 : (volume<0 ? 0 : volume);
PlayerControl * pc = &(getPlayerData()->playerControl);
pc->softwareVolume = volume;
}
int getPlayerSoftwareVolume() {
PlayerControl * pc = &(getPlayerData()->playerControl);
return pc->softwareVolume;
}
double getPlayerTotalPlayTime() {
PlayerControl * pc = &(getPlayerData()->playerControl);
if(pc->state==PLAYER_STATE_STOP) {
return pc->totalPlayTime;
}
return pc->totalPlayTime+pc->elapsedTime-pc->beginTime;
}
unsigned int getPlayerSampleRate() {
PlayerControl * pc = &(getPlayerData()->playerControl);
return pc->sampleRate;
}
int getPlayerBits() {
PlayerControl * pc = &(getPlayerData()->playerControl);
return pc->bits;
}
int getPlayerChannels() {
PlayerControl * pc = &(getPlayerData()->playerControl);
return pc->channels;
}
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