Commit cd6cf8d0 authored by Led's avatar Led

Merge commit '0.14-alpha2' into alt

parents 1c3eeaf3 7dd72790
......@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
timestamp='2008-01-23'
timestamp='2008-09-28'
# 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
......@@ -139,6 +139,23 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
if [ "${UNAME_SYSTEM}" = "Linux" ] ; then
eval $set_cc_for_build
cat << EOF > $dummy.c
#include <features.h>
#ifdef __UCLIBC__
# ifdef __UCLIBC_CONFIG_VERSION__
LIBC=uclibc __UCLIBC_CONFIG_VERSION__
# else
LIBC=uclibc
# endif
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'`
fi
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
......@@ -796,7 +813,7 @@ EOF
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T | authenticamd)
EM64T | authenticamd | genuineintel)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
......@@ -840,31 +857,31 @@ EOF
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
echo cris-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo crisv32-axis-linux-gnu
echo crisv32-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo frv-unknown-linux-gnu
echo frv-unknown-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:*)
eval $set_cc_for_build
......@@ -887,7 +904,7 @@ EOF
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
mips64:Linux:*:*)
eval $set_cc_for_build
......@@ -910,16 +927,16 @@ EOF
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
or32:Linux:*:*)
echo or32-unknown-linux-gnu
echo or32-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
echo powerpc-unknown-linux-${LIBC}
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
echo powerpc64-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
......@@ -932,40 +949,43 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-gnu ;;
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
echo hppa64-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
echo x86_64-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
......@@ -980,20 +1000,19 @@ EOF
p'`
case "$ld_supported_targets" in
elf32-i386)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}"
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout"
exit ;;
"")
# Either a pre-BFD a.out linker (linux-gnuoldld) or
# one that does not give us useful --help.
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld"
exit ;;
esac
# This should get integrated into the C code below, but now we hack
if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi
# Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
......@@ -1216,6 +1235,9 @@ EOF
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
......
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to enable ALSA support */
#undef HAVE_ALSA
......@@ -203,6 +206,14 @@
/* Version number of package */
#undef VERSION
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
......@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
timestamp='2008-01-16'
timestamp='2008-09-08'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
......@@ -244,18 +244,20 @@ case $basic_machine in
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| d10v | d30v | dlx | dsp16xx | dvp \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep \
| maxq | mb | microblaze | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr | mips64vrel \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
......@@ -277,7 +279,7 @@ case $basic_machine in
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| score \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
......@@ -286,7 +288,7 @@ case $basic_machine in
| v850 | v850e \
| we32k \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
......@@ -331,12 +333,14 @@ case $basic_machine in
| ip2k-* | iq2000-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr-* | mips64vrel-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
......@@ -358,20 +362,20 @@ case $basic_machine in
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-*)
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
......@@ -459,6 +463,10 @@ case $basic_machine in
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
......@@ -526,6 +534,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
......@@ -714,6 +726,24 @@ case $basic_machine in
basic_machine=m68k-atari
os=-mint
;;
mipsEE* | ee | ps2)
basic_machine=mips64r5900el-scei
case $os in
-linux*)
;;
*)
os=-elf
;;
esac
;;
iop)
basic_machine=mipsel-scei
os=-irx
;;
dvp)
basic_machine=dvp-scei
os=-elf
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
......@@ -1128,6 +1158,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
......@@ -1248,7 +1282,7 @@ case $os in
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
......@@ -1258,7 +1292,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
......@@ -1388,6 +1422,9 @@ case $os in
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-none)
;;
*)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
dnl AC_INIT(src/main.c)
dnl AM_INIT_AUTOMAKE(mpd, 0.14.0)
AC_PREREQ(2.60)
AC_INIT(mpd, 0.14~alpha1, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.14~alpha2, musicpd-dev-team@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
AM_CONFIG_HEADER(config.h)
AC_CONFIG_MACRO_DIR([m4])
AC_SUBST(MPD_LIBS)
......@@ -13,7 +12,6 @@ AC_PROG_CC_C99
AC_PROG_INSTALL
AC_PROG_MAKE_SET
AM_CONFIG_HEADER(config.h)
AC_DEFINE(PROTOCOL_VERSION, "0.14.0", [The mpd protocol version])
MPD_LIBS=""
......@@ -726,7 +724,7 @@ fi
AM_CONDITIONAL(HAVE_OGGFLAC, test x$enable_oggflac = xyes)
AM_CONDITIONAL(HAVE_FLAC_COMMON, test x$enable_flac = xyes || test x$enable_oggflac = xyes)
AM_CONDITIONAL(HAVE_OGG_COMMON, test x$enable_oggvorbis = xyes || test x$enable_oggflac = xyes)
AM_CONDITIONAL(HAVE_OGG_COMMON, test x$enable_oggvorbis = xyes || test x$enable_oggflac = xyes || test x$enable_flac = xyes)
if test x$enable_audiofile = xyes; then
PKG_CHECK_MODULES(AUDIOFILE, [audiofile >= 0.1.7],
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# Generated from ltversion.in.
# serial 3012 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.2.6])
m4_define([LT_PACKAGE_REVISION], [1.3012])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.2.6'
macro_revision='1.3012'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 4 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
......@@ -59,7 +59,7 @@ mpd_headers = \
playerData.h \
playlist.h \
playlist_save.h \
replayGain.h \
replay_gain.h \
signal_check.h \
sig_handlers.h \
song.h \
......@@ -137,7 +137,7 @@ mpd_SOURCES = \
playerData.c \
playlist.c \
playlist_save.c \
replayGain.c \
replay_gain.c \
sig_handlers.c \
signal_check.c \
song.c \
......
......@@ -97,7 +97,7 @@ am__mpd_SOURCES_DIST = notify.h ack.h audio.h audio_format.h \
compress.h os_compat.h pipe.h path.h mapper.h pcm_utils.h \
pcm_channels.h pcm_resample.h pcm_dither.h permission.h \
player_thread.h player_control.h playerData.h playlist.h \
playlist_save.h replayGain.h signal_check.h sig_handlers.h \
playlist_save.h replay_gain.h signal_check.h sig_handlers.h \
song.h song_print.h song_save.h songvec.h state_file.h stats.h \
tag.h tag_internal.h tag_pool.h tag_id3.h tag_print.h \
tag_save.h strset.h utils.h volume.h ioops.h zeroconf.h \
......@@ -112,7 +112,7 @@ am__mpd_SOURCES_DIST = notify.h ack.h audio.h audio_format.h \
main_notify.c normalize.c compress.c pipe.c path.c mapper.c \
pcm_utils.c pcm_channels.c pcm_resample.c pcm_dither.c \
permission.c player_thread.c player_control.c playerData.c \
playlist.c playlist_save.c replayGain.c sig_handlers.c \
playlist.c playlist_save.c replay_gain.c sig_handlers.c \
signal_check.c song.c song_print.c song_save.c songvec.c \
state_file.c stats.c tag.c tag_pool.c tag_print.c tag_save.c \
strset.c utils.c volume.c locate.c stored_playlist.c timer.c \
......@@ -183,7 +183,7 @@ am_mpd_OBJECTS = $(am__objects_1) mpd-notify.$(OBJEXT) \
mpd-permission.$(OBJEXT) mpd-player_thread.$(OBJEXT) \
mpd-player_control.$(OBJEXT) mpd-playerData.$(OBJEXT) \
mpd-playlist.$(OBJEXT) mpd-playlist_save.$(OBJEXT) \
mpd-replayGain.$(OBJEXT) mpd-sig_handlers.$(OBJEXT) \
mpd-replay_gain.$(OBJEXT) mpd-sig_handlers.$(OBJEXT) \
mpd-signal_check.$(OBJEXT) mpd-song.$(OBJEXT) \
mpd-song_print.$(OBJEXT) mpd-song_save.$(OBJEXT) \
mpd-songvec.$(OBJEXT) mpd-state_file.$(OBJEXT) \
......@@ -475,7 +475,7 @@ mpd_headers = \
playerData.h \
playlist.h \
playlist_save.h \
replayGain.h \
replay_gain.h \
signal_check.h \
sig_handlers.h \
song.h \
......@@ -510,7 +510,7 @@ mpd_SOURCES = $(mpd_headers) notify.c audio.c audioOutput.c \
normalize.c compress.c pipe.c path.c mapper.c pcm_utils.c \
pcm_channels.c pcm_resample.c pcm_dither.c permission.c \
player_thread.c player_control.c playerData.c playlist.c \
playlist_save.c replayGain.c sig_handlers.c signal_check.c \
playlist_save.c replay_gain.c sig_handlers.c signal_check.c \
song.c song_print.c song_save.c songvec.c state_file.c stats.c \
tag.c tag_pool.c tag_print.c tag_save.c strset.c utils.c \
volume.c locate.c stored_playlist.c timer.c $(am__append_1) \
......@@ -699,7 +699,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-playlist.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-playlist_save.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-pulse_plugin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-replayGain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-replay_gain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-shout_mp3.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-shout_ogg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-shout_plugin.Po@am__quote@
......@@ -1453,19 +1453,19 @@ mpd-playlist_save.obj: playlist_save.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-playlist_save.obj `if test -f 'playlist_save.c'; then $(CYGPATH_W) 'playlist_save.c'; else $(CYGPATH_W) '$(srcdir)/playlist_save.c'; fi`
mpd-replayGain.o: replayGain.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -MT mpd-replayGain.o -MD -MP -MF "$(DEPDIR)/mpd-replayGain.Tpo" -c -o mpd-replayGain.o `test -f 'replayGain.c' || echo '$(srcdir)/'`replayGain.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mpd-replayGain.Tpo" "$(DEPDIR)/mpd-replayGain.Po"; else rm -f "$(DEPDIR)/mpd-replayGain.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='replayGain.c' object='mpd-replayGain.o' libtool=no @AMDEPBACKSLASH@
mpd-replay_gain.o: replay_gain.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -MT mpd-replay_gain.o -MD -MP -MF "$(DEPDIR)/mpd-replay_gain.Tpo" -c -o mpd-replay_gain.o `test -f 'replay_gain.c' || echo '$(srcdir)/'`replay_gain.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mpd-replay_gain.Tpo" "$(DEPDIR)/mpd-replay_gain.Po"; else rm -f "$(DEPDIR)/mpd-replay_gain.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='replay_gain.c' object='mpd-replay_gain.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-replayGain.o `test -f 'replayGain.c' || echo '$(srcdir)/'`replayGain.c
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-replay_gain.o `test -f 'replay_gain.c' || echo '$(srcdir)/'`replay_gain.c
mpd-replayGain.obj: replayGain.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -MT mpd-replayGain.obj -MD -MP -MF "$(DEPDIR)/mpd-replayGain.Tpo" -c -o mpd-replayGain.obj `if test -f 'replayGain.c'; then $(CYGPATH_W) 'replayGain.c'; else $(CYGPATH_W) '$(srcdir)/replayGain.c'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mpd-replayGain.Tpo" "$(DEPDIR)/mpd-replayGain.Po"; else rm -f "$(DEPDIR)/mpd-replayGain.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='replayGain.c' object='mpd-replayGain.obj' libtool=no @AMDEPBACKSLASH@
mpd-replay_gain.obj: replay_gain.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -MT mpd-replay_gain.obj -MD -MP -MF "$(DEPDIR)/mpd-replay_gain.Tpo" -c -o mpd-replay_gain.obj `if test -f 'replay_gain.c'; then $(CYGPATH_W) 'replay_gain.c'; else $(CYGPATH_W) '$(srcdir)/replay_gain.c'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mpd-replay_gain.Tpo" "$(DEPDIR)/mpd-replay_gain.Po"; else rm -f "$(DEPDIR)/mpd-replay_gain.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='replay_gain.c' object='mpd-replay_gain.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-replayGain.obj `if test -f 'replayGain.c'; then $(CYGPATH_W) 'replayGain.c'; else $(CYGPATH_W) '$(srcdir)/replayGain.c'; fi`
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-replay_gain.obj `if test -f 'replay_gain.c'; then $(CYGPATH_W) 'replay_gain.c'; else $(CYGPATH_W) '$(srcdir)/replay_gain.c'; fi`
mpd-sig_handlers.o: sig_handlers.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mpd_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -MT mpd-sig_handlers.o -MD -MP -MF "$(DEPDIR)/mpd-sig_handlers.Tpo" -c -o mpd-sig_handlers.o `test -f 'sig_handlers.c' || echo '$(srcdir)/'`sig_handlers.c; \
......
......@@ -70,21 +70,21 @@ static void flacParseReplayGain(const FLAC__StreamMetadata * block,
int found = 0;
if (data->replayGainInfo)
freeReplayGainInfo(data->replayGainInfo);
replay_gain_info_free(data->replayGainInfo);
data->replayGainInfo = newReplayGainInfo();
data->replayGainInfo = replay_gain_info_new();
found |= flacFindVorbisCommentFloat(block, "replaygain_album_gain",
&data->replayGainInfo->albumGain);
&data->replayGainInfo->tuples[REPLAY_GAIN_ALBUM].gain);
found |= flacFindVorbisCommentFloat(block, "replaygain_album_peak",
&data->replayGainInfo->albumPeak);
&data->replayGainInfo->tuples[REPLAY_GAIN_ALBUM].peak);
found |= flacFindVorbisCommentFloat(block, "replaygain_track_gain",
&data->replayGainInfo->trackGain);
&data->replayGainInfo->tuples[REPLAY_GAIN_TRACK].gain);
found |= flacFindVorbisCommentFloat(block, "replaygain_track_peak",
&data->replayGainInfo->trackPeak);
&data->replayGainInfo->tuples[REPLAY_GAIN_TRACK].peak);
if (!found) {
freeReplayGainInfo(data->replayGainInfo);
replay_gain_info_free(data->replayGainInfo);
data->replayGainInfo = NULL;
}
}
......
......@@ -145,7 +145,7 @@ typedef struct {
FLAC__uint64 position;
struct decoder *decoder;
struct input_stream *inStream;
ReplayGainInfo *replayGainInfo;
struct replay_gain_info *replayGainInfo;
struct tag *tag;
} FlacData;
......
......@@ -33,8 +33,7 @@ typedef struct {
size_t bytesIntoBuffer;
size_t bytesConsumed;
off_t fileOffset;
unsigned char *buffer;
bool atEof;
unsigned char buffer[FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS];
} AacBuffer;
static void aac_buffer_shift(AacBuffer * b, size_t length)
......@@ -52,25 +51,20 @@ static void aac_buffer_shift(AacBuffer * b, size_t length)
static void fillAacBuffer(AacBuffer * b)
{
size_t bread;
size_t rest, bread;
if (b->bytesIntoBuffer >= FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
if (b->bytesConsumed > 0)
aac_buffer_shift(b, b->bytesConsumed);
rest = sizeof(b->buffer) - b->bytesIntoBuffer;
if (rest == 0)
/* buffer already full */
return;
aac_buffer_shift(b, b->bytesConsumed);
if (!b->atEof) {
size_t rest = FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS -
b->bytesIntoBuffer;
bread = decoder_read(b->decoder, b->inStream,
(void *)(b->buffer + b->bytesIntoBuffer),
rest);
if (bread == 0 && input_stream_eof(b->inStream))
b->atEof = true;
b->bytesIntoBuffer += bread;
}
bread = decoder_read(b->decoder, b->inStream,
(void *)(b->buffer + b->bytesIntoBuffer),
rest);
b->bytesIntoBuffer += bread;
if ((b->bytesIntoBuffer > 3 && memcmp(b->buffer, "TAG", 3) == 0) ||
(b->bytesIntoBuffer > 11 &&
......@@ -86,7 +80,7 @@ static void advanceAacBuffer(AacBuffer * b, size_t bytes)
b->bytesIntoBuffer -= bytes;
}
static int adtsSampleRates[] =
static const unsigned adtsSampleRates[] =
{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
......@@ -146,7 +140,7 @@ static size_t adts_find_frame(AacBuffer * b)
static void adtsParse(AacBuffer * b, float *length)
{
unsigned int frames, frameLength;
int sample_rate = 0;
unsigned sample_rate = 0;
float framesPerSec;
/* Read all frames to ensure correct time and bitrate */
......@@ -170,7 +164,7 @@ static void adtsParse(AacBuffer * b, float *length)
}
framesPerSec = (float)sample_rate / 1024.0;
if (framesPerSec != 0)
if (framesPerSec > 0)
*length = (float)frames / framesPerSec;
}
......@@ -182,9 +176,6 @@ initAacBuffer(AacBuffer * b, struct decoder *decoder,
b->decoder = decoder;
b->inStream = inStream;
b->buffer = xmalloc(FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
memset(b->buffer, 0, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
}
static void aac_parse_header(AacBuffer * b, float *length)
......@@ -212,7 +203,8 @@ static void aac_parse_header(AacBuffer * b, float *length)
if (length == NULL)
return;
if (b->bytesIntoBuffer >= 2 &&
if (b->inStream->seekable &&
b->bytesIntoBuffer >= 2 &&
(b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
adtsParse(b, length);
input_stream_seek(b->inStream, tagsize, SEEK_SET);
......@@ -223,8 +215,15 @@ static void aac_parse_header(AacBuffer * b, float *length)
fillAacBuffer(b);
} else if (memcmp(b->buffer, "ADIF", 4) == 0) {
int bitRate;
int skipSize = (b->buffer[4] & 0x80) ? 9 : 0;
unsigned bitRate;
size_t skipSize = (b->buffer[4] & 0x80) ? 9 : 0;
if (8 + skipSize > b->bytesIntoBuffer)
/* not enough data yet; skip parsing this
header */
return;
bitRate =
((unsigned int)(b->
buffer[4 +
......@@ -301,7 +300,7 @@ static int getAacTotalTime(const char *file)
return file_time;
}
static bool
static void
aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
{
float file_time;
......@@ -310,7 +309,6 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
faacDecFrameInfo frameInfo;
faacDecConfigurationPtr config;
long bread;
struct audio_format audio_format;
uint32_t sample_rate;
unsigned char channels;
unsigned int sampleCount;
......@@ -319,8 +317,10 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
uint16_t bitRate = 0;
AacBuffer b;
bool initialized = false;
enum decoder_command cmd;
initAacBuffer(&b, mpd_decoder, inStream);
aac_parse_header(&b, &totalTime);
decoder = faacDecOpen();
......@@ -334,8 +334,8 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
#endif
faacDecSetConfiguration(decoder, config);
while (b.bytesIntoBuffer < FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS &&
!b.atEof &&
while (b.bytesIntoBuffer < sizeof(b.buffer) &&
!input_stream_eof(b.inStream) &&
decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) {
fillAacBuffer(&b);
adts_find_frame(&b);
......@@ -354,11 +354,9 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
return false;
return;
}
audio_format.bits = 16;
file_time = 0.0;
advanceAacBuffer(&b, bread);
......@@ -389,136 +387,12 @@ aac_stream_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
#endif
if (!initialized) {
audio_format.channels = frameInfo.channels;
audio_format.sample_rate = sample_rate;
decoder_initialized(mpd_decoder, &audio_format,
false, totalTime);
initialized = true;
}
advanceAacBuffer(&b, frameInfo.bytesconsumed);
sampleCount = (unsigned long)(frameInfo.samples);
if (sampleCount > 0) {
bitRate = frameInfo.bytesconsumed * 8.0 *
frameInfo.channels * sample_rate /
frameInfo.samples / 1000 + 0.5;
file_time +=
(float)(frameInfo.samples) / frameInfo.channels /
sample_rate;
}
sampleBufferLen = sampleCount * 2;
decoder_data(mpd_decoder, NULL, sampleBuffer,
sampleBufferLen, file_time,
bitRate, NULL);
} while (decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE);
faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
if (!initialized)
return false;
return true;
}
static bool
aac_decode(struct decoder *mpd_decoder, const char *path)
{
float file_time;
float totalTime;
faacDecHandle decoder;
faacDecFrameInfo frameInfo;
faacDecConfigurationPtr config;
long bread;
struct audio_format audio_format;
uint32_t sample_rate;
unsigned char channels;
unsigned int sampleCount;
char *sampleBuffer;
size_t sampleBufferLen;
/*float * seekTable;
long seekTableEnd = -1;
int seekPositionFound = 0; */
uint16_t bitRate = 0;
AacBuffer b;
struct input_stream inStream;
bool initialized = false;
if ((totalTime = getAacFloatTotalTime(path)) < 0)
return false;
if (!input_stream_open(&inStream, path))
return false;
initAacBuffer(&b, mpd_decoder, &inStream);
aac_parse_header(&b, NULL);
const struct audio_format audio_format = {
.bits = 16,
.channels = frameInfo.channels,
.sample_rate = sample_rate,
};
decoder = faacDecOpen();
config = faacDecGetCurrentConfiguration(decoder);
config->outputFormat = FAAD_FMT_16BIT;
#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
config->downMatrix = 1;
#endif
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
config->dontUpSampleImplicitSBR = 0;
#endif
faacDecSetConfiguration(decoder, config);
fillAacBuffer(&b);
#ifdef HAVE_FAAD_BUFLEN_FUNCS
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
&sample_rate, &channels);
#else
bread = faacDecInit(decoder, b.buffer, &sample_rate, &channels);
#endif
if (bread < 0) {
ERROR("Error not a AAC stream.\n");
faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
return false;
}
audio_format.bits = 16;
file_time = 0.0;
advanceAacBuffer(&b, bread);
do {
fillAacBuffer(&b);
if (b.bytesIntoBuffer == 0)
break;
#ifdef HAVE_FAAD_BUFLEN_FUNCS
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer,
b.bytesIntoBuffer);
#else
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer);
#endif
if (frameInfo.error > 0) {
ERROR("error decoding AAC file: %s\n", path);
ERROR("faad2 error: %s\n",
faacDecGetErrorMessage(frameInfo.error));
break;
}
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
sample_rate = frameInfo.samplerate;
#endif
if (!initialized) {
audio_format.channels = frameInfo.channels;
audio_format.sample_rate = sample_rate;
decoder_initialized(mpd_decoder, &audio_format,
false, totalTime);
initialized = true;
......@@ -539,19 +413,14 @@ aac_decode(struct decoder *mpd_decoder, const char *path)
sampleBufferLen = sampleCount * 2;
decoder_data(mpd_decoder, NULL, sampleBuffer,
sampleBufferLen, file_time,
bitRate, NULL);
} while (decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE);
cmd = decoder_data(mpd_decoder, NULL, sampleBuffer,
sampleBufferLen, file_time,
bitRate, NULL);
if (cmd == DECODE_COMMAND_SEEK)
decoder_seek_error(mpd_decoder);
} while (cmd != DECODE_COMMAND_STOP);
faacDecClose(decoder);
if (b.buffer)
free(b.buffer);
if (!initialized)
return false;
return true;
}
static struct tag *aacTagDup(const char *file)
......@@ -577,7 +446,6 @@ static const char *const aac_mimeTypes[] = { "audio/aac", "audio/aacp", NULL };
const struct decoder_plugin aacPlugin = {
.name = "aac",
.stream_decode = aac_stream_decode,
.file_decode = aac_decode,
.tag_dup = aacTagDup,
.suffixes = aac_suffixes,
.mime_types = aac_mimeTypes
......
......@@ -41,7 +41,7 @@ static int getAudiofileTotalTime(const char *file)
return total_time;
}
static bool
static void
audiofile_decode(struct decoder *decoder, const char *path)
{
int fs, frame_count;
......@@ -56,13 +56,13 @@ audiofile_decode(struct decoder *decoder, const char *path)
if (stat(path, &st) < 0) {
ERROR("failed to stat: %s\n", path);
return false;
return;
}
af_fp = afOpenFile(path, "r", NULL);
if (af_fp == AF_NULL_FILEHANDLE) {
ERROR("failed to open: %s\n", path);
return false;
return;
}
afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK,
......@@ -84,7 +84,7 @@ audiofile_decode(struct decoder *decoder, const char *path)
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
path, audio_format.bits);
afCloseFile(af_fp);
return false;
return;
}
fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
......@@ -112,7 +112,6 @@ audiofile_decode(struct decoder *decoder, const char *path)
} while (decoder_get_command(decoder) != DECODE_COMMAND_STOP);
afCloseFile(af_fp);
return true;
}
static struct tag *audiofileTagDup(const char *file)
......
......@@ -193,12 +193,6 @@ ffmpeg_helper(struct input_stream *input,
return ret;
}
static bool
ffmpeg_try_decode(struct input_stream *input)
{
return ffmpeg_helper(input, NULL, NULL);
}
static enum decoder_command
ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
const AVPacket *packet,
......@@ -287,7 +281,7 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
return true;
}
static bool
static void
ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
{
struct ffmpeg_context ctx;
......@@ -295,7 +289,7 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
ctx.input = input;
ctx.decoder = decoder;
return ffmpeg_helper(input, ffmpeg_decode_internal, &ctx);
ffmpeg_helper(input, ffmpeg_decode_internal, &ctx);
}
static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
......@@ -370,7 +364,6 @@ static const char *const ffmpeg_mime_types[] = {
const struct decoder_plugin ffmpeg_plugin = {
.name = "ffmpeg",
.init = ffmpeg_init,
.try_decode = ffmpeg_try_decode,
.stream_decode = ffmpeg_decode,
.tag_dup = ffmpeg_tag,
.suffixes = ffmpeg_suffixes,
......
......@@ -301,7 +301,7 @@ static struct tag *flacTagDup(const char *file)
return ret;
}
static bool
static void
flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
bool is_ogg)
{
......@@ -310,7 +310,7 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
const char *err = NULL;
if (!(flacDec = flac_new()))
return false;
return;
init_FlacData(&data, decoder, inStream);
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
......@@ -335,10 +335,11 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
err = "doing init()";
goto fail;
}
if (!flac_process_metadata(flacDec)) {
err = "problem reading metadata";
goto fail;
}
}
if (!flac_process_metadata(flacDec)) {
err = "problem reading metadata";
goto fail;
}
decoder_initialized(decoder, &data.audio_format,
......@@ -367,26 +368,39 @@ flac_decode_internal(struct decoder * decoder, struct input_stream *inStream,
fail:
if (data.replayGainInfo)
freeReplayGainInfo(data.replayGainInfo);
replay_gain_info_free(data.replayGainInfo);
if (flacDec)
flac_delete(flacDec);
if (err) {
ERROR("flac %s\n", err);
return false;
return;
}
return true;
return;
}
static bool
static void
flac_decode(struct decoder * decoder, struct input_stream *inStream)
{
return flac_decode_internal(decoder, inStream, false);
flac_decode_internal(decoder, inStream, false);
}
#ifndef HAVE_OGGFLAC
static bool
oggflac_init(void)
{
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
return !!FLAC_API_SUPPORTS_OGG_FLAC;
#else
/* disable oggflac when libflac is too old */
return false;
#endif
}
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 && \
!defined(HAVE_OGGFLAC)
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
static struct tag *oggflac_tag_dup(const char *file)
{
struct tag *ret = NULL;
......@@ -417,17 +431,17 @@ out:
return ret;
}
static bool
static void
oggflac_decode(struct decoder *decoder, struct input_stream *inStream)
{
return flac_decode_internal(decoder, inStream, true);
}
if (ogg_stream_type_detect(inStream) != FLAC)
return;
static bool
oggflac_try_decode(struct input_stream *inStream)
{
return FLAC_API_SUPPORTS_OGG_FLAC &&
ogg_stream_type_detect(inStream) == FLAC;
/* rewind the stream, because ogg_stream_type_detect() has
moved it */
input_stream_seek(inStream, 0, SEEK_SET);
flac_decode_internal(decoder, inStream, true);
}
static const char *const oggflac_suffixes[] = { "ogg", "oga", NULL };
......@@ -438,16 +452,20 @@ static const char *const oggflac_mime_types[] = {
NULL
};
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
const struct decoder_plugin oggflacPlugin = {
.name = "oggflac",
.try_decode = oggflac_try_decode,
.init = oggflac_init,
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
.stream_decode = oggflac_decode,
.tag_dup = oggflac_tag_dup,
.suffixes = oggflac_suffixes,
.mime_types = oggflac_mime_types
#endif
};
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
#endif /* HAVE_OGGFLAC */
static const char *const flacSuffixes[] = { "flac", NULL };
static const char *const flac_mime_types[] = {
......
......@@ -160,7 +160,7 @@ static void mod_close(mod_Data * data)
free(data);
}
static bool
static void
mod_decode(struct decoder *decoder, const char *path)
{
mod_Data *data;
......@@ -173,7 +173,7 @@ mod_decode(struct decoder *decoder, const char *path)
if (!(data = mod_open(path))) {
ERROR("failed to open mod: %s\n", path);
MikMod_Exit();
return false;
return;
}
audio_format.bits = 16;
......@@ -197,8 +197,6 @@ mod_decode(struct decoder *decoder, const char *path)
mod_close(data);
MikMod_Exit();
return true;
}
static struct tag *modTagDup(const char *file)
......
......@@ -204,16 +204,17 @@ mp3_fill_buffer(struct mp3_data *data)
}
#ifdef HAVE_ID3TAG
static ReplayGainInfo *parse_id3_replay_gain_info(struct id3_tag *tag)
static struct replay_gain_info *
parse_id3_replay_gain_info(struct id3_tag *tag)
{
int i;
char *key;
char *value;
struct id3_frame *frame;
bool found = false;
ReplayGainInfo *replay_gain_info;
struct replay_gain_info *replay_gain_info;
replay_gain_info = newReplayGainInfo();
replay_gain_info = replay_gain_info_new();
for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
if (frame->nfields < 3)
......@@ -227,16 +228,16 @@ static ReplayGainInfo *parse_id3_replay_gain_info(struct id3_tag *tag)
(&frame->fields[2]));
if (strcasecmp(key, "replaygain_track_gain") == 0) {
replay_gain_info->trackGain = atof(value);
replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain = atof(value);
found = true;
} else if (strcasecmp(key, "replaygain_album_gain") == 0) {
replay_gain_info->albumGain = atof(value);
replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain = atof(value);
found = true;
} else if (strcasecmp(key, "replaygain_track_peak") == 0) {
replay_gain_info->trackPeak = atof(value);
replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak = atof(value);
found = true;
} else if (strcasecmp(key, "replaygain_album_peak") == 0) {
replay_gain_info->albumPeak = atof(value);
replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak = atof(value);
found = true;
}
......@@ -246,7 +247,7 @@ static ReplayGainInfo *parse_id3_replay_gain_info(struct id3_tag *tag)
if (found)
return replay_gain_info;
freeReplayGainInfo(replay_gain_info);
replay_gain_info_free(replay_gain_info);
return NULL;
}
#endif
......@@ -254,7 +255,7 @@ static ReplayGainInfo *parse_id3_replay_gain_info(struct id3_tag *tag)
#ifdef HAVE_ID3TAG
static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
struct tag **mpd_tag,
ReplayGainInfo **replay_gain_info_r)
struct replay_gain_info **replay_gain_info_r)
{
struct id3_tag *id3_tag = NULL;
id3_length_t count;
......@@ -307,10 +308,11 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
}
if (replay_gain_info_r) {
ReplayGainInfo *tmp_rgi = parse_id3_replay_gain_info(id3_tag);
struct replay_gain_info *tmp_rgi =
parse_id3_replay_gain_info(id3_tag);
if (tmp_rgi != NULL) {
if (*replay_gain_info_r)
freeReplayGainInfo(*replay_gain_info_r);
replay_gain_info_free(*replay_gain_info_r);
*replay_gain_info_r = tmp_rgi;
}
}
......@@ -323,7 +325,7 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
static enum mp3_action
decode_next_frame_header(struct mp3_data *data, struct tag **tag,
ReplayGainInfo **replay_gain_info_r)
struct replay_gain_info **replay_gain_info_r)
{
enum mad_layer layer;
......@@ -698,9 +700,8 @@ mp3_filesize_to_song_length(struct mp3_data *data)
static bool
mp3_decode_first_frame(struct mp3_data *data, struct tag **tag,
ReplayGainInfo **replay_gain_info_r)
struct replay_gain_info **replay_gain_info_r)
{
struct decoder *decoder = data->decoder;
struct xing xing;
struct lame lame;
struct mad_bitptr ptr;
......@@ -712,17 +713,18 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag,
xing.flags = 0;
while (true) {
while ((ret = decode_next_frame_header(data, tag, replay_gain_info_r)) == DECODE_CONT &&
(!decoder || decoder_get_command(decoder) == DECODE_COMMAND_NONE));
if (ret == DECODE_BREAK ||
(decoder && decoder_get_command(decoder) != DECODE_COMMAND_NONE))
do {
ret = decode_next_frame_header(data, tag,
replay_gain_info_r);
} while (ret == DECODE_CONT);
if (ret == DECODE_BREAK)
return false;
if (ret == DECODE_SKIP) continue;
while ((ret = decodeNextFrame(data)) == DECODE_CONT &&
(!decoder || decoder_get_command(decoder) == DECODE_COMMAND_NONE));
if (ret == DECODE_BREAK ||
(decoder && decoder_get_command(decoder) != DECODE_COMMAND_NONE))
do {
ret = decodeNextFrame(data);
} while (ret == DECODE_CONT);
if (ret == DECODE_BREAK)
return false;
if (ret == DECODE_OK) break;
}
......@@ -758,9 +760,9 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag,
* parse_lame() for details. -- jat */
if (replay_gain_info_r && !*replay_gain_info_r &&
lame.track_gain) {
*replay_gain_info_r = newReplayGainInfo();
(*replay_gain_info_r)->trackGain = lame.track_gain;
(*replay_gain_info_r)->trackPeak = lame.peak;
*replay_gain_info_r = replay_gain_info_new();
(*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
(*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
}
}
}
......@@ -813,7 +815,7 @@ static int mp3_total_file_time(const char *file)
static bool
mp3_open(struct input_stream *is, struct mp3_data *data,
struct decoder *decoder, struct tag **tag,
ReplayGainInfo **replay_gain_info_r)
struct replay_gain_info **replay_gain_info_r)
{
mp3_data_init(data, decoder, is);
*tag = NULL;
......@@ -877,7 +879,7 @@ mp3_update_timer_next_frame(struct mp3_data *data)
*/
static enum decoder_command
mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length,
ReplayGainInfo *replay_gain_info)
struct replay_gain_info *replay_gain_info)
{
unsigned max_samples;
......@@ -916,7 +918,8 @@ mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length,
* Synthesize the current frame and send it via decoder_data().
*/
static enum decoder_command
mp3_synth_and_send(struct mp3_data *data, ReplayGainInfo *replay_gain_info)
mp3_synth_and_send(struct mp3_data *data,
struct replay_gain_info *replay_gain_info)
{
unsigned i, pcm_length;
enum decoder_command cmd;
......@@ -971,7 +974,7 @@ mp3_synth_and_send(struct mp3_data *data, ReplayGainInfo *replay_gain_info)
}
static bool
mp3_read(struct mp3_data *data, ReplayGainInfo **replay_gain_info_r)
mp3_read(struct mp3_data *data, struct replay_gain_info **replay_gain_info_r)
{
struct decoder *decoder = data->decoder;
int ret;
......@@ -1018,21 +1021,30 @@ mp3_read(struct mp3_data *data, ReplayGainInfo **replay_gain_info_r)
while (true) {
bool skip = false;
while ((ret =
decode_next_frame_header(data, NULL,
replay_gain_info_r)) == DECODE_CONT
&& decoder_get_command(decoder) == DECODE_COMMAND_NONE) ;
if (ret == DECODE_BREAK || decoder_get_command(decoder) != DECODE_COMMAND_NONE)
do {
struct tag *tag = NULL;
ret = decode_next_frame_header(data, &tag,
replay_gain_info_r);
if (tag != NULL) {
decoder_tag(decoder, data->input_stream, tag);
tag_free(tag);
}
} while (ret == DECODE_CONT);
if (ret == DECODE_BREAK)
return false;
else if (ret == DECODE_SKIP)
skip = true;
if (data->mute_frame == MUTEFRAME_NONE) {
while ((ret = decodeNextFrame(data)) == DECODE_CONT &&
decoder_get_command(decoder) == DECODE_COMMAND_NONE) ;
if (ret == DECODE_BREAK ||
decoder_get_command(decoder) != DECODE_COMMAND_NONE)
do {
ret = decodeNextFrame(data);
} while (ret == DECODE_CONT);
if (ret == DECODE_BREAK)
return false;
}
if (!skip && ret == DECODE_OK)
break;
}
......@@ -1047,21 +1059,19 @@ static void mp3_audio_format(struct mp3_data *data, struct audio_format *af)
af->channels = MAD_NCHANNELS(&(data->frame).header);
}
static bool
static void
mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
{
struct mp3_data data;
struct tag *tag = NULL;
ReplayGainInfo *replay_gain_info = NULL;
struct replay_gain_info *replay_gain_info = NULL;
struct audio_format audio_format;
if (!mp3_open(input_stream, &data, decoder, &tag, &replay_gain_info)) {
if (decoder_get_command(decoder) == DECODE_COMMAND_NONE) {
if (decoder_get_command(decoder) == DECODE_COMMAND_NONE)
ERROR
("Input does not appear to be a mp3 bit stream.\n");
return false;
}
return true;
return;
}
mp3_audio_format(&data, &audio_format);
......@@ -1077,14 +1087,13 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
while (mp3_read(&data, &replay_gain_info)) ;
if (replay_gain_info)
freeReplayGainInfo(replay_gain_info);
replay_gain_info_free(replay_gain_info);
if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK &&
data.mute_frame == MUTEFRAME_SEEK)
decoder_command_finished(decoder);
mp3_data_finish(&data);
return true;
}
static struct tag *mp3_tag_dup(const char *file)
......
......@@ -90,7 +90,7 @@ mp4_seek(void *user_data, uint64_t position)
? 0 : -1;
}
static bool
static void
mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
{
struct mp4_context ctx = {
......@@ -133,14 +133,14 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
mp4fh = mp4ff_open_read(&callback);
if (!mp4fh) {
g_warning("Input does not appear to be a mp4 stream.\n");
return false;
return;
}
track = mp4_get_aac_track(mp4fh);
if (track < 0) {
g_warning("No AAC track found in mp4 stream.\n");
mp4ff_close(mp4fh);
return false;
return;
}
decoder = faacDecOpen();
......@@ -164,7 +164,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
g_warning("Not an AAC stream.\n");
faacDecClose(decoder);
mp4ff_close(mp4fh);
return false;
return;
}
file_time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
......@@ -176,7 +176,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
g_warning("Error getting audio format of mp4 AAC track.\n");
faacDecClose(decoder);
mp4ff_close(mp4fh);
return false;
return;
}
total_time = ((float)file_time) / scale;
......@@ -185,7 +185,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
g_warning("Integer overflow.\n");
faacDecClose(decoder);
mp4ff_close(mp4fh);
return false;
return;
}
file_time = 0.0;
......@@ -299,14 +299,6 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
free(seek_table);
faacDecClose(decoder);
mp4ff_close(mp4fh);
if (!initialized)
return false;
if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK && seeking)
decoder_command_finished(mpd_decoder);
return true;
}
static struct tag *
......
......@@ -17,10 +17,9 @@
*/
#include "../decoder_api.h"
#include "../utils.h"
#include "../log.h"
#include <mpcdec/mpcdec.h>
#include <glib.h>
typedef struct _MpcCallbackData {
struct input_stream *inStream;
......@@ -96,7 +95,15 @@ static inline int32_t convertSample(MPC_SAMPLE_FORMAT sample)
return val;
}
static bool
static void
mpc_to_mpd_buffer(int32_t *dest, const MPC_SAMPLE_FORMAT *src,
unsigned num_samples)
{
while (num_samples-- > 0)
*dest++ = convertSample(*src++);
}
static void
mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
{
mpc_decoder decoder;
......@@ -108,19 +115,15 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
bool eof = false;
long ret;
#define MPC_CHUNK_SIZE 4096
char chunk[MPC_CHUNK_SIZE];
int chunkpos = 0;
mpc_uint32_t ret;
int32_t chunk[G_N_ELEMENTS(sample_buffer)];
long bitRate = 0;
int32_t *dest = (int32_t *) chunk;
unsigned long samplePos = 0;
mpc_uint32_t vbrUpdateAcc;
mpc_uint32_t vbrUpdateBits;
float total_time;
int i;
ReplayGainInfo *replayGainInfo = NULL;
struct replay_gain_info *replayGainInfo = NULL;
enum decoder_command cmd = DECODE_COMMAND_NONE;
data.inStream = inStream;
data.decoder = mpd_decoder;
......@@ -135,46 +138,40 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
mpc_streaminfo_init(&info);
if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) {
if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP) {
ERROR("Not a valid musepack stream\n");
return false;
}
return true;
if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP)
g_warning("Not a valid musepack stream\n");
return;
}
mpc_decoder_setup(&decoder, &reader);
if (!mpc_decoder_initialize(&decoder, &info)) {
if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP) {
ERROR("Not a valid musepack stream\n");
return false;
}
return true;
if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP)
g_warning("Not a valid musepack stream\n");
return;
}
audio_format.bits = 24;
audio_format.channels = info.channels;
audio_format.sample_rate = info.sample_freq;
replayGainInfo = newReplayGainInfo();
replayGainInfo->albumGain = info.gain_album * 0.01;
replayGainInfo->albumPeak = info.peak_album / 32767.0;
replayGainInfo->trackGain = info.gain_title * 0.01;
replayGainInfo->trackPeak = info.peak_title / 32767.0;
replayGainInfo = replay_gain_info_new();
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01;
replayGainInfo->tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0;
replayGainInfo->tuples[REPLAY_GAIN_TRACK].gain = info.gain_title * 0.01;
replayGainInfo->tuples[REPLAY_GAIN_TRACK].peak = info.peak_title / 32767.0;
decoder_initialized(mpd_decoder, &audio_format,
inStream->seekable,
mpc_streaminfo_get_length(&info));
while (!eof) {
if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK) {
do {
if (cmd == DECODE_COMMAND_SEEK) {
samplePos = decoder_seek_where(mpd_decoder) *
audio_format.sample_rate;
if (mpc_decoder_seek_sample(&decoder, samplePos)) {
dest = (int32_t *)chunk;
chunkpos = 0;
if (mpc_decoder_seek_sample(&decoder, samplePos))
decoder_command_finished(mpd_decoder);
} else
else
decoder_seek_error(mpd_decoder);
}
......@@ -182,58 +179,26 @@ mpc_decode(struct decoder *mpd_decoder, struct input_stream *inStream)
vbrUpdateBits = 0;
ret = mpc_decoder_decode(&decoder, sample_buffer,
&vbrUpdateAcc, &vbrUpdateBits);
if (ret <= 0 || decoder_get_command(mpd_decoder) == DECODE_COMMAND_STOP) {
eof = true;
if (ret == 0 || ret == (mpc_uint32_t)-1)
break;
}
samplePos += ret;
/* ret is in samples, and we have stereo */
ret *= 2;
for (i = 0; i < ret; i++) {
*dest++ = convertSample(sample_buffer[i]);
chunkpos += sizeof(*dest);
if (chunkpos >= MPC_CHUNK_SIZE) {
total_time = ((float)samplePos) /
audio_format.sample_rate;
ret *= info.channels;
bitRate = vbrUpdateBits *
audio_format.sample_rate / 1152 / 1000;
mpc_to_mpd_buffer(chunk, sample_buffer, ret);
decoder_data(mpd_decoder, inStream,
chunk, chunkpos,
total_time,
bitRate, replayGainInfo);
chunkpos = 0;
dest = (int32_t *)chunk;
if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_STOP) {
eof = true;
break;
}
}
}
}
if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP &&
chunkpos > 0) {
total_time = ((float)samplePos) / audio_format.sample_rate;
bitRate = vbrUpdateBits * audio_format.sample_rate
/ 1152 / 1000;
bitRate =
vbrUpdateBits * audio_format.sample_rate / 1152 / 1000;
cmd = decoder_data(mpd_decoder, inStream,
chunk, ret * sizeof(chunk[0]),
total_time,
bitRate, replayGainInfo);
} while (cmd != DECODE_COMMAND_STOP);
decoder_data(mpd_decoder, NULL,
chunk, chunkpos, total_time, bitRate,
replayGainInfo);
}
freeReplayGainInfo(replayGainInfo);
return true;
replay_gain_info_free(replayGainInfo);
}
static float mpcGetTime(const char *file)
......@@ -257,10 +222,8 @@ static float mpcGetTime(const char *file)
mpc_streaminfo_init(&info);
if (!input_stream_open(&inStream, file)) {
DEBUG("mpcGetTime: Failed to open file: %s\n", file);
if (!input_stream_open(&inStream, file))
return -1;
}
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
input_stream_close(&inStream);
......@@ -280,8 +243,8 @@ static struct tag *mpcTagDup(const char *file)
float total_time = mpcGetTime(file);
if (total_time < 0) {
DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n",
file);
g_debug("mpcTagDup: Failed to get Songlength of file: %s\n",
file);
return NULL;
}
......
......@@ -31,7 +31,7 @@ static void oggflac_cleanup(FlacData * data,
OggFLAC__SeekableStreamDecoder * decoder)
{
if (data->replayGainInfo)
freeReplayGainInfo(data->replayGainInfo);
replay_gain_info_free(data->replayGainInfo);
if (decoder)
OggFLAC__seekable_stream_decoder_delete(decoder);
}
......@@ -279,22 +279,18 @@ static struct tag *oggflac_TagDup(const char *file)
return data.tag;
}
static bool oggflac_try_decode(struct input_stream *inStream)
{
return ogg_stream_type_detect(inStream) == FLAC;
}
static bool
static void
oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream)
{
OggFLAC__SeekableStreamDecoder *decoder = NULL;
FlacData data;
bool ret = true;
if (ogg_stream_type_detect(inStream) != FLAC)
return;
init_FlacData(&data, mpd_decoder, inStream);
if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) {
ret = false;
goto fail;
}
......@@ -329,8 +325,6 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream)
fail:
oggflac_cleanup(&data, decoder);
return ret;
}
static const char *const oggflac_Suffixes[] = { "ogg", "oga", NULL };
......@@ -343,7 +337,6 @@ static const char *const oggflac_mime_types[] = {
const struct decoder_plugin oggflacPlugin = {
.name = "oggflac",
.try_decode = oggflac_try_decode,
.stream_decode = oggflac_decode,
.tag_dup = oggflac_TagDup,
.suffixes = oggflac_Suffixes,
......
......@@ -19,8 +19,6 @@
/* TODO 'ogg' should probably be replaced with 'oggvorbis' in all instances */
#include "_ogg_common.h"
#include "../utils.h"
#include "../log.h"
#ifndef HAVE_TREMOR
#include <vorbis/vorbisfile.h>
......@@ -37,6 +35,10 @@
#define ov_time_seek_page(VF, S) (ov_time_seek_page(VF, (S)*1000))
#endif /* HAVE_TREMOR */
#include <glib.h>
#include <errno.h>
#include <stdlib.h>
#ifdef WORDS_BIGENDIAN
#define OGG_DECODE_USE_BIGENDIAN 1
#else
......@@ -93,31 +95,31 @@ static const char *ogg_parseComment(const char *comment, const char *needle)
return NULL;
}
static void ogg_getReplayGainInfo(char **comments, ReplayGainInfo ** infoPtr)
static struct replay_gain_info *
ogg_getReplayGainInfo(char **comments)
{
struct replay_gain_info *rgi;
const char *temp;
bool found = false;
if (*infoPtr)
freeReplayGainInfo(*infoPtr);
*infoPtr = newReplayGainInfo();
rgi = replay_gain_info_new();
while (*comments) {
if ((temp =
ogg_parseComment(*comments, "replaygain_track_gain"))) {
(*infoPtr)->trackGain = atof(temp);
rgi->tuples[REPLAY_GAIN_TRACK].gain = atof(temp);
found = true;
} else if ((temp = ogg_parseComment(*comments,
"replaygain_album_gain"))) {
(*infoPtr)->albumGain = atof(temp);
rgi->tuples[REPLAY_GAIN_ALBUM].gain = atof(temp);
found = true;
} else if ((temp = ogg_parseComment(*comments,
"replaygain_track_peak"))) {
(*infoPtr)->trackPeak = atof(temp);
rgi->tuples[REPLAY_GAIN_TRACK].peak = atof(temp);
found = true;
} else if ((temp = ogg_parseComment(*comments,
"replaygain_album_peak"))) {
(*infoPtr)->albumPeak = atof(temp);
rgi->tuples[REPLAY_GAIN_ALBUM].peak = atof(temp);
found = true;
}
......@@ -125,9 +127,11 @@ static void ogg_getReplayGainInfo(char **comments, ReplayGainInfo ** infoPtr)
}
if (!found) {
freeReplayGainInfo(*infoPtr);
*infoPtr = NULL;
replay_gain_info_free(rgi);
rgi = NULL;
}
return rgi;
}
static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber";
......@@ -194,7 +198,7 @@ static void putOggCommentsIntoOutputBuffer(struct decoder *decoder,
}
/* public */
static bool
static void
oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
{
OggVorbis_File vf;
......@@ -206,13 +210,20 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
long ret;
#define OGG_CHUNK_SIZE 4096
char chunk[OGG_CHUNK_SIZE];
int chunkpos = 0;
long bitRate = 0;
long test;
ReplayGainInfo *replayGainInfo = NULL;
struct replay_gain_info *replayGainInfo = NULL;
char **comments;
const char *errorStr;
bool initialized = false;
enum decoder_command cmd = DECODE_COMMAND_NONE;
if (ogg_stream_type_detect(inStream) != VORBIS)
return;
/* rewind the stream, because ogg_stream_type_detect() has
moved it */
input_stream_seek(inStream, 0, SEEK_SET);
data.inStream = inStream;
data.decoder = decoder;
......@@ -223,7 +234,7 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
callbacks.tell_func = ogg_tell_cb;
if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
if (decoder_get_command(decoder) != DECODE_COMMAND_NONE)
return true;
return;
switch (ret) {
case OV_EREAD:
......@@ -245,27 +256,29 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
errorStr = "unknown error";
break;
}
ERROR("Error decoding Ogg Vorbis stream: %s\n",
errorStr);
return false;
g_warning("Error decoding Ogg Vorbis stream: %s\n",
errorStr);
return;
}
audio_format.bits = 16;
while (true) {
if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) {
do {
if (cmd == DECODE_COMMAND_SEEK) {
double seek_where = decoder_seek_where(decoder);
if (0 == ov_time_seek_page(&vf, seek_where)) {
chunkpos = 0;
decoder_command_finished(decoder);
} else
decoder_seek_error(decoder);
}
ret = ov_read(&vf, chunk + chunkpos,
OGG_CHUNK_SIZE - chunkpos,
ret = ov_read(&vf, chunk, sizeof(chunk),
OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
if (current_section != prev_section) {
/*printf("new song!\n"); */
vorbis_info *vi = ov_info(&vf, -1);
struct replay_gain_info *new_rgi;
audio_format.channels = vi->channels;
audio_format.sample_rate = vi->rate;
if (!initialized) {
......@@ -280,7 +293,12 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
comments = ov_comment(&vf, -1)->user_comments;
putOggCommentsIntoOutputBuffer(decoder, inStream,
comments);
ogg_getReplayGainInfo(comments, &replayGainInfo);
new_rgi = ogg_getReplayGainInfo(comments);
if (new_rgi != NULL) {
if (replayGainInfo != NULL)
replay_gain_info_free(replayGainInfo);
replayGainInfo = new_rgi;
}
}
prev_section = current_section;
......@@ -292,35 +310,19 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream)
break;
}
chunkpos += ret;
if ((test = ov_bitrate_instant(&vf)) > 0)
bitRate = test / 1000;
if (chunkpos >= OGG_CHUNK_SIZE) {
if ((test = ov_bitrate_instant(&vf)) > 0) {
bitRate = test / 1000;
}
decoder_data(decoder, inStream,
chunk, chunkpos,
ov_pcm_tell(&vf) / audio_format.sample_rate,
bitRate, replayGainInfo);
chunkpos = 0;
if (decoder_get_command(decoder) == DECODE_COMMAND_STOP)
break;
}
}
if (decoder_get_command(decoder) == DECODE_COMMAND_NONE &&
chunkpos > 0) {
decoder_data(decoder, NULL,
chunk, chunkpos,
ov_time_tell(&vf), bitRate,
replayGainInfo);
}
cmd = decoder_data(decoder, inStream,
chunk, ret,
ov_pcm_tell(&vf) / audio_format.sample_rate,
bitRate, replayGainInfo);
} while (cmd != DECODE_COMMAND_STOP);
if (replayGainInfo)
freeReplayGainInfo(replayGainInfo);
replay_gain_info_free(replayGainInfo);
ov_clear(&vf);
return true;
}
static struct tag *oggvorbis_TagDup(const char *file)
......@@ -331,10 +333,9 @@ static struct tag *oggvorbis_TagDup(const char *file)
fp = fopen(file, "r");
if (!fp) {
DEBUG("oggvorbis_TagDup: Failed to open file: '%s', %s\n",
file, strerror(errno));
return NULL;
}
if (ov_open(fp, &vf, NULL, 0) < 0) {
fclose(fp);
return NULL;
......@@ -351,12 +352,6 @@ static struct tag *oggvorbis_TagDup(const char *file)
return ret;
}
static bool
oggvorbis_try_decode(struct input_stream *inStream)
{
return ogg_stream_type_detect(inStream) == VORBIS;
}
static const char *const oggvorbis_Suffixes[] = { "ogg","oga", NULL };
static const char *const oggvorbis_MimeTypes[] = {
"application/ogg",
......@@ -367,7 +362,6 @@ static const char *const oggvorbis_MimeTypes[] = {
const struct decoder_plugin oggvorbisPlugin = {
.name = "oggvorbis",
.try_decode = oggvorbis_try_decode,
.stream_decode = oggvorbis_decode,
.tag_dup = oggvorbis_TagDup,
.suffixes = oggvorbis_Suffixes,
......
......@@ -35,7 +35,11 @@ void decoder_initialized(struct decoder * decoder,
bool seekable, float total_time)
{
assert(dc.state == DECODE_STATE_START);
assert(decoder != NULL);
assert(!decoder->stream_tag_sent);
assert(!decoder->seeking);
assert(audio_format != NULL);
assert(audio_format_defined(audio_format));
pcm_convert_init(&decoder->conv_state);
......@@ -96,14 +100,20 @@ size_t decoder_read(struct decoder *decoder,
{
size_t nbytes;
assert(decoder == NULL ||
dc.state == DECODE_STATE_START ||
dc.state == DECODE_STATE_DECODE);
assert(is != NULL);
assert(buffer != NULL);
while (true) {
/* XXX don't allow decoder==NULL */
if (decoder != NULL &&
/* ignore the SEEK command during initialization,
the plugin should handle that after it has
initialized successfully */
(dc.command != DECODE_COMMAND_SEEK ||
!decoder->seeking) &&
(dc.state != DECODE_STATE_START && !decoder->seeking)) &&
dc.command != DECODE_COMMAND_NONE)
return 0;
......@@ -149,13 +159,13 @@ tag_add_stream_tags(const struct tag *src_tag, const struct input_stream *is)
* one.
*/
static enum decoder_command
need_chunks(struct input_stream *is)
need_chunks(struct input_stream *is, bool wait)
{
if (dc.command == DECODE_COMMAND_STOP ||
dc.command == DECODE_COMMAND_SEEK)
return dc.command;
if (is == NULL || input_stream_buffer(is) <= 0) {
if ((is == NULL || input_stream_buffer(is) <= 0) && wait) {
notify_wait(&dc.notify);
notify_signal(&pc.notify);
}
......@@ -168,13 +178,19 @@ decoder_data(struct decoder *decoder,
struct input_stream *is,
void *_data, size_t length,
float data_time, uint16_t bitRate,
ReplayGainInfo *replay_gain_info)
struct replay_gain_info *replay_gain_info)
{
static char *conv_buffer;
static size_t conv_buffer_size;
size_t nbytes;
char *data;
assert(dc.state == DECODE_STATE_DECODE);
if (dc.command == DECODE_COMMAND_STOP ||
dc.command == DECODE_COMMAND_SEEK)
return dc.command;
if (is != NULL && !decoder->stream_tag_sent) {
const struct tag *src;
struct tag *tag1, *tag2;
......@@ -225,8 +241,8 @@ decoder_data(struct decoder *decoder,
data, &decoder->conv_state);
}
if (replay_gain_info != NULL && (replayGainState != REPLAYGAIN_OFF))
doReplayGain(replay_gain_info, data, length,
if (replay_gain_info != NULL && (replay_gain_mode != REPLAY_GAIN_OFF))
replay_gain_apply(replay_gain_info, data, length,
&dc.out_audio_format);
else if (normalizationEnabled)
normalizeData(data, length, &dc.out_audio_format);
......@@ -239,7 +255,8 @@ decoder_data(struct decoder *decoder,
data += nbytes;
if (length > 0) {
enum decoder_command cmd = need_chunks(is);
enum decoder_command cmd =
need_chunks(is, nbytes == 0);
if (cmd != DECODE_COMMAND_NONE)
return cmd;
}
......@@ -254,11 +271,13 @@ decoder_tag(mpd_unused struct decoder *decoder, struct input_stream *is,
{
struct tag *tag2 = is != NULL ? tag_add_stream_tags(tag, is) : NULL;
assert(dc.state == DECODE_STATE_DECODE);
if (tag2 != NULL)
tag = tag2;
while (!music_pipe_tag(tag)) {
enum decoder_command cmd = need_chunks(is);
enum decoder_command cmd = need_chunks(is, true);
if (cmd != DECODE_COMMAND_NONE)
return cmd;
}
......
......@@ -27,7 +27,7 @@
*/
#include "input_stream.h"
#include "replayGain.h"
#include "replay_gain.h"
#include "tag.h"
#include "tag_id3.h"
#include "audio_format.h"
......@@ -61,27 +61,25 @@ struct decoder_plugin {
void (*finish)(void);
/**
* returns true if the input stream is decodable by the
* decoder plugin, false if not
*/
bool (*try_decode)(struct input_stream *);
/**
* this will be used to decode InputStreams, and is
* recommended for files and networked (HTTP) connections.
*
* returns false on error, true on success
* @return false if the plugin cannot decode the stream, and
* true if it was able to do so (even if an error occured
* during playback)
*/
bool (*stream_decode)(struct decoder *, struct input_stream *);
void (*stream_decode)(struct decoder *, struct input_stream *);
/**
* use this if and only if your InputPlugin can only be passed
* a filename or handle as input, and will not allow callbacks
* to be set (like Ogg-Vorbis and FLAC libraries allow)
*
* returns -1 on error, 0 on success
* @return false if the plugin cannot decode the file, and
* true if it was able to do so (even if an error occured
* during playback)
*/
bool (*file_decode)(struct decoder *, const char *path);
void (*file_decode)(struct decoder *, const char *path);
/**
* file should be the full path! Returns NULL if a tag cannot
......@@ -145,7 +143,7 @@ enum decoder_command
decoder_data(struct decoder *decoder,
struct input_stream *inStream,
void *data, size_t datalen, float data_time, uint16_t bitRate,
ReplayGainInfo * replayGainInfo);
struct replay_gain_info *replay_gain_info);
/**
* This function is called by the decoder plugin when it has
......
......@@ -27,7 +27,6 @@ void dc_init(void)
notify_init(&dc.notify);
dc.state = DECODE_STATE_STOP;
dc.command = DECODE_COMMAND_NONE;
dc.error = DECODE_ERROR_NOERROR;
}
void dc_deinit(void)
......@@ -63,7 +62,6 @@ dc_start(struct notify *notify, struct song *song)
assert(song != NULL);
dc.next_song = song;
dc.error = DECODE_ERROR_NOERROR;
dc_command(notify, DECODE_COMMAND_START);
}
......@@ -73,7 +71,6 @@ dc_start_async(struct song *song)
assert(song != NULL);
dc.next_song = song;
dc.error = DECODE_ERROR_NOERROR;
dc_command_async(DECODE_COMMAND_START);
}
......@@ -81,7 +78,7 @@ void
dc_stop(struct notify *notify)
{
if (dc.command == DECODE_COMMAND_START ||
dc.state != DECODE_STATE_STOP)
(dc.state != DECODE_STATE_STOP && dc.state != DECODE_STATE_ERROR))
dc_command(notify, DECODE_COMMAND_STOP);
}
......@@ -90,7 +87,8 @@ dc_seek(struct notify *notify, double where)
{
assert(where >= 0.0);
if (dc.state == DECODE_STATE_STOP || !dc.seekable)
if (dc.state == DECODE_STATE_STOP ||
dc.state == DECODE_STATE_ERROR || !dc.seekable)
return false;
dc.seek_where = where;
......
......@@ -25,19 +25,23 @@
#include "audio_format.h"
#include "notify.h"
#include <assert.h>
#define DECODE_TYPE_FILE 0
#define DECODE_TYPE_URL 1
enum decoder_state {
DECODE_STATE_STOP = 0,
DECODE_STATE_START,
DECODE_STATE_DECODE
};
enum decoder_error {
DECODE_ERROR_NOERROR = 0,
DECODE_ERROR_UNKTYPE,
DECODE_ERROR_FILE,
DECODE_STATE_DECODE,
/**
* The last "START" command failed, because there was an I/O
* error or because no decoder was able to decode the file.
* This state will only come after START; once the state has
* turned to DECODE, by definition no such error can occur.
*/
DECODE_STATE_ERROR,
};
struct decoder_control {
......@@ -45,7 +49,6 @@ struct decoder_control {
volatile enum decoder_state state;
volatile enum decoder_command command;
volatile enum decoder_error error;
bool seek_error;
bool seekable;
volatile double seek_where;
......@@ -69,7 +72,8 @@ void dc_deinit(void);
static inline bool decoder_is_idle(void)
{
return dc.state == DECODE_STATE_STOP &&
return (dc.state == DECODE_STATE_STOP ||
dc.state == DECODE_STATE_ERROR) &&
dc.command != DECODE_COMMAND_START;
}
......@@ -79,14 +83,28 @@ static inline bool decoder_is_starting(void)
dc.state == DECODE_STATE_START;
}
static inline bool decoder_has_failed(void)
{
assert(dc.command == DECODE_COMMAND_NONE);
return dc.state == DECODE_STATE_ERROR;
}
static inline struct song *
decoder_current_song(void)
{
if (dc.state == DECODE_STATE_STOP ||
dc.error != DECODE_ERROR_NOERROR)
switch (dc.state) {
case DECODE_STATE_STOP:
case DECODE_STATE_ERROR:
return NULL;
return dc.current_song;
case DECODE_STATE_START:
case DECODE_STATE_DECODE:
return dc.current_song;
}
assert(false);
return NULL;
}
void
......
......@@ -23,8 +23,6 @@
#include "pcm_utils.h"
struct decoder {
const struct decoder_plugin *plugin;
struct pcm_convert_state conv_state;
bool seeking;
......
......@@ -40,7 +40,7 @@ static const struct decoder_plugin *const decoder_plugins[] = {
#ifdef HAVE_OGGVORBIS
&oggvorbisPlugin,
#endif
#ifdef HAVE_FLAC_COMMON
#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
&oggflacPlugin,
#endif
#ifdef HAVE_FLAC
......
......@@ -29,20 +29,47 @@
#include "ls.h"
static bool
decoder_try_decode(const struct decoder_plugin *plugin,
struct input_stream *input_stream)
decoder_stream_decode(const struct decoder_plugin *plugin,
struct decoder *decoder,
struct input_stream *input_stream)
{
bool ret;
assert(plugin != NULL);
assert(plugin->stream_decode != NULL);
assert(decoder != NULL);
assert(!decoder->stream_tag_sent);
assert(input_stream != NULL);
assert(input_stream->ready);
assert(dc.state == DECODE_STATE_START);
/* rewind the stream, so each plugin gets a fresh start */
input_stream_seek(input_stream, 0, SEEK_SET);
if (plugin->try_decode == NULL)
return true;
plugin->stream_decode(decoder, input_stream);
ret = plugin->try_decode(input_stream);
assert(dc.state == DECODE_STATE_START ||
dc.state == DECODE_STATE_DECODE);
/* rewind the stream, so the next reader gets a fresh start */
input_stream_seek(input_stream, 0, SEEK_SET);
return dc.state != DECODE_STATE_START;
}
static bool
decoder_file_decode(const struct decoder_plugin *plugin,
struct decoder *decoder, const char *path)
{
assert(plugin != NULL);
assert(plugin->file_decode != NULL);
assert(decoder != NULL);
assert(!decoder->stream_tag_sent);
assert(path != NULL);
assert(path[0] == '/');
assert(dc.state == DECODE_STATE_START);
return ret;
plugin->file_decode(decoder, path);
assert(dc.state == DECODE_STATE_START ||
dc.state == DECODE_STATE_DECODE);
return dc.state != DECODE_STATE_START;
}
static void decoder_run(void)
......@@ -61,13 +88,13 @@ static void decoder_run(void)
else
uri = song_get_url(song, buffer);
if (uri == NULL) {
dc.error = DECODE_ERROR_FILE;
dc.state = DECODE_STATE_ERROR;
return;
}
dc.current_song = dc.next_song; /* NEED LOCK */
if (!input_stream_open(&input_stream, uri)) {
dc.error = DECODE_ERROR_FILE;
dc.state = DECODE_STATE_ERROR;
return;
}
......@@ -84,19 +111,21 @@ static void decoder_run(void)
while (!input_stream.ready) {
if (dc.command != DECODE_COMMAND_NONE) {
input_stream_close(&input_stream);
dc.state = DECODE_STATE_STOP;
return;
}
ret = input_stream_buffer(&input_stream);
if (ret < 0) {
input_stream_close(&input_stream);
dc.error = DECODE_ERROR_FILE;
dc.state = DECODE_STATE_ERROR;
return;
}
}
if (dc.command == DECODE_COMMAND_STOP) {
input_stream_close(&input_stream);
dc.state = DECODE_STATE_STOP;
return;
}
......@@ -108,10 +137,12 @@ static void decoder_run(void)
while ((plugin = decoder_plugin_from_mime_type(input_stream.mime, next++))) {
if (plugin->stream_decode == NULL)
continue;
if (!decoder_try_decode(plugin, &input_stream))
continue;
ret = plugin->stream_decode(&decoder, &input_stream);
break;
ret = decoder_stream_decode(plugin, &decoder,
&input_stream);
if (ret)
break;
plugin = NULL;
}
/* if that fails, try suffix matching the URL: */
......@@ -121,12 +152,13 @@ static void decoder_run(void)
while ((plugin = decoder_plugin_from_suffix(s, next++))) {
if (plugin->stream_decode == NULL)
continue;
if (!decoder_try_decode(plugin, &input_stream))
continue;
decoder.plugin = plugin;
ret = plugin->stream_decode(&decoder,
ret = decoder_stream_decode(plugin, &decoder,
&input_stream);
break;
if (ret)
break;
assert(dc.state == DECODE_STATE_START);
plugin = NULL;
}
}
/* fallback to mp3: */
......@@ -136,8 +168,7 @@ static void decoder_run(void)
/* we already know our mp3Plugin supports streams, no
* need to check for stream{Types,DecodeFunc} */
if ((plugin = decoder_plugin_from_name("mp3"))) {
decoder.plugin = plugin;
ret = plugin->stream_decode(&decoder,
ret = decoder_stream_decode(plugin, &decoder,
&input_stream);
}
}
......@@ -145,47 +176,41 @@ static void decoder_run(void)
unsigned int next = 0;
const char *s = getSuffix(uri);
while ((plugin = decoder_plugin_from_suffix(s, next++))) {
if (!decoder_try_decode(plugin, &input_stream))
continue;
if (plugin->file_decode != NULL) {
input_stream_close(&input_stream);
close_instream = false;
decoder.plugin = plugin;
ret = plugin->file_decode(&decoder, uri);
break;
ret = decoder_file_decode(plugin,
&decoder, uri);
if (ret)
break;
} else if (plugin->stream_decode != NULL) {
decoder.plugin = plugin;
ret = plugin->stream_decode(&decoder,
ret = decoder_stream_decode(plugin, &decoder,
&input_stream);
break;
if (ret)
break;
}
}
}
music_pipe_flush();
if (!ret) {
dc.error = plugin == NULL
? DECODE_ERROR_UNKTYPE
: DECODE_ERROR_FILE;
}
if (close_instream)
input_stream_close(&input_stream);
dc.state = ret ? DECODE_STATE_STOP : DECODE_STATE_ERROR;
}
static void * decoder_task(mpd_unused void *arg)
{
while (1) {
assert(dc.state == DECODE_STATE_STOP);
assert(dc.state == DECODE_STATE_STOP ||
dc.state == DECODE_STATE_ERROR);
switch (dc.command) {
case DECODE_COMMAND_START:
case DECODE_COMMAND_SEEK:
decoder_run();
dc.state = DECODE_STATE_STOP;
dc.command = DECODE_COMMAND_NONE;
notify_signal(&pc.notify);
break;
......
......@@ -70,6 +70,9 @@ struct input_curl {
/** limited list of old buffers, for rewinding */
struct list_head rewind;
/** error message provided by libcurl */
char error[CURL_ERROR_SIZE];
};
/** libcurl should accept "ICY 200 OK" */
......@@ -154,8 +157,8 @@ input_curl_multi_info_read(struct input_stream *is)
&msgs_in_queue)) != NULL) {
if (msg->msg == CURLMSG_DONE &&
msg->data.result != CURLE_OK) {
g_warning("curl failed: %s\n",
curl_easy_strerror(msg->data.result));
g_warning("curl failed: %s\n", c->error);
is->error = -1;
c->eof = true;
return false;
}
......@@ -262,7 +265,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size)
bret = input_curl_multi_info_read(is);
if (!bret)
return -1;
return 0;
c->eof = running_handles == 0;
}
......@@ -452,6 +455,8 @@ input_curl_easy_init(struct input_stream *is)
input_curl_writefunction);
curl_easy_setopt(c->easy, CURLOPT_WRITEDATA, is);
curl_easy_setopt(c->easy, CURLOPT_HTTP200ALIASES, http_200_aliases);
curl_easy_setopt(c->easy, CURLOPT_FAILONERROR, true);
curl_easy_setopt(c->easy, CURLOPT_ERRORBUFFER, c->error);
code = curl_easy_setopt(c->easy, CURLOPT_URL, c->url);
if (code != CURLE_OK)
......
......@@ -159,19 +159,19 @@ static void parseListenConfigParam(unsigned int port, ConfigParam * param)
#ifdef HAVE_UN
} else if (param->value[0] == '/') {
size_t path_length;
struct sockaddr_un sun;
struct sockaddr_un s_un;
path_length = strlen(param->value);
if (path_length >= sizeof(sun.sun_path))
if (path_length >= sizeof(s_un.sun_path))
FATAL("unix socket path is too long\n");
unlink(param->value);
sun.sun_family = AF_UNIX;
memcpy(sun.sun_path, param->value, path_length + 1);
s_un.sun_family = AF_UNIX;
memcpy(s_un.sun_path, param->value, path_length + 1);
addrp = (const struct sockaddr *)&sun;
addrlen = sizeof(sun);
addrp = (const struct sockaddr *)&s_un;
addrlen = sizeof(s_un);
if (establishListen(PF_UNIX, addrp, addrlen) < 0)
FATAL("unable to bind to %s: %s\n",
......
......@@ -159,7 +159,7 @@ void setup_log_output(bool use_stdout)
#define log_func(func,level) \
mpd_printf void func(const char *fmt, ...) \
{ \
if ((int)log_threshold <= level) { \
if (level <= (int)log_threshold) { \
va_list args; \
va_start(args, fmt); \
g_logv(NULL, level, fmt, args); \
......
......@@ -38,7 +38,7 @@
#include "volume.h"
#include "log.h"
#include "permission.h"
#include "replayGain.h"
#include "replay_gain.h"
#include "decoder_list.h"
#include "audioOutput.h"
#include "input_stream.h"
......@@ -429,7 +429,7 @@ int main(int argc, char *argv[])
initAudioDriver();
initVolume();
client_manager_init();
initReplayGainState();
replay_gain_global_init();
initNormalization();
input_stream_global_init();
......
......@@ -53,7 +53,8 @@ pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume)
while (num_samples > 0) {
int32_t sample = *buffer;
sample = (sample * volume + pcm_dither() + 500) / 1000;
sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2)
/ PCM_VOLUME_1;
*buffer++ = pcm_range(sample, 8);
--num_samples;
......@@ -66,7 +67,8 @@ pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume)
while (num_samples > 0) {
int32_t sample = *buffer;
sample = (sample * volume + pcm_dither() + 500) / 1000;
sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2)
/ PCM_VOLUME_1;
*buffer++ = pcm_range(sample, 16);
--num_samples;
......@@ -79,7 +81,8 @@ pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume)
while (num_samples > 0) {
int64_t sample = *buffer;
sample = (sample * volume + pcm_dither() + 500) / 1000;
sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2)
/ PCM_VOLUME_1;
*buffer++ = pcm_range(sample, 24);
--num_samples;
......@@ -90,7 +93,7 @@ void pcm_volume(char *buffer, int bufferSize,
const struct audio_format *format,
int volume)
{
if (volume >= 1000)
if (volume == PCM_VOLUME_1)
return;
if (volume <= 0) {
......@@ -128,7 +131,7 @@ pcm_add_8(int8_t *buffer1, const int8_t *buffer2,
int32_t sample2 = *buffer2++;
sample1 = ((sample1 * volume1 + sample2 * volume2) +
pcm_dither() + 500) / 1000;
pcm_dither() + PCM_VOLUME_1 / 2) / PCM_VOLUME_1;
*buffer1++ = pcm_range(sample1, 8);
--num_samples;
......@@ -144,7 +147,7 @@ pcm_add_16(int16_t *buffer1, const int16_t *buffer2,
int32_t sample2 = *buffer2++;
sample1 = ((sample1 * volume1 + sample2 * volume2) +
pcm_dither() + 500) / 1000;
pcm_dither() + PCM_VOLUME_1 / 2) / PCM_VOLUME_1;
*buffer1++ = pcm_range(sample1, 16);
--num_samples;
......@@ -160,7 +163,7 @@ pcm_add_24(int32_t *buffer1, const int32_t *buffer2,
int64_t sample2 = *buffer2++;
sample1 = ((sample1 * volume1 + sample2 * volume2) +
pcm_dither() + 500) / 1000;
pcm_dither() + PCM_VOLUME_1 / 2) / PCM_VOLUME_1;
*buffer1++ = pcm_range(sample1, 24);
--num_samples;
......@@ -200,10 +203,10 @@ void pcm_mix(char *buffer1, const char *buffer2, size_t size,
float s = sin(M_PI_2 * portion1);
s *= s;
vol1 = s * 1000 + 0.5;
vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1);
vol1 = s * PCM_VOLUME_1 + 0.5;
vol1 = vol1 > PCM_VOLUME_1 ? PCM_VOLUME_1 : (vol1 < 0 ? 0 : vol1);
pcm_add(buffer1, buffer2, size, vol1, 1000 - vol1, format);
pcm_add(buffer1, buffer2, size, vol1, PCM_VOLUME_1 - vol1, format);
}
void pcm_convert_init(struct pcm_convert_state *state)
......
......@@ -27,6 +27,11 @@
struct audio_format;
enum {
/** this value means "100% volume" */
PCM_VOLUME_1 = 1000,
};
struct pcm_convert_state {
struct pcm_resample_state resample;
......@@ -36,6 +41,16 @@ struct pcm_convert_state {
int error;
};
/**
* Converts a float value (0.0 = silence, 1.0 = 100% volume) to an
* integer volume value (1000 = 100%).
*/
static inline int
pcm_float_to_volume(float volume)
{
return volume * PCM_VOLUME_1 + 0.5;
}
void pcm_volume(char *buffer, int bufferSize,
const struct audio_format *format,
int volume);
......
......@@ -190,6 +190,8 @@ tail_chunk(size_t frame_size)
chunk = music_pipe_get_chunk(music_pipe.end);
assert(chunk->length <= sizeof(chunk->data));
assert((chunk->length % frame_size) == 0);
if (chunk->length + frame_size > sizeof(chunk->data)) {
/* this chunk is full; allocate a new chunk */
next = successor(music_pipe.end);
......@@ -298,3 +300,33 @@ void music_pipe_skip(unsigned num)
while (music_pipe.begin != (unsigned)i)
music_pipe_shift();
}
void music_pipe_chop(unsigned first)
{
for (unsigned i = first; i != music_pipe.end; i = successor(i))
music_chunk_free(&music_pipe.chunks[i]);
music_chunk_free(&music_pipe.chunks[music_pipe.end]);
music_pipe.end = first;
music_chunk_init(&music_pipe.chunks[first]);
}
#ifndef NDEBUG
void music_pipe_check_format(const struct audio_format *current,
int next_index, const struct audio_format *next)
{
const struct audio_format *audio_format = current;
for (unsigned i = music_pipe.begin; i != music_pipe.end;
i = successor(i)) {
const struct music_chunk *chunk = music_pipe_get_chunk(i);
if (next_index > 0 && i == (unsigned)next_index)
audio_format = next;
assert(chunk->length % audio_format_frame_size(audio_format) == 0);
}
}
#endif
......@@ -164,4 +164,15 @@ bool music_pipe_tag(const struct tag *tag);
void music_pipe_skip(unsigned num);
/**
* Chop off the tail of the music pipe, starting with the chunk at
* index "first".
*/
void music_pipe_chop(unsigned first);
#ifndef NDEBUG
void music_pipe_check_format(const struct audio_format *current,
int next_index, const struct audio_format *next);
#endif
#endif
......@@ -22,6 +22,7 @@
#include "tag.h"
#include "song.h"
#include "idle.h"
#include "pcm_utils.h"
#include "os_compat.h"
#include "main_notify.h"
......@@ -35,7 +36,7 @@ void pc_init(unsigned int buffered_before_play)
pc.error = PLAYER_ERROR_NOERROR;
pc.state = PLAYER_STATE_STOP;
pc.cross_fade_seconds = 0;
pc.software_volume = 1000;
pc.software_volume = PCM_VOLUME_1;
}
void pc_deinit(void)
......@@ -220,7 +221,11 @@ void setPlayerCrossFade(float crossFadeInSeconds)
void setPlayerSoftwareVolume(int volume)
{
volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume);
if (volume > PCM_VOLUME_1)
volume = PCM_VOLUME_1;
else if (volume < 0)
volume = 0;
pc.software_volume = volume;
}
......
......@@ -93,7 +93,7 @@ static int player_wait_for_decoder(struct player *player)
{
dc_command_wait(&pc.notify);
if (dc.error != DECODE_ERROR_NOERROR) {
if (decoder_has_failed()) {
assert(dc.next_song == NULL || dc.next_song->url != NULL);
pc.errored_song = dc.next_song;
pc.error = PLAYER_ERROR_FILE;
......@@ -203,6 +203,7 @@ static void player_process_command(struct player *player)
/* the decoder is already decoding the song -
stop it and reset the position */
dc_stop(&pc.notify);
music_pipe_chop(player->next_song_chunk);
player->next_song_chunk = -1;
}
......@@ -225,11 +226,13 @@ play_chunk(struct song *song, struct music_chunk *chunk,
if (!song_is_file(song)) {
/* always update the tag of remote streams */
struct tag *old_tag = song->tag;
if (song->tag != NULL)
tag_free(song->tag);
song->tag = tag_dup(chunk->tag);
if (old_tag != NULL)
tag_free(old_tag);
/* notify all clients that the tag of the
current song has changed */
idle_add(IDLE_PLAYER);
......@@ -305,7 +308,7 @@ static void do_play(void)
}
if (player.decoder_starting) {
if (dc.error != DECODE_ERROR_NOERROR) {
if (decoder_has_failed()) {
/* the decoder failed */
assert(dc.next_song == NULL || dc.next_song->url != NULL);
pc.errored_song = dc.next_song;
......@@ -342,6 +345,12 @@ static void do_play(void)
}
}
#ifndef NDEBUG
music_pipe_check_format(&play_audio_format,
player.next_song_chunk,
&dc.out_audio_format);
#endif
if (decoder_is_idle() && !player.queued &&
pc.next_song != NULL &&
pc.command == PLAYER_COMMAND_NONE) {
......@@ -355,6 +364,7 @@ static void do_play(void)
/* the decoder has finished the current song;
make it decode the next song */
assert(pc.next_song != NULL);
assert(player.next_song_chunk == -1);
player.queued = false;
player.next_song_chunk = music_pipe_tail_index();
......
......@@ -830,13 +830,8 @@ enum playlist_result playPlaylistById(int id, int stopOnError)
static void syncCurrentPlayerDecodeMetadata(void)
{
struct song *songPlayer = playerCurrentDecodeSong();
struct song *song;
int songNum;
char path_max_tmp[MPD_PATH_MAX];
if (!songPlayer)
return;
if (playlist_state != PLAYLIST_STATE_PLAY)
return;
......@@ -844,16 +839,18 @@ static void syncCurrentPlayerDecodeMetadata(void)
songNum = playlist.order[playlist.current];
song = playlist.songs[songNum];
if (!song_is_file(song) &&
0 == strcmp(song_get_url(song, path_max_tmp), songPlayer->url) &&
!tag_equal(song->tag, songPlayer->tag)) {
assert(!song_in_database(song));
if (song != playlist.prev_song) {
/* song change: initialize playlist.prev_{song,tag} */
playlist.prev_song = song;
playlist.prev_tag = song->tag;
} else if (song->tag != playlist.prev_tag) {
/* tag change: update playlist */
if (song->tag)
tag_free(song->tag);
song->tag = tag_dup(songPlayer->tag);
playlist.songMod[songNum] = playlist.version;
incrPlaylistVersion();
playlist.prev_tag = song->tag;
}
}
......@@ -982,11 +979,8 @@ enum playlist_result moveSongInPlaylist(unsigned from, int to)
to = (currentSong + abs(to)) % playlist.length;
}
if (playlist_state == PLAYLIST_STATE_PLAY) {
int queuedSong = -1;
if (playlist.queued >= 0)
queuedSong = playlist.order[playlist.queued];
if (playlist_state == PLAYLIST_STATE_PLAY && playlist.queued >= 0) {
int queuedSong = playlist.order[playlist.queued];
if (queuedSong == (int)from || queuedSong == to
|| currentSong == from || (int)currentSong == to)
clearPlayerQueue();
......@@ -1065,10 +1059,8 @@ static void orderPlaylist(void)
if (playlist.current >= 0 && playlist.current < (int)playlist.length)
playlist.current = playlist.order[playlist.current];
if (playlist_state == PLAYLIST_STATE_PLAY) {
if (playlist.queued >= 0)
clearPlayerQueue();
}
if (playlist_state == PLAYLIST_STATE_PLAY && playlist.queued >= 0)
clearPlayerQueue();
for (i = 0; i < playlist.length; i++) {
playlist.order[i] = i;
......@@ -1090,10 +1082,9 @@ static void randomizeOrder(int start, int end)
DEBUG("playlist: randomize from %i to %i\n", start, end);
if (playlist_state == PLAYLIST_STATE_PLAY) {
if (playlist.queued >= start && playlist.queued <= end)
clearPlayerQueue();
}
if (playlist_state == PLAYLIST_STATE_PLAY &&
playlist.queued >= start && playlist.queued <= end)
clearPlayerQueue();
for (i = start; i <= end; i++) {
ri = random() % (end - start + 1) + start;
......@@ -1161,7 +1152,9 @@ void shufflePlaylist(void)
if (playlist.length > 1) {
if (playlist_state == PLAYLIST_STATE_PLAY) {
clearPlayerQueue();
if (playlist.queued >= 0)
clearPlayerQueue();
/* put current playing song first */
swapSongs(0, playlist.order[playlist.current]);
if (playlist.random) {
......
......@@ -54,6 +54,11 @@ typedef struct _Playlist {
bool repeat;
bool random;
uint32_t version;
/** used by syncCurrentPlayerDecodeMetadata() to detect tag changes */
const struct song *prev_song;
/** used by syncCurrentPlayerDecodeMetadata() to detect tag changes */
const struct tag *prev_tag;
} Playlist;
extern bool playlist_saveAbsolutePaths;
......
......@@ -17,20 +17,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "replayGain.h"
#include "utils.h"
#include "log.h"
#include "replay_gain.h"
#include "conf.h"
#include "audio_format.h"
#include "os_compat.h"
#include "pcm_utils.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* Added 4/14/2004 by AliasMrJones */
int replayGainState = REPLAYGAIN_OFF;
static const char *const replay_gain_mode_names[] = {
[REPLAY_GAIN_ALBUM] = "album",
[REPLAY_GAIN_TRACK] = "track",
};
static float replayGainPreamp = 1.0;
enum replay_gain_mode replay_gain_mode = REPLAY_GAIN_OFF;
void initReplayGainState(void)
static float replay_gain_preamp = 1.0;
void replay_gain_global_init(void)
{
ConfigParam *param = getConfigParam(CONF_REPLAYGAIN);
......@@ -38,12 +44,12 @@ void initReplayGainState(void)
return;
if (strcmp(param->value, "track") == 0) {
replayGainState = REPLAYGAIN_TRACK;
replay_gain_mode = REPLAY_GAIN_TRACK;
} else if (strcmp(param->value, "album") == 0) {
replayGainState = REPLAYGAIN_ALBUM;
replay_gain_mode = REPLAY_GAIN_ALBUM;
} else {
FATAL("replaygain value \"%s\" at line %i is invalid\n",
param->value, param->line);
g_error("replaygain value \"%s\" at line %i is invalid\n",
param->value, param->line);
}
param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
......@@ -53,27 +59,27 @@ void initReplayGainState(void)
float f = strtod(param->value, &test);
if (*test != '\0') {
FATAL("Replaygain preamp \"%s\" is not a number at "
"line %i\n", param->value, param->line);
g_error("Replaygain preamp \"%s\" is not a number at "
"line %i\n", param->value, param->line);
}
if (f < -15 || f > 15) {
FATAL("Replaygain preamp \"%s\" is not between -15 and"
"15 at line %i\n", param->value, param->line);
g_error("Replaygain preamp \"%s\" is not between -15 and"
"15 at line %i\n", param->value, param->line);
}
replayGainPreamp = pow(10, f / 20.0);
replay_gain_preamp = pow(10, f / 20.0);
}
}
static float computeReplayGainScale(float gain, float peak)
static float calc_replay_gain_scale(float gain, float peak)
{
float scale;
if (gain == 0.0)
return (1);
scale = pow(10.0, gain / 20.0);
scale *= replayGainPreamp;
scale *= replay_gain_preamp;
if (scale > 15.0)
scale = 15.0;
......@@ -83,85 +89,43 @@ static float computeReplayGainScale(float gain, float peak)
return (scale);
}
ReplayGainInfo *newReplayGainInfo(void)
struct replay_gain_info *replay_gain_info_new(void)
{
ReplayGainInfo *ret = xmalloc(sizeof(ReplayGainInfo));
ret->albumGain = 0.0;
ret->albumPeak = 0.0;
struct replay_gain_info *ret = g_new(struct replay_gain_info, 1);
ret->trackGain = 0.0;
ret->trackPeak = 0.0;
for (unsigned i = 0; i < G_N_ELEMENTS(ret->tuples); ++i) {
ret->tuples[i].gain = 0.0;
ret->tuples[i].peak = 0.0;
}
/* set to -1 so that we know in doReplayGain to compute the scale */
/* set to -1 so that we know in replay_gain_apply to compute the scale */
ret->scale = -1.0;
return ret;
}
void freeReplayGainInfo(ReplayGainInfo * info)
void replay_gain_info_free(struct replay_gain_info *info)
{
free(info);
g_free(info);
}
void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize,
void
replay_gain_apply(struct replay_gain_info *info, char *buffer, int size,
const struct audio_format *format)
{
int16_t *buffer16;
int8_t *buffer8;
int32_t temp32;
float scale;
if (replayGainState == REPLAYGAIN_OFF || !info)
if (replay_gain_mode == REPLAY_GAIN_OFF || !info)
return;
if (info->scale < 0) {
switch (replayGainState) {
case REPLAYGAIN_TRACK:
DEBUG("computing ReplayGain track scale with gain %f, "
"peak %f\n", info->trackGain, info->trackPeak);
info->scale = computeReplayGainScale(info->trackGain,
info->trackPeak);
break;
default:
DEBUG("computing ReplayGain album scale with gain %f, "
"peak %f\n", info->albumGain, info->albumPeak);
info->scale = computeReplayGainScale(info->albumGain,
info->albumPeak);
break;
}
}
if (info->scale <= 1.01 && info->scale >= 0.99)
return;
buffer16 = (int16_t *) buffer;
buffer8 = (int8_t *) buffer;
const struct replay_gain_tuple *tuple =
&info->tuples[replay_gain_mode];
scale = info->scale;
g_debug("computing ReplayGain %s scale with gain %f, peak %f\n",
replay_gain_mode_names[replay_gain_mode],
tuple->gain, tuple->peak);
switch (format->bits) {
case 16:
while (bufferSize > 0) {
temp32 = *buffer16;
temp32 *= scale;
*buffer16 = temp32 > 32767 ? 32767 :
(temp32 < -32768 ? -32768 : temp32);
buffer16++;
bufferSize -= 2;
}
break;
case 8:
while (bufferSize > 0) {
temp32 = *buffer8;
temp32 *= scale;
*buffer8 = temp32 > 127 ? 127 :
(temp32 < -128 ? -128 : temp32);
buffer8++;
bufferSize--;
}
break;
default:
ERROR("%i bits not supported by doReplaygain!\n", format->bits);
info->scale = calc_replay_gain_scale(tuple->gain, tuple->peak);
}
pcm_volume(buffer, size, format, pcm_float_to_volume(info->scale));
}
......@@ -17,34 +17,40 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MPD_REPLAYGAIN_H
#define MPD_REPLAYGAIN_H
#ifndef MPD_REPLAY_GAIN_H
#define MPD_REPLAY_GAIN_H
#define REPLAYGAIN_OFF 0
#define REPLAYGAIN_TRACK 1
#define REPLAYGAIN_ALBUM 2
enum replay_gain_mode {
REPLAY_GAIN_OFF = -1,
REPLAY_GAIN_ALBUM,
REPLAY_GAIN_TRACK,
};
struct audio_format;
extern int replayGainState;
extern enum replay_gain_mode replay_gain_mode;
typedef struct _ReplayGainInfo {
float albumGain;
float albumPeak;
float trackGain;
float trackPeak;
struct replay_gain_tuple {
float gain;
float peak;
};
struct replay_gain_info {
struct replay_gain_tuple tuples[2];
/* used internally by mpd, to mess with it */
float scale;
} ReplayGainInfo;
};
ReplayGainInfo *newReplayGainInfo(void);
struct replay_gain_info *
replay_gain_info_new(void);
void freeReplayGainInfo(ReplayGainInfo * info);
void replay_gain_info_free(struct replay_gain_info *info);
void initReplayGainState(void);
void replay_gain_global_init(void);
void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize,
void
replay_gain_apply(struct replay_gain_info *info, char *buffer, int bufferSize,
const struct audio_format *format);
#endif
......@@ -22,6 +22,7 @@
#include "player_control.h"
#include "utils.h"
#include "idle.h"
#include "pcm_utils.h"
#include "os_compat.h"
#include "../config.h"
......@@ -479,12 +480,12 @@ static int changeSoftwareVolume(int change, int rel)
/*new = 100.0*(exp(new/50.0)-1)/(M_E*M_E-1)+0.5; */
if (new >= 100)
new = 1000;
new = PCM_VOLUME_1;
else if (new <= 0)
new = 0;
else
new =
1000.0 * (exp(new / 25.0) - 1) / (54.5981500331F - 1) + 0.5;
new = pcm_float_to_volume((exp(new / 25.0) - 1) /
(54.5981500331F - 1));
setPlayerSoftwareVolume(new);
......
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