Commit c0a444d7 authored by Led's avatar Led

0.9.3-rc1

parent 4e533633
Developer -> Warren Dukes <shank@mercury.chem.pitt.edu>
Developer -> tw-nym
wave File Support -> normalperson
setuid patch -> Nagilum
'next' and 'previous' patch -> Niklas Hofer
ver 0.9.3 (2003/10/31)
1) Store total time/length of songs in db and display in *info commands
2) Display instantaneous bitrate in status command
3) Add Wave Support using libaudiofile (Patch from normalperson)
4) Command code cleanup (Patch from tw-nym)
5) Optimize listing of playlists (10-100x faster)
6) Optimize interface output (write in 4kB chunks instead of on every '\n')
7) Fix bug that prevented rm command from working
8) Fix bug where deleting current song skips the next song
ver 0.9.2 (2003/10/6)
1) Fix FreeBSD Compilation Problems
2) Fix bug in move command
......
......@@ -70,6 +70,9 @@ 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@
......@@ -125,9 +128,10 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
uninstall-info-recursive all-recursive install-data-recursive \
install-exec-recursive installdirs-recursive install-recursive \
uninstall-recursive check-recursive installcheck-recursive
DIST_COMMON = README COPYING ChangeLog INSTALL Makefile.am Makefile.in \
TODO aclocal.m4 config.guess config.sub configure configure.in \
depcomp install-sh ltmain.sh missing mkinstalldirs
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
Makefile.in TODO aclocal.m4 compile config.guess config.sub \
configure configure.in depcomp install-sh ltmain.sh missing \
mkinstalldirs
DIST_SUBDIRS = $(SUBDIRS)
all: all-recursive
......
Music Player Daemon (MPD) - UPGRADING
Upgrading to 0.9.x
Upgrading to 0.9.3
------------------
Wave support was added, so to have your wave files added, update the db (mpc
update).
Also, song lengths are now stored in the db. To get this stuff
added to the db, you will need to recreate the db from scratch. To do this,
run mpd with the "--create-db" commandline option.
Upgrading to 0.9.0
------------------
The "stop_on_error" config parameter was removed, so be sure to remove this
......
......@@ -7116,3 +7116,183 @@ int main ()
rm -f conf.libFLACtest
])
# Configure paths for the Audio File Library
# Bertrand Guiheneuf 98-10-21
# stolen from esd.m4 in esound :
# Manish Singh 98-9-30
# stolen back from Frank Belew
# stolen from Manish Singh
# Shamelessly stolen from Owen Taylor
dnl AM_PATH_AUDIOFILE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for Audio File Library, and define AUDIOFILE_CFLAGS and AUDIOFILE_LIBS.
dnl
AC_DEFUN(AM_PATH_AUDIOFILE,
[dnl
dnl Get compiler flags and libraries from the audiofile-config script.
dnl
AC_ARG_WITH(audiofile-prefix,[ --with-audiofile-prefix=PFX Prefix where Audio File Library is installed (optional)],
audiofile_prefix="$withval", audiofile_prefix="")
AC_ARG_WITH(audiofile-exec-prefix,[ --with-audiofile-exec-prefix=PFX Exec prefix where Audio File Library is installed (optional)],
audiofile_exec_prefix="$withval", audiofile_exec_prefix="")
AC_ARG_ENABLE(audiofiletest, [ --disable-audiofiletest Do not try to compile and run a test Audio File Library program], , enable_audiofiletest=yes)
if test x$audiofile_exec_prefix != x ; then
audiofile_args="$audiofile_args --exec-prefix=$audiofile_exec_prefix"
if test x${AUDIOFILE_CONFIG+set} != xset ; then
AUDIOFILE_CONFIG=$audiofile_exec_prefix/bin/audiofile-config
fi
fi
if test x$audiofile_prefix != x ; then
audiofile_args="$audiofile_args --prefix=$audiofile_prefix"
if test x${AUDIOFILE_CONFIG+set} != xset ; then
AUDIOFILE_CONFIG=$audiofile_prefix/bin/audiofile-config
fi
fi
AC_PATH_PROG(AUDIOFILE_CONFIG, audiofile-config, no)
min_audiofile_version=ifelse([$1], ,0.2.5,$1)
AC_MSG_CHECKING(for Audio File Library - version >= $min_audiofile_version)
no_audiofile=""
if test "$AUDIOFILE_CONFIG" = "no" ; then
no_audiofile=yes
else
AUDIOFILE_LIBS=`$AUDIOFILE_CONFIG $audiofileconf_args --libs`
AUDIOFILE_CFLAGS=`$AUDIOFILE_CONFIG $audiofileconf_args --cflags`
audiofile_major_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
audiofile_minor_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
audiofile_micro_version=`$AUDIOFILE_CONFIG $audiofile_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_audiofiletest" = "xyes" ; then
AC_LANG_SAVE
AC_LANG_C
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
LIBS="$LIBS $AUDIOFILE_LIBS"
dnl
dnl Now check if the installed Audio File Library is sufficiently new.
dnl (Also checks the sanity of the results of audiofile-config to some extent.)
dnl
rm -f conf.audiofiletest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <audiofile.h>
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
int main ()
{
int major, minor, micro;
char *tmp_version;
system ("touch conf.audiofiletest");
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_audiofile_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_audiofile_version");
exit(1);
}
if (($audiofile_major_version > major) ||
(($audiofile_major_version == major) && ($audiofile_minor_version > minor)) ||
(($audiofile_major_version == major) && ($audiofile_minor_version == minor) && ($audiofile_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'audiofile-config --version' returned %d.%d.%d, but the minimum version\n", $audiofile_major_version, $audiofile_minor_version, $audiofile_micro_version);
printf("*** of the Audio File Library required is %d.%d.%d. If audiofile-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If audiofile-config was wrong, set the environment variable AUDIOFILE_CONFIG\n");
printf("*** to point to the correct copy of audiofile-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
],, no_audiofile=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
AC_LANG_RESTORE
fi
fi
if test "x$no_audiofile" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$AUDIOFILE_CONFIG" = "no" ; then
cat <<END
*** The audiofile-config script installed by the Audio File Library could
*** not be found. If the Audio File Library was installed in PREFIX, make
*** sure PREFIX/bin is in your path, or set the AUDIOFILE_CONFIG
*** environment variable to the full path to audiofile-config.
END
else
if test -f conf.audiofiletest ; then
:
else
echo "*** Could not run Audio File Library test program; checking why..."
AC_LANG_SAVE
AC_LANG_C
CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
LIBS="$LIBS $AUDIOFILE_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <audiofile.h>
], [ return 0; ],
[ cat <<END
*** The test program compiled, but did not run. This usually means that
*** the run-time linker is not finding Audio File Library or finding the
*** wrong version of Audio File Library.
***
*** If it is not finding Audio File Library, you'll need to set your
*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point
*** to the installed location. Also, make sure you have run ldconfig if
*** that is required on your system.
***
*** If you have an old version installed, it is best to remove it, although
*** you may also be able to get things to work by modifying
*** LD_LIBRARY_PATH.
END
],
[ echo "*** The test program failed to compile or link. See the file config.log"
echo "*** for the exact error that occured. This usually means the Audio File"
echo "*** Library was incorrectly installed or that you have moved the Audio"
echo "*** File Library since it was installed. In the latter case, you may want"
echo "*** to edit the audiofile-config script: $AUDIOFILE_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
AC_LANG_RESTORE
fi
fi
AUDIOFILE_CFLAGS=""
AUDIOFILE_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(AUDIOFILE_CFLAGS)
AC_SUBST(AUDIOFILE_LIBS)
rm -f conf.audiofiletest
])
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
# Copyright 1999, 2000 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Usage:
# compile PROGRAM [ARGS]...
# `-o FOO.o' is removed from the args passed to the actual compile.
prog=$1
shift
ofile=
cfile=
args=
while test $# -gt 0; do
case "$1" in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we do something ugly here.
ofile=$2
shift
case "$ofile" in
*.o | *.obj)
;;
*)
args="$args -o $ofile"
ofile=
;;
esac
;;
*.c)
cfile=$1
args="$args $1"
;;
*)
args="$args $1"
;;
esac
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$prog" $args
fi
# Name of file we expect compiler to create.
cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir $lockdir > /dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir $lockdir; exit 1" 1 2 15
# Run the compile.
"$prog" $args
status=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
fi
rmdir $lockdir
exit $status
......@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
timestamp='2003-07-02'
timestamp='2003-10-07'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
......@@ -734,7 +734,7 @@ EOF
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
*:UNICOS/mp:*:*)
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
......@@ -751,7 +751,7 @@ EOF
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
*:FreeBSD:*:*)
# Determine whether the default compiler uses glibc.
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
......@@ -763,7 +763,7 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
# GNU/FreeBSD systems have a "k" prefix to indicate we are using
# GNU/KFreeBSD systems have a "k" prefix to indicate we are using
# FreeBSD's kernel, but not the complete OS.
case ${LIBC} in gnu) kernel_only='k' ;; esac
echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
......@@ -799,8 +799,13 @@ EOF
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
exit 0 ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit 0 ;;
......@@ -948,6 +953,9 @@ EOF
LIBC=gnuaout
#endif
#endif
#ifdef __dietlibc__
LIBC=dietlibc
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
......@@ -1049,7 +1057,7 @@ EOF
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
......@@ -1164,7 +1172,7 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
*:NonStop-UX:*:*)
......
......@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
timestamp='2003-07-17'
timestamp='2003-10-07'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
......@@ -118,7 +118,7 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
......@@ -248,6 +248,7 @@ case $basic_machine in
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
......@@ -320,6 +321,7 @@ case $basic_machine in
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
......@@ -1129,7 +1131,7 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
......@@ -1165,6 +1167,9 @@ case $os in
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
......
AC_INIT(src/main.c)
AM_INIT_AUTOMAKE(mpd, 0.9.2)
AM_INIT_AUTOMAKE(mpd, 0.9.3)
AC_PROG_CC
AC_PROG_INSTALL
......@@ -19,9 +19,11 @@ AC_SUBST(MPD_CFLAGS)
MPD_CFLAGS="-Wall"
MPD_LIBS=""
AC_ARG_ENABLE(ogg,[ --disable-iconv disable iconv support],,enable_iconv=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)
AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support],,enable_audiofile=yes)
AC_ARG_ENABLE(mpd_mad,[ --enable-mpd-mad use mpd libmad],use_mpd_mad=yes,)
AC_ARG_ENABLE(id3,[ --disable-id3 disable id3 support],,enable_id3=yes)
AC_ARG_ENABLE(mpd_id3tag,[ --enable-mpd-id3tag use mpd libid3tag],use_mpd_id3tag=yes,)
......@@ -37,6 +39,10 @@ AC_ARG_WITH(mad-includes,[ --with-mad-includes=DIR Directory where mad header
AC_CHECK_LIB(socket,socket,MPD_LIBS="$MPD_LIBS -lsocket",)
AC_CHECK_LIB(nsl,gethostbyname,MPD_LIBS="$MPD_LIBS -lnsl",)
if test x$enable_iconv = xyes; then
AC_CHECK_HEADER(iconv.h,MPD_CFLAGS="$MPD_CFLAGS -DHAVE_ICONV",)
fi
AC_MSG_CHECKING(for ipv6)
AC_EGREP_CPP([AP_maGiC_VALUE],
[
......@@ -242,4 +248,9 @@ if test x$enable_flac = xyes; then
MPD_CFLAGS="$MPD_CFLAGS -DHAVE_FLAC"
fi
if test x$enable_audiofile = xyes; then
AM_PATH_AUDIOFILE(0.1.7, MPD_LIBS="$MPD_LIBS -laudiofile" MPD_CFLAGS="$MPD_CFLAGS -DHAVE_AUDIOFILE",
[enable_audiofile=no;AC_MSG_WARN(You need audiofile -- disabling audiofile support)])
fi
AC_OUTPUT(debian/Makefile doc/Makefile src/Makefile Makefile )
EXTRA_DIST = changelog compat control copyright dirs docs rules
EXTRA_DIST = changelog compat control copyright dirs docs rules config \
init postinst postrm prerm templates conffiles
......@@ -70,6 +70,9 @@ 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@
......@@ -109,7 +112,9 @@ 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
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 =
......
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 <shank@mercury.chem.pitt.edu> Tue, 06 Oct 2003 22:04:00 -0400
-- 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
......
/etc/mpd/conf
#!/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 <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
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}
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
......
#! /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
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
config.status: configure
dh_testdir
# Add here commands to configure the package.
./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
#/usr/bin/docbook-to-man debian/mpd.sgml > mpd.1
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
-$(MAKE) distclean
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/mpd.
$(MAKE) install DESTDIR=$(CURDIR)/debian/mpd
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples doc/mpdconf.example
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
# dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
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?
......@@ -130,6 +130,7 @@ status
state: ("play", "stop", or "pause")
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)
error: if there is an error, returns message here
stop
......
......@@ -70,6 +70,9 @@ 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@
......
......@@ -124,7 +124,8 @@ 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.
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
......
......@@ -127,7 +127,7 @@ then
echo "install: no input file specified"
exit 1
else
:
true
fi
if [ x"$dir_arg" != x ]; then
......@@ -138,7 +138,7 @@ if [ x"$dir_arg" != x ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
instcmd=mkdir
fi
else
......@@ -146,9 +146,9 @@ else
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
if [ -f $src -o -d $src ]
then
:
true
else
echo "install: $src does not exist"
exit 1
......@@ -159,7 +159,7 @@ else
echo "install: no destination specified"
exit 1
else
:
true
fi
# If destination is a directory, append the input filename; if your system
......@@ -169,7 +169,7 @@ else
then
dst="$dst"/`basename $src`
else
:
true
fi
fi
......@@ -181,8 +181,8 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
......@@ -201,7 +201,7 @@ while [ $# -ne 0 ] ; do
then
$mkdirprog "${pathcomp}"
else
:
true
fi
pathcomp="${pathcomp}/"
......@@ -212,10 +212,10 @@ if [ x"$dir_arg" != x ]
then
$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 true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
......@@ -234,7 +234,7 @@ else
then
dstfile=`basename $dst`
else
:
true
fi
# Make a temp file name in the proper directory.
......@@ -253,10 +253,10 @@ 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 true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
......
......@@ -4,53 +4,9 @@
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
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
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
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 ;;
esac
errstatus=0
for file
do
......@@ -66,24 +22,13 @@ do
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"
echo "mkdir $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
mkdir "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
......@@ -92,8 +37,4 @@ done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 3
# End:
# mkinstalldirs ends here
......@@ -3,12 +3,13 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR)
mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
song.h list.h directory.h tables.h utils.h path.h mp3_decode.h \
tag.h player.h listen.h conf.h ogg_decode.h volume.h flac_decode.h \
audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h
audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h \
char_conv.h audiofile_decode.h
mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
song.c list.c directory.c tables.c utils.c path.c mp3_decode.c \
tag.c player.c listen.c conf.c ogg_decode.c volume.c flac_decode.c \
audio.c playerData.c stats.c myfprintf.c sig_handlers.c decode.c log.c \
$(mpd_headers)
char_conv.c audiofile_decode.c $(mpd_headers)
CFLAGS = @CFLAGS@ $(MPD_CFLAGS)
mpd_CFLAGS = $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB)
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_AUDIOFILE
#include "audiofile_decode.h"
#include "command.h"
#include "utils.h"
#include "audio.h"
#include "log.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <audiofile.h>
int getAudiofileTotalTime(char * file)
{
int time;
AFfilehandle af_fp = afOpenFile(file, "r", NULL);
if(af_fp == AF_NULL_FILEHANDLE) {
return -1;
}
time = (int)
((double)afGetFrameCount(af_fp,AF_DEFAULT_TRACK)
/afGetRate(af_fp,AF_DEFAULT_TRACK));
afCloseFile(af_fp);
return time;
}
int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
{
int fs, frame_count;
AFfilehandle af_fp;
af_fp = afOpenFile(dc->file,"r", NULL);
if(af_fp == AF_NULL_FILEHANDLE) {
ERROR1("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);
af->channels = afGetChannels(af_fp,AF_DEFAULT_TRACK);
frame_count = afGetFrameCount(af_fp,AF_DEFAULT_TRACK);
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",
dc->file,af->bits);
afCloseFile(af_fp);
return -1;
}
fs = (int)afGetFrameSize(af_fp, AF_DEFAULT_TRACK,1);
dc->state = DECODE_STATE_DECODE;
dc->start = 0;
{
int ret, eof = 0, current = 0;
unsigned char chunk[CHUNK_SIZE];
while(!eof) {
if(dc->seek) {
cb->end = 0;
cb->wrap = 0;
current = dc->seekWhere * af->sampleRate;
afSeekFrame(af_fp, AF_DEFAULT_TRACK,current);
dc->seek = 0;
}
ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, CHUNK_SIZE/fs);
if(ret<=0) eof = 1;
else {
while(cb->begin==cb->end && cb->wrap &&
!dc->stop && !dc->seek){
usleep(1000);
}
if(dc->stop) break;
else if(dc->seek) continue;
memcpy(cb->chunks[cb->end],chunk,CHUNK_SIZE);
cb->chunkSize[cb->end] = CHUNK_SIZE;
current += ret;
cb->times[cb->end] = (float)current/(float)af->sampleRate;
++cb->end;
if(cb->end>=BUFFERED_CHUNKS) {
cb->end = 0;
cb->wrap = 1;
}
}
}
if(dc->seek) dc->seek = 0;
if(dc->stop) {
dc->state = DECODE_STATE_STOP;
dc->stop = 0;
}
else dc->state = DECODE_STATE_STOP;
}
afCloseFile(af_fp);
return 0;
}
#endif /* HAVE_AUDIOFILE */
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net>
*
* 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 AUDIOFILE_DECODE_H
#define AUDIOFILE_DECODE_H
#ifdef HAVE_AUDIOFILE
#include "playerData.h"
int audiofile_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc);
int getAudiofileTotalTime(char * file);
#endif /* HAVE_AUDIOFILE */
#endif /* AUDIOFILE_DECODE_H */
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "char_conv.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_ICONV
#include <iconv.h>
iconv_t char_conv_iconv;
char * char_conv_to = NULL;
char * char_conv_from = NULL;
#endif
#define BUFFER_SIZE 1024
int setCharSetConversion(char * to, char * from) {
#ifdef HAVE_ICONV
if(char_conv_to && strcmp(to,char_conv_to)==0 &&
char_conv_from && strcmp(from,char_conv_from)==0)
{
return 0;
}
closeCharSetConversion();
if((char_conv_iconv = iconv_open(to,from))==(iconv_t)(-1)) return -1;
char_conv_to = strdup(to);
char_conv_from = strdup(from);
return 0;
#endif
return -1;
}
char * convStrDup(char * string) {
#ifdef HAVE_ICONV
char buffer[BUFFER_SIZE];
int inleft = strlen(string);
char * ret;
int outleft;
int retlen = 0;
size_t err;
char * bufferPtr;
if(!char_conv_to) return NULL;
ret = strdup("");
while(inleft) {
bufferPtr = buffer;
outleft = BUFFER_SIZE;
err = iconv(char_conv_iconv,&string,&inleft,&bufferPtr,
&outleft);
if(outleft==BUFFER_SIZE || (err<0 && errno!=E2BIG)) {
free(ret);
return NULL;
}
ret = realloc(ret,retlen+BUFFER_SIZE-outleft+1);
strncpy(&(ret[retlen]),buffer,BUFFER_SIZE-outleft);
retlen+=BUFFER_SIZE-outleft;
ret[retlen] = '\0';
}
return ret;
#endif
return NULL;
}
void closeCharSetConversion() {
#ifdef HAVE_ICONV
if(char_conv_to) {
iconv_close(char_conv_iconv);
free(char_conv_to);
free(char_conv_from);
char_conv_to = NULL;
char_conv_from = NULL;
}
#endif
}
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CHAR_CONV_H
#define CHAR_CONV_H
int setCharSetConversion(char * to, char * from);
char * convStrDup(char * string);
void closeCharSetConversion();
#endif
......@@ -18,6 +18,7 @@
#include "decode.h"
#include "player.h"
#include "playerData.h"
#include "utils.h"
#include "audio.h"
......@@ -30,6 +31,9 @@
#ifdef HAVE_FLAC
#include "flac_decode.h"
#endif
#ifdef HAVE_AUDIOFILE
#include "audiofile_decode.h"
#endif
#include "path.h"
#include "log.h"
......@@ -98,6 +102,7 @@ int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
}
pc->elapsedTime = 0;
pc->bitRate = 0;
pc->totalTime = cb->totalTime;
return 0;
......@@ -125,6 +130,7 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
cb->begin = 0;
dc->seek = 1;
pc->elapsedTime = dc->seekWhere;
pc->bitRate = 0;
while(decode_pid>0 && dc->seek) usleep(10);
}
}
......@@ -182,6 +188,11 @@ int decoderInit(PlayerControl * pc, Buffer * cb, AudioFormat *af,
dc->error = flac_decode(cb,af,dc);
break;
#endif
#ifdef HAVE_AUDIOFILE
case DECODE_TYPE_AUDIOFILE:
dc->error = audiofile_decode(cb,af,dc);
break;
#endif
default:
dc->error = DECODE_ERROR_UNKTYPE;
}
......@@ -196,7 +207,7 @@ int decoderInit(PlayerControl * pc, Buffer * cb, AudioFormat *af,
dc->stop = 0;
}
else if(dc->seek) dc->start = 1;
else usleep(10);
else usleep(1000);
}
exit(0);
......@@ -279,6 +290,7 @@ void decode() {
cb->begin!=cb->next)
{
pc->elapsedTime = cb->times[cb->begin];
pc->bitRate = cb->bitRate[cb->begin];
playAudio(cb->chunks[cb->begin],
cb->chunkSize[cb->begin]);
cb->begin++;
......
......@@ -25,6 +25,7 @@
#define DECODE_TYPE_MP3 0
#define DECODE_TYPE_OGG 1
#define DECODE_TYPE_FLAC 2
#define DECODE_TYPE_AUDIOFILE 3
#define DECODE_STATE_STOP 0
#define DECODE_STATE_DECODE 1
......
......@@ -526,31 +526,36 @@ void initMp3Directory() {
}
Song * getSong(char * file) {
static char * c;
static char * shortname;
static char dir[MAXPATHLEN];
static char dup[MAXPATHLEN];
static Directory * directory;
static void * song;
if(strlen(file)>MAXPATHLEN) return NULL;
dir[0] = '\0';
strcpy(dup,file);
c = strtok(dup,"/");
void * song;
Directory * directory;
char * shortname = NULL;
char * dir = NULL;
char * dup = strdup(file);
char * c = strtok(dup,"/");
while(c) {
shortname = c;
c = strtok(NULL,"/");
if(c) {
strcat(dir,shortname);
strcat(dir,"/");
}
if(shortname!=dup) {
for(c = dup; c < shortname-1; c++) {
if(*c=='\0') *c = '/';
}
dir = dup;
}
if(!(directory = getSubDirectory(mp3rootDirectory,dir))) return NULL;
if(!(directory = getSubDirectory(mp3rootDirectory,dir))) {
free(dup);
return NULL;
}
if(!findInList(directory->songs,shortname,&song)) return NULL;
if(!findInList(directory->songs,shortname,&song)) {
free(dup);
return NULL;
}
free(dup);
return (Song *)song;
}
......
......@@ -175,7 +175,7 @@ int flacSendChunk(FlacData * data) {
while(data->cb->begin==data->cb->end && data->cb->wrap &&
!data->dc->stop && !data->dc->seek)
{
usleep(10);
usleep(1000);
}
if(data->dc->stop) return -1;
......@@ -184,6 +184,7 @@ int flacSendChunk(FlacData * data) {
memcpy(data->cb->chunks[data->cb->end],data->chunk,CHUNK_SIZE);
data->cb->chunkSize[data->cb->end] = data->chunk_length;
data->cb->times[data->cb->end] = data->time;
data->cb->bitRate[data->cb->end] = 0;
data->cb->end++;
if(data->cb->end>=BUFFERED_CHUNKS) {
......
......@@ -45,6 +45,7 @@
#define INTERFACE_MAX_BUFFER_LENGTH MAXPATHLEN+1024
#define INTERFACE_LIST_MODE_BEGIN "command_list_begin"
#define INTERFACE_LIST_MODE_END "command_list_end"
#define INTERFACE_MAX_OUT_BUFFER_LENGTH 4096
int interface_max_connections;
int interface_timeout;
......@@ -65,12 +66,16 @@ typedef struct _Interface {
int expired; /* set whether this interface should be closed on next
check of old interfaces */
int num; /* interface number */
char outBuffer[INTERFACE_MAX_OUT_BUFFER_LENGTH];
int outBuflen;
} Interface;
Interface * interfaces = NULL;
void flushInterfaceBuffer(Interface * interface);
void printInterfaceOutBuffer(Interface * interface);
void openInterface(Interface * interface, int fd) {
int flags;
......@@ -90,9 +95,12 @@ void openInterface(Interface * interface, int fd) {
interface->bufferList = NULL;
interface->expired = 0;
interface->outputBufferSize = 0;
interface->outBuflen = 0;
unblockSignals();
myfprintf(interface->fp,"%s %s %s\n",COMMAND_RESPOND_OK,GREETING,VERSION);
myfprintf(interface->fp,"%s %s %s\n",COMMAND_RESPOND_OK,GREETING,
VERSION);
printInterfaceOutBuffer(interface);
}
void closeInterface(Interface * interface) {
......@@ -205,6 +213,7 @@ int interfaceReadInput(Interface * interface) {
interface->expired) {
closeInterface(interface);
}
printInterfaceOutBuffer(interface);
freeList(interface->commandList);
interface->commandList = NULL;
......@@ -246,6 +255,7 @@ int interfaceReadInput(Interface * interface) {
interface->expired) {
closeInterface(interface);
}
printInterfaceOutBuffer(interface);
}
}
freeArgArray(argArray,argArrayLength);
......@@ -260,28 +270,30 @@ int interfaceReadInput(Interface * interface) {
return 1;
}
void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds) {
void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds, int * fdmax) {
int i;
FD_ZERO(fds);
FD_SET(listenSocket,fds);
if(*fdmax<listenSocket) *fdmax = listenSocket;
for(i=0;i<interface_max_connections;i++) {
if(interfaces[i].open && !interfaces[i].expired && !interfaces[i].bufferList) {
FD_SET(interfaces[i].fd,fds);
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd;
}
}
}
void addInterfacesForBufferFlushToFdSet(fd_set * fds) {
void addInterfacesForBufferFlushToFdSet(fd_set * fds, int * fdmax) {
int i;
FD_ZERO(fds);
FD_SET(listenSocket,fds);
for(i=0;i<interface_max_connections;i++) {
if(interfaces[i].open && !interfaces[i].expired && interfaces[i].bufferList) {
FD_SET(interfaces[i].fd,fds);
if(*fdmax<interfaces[i].fd) *fdmax = interfaces[i].fd;
}
}
}
......@@ -312,14 +324,15 @@ int doIOForInterfaces() {
struct timeval tv;
int i;
int selret;
int fdmax = 0;
tv.tv_sec = 1;
tv.tv_usec = 0;
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds);
addInterfacesForBufferFlushToFdSet(&wfds);
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds,&fdmax);
addInterfacesForBufferFlushToFdSet(&wfds,&fdmax);
while((selret = select(FD_SETSIZE,&rfds,&wfds,NULL,&tv))) {
while((selret = select(fdmax+1,&rfds,&wfds,NULL,&tv))) {
if(FD_ISSET(listenSocket,&rfds)) getConnections(listenSocket);
if(selret<0 && errno==EINTR) break;
else if(selret<0) {
......@@ -340,8 +353,9 @@ int doIOForInterfaces() {
}
tv.tv_sec = 0;
tv.tv_usec = 0;
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds);
addInterfacesForBufferFlushToFdSet(&wfds);
fdmax = 0;
addInterfacesReadyToReadAndListenSocketToFdSet(&rfds,&fdmax);
addInterfacesForBufferFlushToFdSet(&wfds,&fdmax);
}
return 1;
......@@ -474,9 +488,11 @@ void flushAllInterfaceBuffers() {
int interfacePrintWithFD(int fd,char * buffer) {
int i;
int ret;
int buflen;
int copylen;
Interface * interface;
if(!strlen(buffer)) return -1;
if(!(buflen = strlen(buffer))) return -1;
for(i=0;i<interface_max_connections;i++) {
if(interfaces[i].fd==fd) break;
......@@ -485,50 +501,96 @@ int interfacePrintWithFD(int fd,char * buffer) {
/* if fd isn't found or interfaces is going to be closed, do nothing */
if(i==interface_max_connections || interfaces[i].expired) return -1;
if(interfaces[i].bufferList) {
interfaces[i].outputBufferSize+=sizeof(ListNode);
interfaces[i].outputBufferSize+=strlen(buffer)+1;
if(interfaces[i].outputBufferSize>interface_max_output_buffer_size) {
interface = interfaces+i;
while(buflen>0) {
copylen = buflen>
INTERFACE_MAX_OUT_BUFFER_LENGTH-interface->outBuflen?
INTERFACE_MAX_OUT_BUFFER_LENGTH-interface->outBuflen:
buflen;
memcpy(interface->outBuffer+interface->outBuflen,buffer,
copylen);
buflen-=copylen;
interface->outBuflen+=copylen;
buffer+=copylen;
if(interface->outBuflen>=INTERFACE_MAX_OUT_BUFFER_LENGTH) {
printInterfaceOutBuffer(interface);
}
}
return 0;
}
void printInterfaceOutBuffer(Interface * interface) {
char * buffer;
int ret;
if(!interface->open || interface->expired || !interface->outBuflen) {
return;
}
if(interface->bufferList) {
interface->outputBufferSize+=sizeof(ListNode);
interface->outputBufferSize+=interface->outBuflen+1;
if(interface->outputBufferSize>
interface_max_output_buffer_size)
{
ERROR3("interface %i: output buffer size (%lli) is "
"larger than the max (%lli)\n",
interfaces[i].num,
interfaces[i].outputBufferSize,
interface->num,
interface->outputBufferSize,
interface_max_output_buffer_size);
/* cause interface to close */
freeList(interfaces[i].bufferList);
interfaces[i].bufferList = NULL;
interfaces[i].expired = 1;
return 0;
freeList(interface->bufferList);
interface->bufferList = NULL;
interface->expired = 1;
}
else {
insertInListWithoutKey(interfaces[i].bufferList,(void *)strdup(buffer));
flushInterfaceBuffer(&interfaces[i]);
buffer = malloc(interface->outBuflen+1);
memcpy(buffer,interface->outBuffer,interface->outBuflen);
buffer[interface->outBuflen] = '\0';
insertInListWithoutKey(interface->bufferList,(void *)buffer);
flushInterfaceBuffer(interface);
}
}
else {
if((ret = write(fd,buffer,strlen(buffer)))<0) {
if((ret = write(interface->fd,interface->outBuffer,
interface->outBuflen))<0)
{
if(errno==EAGAIN || errno==EINTR) {
interfaces[i].bufferList = makeList(free);
insertInListWithoutKey(interfaces[i].bufferList,(void *)strdup(buffer));
buffer = malloc(interface->outBuflen+1);
memcpy(buffer,interface->outBuffer,
interface->outBuflen);
buffer[interface->outBuflen] = '\0';
interface->bufferList = makeList(free);
insertInListWithoutKey(interface->bufferList,
(void *)buffer);
}
else {
DEBUG1("interface %i: problems writing\n",i);
interfaces[i].expired = 1;
return 0;
DEBUG1("interface %i: problems writing\n",
interface->num);
interface->expired = 1;
return;
}
}
else if(ret<strlen(buffer)) {
interfaces[i].bufferList = makeList(free);
insertInListWithoutKey(interfaces[i].bufferList,(void *)strdup(&buffer[ret]));
else if(ret<interface->outBuflen) {
buffer = malloc(interface->outBuflen-ret+1);
memcpy(buffer,interface->outBuffer+ret,
interface->outBuflen-ret);
buffer[interface->outBuflen-ret] = '\0';
interface->bufferList = makeList(free);
insertInListWithoutKey(interface->bufferList,buffer);
}
/* if we needed to create buffer, initialize bufferSize info */
if(interfaces[i].bufferList) {
DEBUG1("interface %i: buffer created\n",i);
interfaces[i].outputBufferSize = sizeof(List);
interfaces[i].outputBufferSize+=sizeof(ListNode);
interfaces[i].outputBufferSize+=strlen((char *)interfaces[i].bufferList->firstNode->data)+1;
if(interface->bufferList) {
DEBUG1("interface %i: buffer created\n",interface->num);
interface->outputBufferSize = sizeof(List);
interface->outputBufferSize+=sizeof(ListNode);
interface->outputBufferSize+=strlen(
(char *)interface->bufferList->
firstNode->data)+1;
}
}
return 0;
interface->outBuflen = 0;
}
......@@ -82,36 +82,40 @@ int lsPlaylists(FILE * fp, char * path) {
DIR * dir;
struct stat st;
struct dirent * ent;
char * cLast;
char * cNext;
char * dup;
char s[MAXPATHLEN+1];
List * list = NULL;
ListNode * node = NULL;
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;
s[MAXPATHLEN] = '\0';
strcpy(s,actualPath);
strcat(s,"/");
while((ent = readdir(dir))) {
if(ent->d_name[0]=='.') continue; /* hide hidden stuff */
snprintf(s,MAXPATHLEN,"%s/%s",actualPath,ent->d_name);
if(stat(s,&st)==0) {
if(S_ISREG(st.st_mode)) {
dup = strdup(ent->d_name);
cNext = cLast = strtok(dup,".");
while((cNext = strtok(NULL,"."))) cLast = cNext;
if(cLast && 0==strcmp(cLast,
PLAYLIST_FILE_SUFFIX))
{
dup = ent->d_name;
if(dup[0]!='.' &&
(suff=strlen(dup)-suflen)>0 &&
dup[suff]=='.' &&
strcmp(dup+suff+1,PLAYLIST_FILE_SUFFIX)==0)
{
strncpy(s+actlen,ent->d_name,maxlen);
if(stat(s,&st)==0) {
if(S_ISREG(st.st_mode)) {
if(list==NULL) list = makeList(NULL);
memset(dup,0,strlen(ent->d_name));
strncpy(dup,ent->d_name,
strlen(ent->d_name)-
strlen(PLAYLIST_FILE_SUFFIX)-1);
//myfprintf(fp,"playlist: %s\n",dup);
dup = strdup(ent->d_name);
dup[suff] = '\0';
insertInList(list,dup,NULL);
free(dup);
}
free(dup);
}
}
}
......@@ -151,6 +155,9 @@ time_t isMusic(char * file) {
#ifdef HAVE_MAD
if((ret = isMp3(file)>0)) return ret;
#endif
#ifdef HAVE_AUDIOFILE
if((ret = isWave(file)>0)) return ret;
#endif
return ret;
}
......@@ -184,6 +191,33 @@ time_t isPlaylist(char * file) {
return 0;
}
time_t isWave(char * file) {
struct stat st;
char * actualFile = file;
if(actualFile[0]!='/') actualFile = rmp2amp(file);
if(stat(actualFile,&st)==0) {
if(S_ISREG(st.st_mode)) {
char * dup;
char * cLast;
char * cNext;
int ret = 0;
dup = strdup(file);
cNext = cLast = strtok(dup,".");
while((cNext = strtok(NULL,"."))) cLast = cNext;
if(cLast && 0==strcasecmp(cLast,"wav")) {
ret = st.st_mtime;
}
free(dup);
return ret;
}
else return 0;
}
return 0;
}
time_t isFlac(char * file) {
struct stat st;
char * actualFile = file;
......
......@@ -32,6 +32,8 @@ time_t isOgg(char * file);
time_t isFlac(char * file);
time_t isWave(char * file);
time_t isMusic(char * file);
time_t isDir(char * name);
......
......@@ -67,11 +67,12 @@ void usage(char * argv[]) {
SYSTEM_CONFIG_FILE_LOCATION);
ERROR0("\n");
ERROR0("options:\n");
ERROR0(" --help this usage statement\n");
ERROR0(" --no-daemon don't detach from console\n");
ERROR0(" --create-db (re)create database\n");
ERROR0(" --verbose verbose logging\n");
ERROR0(" --version prints version information\n");
ERROR0(" --help this usage statement\n");
ERROR0(" --no-daemon don't detach from console\n");
ERROR0(" --create-db force (re)creation database\n");
ERROR0(" --no-create-db don't create database\n");
ERROR0(" --verbose verbose logging\n");
ERROR0(" --version prints version information\n");
}
void version() {
......@@ -106,6 +107,10 @@ void parseOptions(int argc, char ** argv, Options * options) {
options->createDB = 1;
argcLeft--;
}
else if(strcmp(argv[i],"--no-create-db")==0) {
options->createDB = -1;
argcLeft--;
}
else if(strcmp(argv[i],"--verbose")==0) {
logLevel = LOG_LEVEL_DEBUG;
argcLeft--;
......@@ -174,6 +179,18 @@ int main(int argc, char * argv[]) {
FILE * out;
FILE * err;
Options options;
int i;
for(i=0;i<FD_SETSIZE;i++) {
switch(i) {
case STDIN_FILENO:
case STDOUT_FILENO:
case STDERR_FILENO:
break;
default:
close(i);
}
}
initConf();
......@@ -309,6 +326,11 @@ int main(int argc, char * argv[]) {
}
else strncpy(directorydb,options.dbFile,MAXPATHLEN);
if(options.createDB || readDirectoryDB()<0) {
if(options.createDB<0) {
ERROR0("can't open db file and using \"--no-create-db\""
" command line option\n");
exit(-1);
}
initMp3Directory();
if(writeDirectoryDB()<0) {
ERROR0("problem opening db for reading or writing\n");
......@@ -323,9 +345,12 @@ int main(int argc, char * argv[]) {
initStats();
initPlaylist();
close(STDIN_FILENO);
if(options.daemon) {
int pid = fork();
int pid;
fflush(NULL);
pid = fork();
if(pid>0) _exit(0);
else if(pid<0) {
ERROR0("problems fork'ing for daemon!\n");
......@@ -337,6 +362,11 @@ int main(int argc, char * argv[]) {
exit(-1);
}
if(setsid()<0) {
ERROR0("problems setsid'ing\n");
exit(-1);
}
if(close(STDOUT_FILENO)) {
fprintf(err,"problems closing stdout : %s\n",
strerror(errno));
......@@ -362,13 +392,20 @@ int main(int argc, char * argv[]) {
}
myfprintfStdLogMode(out,err);
fflush(NULL);
pid = fork();
if(pid>0) _exit(0);
else if(pid<0) {
ERROR0("problems fork'ing for daemon!\n");
exit(-1);
}
}
else {
fclose(out);
fclose(err);
}
fclose(stdin);
/* lets redirect stdin to dev null as a work around for libao bug */
{
int fd = open("/dev/null",O_RDONLY);
......
......@@ -118,6 +118,7 @@ typedef struct _mp3DecodeData {
long maxFrames;
long currentFrame;
int flush;
unsigned long bitRate;
} mp3DecodeData;
void initMp3DecodeData(mp3DecodeData * data) {
......@@ -325,6 +326,22 @@ void mp3DecodeDataFinalize(mp3DecodeData * data) {
if(data->times) free(data->times);
}
/* this is primarily used for getting total time for tags */
int getMp3TotalTime(char * file) {
mp3DecodeData data;
int ret;
while(!(data.fp = fopen(file,"r")) && errno==EINTR);
if(!data.fp) return -1;
initMp3DecodeData(&data);
if(decodeFirstFrame(&data)<0) ret = -1;
else ret = data.totalTime;
mp3DecodeDataFinalize(&data);
return ret;
}
int openMp3(char * file, mp3DecodeData * data) {
if((data->fp = fopen(file,"r"))<=0) {
ERROR1("problems opening \"%s\"\n",file);
......@@ -341,7 +358,7 @@ int openMp3(char * file, mp3DecodeData * data) {
int mp3ChildSendData(mp3DecodeData * data, Buffer * cb, DecoderControl * dc) {
while(cb->begin==cb->end && cb->wrap && !dc->stop && !dc->seek)
usleep(10);
usleep(1000);
if(dc->stop) return -1;
/* just for now, so it doesn't hang */
if(dc->seek) return 0;
......@@ -349,6 +366,7 @@ int mp3ChildSendData(mp3DecodeData * data, Buffer * cb, DecoderControl * dc) {
memcpy(cb->chunks[cb->end],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++;
......@@ -369,6 +387,7 @@ int mp3Read(mp3DecodeData * data, Buffer * cb, DecoderControl * dc) {
data->highestFrame<data->maxFrames)
{
mad_timer_add(&data->timer,(data->frame).header.duration);
data->bitRate = (data->frame).header.bitrate;
data->frameOffset[data->currentFrame] =
data->currentOffset;
if(data->stream.this_frame!=NULL) {
......
......@@ -19,8 +19,15 @@
#ifndef MP3_DECODE_H
#define MP3_DECODE_H
#ifdef HAVE_MAD
#include "playerData.h"
/* this is primarily used in tag.c */
int getMp3TotalTime(char * file);
int mp3_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc);
#endif
#endif
......@@ -61,6 +61,8 @@ int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
int eof = 0;
long ret;
char chunk[CHUNK_SIZE];
long bitRate = 0;
long test;
while(!eof) {
if(dc->seek) {
......@@ -76,13 +78,17 @@ int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
while(cb->begin==cb->end && cb->wrap &&
!dc->stop && !dc->seek)
{
usleep(10);
usleep(1000);
}
if(dc->stop) break;
else if(dc->seek) continue;
memcpy(cb->chunks[cb->end],chunk,CHUNK_SIZE);
cb->chunkSize[cb->end] = ret;
cb->times[cb->end] = ov_time_tell(&vf);
if((test = ov_bitrate_instant(&vf))>0) {
bitRate = test/1000;
}
cb->bitRate[cb->end] = bitRate;
cb->end++;
if(cb->end>=BUFFERED_CHUNKS) {
cb->end = 0;
......
......@@ -30,6 +30,7 @@
#include "directory.h"
#include "volume.h"
#include "playerData.h"
#include "char_conv.h"
#include <stdio.h>
#include <sys/types.h>
......@@ -97,6 +98,7 @@ int playerInit() {
closeMp3Directory();
closeTables();
finishVolume();
closeCharSetConversion();
while(1) {
if(pc->play) decode();
......@@ -115,7 +117,7 @@ int playerInit() {
pc->queueLockState = PLAYER_QUEUE_UNLOCKED;
pc->unlockQueue = 0;
}
else usleep(10);
else usleep(1000);
}
exit(0);
......@@ -155,6 +157,9 @@ int playerPlay(FILE * fp, char * file) {
#ifdef HAVE_FLAC
else if(isFlac(file)) pc->decodeType = DECODE_TYPE_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
else if(isWave(file)) pc->decodeType = DECODE_TYPE_AUDIOFILE;
#endif
else {
strcpy(pc->erroredFile,pc->file);
pc->error = PLAYER_ERROR_UNKTYPE;
......@@ -215,6 +220,10 @@ int getPlayerElapsedTime() {
return (int)(getPlayerData()->playerControl.elapsedTime+0.5);
}
unsigned long getPlayerBitRate() {
return getPlayerData()->playerControl.bitRate;
}
int getPlayerTotalTime() {
return (int)(getPlayerData()->playerControl.totalTime+0.5);
}
......@@ -282,6 +291,9 @@ int queueSong(char * file) {
#ifdef HAVE_FLAC
else if(isFlac(file)) pc->decodeType = DECODE_TYPE_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
else if(isWave(file)) pc->decodeType = DECODE_TYPE_AUDIOFILE;
#endif
else return -1;
pc->queueState = PLAYER_QUEUE_FULL;
return 0;
......
......@@ -54,6 +54,7 @@ typedef struct _PlayerControl {
int state;
int closeAudio;
int error;
unsigned long bitRate;
float totalTime;
float elapsedTime;
char file[MAXPATHLEN+1];
......@@ -84,6 +85,8 @@ int getPlayerTotalTime();
int getPlayerElapsedTime();
unsigned long getPlayerBitRate();
int getPlayerState();
void clearPlayerError();
......
......@@ -31,6 +31,7 @@ extern int buffered_before_play;
typedef struct _Buffer {
char chunks[BUFFERED_CHUNKS][CHUNK_SIZE];
uint_16 chunkSize[BUFFERED_CHUNKS];
uint_16 bitRate[BUFFERED_CHUNKS];
float times[BUFFERED_CHUNKS];
int begin;
int end;
......
......@@ -77,6 +77,7 @@ int playlist_max_length;
int playlist_stopOnError;
int playlist_errorCount = 0;
int playlist_queueError;
int playlist_noGoToNext = 0;
int playlist_saveAbsolutePaths;
......@@ -452,6 +453,10 @@ int addToPlaylist(FILE * fp, char * file) {
return -1;
}
return addSongToPlaylist(fp,song);
}
int addSongToPlaylist(FILE * fp, Song * song) {
if(playlist.length==playlist_max_length) {
myfprintf(fp,"%s playlist is at the max size\n",COMMAND_RESPOND_ERROR);
return -1;
......@@ -592,6 +597,7 @@ int deleteFromPlaylist(FILE * fp, int song) {
/*if(playlist.current>=playlist.length) return playerStop(fp);
else return playPlaylistOrderNumber(fp,playlist.current);*/
playerStop(stderr);
playlist_noGoToNext = 1;
}
else if(playlist_state!=PLAYLIST_STATE_STOP &&
playlist.current>songOrder) {
......@@ -632,6 +638,7 @@ int stopPlaylist(FILE * fp) {
playerCloseAudio();
playlist.queued = -1;
playlist_state = PLAYLIST_STATE_STOP;
playlist_noGoToNext = 0;
/*stats.playTime+=getPlayerElapsedTime();*/
if(playlist.random) randomizeOrder(0,playlist.length-1);
return 0;
......@@ -643,6 +650,7 @@ int playPlaylistOrderNumber(FILE * fp, int orderNum) {
if(playerStop(fp)<0) return -1;
playlist_state = PLAYLIST_STATE_PLAY;
playlist_noGoToNext = 0;
playlist.queued = -1;
playlist_queueError = 0;
playlist.current = orderNum;
......@@ -700,25 +708,6 @@ int playPlaylist(FILE * fp, int song, int stopOnError) {
return playPlaylistOrderNumber(fp,i);
}
void playPlaylistIfPlayerStopped() {
if(getPlayerState()==PLAYER_STATE_STOP) {
int error = getPlayerError();
if(error==PLAYER_ERROR_NOERROR) playlist_errorCount = 0;
else playlist_errorCount++;
if(playlist_state==PLAYLIST_STATE_PLAY && (
(playlist_stopOnError &&
error!=PLAYER_ERROR_NOERROR) ||
error==PLAYER_ERROR_AUDIO ||
error==PLAYER_ERROR_SYSTEM ||
playlist_errorCount>=playlist.length)) {
stopPlaylist(stderr);
}
else nextSongInPlaylist(stderr);
}
}
void syncPlayerAndPlaylist() {
if(playlist_state!=PLAYLIST_STATE_PLAY) return;
......@@ -726,6 +715,19 @@ void syncPlayerAndPlaylist() {
else syncPlaylistWithQueue(!playlist_queueError);
}
int currentSongInPlaylist(FILE * fp) {
if(playlist_state!=PLAYLIST_STATE_PLAY) return 0;
playlist_stopOnError = 0;
if(playlist.current<playlist.length) {
return playPlaylistOrderNumber(fp,playlist.current);
}
else return stopPlaylist(fp);;
return 0;
}
int nextSongInPlaylist(FILE * fp) {
if(playlist_state!=PLAYLIST_STATE_PLAY) return 0;
......@@ -747,6 +749,26 @@ int nextSongInPlaylist(FILE * fp) {
return 0;
}
void playPlaylistIfPlayerStopped() {
if(getPlayerState()==PLAYER_STATE_STOP) {
int error = getPlayerError();
if(error==PLAYER_ERROR_NOERROR) playlist_errorCount = 0;
else playlist_errorCount++;
if(playlist_state==PLAYLIST_STATE_PLAY && (
(playlist_stopOnError &&
error!=PLAYER_ERROR_NOERROR) ||
error==PLAYER_ERROR_AUDIO ||
error==PLAYER_ERROR_SYSTEM ||
playlist_errorCount>=playlist.length)) {
stopPlaylist(stderr);
}
else if(playlist_noGoToNext) currentSongInPlaylist(stderr);
else nextSongInPlaylist(stderr);
}
}
int getPlaylistRepeatStatus() {
return playlist.repeat;
}
......@@ -977,7 +999,6 @@ int shufflePlaylist(FILE * fp) {
}
int deletePlaylist(FILE * fp, char * file) {
struct stat st;
char * rfile = malloc(strlen(file)+strlen(".")+
strlen(PLAYLIST_FILE_SUFFIX)+1);
char * actualFile;
......@@ -994,17 +1015,7 @@ int deletePlaylist(FILE * fp, char * file) {
return -1;
}
if(stat(file,&st)<0) {
myfprintf(fp,"%s problems stat'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(!S_ISREG(st.st_mode)) {
myfprintf(fp,"%s not a file\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(unlink(file)<0) {
if(unlink(actualFile)<0) {
myfprintf(fp,"%s problems deleting file\n",COMMAND_RESPOND_ERROR);
return -1;
}
......@@ -1132,7 +1143,7 @@ int loadPlaylist(FILE * fp, char * file) {
while(fclose(fileP) && errno==EINTR);
if(erroredFile) {
fprintf(fp,"%s can't add file \"%s\"\n",COMMAND_RESPOND_ERROR,
myfprintf(fp,"%s can't add file \"%s\"\n",COMMAND_RESPOND_ERROR,
erroredFile);
free(erroredFile);
return -1;
......
......@@ -41,6 +41,8 @@ int clearPlaylist(FILE * fp);
int addToPlaylist(FILE * fp, char * file);
int addSongToPlaylist(FILE * fp, Song * song);
int showPlaylist(FILE * fp);
int deleteFromPlaylist(FILE * fp, int song);
......
......@@ -30,6 +30,7 @@
#define SONG_ALBUM "Album: "
#define SONG_TRACK "Track: "
#define SONG_TITLE "Title: "
#define SONG_TIME "Time: "
#define SONG_MTIME "mtime: "
#include <stdlib.h>
......@@ -43,25 +44,28 @@ Song * newSong(char * file) {
song->file = strdup(file);
#ifdef HAVE_OGG
if((song->mtime = isOgg(file))) {
song->tag = oggCommentDup(file);
song->tag = oggTagDup(file);
return song;
}
#endif
#ifdef HAVE_FLAC
if((song->mtime = isFlac(file))) {
if(!(song->tag = flacVorbisCommentDup(file))) {
song->tag = id3Dup(file);
}
song->tag = flacTagDup(file);
return song;
}
#endif
#ifdef HAVE_MAD
if((song->mtime = isMp3(file))) {
song->tag = id3Dup(file);
song->tag = mp3TagDup(file);
return song;
}
#endif
#ifdef HAVE_AUDIOFILE
if((song->mtime = isWave(file))) {
song->tag = audiofileTagDup(file);
return song;
}
#endif
return song;
}
......@@ -169,6 +173,10 @@ void readSongInfoIntoList(FILE * fp, SongList * list) {
if(!song->tag) song->tag = newMpdTag();
song->tag->title = strdup(&(buffer[strlen(SONG_TITLE)]));
}
else if(0==strncmp(SONG_TIME,buffer,strlen(SONG_TIME))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->time = atoi(&(buffer[strlen(SONG_TIME)]));
}
else if(0==strncmp(SONG_MTIME,buffer,strlen(SONG_MTIME))) {
song->mtime = atoi(&(buffer[strlen(SONG_TITLE)]));
}
......@@ -189,21 +197,25 @@ int updateSongInfo(Song * song) {
if(song->tag) freeMpdTag(song->tag);
#ifdef HAVE_MAD
if((song->mtime = isMp3(song->file))) {
song->tag = id3Dup(song->file);
song->tag = mp3TagDup(song->file);
return 0;
}
#endif
#ifdef HAVE_OGG
if((song->mtime = isOgg(song->file))) {
song->tag = oggCommentDup(song->file);
song->tag = oggTagDup(song->file);
return 0;
}
#endif
#ifdef HAVE_FLAC
if((song->mtime = isFlac(song->file))) {
if(!(song->tag = flacVorbisCommentDup(song->file))) {
song->tag = id3Dup(song->file);
}
song->tag = flacTagDup(song->file);
return 0;
}
#endif
#ifdef HAVE_AUDIOFILE
if((song->mtime = isWave(song->file))) {
song->tag = audiofileTagDup(song->file);
return 0;
}
#endif
......
......@@ -68,7 +68,7 @@ void closeTables() {
void addSongToSomeAlbumTable(List * table, Song * song) {
void * album;
if(!song->tag) return;
if(!song->tag->title || !strlen(song->tag->title)) return;
if(!song->tag->album || !strlen(song->tag->album)) return;
if(findInList(table,song->tag->album,&album)) {
insertInList((SongList *)album,song->file,song);
}
......
......@@ -20,6 +20,9 @@
#include "path.h"
#include "myfprintf.h"
#include "sig_handlers.h"
#include "mp3_decode.h"
#include "audiofile_decode.h"
#include "char_conv.h"
#include <sys/stat.h>
#include <stdlib.h>
......@@ -47,6 +50,7 @@ void printMpdTag(FILE * fp, MpdTag * tag) {
if(tag->album) myfprintf(fp,"Album: %s\n",tag->album);
if(tag->track) myfprintf(fp,"Track: %s\n",tag->track);
if(tag->title) myfprintf(fp,"Title: %s\n",tag->title);
if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time);
}
#ifdef HAVE_ID3TAG
......@@ -121,19 +125,45 @@ MpdTag * id3Dup(char * filename) {
id3_file_close(file);
if(ret) {
if(!ret->artist) ret->artist = strdup("");
if(!ret->album) ret->album = strdup("");
if(!ret->title) ret->title = strdup("");
if(!ret->track) ret->track = strdup("");
}
unblockSignals();
#endif
return ret;
}
#ifdef HAVE_AUDIOFILE
MpdTag * audiofileTagDup(char * file) {
MpdTag * ret = NULL;
int time = getAudiofileTotalTime(rmp2amp(file));
if (time>=0) {
if(!ret) ret = newMpdTag();
ret->time = time;
}
return ret;
}
#endif
#ifdef HAVE_MAD
MpdTag * mp3TagDup(char * file) {
MpdTag * ret = NULL;
int time;
ret = id3Dup(file);
time = getMp3TotalTime(rmp2amp(file));
if(time>=0) {
if(!ret) ret = newMpdTag();
ret->time = time;
}
return ret;
}
#endif
#ifdef HAVE_OGG
MpdTag * oggCommentDup(char * file) {
MpdTag * oggTagDup(char * file) {
MpdTag * ret = NULL;
FILE * fp;
OggVorbis_File vf;
......@@ -142,6 +172,8 @@ MpdTag * oggCommentDup(char * file) {
char * s1;
char * s2;
setCharSetConversion("LATIN1","UTF-8");
while(!(fp = fopen(rmp2amp(file),"r")) && errno==EINTR);
if(!fp) return NULL;
blockSignals();
......@@ -151,6 +183,9 @@ MpdTag * oggCommentDup(char * file) {
return NULL;
}
ret = newMpdTag();
ret->time = (int)(ov_time_total(&vf,-1)+0.5);
comments = ov_comment(&vf,-1)->user_comments;
while(*comments) {
......@@ -158,20 +193,32 @@ MpdTag * oggCommentDup(char * file) {
s1 = strtok(temp,"=");
s2 = strtok(NULL,"=");
if(0==strcasecmp(s1,"artist")) {
if(!ret) ret = newMpdTag();
if(!ret->artist && s2) ret->artist = strdup(s2);
if(!ret->artist && s2) {
if(!(ret->artist = convStrDup(s2))) {
ret->artist = strdup(s2);
}
}
}
else if(0==strcasecmp(s1,"title")) {
if(!ret) ret = newMpdTag();
if(!ret->title && s2) ret->title = strdup(s2);
if(!ret->title && s2) {
if(!(ret->title = convStrDup(s2))) {
ret->title = strdup(s2);
}
}
}
else if(0==strcasecmp(s1,"album")) {
if(!ret) ret = newMpdTag();
if(!ret->album && s2) ret->album = strdup(s2);
if(!ret->album && s2) {
if(!(ret->album = convStrDup(s2))) {
ret->album = strdup(s2);
}
}
}
else if(0==strcasecmp(s1,"tracknumber")) {
if(!ret) ret = newMpdTag();
if(!ret->track && s2) ret->track = strdup(s2);
if(!ret->track && s2) {
if(!(ret->track = convStrDup(s2))) {
ret->track = strdup(s2);
}
}
}
free(temp);
++comments;
......@@ -179,27 +226,21 @@ MpdTag * oggCommentDup(char * file) {
ov_clear(&vf);
if(ret) {
if(!ret->artist) ret->artist = strdup("");
if(!ret->album) ret->album = strdup("");
if(!ret->title) ret->title = strdup("");
if(!ret->track) ret->track = strdup("");
}
unblockSignals();
return ret;
}
#endif
#ifdef HAVE_FLAC
MpdTag * flacVorbisCommentDup(char * file) {
MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
MpdTag * ret = NULL;
FLAC__Metadata_SimpleIterator * it;
FLAC__StreamMetadata * block = NULL;
int found = 0;
int offset;
int len, pos;
*vorbisCommentFound = 0;
blockSignals();
it = FLAC__metadata_simple_iterator_new();
if(!FLAC__metadata_simple_iterator_init(it,rmp2amp(file),1,0)) {
......@@ -209,69 +250,110 @@ MpdTag * flacVorbisCommentDup(char * file) {
}
do {
if(block) FLAC__metadata_object_delete(block);
block = FLAC__metadata_simple_iterator_get_block(it);
if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) found=1;
} while(!found && FLAC__metadata_simple_iterator_next(it));
if(found) {
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"artist");
if(offset>=0) {
if(!ret) ret = newMpdTag();
pos = strlen("artist=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
ret->artist = malloc(len+1);
memcpy(ret->artist,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
ret->artist[len] = '\0';
if(!block) break;
if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
char * dup;
setCharSetConversion("LATIN1","UTF-8");
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"artist");
if(offset>=0) {
*vorbisCommentFound = 1;
if(!ret) ret = newMpdTag();
pos = strlen("artist=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
dup = malloc(len+1);
memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
dup[len] = '\0';
if((ret->artist = convStrDup(dup))) {
free(dup);
}
else ret->artist = dup;
}
}
}
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"album");
if(offset>=0) {
if(!ret) ret = newMpdTag();
pos = strlen("album=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
ret->album = malloc(len+1);
memcpy(ret->album,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
ret->album[len] = '\0';
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"album");
if(offset>=0) {
*vorbisCommentFound = 1;
if(!ret) ret = newMpdTag();
pos = strlen("album=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
dup = malloc(len+1);
memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
dup[len] = '\0';
if((ret->album = convStrDup(dup))) {
free(dup);
}
else ret->album = dup;
}
}
}
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"title");
if(offset>=0) {
if(!ret) ret = newMpdTag();
pos = strlen("title=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
ret->title = malloc(len+1);
memcpy(ret->title,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
ret->title[len] = '\0';
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"title");
if(offset>=0) {
*vorbisCommentFound = 1;
if(!ret) ret = newMpdTag();
pos = strlen("title=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
dup = malloc(len+1);
memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
dup[len] = '\0';
if((ret->title = convStrDup(dup))) {
free(dup);
}
else ret->title = dup;
}
}
}
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"tracknumber");
if(offset>=0) {
if(!ret) ret = newMpdTag();
pos = strlen("tracknumber=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
ret->track = malloc(len+1);
memcpy(ret->track,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
ret->track[len] = '\0';
offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"tracknumber");
if(offset>=0) {
*vorbisCommentFound = 1;
if(!ret) ret = newMpdTag();
pos = strlen("tracknumber=");
len = block->data.vorbis_comment.comments[offset].length-pos;
if(len>0) {
dup = malloc(len+1);
memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
dup[len] = '\0';
if((ret->track = convStrDup(dup))) {
free(dup);
}
else ret->track = dup;
}
}
}
if(ret) {
if(!ret->artist) ret->artist = strdup("");
if(!ret->album) ret->album = strdup("");
if(!ret->title) ret->title = strdup("");
if(!ret->track) ret->track = strdup("");
else if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
if(!ret) ret = newMpdTag();
ret->time = ((float)block->data.stream_info.
total_samples) /
block->data.stream_info.sample_rate +
0.5;
}
}
FLAC__metadata_object_delete(block);
} while(FLAC__metadata_simple_iterator_next(it));
if(block) FLAC__metadata_object_delete(block);
FLAC__metadata_simple_iterator_delete(it);
unblockSignals();
return ret;
}
MpdTag * flacTagDup(char * file) {
MpdTag * ret = NULL;
int foundVorbisComment = 0;
ret = flacMetadataDup(file,&foundVorbisComment);
if(!ret) return NULL;
if(!foundVorbisComment) {
MpdTag * temp = id3Dup(file);
if(temp) {
temp->time = ret->time;
freeMpdTag(ret);
ret = temp;
}
}
return ret;
}
#endif
MpdTag * newMpdTag() {
......@@ -280,6 +362,7 @@ MpdTag * newMpdTag() {
ret->artist = NULL;
ret->title = NULL;
ret->track = NULL;
ret->time = -1;
return ret;
}
......@@ -300,6 +383,7 @@ MpdTag * mpdTagDup(MpdTag * tag) {
ret->album = strdup(tag->album);
ret->title = strdup(tag->title);
ret->track = strdup(tag->track);
ret->time = tag->time;
}
return ret;
......
......@@ -26,17 +26,28 @@ typedef struct _MpdTag {
char * album;
char * track;
char * title;
int time;
} MpdTag;
MpdTag * newMpdTag();
void freeMpdTag(MpdTag * tag);
MpdTag * id3Dup(char * file);
#ifdef HAVE_MAD
MpdTag * mp3TagDup(char * file);
#endif
MpdTag * oggCommentDup(char * file);
#ifdef HAVE_OGG
MpdTag * oggTagDup(char * file);
#endif
MpdTag * flacVorbisCommentDup(char * file);
#ifdef HAVE_FLAC
MpdTag * flacTagDup(char * file);
#endif
#ifdef HAVE_AUDIOFILE
MpdTag * audiofileTagDup(char * file);
#endif
void printMpdTag(FILE * fp, MpdTag * tag);
......
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