diff -Nru mpd-0.19.21/aclocal.m4 mpd-0.20.9/aclocal.m4 --- mpd-0.19.21/aclocal.m4 2016-12-13 07:55:28.000000000 +0000 +++ mpd-0.20.9/aclocal.m4 2017-06-03 18:58:49.000000000 +0000 @@ -1156,14 +1156,16 @@ m4_include([m4/ax_boost_base.m4]) m4_include([m4/ax_check_compile_flag.m4]) m4_include([m4/ax_check_link_flag.m4]) -m4_include([m4/ax_cxx_compile_stdcxx_0x.m4]) +m4_include([m4/ax_cxx_compile_stdcxx.m4]) +m4_include([m4/ax_cxx_compile_stdcxx_14.m4]) m4_include([m4/ax_pthread.m4]) m4_include([m4/ax_require_defined.m4]) -m4_include([m4/faad.m4]) m4_include([m4/libwrap.m4]) m4_include([m4/mpd_auto.m4]) +m4_include([m4/mpd_define_conditional.m4]) m4_include([m4/mpd_depends.m4]) m4_include([m4/mpd_func.m4]) +m4_include([m4/mpd_with_flags.m4]) m4_include([m4/pkg.m4]) m4_include([m4/pretty_print.m4]) m4_include([m4/ucred.m4]) diff -Nru mpd-0.19.21/android/build.py mpd-0.20.9/android/build.py --- mpd-0.19.21/android/build.py 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/android/build.py 2017-03-01 16:19:04.000000000 +0000 @@ -1,10 +1,7 @@ #!/usr/bin/env python3 import os, os.path -import sys, shutil, subprocess -import urllib.request -import hashlib -import re +import sys, subprocess if len(sys.argv) < 3: print("Usage: build.py SDK_PATH NDK_PATH [configure_args...]", file=sys.stderr) @@ -22,412 +19,140 @@ print("NDK not found in", ndk_path, file=sys.stderr) sys.exit(1) +# select the NDK target +arch = 'arm-linux-androideabi' + # the path to the MPD sources mpd_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]) or '.', '..')) +sys.path[0] = os.path.join(mpd_path, 'python') # output directories -lib_path = os.path.abspath('lib') -tarball_path = lib_path -src_path = os.path.join(lib_path, 'src') -build_path = os.path.join(lib_path, 'build') -root_path = os.path.join(lib_path, 'root') +from build.dirs import lib_path, tarball_path, src_path + +arch_path = os.path.join(lib_path, arch) +build_path = os.path.join(arch_path, 'build') # build host configuration build_arch = 'linux-x86_64' -# redirect pkg-config to use our root directory instead of the default -# one on the build host -os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(root_path, 'lib/pkgconfig') - -# select the NDK compiler -gcc_version = '4.9' -llvm_version = '3.5' - -# select the NDK target -ndk_arch = 'arm' -host_arch = 'arm-linux-androideabi' -android_abi = 'armeabi-v7a' -ndk_platform = 'android-14' - # set up the NDK toolchain -gcc_toolchain = os.path.join(ndk_path, 'toolchains', host_arch + '-' + gcc_version, 'prebuilt', build_arch) -llvm_toolchain = os.path.join(ndk_path, 'toolchains', 'llvm-' + llvm_version, 'prebuilt', build_arch) -ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform) -target_root = os.path.join(ndk_platform_path, 'arch-' + ndk_arch) - -llvm_triple = 'armv7-none-linux-androideabi' - -def select_toolchain(use_cxx, use_clang): - global cc, cxx, ar, strip, cflags, cxxflags, cppflags, ldflags, libs - - target_arch = '-march=armv7-a -mfloat-abi=softfp' - if use_clang: - cc = os.path.join(llvm_toolchain, 'bin/clang') - cxx = os.path.join(llvm_toolchain, 'bin/clang++') - target_arch += ' -target ' + llvm_triple + ' -integrated-as -gcc-toolchain ' + gcc_toolchain - else: - cc = os.path.join(gcc_toolchain, 'bin', host_arch + '-gcc') - cxx = os.path.join(gcc_toolchain, 'bin', host_arch + '-g++') - ar = os.path.join(gcc_toolchain, 'bin', host_arch + '-ar') - strip = os.path.join(gcc_toolchain, 'bin', host_arch + '-strip') - - libstdcxx_path = os.path.join(ndk_path, 'sources/cxx-stl/gnu-libstdc++', gcc_version) - libstdcxx_cppflags = '-isystem ' + os.path.join(libstdcxx_path, 'include') + ' -isystem ' + os.path.join(libstdcxx_path, 'libs', android_abi, 'include') - if use_clang: - libstdcxx_cppflags += ' -D__STRICT_ANSI__' - libstdcxx_ldadd = os.path.join(libstdcxx_path, 'libs', android_abi, 'libgnustl_static.a') - - cflags = '-Os -g ' + target_arch - cxxflags = '-Os -g ' + target_arch - cppflags = '--sysroot=' + target_root + ' -I' + root_path + '/include' - ldflags = '--sysroot=' + target_root + ' -L' + root_path + '/lib' - libs = '' - - if use_cxx: - libs += ' ' + libstdcxx_ldadd - cppflags += ' ' + libstdcxx_cppflags - -def file_md5(path): - """Calculate the MD5 checksum of a file and return it in hexadecimal notation.""" - - with open(path, 'rb') as f: - m = hashlib.md5() - while True: - data = f.read(65536) - if len(data) == 0: - # end of file - return m.hexdigest() - m.update(data) - -def download_tarball(url, md5): - """Download a tarball, verify its MD5 checksum and return the local path.""" - - global tarball_path - os.makedirs(tarball_path, exist_ok=True) - path = os.path.join(tarball_path, os.path.basename(url)) - - try: - calculated_md5 = file_md5(path) - if md5 == calculated_md5: return path - os.unlink(path) - except FileNotFoundError: - pass - - tmp_path = path + '.tmp' - - print("download", url) - urllib.request.urlretrieve(url, tmp_path) - calculated_md5 = file_md5(tmp_path) - if calculated_md5 != md5: - os.unlink(tmp_path) - raise "MD5 mismatch" - - os.rename(tmp_path, path) - return path - -class Project: - def __init__(self, url, md5, installed, name=None, version=None, - base=None, - use_cxx=False, use_clang=False): - if base is None: - basename = os.path.basename(url) - m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename) - if not m: raise - self.base = m.group(1) - else: - self.base = base - - if name is None or version is None: - m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?)$', self.base) - if name is None: name = m.group(1) - if version is None: version = m.group(2) - - self.name = name - self.version = version - - self.url = url - self.md5 = md5 - self.installed = installed - - self.use_cxx = use_cxx - self.use_clang = use_clang - - def download(self): - return download_tarball(self.url, self.md5) - - def is_installed(self): - global root_path - tarball = self.download() - installed = os.path.join(root_path, self.installed) - tarball_mtime = os.path.getmtime(tarball) - try: - return os.path.getmtime(installed) >= tarball_mtime - except FileNotFoundError: - return False - - def unpack(self): - global src_path - tarball = self.download() - path = os.path.join(src_path, self.base) - try: - shutil.rmtree(path) - except FileNotFoundError: - pass - os.makedirs(src_path, exist_ok=True) - subprocess.check_call(['/bin/tar', 'xfC', tarball, src_path]) - return path - - def make_build_path(self): - path = os.path.join(build_path, self.base) - try: - shutil.rmtree(path) - except FileNotFoundError: - pass - os.makedirs(path, exist_ok=True) - return path - -class AutotoolsProject(Project): - def __init__(self, url, md5, installed, configure_args=[], - autogen=False, - cppflags='', - **kwargs): - Project.__init__(self, url, md5, installed, **kwargs) - self.configure_args = configure_args - self.autogen = autogen - self.cppflags = cppflags - - def build(self): - src = self.unpack() - if self.autogen: - subprocess.check_call(['/usr/bin/aclocal'], cwd=src) - subprocess.check_call(['/usr/bin/automake', '--add-missing', '--force-missing', '--foreign'], cwd=src) - subprocess.check_call(['/usr/bin/autoconf'], cwd=src) - subprocess.check_call(['/usr/bin/libtoolize', '--force'], cwd=src) - - build = self.make_build_path() - - select_toolchain(use_cxx=self.use_cxx, use_clang=self.use_clang) - configure = [ - os.path.join(src, 'configure'), - 'CC=' + cc, - 'CXX=' + cxx, - 'CFLAGS=' + cflags, - 'CXXFLAGS=' + cxxflags, - 'CPPFLAGS=' + cppflags + ' ' + self.cppflags, - 'LDFLAGS=' + ldflags, - 'LIBS=' + libs, - 'AR=' + ar, - 'STRIP=' + strip, - '--host=' + host_arch, - '--prefix=' + root_path, - '--with-sysroot=' + target_root, - '--enable-silent-rules', - ] + self.configure_args - - subprocess.check_call(configure, cwd=build) - subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], cwd=build) - subprocess.check_call(['/usr/bin/make', '--quiet', 'install'], cwd=build) - -class FfmpegProject(Project): - def __init__(self, url, md5, installed, configure_args=[], - cppflags='', - **kwargs): - Project.__init__(self, url, md5, installed, **kwargs) - self.configure_args = configure_args - self.cppflags = cppflags - - def build(self): - src = self.unpack() - build = self.make_build_path() - - select_toolchain(use_cxx=self.use_cxx, use_clang=self.use_clang) - configure = [ - os.path.join(src, 'configure'), - '--cc=' + cc, - '--cxx=' + cxx, - '--extra-cflags=' + cflags + ' ' + cppflags + ' ' + self.cppflags, - '--extra-cxxflags=' + cxxflags + ' ' + cppflags + ' ' + self.cppflags, - '--extra-ldflags=' + ldflags, - '--extra-libs=' + libs, - '--ar=' + ar, - '--enable-cross-compile', - '--target-os=linux', - '--arch=' + ndk_arch, - '--cpu=cortex-a8', - '--prefix=' + root_path, - ] + self.configure_args - - subprocess.check_call(configure, cwd=build) - subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], cwd=build) - subprocess.check_call(['/usr/bin/make', '--quiet', 'install'], cwd=build) - -class BoostProject(Project): - def __init__(self, url, md5, installed, - **kwargs): - m = re.match(r'.*/boost_(\d+)_(\d+)_(\d+)\.tar\.bz2$', url) - version = "%s.%s.%s" % (m.group(1), m.group(2), m.group(3)) - Project.__init__(self, url, md5, installed, - name='boost', version=version, - **kwargs) - - def build(self): - src = self.unpack() - - # install the headers manually; don't build any library - # (because right now, we only use header-only libraries) - includedir = os.path.join(root_path, 'include') - for dirpath, dirnames, filenames in os.walk(os.path.join(src, 'boost')): - relpath = dirpath[len(src)+1:] - destdir = os.path.join(includedir, relpath) - try: - os.mkdir(destdir) - except: - pass - for name in filenames: - if name[-4:] == '.hpp': - shutil.copyfile(os.path.join(dirpath, name), - os.path.join(destdir, name)) +class AndroidNdkToolchain: + def __init__(self, tarball_path, src_path, build_path, + use_cxx): + self.tarball_path = tarball_path + self.src_path = src_path + self.build_path = build_path + + self.ndk_arch = 'arm' + android_abi = 'armeabi-v7a' + ndk_platform = 'android-14' + + # select the NDK compiler + gcc_version = '4.9' + + ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform) + sysroot = os.path.join(ndk_platform_path, 'arch-' + self.ndk_arch) + + install_prefix = os.path.join(arch_path, 'root') + + self.arch = arch + self.install_prefix = install_prefix + self.sysroot = sysroot + + toolchain_path = os.path.join(ndk_path, 'toolchains', arch + '-' + gcc_version, 'prebuilt', build_arch) + llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm', 'prebuilt', build_arch) + llvm_triple = 'armv7-none-linux-androideabi' + + common_flags = '-march=armv7-a -mfloat-abi=softfp' + + toolchain_bin = os.path.join(toolchain_path, 'bin') + llvm_bin = os.path.join(llvm_path, 'bin') + self.cc = os.path.join(llvm_bin, 'clang') + self.cxx = os.path.join(llvm_bin, 'clang++') + common_flags += ' -target ' + llvm_triple + ' -integrated-as -gcc-toolchain ' + toolchain_path + + self.ar = os.path.join(toolchain_bin, arch + '-ar') + self.ranlib = os.path.join(toolchain_bin, arch + '-ranlib') + self.nm = os.path.join(toolchain_bin, arch + '-nm') + self.strip = os.path.join(toolchain_bin, arch + '-strip') + + self.cflags = '-Os -g ' + common_flags + self.cxxflags = '-Os -g ' + common_flags + self.cppflags = '--sysroot=' + self.sysroot + ' -isystem ' + os.path.join(install_prefix, 'include') + self.ldflags = '--sysroot=' + self.sysroot + ' ' + common_flags + ' -L' + os.path.join(install_prefix, 'lib') + self.libs = '' + + self.is_arm = self.ndk_arch == 'arm' + self.is_armv7 = self.is_arm and 'armv7' in self.cflags + self.is_windows = False + + libcxx_path = os.path.join(ndk_path, 'sources/cxx-stl/llvm-libc++') + libcxx_libs_path = os.path.join(libcxx_path, 'libs', android_abi) + + libstdcxx_cppflags = '-nostdinc++ -isystem ' + os.path.join(libcxx_path, 'include') + ' -isystem ' + os.path.join(ndk_path, 'sources/android/support/include') + libstdcxx_ldadd = os.path.join(libcxx_libs_path, 'libc++_static.a') + ' ' + os.path.join(libcxx_libs_path, 'libc++abi.a') + + if self.is_armv7: + libstdcxx_ldadd += ' ' + os.path.join(libcxx_libs_path, 'libunwind.a') + + if use_cxx: + self.libs += ' ' + libstdcxx_ldadd + self.cppflags += ' ' + libstdcxx_cppflags + + self.env = dict(os.environ) + + # redirect pkg-config to use our root directory instead of the + # default one on the build host + self.env['PKG_CONFIG_LIBDIR'] = os.path.join(install_prefix, 'lib/pkgconfig') # a list of third-party libraries to be used by MPD on Android +from build.libs import * thirdparty_libs = [ - AutotoolsProject( - 'http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz', - '5c3a34309d8b98640827e5d0991a4015', - 'lib/libogg.a', - ['--disable-shared', '--enable-static'], - ), - - AutotoolsProject( - 'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.4.tar.xz', - '55f2288055e44754275a17c9a2497391', - 'lib/libvorbis.a', - ['--disable-shared', '--enable-static'], - ), - - AutotoolsProject( - 'http://downloads.xiph.org/releases/opus/opus-1.1.tar.gz', - 'c5a8cf7c0b066759542bc4ca46817ac6', - 'lib/libopus.a', - ['--disable-shared', '--enable-static'], - use_clang=True, - ), - - AutotoolsProject( - 'http://downloads.xiph.org/releases/flac/flac-1.3.1.tar.xz', - 'b9922c9a0378c88d3e901b234f852698', - 'lib/libFLAC.a', - [ - '--disable-shared', '--enable-static', - '--disable-xmms-plugin', '--disable-cpplibs', - ], - use_clang=True, - ), - - AutotoolsProject( - 'ftp://ftp.mars.org/pub/mpeg/libid3tag-0.15.1b.tar.gz', - 'e5808ad997ba32c498803822078748c3', - 'lib/libid3tag.a', - ['--disable-shared', '--enable-static'], - autogen=True, - ), - - AutotoolsProject( - 'ftp://ftp.mars.org/pub/mpeg/libmad-0.15.1b.tar.gz', - '1be543bc30c56fb6bea1d7bf6a64e66c', - 'lib/libmad.a', - ['--disable-shared', '--enable-static'], - autogen=True, - ), - - FfmpegProject( - 'http://ffmpeg.org/releases/ffmpeg-2.5.tar.bz2', - '4346fe710cc6bdd981f6534d2420d1ab', - 'lib/libavcodec.a', - [ - '--disable-shared', '--enable-static', - '--enable-gpl', - '--enable-small', - '--disable-pthreads', - '--disable-runtime-cpudetect', - '--disable-programs', - '--disable-doc', - '--disable-avdevice', - '--disable-swresample', - '--disable-swscale', - '--disable-postproc', - '--disable-avfilter', - '--disable-network', - '--disable-encoders', - '--disable-protocols', - '--disable-outdevs', - '--disable-filters', - ], - ), - - AutotoolsProject( - 'http://curl.haxx.se/download/curl-7.39.0.tar.lzma', - 'e9aa6dec29920eba8ef706ea5823bad7', - 'lib/libcurl.a', - [ - '--disable-shared', '--enable-static', - '--disable-debug', - '--enable-http', - '--enable-ipv6', - '--disable-ftp', '--disable-file', - '--disable-ldap', '--disable-ldaps', - '--disable-rtsp', '--disable-proxy', '--disable-dict', '--disable-telnet', - '--disable-tftp', '--disable-pop3', '--disable-imap', '--disable-smtp', - '--disable-gopher', - '--disable-manual', - '--disable-threaded-resolver', '--disable-verbose', '--disable-sspi', - '--disable-crypto-auth', '--disable-ntlm-wb', '--disable-tls-srp', '--disable-cookies', - '--without-ssl', '--without-gnutls', '--without-nss', '--without-libssh2', - ], - use_clang=True, - ), - - BoostProject( - 'http://netcologne.dl.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2', - 'd6eef4b4cacb2183f2bf265a5a03a354', - 'include/boost/version.hpp', - ), + libogg, + libvorbis, + opus, + flac, + libid3tag, + libmad, + ffmpeg, + curl, + boost, ] # build the third-party libraries for x in thirdparty_libs: - if not x.is_installed(): - x.build() + toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path, + use_cxx=x.use_cxx) + if not x.is_installed(toolchain): + x.build(toolchain) # configure and build MPD -select_toolchain(use_cxx=True, use_clang=True) +toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path, + use_cxx=True) configure = [ os.path.join(mpd_path, 'configure'), - 'CC=' + cc, - 'CXX=' + cxx, - 'CFLAGS=' + cflags, - 'CXXFLAGS=' + cxxflags, - 'CPPFLAGS=' + cppflags, - 'LDFLAGS=' + ldflags, - 'LIBS=' + libs, - 'AR=' + ar, - 'STRIP=' + strip, - '--host=' + host_arch, - '--prefix=' + root_path, - '--with-sysroot=' + target_root, + 'CC=' + toolchain.cc, + 'CXX=' + toolchain.cxx, + 'CFLAGS=' + toolchain.cflags, + 'CXXFLAGS=' + toolchain.cxxflags, + 'CPPFLAGS=' + toolchain.cppflags, + 'LDFLAGS=' + toolchain.ldflags, + 'LIBS=' + toolchain.libs, + 'AR=' + toolchain.ar, + 'RANLIB=' + toolchain.ranlib, + 'STRIP=' + toolchain.strip, + '--host=' + toolchain.arch, + '--prefix=' + toolchain.install_prefix, + '--with-sysroot=' + toolchain.sysroot, '--with-android-sdk=' + sdk_path, '--enable-silent-rules', - '--disable-glib', '--disable-icu', - # disabled for now because these features require GLib: - '--disable-httpd-output', - '--disable-vorbis-encoder', - ] + configure_args -subprocess.check_call(configure) -subprocess.check_call(['/usr/bin/make', '--quiet', '-j12']) +subprocess.check_call(configure, env=toolchain.env) +subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env) diff -Nru mpd-0.19.21/android/src/Bridge.java mpd-0.20.9/android/src/Bridge.java --- mpd-0.19.21/android/src/Bridge.java 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/android/src/Bridge.java 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/android/src/Loader.java mpd-0.20.9/android/src/Loader.java --- mpd-0.19.21/android/src/Loader.java 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/android/src/Loader.java 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/android/src/Main.java mpd-0.20.9/android/src/Main.java --- mpd-0.19.21/android/src/Main.java 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/android/src/Main.java 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/AUTHORS mpd-0.20.9/AUTHORS --- mpd-0.19.21/AUTHORS 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/AUTHORS 2017-01-27 07:46:51.000000000 +0000 @@ -1,11 +1,11 @@ Music Player Daemon - http://www.musicpd.org -Copyright (C) 2003-2014 The Music Player Daemon Project +Copyright 2003-2017 The Music Player Daemon Project The following people have contributed code to MPD: Warren Dukes Avuton Olrich - Max Kellermann + Max Kellermann Laszlo Ashin Viliam Mateicka Eric Wollesen @@ -29,3 +29,4 @@ Denis Krjuchkov Jurgen Kramer Jean-Francois Dockes + Yue Wang diff -Nru mpd-0.19.21/build/config.guess mpd-0.20.9/build/config.guess --- mpd-0.19.21/build/config.guess 2016-07-29 08:02:08.000000000 +0000 +++ mpd-0.20.9/build/config.guess 2017-05-19 17:26:26.000000000 +0000 @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2016-04-02' +timestamp='2016-10-02' # 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 @@ -186,9 +186,12 @@ *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. + # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in - arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -997,6 +1000,9 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; @@ -1029,6 +1035,9 @@ ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; @@ -1408,18 +1417,17 @@ cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp diff -Nru mpd-0.19.21/build/config.sub mpd-0.20.9/build/config.sub --- mpd-0.19.21/build/config.sub 2016-07-29 08:02:08.000000000 +0000 +++ mpd-0.20.9/build/config.sub 2017-05-19 17:26:26.000000000 +0000 @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2016-03-30' +timestamp='2016-11-04' # 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 @@ -117,7 +117,7 @@ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -301,6 +301,7 @@ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ @@ -428,6 +429,7 @@ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ @@ -643,6 +645,14 @@ basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -1022,7 +1032,7 @@ ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) @@ -1032,7 +1042,7 @@ ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) @@ -1389,7 +1399,7 @@ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ @@ -1399,7 +1409,7 @@ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) diff -Nru mpd-0.19.21/config.h.in mpd-0.20.9/config.h.in --- mpd-0.19.21/config.h.in 2016-12-13 07:55:32.000000000 +0000 +++ mpd-0.20.9/config.h.in 2017-06-03 18:58:54.000000000 +0000 @@ -1,120 +1,204 @@ /* config.h.in. Generated from configure.ac by autoheader. */ -/* The archive API is available */ +/* Define to enable AdPlug decoder plugin */ +#undef ENABLE_ADPLUG + +/* Define to enable ALSA output plugin */ +#undef ENABLE_ALSA + +/* Define to enable libao output plugin */ +#undef ENABLE_AO + +/* Define to enable the archive API */ #undef ENABLE_ARCHIVE -/* Define to enable libcdio_paranoia support */ +/* Define to enable audiofile decoder plugin */ +#undef ENABLE_AUDIOFILE + +/* Define to enable bzip2 archive plugin */ +#undef ENABLE_BZ2 + +/* Define to enable libcdio_paranoia input plugin */ #undef ENABLE_CDIO_PARANOIA -/* Define when libcurl is used for HTTP streaming */ +/* Define to enable CUE sheet parser */ +#undef ENABLE_CUE + +/* Define to enable libcurl HTTP streaming */ #undef ENABLE_CURL +/* Define to enable Enable daemonization? */ +#undef ENABLE_DAEMON + /* Define to enable the music database */ #undef ENABLE_DATABASE -/* Define for the DSD decoder */ +/* Define to enable DSD decoder */ #undef ENABLE_DSD /* Define to enable the encoder plugins */ #undef ENABLE_ENCODER -/* Define to enable the FLAC encoder plugin */ +/* Define to enable expat XML parser */ +#undef ENABLE_EXPAT + +/* Define to enable FAAD decoder plugin */ +#undef ENABLE_FAAD + +/* Define to enable ffmpeg decoder library */ +#undef ENABLE_FFMPEG + +/* Define to enable FLAC decoder */ +#undef ENABLE_FLAC + +/* Define to enable FLAC encoder plugin */ #undef ENABLE_FLAC_ENCODER -/* Define for fluidsynth support */ +/* Define to enable fluidsynth MIDI decoder plugin */ #undef ENABLE_FLUIDSYNTH +/* Define to enable Game Music Emulator decoder plugin */ +#undef ENABLE_GME + +/* Define to enable Haiku output plugin */ +#undef ENABLE_HAIKU + /* Define to enable the HTTP server output */ #undef ENABLE_HTTPD_OUTPUT +/* Define to enable ID3 support using libid3tag */ +#undef ENABLE_ID3TAG + /* Define to enable inotify support */ #undef ENABLE_INOTIFY -/* Define to enable the lame encoder plugin */ -#undef ENABLE_LAME_ENCODER +/* Define to enable libiso9660 archive plugin */ +#undef ENABLE_ISO9660 + +/* Define to enable JACK output plugin */ +#undef ENABLE_JACK + +/* Define to enable LAME encoder plugin */ +#undef ENABLE_LAME /* Define if large file support is enabled */ #undef ENABLE_LARGEFILE +/* Define to enable MPD client library */ +#undef ENABLE_LIBMPDCLIENT + +/* Define to enable libsamplerate resampling */ +#undef ENABLE_LIBSAMPLERATE + +/* Define to enable libmad MP3 decoder plugin */ +#undef ENABLE_MAD + /* Define for mikmod support */ #undef ENABLE_MIKMOD_DECODER -/* Define when libmms is used for the MMS protocol */ +/* Define to enable libmms mms:// protocol support */ #undef ENABLE_MMS -/* Define to enable support for neighbor discovery */ +/* Define to enable modplug decoder plugin */ +#undef ENABLE_MODPLUG + +/* Define to enable Musepack decoder plugin */ +#undef ENABLE_MPCDEC + +/* Define to enable libmpg123 decoder plugin */ +#undef ENABLE_MPG123 + +/* Define to enable neighbor discovery */ #undef ENABLE_NEIGHBOR_PLUGINS -/* Define when libnfs is used */ +/* Define to enable NFS input plugin */ #undef ENABLE_NFS +/* Define to enable opus decoder plugin */ +#undef ENABLE_OPUS + /* Define to enable support for writing audio to a pipe */ #undef ENABLE_PIPE_OUTPUT +/* Define to enable PulseAudio output plugin */ +#undef ENABLE_PULSE + /* Define to enable the recorder output */ #undef ENABLE_RECORDER_OUTPUT -/* Define to enable the shine encoder plugin */ -#undef ENABLE_SHINE_ENCODER +/* Define to enable RoarAudio output plugin */ +#undef ENABLE_ROAR + +/* Define to enable shine encoder */ +#undef ENABLE_SHINE /* Define for libsidplay2 support */ #undef ENABLE_SIDPLAY -/* Define when libsmbclient is used */ +/* Define to enable smbclient input plugin */ #undef ENABLE_SMBCLIENT -/* Define to enable the sndfile decoder plugin */ +/* Define to enable libsndfile decoder plugin */ #undef ENABLE_SNDFILE +/* Define to enable sndio output plugin */ +#undef ENABLE_SNDIO + /* Define to enable Solaris /dev/audio support */ #undef ENABLE_SOLARIS_OUTPUT -/* Define when soundcloud is enabled */ +/* Define to enable soundcloud.com support */ #undef ENABLE_SOUNDCLOUD -/* Define to enable sqlite database support */ +/* Define to enable libsoxr resampler */ +#undef ENABLE_SOXR + +/* Define to enable SQLite database support */ #undef ENABLE_SQLITE -/* Define to use the systemd daemon library */ +/* Define to enable systemd socket activation */ #undef ENABLE_SYSTEMD_DAEMON -/* Define to enable the TwoLAME encoder plugin */ -#undef ENABLE_TWOLAME_ENCODER +/* Define to enable TwoLAME encoder plugin */ +#undef ENABLE_TWOLAME + +/* Define to enable UPnP client support */ +#undef ENABLE_UPNP + +/* Define to enable Ogg Vorbis encoder */ +#undef ENABLE_VORBISENC /* Define for Ogg Vorbis support */ #undef ENABLE_VORBIS_DECODER -/* Define to enable the vorbis encoder plugin */ -#undef ENABLE_VORBIS_ENCODER - -/* Define to enable the PCM wave encoder plugin */ +/* Define to enable PCM wave encoder plugin */ #undef ENABLE_WAVE_ENCODER -/* Define for wildmidi support */ +/* Define to enable WavPack decoder plugin */ +#undef ENABLE_WAVPACK + +/* Define to enable WebDAV storage plugin */ +#undef ENABLE_WEBDAV + +/* Define to enable WildMidi decoder plugin */ #undef ENABLE_WILDMIDI /* Define to enable WinMM support */ #undef ENABLE_WINMM_OUTPUT +/* Define to enable zlib support */ +#undef ENABLE_ZLIB + +/* Define to enable libzzip archive library */ +#undef ENABLE_ZZIP + /* The current git commit */ #undef GIT_COMMIT /* Define to 1 if you have the `accept4' function. */ #undef HAVE_ACCEPT4 -/* Define to use libadplug */ -#undef HAVE_ADPLUG - -/* Define to enable ALSA support */ -#undef HAVE_ALSA - -/* Define to play with ao */ -#undef HAVE_AO - -/* Define for audiofile support */ -#undef HAVE_AUDIOFILE - -/* Define to enable Avahi Zeroconf support */ +/* Define to enable Avahi Zeroconf */ #undef HAVE_AVAHI /* Define to enable Bonjour Zeroconf support */ @@ -123,26 +207,17 @@ /* define if the Boost library is available */ #undef HAVE_BOOST -/* Define to have bz2 archive support */ -#undef HAVE_BZ2 - /* Define to 1 if you have the header file. */ #undef HAVE_CDIO_PARANOIA_PARANOIA_H -/* Define to use the expat XML parser */ -#undef HAVE_EXPAT - -/* Define to use FAAD2 for AAC decoding */ -#undef HAVE_FAAD - -/* Define for FFMPEG support */ -#undef HAVE_FFMPEG +/* define if the compiler supports basic C++14 syntax */ +#undef HAVE_CXX14 /* Define to enable support for writing audio to a FIFO */ #undef HAVE_FIFO -/* Define for FLAC support */ -#undef HAVE_FLAC +/* Define to 1 if you have the `fnmatch' function. */ +#undef HAVE_FNMATCH /* Define to 1 if you have the `getpeereid' function. */ #undef HAVE_GETPEEREID @@ -153,18 +228,12 @@ /* Define to 1 if you have the `getpwuid_r' function. */ #undef HAVE_GETPWUID_R -/* Define if GLib is used */ -#undef HAVE_GLIB - -/* Define for gme support */ -#undef HAVE_GME +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV -/* Define if libicu is used */ +/* Define to enable libicu */ #undef HAVE_ICU -/* Define to use id3tag */ -#undef HAVE_ID3TAG - /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS @@ -180,55 +249,25 @@ /* Define if IPv6 support present */ #undef HAVE_IPV6 -/* Define to have ISO9660 archive support */ -#undef HAVE_ISO9660 - -/* Define to enable JACK support */ -#undef HAVE_JACK - /* Define to 1 if you have the `jack_set_info_function' function. */ #undef HAVE_JACK_SET_INFO_FUNCTION /* Define to 1 if you have the `dns_sd' library (-ldns_sd). */ #undef HAVE_LIBDNS_SD -/* Define to 1 if you have the `faad' library (-lfaad). */ -#undef HAVE_LIBFAAD - -/* Define to use libmpdclient */ -#undef HAVE_LIBMPDCLIENT - -/* Define to enable libsamplerate */ -#undef HAVE_LIBSAMPLERATE - -/* Define when libupnp is used */ -#undef HAVE_LIBUPNP - -/* Define to 1 if you have the `vorbisidec' library (-lvorbisidec). */ -#undef HAVE_LIBVORBISIDEC - /* define to enable libwrap library */ #undef HAVE_LIBWRAP +/* Define to 1 if you have the `linkat' function. */ +#undef HAVE_LINKAT + /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H -/* Define to use libmad */ -#undef HAVE_MAD - /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define for modplug support */ -#undef HAVE_MODPLUG - -/* Define to use libmpcdec for MPC decoding */ -#undef HAVE_MPCDEC - -/* Define to use libmpg123 */ -#undef HAVE_MPG123 - -/* Define for OpenAL support */ +/* Define to enable OpenAL support */ #undef HAVE_OPENAL /* Define to 1 if you have the header file. */ @@ -237,10 +276,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENAL_AL_H -/* Define to use libopus */ -#undef HAVE_OPUS - -/* Define to enable OSS */ +/* Define to enable Open Sound System */ #undef HAVE_OSS /* Define for compiling OS X support */ @@ -258,27 +294,15 @@ /* Have PTHREAD_PRIO_INHERIT. */ #undef HAVE_PTHREAD_PRIO_INHERIT -/* Is pthread_setname_np() available? */ +/* Define to 1 if you have the `pthread_setname_np' function. */ #undef HAVE_PTHREAD_SETNAME_NP -/* Define to enable PulseAudio support */ -#undef HAVE_PULSE - -/* Define to enable ROAR support */ -#undef HAVE_ROAR - -/* Define to enable the shoutcast output */ +/* Define to enable shoutcast output */ #undef HAVE_SHOUT /* Define if libsidplayfp is used instead of libsidplay2 */ #undef HAVE_SIDPLAYFP -/* Define to enable libsoxr */ -#undef HAVE_SOXR - -/* Define if g++ supports C++0x features. */ -#undef HAVE_STDCXX_0X - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -327,18 +351,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_VALGRIND_MEMCHECK_H -/* Define to enable WavPack support */ -#undef HAVE_WAVPACK - /* Define to enable Zeroconf support */ #undef HAVE_ZEROCONF -/* Define to enable zlib support */ -#undef HAVE_ZLIB - -/* Define to have zip archive support */ -#undef HAVE_ZZIP - /* Name of package */ #undef PACKAGE diff -Nru mpd-0.19.21/configure mpd-0.20.9/configure --- mpd-0.19.21/configure 2016-12-13 07:55:28.000000000 +0000 +++ mpd-0.20.9/configure 2017-06-03 18:58:49.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for mpd 0.19.21. +# Generated by GNU Autoconf 2.69 for mpd 0.20.9. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='mpd' PACKAGE_TARNAME='mpd' -PACKAGE_VERSION='0.19.21' -PACKAGE_STRING='mpd 0.19.21' +PACKAGE_VERSION='0.20.9' +PACKAGE_STRING='mpd 0.20.9' PACKAGE_BUGREPORT='musicpd-dev-team@lists.sourceforge.net' PACKAGE_URL='' @@ -634,6 +634,12 @@ ENABLE_DOCUMENTATION_TRUE DOXYGEN XMLTO +HAVE_XIPH_FALSE +HAVE_XIPH_TRUE +HAVE_OGG_FALSE +HAVE_OGG_TRUE +OGG_LIBS +OGG_CFLAGS ENABLE_WINMM_OUTPUT_FALSE ENABLE_WINMM_OUTPUT_TRUE ENABLE_SOLARIS_OUTPUT_FALSE @@ -642,8 +648,8 @@ HAVE_SHOUT_TRUE ENABLE_RECORDER_OUTPUT_FALSE ENABLE_RECORDER_OUTPUT_TRUE -HAVE_PULSE_FALSE -HAVE_PULSE_TRUE +ENABLE_PULSE_FALSE +ENABLE_PULSE_TRUE PULSE_LIBS PULSE_CFLAGS ENABLE_PIPE_OUTPUT_FALSE @@ -656,58 +662,62 @@ HAVE_OPENAL_TRUE OPENAL_LIBS OPENAL_CFLAGS -HAVE_AO_FALSE -HAVE_AO_TRUE +ENABLE_AO_FALSE +ENABLE_AO_TRUE AO_LIBS AO_CFLAGS -HAVE_JACK_FALSE -HAVE_JACK_TRUE +ENABLE_JACK_FALSE +ENABLE_JACK_TRUE JACK_LIBS JACK_CFLAGS ENABLE_HTTPD_OUTPUT_FALSE ENABLE_HTTPD_OUTPUT_TRUE +ENABLE_HAIKU_FALSE +ENABLE_HAIKU_TRUE +HAIKU_CFLAGS +HAIKU_LIBS +ENABLE_SNDIO_FALSE +ENABLE_SNDIO_TRUE +SNDIO_CFLAGS +SNDIO_LIBS HAVE_FIFO_FALSE HAVE_FIFO_TRUE -HAVE_ROAR_FALSE -HAVE_ROAR_TRUE +ENABLE_ROAR_FALSE +ENABLE_ROAR_TRUE ROAR_LIBS ROAR_CFLAGS -HAVE_ALSA_FALSE -HAVE_ALSA_TRUE +ENABLE_ALSA_FALSE +ENABLE_ALSA_TRUE ALSA_LIBS ALSA_CFLAGS -HAVE_OGG_ENCODER_FALSE -HAVE_OGG_ENCODER_TRUE ENABLE_ENCODER_FALSE ENABLE_ENCODER_TRUE ENABLE_WAVE_ENCODER_FALSE ENABLE_WAVE_ENCODER_TRUE -ENABLE_TWOLAME_ENCODER_FALSE -ENABLE_TWOLAME_ENCODER_TRUE +ENABLE_TWOLAME_FALSE +ENABLE_TWOLAME_TRUE TWOLAME_LIBS TWOLAME_CFLAGS -ENABLE_LAME_ENCODER_FALSE -ENABLE_LAME_ENCODER_TRUE +ENABLE_LAME_FALSE +ENABLE_LAME_TRUE LAME_CFLAGS LAME_LIBS -ENABLE_VORBIS_ENCODER_FALSE -ENABLE_VORBIS_ENCODER_TRUE +ENABLE_VORBISENC_FALSE +ENABLE_VORBISENC_TRUE VORBISENC_LIBS VORBISENC_CFLAGS -ENABLE_SHINE_ENCODER_FALSE -ENABLE_SHINE_ENCODER_TRUE +ENABLE_SHINE_FALSE +ENABLE_SHINE_TRUE SHINE_LIBS SHINE_CFLAGS ENABLE_FLAC_ENCODER_FALSE ENABLE_FLAC_ENCODER_TRUE -HAVE_XIPH_FALSE -HAVE_XIPH_TRUE ENABLE_WILDMIDI_FALSE ENABLE_WILDMIDI_TRUE WILDMIDI_CFLAGS WILDMIDI_LIBS -HAVE_WAVPACK_FALSE -HAVE_WAVPACK_TRUE +ENABLE_WAVPACK_FALSE +ENABLE_WAVPACK_TRUE WAVPACK_LIBS WAVPACK_CFLAGS ENABLE_SIDPLAY_FALSE @@ -720,20 +730,20 @@ VORBIS_CFLAGS TREMOR_LIBS TREMOR_CFLAGS -HAVE_MPCDEC_FALSE -HAVE_MPCDEC_TRUE +ENABLE_MPCDEC_FALSE +ENABLE_MPCDEC_TRUE MPCDEC_CFLAGS MPCDEC_LIBS ENABLE_SNDFILE_FALSE ENABLE_SNDFILE_TRUE SNDFILE_LIBS SNDFILE_CFLAGS -HAVE_OPUS_FALSE -HAVE_OPUS_TRUE +ENABLE_OPUS_FALSE +ENABLE_OPUS_TRUE OPUS_LIBS OPUS_CFLAGS -HAVE_MODPLUG_FALSE -HAVE_MODPLUG_TRUE +ENABLE_MODPLUG_FALSE +ENABLE_MODPLUG_TRUE MODPLUG_LIBS MODPLUG_CFLAGS ENABLE_MIKMOD_DECODER_FALSE @@ -741,44 +751,44 @@ LIBMIKMOD_LIBS LIBMIKMOD_CFLAGS LIBMIKMOD_CONFIG -HAVE_MPG123_FALSE -HAVE_MPG123_TRUE +ENABLE_MPG123_FALSE +ENABLE_MPG123_TRUE MPG123_LIBS MPG123_CFLAGS SHOUT_LIBS SHOUT_CFLAGS -HAVE_MAD_FALSE -HAVE_MAD_TRUE +ENABLE_MAD_FALSE +ENABLE_MAD_TRUE MAD_LIBS MAD_CFLAGS -HAVE_GME_FALSE -HAVE_GME_TRUE +ENABLE_GME_FALSE +ENABLE_GME_TRUE GME_LIBS GME_CFLAGS ENABLE_FLUIDSYNTH_FALSE ENABLE_FLUIDSYNTH_TRUE FLUIDSYNTH_LIBS FLUIDSYNTH_CFLAGS -HAVE_FLAC_FALSE -HAVE_FLAC_TRUE +ENABLE_FLAC_FALSE +ENABLE_FLAC_TRUE FLAC_LIBS FLAC_CFLAGS -HAVE_FFMPEG_FALSE -HAVE_FFMPEG_TRUE +ENABLE_FFMPEG_FALSE +ENABLE_FFMPEG_TRUE FFMPEG_LIBS FFMPEG_CFLAGS -HAVE_FAAD_FALSE -HAVE_FAAD_TRUE -FAAD_LIBS +ENABLE_FAAD_FALSE +ENABLE_FAAD_TRUE FAAD_CFLAGS +FAAD_LIBS ENABLE_DSD_FALSE ENABLE_DSD_TRUE -HAVE_AUDIOFILE_FALSE -HAVE_AUDIOFILE_TRUE +ENABLE_AUDIOFILE_FALSE +ENABLE_AUDIOFILE_TRUE AUDIOFILE_LIBS AUDIOFILE_CFLAGS -HAVE_ADPLUG_FALSE -HAVE_ADPLUG_TRUE +ENABLE_ADPLUG_FALSE +ENABLE_ADPLUG_TRUE ADPLUG_LIBS ADPLUG_CFLAGS ENABLE_ARCHIVE_FALSE @@ -786,34 +796,38 @@ ENABLE_ZZIP_TEST_FALSE ENABLE_ZZIP_TEST_TRUE ZIP -HAVE_ZZIP_FALSE -HAVE_ZZIP_TRUE +ENABLE_ZZIP_FALSE +ENABLE_ZZIP_TRUE ZZIP_LIBS ZZIP_CFLAGS -HAVE_LIBUPNP_FALSE -HAVE_LIBUPNP_TRUE +ENABLE_UPNP_FALSE +ENABLE_UPNP_TRUE UPNP_LIBS UPNP_CFLAGS ENABLE_BZIP2_TEST_FALSE ENABLE_BZIP2_TEST_TRUE BZIP2 -HAVE_BZ2_FALSE -HAVE_BZ2_TRUE +ENABLE_BZ2_FALSE +ENABLE_BZ2_TRUE BZ2_CFLAGS BZ2_LIBS -HAVE_ZLIB_FALSE -HAVE_ZLIB_TRUE +ENABLE_ZLIB_FALSE +ENABLE_ZLIB_TRUE ZLIB_LIBS ZLIB_CFLAGS ENABLE_ISO9660_TEST_FALSE ENABLE_ISO9660_TEST_TRUE MKISOFS -HAVE_ISO9660_FALSE -HAVE_ISO9660_TRUE +ENABLE_ISO9660_FALSE +ENABLE_ISO9660_TRUE ISO9660_LIBS ISO9660_CFLAGS ENABLE_NEIGHBOR_PLUGINS_FALSE ENABLE_NEIGHBOR_PLUGINS_TRUE +ENABLE_CUE_FALSE +ENABLE_CUE_TRUE +ENABLE_WEBDAV_FALSE +ENABLE_WEBDAV_TRUE ENABLE_MMS_FALSE ENABLE_MMS_TRUE MMS_LIBS @@ -838,14 +852,14 @@ ENABLE_CURL_TRUE CURL_LIBS CURL_CFLAGS -HAVE_SOXR_FALSE -HAVE_SOXR_TRUE +ENABLE_SOXR_FALSE +ENABLE_SOXR_TRUE SOXR_LIBS SOXR_CFLAGS -HAVE_LIBSAMPLERATE_FALSE -HAVE_LIBSAMPLERATE_TRUE -SAMPLERATE_LIBS -SAMPLERATE_CFLAGS +ENABLE_LIBSAMPLERATE_FALSE +ENABLE_LIBSAMPLERATE_TRUE +LIBSAMPLERATE_LIBS +LIBSAMPLERATE_CFLAGS ENABLE_SQLITE_FALSE ENABLE_SQLITE_TRUE SQLITE_LIBS @@ -858,36 +872,34 @@ HAVE_AVAHI_TRUE AVAHI_LIBS AVAHI_CFLAGS -HAVE_ID3TAG_FALSE -HAVE_ID3TAG_TRUE +ENABLE_ID3TAG_FALSE +ENABLE_ID3TAG_TRUE ID3TAG_LIBS ID3TAG_CFLAGS LIBWRAP_LDFLAGS LIBWRAP_CFLAGS ENABLE_INOTIFY_FALSE ENABLE_INOTIFY_TRUE -HAVE_EXPAT_FALSE -HAVE_EXPAT_TRUE +ENABLE_EXPAT_FALSE +ENABLE_EXPAT_TRUE EXPAT_LIBS EXPAT_CFLAGS -HAVE_LIBMPDCLIENT_FALSE -HAVE_LIBMPDCLIENT_TRUE +ENABLE_LIBMPDCLIENT_FALSE +ENABLE_LIBMPDCLIENT_TRUE LIBMPDCLIENT_LIBS LIBMPDCLIENT_CFLAGS ENABLE_SYSTEMD_DAEMON_FALSE ENABLE_SYSTEMD_DAEMON_TRUE SYSTEMD_DAEMON_LIBS SYSTEMD_DAEMON_CFLAGS -HAVE_GLIB_FALSE -HAVE_GLIB_TRUE -GLIB_LIBS -GLIB_CFLAGS HAVE_ICU_FALSE HAVE_ICU_TRUE ICU_LIBS ICU_CFLAGS BOOST_LDFLAGS BOOST_CPPFLAGS +ENABLE_DAEMON_FALSE +ENABLE_DAEMON_TRUE ENABLE_DATABASE_FALSE ENABLE_DATABASE_TRUE PTHREAD_CFLAGS @@ -897,11 +909,15 @@ EGREP GREP CPP +SED +HAVE_CXX14 ANDROID_SDK HAVE_WINDOWS_FALSE HAVE_WINDOWS_TRUE ANDROID_FALSE ANDROID_TRUE +XRES +RC WINDRES host_os host_vendor @@ -1026,87 +1042,91 @@ with_systemdsystemunitdir with_systemduserunitdir with_android_sdk +enable_syslog enable_eventfd enable_signalfd enable_poll enable_epoll with_pollmethod enable_database -enable_libmpdclient -enable_expat -enable_upnp -enable_adplug -enable_alsa -enable_roar -enable_ao -enable_audiofile -enable_zlib -enable_bzip2 -enable_cdio_paranoia -enable_curl -enable_smbclient -enable_nfs +enable_daemon enable_debug enable_documentation enable_dsd -enable_ffmpeg enable_fifo -enable_flac -enable_fluidsynth -enable_gme enable_httpd_output -enable_id3 enable_inotify enable_ipv6 -enable_iso9660 -enable_jack enable_largefile enable_soundcloud -enable_lame_encoder enable_libwrap -enable_lsr -enable_soxr -enable_mad enable_mikmod -enable_mms -enable_modplug -enable_mpc -enable_mpg123 enable_openal -enable_opus enable_oss enable_osx enable_pipe_output -enable_pulse enable_recorder_output enable_sidplay -enable_shine_encoder enable_shout -enable_sndfile enable_solaris_output -enable_sqlite -enable_systemd_daemon enable_tcp enable_test -with_tremor -enable_twolame_encoder enable_un enable_vorbis -enable_vorbis_encoder enable_wave_encoder -enable_wavpack enable_werror -enable_wildmidi with_zeroconf -enable_zzip -with_tremor_libraries -with_tremor_includes with_boost with_boost_libdir enable_icu -enable_glib +enable_iconv +enable_systemd_daemon +enable_libmpdclient +enable_expat +enable_id3 +enable_sqlite +enable_lsr +enable_soxr +enable_curl +enable_smbclient +enable_nfs +enable_cdio_paranoia +enable_mms +enable_webdav +enable_cue enable_neighbor_plugins +enable_iso9660 +enable_zlib +enable_bzip2 +enable_upnp +enable_zzip +enable_adplug +enable_audiofile enable_aac +enable_ffmpeg +enable_flac +enable_fluidsynth +enable_gme +enable_mad +enable_mpg123 +enable_modplug +enable_opus +enable_sndfile +enable_mpc +with_tremor +enable_wavpack +enable_wildmidi +enable_shine_encoder +enable_vorbis_encoder +enable_lame_encoder +enable_twolame_encoder +enable_alsa +enable_roar +enable_sndio +enable_haiku +enable_jack +enable_ao +enable_pulse ' ac_precious_vars='build_alias host_alias @@ -1125,8 +1145,6 @@ CPP ICU_CFLAGS ICU_LIBS -GLIB_CFLAGS -GLIB_LIBS SYSTEMD_DAEMON_CFLAGS SYSTEMD_DAEMON_LIBS LIBMPDCLIENT_CFLAGS @@ -1139,8 +1157,8 @@ AVAHI_LIBS SQLITE_CFLAGS SQLITE_LIBS -SAMPLERATE_CFLAGS -SAMPLERATE_LIBS +LIBSAMPLERATE_CFLAGS +LIBSAMPLERATE_LIBS SOXR_CFLAGS SOXR_LIBS CURL_CFLAGS @@ -1187,6 +1205,8 @@ OPUS_LIBS SNDFILE_CFLAGS SNDFILE_LIBS +TREMOR_CFLAGS +TREMOR_LIBS VORBIS_CFLAGS VORBIS_LIBS SIDPLAY_CFLAGS @@ -1211,6 +1231,8 @@ OPENAL_LIBS PULSE_CFLAGS PULSE_LIBS +OGG_CFLAGS +OGG_LIBS CPPUNIT_CFLAGS CPPUNIT_LIBS' @@ -1763,7 +1785,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures mpd 0.19.21 to adapt to many kinds of systems. +\`configure' configures mpd 0.20.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1834,7 +1856,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of mpd 0.19.21:";; + short | recursive ) echo "Configuration of mpd 0.20.9:";; esac cat <<\_ACEOF @@ -1848,92 +1870,101 @@ do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build + --enable-syslog enable syslog support (default: auto) --enable-eventfd use the function "eventfd" (default: auto) --enable-signalfd use the function "signalfd" (default: auto) --enable-poll use the function "poll" (default: auto) --enable-epoll use the function "epoll" (default: auto) --enable-database enable support for the music database - --enable-libmpdclient enable support for the MPD client - --enable-expat enable the expat XML parser - --enable-upnp enable UPnP client support (default: auto) - --enable-adplug enable the AdPlug decoder plugin (default: auto) - --enable-alsa enable ALSA support - --enable-roar enable support for RoarAudio - --enable-ao enable support for libao - --enable-audiofile enable audiofile support (WAV and others) - --enable-zlib enable zlib support (default: auto) - --enable-bzip2 enable bzip2 archive support (default: auto) - --enable-cdio-paranoia enable support for audio CD support - --enable-curl enable support for libcurl HTTP streaming (default: - auto) - --enable-smbclient enable support for libsmbclient (default: auto) - --enable-nfs enable support for libnfs (default: auto) + --enable-daemon enable daemonization (default: enabled) --enable-debug enable debugging (default: disabled) --enable-documentation build documentation (default: disable) --enable-dsd enable DSD decoder (default: enable) - --enable-ffmpeg enable FFMPEG support --disable-fifo disable support for writing audio to a FIFO (default: enable) - --enable-flac enable FLAC decoder - --enable-fluidsynth enable MIDI support via fluidsynth (default: auto) - --enable-gme enable Blargg's game music emulator plugin --enable-httpd-output enables the HTTP server output - --enable-id3 enable id3 support --disable-inotify disable support Inotify automatic database update (default: enabled) --disable-ipv6 disable IPv6 support (default: enable) - --enable-iso9660 enable iso9660 archive support (default: disabled) - --enable-jack enable jack support --disable-largefile omit support for large files --enable-soundcloud enable support for soundcloud.com - --enable-lame-encoder enable the LAME mp3 encoder --enable-libwrap use libwrap - --enable-lsr enable libsamplerate support - --enable-soxr enable the libsoxr resampler - --enable-mad enable libmad mp3 decoder plugin --enable-mikmod enable the mikmod decoder (default: disable) - --enable-mms enable the MMS protocol with libmms - --enable-modplug enable modplug decoder plugin - --enable-mpc disable musepack (MPC) support (default: auto) - --enable-mpg123 enable libmpg123 decoder plugin --enable-openal enable OpenAL support (default: auto) - --enable-opus enable Opus codec support (default: auto) --disable-oss disable OSS support (default: enable) --enable-osx enable the OS X output plugin - unsupported! (default: disable) --enable-pipe-output enable support for writing audio to a pipe (default: disable) - --enable-pulse enable support for the PulseAudio sound server --enable-recorder-output enables the recorder file output plugin (default: disable) --enable-sidplay enable C64 SID support via libsidplay2 - --enable-shine-encoder enables shine encoder --enable-shout enables the shoutcast streaming output - --enable-sndfile enable sndfile support --enable-solaris-output enables the Solaris /dev/audio output - --enable-sqlite enable support for the SQLite database - --enable-systemd-daemon use the systemd daemon library (default=auto) --disable-tcp disable support for clients connecting via TCP (default: enable) --enable-test build the test programs (default: disabled) - --enable-twolame-encoder - enable the TwoLAME mp2 encoder --disable-un disable support for clients connecting via unix domain sockets (default: enable) --enable-vorbis enable Ogg Vorbis decoder - --enable-vorbis-encoder enable the Ogg Vorbis encoder --enable-wave-encoder enable the PCM wave encoder - --enable-wavpack enable WavPack support --enable-werror treat warnings as errors (default: disabled) - --enable-wildmidi enable MIDI support via wildmidi (default: auto) - --enable-zzip enable zip archive support (default: disabled) - --enable-icu enable libicu for Unicode (default: enabled) - --enable-glib enable GLib usage (default: enabled) + --enable-icu enable libicu for Unicode (default: auto) + --enable-iconv enable iconv for character set conversion (default: + auto) + --enable-systemd-daemon enable systemd socket activation (default: auto) + --enable-libmpdclient enable MPD client library (default: auto) + --enable-expat enable expat XML parser (default: auto) + --enable-id3 enable ID3 support using libid3tag (default: auto) + --enable-sqlite enable SQLite database support (default: auto) + --enable-lsr enable libsamplerate resampling (default: auto) + --enable-soxr enable libsoxr resampler (default: auto) + --enable-curl enable libcurl HTTP streaming (default: auto) + --enable-smbclient enable smbclient input plugin (default: auto) + --enable-nfs enable NFS input plugin (default: auto) + --enable-cdio-paranoia enable libcdio_paranoia input plugin (default: auto) + --enable-mms enable libmms mms:// protocol support (default: + auto) + --enable-webdav enable WebDAV storage plugin (default: auto) + --enable-cue enable CUE sheet parser (default: yes) --enable-neighbor-plugins enable support for neighbor discovery (default: auto) - --disable-aac disable AAC support (default: enable) + --enable-iso9660 enable libiso9660 archive plugin (default: auto) + --enable-zlib enable zlib support (default: auto) + --enable-bzip2 enable bzip2 archive plugin (default: auto) + --enable-upnp enable UPnP client support (default: auto) + --enable-zzip enable libzzip archive library (default: no) + --enable-adplug enable AdPlug decoder plugin (default: auto) + --enable-audiofile enable audiofile decoder plugin (default: auto) + --enable-aac enable FAAD decoder plugin (default: auto) + --enable-ffmpeg enable ffmpeg decoder library (default: auto) + --enable-flac enable FLAC decoder (default: auto) + --enable-fluidsynth enable fluidsynth MIDI decoder plugin (default: + auto) + --enable-gme enable Game Music Emulator decoder plugin (default: + auto) + --enable-mad enable libmad MP3 decoder plugin (default: auto) + --enable-mpg123 enable libmpg123 decoder plugin (default: auto) + --enable-modplug enable modplug decoder plugin (default: auto) + --enable-opus enable opus decoder plugin (default: auto) + --enable-sndfile enable libsndfile decoder plugin (default: auto) + --enable-mpc enable Musepack decoder plugin (default: auto) + --enable-wavpack enable WavPack decoder plugin (default: auto) + --enable-wildmidi enable WildMidi decoder plugin (default: auto) + --enable-shine-encoder enable shine encoder (default: auto) + --enable-vorbis-encoder enable Ogg Vorbis encoder (default: auto) + --enable-lame-encoder enable LAME encoder plugin (default: auto) + --enable-twolame-encoder + enable TwoLAME encoder plugin (default: auto) + --enable-alsa enable ALSA output plugin (default: auto) + --enable-roar enable RoarAudio output plugin (default: auto) + --enable-sndio enable sndio output plugin (default: auto) + --enable-haiku enable Haiku output plugin (default: auto) + --enable-jack enable JACK output plugin (default: auto) + --enable-ao enable libao output plugin (default: auto) + --enable-pulse enable PulseAudio output plugin (default: auto) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1946,16 +1977,8 @@ --with-pollmethod=[epoll|poll|winselect|auto] specify poll method for internal event loop (default=auto) - --with-tremor=PFX use Tremor (vorbisidec) integer Ogg Vorbis decoder - (with optional prefix) --with-zeroconf=[auto|avahi|bonjour|no] enable zeroconf backend (default=auto) - --with-tremor-libraries=DIR - directory where Tremor library is installed - (optional) - --with-tremor-includes=DIR - directory where Tremor header files are installed - (optional) --with-boost[=ARG] use Boost library from a standard location (ARG=yes), from the specified location (ARG=), or disable it (ARG=no) [ARG=yes] @@ -1965,6 +1988,8 @@ this parameter only if default library detection fails and you know exactly where your boost libraries are located. + --with-tremor=PFX use Tremor (vorbisidec) integer Ogg Vorbis decoder + (with optional prefix) Some influential environment variables: CC C compiler command @@ -1984,8 +2009,6 @@ CPP C preprocessor ICU_CFLAGS C compiler flags for ICU, overriding pkg-config ICU_LIBS linker flags for ICU, overriding pkg-config - GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config - GLIB_LIBS linker flags for GLIB, overriding pkg-config SYSTEMD_DAEMON_CFLAGS C compiler flags for SYSTEMD_DAEMON, overriding pkg-config SYSTEMD_DAEMON_LIBS @@ -2006,10 +2029,10 @@ SQLITE_CFLAGS C compiler flags for SQLITE, overriding pkg-config SQLITE_LIBS linker flags for SQLITE, overriding pkg-config - SAMPLERATE_CFLAGS - C compiler flags for SAMPLERATE, overriding pkg-config - SAMPLERATE_LIBS - linker flags for SAMPLERATE, overriding pkg-config + LIBSAMPLERATE_CFLAGS + C compiler flags for LIBSAMPLERATE, overriding pkg-config + LIBSAMPLERATE_LIBS + linker flags for LIBSAMPLERATE, overriding pkg-config SOXR_CFLAGS C compiler flags for SOXR, overriding pkg-config SOXR_LIBS linker flags for SOXR, overriding pkg-config CURL_CFLAGS C compiler flags for CURL, overriding pkg-config @@ -2074,6 +2097,9 @@ C compiler flags for SNDFILE, overriding pkg-config SNDFILE_LIBS linker flags for SNDFILE, overriding pkg-config + TREMOR_CFLAGS + C compiler flags for Tremor + TREMOR_LIBS linker flags for Tremor VORBIS_CFLAGS C compiler flags for VORBIS, overriding pkg-config VORBIS_LIBS linker flags for VORBIS, overriding pkg-config @@ -2110,6 +2136,8 @@ PULSE_CFLAGS C compiler flags for PULSE, overriding pkg-config PULSE_LIBS linker flags for PULSE, overriding pkg-config + OGG_CFLAGS C compiler flags for OGG, overriding pkg-config + OGG_LIBS linker flags for OGG, overriding pkg-config CPPUNIT_CFLAGS C compiler flags for CPPUNIT, overriding pkg-config CPPUNIT_LIBS @@ -2181,7 +2209,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mpd configure 0.19.21 +mpd configure 0.20.9 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2317,6 +2345,43 @@ } # ac_fn_c_try_link +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly @@ -2384,43 +2449,6 @@ } # ac_fn_c_check_func -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using @@ -2584,57 +2612,11 @@ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile - -# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES -# --------------------------------------------- -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. -ac_fn_c_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - as_decl_name=`echo $2|sed 's/ *(.*//'` - as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by mpd $as_me 0.19.21, which was +It was created by mpd $as_me 0.20.9, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2984,8 +2966,8 @@ VERSION_MAJOR=0 -VERSION_MINOR=19 -VERSION_REVISION=21 +VERSION_MINOR=20 +VERSION_REVISION=9 VERSION_EXTRA=0 @@ -3504,7 +3486,7 @@ # Define the identity of the package. PACKAGE='mpd' - VERSION='0.19.21' + VERSION='0.20.9' cat >>confdefs.h <<_ACEOF @@ -3641,7 +3623,7 @@ -$as_echo "#define PROTOCOL_VERSION \"0.19.0\"" >>confdefs.h +$as_echo "#define PROTOCOL_VERSION \"0.20.0\"" >>confdefs.h GIT_COMMIT=`GIT_DIR="$srcdir/.git" git describe --dirty --always 2>/dev/null` @@ -5767,7 +5749,7 @@ ;; mingw32* | windows*) - ac_config_files="$ac_config_files src/win32/mpd_win32_rc.rc" + ac_config_files="$ac_config_files win32/res/mpd.rc" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. @@ -5863,6 +5845,8 @@ AM_CPPFLAGS="$AM_CPPFLAGS -DWIN32_LEAN_AND_MEAN" AM_CPPFLAGS="$AM_CPPFLAGS -DWINVER=0x0600 -D_WIN32_WINNT=0x0600" + AM_CPPFLAGS="$AM_CPPFLAGS -DSTRICT" + AM_CPPFLAGS="$AM_CPPFLAGS -DUNICODE -D_UNICODE" LIBS="$LIBS -lws2_32" host_is_windows=yes host_is_unix=no @@ -5875,33 +5859,219 @@ solaris*) host_is_solaris=yes ;; -esac - - if test x$host_is_android = xyes; then - ANDROID_TRUE= - ANDROID_FALSE='#' +haiku*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}rc", so it can be a program name with args. +set dummy ${ac_tool_prefix}rc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RC+:} false; then : + $as_echo_n "(cached) " >&6 else - ANDROID_TRUE='#' - ANDROID_FALSE= -fi + if test -n "$RC"; then + ac_cv_prog_RC="$RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RC="${ac_tool_prefix}rc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS - if test x$host_is_windows = xyes; then - HAVE_WINDOWS_TRUE= - HAVE_WINDOWS_FALSE='#' +fi +fi +RC=$ac_cv_prog_RC +if test -n "$RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 +$as_echo "$RC" >&6; } else - HAVE_WINDOWS_TRUE='#' - HAVE_WINDOWS_FALSE= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -if test -z "$prefix" || test "x$prefix" = xNONE; then - local_lib= - local_include= - - # aren't autotools supposed to be smart enough to figure this out? oh - # well, the git-core Makefile managed to do some of the work for us :) - case "$host_os" in - darwin*) +fi +if test -z "$ac_cv_prog_RC"; then + ac_ct_RC=$RC + # Extract the first word of "rc", so it can be a program name with args. +set dummy rc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RC"; then + ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RC="rc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RC=$ac_cv_prog_ac_ct_RC +if test -n "$ac_ct_RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 +$as_echo "$ac_ct_RC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RC" = x; then + RC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RC=$ac_ct_RC + fi +else + RC="$ac_cv_prog_RC" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}xres", so it can be a program name with args. +set dummy ${ac_tool_prefix}xres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_XRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$XRES"; then + ac_cv_prog_XRES="$XRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_XRES="${ac_tool_prefix}xres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +XRES=$ac_cv_prog_XRES +if test -n "$XRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XRES" >&5 +$as_echo "$XRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_XRES"; then + ac_ct_XRES=$XRES + # Extract the first word of "xres", so it can be a program name with args. +set dummy xres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_XRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_XRES"; then + ac_cv_prog_ac_ct_XRES="$ac_ct_XRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_XRES="xres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_XRES=$ac_cv_prog_ac_ct_XRES +if test -n "$ac_ct_XRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_XRES" >&5 +$as_echo "$ac_ct_XRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_XRES" = x; then + XRES="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + XRES=$ac_ct_XRES + fi +else + XRES="$ac_cv_prog_XRES" +fi + + ;; +esac + + if test x$host_is_android = xyes; then + ANDROID_TRUE= + ANDROID_FALSE='#' +else + ANDROID_TRUE='#' + ANDROID_FALSE= +fi + + if test x$host_is_windows = xyes; then + HAVE_WINDOWS_TRUE= + HAVE_WINDOWS_FALSE='#' +else + HAVE_WINDOWS_TRUE='#' + HAVE_WINDOWS_FALSE= +fi + + +if test -z "$prefix" || test "x$prefix" = xNONE; then + local_lib= + local_include= + + # aren't autotools supposed to be smart enough to figure this out? oh + # well, the git-core Makefile managed to do some of the work for us :) + case "$host_os" in + darwin*) local_lib='/sw/lib /opt/local/lib' local_include='/sw/include /opt/local/include' ;; @@ -5955,316 +6125,1280 @@ - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if g++ supports C++0x features without additional flags" >&5 -$as_echo_n "checking if g++ supports C++0x features without additional flags... " >&6; } -if ${ax_cv_cxx_compile_cxx0x_native+:} false; then : - $as_echo_n "(cached) " >&6 -else - + ax_cxx_compile_cxx14_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - + ac_success=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++14 features by default... " >&6; } +if ${ax_cv_cxx_compile_cxx14+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - int a; - decltype(a) b; +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); -int -main () -{ +#ifndef __cplusplus - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx0x_native=yes -else - ax_cv_cxx_compile_cxx0x_native=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu +#error "This is not a C++ compiler" +#elif __cplusplus < 201103L -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx0x_native" >&5 -$as_echo "$ax_cv_cxx_compile_cxx0x_native" >&6; } +#error "This is not a C++11 compiler" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if g++ supports C++0x features with -std=c++0x" >&5 -$as_echo_n "checking if g++ supports C++0x features with -std=c++0x... " >&6; } -if ${ax_cv_cxx_compile_cxx0x_cxx+:} false; then : - $as_echo_n "(cached) " >&6 -else +#else - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +namespace cxx11 +{ - ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -std=c++0x" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + namespace test_static_assert + { - template + template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; - typedef check> right_angle_brackets; + } - int a; - decltype(a) b; + namespace test_final_override + { - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); -int -main () -{ + struct Base + { + virtual void f() {} + }; - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx0x_cxx=yes -else - ax_cv_cxx_compile_cxx0x_cxx=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS="$ac_save_CXXFLAGS" - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu + struct Derived : public Base + { + virtual void f() override {} + }; + } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx0x_cxx" >&5 -$as_echo "$ax_cv_cxx_compile_cxx0x_cxx" >&6; } + namespace test_double_right_angle_brackets + { - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if g++ supports C++0x features with -std=gnu++0x" >&5 -$as_echo_n "checking if g++ supports C++0x features with -std=gnu++0x... " >&6; } -if ${ax_cv_cxx_compile_cxx0x_gxx+:} false; then : - $as_echo_n "(cached) " >&6 -else + template < typename T > + struct check {}; - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; - ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -std=gnu++0x" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + } - template - struct check + namespace test_decltype + { + + int + f() { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; }; - typedef check> right_angle_brackets; + template < typename T > + struct is_same + { + static const bool value = true; + }; - int a; - decltype(a) b; + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); -int -main () -{ + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx0x_gxx=yes -else - ax_cv_cxx_compile_cxx0x_gxx=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS="$ac_save_CXXFLAGS" - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu + } + namespace test_noexcept + { -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx0x_gxx" >&5 -$as_echo "$ax_cv_cxx_compile_cxx0x_gxx" >&6; } + int f() { return 0; } + int g() noexcept { return 0; } - if test "$ax_cv_cxx_compile_cxx0x_native" = yes || - test "$ax_cv_cxx_compile_cxx0x_cxx" = yes || - test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); -$as_echo "#define HAVE_STDCXX_0X /**/" >>confdefs.h + } - fi + namespace test_constexpr + { -if test "$ax_cv_cxx_compile_cxx0x_native" != yes; then - if test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then - AM_CXXFLAGS="$AM_CXXFLAGS -std=gnu++0x" - elif test "$ax_cv_cxx_compile_cxx0x_cxx" = yes; then - AM_CXXFLAGS="$AM_CXXFLAGS -std=c++0x" - fi -fi + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 -$as_echo_n "checking for library containing clock_gettime... " >&6; } -if ${ac_cv_search_clock_gettime+:} false; then : + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + + + + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201300L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + +#ifdef DISALLOW_GCC48 + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } +#endif + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_cxx_compile_cxx14=yes +else + ax_cv_cxx_compile_cxx14=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx14" >&5 +$as_echo "$ax_cv_cxx_compile_cxx14" >&6; } + if test x$ax_cv_cxx_compile_cxx14 = xyes; then + ac_success=yes + fi + + + + if test x$ac_success = xno; then + for switch in -std=c++14 -std=c++0x +std=c++14 "-h std=c++14"; do + cachevar=`$as_echo "ax_cv_cxx_compile_cxx14_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++14 features with $switch... " >&6; } +if eval \${$cachevar+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_CXX="$CXX" + CXX="$CXX $switch" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + + + + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201300L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + +#ifdef DISALLOW_GCC48 + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } +#endif + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXX="$ac_save_CXX" +fi +eval ac_res=\$$cachevar + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test x$ax_cxx_compile_cxx14_required = xtrue; then + if test x$ac_success = xno; then + as_fn_error $? "*** A compiler with support for C++14 language features is required." "$LINENO" 5 + fi + fi + if test x$ac_success = xno; then + HAVE_CXX14=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++14 support was found" >&5 +$as_echo "$as_me: No compiler with C++14 support was found" >&6;} + else + HAVE_CXX14=1 + +$as_echo "#define HAVE_CXX14 1" >>confdefs.h + + fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" +#ifdef __STDC__ +# include +#else +# include #endif -char clock_gettime (); -int -main () -{ -return clock_gettime (); - ; - return 0; -} + Syntax error _ACEOF -for ac_lib in '' rt; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_clock_gettime=$ac_res +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_clock_gettime+:} false; then : - break +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break fi +rm -f conftest.err conftest.i conftest.$ac_ext + done -if ${ac_cv_search_clock_gettime+:} false; then : +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : else - ac_cv_search_clock_gettime=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 -$as_echo "$ac_cv_search_clock_gettime" >&6; } -ac_res=$ac_cv_search_clock_gettime -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing syslog" >&5 -$as_echo_n "checking for library containing syslog... " >&6; } -if ${ac_cv_search_syslog+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char syslog (); -int -main () -{ -return syslog (); - ; - return 0; -} -_ACEOF -for ac_lib in '' bsd socket inet; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_syslog=$ac_res +else + ac_cv_path_GREP=$GREP fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_syslog+:} false; then : - break + fi -done -if ${ac_cv_search_syslog+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_search_syslog=no + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS + + fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_syslog" >&5 -$as_echo "$ac_cv_search_syslog" >&6; } -ac_res=$ac_cv_search_syslog -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" -$as_echo "#define HAVE_SYSLOG 1" >>confdefs.h -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 -$as_echo_n "checking for library containing socket... " >&6; } -if ${ac_cv_search_socket+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -6273,381 +7407,601 @@ #ifdef __cplusplus extern "C" #endif -char socket (); +char pthread_join (); int main () { -return socket (); +return pthread_join (); ; return 0; } _ACEOF -for ac_lib in '' socket; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_socket=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_socket+:} false; then : - break + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi -done -if ${ac_cv_search_socket+:} false; then : -else - ac_cv_search_socket=no +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 -$as_echo "$ac_cv_search_socket" >&6; } -ac_res=$ac_cv_search_socket -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 -$as_echo_n "checking for library containing gethostbyname... " >&6; } -if ${ac_cv_search_gethostbyname+:} false; then : +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gethostbyname (); -int -main () -{ -return gethostbyname (); - ; - return 0; -} _ACEOF -for ac_lib in '' nsl; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_gethostbyname=$ac_res +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_gethostbyname+:} false; then : +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : break fi -done -if ${ac_cv_search_gethostbyname+:} false; then : + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext -else - ac_cv_search_gethostbyname=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 -$as_echo "$ac_cv_search_gethostbyname" >&6; } -ac_res=$ac_cv_search_gethostbyname -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac -if test x$host_is_linux = xyes; then - for ac_func in pipe2 accept4 -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF +fi # $ax_pthread_clang = yes -fi +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ax_pthread_config" = "xno"; then : + continue fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; -for ac_func in getpwnam_r getpwuid_r -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac -fi -done + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" -for ac_func in initgroups -do : - ac_fn_c_check_func "$LINENO" "initgroups" "ac_cv_func_initgroups" -if test "x$ac_cv_func_initgroups" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_INITGROUPS 1 -_ACEOF + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes fi -done +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext -for ac_func in strndup -do : - ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" -if test "x$ac_cv_func_strndup" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_STRNDUP 1 -_ACEOF + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break fi -done + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi -if test x$host_is_linux = xyes; then - - # Check whether --enable-eventfd was given. -if test "${enable_eventfd+set}" = set; then : - enableval=$enable_eventfd; test xenable_eventfd = xyes && -$as_echo "#define USE_EVENTFD 1" >>confdefs.h +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_fn_c_check_func "$LINENO" "eventfd" "ac_cv_func_eventfd" -if test "x$ac_cv_func_eventfd" = xyes; then : - -$as_echo "#define USE_EVENTFD 1" >>confdefs.h - + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + ax_pthread_joinable_attr_defined=yes - # Check whether --enable-signalfd was given. -if test "${enable_signalfd+set}" = set; then : - enableval=$enable_signalfd; test xenable_signalfd = xyes && -$as_echo "#define USE_SIGNALFD 1" >>confdefs.h +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_fn_c_check_func "$LINENO" "signalfd" "ac_cv_func_signalfd" -if test "x$ac_cv_func_signalfd" = xyes; then : - -$as_echo "#define USE_SIGNALFD 1" >>confdefs.h + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac fi - -fi - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exp" >&5 -$as_echo_n "checking for library containing exp... " >&6; } -if ${ac_cv_search_exp+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exp (); +#include int main () { -return exp (); +int i = PTHREAD_PRIO_INHERIT; ; return 0; } _ACEOF -for ac_lib in '' m; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_exp=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_exp+:} false; then : - break -fi -done -if ${ac_cv_search_exp+:} false; then : + conftest$ac_exeext conftest.$ac_ext -else - ac_cv_search_exp=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exp" >&5 -$as_echo "$ac_cv_search_exp" >&6; } -ac_res=$ac_cv_search_exp -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : -else - as_fn_error $? "exp() not found" "$LINENO" 5 -fi +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + ax_pthread_prio_inherit_defined=yes -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } else - # Passes both tests. -ac_preproc_ok=: -break + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f conftest.err conftest.i conftest.$ac_ext + + test -n "$PTHREAD_CC" && break done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi fi - done - ac_cv_prog_CPP=$CPP +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + : else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi + ax_pthread_ok=no +fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -6655,338 +8009,408 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : +LIBS="$PTHREAD_LIBS $LIBS" +AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS" +AM_CXXFLAGS="$AM_CXXFLAGS $PTHREAD_CFLAGS" + + + ac_save_CFLAGS="$CFLAGS" + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" + LIBS="$LIBS $PTHREAD_LIBS" + for ac_func in pthread_setname_np +do : + ac_fn_c_check_func "$LINENO" "pthread_setname_np" "ac_cv_func_pthread_setname_np" +if test "x$ac_cv_func_pthread_setname_np" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_SETNAME_NP 1 +_ACEOF + +fi +done + + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi -else - ac_cv_path_GREP=$GREP + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res fi - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - +done +if ${ac_cv_search_clock_gettime+:} false; then : -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP fi - fi + +# Check whether --enable-syslog was given. +if test "${enable_syslog+set}" = set; then : + enableval=$enable_syslog; +else + enable_syslog=auto fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : + if test x$enable_syslog != xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing syslog" >&5 +$as_echo_n "checking for library containing syslog... " >&6; } +if ${ac_cv_search_syslog+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char syslog (); int main () { - +return syslog (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes +for ac_lib in '' bsd socket inet; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_syslog=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_syslog+:} false; then : + break +fi +done +if ${ac_cv_search_syslog+:} false; then : + else - ac_cv_header_stdc=no + ac_cv_search_syslog=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_syslog" >&5 +$as_echo "$ac_cv_search_syslog" >&6; } +ac_res=$ac_cv_search_syslog +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + found_syslog=yes +else + found_syslog=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include + fi -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : + if test x$enable_syslog = xno; then + found_syslog=no + fi -else - ac_cv_header_stdc=no -fi -rm -f conftest* + if test x$found_syslog = xyes; then + + if test x$enable_syslog = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected syslog support" >&5 +$as_echo "$as_me: auto-detected syslog support" >&6;} + enable_syslog=yes + fi + + else + + if test x$enable_syslog = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: syslog() not available -- disabling syslog support" >&5 +$as_echo "$as_me: WARNING: syslog() not available -- disabling syslog support" >&2;} + enable_syslog=no + elif test x$enable_syslog = xyes; then + as_fn_error $? "syslog support: syslog() not available" "$LINENO" 5 + fi + + fi + + +if test x$enable_syslog = xyes; then + +$as_echo "#define HAVE_SYSLOG 1" >>confdefs.h fi -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} _ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : +for ac_lib in '' network socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : else - ac_cv_header_stdc=no + ac_cv_search_socket=no fi -rm -f conftest* +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); int main () { - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; +return gethostbyname (); + ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO"; then : +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : else - ac_cv_header_stdc=no + ac_cv_search_gethostbyname=no fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + fi + +if test x$host_is_linux = xyes; then + for ac_func in pipe2 accept4 linkat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + fi +done + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h +for ac_func in getpwnam_r getpwuid_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h +for ac_func in initgroups do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + ac_fn_c_check_func "$LINENO" "initgroups" "ac_cv_func_initgroups" +if test "x$ac_cv_func_initgroups" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define HAVE_INITGROUPS 1 _ACEOF fi - done - -for ac_header in locale.h +for ac_func in fnmatch do : - ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" -if test "x$ac_cv_header_locale_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch" +if test "x$ac_cv_func_fnmatch" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_LOCALE_H 1 +#define HAVE_FNMATCH 1 _ACEOF fi - done -for ac_header in valgrind/memcheck.h +for ac_func in strndup do : - ac_fn_c_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" -if test "x$ac_cv_header_valgrind_memcheck_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" +if test "x$ac_cv_func_strndup" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_VALGRIND_MEMCHECK_H 1 +#define HAVE_STRNDUP 1 _ACEOF fi - done -for ac_header in sys/prctl.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_prctl_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_PRCTL_H 1 -_ACEOF - for ac_func in prctl -do : - ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" -if test "x$ac_cv_func_prctl" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_PRCTL 1 -_ACEOF +if test x$host_is_linux = xyes; then + + # Check whether --enable-eventfd was given. +if test "${enable_eventfd+set}" = set; then : + enableval=$enable_eventfd; test x$enable_eventfd = xyes && +$as_echo "#define USE_EVENTFD 1" >>confdefs.h + +else + ac_fn_c_check_func "$LINENO" "eventfd" "ac_cv_func_eventfd" +if test "x$ac_cv_func_eventfd" = xyes; then : + +$as_echo "#define USE_EVENTFD 1" >>confdefs.h fi -done fi -done + # Check whether --enable-signalfd was given. +if test "${enable_signalfd+set}" = set; then : + enableval=$enable_signalfd; test x$enable_signalfd = xyes && +$as_echo "#define USE_SIGNALFD 1" >>confdefs.h +else + ac_fn_c_check_func "$LINENO" "signalfd" "ac_cv_func_signalfd" +if test "x$ac_cv_func_signalfd" = xyes; then : -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu +$as_echo "#define USE_SIGNALFD 1" >>confdefs.h -ax_pthread_ok=no +fi -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. +fi -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 -$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exp" >&5 +$as_echo_n "checking for library containing exp... " >&6; } +if ${ac_cv_search_exp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -6995,466 +8419,226 @@ #ifdef __cplusplus extern "C" #endif -char pthread_join (); +char exp (); int main () { -return pthread_join (); +return exp (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ax_pthread_ok=yes +for ac_lib in '' m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_exp=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 -$as_echo "$ax_pthread_ok" >&6; } - if test x"$ax_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case ${host_os} in - solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; - - darwin*) - ax_pthread_flags="-pthread $ax_pthread_flags" - ;; -esac - -# Clang doesn't consider unrecognized options an error unless we specify -# -Werror. We throw in some extra Clang-specific options to ensure that -# this doesn't happen for GCC, which also accepts -Werror. - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler needs -Werror to reject unknown flags" >&5 -$as_echo_n "checking if compiler needs -Werror to reject unknown flags... " >&6; } -save_CFLAGS="$CFLAGS" -ax_pthread_extra_flags="-Werror" -CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int foo(void); -int -main () -{ -foo() - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - ax_pthread_extra_flags= - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + conftest$ac_exeext + if ${ac_cv_search_exp+:} false; then : + break fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -CFLAGS="$save_CFLAGS" - -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do - - case $flag in - none) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 -$as_echo_n "checking whether pthreads work without any flags... " >&6; } - ;; - - -*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 -$as_echo_n "checking whether pthreads work with $flag... " >&6; } - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - # Extract the first word of "pthread-config", so it can be a program name with args. -set dummy pthread-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ax_pthread_config+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ax_pthread_config"; then - ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ax_pthread_config="yes" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi done - done -IFS=$as_save_IFS +if ${ac_cv_search_exp+:} false; then : - test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" -fi -fi -ax_pthread_config=$ac_cv_prog_ax_pthread_config -if test -n "$ax_pthread_config"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 -$as_echo "$ax_pthread_config" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_search_exp=no fi - - - if test x"$ax_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 -$as_echo_n "checking for the pthreads library -l$flag... " >&6; } - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - static void routine(void *a) { a = 0; } - static void *start_routine(void *a) { return a; } -int -main () -{ -pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */ - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ax_pthread_ok=yes +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 -$as_echo "$ax_pthread_ok" >&6; } - if test "x$ax_pthread_ok" = xyes; then - break; - fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exp" >&5 +$as_echo "$ac_cv_search_exp" >&6; } +ac_res=$ac_cv_search_exp +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done +else + as_fn_error $? "exp() not found" "$LINENO" 5 fi -# Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 -$as_echo_n "checking for joinable pthread attribute... " >&6; } - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include +#include +#include +#include + int main () { -int attr = $attr; return attr /* ; */ + ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - attr_name=$attr; break +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 -$as_echo "$attr_name" >&6; } - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include -cat >>confdefs.h <<_ACEOF -#define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : - fi +else + ac_cv_header_stdc=no +fi +rm -f conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 -$as_echo_n "checking if more special flags are required for pthreads... " >&6; } - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - # TODO: What about Clang on Solaris? - flag="-mt -D_REENTRANT" - fi - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag" >&5 -$as_echo "$flag" >&6; } - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 -$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } -if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : - $as_echo_n "(cached) " >&6 else + ac_cv_header_stdc=no +fi +rm -f conftest* - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { -int i = PTHREAD_PRIO_INHERIT; - ; + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ax_cv_PTHREAD_PRIO_INHERIT=yes -else - ax_cv_PTHREAD_PRIO_INHERIT=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +if ac_fn_c_try_run "$LINENO"; then : +else + ac_cv_header_stdc=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 -$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } - if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then : - -$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h - +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then - case $host_os in - aix*) - case "x/$CC" in #( - x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : - #handle absolute path differently from PATH based program lookup - case "x$CC" in #( - x/*) : - if as_fn_executable_p ${CC}_r; then : - PTHREAD_CC="${CC}_r" -fi ;; #( - *) : - for ac_prog in ${CC}_r -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_PTHREAD_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$PTHREAD_CC"; then - ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_PTHREAD_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi fi -PTHREAD_CC=$ac_cv_prog_PTHREAD_CC -if test -n "$PTHREAD_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 -$as_echo "$PTHREAD_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then +$as_echo "#define STDC_HEADERS 1" >>confdefs.h - test -n "$PTHREAD_CC" && break -done -test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" - ;; -esac ;; #( - *) : - ;; -esac - ;; - esac - fi fi -test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF +fi +done +for ac_header in locale.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then +fi -$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h +done - : -else - ax_pthread_ok=no +for ac_header in valgrind/memcheck.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" +if test "x$ac_cv_header_valgrind_memcheck_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VALGRIND_MEMCHECK_H 1 +_ACEOF fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu +done -LIBS="$PTHREAD_LIBS $LIBS" -AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS" -AM_CXXFLAGS="$AM_CXXFLAGS $PTHREAD_CFLAGS" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np in -lpthread" >&5 -$as_echo_n "checking for pthread_setname_np in -lpthread... " >&6; } -if ${ac_cv_lib_pthread_pthread_setname_np+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_setname_np (); -int -main () -{ -return pthread_setname_np (); - ; - return 0; -} +for ac_header in sys/prctl.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_prctl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PRCTL_H 1 _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread_pthread_setname_np=yes -else - ac_cv_lib_pthread_pthread_setname_np=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_setname_np" >&5 -$as_echo "$ac_cv_lib_pthread_pthread_setname_np" >&6; } -if test "x$ac_cv_lib_pthread_pthread_setname_np" = xyes; then : - have_pthread_setname_np=yes -else - have_pthread_setname_np=no + for ac_func in prctl +do : + ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" +if test "x$ac_cv_func_prctl" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PRCTL 1 +_ACEOF + fi +done -if test x$have_pthread_setname_np = xyes; then +fi -$as_echo "#define HAVE_PTHREAD_SETNAME_NP 1" >>confdefs.h +done -fi @@ -7535,7 +8719,7 @@ enable_database=yes fi - if test x$enable_database = xyes; then + if test x$enable_database = xyes; then ENABLE_DATABASE_TRUE= ENABLE_DATABASE_FALSE='#' else @@ -7543,163 +8727,42 @@ ENABLE_DATABASE_FALSE= fi -if test x$enable_database = xyes; then - database_auto=auto + if test x$enable_database = xyes; then $as_echo "#define ENABLE_DATABASE 1" >>confdefs.h -else - database_auto=no -fi - -# Check whether --enable-libmpdclient was given. -if test "${enable_libmpdclient+set}" = set; then : - enableval=$enable_libmpdclient; -else - enable_libmpdclient=auto -fi - - - if test x$enable_database = xno; then - if test x$enable_libmpdclient = xauto; then - enable_libmpdclient=no - elif test x$enable_libmpdclient = xyes; then - as_fn_error $? "Cannot use --enable-libmpdclient with --disable-database" "$LINENO" 5 - fi - fi - - -# Check whether --enable-expat was given. -if test "${enable_expat+set}" = set; then : - enableval=$enable_expat; -else - enable_expat=auto -fi - - -# Check whether --enable-upnp was given. -if test "${enable_upnp+set}" = set; then : - enableval=$enable_upnp; -else - enable_upnp=auto -fi - - - if test x$enable_database = xno; then - if test x$enable_upnp = xauto; then - enable_upnp=no - elif test x$enable_upnp = xyes; then - as_fn_error $? "Cannot use --enable-upnp with --disable-database" "$LINENO" 5 - fi fi - - -# Check whether --enable-adplug was given. -if test "${enable_adplug+set}" = set; then : - enableval=$enable_adplug; -else - enable_adplug=auto -fi - - -# Check whether --enable-alsa was given. -if test "${enable_alsa+set}" = set; then : - enableval=$enable_alsa; -else - enable_alsa=$linux_auto -fi - - -# Check whether --enable-roar was given. -if test "${enable_roar+set}" = set; then : - enableval=$enable_roar; -else - enable_roar=auto -fi - - -# Check whether --enable-ao was given. -if test "${enable_ao+set}" = set; then : - enableval=$enable_ao; +if test x$enable_database = xyes; then + database_auto=auto else - enable_ao=auto + database_auto=no fi - - if test x$enable_glib = xno; then - if test x$enable_ao = xauto; then - enable_ao=no - elif test x$enable_ao = xyes; then - as_fn_error $? "Cannot use --enable-ao with --disable-glib" "$LINENO" 5 - fi - fi - - -# Check whether --enable-audiofile was given. -if test "${enable_audiofile+set}" = set; then : - enableval=$enable_audiofile; -else - enable_audiofile=auto +default_enable_daemon=yes +if test x$host_is_android = xyes || test x$host_is_android = xyes; then + default_enable_daemon=no fi - - -# Check whether --enable-zlib was given. -if test "${enable_zlib+set}" = set; then : - enableval=$enable_zlib; +# Check whether --enable-daemon was given. +if test "${enable_daemon+set}" = set; then : + enableval=$enable_daemon; else - enable_zlib=auto + enable_daemon=$default_enable_daemon fi - -# Check whether --enable-bzip2 was given. -if test "${enable_bzip2+set}" = set; then : - enableval=$enable_bzip2; + if test x$enable_daemon = xyes; then + ENABLE_DAEMON_TRUE= + ENABLE_DAEMON_FALSE='#' else - enable_bzip2=auto + ENABLE_DAEMON_TRUE='#' + ENABLE_DAEMON_FALSE= fi + if test x$enable_daemon = xyes; then -# Check whether --enable-cdio-paranoia was given. -if test "${enable_cdio_paranoia+set}" = set; then : - enableval=$enable_cdio_paranoia; -else - enable_cdio_paranoia=auto -fi - +$as_echo "#define ENABLE_DAEMON 1" >>confdefs.h - if test x$enable_glib = xno; then - if test x$enable_cdio_paranoia = xauto; then - enable_cdio_paranoia=no - elif test x$enable_cdio_paranoia = xyes; then - as_fn_error $? "Cannot use --enable-cdio-paranoia with --disable-glib" "$LINENO" 5 - fi fi - -# Check whether --enable-curl was given. -if test "${enable_curl+set}" = set; then : - enableval=$enable_curl; -else - enable_curl=auto -fi - - -# Check whether --enable-smbclient was given. -if test "${enable_smbclient+set}" = set; then : - enableval=$enable_smbclient; -else - enable_smbclient=auto -fi - - -# Check whether --enable-nfs was given. -if test "${enable_nfs+set}" = set; then : - enableval=$enable_nfs; -else - enable_nfs=auto -fi - - # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; @@ -7724,14 +8787,6 @@ fi -# Check whether --enable-ffmpeg was given. -if test "${enable_ffmpeg+set}" = set; then : - enableval=$enable_ffmpeg; -else - enable_ffmpeg=auto -fi - - # Check whether --enable-fifo was given. if test "${enable_fifo+set}" = set; then : enableval=$enable_fifo; @@ -7740,39 +8795,6 @@ fi -# Check whether --enable-flac was given. -if test "${enable_flac+set}" = set; then : - enableval=$enable_flac; -else - enable_flac=auto -fi - - -# Check whether --enable-fluidsynth was given. -if test "${enable_fluidsynth+set}" = set; then : - enableval=$enable_fluidsynth; -else - enable_fluidsynth=auto -fi - - -# Check whether --enable-gme was given. -if test "${enable_gme+set}" = set; then : - enableval=$enable_gme; -else - enable_gme=auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_gme = xauto; then - enable_gme=no - elif test x$enable_gme = xyes; then - as_fn_error $? "Cannot use --enable-gme with --disable-glib" "$LINENO" 5 - fi - fi - - # Check whether --enable-httpd-output was given. if test "${enable_httpd_output+set}" = set; then : enableval=$enable_httpd_output; @@ -7781,23 +8803,6 @@ fi - if test x$enable_glib = xno; then - if test x$enable_httpd_output = xauto; then - enable_httpd_output=no - elif test x$enable_httpd_output = xyes; then - as_fn_error $? "Cannot use --enable-httpd-output with --disable-glib" "$LINENO" 5 - fi - fi - - -# Check whether --enable-id3 was given. -if test "${enable_id3+set}" = set; then : - enableval=$enable_id3; -else - enable_id3=auto -fi - - # Check whether --enable-inotify was given. if test "${enable_inotify+set}" = set; then : enableval=$enable_inotify; @@ -7814,31 +8819,6 @@ fi -# Check whether --enable-iso9660 was given. -if test "${enable_iso9660+set}" = set; then : - enableval=$enable_iso9660; -else - enable_iso9660=no -fi - - -# Check whether --enable-jack was given. -if test "${enable_jack+set}" = set; then : - enableval=$enable_jack; -else - enable_jack=auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_jack = xauto; then - enable_jack=no - elif test x$enable_jack = xyes; then - as_fn_error $? "Cannot use --enable-jack with --disable-glib" "$LINENO" 5 - fi - fi - - # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; @@ -8024,116 +9004,43 @@ done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 -$as_echo "$ac_cv_sys_large_files" >&6; } -case $ac_cv_sys_large_files in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _LARGE_FILES $ac_cv_sys_large_files -_ACEOF -;; -esac -rm -rf conftest* - fi - - -fi - - -# Check whether --enable-soundcloud was given. -if test "${enable_soundcloud+set}" = set; then : - enableval=$enable_soundcloud; -else - enable_soundcloud=auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_soundcloud = xauto; then - enable_soundcloud=no - elif test x$enable_soundcloud = xyes; then - as_fn_error $? "Cannot use --enable-soundcloud with --disable-glib" "$LINENO" 5 - fi - fi - - -# Check whether --enable-lame-encoder was given. -if test "${enable_lame_encoder+set}" = set; then : - enableval=$enable_lame_encoder; -else - enable_lame_encoder=auto -fi - - -# Check whether --enable-libwrap was given. -if test "${enable_libwrap+set}" = set; then : - enableval=$enable_libwrap; -else - enable_libwrap=auto -fi - - -# Check whether --enable-lsr was given. -if test "${enable_lsr+set}" = set; then : - enableval=$enable_lsr; -else - enable_lsr=auto -fi - - -# Check whether --enable-soxr was given. -if test "${enable_soxr+set}" = set; then : - enableval=$enable_soxr; -else - enable_soxr=auto -fi - - -# Check whether --enable-mad was given. -if test "${enable_mad+set}" = set; then : - enableval=$enable_mad; -else - enable_mad=auto -fi - - -# Check whether --enable-mikmod was given. -if test "${enable_mikmod+set}" = set; then : - enableval=$enable_mikmod; -else - enable_mikmod=no -fi +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi -# Check whether --enable-mms was given. -if test "${enable_mms+set}" = set; then : - enableval=$enable_mms; -else - enable_mms=auto fi -# Check whether --enable-modplug was given. -if test "${enable_modplug+set}" = set; then : - enableval=$enable_modplug; +# Check whether --enable-soundcloud was given. +if test "${enable_soundcloud+set}" = set; then : + enableval=$enable_soundcloud; else - enable_modplug=auto + enable_soundcloud=auto fi -# Check whether --enable-mpc was given. -if test "${enable_mpc+set}" = set; then : - enableval=$enable_mpc; +# Check whether --enable-libwrap was given. +if test "${enable_libwrap+set}" = set; then : + enableval=$enable_libwrap; else - enable_mpc=auto + enable_libwrap=auto fi -# Check whether --enable-mpg123 was given. -if test "${enable_mpg123+set}" = set; then : - enableval=$enable_mpg123; +# Check whether --enable-mikmod was given. +if test "${enable_mikmod+set}" = set; then : + enableval=$enable_mikmod; else - enable_mpg123=auto + enable_mikmod=no fi @@ -8145,14 +9052,6 @@ fi -# Check whether --enable-opus was given. -if test "${enable_opus+set}" = set; then : - enableval=$enable_opus; -else - enable_opus=auto -fi - - # Check whether --enable-oss was given. if test "${enable_oss+set}" = set; then : enableval=$enable_oss; @@ -8177,14 +9076,6 @@ fi -# Check whether --enable-pulse was given. -if test "${enable_pulse+set}" = set; then : - enableval=$enable_pulse; -else - enable_pulse=auto -fi - - # Check whether --enable-recorder-output was given. if test "${enable_recorder_output+set}" = set; then : enableval=$enable_recorder_output; @@ -8201,14 +9092,6 @@ fi -# Check whether --enable-shine-encoder was given. -if test "${enable_shine_encoder+set}" = set; then : - enableval=$enable_shine_encoder; -else - enable_shine_encoder=auto -fi - - # Check whether --enable-shout was given. if test "${enable_shout+set}" = set; then : enableval=$enable_shout; @@ -8217,14 +9100,6 @@ fi -# Check whether --enable-sndfile was given. -if test "${enable_sndfile+set}" = set; then : - enableval=$enable_sndfile; -else - enable_sndfile=auto -fi - - # Check whether --enable-solaris_output was given. if test "${enable_solaris_output+set}" = set; then : enableval=$enable_solaris_output; @@ -8233,31 +9108,6 @@ fi -# Check whether --enable-sqlite was given. -if test "${enable_sqlite+set}" = set; then : - enableval=$enable_sqlite; -else - enable_sqlite=$database_auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_sqlite = xauto; then - enable_sqlite=no - elif test x$enable_sqlite = xyes; then - as_fn_error $? "Cannot use --enable-sqlite with --disable-glib" "$LINENO" 5 - fi - fi - - -# Check whether --enable-systemd-daemon was given. -if test "${enable_systemd_daemon+set}" = set; then : - enableval=$enable_systemd_daemon; -else - enable_systemd_daemon=$linux_auto -fi - - # Check whether --enable-tcp was given. if test "${enable_tcp+set}" = set; then : enableval=$enable_tcp; @@ -8274,23 +9124,6 @@ fi - -# Check whether --with-tremor was given. -if test "${with_tremor+set}" = set; then : - withval=$with_tremor; -else - with_tremor=no -fi - - -# Check whether --enable-twolame-encoder was given. -if test "${enable_twolame_encoder+set}" = set; then : - enableval=$enable_twolame_encoder; -else - enable_twolame_encoder=auto -fi - - # Check whether --enable-un was given. if test "${enable_un+set}" = set; then : enableval=$enable_un; @@ -8307,23 +9140,6 @@ fi -# Check whether --enable-vorbis-encoder was given. -if test "${enable_vorbis_encoder+set}" = set; then : - enableval=$enable_vorbis_encoder; -else - enable_vorbis_encoder=auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_vorbis_encoder = xauto; then - enable_vorbis_encoder=no - elif test x$enable_vorbis_encoder = xyes; then - as_fn_error $? "Cannot use --enable-vorbis-encoder with --disable-glib" "$LINENO" 5 - fi - fi - - # Check whether --enable-wave-encoder was given. if test "${enable_wave_encoder+set}" = set; then : enableval=$enable_wave_encoder; @@ -8332,23 +9148,6 @@ fi -# Check whether --enable-wavpack was given. -if test "${enable_wavpack+set}" = set; then : - enableval=$enable_wavpack; -else - enable_wavpack=auto -fi - - - if test x$enable_glib = xno; then - if test x$enable_wavpack = xauto; then - enable_wavpack=no - elif test x$enable_wavpack = xyes; then - as_fn_error $? "Cannot use --enable-wavpack with --disable-glib" "$LINENO" 5 - fi - fi - - # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; @@ -8357,14 +9156,6 @@ fi -# Check whether --enable-wildmidi was given. -if test "${enable_wildmidi+set}" = set; then : - enableval=$enable_wildmidi; -else - enable_wildmidi=auto -fi - - # Check whether --with-zeroconf was given. if test "${with_zeroconf+set}" = set; then : @@ -8374,35 +9165,6 @@ fi -# Check whether --enable-zzip was given. -if test "${enable_zzip+set}" = set; then : - enableval=$enable_zzip; -else - enable_zzip=no -fi - - - - -# Check whether --with-tremor-libraries was given. -if test "${with_tremor_libraries+set}" = set; then : - withval=$with_tremor_libraries; -else - tremor_libraries="" -fi - - - -# Check whether --with-tremor-includes was given. -if test "${with_tremor_includes+set}" = set; then : - withval=$with_tremor_includes; -else - tremor_includes="" -fi - - - -no_exceptions=yes @@ -8459,7 +9221,10 @@ libsubdirs="lib" ax_arch=`uname -m` case $ax_arch in - x86_64|ppc64|s390x|sparc64|aarch64) + x86_64) + libsubdirs="lib64 libx32 lib lib64" + ;; + ppc64|s390x|sparc64|aarch64|ppc64le) libsubdirs="lib64 lib lib64" ;; esac @@ -8551,6 +9316,10 @@ if test "x$succeeded" != "xyes"; then + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + BOOST_CPPFLAGS= + BOOST_LDFLAGS= _version=0 if test "$ac_boost_path" != ""; then if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then @@ -8563,6 +9332,11 @@ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" done + if test -z "$BOOST_CPPFLAGS"; then + if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then + BOOST_CPPFLAGS="-I$ac_boost_path" + fi + fi fi else if test "$cross_compiling" != yes; then @@ -8681,55 +9455,17 @@ -CPPFLAGS_SAVED="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" -export CPPFLAGS -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include - -int -main () -{ - -#if BOOST_VERSION < 105400 -#error detected Boost older than 1.54 -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - no_exceptions=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CPPFLAGS="$CPPFLAGS_SAVED" - # Check whether --enable-icu was given. if test "${enable_icu+set}" = set; then : enableval=$enable_icu; else - enable_icu=yes + enable_icu=auto fi -if test x$enable_icu = xyes; then + + + if test x$enable_icu != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ICU" >&5 @@ -8787,126 +9523,87 @@ ICU_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "icu-i18n" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$ICU_PKG_ERRORS" >&5 - - as_fn_error $? "libicu not found" "$LINENO" 5 -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - as_fn_error $? "libicu not found" "$LINENO" 5 -else - ICU_CFLAGS=$pkg_cv_ICU_CFLAGS - ICU_LIBS=$pkg_cv_ICU_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -fi - - -$as_echo "#define HAVE_ICU 1" >>confdefs.h - -fi - if test x$enable_icu = xyes; then - HAVE_ICU_TRUE= - HAVE_ICU_FALSE='#' -else - HAVE_ICU_TRUE='#' - HAVE_ICU_FALSE= -fi - - -# Check whether --enable-glib was given. -if test "${enable_glib+set}" = set; then : - enableval=$enable_glib; -else - enable_glib=yes -fi - - -if test x$enable_glib = xyes; then - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 -$as_echo_n "checking for GLIB... " >&6; } - -if test -n "$GLIB_CFLAGS"; then - pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.28 gthread-2.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.28 gthread-2.0") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.28 gthread-2.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$GLIB_LIBS"; then - pkg_cv_GLIB_LIBS="$GLIB_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.28 gthread-2.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.28 gthread-2.0") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.28 gthread-2.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.28 gthread-2.0" 2>&1` - else - GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.28 gthread-2.0" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$GLIB_PKG_ERRORS" >&5 + echo "$ICU_PKG_ERRORS" >&5 - as_fn_error $? "GLib 2.28 is required" "$LINENO" 5 + found_icu=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "GLib 2.28 is required" "$LINENO" 5 + found_icu=no else - GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS - GLIB_LIBS=$pkg_cv_GLIB_LIBS + ICU_CFLAGS=$pkg_cv_ICU_CFLAGS + ICU_LIBS=$pkg_cv_ICU_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - + found_icu=yes fi + fi + + if test x$enable_icu = xno; then + found_icu=no + fi + + if test x$found_icu = xyes; then + + if test x$enable_icu = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libicu" >&5 +$as_echo "$as_me: auto-detected libicu" >&6;} + enable_icu=yes + fi + + else + + if test x$enable_icu = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libicu not found -- disabling libicu" >&5 +$as_echo "$as_me: WARNING: libicu not found -- disabling libicu" >&2;} + enable_icu=no + elif test x$enable_icu = xyes; then + as_fn_error $? "libicu: libicu not found" "$LINENO" 5 + fi + + fi -$as_echo "#define HAVE_GLIB 1" >>confdefs.h + + if test x$enable_icu = xyes; then + HAVE_ICU_TRUE= + HAVE_ICU_FALSE='#' +else + HAVE_ICU_TRUE='#' + HAVE_ICU_FALSE= fi - if test x$enable_glib = xyes; then - HAVE_GLIB_TRUE= - HAVE_GLIB_FALSE='#' + + if test x$enable_icu = xyes; then + +$as_echo "#define HAVE_ICU 1" >>confdefs.h + + fi + +# Check whether --enable-iconv was given. +if test "${enable_iconv+set}" = set; then : + enableval=$enable_iconv; else - HAVE_GLIB_TRUE='#' - HAVE_GLIB_FALSE= + enable_iconv=yes +fi + + +if test x$enable_icu = xyes; then + enable_iconv=no fi +if test x$enable_iconv = xyes; then + for ac_func in iconv +do : + ac_fn_c_check_func "$LINENO" "iconv" "ac_cv_func_iconv" +if test "x$ac_cv_func_iconv" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ICONV 1 +_ACEOF + +fi +done + +fi if test x$enable_tcp = xno; then @@ -9016,7 +9713,78 @@ fi - if eval "test x`echo '$'enable_systemd_daemon` != xno"; then + + # Check whether --enable-systemd-daemon was given. +if test "${enable_systemd_daemon+set}" = set; then : + enableval=$enable_systemd_daemon; +else + enable_systemd_daemon=$linux_auto +fi + + + + + if test x$enable_systemd_daemon != xno; then + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD_DAEMON" >&5 +$as_echo_n "checking for SYSTEMD_DAEMON... " >&6; } + +if test -n "$SYSTEMD_DAEMON_CFLAGS"; then + pkg_cv_SYSTEMD_DAEMON_CFLAGS="$SYSTEMD_DAEMON_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_DAEMON_CFLAGS=`$PKG_CONFIG --cflags "libsystemd" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SYSTEMD_DAEMON_LIBS"; then + pkg_cv_SYSTEMD_DAEMON_LIBS="$SYSTEMD_DAEMON_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_DAEMON_LIBS=`$PKG_CONFIG --libs "libsystemd" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SYSTEMD_DAEMON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1` + else + SYSTEMD_DAEMON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SYSTEMD_DAEMON_PKG_ERRORS" >&5 + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD_DAEMON" >&5 @@ -9076,60 +9844,130 @@ # Put the nasty error message in config.log where it belongs echo "$SYSTEMD_DAEMON_PKG_ERRORS" >&5 - eval "found_systemd_daemon=no" + found_systemd_daemon=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_systemd_daemon=no" + found_systemd_daemon=no else SYSTEMD_DAEMON_CFLAGS=$pkg_cv_SYSTEMD_DAEMON_CFLAGS SYSTEMD_DAEMON_LIBS=$pkg_cv_SYSTEMD_DAEMON_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_systemd_daemon=yes" + found_systemd_daemon=yes fi - fi +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD_DAEMON" >&5 +$as_echo_n "checking for SYSTEMD_DAEMON... " >&6; } + +if test -n "$SYSTEMD_DAEMON_CFLAGS"; then + pkg_cv_SYSTEMD_DAEMON_CFLAGS="$SYSTEMD_DAEMON_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_DAEMON_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-daemon" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SYSTEMD_DAEMON_LIBS"; then + pkg_cv_SYSTEMD_DAEMON_LIBS="$SYSTEMD_DAEMON_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_DAEMON_LIBS=`$PKG_CONFIG --libs "libsystemd-daemon" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SYSTEMD_DAEMON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-daemon" 2>&1` + else + SYSTEMD_DAEMON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-daemon" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SYSTEMD_DAEMON_PKG_ERRORS" >&5 - name="systemd_daemon" - var="enable_systemd_daemon" - found="found_$name" - feature="systemd activation" - msg="libsystemd-daemon not found" + found_systemd_daemon=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + found_systemd_daemon=no +else + SYSTEMD_DAEMON_CFLAGS=$pkg_cv_SYSTEMD_DAEMON_CFLAGS + SYSTEMD_DAEMON_LIBS=$pkg_cv_SYSTEMD_DAEMON_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_systemd_daemon=yes +fi +else + SYSTEMD_DAEMON_CFLAGS=$pkg_cv_SYSTEMD_DAEMON_CFLAGS + SYSTEMD_DAEMON_LIBS=$pkg_cv_SYSTEMD_DAEMON_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + found_systemd_daemon=yes +fi - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$enable_systemd_daemon = xno; then + found_systemd_daemon=no + fi - var="enable_$name" - feature="$feature" + if test x$found_systemd_daemon = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_systemd_daemon = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected systemd socket activation" >&5 +$as_echo "$as_me: auto-detected systemd socket activation" >&6;} + enable_systemd_daemon=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_systemd_daemon = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsystemd not found -- disabling systemd socket activation" >&5 +$as_echo "$as_me: WARNING: libsystemd not found -- disabling systemd socket activation" >&2;} + enable_systemd_daemon=no + elif test x$enable_systemd_daemon = xyes; then + as_fn_error $? "systemd socket activation: libsystemd not found" "$LINENO" 5 fi fi - if test x$enable_systemd_daemon = xyes; then + + + if test x$enable_systemd_daemon = xyes; then ENABLE_SYSTEMD_DAEMON_TRUE= ENABLE_SYSTEMD_DAEMON_FALSE='#' else @@ -9137,11 +9975,13 @@ ENABLE_SYSTEMD_DAEMON_FALSE= fi -if test x$enable_systemd_daemon = xyes; then + if test x$enable_systemd_daemon = xyes; then $as_echo "#define ENABLE_SYSTEMD_DAEMON 1" >>confdefs.h -fi + fi + + if test x$enable_largefile != xno; then @@ -9151,7 +9991,29 @@ - if eval "test x`echo '$'enable_libmpdclient` != xno"; then + + + # Check whether --enable-libmpdclient was given. +if test "${enable_libmpdclient+set}" = set; then : + enableval=$enable_libmpdclient; +else + enable_libmpdclient=auto +fi + + + + + if test x$enable_database = xno; then + if test x$enable_libmpdclient = xauto; then + enable_libmpdclient=no + elif test x$enable_libmpdclient = xyes; then + as_fn_error $? "Cannot use --enable-libmpdclient with --disable-database" "$LINENO" 5 + fi + fi + + + + if test x$enable_libmpdclient != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBMPDCLIENT" >&5 @@ -9211,76 +10073,80 @@ # Put the nasty error message in config.log where it belongs echo "$LIBMPDCLIENT_PKG_ERRORS" >&5 - eval "found_libmpdclient=no" + found_libmpdclient=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_libmpdclient=no" + found_libmpdclient=no else LIBMPDCLIENT_CFLAGS=$pkg_cv_LIBMPDCLIENT_CFLAGS LIBMPDCLIENT_LIBS=$pkg_cv_LIBMPDCLIENT_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_libmpdclient=yes" + found_libmpdclient=yes fi fi + if test x$enable_libmpdclient = xno; then + found_libmpdclient=no + fi - name="libmpdclient" - var="enable_libmpdclient" - found="found_$name" - feature="MPD client library" - msg="libmpdclient not found" + if test x$found_libmpdclient = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_libmpdclient = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected MPD client library" >&5 +$as_echo "$as_me: auto-detected MPD client library" >&6;} + enable_libmpdclient=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_libmpdclient = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmpdclient not found -- disabling MPD client library" >&5 +$as_echo "$as_me: WARNING: libmpdclient not found -- disabling MPD client library" >&2;} + enable_libmpdclient=no + elif test x$enable_libmpdclient = xyes; then + as_fn_error $? "MPD client library: libmpdclient not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_libmpdclient = xyes; then + ENABLE_LIBMPDCLIENT_TRUE= + ENABLE_LIBMPDCLIENT_FALSE='#' +else + ENABLE_LIBMPDCLIENT_TRUE='#' + ENABLE_LIBMPDCLIENT_FALSE= +fi + + if test x$enable_libmpdclient = xyes; then + +$as_echo "#define ENABLE_LIBMPDCLIENT 1" >>confdefs.h fi -if test x$enable_libmpdclient = xyes; then -$as_echo "#define HAVE_LIBMPDCLIENT 1" >>confdefs.h -fi - if test x$enable_libmpdclient = xyes; then - HAVE_LIBMPDCLIENT_TRUE= - HAVE_LIBMPDCLIENT_FALSE='#' + + # Check whether --enable-expat was given. +if test "${enable_expat+set}" = set; then : + enableval=$enable_expat; else - HAVE_LIBMPDCLIENT_TRUE='#' - HAVE_LIBMPDCLIENT_FALSE= + enable_expat=auto fi - if eval "test x`echo '$'enable_expat` != xno"; then + + + + if test x$enable_expat != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXPAT" >&5 @@ -9340,73 +10206,63 @@ # Put the nasty error message in config.log where it belongs echo "$EXPAT_PKG_ERRORS" >&5 - eval "found_expat=no" + found_expat=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_expat=no" + found_expat=no else EXPAT_CFLAGS=$pkg_cv_EXPAT_CFLAGS EXPAT_LIBS=$pkg_cv_EXPAT_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_expat=yes" + found_expat=yes fi fi - - name="expat" - var="enable_expat" - found="found_$name" - feature="expat XML parser" - msg="expat not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_expat = xno; then + found_expat=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_expat = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_expat = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected expat XML parser" >&5 +$as_echo "$as_me: auto-detected expat XML parser" >&6;} + enable_expat=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_expat = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: expat not found -- disabling expat XML parser" >&5 +$as_echo "$as_me: WARNING: expat not found -- disabling expat XML parser" >&2;} + enable_expat=no + elif test x$enable_expat = xyes; then + as_fn_error $? "expat XML parser: expat not found" "$LINENO" 5 fi fi -if test x$enable_expat = xyes; then -$as_echo "#define HAVE_EXPAT 1" >>confdefs.h -fi - if test x$enable_expat = xyes; then - HAVE_EXPAT_TRUE= - HAVE_EXPAT_FALSE='#' + if test x$enable_expat = xyes; then + ENABLE_EXPAT_TRUE= + ENABLE_EXPAT_FALSE='#' else - HAVE_EXPAT_TRUE='#' - HAVE_EXPAT_FALSE= + ENABLE_EXPAT_TRUE='#' + ENABLE_EXPAT_FALSE= fi + if test x$enable_expat = xyes; then + +$as_echo "#define ENABLE_EXPAT 1" >>confdefs.h + + fi + + for ac_func in inotify_init inotify_init1 do : @@ -9425,12 +10281,7 @@ enable_inotify=no fi -if test x$enable_inotify = xyes; then - -$as_echo "#define ENABLE_INOTIFY 1" >>confdefs.h - -fi - if test x$enable_inotify = xyes; then + if test x$enable_inotify = xyes; then ENABLE_INOTIFY_TRUE= ENABLE_INOTIFY_FALSE='#' else @@ -9438,6 +10289,11 @@ ENABLE_INOTIFY_FALSE= fi + if test x$enable_inotify = xyes; then + +$as_echo "#define ENABLE_INOTIFY 1" >>confdefs.h + + fi if test x$enable_libwrap != xno; then @@ -9540,56 +10396,56 @@ fi - name="libwrap" - var="enable_libwrap" - found="found_$name" - feature="libwrap" - msg="libwrap not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_libwrap = xno; then + found_libwrap=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_libwrap = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_libwrap = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libwrap" >&5 +$as_echo "$as_me: auto-detected libwrap" >&6;} + enable_libwrap=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_libwrap = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libwrap not found -- disabling libwrap" >&5 +$as_echo "$as_me: WARNING: libwrap not found -- disabling libwrap" >&2;} + enable_libwrap=no + elif test x$enable_libwrap = xyes; then + as_fn_error $? "libwrap: libwrap not found" "$LINENO" 5 fi fi fi -if test x$enable_libwrap = xyes; then - +if test x$enable_libwrap = xyes; then + + + +$as_echo "#define HAVE_LIBWRAP 1" >>confdefs.h + +fi + -$as_echo "#define HAVE_LIBWRAP 1" >>confdefs.h + # Check whether --enable-id3 was given. +if test "${enable_id3+set}" = set; then : + enableval=$enable_id3; +else + enable_id3=auto fi - if eval "test x`echo '$'enable_id3` != xno"; then + + + + if test x$enable_id3 != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ID3TAG" >&5 @@ -9686,9 +10542,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_id3tag_id3_file_open" >&5 $as_echo "$ac_cv_lib_id3tag_id3_file_open" >&6; } if test "x$ac_cv_lib_id3tag_id3_file_open" = xyes; then : - eval "found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS=''" + found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS='' else - eval "found_id3=no" + found_id3=no fi elif test $pkg_failed = untried; then @@ -9731,9 +10587,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_id3tag_id3_file_open" >&5 $as_echo "$ac_cv_lib_id3tag_id3_file_open" >&6; } if test "x$ac_cv_lib_id3tag_id3_file_open" = xyes; then : - eval "found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS=''" + found_id3=yes ID3TAG_LIBS='-lid3tag -lz' ID3TAG_CFLAGS='' else - eval "found_id3=no" + found_id3=no fi else @@ -9741,63 +10597,53 @@ ID3TAG_LIBS=$pkg_cv_ID3TAG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_id3=yes" + found_id3=yes fi fi - - name="id3" - var="enable_id3" - found="found_$name" - feature="id3tag" - msg="libid3tag not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_id3 = xno; then + found_id3=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_id3 = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_id3 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected ID3 support using libid3tag" >&5 +$as_echo "$as_me: auto-detected ID3 support using libid3tag" >&6;} + enable_id3=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_id3 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libid3tag not found -- disabling ID3 support using libid3tag" >&5 +$as_echo "$as_me: WARNING: libid3tag not found -- disabling ID3 support using libid3tag" >&2;} + enable_id3=no + elif test x$enable_id3 = xyes; then + as_fn_error $? "ID3 support using libid3tag: libid3tag not found" "$LINENO" 5 fi fi -if test x$enable_id3 = xyes; then -$as_echo "#define HAVE_ID3TAG 1" >>confdefs.h -fi - if test x$enable_id3 = xyes; then - HAVE_ID3TAG_TRUE= - HAVE_ID3TAG_FALSE='#' + if test x$enable_id3 = xyes; then + ENABLE_ID3TAG_TRUE= + ENABLE_ID3TAG_FALSE='#' else - HAVE_ID3TAG_TRUE='#' - HAVE_ID3TAG_FALSE= + ENABLE_ID3TAG_TRUE='#' + ENABLE_ID3TAG_FALSE= fi + if test x$enable_id3 = xyes; then + +$as_echo "#define ENABLE_ID3TAG 1" >>confdefs.h + + fi + + @@ -9817,7 +10663,8 @@ esac - if eval "test x`echo '$'enable_avahi` != xno"; then + + if test x$enable_avahi != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVAHI" >&5 @@ -9877,67 +10724,51 @@ # Put the nasty error message in config.log where it belongs echo "$AVAHI_PKG_ERRORS" >&5 - eval "found_avahi=no" + found_avahi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_avahi=no" + found_avahi=no else AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS AVAHI_LIBS=$pkg_cv_AVAHI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_avahi=yes" + found_avahi=yes fi fi - - name="avahi" - var="enable_avahi" - found="found_$name" - feature="avahi client library" - msg="avahi-client not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_avahi = xno; then + found_avahi=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_avahi = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_avahi = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected avahi client library" >&5 +$as_echo "$as_me: auto-detected avahi client library" >&6;} + enable_avahi=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_avahi = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: avahi-client not found -- disabling avahi client library" >&5 +$as_echo "$as_me: WARNING: avahi-client not found -- disabling avahi client library" >&2;} + enable_avahi=no + elif test x$enable_avahi = xyes; then + as_fn_error $? "avahi client library: avahi-client not found" "$LINENO" 5 fi fi -if test x$enable_avahi = xyes; then - -$as_echo "#define HAVE_AVAHI 1" >>confdefs.h +if test x$enable_avahi = xyes; then with_zeroconf=avahi fi - if test x$enable_avahi = xyes; then + if test x$enable_avahi = xyes; then HAVE_AVAHI_TRUE= HAVE_AVAHI_FALSE='#' else @@ -9945,6 +10776,11 @@ HAVE_AVAHI_FALSE= fi + if test x$enable_avahi = xyes; then + +$as_echo "#define HAVE_AVAHI 1" >>confdefs.h + + fi enable_bounjour=no if test x$with_zeroconf != xno; then @@ -10041,7 +10877,20 @@ - if eval "test x`echo '$'enable_sqlite` != xno"; then + + # Check whether --enable-sqlite was given. +if test "${enable_sqlite+set}" = set; then : + enableval=$enable_sqlite; +else + enable_sqlite=$database_auto +fi + + + + + + + if test x$enable_sqlite != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLITE" >&5 @@ -10051,12 +10900,12 @@ pkg_cv_SQLITE_CFLAGS="$SQLITE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SQLITE_CFLAGS=`$PKG_CONFIG --cflags "sqlite3" 2>/dev/null` + pkg_cv_SQLITE_CFLAGS=`$PKG_CONFIG --cflags "sqlite3 >= 3.7.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10068,12 +10917,12 @@ pkg_cv_SQLITE_LIBS="$SQLITE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SQLITE_LIBS=`$PKG_CONFIG --libs "sqlite3" 2>/dev/null` + pkg_cv_SQLITE_LIBS=`$PKG_CONFIG --libs "sqlite3 >= 3.7.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10094,73 +10943,56 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - SQLITE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3" 2>&1` + SQLITE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3 >= 3.7.3" 2>&1` else - SQLITE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3" 2>&1` + SQLITE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3 >= 3.7.3" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SQLITE_PKG_ERRORS" >&5 - eval "found_sqlite=no" + found_sqlite=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_sqlite=no" + found_sqlite=no else SQLITE_CFLAGS=$pkg_cv_SQLITE_CFLAGS SQLITE_LIBS=$pkg_cv_SQLITE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_sqlite=yes" + found_sqlite=yes fi fi - - name="sqlite" - var="enable_sqlite" - found="found_$name" - feature="SQLite database support" - msg="sqlite not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_sqlite = xno; then + found_sqlite=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_sqlite = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_sqlite = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected SQLite database support" >&5 +$as_echo "$as_me: auto-detected SQLite database support" >&6;} + enable_sqlite=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_sqlite = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: sqlite not found -- disabling SQLite database support" >&5 +$as_echo "$as_me: WARNING: sqlite not found -- disabling SQLite database support" >&2;} + enable_sqlite=no + elif test x$enable_sqlite = xyes; then + as_fn_error $? "SQLite database support: sqlite not found" "$LINENO" 5 fi fi -if test x$enable_sqlite = xyes; then -$as_echo "#define ENABLE_SQLITE 1" >>confdefs.h -fi - if test x$enable_sqlite = xyes; then + if test x$enable_sqlite = xyes; then ENABLE_SQLITE_TRUE= ENABLE_SQLITE_FALSE='#' else @@ -10168,17 +11000,37 @@ ENABLE_SQLITE_FALSE= fi + if test x$enable_sqlite = xyes; then + +$as_echo "#define ENABLE_SQLITE 1" >>confdefs.h + + fi + + + + + + + # Check whether --enable-lsr was given. +if test "${enable_lsr+set}" = set; then : + enableval=$enable_lsr; +else + enable_lsr=auto +fi + + - if eval "test x`echo '$'enable_lsr` != xno"; then + + if test x$enable_lsr != xno; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SAMPLERATE" >&5 -$as_echo_n "checking for SAMPLERATE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSAMPLERATE" >&5 +$as_echo_n "checking for LIBSAMPLERATE... " >&6; } -if test -n "$SAMPLERATE_CFLAGS"; then - pkg_cv_SAMPLERATE_CFLAGS="$SAMPLERATE_CFLAGS" +if test -n "$LIBSAMPLERATE_CFLAGS"; then + pkg_cv_LIBSAMPLERATE_CFLAGS="$LIBSAMPLERATE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate >= 0.1.3\""; } >&5 @@ -10186,7 +11038,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SAMPLERATE_CFLAGS=`$PKG_CONFIG --cflags "samplerate >= 0.1.3" 2>/dev/null` + pkg_cv_LIBSAMPLERATE_CFLAGS=`$PKG_CONFIG --cflags "samplerate >= 0.1.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10194,8 +11046,8 @@ else pkg_failed=untried fi -if test -n "$SAMPLERATE_LIBS"; then - pkg_cv_SAMPLERATE_LIBS="$SAMPLERATE_LIBS" +if test -n "$LIBSAMPLERATE_LIBS"; then + pkg_cv_LIBSAMPLERATE_LIBS="$LIBSAMPLERATE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate >= 0.1.3\""; } >&5 @@ -10203,7 +11055,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SAMPLERATE_LIBS=`$PKG_CONFIG --libs "samplerate >= 0.1.3" 2>/dev/null` + pkg_cv_LIBSAMPLERATE_LIBS=`$PKG_CONFIG --libs "samplerate >= 0.1.3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10224,82 +11076,86 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "samplerate >= 0.1.3" 2>&1` + LIBSAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "samplerate >= 0.1.3" 2>&1` else - SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "samplerate >= 0.1.3" 2>&1` + LIBSAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "samplerate >= 0.1.3" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$SAMPLERATE_PKG_ERRORS" >&5 + echo "$LIBSAMPLERATE_PKG_ERRORS" >&5 - eval "found_lsr=no" + found_lsr=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_lsr=no" + found_lsr=no else - SAMPLERATE_CFLAGS=$pkg_cv_SAMPLERATE_CFLAGS - SAMPLERATE_LIBS=$pkg_cv_SAMPLERATE_LIBS + LIBSAMPLERATE_CFLAGS=$pkg_cv_LIBSAMPLERATE_CFLAGS + LIBSAMPLERATE_LIBS=$pkg_cv_LIBSAMPLERATE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_lsr=yes" + found_lsr=yes fi fi + if test x$enable_lsr = xno; then + found_lsr=no + fi - name="lsr" - var="enable_lsr" - found="found_$name" - feature="libsamplerate resampling" - msg="libsamplerate not found" + if test x$found_lsr = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_lsr = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libsamplerate resampling" >&5 +$as_echo "$as_me: auto-detected libsamplerate resampling" >&6;} + enable_lsr=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_lsr = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsamplerate not found -- disabling libsamplerate resampling" >&5 +$as_echo "$as_me: WARNING: libsamplerate not found -- disabling libsamplerate resampling" >&2;} + enable_lsr=no + elif test x$enable_lsr = xyes; then + as_fn_error $? "libsamplerate resampling: libsamplerate not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_lsr = xyes; then + ENABLE_LIBSAMPLERATE_TRUE= + ENABLE_LIBSAMPLERATE_FALSE='#' +else + ENABLE_LIBSAMPLERATE_TRUE='#' + ENABLE_LIBSAMPLERATE_FALSE= +fi + + if test x$enable_lsr = xyes; then + +$as_echo "#define ENABLE_LIBSAMPLERATE 1" >>confdefs.h fi -if test x$enable_lsr = xyes; then -$as_echo "#define HAVE_LIBSAMPLERATE 1" >>confdefs.h -fi - if test x$enable_lsr = xyes; then - HAVE_LIBSAMPLERATE_TRUE= - HAVE_LIBSAMPLERATE_FALSE='#' + + # Check whether --enable-soxr was given. +if test "${enable_soxr+set}" = set; then : + enableval=$enable_soxr; else - HAVE_LIBSAMPLERATE_TRUE='#' - HAVE_LIBSAMPLERATE_FALSE= + enable_soxr=auto fi - if eval "test x`echo '$'enable_soxr` != xno"; then + + + + if test x$enable_soxr != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SOXR" >&5 @@ -10359,77 +11215,80 @@ # Put the nasty error message in config.log where it belongs echo "$SOXR_PKG_ERRORS" >&5 - eval "found_soxr=no" + found_soxr=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_soxr=no" + found_soxr=no else SOXR_CFLAGS=$pkg_cv_SOXR_CFLAGS SOXR_LIBS=$pkg_cv_SOXR_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_soxr=yes" + found_soxr=yes fi fi + if test x$enable_soxr = xno; then + found_soxr=no + fi - name="soxr" - var="enable_soxr" - found="found_$name" - feature="libsoxr resampler" - msg="libsoxr not found" + if test x$found_soxr = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_soxr = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libsoxr resampler" >&5 +$as_echo "$as_me: auto-detected libsoxr resampler" >&6;} + enable_soxr=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_soxr = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsoxr not found -- disabling libsoxr resampler" >&5 +$as_echo "$as_me: WARNING: libsoxr not found -- disabling libsoxr resampler" >&2;} + enable_soxr=no + elif test x$enable_soxr = xyes; then + as_fn_error $? "libsoxr resampler: libsoxr not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_soxr = xyes; then + ENABLE_SOXR_TRUE= + ENABLE_SOXR_FALSE='#' +else + ENABLE_SOXR_TRUE='#' + ENABLE_SOXR_FALSE= +fi + + if test x$enable_soxr = xyes; then + +$as_echo "#define ENABLE_SOXR 1" >>confdefs.h fi -if test x$enable_soxr = xyes; then -$as_echo "#define HAVE_SOXR 1" >>confdefs.h -fi - if test x$enable_soxr = xyes; then - HAVE_SOXR_TRUE= - HAVE_SOXR_FALSE='#' + + # Check whether --enable-curl was given. +if test "${enable_curl+set}" = set; then : + enableval=$enable_curl; else - HAVE_SOXR_TRUE='#' - HAVE_SOXR_FALSE= + enable_curl=auto fi - if eval "test x`echo '$'enable_curl` != xno"; then + + + if test x$enable_curl != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5 @@ -10489,65 +11348,49 @@ # Put the nasty error message in config.log where it belongs echo "$CURL_PKG_ERRORS" >&5 - eval "found_curl=no" + found_curl=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_curl=no" + found_curl=no else CURL_CFLAGS=$pkg_cv_CURL_CFLAGS CURL_LIBS=$pkg_cv_CURL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_curl=yes" + found_curl=yes fi fi - - name="curl" - var="enable_curl" - found="found_$name" - feature="libcurl HTTP streaming" - msg="libcurl not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_curl = xno; then + found_curl=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_curl = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_curl = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libcurl HTTP streaming" >&5 +$as_echo "$as_me: auto-detected libcurl HTTP streaming" >&6;} + enable_curl=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_curl = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libcurl not found -- disabling libcurl HTTP streaming" >&5 +$as_echo "$as_me: WARNING: libcurl not found -- disabling libcurl HTTP streaming" >&2;} + enable_curl=no + elif test x$enable_curl = xyes; then + as_fn_error $? "libcurl HTTP streaming: libcurl not found" "$LINENO" 5 fi fi -if test x$enable_curl = xyes; then -$as_echo "#define ENABLE_CURL 1" >>confdefs.h -fi - if test x$enable_curl = xyes; then + + if test x$enable_curl = xyes; then ENABLE_CURL_TRUE= ENABLE_CURL_FALSE='#' else @@ -10555,9 +11398,29 @@ ENABLE_CURL_FALSE= fi + if test x$enable_curl = xyes; then + +$as_echo "#define ENABLE_CURL 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-smbclient was given. +if test "${enable_smbclient+set}" = set; then : + enableval=$enable_smbclient; +else + enable_smbclient=auto +fi + - if eval "test x`echo '$'enable_smbclient` != xno"; then + + + + if test x$enable_smbclient != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMBCLIENT" >&5 @@ -10654,9 +11517,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_smbclient_smbc_init" >&5 $as_echo "$ac_cv_lib_smbclient_smbc_init" >&6; } if test "x$ac_cv_lib_smbclient_smbc_init" = xyes; then : - eval "found_smbclient=yes SMBCLIENT_LIBS='-lsmbclient' SMBCLIENT_CFLAGS=''" + found_smbclient=yes SMBCLIENT_LIBS='-lsmbclient' SMBCLIENT_CFLAGS='' else - eval "found_smbclient=no" + found_smbclient=no fi elif test $pkg_failed = untried; then @@ -10699,9 +11562,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_smbclient_smbc_init" >&5 $as_echo "$ac_cv_lib_smbclient_smbc_init" >&6; } if test "x$ac_cv_lib_smbclient_smbc_init" = xyes; then : - eval "found_smbclient=yes SMBCLIENT_LIBS='-lsmbclient' SMBCLIENT_CFLAGS=''" + found_smbclient=yes SMBCLIENT_LIBS='-lsmbclient' SMBCLIENT_CFLAGS='' else - eval "found_smbclient=no" + found_smbclient=no fi else @@ -10709,55 +11572,39 @@ SMBCLIENT_LIBS=$pkg_cv_SMBCLIENT_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_smbclient=yes" + found_smbclient=yes fi fi - - name="smbclient" - var="enable_smbclient" - found="found_$name" - feature="smbclient input plugin" - msg="libsmbclient not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_smbclient = xno; then + found_smbclient=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_smbclient = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_smbclient = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected smbclient input plugin" >&5 +$as_echo "$as_me: auto-detected smbclient input plugin" >&6;} + enable_smbclient=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_smbclient = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsmbclient not found -- disabling smbclient input plugin" >&5 +$as_echo "$as_me: WARNING: libsmbclient not found -- disabling smbclient input plugin" >&2;} + enable_smbclient=no + elif test x$enable_smbclient = xyes; then + as_fn_error $? "smbclient input plugin: libsmbclient not found" "$LINENO" 5 fi fi -if test x$enable_smbclient = xyes; then -$as_echo "#define ENABLE_SMBCLIENT 1" >>confdefs.h -fi - if test x$enable_smbclient = xyes; then + + if test x$enable_smbclient = xyes; then ENABLE_SMBCLIENT_TRUE= ENABLE_SMBCLIENT_FALSE='#' else @@ -10765,9 +11612,29 @@ ENABLE_SMBCLIENT_FALSE= fi + if test x$enable_smbclient = xyes; then + +$as_echo "#define ENABLE_SMBCLIENT 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-nfs was given. +if test "${enable_nfs+set}" = set; then : + enableval=$enable_nfs; +else + enable_nfs=auto +fi + + + - if eval "test x`echo '$'enable_nfs` != xno"; then + + if test x$enable_nfs != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NFS" >&5 @@ -10827,65 +11694,49 @@ # Put the nasty error message in config.log where it belongs echo "$NFS_PKG_ERRORS" >&5 - eval "found_nfs=no" + found_nfs=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_nfs=no" + found_nfs=no else NFS_CFLAGS=$pkg_cv_NFS_CFLAGS NFS_LIBS=$pkg_cv_NFS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_nfs=yes" + found_nfs=yes fi fi - - name="nfs" - var="enable_nfs" - found="found_$name" - feature="NFS input plugin" - msg="libnfs not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_nfs = xno; then + found_nfs=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_nfs = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_nfs = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected NFS input plugin" >&5 +$as_echo "$as_me: auto-detected NFS input plugin" >&6;} + enable_nfs=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_nfs = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libnfs not found -- disabling NFS input plugin" >&5 +$as_echo "$as_me: WARNING: libnfs not found -- disabling NFS input plugin" >&2;} + enable_nfs=no + elif test x$enable_nfs = xyes; then + as_fn_error $? "NFS input plugin: libnfs not found" "$LINENO" 5 fi fi -if test x$enable_nfs = xyes; then -$as_echo "#define ENABLE_NFS 1" >>confdefs.h -fi - if test x$enable_nfs = xyes; then + + if test x$enable_nfs = xyes; then ENABLE_NFS_TRUE= ENABLE_NFS_FALSE='#' else @@ -10893,8 +11744,16 @@ ENABLE_NFS_FALSE= fi + if test x$enable_nfs = xyes; then + +$as_echo "#define ENABLE_NFS 1" >>confdefs.h + + fi + + -if test x$enable_soundcloud != xno; then + + if test x$enable_soundcloud != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for YAJL" >&5 @@ -10921,126 +11780,44 @@ pkg_cv_YAJL_LIBS="$YAJL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yajl >= 2.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "yajl >= 2.0") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_YAJL_LIBS=`$PKG_CONFIG --libs "yajl >= 2.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - YAJL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "yajl >= 2.0" 2>&1` - else - YAJL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "yajl >= 2.0" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$YAJL_PKG_ERRORS" >&5 - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yajl_parse_complete in -lyajl" >&5 -$as_echo_n "checking for yajl_parse_complete in -lyajl... " >&6; } -if ${ac_cv_lib_yajl_yajl_parse_complete+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lyajl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char yajl_parse_complete (); -int -main () -{ -return yajl_parse_complete (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_yajl_yajl_parse_complete=yes -else - ac_cv_lib_yajl_yajl_parse_complete=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_yajl_yajl_parse_complete" >&5 -$as_echo "$ac_cv_lib_yajl_yajl_parse_complete" >&6; } -if test "x$ac_cv_lib_yajl_yajl_parse_complete" = xyes; then : - found_soundcloud=yes YAJL_CFLAGS=-DHAVE_YAJL1 YAJL_LIBS=-lyajl -else - found_soundcloud=no -fi - -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yajl_parse_complete in -lyajl" >&5 -$as_echo_n "checking for yajl_parse_complete in -lyajl... " >&6; } -if ${ac_cv_lib_yajl_yajl_parse_complete+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lyajl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char yajl_parse_complete (); -int -main () -{ -return yajl_parse_complete (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_yajl_yajl_parse_complete=yes + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yajl >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "yajl >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_YAJL_LIBS=`$PKG_CONFIG --libs "yajl >= 2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - ac_cv_lib_yajl_yajl_parse_complete=no + pkg_failed=yes fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + else + pkg_failed=untried fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_yajl_yajl_parse_complete" >&5 -$as_echo "$ac_cv_lib_yajl_yajl_parse_complete" >&6; } -if test "x$ac_cv_lib_yajl_yajl_parse_complete" = xyes; then : - found_soundcloud=yes YAJL_CFLAGS=-DHAVE_YAJL1 YAJL_LIBS=-lyajl + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes else - found_soundcloud=no + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + YAJL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "yajl >= 2.0" 2>&1` + else + YAJL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "yajl >= 2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$YAJL_PKG_ERRORS" >&5 + found_soundcloud=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + found_soundcloud=no else YAJL_CFLAGS=$pkg_cv_YAJL_CFLAGS YAJL_LIBS=$pkg_cv_YAJL_LIBS @@ -11048,51 +11825,34 @@ $as_echo "yes" >&6; } found_soundcloud=yes fi -fi - - name="soundcloud" - var="enable_soundcloud" - found="found_$name" - feature="soundcloud.com support" - msg="libyajl not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$enable_soundcloud = xno; then + found_soundcloud=no + fi - var="enable_$name" - feature="$feature" + if test x$found_soundcloud = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_soundcloud = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected soundcloud.com support" >&5 +$as_echo "$as_me: auto-detected soundcloud.com support" >&6;} + enable_soundcloud=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_soundcloud = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libyajl not found -- disabling soundcloud.com support" >&5 +$as_echo "$as_me: WARNING: libyajl not found -- disabling soundcloud.com support" >&2;} + enable_soundcloud=no + elif test x$enable_soundcloud = xyes; then + as_fn_error $? "soundcloud.com support: libyajl not found" "$LINENO" 5 fi fi -if test x$enable_soundcloud = xyes; then - -$as_echo "#define ENABLE_SOUNDCLOUD 1" >>confdefs.h -fi - if test x$enable_soundcloud = xyes; then + if test x$enable_soundcloud = xyes; then ENABLE_SOUNDCLOUD_TRUE= ENABLE_SOUNDCLOUD_FALSE='#' else @@ -11100,10 +11860,27 @@ ENABLE_SOUNDCLOUD_FALSE= fi + if test x$enable_soundcloud = xyes; then + +$as_echo "#define ENABLE_SOUNDCLOUD 1" >>confdefs.h + + fi + + + + # Check whether --enable-cdio-paranoia was given. +if test "${enable_cdio_paranoia+set}" = set; then : + enableval=$enable_cdio_paranoia; +else + enable_cdio_paranoia=auto +fi + + + - if eval "test x`echo '$'enable_cdio_paranoia` != xno"; then + if test x$enable_cdio_paranoia != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CDIO_PARANOIA" >&5 @@ -11163,63 +11940,64 @@ # Put the nasty error message in config.log where it belongs echo "$CDIO_PARANOIA_PKG_ERRORS" >&5 - eval "found_cdio_paranoia=no" + found_cdio_paranoia=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_cdio_paranoia=no" + found_cdio_paranoia=no else CDIO_PARANOIA_CFLAGS=$pkg_cv_CDIO_PARANOIA_CFLAGS CDIO_PARANOIA_LIBS=$pkg_cv_CDIO_PARANOIA_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_cdio_paranoia=yes" + found_cdio_paranoia=yes fi fi + if test x$enable_cdio_paranoia = xno; then + found_cdio_paranoia=no + fi - name="cdio_paranoia" - var="enable_cdio_paranoia" - found="found_$name" - feature="libcdio_paranoia audio CD library" - msg="libcdio_paranoia not found" + if test x$found_cdio_paranoia = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_cdio_paranoia = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libcdio_paranoia input plugin" >&5 +$as_echo "$as_me: auto-detected libcdio_paranoia input plugin" >&6;} + enable_cdio_paranoia=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_cdio_paranoia = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libcdio_paranoia not found -- disabling libcdio_paranoia input plugin" >&5 +$as_echo "$as_me: WARNING: libcdio_paranoia not found -- disabling libcdio_paranoia input plugin" >&2;} + enable_cdio_paranoia=no + elif test x$enable_cdio_paranoia = xyes; then + as_fn_error $? "libcdio_paranoia input plugin: libcdio_paranoia not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi - fi + if test x$enable_cdio_paranoia = xyes; then + ENABLE_CDIO_PARANOIA_TRUE= + ENABLE_CDIO_PARANOIA_FALSE='#' +else + ENABLE_CDIO_PARANOIA_TRUE='#' + ENABLE_CDIO_PARANOIA_FALSE= +fi -if test x$enable_cdio_paranoia = xyes; then + if test x$enable_cdio_paranoia = xyes; then $as_echo "#define ENABLE_CDIO_PARANOIA 1" >>confdefs.h + fi + + +if test x$enable_cdio_paranoia = xyes; then for ac_header in cdio/paranoia/paranoia.h do : ac_fn_c_check_header_mongrel "$LINENO" "cdio/paranoia/paranoia.h" "ac_cv_header_cdio_paranoia_paranoia_h" "$ac_includes_default" @@ -11234,17 +12012,21 @@ fi - if test x$enable_cdio_paranoia = xyes; then - ENABLE_CDIO_PARANOIA_TRUE= - ENABLE_CDIO_PARANOIA_FALSE='#' + + + # Check whether --enable-mms was given. +if test "${enable_mms+set}" = set; then : + enableval=$enable_mms; else - ENABLE_CDIO_PARANOIA_TRUE='#' - ENABLE_CDIO_PARANOIA_FALSE= + enable_mms=auto fi - if eval "test x`echo '$'enable_mms` != xno"; then + + + + if test x$enable_mms != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMS" >&5 @@ -11304,72 +12086,154 @@ # Put the nasty error message in config.log where it belongs echo "$MMS_PKG_ERRORS" >&5 - eval "found_mms=no" + found_mms=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_mms=no" + found_mms=no else MMS_CFLAGS=$pkg_cv_MMS_CFLAGS MMS_LIBS=$pkg_cv_MMS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_mms=yes" + found_mms=yes fi fi + if test x$enable_mms = xno; then + found_mms=no + fi + + if test x$found_mms = xyes; then + + if test x$enable_mms = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libmms mms:// protocol support" >&5 +$as_echo "$as_me: auto-detected libmms mms:// protocol support" >&6;} + enable_mms=yes + fi + + else - name="mms" - var="enable_mms" - found="found_$name" - feature="libmms mms:// protocol support" - msg="libmms not found" + if test x$enable_mms = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmms not found -- disabling libmms mms:// protocol support" >&5 +$as_echo "$as_me: WARNING: libmms not found -- disabling libmms mms:// protocol support" >&2;} + enable_mms=no + elif test x$enable_mms = xyes; then + as_fn_error $? "libmms mms:// protocol support: libmms not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" fi - if eval "test x`echo '$'$found` = xyes"; then - var="enable_$name" - feature="$feature" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + + + if test x$enable_mms = xyes; then + ENABLE_MMS_TRUE= + ENABLE_MMS_FALSE='#' +else + ENABLE_MMS_TRUE='#' + ENABLE_MMS_FALSE= +fi + + if test x$enable_mms = xyes; then + +$as_echo "#define ENABLE_MMS 1" >>confdefs.h + fi + + + + + + # Check whether --enable-webdav was given. +if test "${enable_webdav+set}" = set; then : + enableval=$enable_webdav; +else + enable_webdav=auto +fi + + + + + if test x$enable_webdav != xno; then + if test x$enable_curl = xyes && test x$enable_expat = xyes; then + found_webdav=yes else + found_webdav=no + fi + fi + + if test x$enable_webdav = xno; then + found_webdav=no + fi + + if test x$found_webdav = xyes; then - var="enable_$name" - feature="$feature" - msg="$msg" + if test x$enable_webdav = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected WebDAV storage plugin" >&5 +$as_echo "$as_me: auto-detected WebDAV storage plugin" >&6;} + enable_webdav=yes + fi + + else - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_webdav = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: WebDAV requires libcurl and libexpat -- disabling WebDAV storage plugin" >&5 +$as_echo "$as_me: WARNING: WebDAV requires libcurl and libexpat -- disabling WebDAV storage plugin" >&2;} + enable_webdav=no + elif test x$enable_webdav = xyes; then + as_fn_error $? "WebDAV storage plugin: WebDAV requires libcurl and libexpat" "$LINENO" 5 fi fi -if test x$enable_mms = xyes; then -$as_echo "#define ENABLE_MMS 1" >>confdefs.h + if test x$enable_webdav = xyes; then + ENABLE_WEBDAV_TRUE= + ENABLE_WEBDAV_FALSE='#' +else + ENABLE_WEBDAV_TRUE='#' + ENABLE_WEBDAV_FALSE= fi - if test x$enable_mms = xyes; then - ENABLE_MMS_TRUE= - ENABLE_MMS_FALSE='#' + + if test x$enable_webdav = xyes; then + +$as_echo "#define ENABLE_WEBDAV 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-cue was given. +if test "${enable_cue+set}" = set; then : + enableval=$enable_cue; else - ENABLE_MMS_TRUE='#' - ENABLE_MMS_FALSE= + enable_cue=yes +fi + + + + + if test x$enable_cue = xyes; then + ENABLE_CUE_TRUE= + ENABLE_CUE_FALSE='#' +else + ENABLE_CUE_TRUE='#' + ENABLE_CUE_FALSE= fi + if test x$enable_cue = xyes; then + +$as_echo "#define ENABLE_CUE 1" >>confdefs.h + + fi + # Check whether --enable-neighbor-plugins was given. @@ -11389,12 +12253,7 @@ fi fi -if test x$enable_neighbor_plugins = xyes; then - -$as_echo "#define ENABLE_NEIGHBOR_PLUGINS 1" >>confdefs.h - -fi - if test x$enable_neighbor_plugins = xyes; then + if test x$enable_neighbor_plugins = xyes; then ENABLE_NEIGHBOR_PLUGINS_TRUE= ENABLE_NEIGHBOR_PLUGINS_FALSE='#' else @@ -11402,10 +12261,28 @@ ENABLE_NEIGHBOR_PLUGINS_FALSE= fi + if test x$enable_neighbor_plugins = xyes; then + +$as_echo "#define ENABLE_NEIGHBOR_PLUGINS 1" >>confdefs.h + + fi + + + + + # Check whether --enable-iso9660 was given. +if test "${enable_iso9660+set}" = set; then : + enableval=$enable_iso9660; +else + enable_iso9660=auto +fi + + - if eval "test x`echo '$'enable_iso9660` != xno"; then + + if test x$enable_iso9660 != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ISO9660" >&5 @@ -11465,73 +12342,65 @@ # Put the nasty error message in config.log where it belongs echo "$ISO9660_PKG_ERRORS" >&5 - eval "found_iso9660=no" + found_iso9660=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_iso9660=no" + found_iso9660=no else ISO9660_CFLAGS=$pkg_cv_ISO9660_CFLAGS ISO9660_LIBS=$pkg_cv_ISO9660_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_iso9660=yes" + found_iso9660=yes fi fi - - name="iso9660" - var="enable_iso9660" - found="found_$name" - feature="libiso9660 archive library" - msg="libiso9660 not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_iso9660 = xno; then + found_iso9660=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_iso9660 = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_iso9660 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libiso9660 archive plugin" >&5 +$as_echo "$as_me: auto-detected libiso9660 archive plugin" >&6;} + enable_iso9660=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_iso9660 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libiso9660 not found -- disabling libiso9660 archive plugin" >&5 +$as_echo "$as_me: WARNING: libiso9660 not found -- disabling libiso9660 archive plugin" >&2;} + enable_iso9660=no + elif test x$enable_iso9660 = xyes; then + as_fn_error $? "libiso9660 archive plugin: libiso9660 not found" "$LINENO" 5 fi fi - if test x$enable_iso9660 = xyes; then - HAVE_ISO9660_TRUE= - HAVE_ISO9660_FALSE='#' + + + if test x$enable_iso9660 = xyes; then + ENABLE_ISO9660_TRUE= + ENABLE_ISO9660_FALSE='#' else - HAVE_ISO9660_TRUE='#' - HAVE_ISO9660_FALSE= + ENABLE_ISO9660_TRUE='#' + ENABLE_ISO9660_FALSE= fi -if test x$enable_iso9660 = xyes; then + if test x$enable_iso9660 = xyes; then + +$as_echo "#define ENABLE_ISO9660 1" >>confdefs.h + + fi -$as_echo "#define HAVE_ISO9660 1" >>confdefs.h +if test x$enable_iso9660 = xyes; then # Extract the first word of "mkisofs", so it can be a program name with args. set dummy mkisofs; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -11588,7 +12457,20 @@ - if eval "test x`echo '$'enable_zlib` != xno"; then + + # Check whether --enable-zlib was given. +if test "${enable_zlib+set}" = set; then : + enableval=$enable_zlib; +else + enable_zlib=auto +fi + + + + + + + if test x$enable_zlib != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 @@ -11648,80 +12530,83 @@ # Put the nasty error message in config.log where it belongs echo "$ZLIB_PKG_ERRORS" >&5 - eval "found_zlib=no" + found_zlib=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_zlib=no" + found_zlib=no else ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS ZLIB_LIBS=$pkg_cv_ZLIB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_zlib=yes" + found_zlib=yes fi fi + if test x$enable_zlib = xno; then + found_zlib=no + fi - name="zlib" - var="enable_zlib" - found="found_$name" - feature="zlib support" - msg="zlib not found" + if test x$found_zlib = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_zlib = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected zlib support" >&5 +$as_echo "$as_me: auto-detected zlib support" >&6;} + enable_zlib=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_zlib = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib not found -- disabling zlib support" >&5 +$as_echo "$as_me: WARNING: zlib not found -- disabling zlib support" >&2;} + enable_zlib=no + elif test x$enable_zlib = xyes; then + as_fn_error $? "zlib support: zlib not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_zlib = xyes; then + ENABLE_ZLIB_TRUE= + ENABLE_ZLIB_FALSE='#' +else + ENABLE_ZLIB_TRUE='#' + ENABLE_ZLIB_FALSE= +fi + + if test x$enable_zlib = xyes; then + +$as_echo "#define ENABLE_ZLIB 1" >>confdefs.h fi - if test x$enable_zlib = xyes; then - HAVE_ZLIB_TRUE= - HAVE_ZLIB_FALSE='#' + + + + # Check whether --enable-bzip2 was given. +if test "${enable_bzip2+set}" = set; then : + enableval=$enable_bzip2; else - HAVE_ZLIB_TRUE='#' - HAVE_ZLIB_FALSE= + enable_bzip2=auto fi -if test x$enable_zlib = xyes; then -$as_echo "#define HAVE_ZLIB 1" >>confdefs.h -fi - if eval "test x`echo '$'enable_bzip2` != xno"; then + if test x$enable_bzip2 != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzDecompressInit in -lbz2" >&5 $as_echo_n "checking for BZ2_bzDecompressInit in -lbz2... " >&6; } if ${ac_cv_lib_bz2_BZ2_bzDecompressInit+:} false; then : @@ -11759,66 +12644,58 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzDecompressInit" >&5 $as_echo "$ac_cv_lib_bz2_BZ2_bzDecompressInit" >&6; } if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then : - eval "found_bzip2=yes BZ2_LIBS='-lbz2' BZ2_CFLAGS=''" + found_bzip2=yes BZ2_LIBS='-lbz2' BZ2_CFLAGS='' else - eval "found_bzip2=no" + found_bzip2=no fi fi - - name="bzip2" - var="enable_bzip2" - found="found_$name" - feature="bzip2" - msg="libbz2 not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_bzip2 = xno; then + found_bzip2=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_bzip2 = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_bzip2 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected bzip2 archive plugin" >&5 +$as_echo "$as_me: auto-detected bzip2 archive plugin" >&6;} + enable_bzip2=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_bzip2 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libbz2 not found -- disabling bzip2 archive plugin" >&5 +$as_echo "$as_me: WARNING: libbz2 not found -- disabling bzip2 archive plugin" >&2;} + enable_bzip2=no + elif test x$enable_bzip2 = xyes; then + as_fn_error $? "bzip2 archive plugin: libbz2 not found" "$LINENO" 5 fi fi - if test x$enable_bzip2 = xyes; then - HAVE_BZ2_TRUE= - HAVE_BZ2_FALSE='#' + + + if test x$enable_bzip2 = xyes; then + ENABLE_BZ2_TRUE= + ENABLE_BZ2_FALSE='#' else - HAVE_BZ2_TRUE='#' - HAVE_BZ2_FALSE= + ENABLE_BZ2_TRUE='#' + ENABLE_BZ2_FALSE= fi -if test x$enable_bzip2 = xyes; then + if test x$enable_bzip2 = xyes; then + +$as_echo "#define ENABLE_BZ2 1" >>confdefs.h + + fi -$as_echo "#define HAVE_BZ2 1" >>confdefs.h +if test x$enable_bzip2 = xyes; then # Extract the first word of "bzip2", so it can be a program name with args. set dummy bzip2; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -11885,7 +12762,29 @@ fi - if eval "test x`echo '$'enable_upnp` != xno"; then + + + # Check whether --enable-upnp was given. +if test "${enable_upnp+set}" = set; then : + enableval=$enable_upnp; +else + enable_upnp=auto +fi + + + + + if test x$enable_database = xno; then + if test x$enable_upnp = xauto; then + enable_upnp=no + elif test x$enable_upnp = xyes; then + as_fn_error $? "Cannot use --enable-upnp with --disable-database" "$LINENO" 5 + fi + fi + + + + if test x$enable_upnp != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for UPNP" >&5 @@ -11945,75 +12844,80 @@ # Put the nasty error message in config.log where it belongs echo "$UPNP_PKG_ERRORS" >&5 - eval "found_upnp=no" + found_upnp=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_upnp=no" + found_upnp=no else UPNP_CFLAGS=$pkg_cv_UPNP_CFLAGS UPNP_LIBS=$pkg_cv_UPNP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_upnp=yes" + found_upnp=yes fi fi + if test x$enable_upnp = xno; then + found_upnp=no + fi - name="upnp" - var="enable_upnp" - found="found_$name" - feature="UPnP client support" - msg="libupnp not found" + if test x$found_upnp = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_upnp = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected UPnP client support" >&5 +$as_echo "$as_me: auto-detected UPnP client support" >&6;} + enable_upnp=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_upnp = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libupnp not found -- disabling UPnP client support" >&5 +$as_echo "$as_me: WARNING: libupnp not found -- disabling UPnP client support" >&2;} + enable_upnp=no + elif test x$enable_upnp = xyes; then + as_fn_error $? "UPnP client support: libupnp not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + + + if test x$enable_upnp = xyes; then + ENABLE_UPNP_TRUE= + ENABLE_UPNP_FALSE='#' +else + ENABLE_UPNP_TRUE='#' + ENABLE_UPNP_FALSE= +fi + + if test x$enable_upnp = xyes; then + +$as_echo "#define ENABLE_UPNP 1" >>confdefs.h + fi - fi -if test x$enable_upnp = xyes; then -$as_echo "#define HAVE_LIBUPNP 1" >>confdefs.h -fi - if test x$enable_upnp = xyes; then - HAVE_LIBUPNP_TRUE= - HAVE_LIBUPNP_FALSE='#' + + # Check whether --enable-zzip was given. +if test "${enable_zzip+set}" = set; then : + enableval=$enable_zzip; else - HAVE_LIBUPNP_TRUE='#' - HAVE_LIBUPNP_FALSE= + enable_zzip=no fi - if eval "test x`echo '$'enable_zzip` != xno"; then + + + + if test x$enable_zzip != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZZIP" >&5 @@ -12073,73 +12977,65 @@ # Put the nasty error message in config.log where it belongs echo "$ZZIP_PKG_ERRORS" >&5 - eval "found_zzip=no" + found_zzip=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_zzip=no" + found_zzip=no else ZZIP_CFLAGS=$pkg_cv_ZZIP_CFLAGS ZZIP_LIBS=$pkg_cv_ZZIP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_zzip=yes" + found_zzip=yes fi fi - - name="zzip" - var="enable_zzip" - found="found_$name" - feature="libzzip archive library" - msg="libzzip not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_zzip = xno; then + found_zzip=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_zzip = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_zzip = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libzzip archive library" >&5 +$as_echo "$as_me: auto-detected libzzip archive library" >&6;} + enable_zzip=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_zzip = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libzzip not found -- disabling libzzip archive library" >&5 +$as_echo "$as_me: WARNING: libzzip not found -- disabling libzzip archive library" >&2;} + enable_zzip=no + elif test x$enable_zzip = xyes; then + as_fn_error $? "libzzip archive library: libzzip not found" "$LINENO" 5 fi fi - if test x$enable_zzip = xyes; then - HAVE_ZZIP_TRUE= - HAVE_ZZIP_FALSE='#' + + + if test x$enable_zzip = xyes; then + ENABLE_ZZIP_TRUE= + ENABLE_ZZIP_FALSE='#' else - HAVE_ZZIP_TRUE='#' - HAVE_ZZIP_FALSE= + ENABLE_ZZIP_TRUE='#' + ENABLE_ZZIP_FALSE= fi -if test x$enable_zzip = xyes; then + if test x$enable_zzip = xyes; then -$as_echo "#define HAVE_ZZIP 1" >>confdefs.h +$as_echo "#define ENABLE_ZZIP 1" >>confdefs.h + + fi + +if test x$enable_zzip = xyes; then # Extract the first word of "zip", so it can be a program name with args. set dummy zip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -12199,14 +13095,11 @@ test x$enable_zzip = xyes || test x$enable_iso9660 = xyes; then enable_archive=yes - -$as_echo "#define ENABLE_ARCHIVE 1" >>confdefs.h - else enable_archive=no fi - if test x$enable_archive = xyes; then + if test x$enable_archive = xyes; then ENABLE_ARCHIVE_TRUE= ENABLE_ARCHIVE_FALSE='#' else @@ -12214,10 +13107,28 @@ ENABLE_ARCHIVE_FALSE= fi + if test x$enable_archive = xyes; then + +$as_echo "#define ENABLE_ARCHIVE 1" >>confdefs.h + + fi + + + + + # Check whether --enable-adplug was given. +if test "${enable_adplug+set}" = set; then : + enableval=$enable_adplug; +else + enable_adplug=auto +fi + + - if eval "test x`echo '$'enable_adplug` != xno"; then + + if test x$enable_adplug != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ADPLUG" >&5 @@ -12277,75 +13188,79 @@ # Put the nasty error message in config.log where it belongs echo "$ADPLUG_PKG_ERRORS" >&5 - eval "found_adplug=no" + found_adplug=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_adplug=no" + found_adplug=no else ADPLUG_CFLAGS=$pkg_cv_ADPLUG_CFLAGS ADPLUG_LIBS=$pkg_cv_ADPLUG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_adplug=yes" + found_adplug=yes fi fi + if test x$enable_adplug = xno; then + found_adplug=no + fi - name="adplug" - var="enable_adplug" - found="found_$name" - feature="AdPlug decoder plugin" - msg="libadplug not found" + if test x$found_adplug = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_adplug = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected AdPlug decoder plugin" >&5 +$as_echo "$as_me: auto-detected AdPlug decoder plugin" >&6;} + enable_adplug=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_adplug = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libadplug not found -- disabling AdPlug decoder plugin" >&5 +$as_echo "$as_me: WARNING: libadplug not found -- disabling AdPlug decoder plugin" >&2;} + enable_adplug=no + elif test x$enable_adplug = xyes; then + as_fn_error $? "AdPlug decoder plugin: libadplug not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_adplug = xyes; then + ENABLE_ADPLUG_TRUE= + ENABLE_ADPLUG_FALSE='#' +else + ENABLE_ADPLUG_TRUE='#' + ENABLE_ADPLUG_FALSE= +fi + + if test x$enable_adplug = xyes; then + +$as_echo "#define ENABLE_ADPLUG 1" >>confdefs.h fi -if test x$enable_adplug = xyes; then -$as_echo "#define HAVE_ADPLUG 1" >>confdefs.h -fi - if test x$enable_adplug = xyes; then - HAVE_ADPLUG_TRUE= - HAVE_ADPLUG_FALSE='#' + + # Check whether --enable-audiofile was given. +if test "${enable_audiofile+set}" = set; then : + enableval=$enable_audiofile; else - HAVE_ADPLUG_TRUE='#' - HAVE_ADPLUG_FALSE= + enable_audiofile=auto fi - if eval "test x`echo '$'enable_audiofile` != xno"; then + + + + if test x$enable_audiofile != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AUDIOFILE" >&5 @@ -12405,81 +13320,66 @@ # Put the nasty error message in config.log where it belongs echo "$AUDIOFILE_PKG_ERRORS" >&5 - eval "found_audiofile=no" + found_audiofile=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_audiofile=no" + found_audiofile=no else AUDIOFILE_CFLAGS=$pkg_cv_AUDIOFILE_CFLAGS AUDIOFILE_LIBS=$pkg_cv_AUDIOFILE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_audiofile=yes" + found_audiofile=yes fi fi - - name="audiofile" - var="enable_audiofile" - found="found_$name" - feature="audiofile decoder plugin" - msg="libaudiofile not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_audiofile = xno; then + found_audiofile=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_audiofile = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_audiofile = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected audiofile decoder plugin" >&5 +$as_echo "$as_me: auto-detected audiofile decoder plugin" >&6;} + enable_audiofile=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_audiofile = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libaudiofile not found -- disabling audiofile decoder plugin" >&5 +$as_echo "$as_me: WARNING: libaudiofile not found -- disabling audiofile decoder plugin" >&2;} + enable_audiofile=no + elif test x$enable_audiofile = xyes; then + as_fn_error $? "audiofile decoder plugin: libaudiofile not found" "$LINENO" 5 fi fi - if test x$enable_audiofile = xyes; then - HAVE_AUDIOFILE_TRUE= - HAVE_AUDIOFILE_FALSE='#' -else - HAVE_AUDIOFILE_TRUE='#' - HAVE_AUDIOFILE_FALSE= -fi -if test x$enable_audiofile = xyes; then -$as_echo "#define HAVE_AUDIOFILE 1" >>confdefs.h + if test x$enable_audiofile = xyes; then + ENABLE_AUDIOFILE_TRUE= + ENABLE_AUDIOFILE_FALSE='#' +else + ENABLE_AUDIOFILE_TRUE='#' + ENABLE_AUDIOFILE_FALSE= fi + if test x$enable_audiofile = xyes; then -if test x$enable_dsd = xyes; then +$as_echo "#define ENABLE_AUDIOFILE 1" >>confdefs.h -$as_echo "#define ENABLE_DSD 1" >>confdefs.h + fi -fi - if test x$enable_dsd = xyes; then + + + if test x$enable_dsd = xyes; then ENABLE_DSD_TRUE= ENABLE_DSD_FALSE='#' else @@ -12487,52 +13387,37 @@ ENABLE_DSD_FALSE= fi + if test x$enable_dsd = xyes; then + +$as_echo "#define ENABLE_DSD 1" >>confdefs.h + + fi + -# Check whether --enable-aac was given. + # Check whether --enable-aac was given. if test "${enable_aac+set}" = set; then : enableval=$enable_aac; else - enable_aac=yes + enable_aac=auto fi -if test x$enable_aac = xyes; then - FAAD_LIBS="-lfaad" - FAAD_CFLAGS="" - oldcflags=$CFLAGS - oldlibs=$LIBS - oldcppflags=$CPPFLAGS - CFLAGS="$CFLAGS $FAAD_CFLAGS" - LIBS="$LIBS $FAAD_LIBS" - CPPFLAGS=$CFLAGS - ac_fn_c_check_header_mongrel "$LINENO" "faad.h" "ac_cv_header_faad_h" "$ac_includes_default" -if test "x$ac_cv_header_faad_h" = xyes; then : -else - enable_aac=no -fi - if test x$enable_aac = xyes; then - ac_fn_c_check_decl "$LINENO" "FAAD2_VERSION" "ac_cv_have_decl_FAAD2_VERSION" "#include -" -if test "x$ac_cv_have_decl_FAAD2_VERSION" = xyes; then : -else - enable_aac=no -fi - fi - if test x$enable_aac = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NeAACDecInit2 in -lfaad" >&5 -$as_echo_n "checking for NeAACDecInit2 in -lfaad... " >&6; } -if ${ac_cv_lib_faad_NeAACDecInit2+:} false; then : + + if test x$enable_aac != xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NeAACDecOpen in -lfaad" >&5 +$as_echo_n "checking for NeAACDecOpen in -lfaad... " >&6; } +if ${ac_cv_lib_faad_NeAACDecOpen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lfaad $LIBS" +LIBS="-lfaad -lfaad $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -12542,111 +13427,93 @@ #ifdef __cplusplus extern "C" #endif -char NeAACDecInit2 (); +char NeAACDecOpen (); int main () { -return NeAACDecInit2 (); +return NeAACDecOpen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_faad_NeAACDecInit2=yes + ac_cv_lib_faad_NeAACDecOpen=yes else - ac_cv_lib_faad_NeAACDecInit2=no + ac_cv_lib_faad_NeAACDecOpen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_faad_NeAACDecInit2" >&5 -$as_echo "$ac_cv_lib_faad_NeAACDecInit2" >&6; } -if test "x$ac_cv_lib_faad_NeAACDecInit2" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBFAAD 1 -_ACEOF - - LIBS="-lfaad $LIBS" - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_faad_NeAACDecOpen" >&5 +$as_echo "$ac_cv_lib_faad_NeAACDecOpen" >&6; } +if test "x$ac_cv_lib_faad_NeAACDecOpen" = xyes; then : + found_aac=yes FAAD_LIBS='-lfaad' FAAD_CFLAGS='' else - enable_aac=no + found_aac=no fi fi - if test x$enable_aac = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking that FAAD2 can even be used" >&5 -$as_echo_n "checking that FAAD2 can even be used... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -int main() { - char buffer; - NeAACDecHandle decoder; - NeAACDecFrameInfo frameInfo; - NeAACDecConfigurationPtr config; - unsigned char channels; - long sampleRate; - long bufferlen = 0; - - decoder = NeAACDecOpen(); - config = NeAACDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - NeAACDecSetConfiguration(decoder,config); - NeAACDecInit(decoder,&buffer,bufferlen,&sampleRate,&channels); - NeAACDecInit2(decoder,&buffer,bufferlen,&sampleRate,&channels); - NeAACDecDecode(decoder,&frameInfo,&buffer,bufferlen); - NeAACDecClose(decoder); + if test x$enable_aac = xno; then + found_aac=no + fi - return 0; -} + if test x$found_aac = xyes; then -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; };enable_aac=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test x$enable_aac = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected FAAD decoder plugin" >&5 +$as_echo "$as_me: auto-detected FAAD decoder plugin" >&6;} + enable_aac=yes fi - if test x$enable_aac = xyes; then - -$as_echo "#define HAVE_FAAD 1" >>confdefs.h else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: faad2 lib needed for MP4/AAC support -- disabling MP4/AAC support" >&5 -$as_echo "$as_me: WARNING: faad2 lib needed for MP4/AAC support -- disabling MP4/AAC support" >&2;} + + if test x$enable_aac = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libfaad not found -- disabling FAAD decoder plugin" >&5 +$as_echo "$as_me: WARNING: libfaad not found -- disabling FAAD decoder plugin" >&2;} + enable_aac=no + elif test x$enable_aac = xyes; then + as_fn_error $? "FAAD decoder plugin: libfaad not found" "$LINENO" 5 fi - CFLAGS=$oldcflags - LIBS=$oldlibs - CPPFLAGS=$oldcppflags -fi -if test x$enable_aac = xno; then - FAAD_LIBS="" - FAAD_CFLAGS="" + fi + + + + + + if test x$enable_aac = xyes; then + ENABLE_FAAD_TRUE= + ENABLE_FAAD_FALSE='#' +else + ENABLE_FAAD_TRUE='#' + ENABLE_FAAD_FALSE= fi + if test x$enable_aac = xyes; then + +$as_echo "#define ENABLE_FAAD 1" >>confdefs.h + + fi - if test x$enable_aac = xyes; then - HAVE_FAAD_TRUE= - HAVE_FAAD_FALSE='#' + # Check whether --enable-ffmpeg was given. +if test "${enable_ffmpeg+set}" = set; then : + enableval=$enable_ffmpeg; else - HAVE_FAAD_TRUE='#' - HAVE_FAAD_FALSE= + enable_ffmpeg=auto fi - if eval "test x`echo '$'enable_ffmpeg` != xno"; then + + + + if test x$enable_ffmpeg != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FFMPEG" >&5 @@ -12706,78 +13573,80 @@ # Put the nasty error message in config.log where it belongs echo "$FFMPEG_PKG_ERRORS" >&5 - eval "found_ffmpeg=no" + found_ffmpeg=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_ffmpeg=no" + found_ffmpeg=no else FFMPEG_CFLAGS=$pkg_cv_FFMPEG_CFLAGS FFMPEG_LIBS=$pkg_cv_FFMPEG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_ffmpeg=yes" + found_ffmpeg=yes fi fi + if test x$enable_ffmpeg = xno; then + found_ffmpeg=no + fi - name="ffmpeg" - var="enable_ffmpeg" - found="found_$name" - feature="ffmpeg decoder library" - msg="libavformat+libavcodec+libavutil not found" + if test x$found_ffmpeg = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_ffmpeg = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected ffmpeg decoder library" >&5 +$as_echo "$as_me: auto-detected ffmpeg decoder library" >&6;} + enable_ffmpeg=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_ffmpeg = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libavformat+libavcodec+libavutil not found -- disabling ffmpeg decoder library" >&5 +$as_echo "$as_me: WARNING: libavformat+libavcodec+libavutil not found -- disabling ffmpeg decoder library" >&2;} + enable_ffmpeg=no + elif test x$enable_ffmpeg = xyes; then + as_fn_error $? "ffmpeg decoder library: libavformat+libavcodec+libavutil not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_ffmpeg = xyes; then + ENABLE_FFMPEG_TRUE= + ENABLE_FFMPEG_FALSE='#' +else + ENABLE_FFMPEG_TRUE='#' + ENABLE_FFMPEG_FALSE= +fi + + if test x$enable_ffmpeg = xyes; then + +$as_echo "#define ENABLE_FFMPEG 1" >>confdefs.h fi -if test x$enable_ffmpeg = xyes; then -$as_echo "#define HAVE_FFMPEG 1" >>confdefs.h -fi - if test x$enable_ffmpeg = xyes; then - HAVE_FFMPEG_TRUE= - HAVE_FFMPEG_FALSE='#' + # Check whether --enable-flac was given. +if test "${enable_flac+set}" = set; then : + enableval=$enable_flac; else - HAVE_FFMPEG_TRUE='#' - HAVE_FFMPEG_FALSE= + enable_flac=auto fi - if eval "test x`echo '$'enable_flac` != xno"; then + + + if test x$enable_flac != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FLAC" >&5 @@ -12837,80 +13706,82 @@ # Put the nasty error message in config.log where it belongs echo "$FLAC_PKG_ERRORS" >&5 - eval "found_flac=no" + found_flac=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_flac=no" + found_flac=no else FLAC_CFLAGS=$pkg_cv_FLAC_CFLAGS FLAC_LIBS=$pkg_cv_FLAC_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_flac=yes" + found_flac=yes fi fi + if test x$enable_flac = xno; then + found_flac=no + fi - name="flac" - var="enable_flac" - found="found_$name" - feature="FLAC decoder" - msg="libFLAC not found" + if test x$found_flac = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_flac = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected FLAC decoder" >&5 +$as_echo "$as_me: auto-detected FLAC decoder" >&6;} + enable_flac=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_flac = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libFLAC not found -- disabling FLAC decoder" >&5 +$as_echo "$as_me: WARNING: libFLAC not found -- disabling FLAC decoder" >&2;} + enable_flac=no + elif test x$enable_flac = xyes; then + as_fn_error $? "FLAC decoder: libFLAC not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_flac = xyes; then + ENABLE_FLAC_TRUE= + ENABLE_FLAC_FALSE='#' +else + ENABLE_FLAC_TRUE='#' + ENABLE_FLAC_FALSE= +fi + + if test x$enable_flac = xyes; then + +$as_echo "#define ENABLE_FLAC 1" >>confdefs.h fi -if test x$enable_flac = xyes; then +enable_flac_encoder=$enable_flac + -$as_echo "#define HAVE_FLAC 1" >>confdefs.h -fi - if test x$enable_flac = xyes; then - HAVE_FLAC_TRUE= - HAVE_FLAC_FALSE='#' + # Check whether --enable-fluidsynth was given. +if test "${enable_fluidsynth+set}" = set; then : + enableval=$enable_fluidsynth; else - HAVE_FLAC_TRUE='#' - HAVE_FLAC_FALSE= + enable_fluidsynth=auto fi -enable_flac_encoder=$enable_flac - if eval "test x`echo '$'enable_fluidsynth` != xno"; then + + if test x$enable_fluidsynth != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FLUIDSYNTH" >&5 @@ -12970,67 +13841,49 @@ # Put the nasty error message in config.log where it belongs echo "$FLUIDSYNTH_PKG_ERRORS" >&5 - eval "found_fluidsynth=no" + found_fluidsynth=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_fluidsynth=no" + found_fluidsynth=no else FLUIDSYNTH_CFLAGS=$pkg_cv_FLUIDSYNTH_CFLAGS FLUIDSYNTH_LIBS=$pkg_cv_FLUIDSYNTH_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_fluidsynth=yes" + found_fluidsynth=yes fi fi - - name="fluidsynth" - var="enable_fluidsynth" - found="found_$name" - feature="fluidsynth decoder" - msg="fluidsynth not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_fluidsynth = xno; then + found_fluidsynth=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_fluidsynth = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_fluidsynth = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected fluidsynth MIDI decoder plugin" >&5 +$as_echo "$as_me: auto-detected fluidsynth MIDI decoder plugin" >&6;} + enable_fluidsynth=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_fluidsynth = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fluidsynth not found -- disabling fluidsynth MIDI decoder plugin" >&5 +$as_echo "$as_me: WARNING: fluidsynth not found -- disabling fluidsynth MIDI decoder plugin" >&2;} + enable_fluidsynth=no + elif test x$enable_fluidsynth = xyes; then + as_fn_error $? "fluidsynth MIDI decoder plugin: fluidsynth not found" "$LINENO" 5 fi fi -if test x$enable_fluidsynth = xyes; then - -$as_echo "#define ENABLE_FLUIDSYNTH 1" >>confdefs.h -fi - if test x$enable_fluidsynth = xyes; then + if test x$enable_fluidsynth = xyes; then ENABLE_FLUIDSYNTH_TRUE= ENABLE_FLUIDSYNTH_FALSE='#' else @@ -13038,9 +13891,30 @@ ENABLE_FLUIDSYNTH_FALSE= fi + if test x$enable_fluidsynth = xyes; then + +$as_echo "#define ENABLE_FLUIDSYNTH 1" >>confdefs.h + + fi + + + + + + + # Check whether --enable-gme was given. +if test "${enable_gme+set}" = set; then : + enableval=$enable_gme; +else + enable_gme=auto +fi + + + - if eval "test x`echo '$'enable_gme` != xno"; then + + if test x$enable_gme != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GME" >&5 @@ -13106,7 +13980,7 @@ $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lgme -lgme -lstdc++ $LIBS" +LIBS="-lgme -lgme $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13137,9 +14011,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gme_gme_open_file" >&5 $as_echo "$ac_cv_lib_gme_gme_open_file" >&6; } if test "x$ac_cv_lib_gme_gme_open_file" = xyes; then : - eval "found_gme=yes GME_LIBS='-lgme -lstdc++' GME_CFLAGS=''" + found_gme=yes GME_LIBS='-lgme' GME_CFLAGS='' else - eval "found_gme=no" + found_gme=no fi elif test $pkg_failed = untried; then @@ -13151,7 +14025,7 @@ $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lgme -lgme -lstdc++ $LIBS" +LIBS="-lgme -lgme $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13182,9 +14056,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gme_gme_open_file" >&5 $as_echo "$ac_cv_lib_gme_gme_open_file" >&6; } if test "x$ac_cv_lib_gme_gme_open_file" = xyes; then : - eval "found_gme=yes GME_LIBS='-lgme -lstdc++' GME_CFLAGS=''" + found_gme=yes GME_LIBS='-lgme' GME_CFLAGS='' else - eval "found_gme=no" + found_gme=no fi else @@ -13192,65 +14066,69 @@ GME_LIBS=$pkg_cv_GME_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_gme=yes" + found_gme=yes fi fi + if test x$enable_gme = xno; then + found_gme=no + fi - name="gme" - var="enable_gme" - found="found_$name" - feature="gme decoder plugin" - msg="libgme not found" + if test x$found_gme = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_gme = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected Game Music Emulator decoder plugin" >&5 +$as_echo "$as_me: auto-detected Game Music Emulator decoder plugin" >&6;} + enable_gme=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_gme = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libgme not found -- disabling Game Music Emulator decoder plugin" >&5 +$as_echo "$as_me: WARNING: libgme not found -- disabling Game Music Emulator decoder plugin" >&2;} + enable_gme=no + elif test x$enable_gme = xyes; then + as_fn_error $? "Game Music Emulator decoder plugin: libgme not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_gme = xyes; then + ENABLE_GME_TRUE= + ENABLE_GME_FALSE='#' +else + ENABLE_GME_TRUE='#' + ENABLE_GME_FALSE= +fi + + if test x$enable_gme = xyes; then + +$as_echo "#define ENABLE_GME 1" >>confdefs.h fi - if test x$enable_gme = xyes; then - HAVE_GME_TRUE= - HAVE_GME_FALSE='#' + + + + # Check whether --enable-mad was given. +if test "${enable_mad+set}" = set; then : + enableval=$enable_mad; else - HAVE_GME_TRUE='#' - HAVE_GME_FALSE= + enable_mad=auto fi -if test x$enable_gme = xyes; then -$as_echo "#define HAVE_GME 1" >>confdefs.h -fi - if eval "test x`echo '$'enable_mad` != xno"; then + + if test x$enable_mad != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAD" >&5 @@ -13347,9 +14225,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_mad_stream_init" >&5 $as_echo "$ac_cv_lib_mad_mad_stream_init" >&6; } if test "x$ac_cv_lib_mad_mad_stream_init" = xyes; then : - eval "found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS=''" + found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS='' else - eval "found_mad=no" + found_mad=no fi elif test $pkg_failed = untried; then @@ -13392,9 +14270,9 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_mad_stream_init" >&5 $as_echo "$ac_cv_lib_mad_mad_stream_init" >&6; } if test "x$ac_cv_lib_mad_mad_stream_init" = xyes; then : - eval "found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS=''" + found_mad=yes MAD_LIBS='-lmad' MAD_CFLAGS='' else - eval "found_mad=no" + found_mad=no fi else @@ -13402,66 +14280,58 @@ MAD_LIBS=$pkg_cv_MAD_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_mad=yes" + found_mad=yes fi fi - - name="mad" - var="enable_mad" - found="found_$name" - feature="libmad MP3 decoder plugin" - msg="libmad not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_mad = xno; then + found_mad=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_mad = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_mad = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libmad MP3 decoder plugin" >&5 +$as_echo "$as_me: auto-detected libmad MP3 decoder plugin" >&6;} + enable_mad=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_mad = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmad not found -- disabling libmad MP3 decoder plugin" >&5 +$as_echo "$as_me: WARNING: libmad not found -- disabling libmad MP3 decoder plugin" >&2;} + enable_mad=no + elif test x$enable_mad = xyes; then + as_fn_error $? "libmad MP3 decoder plugin: libmad not found" "$LINENO" 5 fi fi -if test x$enable_mad = xyes; then -$as_echo "#define HAVE_MAD 1" >>confdefs.h -fi - if test x$enable_mad = xyes; then - HAVE_MAD_TRUE= - HAVE_MAD_FALSE='#' + + if test x$enable_mad = xyes; then + ENABLE_MAD_TRUE= + ENABLE_MAD_FALSE='#' else - HAVE_MAD_TRUE='#' - HAVE_MAD_FALSE= + ENABLE_MAD_TRUE='#' + ENABLE_MAD_FALSE= fi + if test x$enable_mad = xyes; then + +$as_echo "#define ENABLE_MAD 1" >>confdefs.h + + fi + + enable_shout2="$enable_shout" - if eval "test x`echo '$'enable_shout` != xno"; then + + if test x$enable_shout != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SHOUT" >&5 @@ -13521,65 +14391,65 @@ # Put the nasty error message in config.log where it belongs echo "$SHOUT_PKG_ERRORS" >&5 - eval "found_shout=no" + found_shout=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_shout=no" + found_shout=no else SHOUT_CFLAGS=$pkg_cv_SHOUT_CFLAGS SHOUT_LIBS=$pkg_cv_SHOUT_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_shout=yes" + found_shout=yes fi fi - - name="shout" - var="enable_shout" - found="found_$name" - feature="shout output plugin" - msg="libshout not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_shout = xno; then + found_shout=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_shout = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_shout = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected shout output plugin" >&5 +$as_echo "$as_me: auto-detected shout output plugin" >&6;} + enable_shout=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_shout = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libshout not found -- disabling shout output plugin" >&5 +$as_echo "$as_me: WARNING: libshout not found -- disabling shout output plugin" >&2;} + enable_shout=no + elif test x$enable_shout = xyes; then + as_fn_error $? "shout output plugin: libshout not found" "$LINENO" 5 fi fi + if test x$enable_shout = xyes && test x$enable_shout2 = xauto; then enable_shout=auto fi - if eval "test x`echo '$'enable_mpg123` != xno"; then + + # Check whether --enable-mpg123 was given. +if test "${enable_mpg123+set}" = set; then : + enableval=$enable_mpg123; +else + enable_mpg123=auto +fi + + + + + + + if test x$enable_mpg123 != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MPG123" >&5 @@ -13639,72 +14509,63 @@ # Put the nasty error message in config.log where it belongs echo "$MPG123_PKG_ERRORS" >&5 - eval "found_mpg123=no" + found_mpg123=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_mpg123=no" + found_mpg123=no else MPG123_CFLAGS=$pkg_cv_MPG123_CFLAGS MPG123_LIBS=$pkg_cv_MPG123_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_mpg123=yes" + found_mpg123=yes fi fi - - name="mpg123" - var="enable_mpg123" - found="found_$name" - feature="libmpg123 decoder plugin" - msg="libmpg123 not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_mpg123 = xno; then + found_mpg123=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_mpg123 = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_mpg123 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libmpg123 decoder plugin" >&5 +$as_echo "$as_me: auto-detected libmpg123 decoder plugin" >&6;} + enable_mpg123=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_mpg123 = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmpg123 not found -- disabling libmpg123 decoder plugin" >&5 +$as_echo "$as_me: WARNING: libmpg123 not found -- disabling libmpg123 decoder plugin" >&2;} + enable_mpg123=no + elif test x$enable_mpg123 = xyes; then + as_fn_error $? "libmpg123 decoder plugin: libmpg123 not found" "$LINENO" 5 fi fi -if test x$enable_mpg123 = xyes; then -$as_echo "#define HAVE_MPG123 1" >>confdefs.h -fi - if test x$enable_mpg123 = xyes; then - HAVE_MPG123_TRUE= - HAVE_MPG123_FALSE='#' + + if test x$enable_mpg123 = xyes; then + ENABLE_MPG123_TRUE= + ENABLE_MPG123_FALSE='#' else - HAVE_MPG123_TRUE='#' - HAVE_MPG123_FALSE= + ENABLE_MPG123_TRUE='#' + ENABLE_MPG123_FALSE= fi + if test x$enable_mpg123 = xyes; then + +$as_echo "#define ENABLE_MPG123 1" >>confdefs.h + + fi + + if test x$enable_mikmod = xyes; then # Extract the first word of "libmikmod-config", so it can be a program name with args. @@ -13764,13 +14625,26 @@ ENABLE_MIKMOD_DECODER_TRUE= ENABLE_MIKMOD_DECODER_FALSE='#' else - ENABLE_MIKMOD_DECODER_TRUE='#' - ENABLE_MIKMOD_DECODER_FALSE= + ENABLE_MIKMOD_DECODER_TRUE='#' + ENABLE_MIKMOD_DECODER_FALSE= +fi + + + + + # Check whether --enable-modplug was given. +if test "${enable_modplug+set}" = set; then : + enableval=$enable_modplug; +else + enable_modplug=auto fi - if eval "test x`echo '$'enable_modplug` != xno"; then + + + + if test x$enable_modplug != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MODPLUG" >&5 @@ -13830,76 +14704,79 @@ # Put the nasty error message in config.log where it belongs echo "$MODPLUG_PKG_ERRORS" >&5 - eval "found_modplug=no" + found_modplug=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_modplug=no" + found_modplug=no else MODPLUG_CFLAGS=$pkg_cv_MODPLUG_CFLAGS MODPLUG_LIBS=$pkg_cv_MODPLUG_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_modplug=yes" + found_modplug=yes fi fi + if test x$enable_modplug = xno; then + found_modplug=no + fi - name="modplug" - var="enable_modplug" - found="found_$name" - feature="modplug decoder plugin" - msg="libmodplug not found" + if test x$found_modplug = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_modplug = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected modplug decoder plugin" >&5 +$as_echo "$as_me: auto-detected modplug decoder plugin" >&6;} + enable_modplug=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_modplug = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmodplug not found -- disabling modplug decoder plugin" >&5 +$as_echo "$as_me: WARNING: libmodplug not found -- disabling modplug decoder plugin" >&2;} + enable_modplug=no + elif test x$enable_modplug = xyes; then + as_fn_error $? "modplug decoder plugin: libmodplug not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_modplug = xyes; then + ENABLE_MODPLUG_TRUE= + ENABLE_MODPLUG_FALSE='#' +else + ENABLE_MODPLUG_TRUE='#' + ENABLE_MODPLUG_FALSE= +fi + + if test x$enable_modplug = xyes; then + +$as_echo "#define ENABLE_MODPLUG 1" >>confdefs.h fi -if test x$enable_modplug = xyes; then -$as_echo "#define HAVE_MODPLUG 1" >>confdefs.h -fi - if test x$enable_modplug = xyes; then - HAVE_MODPLUG_TRUE= - HAVE_MODPLUG_FALSE='#' + # Check whether --enable-opus was given. +if test "${enable_opus+set}" = set; then : + enableval=$enable_opus; else - HAVE_MODPLUG_TRUE='#' - HAVE_MODPLUG_FALSE= + enable_opus=auto fi - if eval "test x`echo '$'enable_opus` != xno"; then + + + + if test x$enable_opus != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPUS" >&5 @@ -13959,75 +14836,79 @@ # Put the nasty error message in config.log where it belongs echo "$OPUS_PKG_ERRORS" >&5 - eval "found_opus=no" + found_opus=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_opus=no" + found_opus=no else OPUS_CFLAGS=$pkg_cv_OPUS_CFLAGS OPUS_LIBS=$pkg_cv_OPUS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_opus=yes" + found_opus=yes fi fi + if test x$enable_opus = xno; then + found_opus=no + fi - name="opus" - var="enable_opus" - found="found_$name" - feature="opus decoder plugin" - msg="libopus not found" + if test x$found_opus = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_opus = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected opus decoder plugin" >&5 +$as_echo "$as_me: auto-detected opus decoder plugin" >&6;} + enable_opus=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_opus = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libopus not found -- disabling opus decoder plugin" >&5 +$as_echo "$as_me: WARNING: libopus not found -- disabling opus decoder plugin" >&2;} + enable_opus=no + elif test x$enable_opus = xyes; then + as_fn_error $? "opus decoder plugin: libopus not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_opus = xyes; then + ENABLE_OPUS_TRUE= + ENABLE_OPUS_FALSE='#' +else + ENABLE_OPUS_TRUE='#' + ENABLE_OPUS_FALSE= +fi + + if test x$enable_opus = xyes; then + +$as_echo "#define ENABLE_OPUS 1" >>confdefs.h fi -if test x$enable_opus = xyes; then -$as_echo "#define HAVE_OPUS 1" >>confdefs.h -fi - if test x$enable_opus = xyes; then - HAVE_OPUS_TRUE= - HAVE_OPUS_FALSE='#' + + # Check whether --enable-sndfile was given. +if test "${enable_sndfile+set}" = set; then : + enableval=$enable_sndfile; else - HAVE_OPUS_TRUE='#' - HAVE_OPUS_FALSE= + enable_sndfile=auto fi - if eval "test x`echo '$'enable_sndfile` != xno"; then + + + + if test x$enable_sndfile != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SNDFILE" >&5 @@ -14087,66 +14968,49 @@ # Put the nasty error message in config.log where it belongs echo "$SNDFILE_PKG_ERRORS" >&5 - eval "found_sndfile=no" + found_sndfile=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_sndfile=no" + found_sndfile=no else SNDFILE_CFLAGS=$pkg_cv_SNDFILE_CFLAGS SNDFILE_LIBS=$pkg_cv_SNDFILE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_sndfile=yes" + found_sndfile=yes fi fi - - name="sndfile" - var="enable_sndfile" - found="found_$name" - feature="libsndfile decoder plugin" - msg="libsndfile not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_sndfile = xno; then + found_sndfile=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_sndfile = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_sndfile = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libsndfile decoder plugin" >&5 +$as_echo "$as_me: auto-detected libsndfile decoder plugin" >&6;} + enable_sndfile=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_sndfile = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsndfile not found -- disabling libsndfile decoder plugin" >&5 +$as_echo "$as_me: WARNING: libsndfile not found -- disabling libsndfile decoder plugin" >&2;} + enable_sndfile=no + elif test x$enable_sndfile = xyes; then + as_fn_error $? "libsndfile decoder plugin: libsndfile not found" "$LINENO" 5 fi fi -if test x$enable_sndfile = xyes; then -$as_echo "#define ENABLE_SNDFILE 1" >>confdefs.h -fi - if test x$enable_sndfile = xyes; then + if test x$enable_sndfile = xyes; then ENABLE_SNDFILE_TRUE= ENABLE_SNDFILE_FALSE='#' else @@ -14154,13 +15018,33 @@ ENABLE_SNDFILE_FALSE= fi + if test x$enable_sndfile = xyes; then + +$as_echo "#define ENABLE_SNDFILE 1" >>confdefs.h + + fi + + + + + + + # Check whether --enable-mpc was given. +if test "${enable_mpc+set}" = set; then : + enableval=$enable_mpc; +else + enable_mpc=auto +fi + + - if eval "test x`echo '$'enable_mpc` != xno"; then + + if test x$enable_mpc != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mpc_demux_init in -lmpcdec" >&5 $as_echo_n "checking for mpc_demux_init in -lmpcdec... " >&6; } if ${ac_cv_lib_mpcdec_mpc_demux_init+:} false; then : @@ -14198,143 +15082,109 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mpcdec_mpc_demux_init" >&5 $as_echo "$ac_cv_lib_mpcdec_mpc_demux_init" >&6; } if test "x$ac_cv_lib_mpcdec_mpc_demux_init" = xyes; then : - eval "found_mpc=yes MPCDEC_LIBS='-lmpcdec' MPCDEC_CFLAGS=''" + found_mpc=yes MPCDEC_LIBS='-lmpcdec' MPCDEC_CFLAGS='' else - eval "found_mpc=no" + found_mpc=no fi fi + if test x$enable_mpc = xno; then + found_mpc=no + fi - name="mpc" - var="enable_mpc" - found="found_$name" - feature="mpcdec" - msg="libmpcdec not found" + if test x$found_mpc = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_mpc = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected Musepack decoder plugin" >&5 +$as_echo "$as_me: auto-detected Musepack decoder plugin" >&6;} + enable_mpc=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_mpc = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmpcdec not found -- disabling Musepack decoder plugin" >&5 +$as_echo "$as_me: WARNING: libmpcdec not found -- disabling Musepack decoder plugin" >&2;} + enable_mpc=no + elif test x$enable_mpc = xyes; then + as_fn_error $? "Musepack decoder plugin: libmpcdec not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_mpc = xyes; then + ENABLE_MPCDEC_TRUE= + ENABLE_MPCDEC_FALSE='#' +else + ENABLE_MPCDEC_TRUE='#' + ENABLE_MPCDEC_FALSE= +fi + + if test x$enable_mpc = xyes; then + +$as_echo "#define ENABLE_MPCDEC 1" >>confdefs.h fi -if test x$enable_mpc = xyes; then -$as_echo "#define HAVE_MPCDEC 1" >>confdefs.h -fi - if test x$enable_mpc = xyes; then - HAVE_MPCDEC_TRUE= - HAVE_MPCDEC_FALSE='#' + +# Check whether --with-tremor was given. +if test "${with_tremor+set}" = set; then : + withval=$with_tremor; else - HAVE_MPCDEC_TRUE='#' - HAVE_MPCDEC_FALSE= + with_tremor=no fi + + + if test x$with_tremor = xyes || test x$with_tremor = xno; then enable_tremor="$with_tremor" + tremor_prefix="" else tremor_prefix="$with_tremor" enable_tremor=yes fi if test x$enable_tremor = xyes; then - if test "x$tremor_libraries" != "x" ; then - TREMOR_LIBS="-L$tremor_libraries" - elif test "x$tremor_prefix" != "x" ; then - TREMOR_LIBS="-L$tremor_prefix/lib" - fi - TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec" - if test "x$tremor_includes" != "x" ; then - TREMOR_CFLAGS="-I$tremor_includes" - elif test "x$tremor_prefix" != "x" ; then + if test x$TREMOR_CFLAGS = x && test x$tremor_prefix != x; then TREMOR_CFLAGS="-I$tremor_prefix/include" fi + if test x$TREMOR_LIBS = x; then + TREMOR_LIBS="-lvorbisidec" + + if test x$tremor_prefix != x; then + TREMOR_LIBS="-L$tremor_prefix/lib $TREMOR_LIBS" + fi + fi + + ac_save_CFLAGS="$CFLAGS" + ac_save_CXXFLAGS="$CXXFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $TREMOR_CFLAGS" + CXXFLAGS="$CXXFLAGS $TREMOR_CFLAGS" LIBS="$LIBS $TREMOR_LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ov_read in -lvorbisidec" >&5 -$as_echo_n "checking for ov_read in -lvorbisidec... " >&6; } -if ${ac_cv_lib_vorbisidec_ov_read+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lvorbisidec $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ov_read (); -int -main () -{ -return ov_read (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_vorbisidec_ov_read=yes -else - ac_cv_lib_vorbisidec_ov_read=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbisidec_ov_read" >&5 -$as_echo "$ac_cv_lib_vorbisidec_ov_read" >&6; } -if test "x$ac_cv_lib_vorbisidec_ov_read" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBVORBISIDEC 1 -_ACEOF - - LIBS="-lvorbisidec $LIBS" + ac_fn_c_check_func "$LINENO" "ov_read" "ac_cv_func_ov_read" +if test "x$ac_cv_func_ov_read" = xyes; then : else - enable_tremor=no; - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: vorbisidec lib needed for ogg support with tremor -- disabling ogg support" >&5 -$as_echo "$as_me: WARNING: vorbisidec lib needed for ogg support with tremor -- disabling ogg support" >&2;} + as_fn_error $? "libvorbisidec not found" "$LINENO" 5 fi CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" LIBS="$ac_save_LIBS" -fi -if test x$enable_tremor = xyes; then + $as_echo "#define HAVE_TREMOR 1" >>confdefs.h @@ -14347,9 +15197,6 @@ fi - - - if test x$enable_tremor = xyes; then if test x$enable_vorbis = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"OggTremor detected, could not enable Vorbis.\"" >&5 @@ -14365,7 +15212,8 @@ fi - if eval "test x`echo '$'enable_vorbis` != xno"; then + + if test x$enable_vorbis != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VORBIS" >&5 @@ -14375,12 +15223,12 @@ pkg_cv_VORBIS_CFLAGS="$VORBIS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbisfile vorbis ogg\""; } >&5 - ($PKG_CONFIG --exists --print-errors "vorbisfile vorbis ogg") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis ogg\""; } >&5 + ($PKG_CONFIG --exists --print-errors "vorbis ogg") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_VORBIS_CFLAGS=`$PKG_CONFIG --cflags "vorbisfile vorbis ogg" 2>/dev/null` + pkg_cv_VORBIS_CFLAGS=`$PKG_CONFIG --cflags "vorbis ogg" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -14392,12 +15240,12 @@ pkg_cv_VORBIS_LIBS="$VORBIS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbisfile vorbis ogg\""; } >&5 - ($PKG_CONFIG --exists --print-errors "vorbisfile vorbis ogg") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"vorbis ogg\""; } >&5 + ($PKG_CONFIG --exists --print-errors "vorbis ogg") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_VORBIS_LIBS=`$PKG_CONFIG --libs "vorbisfile vorbis ogg" 2>/dev/null` + pkg_cv_VORBIS_LIBS=`$PKG_CONFIG --libs "vorbis ogg" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -14418,66 +15266,53 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - VORBIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "vorbisfile vorbis ogg" 2>&1` + VORBIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "vorbis ogg" 2>&1` else - VORBIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "vorbisfile vorbis ogg" 2>&1` + VORBIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "vorbis ogg" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$VORBIS_PKG_ERRORS" >&5 - eval "found_vorbis=no" + found_vorbis=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_vorbis=no" + found_vorbis=no else VORBIS_CFLAGS=$pkg_cv_VORBIS_CFLAGS VORBIS_LIBS=$pkg_cv_VORBIS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_vorbis=yes" + found_vorbis=yes fi fi - - name="vorbis" - var="enable_vorbis" - found="found_$name" - feature="Ogg Vorbis decoder" - msg="libvorbis not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_vorbis = xno; then + found_vorbis=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_vorbis = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_vorbis = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected Ogg Vorbis decoder" >&5 +$as_echo "$as_me: auto-detected Ogg Vorbis decoder" >&6;} + enable_vorbis=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_vorbis = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libvorbis not found -- disabling Ogg Vorbis decoder" >&5 +$as_echo "$as_me: WARNING: libvorbis not found -- disabling Ogg Vorbis decoder" >&2;} + enable_vorbis=no + elif test x$enable_vorbis = xyes; then + as_fn_error $? "Ogg Vorbis decoder: libvorbis not found" "$LINENO" 5 fi fi + if test x$enable_vorbis = xyes; then $as_echo "#define ENABLE_VORBIS_DECODER 1" >>confdefs.h @@ -14503,12 +15338,12 @@ pkg_cv_SIDPLAY_CFLAGS="$SIDPLAY_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsidplayfp libsidutils\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libsidplayfp libsidutils") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsidplayfp\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsidplayfp") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SIDPLAY_CFLAGS=`$PKG_CONFIG --cflags "libsidplayfp libsidutils" 2>/dev/null` + pkg_cv_SIDPLAY_CFLAGS=`$PKG_CONFIG --cflags "libsidplayfp" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -14520,12 +15355,12 @@ pkg_cv_SIDPLAY_LIBS="$SIDPLAY_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsidplayfp libsidutils\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libsidplayfp libsidutils") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsidplayfp\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsidplayfp") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_SIDPLAY_LIBS=`$PKG_CONFIG --libs "libsidplayfp libsidutils" 2>/dev/null` + pkg_cv_SIDPLAY_LIBS=`$PKG_CONFIG --libs "libsidplayfp" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -14546,9 +15381,9 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsidplayfp libsidutils" 2>&1` + SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsidplayfp" 2>&1` else - SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsidplayfp libsidutils" 2>&1` + SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsidplayfp" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SIDPLAY_PKG_ERRORS" >&5 @@ -14642,24 +15477,14 @@ fi - name="sidplay" - var="enable_sidplay" - found="found_$name" - feature="sidplay decoder plugin" - msg="libsidplay2 not found" - - if eval "test x`echo '$'$var` != xno" && eval "test x`echo '$'$found` = xno"; then - - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_sidplay != xno && test x$found_sidplay = xno; then + + if test x$enable_sidplay = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsidplay2 not found -- disabling sidplay decoder plugin" >&5 +$as_echo "$as_me: WARNING: libsidplay2 not found -- disabling sidplay decoder plugin" >&2;} + enable_sidplay=no + elif test x$enable_sidplay = xyes; then + as_fn_error $? "sidplay decoder plugin: libsidplay2 not found" "$LINENO" 5 fi fi @@ -14705,39 +15530,26 @@ - name="sidplay" - var="enable_sidplay" - found="found_$name" - feature="sidplay decoder plugin" - msg="libresid-builder not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_sidplay = xno; then + found_sidplay=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_sidplay = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_sidplay = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected sidplay decoder plugin" >&5 +$as_echo "$as_me: auto-detected sidplay decoder plugin" >&6;} + enable_sidplay=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_sidplay = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libresid-builder not found -- disabling sidplay decoder plugin" >&5 +$as_echo "$as_me: WARNING: libresid-builder not found -- disabling sidplay decoder plugin" >&2;} + enable_sidplay=no + elif test x$enable_sidplay = xyes; then + as_fn_error $? "sidplay decoder plugin: libresid-builder not found" "$LINENO" 5 fi fi @@ -14766,7 +15578,20 @@ - if eval "test x`echo '$'enable_wavpack` != xno"; then + + # Check whether --enable-wavpack was given. +if test "${enable_wavpack+set}" = set; then : + enableval=$enable_wavpack; +else + enable_wavpack=auto +fi + + + + + + + if test x$enable_wavpack != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WAVPACK" >&5 @@ -14826,78 +15651,82 @@ # Put the nasty error message in config.log where it belongs echo "$WAVPACK_PKG_ERRORS" >&5 - eval "found_wavpack=no" + found_wavpack=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_wavpack=no" + found_wavpack=no else WAVPACK_CFLAGS=$pkg_cv_WAVPACK_CFLAGS WAVPACK_LIBS=$pkg_cv_WAVPACK_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_wavpack=yes" + found_wavpack=yes fi fi + if test x$enable_wavpack = xno; then + found_wavpack=no + fi - name="wavpack" - var="enable_wavpack" - found="found_$name" - feature="WavPack decoder plugin" - msg="libwavpack not found" + if test x$found_wavpack = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_wavpack = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected WavPack decoder plugin" >&5 +$as_echo "$as_me: auto-detected WavPack decoder plugin" >&6;} + enable_wavpack=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_wavpack = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libwavpack not found -- disabling WavPack decoder plugin" >&5 +$as_echo "$as_me: WARNING: libwavpack not found -- disabling WavPack decoder plugin" >&2;} + enable_wavpack=no + elif test x$enable_wavpack = xyes; then + as_fn_error $? "WavPack decoder plugin: libwavpack not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_wavpack = xyes; then + ENABLE_WAVPACK_TRUE= + ENABLE_WAVPACK_FALSE='#' +else + ENABLE_WAVPACK_TRUE='#' + ENABLE_WAVPACK_FALSE= +fi + + if test x$enable_wavpack = xyes; then + +$as_echo "#define ENABLE_WAVPACK 1" >>confdefs.h fi - if test x$enable_wavpack = xyes; then - HAVE_WAVPACK_TRUE= - HAVE_WAVPACK_FALSE='#' + + + + # Check whether --enable-wildmidi was given. +if test "${enable_wildmidi+set}" = set; then : + enableval=$enable_wildmidi; else - HAVE_WAVPACK_TRUE='#' - HAVE_WAVPACK_FALSE= + enable_wildmidi=auto fi -if test x$enable_wavpack = xyes; then -$as_echo "#define HAVE_WAVPACK 1" >>confdefs.h -fi - if eval "test x`echo '$'enable_wildmidi` != xno"; then + + if test x$enable_wildmidi != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WildMidi_Init in -lWildMidi" >&5 $as_echo_n "checking for WildMidi_Init in -lWildMidi... " >&6; } if ${ac_cv_lib_WildMidi_WildMidi_Init+:} false; then : @@ -14935,59 +15764,42 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_WildMidi_WildMidi_Init" >&5 $as_echo "$ac_cv_lib_WildMidi_WildMidi_Init" >&6; } if test "x$ac_cv_lib_WildMidi_WildMidi_Init" = xyes; then : - eval "found_wildmidi=yes WILDMIDI_LIBS='-lWildMidi' WILDMIDI_CFLAGS=''" + found_wildmidi=yes WILDMIDI_LIBS='-lWildMidi' WILDMIDI_CFLAGS='' else - eval "found_wildmidi=no" + found_wildmidi=no fi fi - - name="wildmidi" - var="enable_wildmidi" - found="found_$name" - feature="wildmidi" - msg="libwildmidi not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_wildmidi = xno; then + found_wildmidi=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_wildmidi = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_wildmidi = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected WildMidi decoder plugin" >&5 +$as_echo "$as_me: auto-detected WildMidi decoder plugin" >&6;} + enable_wildmidi=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_wildmidi = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libwildmidi not found -- disabling WildMidi decoder plugin" >&5 +$as_echo "$as_me: WARNING: libwildmidi not found -- disabling WildMidi decoder plugin" >&2;} + enable_wildmidi=no + elif test x$enable_wildmidi = xyes; then + as_fn_error $? "WildMidi decoder plugin: libwildmidi not found" "$LINENO" 5 fi fi -if test x$enable_wildmidi = xyes; then -$as_echo "#define ENABLE_WILDMIDI 1" >>confdefs.h -fi - if test x$enable_wildmidi = xyes; then + if test x$enable_wildmidi = xyes; then ENABLE_WILDMIDI_TRUE= ENABLE_WILDMIDI_FALSE='#' else @@ -14995,15 +15807,12 @@ ENABLE_WILDMIDI_FALSE= fi + if test x$enable_wildmidi = xyes; then +$as_echo "#define ENABLE_WILDMIDI 1" >>confdefs.h + + fi - if test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_flac = xyes || test x$enable_opus = xyes; then - HAVE_XIPH_TRUE= - HAVE_XIPH_FALSE='#' -else - HAVE_XIPH_TRUE='#' - HAVE_XIPH_FALSE= -fi @@ -15029,12 +15838,7 @@ enable_flac_encoder=no fi -if test x$enable_flac_encoder = xyes; then - -$as_echo "#define ENABLE_FLAC_ENCODER 1" >>confdefs.h - -fi - if test x$enable_flac_encoder = xyes; then + if test x$enable_flac_encoder = xyes; then ENABLE_FLAC_ENCODER_TRUE= ENABLE_FLAC_ENCODER_FALSE='#' else @@ -15042,10 +15846,28 @@ ENABLE_FLAC_ENCODER_FALSE= fi + if test x$enable_flac_encoder = xyes; then + +$as_echo "#define ENABLE_FLAC_ENCODER 1" >>confdefs.h + + fi + + + + + # Check whether --enable-shine-encoder was given. +if test "${enable_shine_encoder+set}" = set; then : + enableval=$enable_shine_encoder; +else + enable_shine_encoder=auto +fi + + - if eval "test x`echo '$'enable_shine_encoder` != xno"; then + + if test x$enable_shine_encoder != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SHINE" >&5 @@ -15105,76 +15927,79 @@ # Put the nasty error message in config.log where it belongs echo "$SHINE_PKG_ERRORS" >&5 - eval "found_shine_encoder=no" + found_shine_encoder=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_shine_encoder=no" + found_shine_encoder=no else SHINE_CFLAGS=$pkg_cv_SHINE_CFLAGS SHINE_LIBS=$pkg_cv_SHINE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_shine_encoder=yes" + found_shine_encoder=yes fi fi + if test x$enable_shine_encoder = xno; then + found_shine_encoder=no + fi - name="shine_encoder" - var="enable_shine_encoder" - found="found_$name" - feature="shine encoder" - msg="libshine not found" + if test x$found_shine_encoder = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_shine_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected shine encoder" >&5 +$as_echo "$as_me: auto-detected shine encoder" >&6;} + enable_shine_encoder=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_shine_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libshine not found -- disabling shine encoder" >&5 +$as_echo "$as_me: WARNING: libshine not found -- disabling shine encoder" >&2;} + enable_shine_encoder=no + elif test x$enable_shine_encoder = xyes; then + as_fn_error $? "shine encoder: libshine not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_shine_encoder = xyes; then + ENABLE_SHINE_TRUE= + ENABLE_SHINE_FALSE='#' +else + ENABLE_SHINE_TRUE='#' + ENABLE_SHINE_FALSE= +fi + + if test x$enable_shine_encoder = xyes; then + +$as_echo "#define ENABLE_SHINE 1" >>confdefs.h fi -if test x$enable_shine_encoder = xyes; then -$as_echo "#define ENABLE_SHINE_ENCODER 1" >>confdefs.h -fi - if test x$enable_shine_encoder = xyes; then - ENABLE_SHINE_ENCODER_TRUE= - ENABLE_SHINE_ENCODER_FALSE='#' + # Check whether --enable-vorbis-encoder was given. +if test "${enable_vorbis_encoder+set}" = set; then : + enableval=$enable_vorbis_encoder; else - ENABLE_SHINE_ENCODER_TRUE='#' - ENABLE_SHINE_ENCODER_FALSE= + enable_vorbis_encoder=auto fi - if eval "test x`echo '$'enable_vorbis_encoder` != xno"; then + + + + if test x$enable_vorbis_encoder != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VORBISENC" >&5 @@ -15234,71 +16059,72 @@ # Put the nasty error message in config.log where it belongs echo "$VORBISENC_PKG_ERRORS" >&5 - eval "found_vorbis_encoder=no" + found_vorbis_encoder=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_vorbis_encoder=no" + found_vorbis_encoder=no else VORBISENC_CFLAGS=$pkg_cv_VORBISENC_CFLAGS VORBISENC_LIBS=$pkg_cv_VORBISENC_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_vorbis_encoder=yes" + found_vorbis_encoder=yes fi fi + if test x$enable_vorbis_encoder = xno; then + found_vorbis_encoder=no + fi - name="vorbis_encoder" - var="enable_vorbis_encoder" - found="found_$name" - feature="Ogg Vorbis encoder" - msg="libvorbisenc not found" + if test x$found_vorbis_encoder = xyes; then - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_vorbis_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected Ogg Vorbis encoder" >&5 +$as_echo "$as_me: auto-detected Ogg Vorbis encoder" >&6;} + enable_vorbis_encoder=yes fi - if eval "test x`echo '$'$found` = xyes"; then + else - var="enable_$name" - feature="$feature" + if test x$enable_vorbis_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libvorbisenc not found -- disabling Ogg Vorbis encoder" >&5 +$as_echo "$as_me: WARNING: libvorbisenc not found -- disabling Ogg Vorbis encoder" >&2;} + enable_vorbis_encoder=no + elif test x$enable_vorbis_encoder = xyes; then + as_fn_error $? "Ogg Vorbis encoder: libvorbisenc not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi + + + if test x$enable_vorbis_encoder = xyes; then + ENABLE_VORBISENC_TRUE= + ENABLE_VORBISENC_FALSE='#' +else + ENABLE_VORBISENC_TRUE='#' + ENABLE_VORBISENC_FALSE= +fi + + if test x$enable_vorbis_encoder = xyes; then + +$as_echo "#define ENABLE_VORBISENC 1" >>confdefs.h fi -if test x$enable_vorbis_encoder = xyes; then -$as_echo "#define ENABLE_VORBIS_ENCODER 1" >>confdefs.h -fi - if test x$enable_vorbis_encoder = xyes; then - ENABLE_VORBIS_ENCODER_TRUE= - ENABLE_VORBIS_ENCODER_FALSE='#' + + # Check whether --enable-lame-encoder was given. +if test "${enable_lame_encoder+set}" = set; then : + enableval=$enable_lame_encoder; else - ENABLE_VORBIS_ENCODER_TRUE='#' - ENABLE_VORBIS_ENCODER_FALSE= + enable_lame_encoder=auto fi @@ -15307,7 +16133,9 @@ - if eval "test x`echo '$'enable_lame_encoder` != xno"; then + + + if test x$enable_lame_encoder != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lame_init in -lmp3lame" >&5 $as_echo_n "checking for lame_init in -lmp3lame... " >&6; } if ${ac_cv_lib_mp3lame_lame_init+:} false; then : @@ -15345,68 +16173,72 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mp3lame_lame_init" >&5 $as_echo "$ac_cv_lib_mp3lame_lame_init" >&6; } if test "x$ac_cv_lib_mp3lame_lame_init" = xyes; then : - eval "found_lame_encoder=yes LAME_LIBS='-lmp3lame' LAME_CFLAGS=''" + found_lame_encoder=yes LAME_LIBS='-lmp3lame' LAME_CFLAGS='' else - eval "found_lame_encoder=no" + found_lame_encoder=no fi fi + if test x$enable_lame_encoder = xno; then + found_lame_encoder=no + fi + + if test x$found_lame_encoder = xyes; then + + if test x$enable_lame_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected LAME encoder plugin" >&5 +$as_echo "$as_me: auto-detected LAME encoder plugin" >&6;} + enable_lame_encoder=yes + fi + + else - name="lame_encoder" - var="enable_lame_encoder" - found="found_$name" - feature="libmp3lame" - msg="libmp3lame not found" + if test x$enable_lame_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libmp3lame not found -- disabling LAME encoder plugin" >&5 +$as_echo "$as_me: WARNING: libmp3lame not found -- disabling LAME encoder plugin" >&2;} + enable_lame_encoder=no + elif test x$enable_lame_encoder = xyes; then + as_fn_error $? "LAME encoder plugin: libmp3lame not found" "$LINENO" 5 + fi - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" fi - if eval "test x`echo '$'$found` = xyes"; then - var="enable_$name" - feature="$feature" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + + + if test x$enable_lame_encoder = xyes; then + ENABLE_LAME_TRUE= + ENABLE_LAME_FALSE='#' +else + ENABLE_LAME_TRUE='#' + ENABLE_LAME_FALSE= +fi + + if test x$enable_lame_encoder = xyes; then + +$as_echo "#define ENABLE_LAME 1" >>confdefs.h + fi - else - var="enable_$name" - feature="$feature" - msg="$msg" - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 - fi - fi + # Check whether --enable-twolame-encoder was given. +if test "${enable_twolame_encoder+set}" = set; then : + enableval=$enable_twolame_encoder; +else + enable_twolame_encoder=auto +fi -if test x$enable_lame_encoder = xyes; then -$as_echo "#define ENABLE_LAME_ENCODER 1" >>confdefs.h -fi - if test x$enable_lame_encoder = xyes; then - ENABLE_LAME_ENCODER_TRUE= - ENABLE_LAME_ENCODER_FALSE='#' -else - ENABLE_LAME_ENCODER_TRUE='#' - ENABLE_LAME_ENCODER_FALSE= -fi - if eval "test x`echo '$'enable_twolame_encoder` != xno"; then + if test x$enable_twolame_encoder != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TWOLAME" >&5 @@ -15466,75 +16298,65 @@ # Put the nasty error message in config.log where it belongs echo "$TWOLAME_PKG_ERRORS" >&5 - eval "found_twolame_encoder=no" + found_twolame_encoder=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_twolame_encoder=no" + found_twolame_encoder=no else TWOLAME_CFLAGS=$pkg_cv_TWOLAME_CFLAGS TWOLAME_LIBS=$pkg_cv_TWOLAME_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_twolame_encoder=yes" + found_twolame_encoder=yes fi fi - - name="twolame_encoder" - var="enable_twolame_encoder" - found="found_$name" - feature="TwoLAME encoder" - msg="libtwolame not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_twolame_encoder = xno; then + found_twolame_encoder=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_twolame_encoder = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_twolame_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected TwoLAME encoder plugin" >&5 +$as_echo "$as_me: auto-detected TwoLAME encoder plugin" >&6;} + enable_twolame_encoder=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_twolame_encoder = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libtwolame not found -- disabling TwoLAME encoder plugin" >&5 +$as_echo "$as_me: WARNING: libtwolame not found -- disabling TwoLAME encoder plugin" >&2;} + enable_twolame_encoder=no + elif test x$enable_twolame_encoder = xyes; then + as_fn_error $? "TwoLAME encoder plugin: libtwolame not found" "$LINENO" 5 fi fi -if test x$enable_twolame_encoder = xyes; then -$as_echo "#define ENABLE_TWOLAME_ENCODER 1" >>confdefs.h -fi - if test x$enable_twolame_encoder = xyes; then - ENABLE_TWOLAME_ENCODER_TRUE= - ENABLE_TWOLAME_ENCODER_FALSE='#' + if test x$enable_twolame_encoder = xyes; then + ENABLE_TWOLAME_TRUE= + ENABLE_TWOLAME_FALSE='#' else - ENABLE_TWOLAME_ENCODER_TRUE='#' - ENABLE_TWOLAME_ENCODER_FALSE= + ENABLE_TWOLAME_TRUE='#' + ENABLE_TWOLAME_FALSE= fi + if test x$enable_twolame_encoder = xyes; then - if test x$enable_wave_encoder = xyes; then +$as_echo "#define ENABLE_TWOLAME 1" >>confdefs.h + + fi + + + + if test x$enable_wave_encoder = xyes; then ENABLE_WAVE_ENCODER_TRUE= ENABLE_WAVE_ENCODER_FALSE='#' else @@ -15542,11 +16364,11 @@ ENABLE_WAVE_ENCODER_FALSE= fi -if test x$enable_wave_encoder = xyes; then + if test x$enable_wave_encoder = xyes; then $as_echo "#define ENABLE_WAVE_ENCODER 1" >>confdefs.h -fi + fi if test x$enable_vorbis_encoder != xno || test x$enable_opus != xno || @@ -15566,12 +16388,7 @@ fi fi -if test x$enable_encoder = xyes; then - -$as_echo "#define ENABLE_ENCODER 1" >>confdefs.h - -fi - if test x$enable_encoder = xyes; then + if test x$enable_encoder = xyes; then ENABLE_ENCODER_TRUE= ENABLE_ENCODER_FALSE='#' else @@ -15579,18 +16396,28 @@ ENABLE_ENCODER_FALSE= fi - if test x$enable_vorbis_encoder = xyes || test x$enable_opus = xyes; then - HAVE_OGG_ENCODER_TRUE= - HAVE_OGG_ENCODER_FALSE='#' + if test x$enable_encoder = xyes; then + +$as_echo "#define ENABLE_ENCODER 1" >>confdefs.h + + fi + + + + + # Check whether --enable-alsa was given. +if test "${enable_alsa+set}" = set; then : + enableval=$enable_alsa; else - HAVE_OGG_ENCODER_TRUE='#' - HAVE_OGG_ENCODER_FALSE= + enable_alsa=$linux_auto fi - if eval "test x`echo '$'enable_alsa` != xno"; then + + + if test x$enable_alsa != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5 @@ -15650,77 +16477,79 @@ # Put the nasty error message in config.log where it belongs echo "$ALSA_PKG_ERRORS" >&5 - eval "found_alsa=no" + found_alsa=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_alsa=no" + found_alsa=no else ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS ALSA_LIBS=$pkg_cv_ALSA_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_alsa=yes" + found_alsa=yes fi fi - - name="alsa" - var="enable_alsa" - found="found_$name" - feature="ALSA output plugin" - msg="libasound not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_alsa = xno; then + found_alsa=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_alsa = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_alsa = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected ALSA output plugin" >&5 +$as_echo "$as_me: auto-detected ALSA output plugin" >&6;} + enable_alsa=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_alsa = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libasound not found -- disabling ALSA output plugin" >&5 +$as_echo "$as_me: WARNING: libasound not found -- disabling ALSA output plugin" >&2;} + enable_alsa=no + elif test x$enable_alsa = xyes; then + as_fn_error $? "ALSA output plugin: libasound not found" "$LINENO" 5 fi fi -if test x$enable_alsa = xyes; then -$as_echo "#define HAVE_ALSA 1" >>confdefs.h + if test x$enable_alsa = xyes; then + ENABLE_ALSA_TRUE= + ENABLE_ALSA_FALSE='#' +else + ENABLE_ALSA_TRUE='#' + ENABLE_ALSA_FALSE= fi - if test x$enable_alsa = xyes; then - HAVE_ALSA_TRUE= - HAVE_ALSA_FALSE='#' + if test x$enable_alsa = xyes; then + +$as_echo "#define ENABLE_ALSA 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-roar was given. +if test "${enable_roar+set}" = set; then : + enableval=$enable_roar; else - HAVE_ALSA_TRUE='#' - HAVE_ALSA_FALSE= + enable_roar=auto fi - if eval "test x`echo '$'enable_roar` != xno"; then + + + + if test x$enable_roar != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ROAR" >&5 @@ -15780,81 +16609,68 @@ # Put the nasty error message in config.log where it belongs echo "$ROAR_PKG_ERRORS" >&5 - eval "found_roar=no" + found_roar=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_roar=no" + found_roar=no else ROAR_CFLAGS=$pkg_cv_ROAR_CFLAGS ROAR_LIBS=$pkg_cv_ROAR_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_roar=yes" + found_roar=yes fi fi - - name="roar" - var="enable_roar" - found="found_$name" - feature="ROAR output plugin" - msg="libroar not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_roar = xno; then + found_roar=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_roar = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_roar = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected RoarAudio output plugin" >&5 +$as_echo "$as_me: auto-detected RoarAudio output plugin" >&6;} + enable_roar=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_roar = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libroar not found -- disabling RoarAudio output plugin" >&5 +$as_echo "$as_me: WARNING: libroar not found -- disabling RoarAudio output plugin" >&2;} + enable_roar=no + elif test x$enable_roar = xyes; then + as_fn_error $? "RoarAudio output plugin: libroar not found" "$LINENO" 5 fi fi -if test x$enable_roar = xyes; then -$as_echo "#define HAVE_ROAR 1" >>confdefs.h -fi - - if test x$enable_roar = xyes; then - HAVE_ROAR_TRUE= - HAVE_ROAR_FALSE='#' + if test x$enable_roar = xyes; then + ENABLE_ROAR_TRUE= + ENABLE_ROAR_FALSE='#' else - HAVE_ROAR_TRUE='#' - HAVE_ROAR_FALSE= + ENABLE_ROAR_TRUE='#' + ENABLE_ROAR_FALSE= fi + if test x$enable_roar = xyes; then + +$as_echo "#define ENABLE_ROAR 1" >>confdefs.h + + fi + + if test x$enable_fifo = xyes; then ac_fn_c_check_func "$LINENO" "mkfifo" "ac_cv_func_mkfifo" if test "x$ac_cv_func_mkfifo" = xyes; then : - enable_fifo=yes; -$as_echo "#define HAVE_FIFO 1" >>confdefs.h - + enable_fifo=yes else enable_fifo=no;{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: mkfifo not found -- disabling support for writing audio to a FIFO" >&5 $as_echo "$as_me: WARNING: mkfifo not found -- disabling support for writing audio to a FIFO" >&2;} @@ -15862,7 +16678,7 @@ fi - if test x$enable_fifo = xyes; then + if test x$enable_fifo = xyes; then HAVE_FIFO_TRUE= HAVE_FIFO_FALSE='#' else @@ -15870,6 +16686,155 @@ HAVE_FIFO_FALSE= fi + if test x$enable_fifo = xyes; then + +$as_echo "#define HAVE_FIFO 1" >>confdefs.h + + fi + + + + # Check whether --enable-sndio was given. +if test "${enable_sndio+set}" = set; then : + enableval=$enable_sndio; +else + enable_sndio=auto +fi + + + + + + + + + + if test x$enable_sndio != xno; then + ac_fn_c_check_header_mongrel "$LINENO" "sndio.h" "ac_cv_header_sndio_h" "$ac_includes_default" +if test "x$ac_cv_header_sndio_h" = xyes; then : + found_sndio=yes SNDIO_LIBS='-lsndio' SNDIO_CFLAGS='' +else + found_sndio=no +fi + + + fi + + if test x$enable_sndio = xno; then + found_sndio=no + fi + + if test x$found_sndio = xyes; then + + if test x$enable_sndio = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected sndio output plugin" >&5 +$as_echo "$as_me: auto-detected sndio output plugin" >&6;} + enable_sndio=yes + fi + + else + + if test x$enable_sndio = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsndio not found -- disabling sndio output plugin" >&5 +$as_echo "$as_me: WARNING: libsndio not found -- disabling sndio output plugin" >&2;} + enable_sndio=no + elif test x$enable_sndio = xyes; then + as_fn_error $? "sndio output plugin: libsndio not found" "$LINENO" 5 + fi + + fi + + + + + + if test x$enable_sndio = xyes; then + ENABLE_SNDIO_TRUE= + ENABLE_SNDIO_FALSE='#' +else + ENABLE_SNDIO_TRUE='#' + ENABLE_SNDIO_FALSE= +fi + + if test x$enable_sndio = xyes; then + +$as_echo "#define ENABLE_SNDIO 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-haiku was given. +if test "${enable_haiku+set}" = set; then : + enableval=$enable_haiku; +else + enable_haiku=auto +fi + + + + + + + + + + if test x$enable_haiku != xno; then + ac_fn_c_check_header_mongrel "$LINENO" "media/MediaDefs.h" "ac_cv_header_media_MediaDefs_h" "$ac_includes_default" +if test "x$ac_cv_header_media_MediaDefs_h" = xyes; then : + found_haiku=yes HAIKU_LIBS='-lbe -lmedia' HAIKU_CFLAGS='' +else + found_haiku=no +fi + + + fi + + if test x$enable_haiku = xno; then + found_haiku=no + fi + + if test x$found_haiku = xyes; then + + if test x$enable_haiku = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected Haiku output plugin" >&5 +$as_echo "$as_me: auto-detected Haiku output plugin" >&6;} + enable_haiku=yes + fi + + else + + if test x$enable_haiku = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Haiku headers not found -- disabling Haiku output plugin" >&5 +$as_echo "$as_me: WARNING: Haiku headers not found -- disabling Haiku output plugin" >&2;} + enable_haiku=no + elif test x$enable_haiku = xyes; then + as_fn_error $? "Haiku output plugin: Haiku headers not found" "$LINENO" 5 + fi + + fi + + + + + + if test x$enable_haiku = xyes; then + ENABLE_HAIKU_TRUE= + ENABLE_HAIKU_FALSE='#' +else + ENABLE_HAIKU_TRUE='#' + ENABLE_HAIKU_FALSE= +fi + + if test x$enable_haiku = xyes; then + +$as_echo "#define ENABLE_HAIKU 1" >>confdefs.h + + fi + + if test x$enable_httpd_output = xauto; then # handle HTTPD auto-detection: disable if no encoder is @@ -15883,12 +16848,7 @@ fi fi -if test x$enable_httpd_output = xyes; then - -$as_echo "#define ENABLE_HTTPD_OUTPUT 1" >>confdefs.h - -fi - if test x$enable_httpd_output = xyes; then + if test x$enable_httpd_output = xyes; then ENABLE_HTTPD_OUTPUT_TRUE= ENABLE_HTTPD_OUTPUT_FALSE='#' else @@ -15896,9 +16856,27 @@ ENABLE_HTTPD_OUTPUT_FALSE= fi + if test x$enable_httpd_output = xyes; then + +$as_echo "#define ENABLE_HTTPD_OUTPUT 1" >>confdefs.h + + fi + + + + # Check whether --enable-jack was given. +if test "${enable_jack+set}" = set; then : + enableval=$enable_jack; +else + enable_jack=auto +fi + + + + - if eval "test x`echo '$'enable_jack` != xno"; then + if test x$enable_jack != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JACK" >&5 @@ -15958,65 +16936,64 @@ # Put the nasty error message in config.log where it belongs echo "$JACK_PKG_ERRORS" >&5 - eval "found_jack=no" + found_jack=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_jack=no" + found_jack=no else JACK_CFLAGS=$pkg_cv_JACK_CFLAGS JACK_LIBS=$pkg_cv_JACK_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_jack=yes" + found_jack=yes fi fi - - name="jack" - var="enable_jack" - found="found_$name" - feature="JACK output plugin" - msg="libjack not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_jack = xno; then + found_jack=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_jack = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_jack = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected JACK output plugin" >&5 +$as_echo "$as_me: auto-detected JACK output plugin" >&6;} + enable_jack=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_jack = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libjack not found -- disabling JACK output plugin" >&5 +$as_echo "$as_me: WARNING: libjack not found -- disabling JACK output plugin" >&2;} + enable_jack=no + elif test x$enable_jack = xyes; then + as_fn_error $? "JACK output plugin: libjack not found" "$LINENO" 5 fi fi -if test x$enable_jack = xyes; then -$as_echo "#define HAVE_JACK 1" >>confdefs.h + + if test x$enable_jack = xyes; then + ENABLE_JACK_TRUE= + ENABLE_JACK_FALSE='#' +else + ENABLE_JACK_TRUE='#' + ENABLE_JACK_FALSE= fi + if test x$enable_jack = xyes; then + +$as_echo "#define ENABLE_JACK 1" >>confdefs.h + + fi + + + if test x$enable_jack = xyes; then # check whether jack_set_info_function() is available old_LIBS=$LIBS @@ -16037,17 +17014,21 @@ LIBS=$old_LIBS fi - if test x$enable_jack = xyes; then - HAVE_JACK_TRUE= - HAVE_JACK_FALSE='#' + + + # Check whether --enable-ao was given. +if test "${enable_ao+set}" = set; then : + enableval=$enable_ao; else - HAVE_JACK_TRUE='#' - HAVE_JACK_FALSE= + enable_ao=auto fi - if eval "test x`echo '$'enable_ao` != xno"; then + + + + if test x$enable_ao != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AO" >&5 @@ -16107,73 +17088,63 @@ # Put the nasty error message in config.log where it belongs echo "$AO_PKG_ERRORS" >&5 - eval "found_ao=no" + found_ao=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_ao=no" + found_ao=no else AO_CFLAGS=$pkg_cv_AO_CFLAGS AO_LIBS=$pkg_cv_AO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_ao=yes" + found_ao=yes fi fi - - name="ao" - var="enable_ao" - found="found_$name" - feature="libao output plugin" - msg="libao not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_ao = xno; then + found_ao=no fi - if eval "test x`echo '$'$found` = xyes"; then - - var="enable_$name" - feature="$feature" + if test x$found_ao = xyes; then - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_ao = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected libao output plugin" >&5 +$as_echo "$as_me: auto-detected libao output plugin" >&6;} + enable_ao=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_ao = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libao not found -- disabling libao output plugin" >&5 +$as_echo "$as_me: WARNING: libao not found -- disabling libao output plugin" >&2;} + enable_ao=no + elif test x$enable_ao = xyes; then + as_fn_error $? "libao output plugin: libao not found" "$LINENO" 5 fi fi -if test x$enable_ao = xyes; then -$as_echo "#define HAVE_AO 1" >>confdefs.h -fi - if test x$enable_ao = xyes; then - HAVE_AO_TRUE= - HAVE_AO_FALSE='#' + if test x$enable_ao = xyes; then + ENABLE_AO_TRUE= + ENABLE_AO_FALSE='#' else - HAVE_AO_TRUE='#' - HAVE_AO_FALSE= + ENABLE_AO_TRUE='#' + ENABLE_AO_FALSE= fi + if test x$enable_ao = xyes; then + +$as_echo "#define ENABLE_AO 1" >>confdefs.h + + fi + + OPENAL_CFLAGS="" @@ -16200,39 +17171,26 @@ fi - name="openal" - var="enable_openal" - found="found_$name" - feature="OpenAL output plugin" - msg="OpenAL not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_openal = xno; then + found_openal=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_openal = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_openal = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected OpenAL output plugin" >&5 +$as_echo "$as_me: auto-detected OpenAL output plugin" >&6;} + enable_openal=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_openal = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenAL not found -- disabling OpenAL output plugin" >&5 +$as_echo "$as_me: WARNING: OpenAL not found -- disabling OpenAL output plugin" >&2;} + enable_openal=no + elif test x$enable_openal = xyes; then + as_fn_error $? "OpenAL output plugin: OpenAL not found" "$LINENO" 5 fi fi @@ -16243,7 +17201,8 @@ fi else - if eval "test x`echo '$'enable_openal` != xno"; then + + if test x$enable_openal != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENAL" >&5 @@ -16303,68 +17262,49 @@ # Put the nasty error message in config.log where it belongs echo "$OPENAL_PKG_ERRORS" >&5 - eval "found_openal=no" + found_openal=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_openal=no" + found_openal=no else OPENAL_CFLAGS=$pkg_cv_OPENAL_CFLAGS OPENAL_LIBS=$pkg_cv_OPENAL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_openal=yes" + found_openal=yes fi fi - - name="openal" - var="enable_openal" - found="found_$name" - feature="OpenAL output plugin" - msg="OpenAL not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_openal = xno; then + found_openal=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_openal = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_openal = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected OpenAL output plugin" >&5 +$as_echo "$as_me: auto-detected OpenAL output plugin" >&6;} + enable_openal=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_openal = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenAL not found -- disabling OpenAL output plugin" >&5 +$as_echo "$as_me: WARNING: OpenAL not found -- disabling OpenAL output plugin" >&2;} + enable_openal=no + elif test x$enable_openal = xyes; then + as_fn_error $? "OpenAL output plugin: OpenAL not found" "$LINENO" 5 fi fi -fi - -if test x$enable_openal = xyes; then - -$as_echo "#define HAVE_OPENAL 1" >>confdefs.h fi - if test x$enable_openal = xyes; then + if test x$enable_openal = xyes; then HAVE_OPENAL_TRUE= HAVE_OPENAL_FALSE='#' else @@ -16372,13 +17312,16 @@ HAVE_OPENAL_FALSE= fi + if test x$enable_openal = xyes; then + +$as_echo "#define HAVE_OPENAL 1" >>confdefs.h + + fi if test x$enable_oss = xyes; then ac_fn_c_check_header_mongrel "$LINENO" "sys/soundcard.h" "ac_cv_header_sys_soundcard_h" "$ac_includes_default" if test "x$ac_cv_header_sys_soundcard_h" = xyes; then : - enable_oss=yes; -$as_echo "#define HAVE_OSS 1" >>confdefs.h - + enable_oss=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Soundcard headers not found -- disabling OSS support" >&5 $as_echo "$as_me: WARNING: Soundcard headers not found -- disabling OSS support" >&2;}; @@ -16388,7 +17331,7 @@ fi - if test x$enable_oss = xyes; then + if test x$enable_oss = xyes; then HAVE_OSS_TRUE= HAVE_OSS_FALSE='#' else @@ -16396,6 +17339,11 @@ HAVE_OSS_FALSE= fi + if test x$enable_oss = xyes; then + +$as_echo "#define HAVE_OSS 1" >>confdefs.h + + fi if test x$enable_osx = xyes; then @@ -16413,12 +17361,7 @@ fi -if test x$enable_pipe_output = xyes; then - -$as_echo "#define ENABLE_PIPE_OUTPUT 1" >>confdefs.h - -fi - if test x$enable_pipe_output = xyes; then + if test x$enable_pipe_output = xyes; then ENABLE_PIPE_OUTPUT_TRUE= ENABLE_PIPE_OUTPUT_FALSE='#' else @@ -16426,9 +17369,27 @@ ENABLE_PIPE_OUTPUT_FALSE= fi + if test x$enable_pipe_output = xyes; then + +$as_echo "#define ENABLE_PIPE_OUTPUT 1" >>confdefs.h + + fi + + + + # Check whether --enable-pulse was given. +if test "${enable_pulse+set}" = set; then : + enableval=$enable_pulse; +else + enable_pulse=auto +fi + + + + - if eval "test x`echo '$'enable_pulse` != xno"; then + if test x$enable_pulse != xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PULSE" >&5 @@ -16488,73 +17449,63 @@ # Put the nasty error message in config.log where it belongs echo "$PULSE_PKG_ERRORS" >&5 - eval "found_pulse=no" + found_pulse=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - eval "found_pulse=no" + found_pulse=no else PULSE_CFLAGS=$pkg_cv_PULSE_CFLAGS PULSE_LIBS=$pkg_cv_PULSE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - eval "found_pulse=yes" + found_pulse=yes fi fi - - name="pulse" - var="enable_pulse" - found="found_$name" - feature="PulseAudio output plugin" - msg="libpulse not found" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$enable_pulse = xno; then + found_pulse=no fi - if eval "test x`echo '$'$found` = xyes"; then + if test x$found_pulse = xyes; then - var="enable_$name" - feature="$feature" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected $feature" >&5 -$as_echo "$as_me: auto-detected $feature" >&6;} - eval "$var=yes" + if test x$enable_pulse = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: auto-detected PulseAudio output plugin" >&5 +$as_echo "$as_me: auto-detected PulseAudio output plugin" >&6;} + enable_pulse=yes fi else - var="enable_$name" - feature="$feature" - msg="$msg" - - if eval "test x`echo '$'$var` = xauto"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg -- disabling $feature" >&5 -$as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;} - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - as_fn_error $? "$feature: $msg" "$LINENO" 5 + if test x$enable_pulse = xauto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libpulse not found -- disabling PulseAudio output plugin" >&5 +$as_echo "$as_me: WARNING: libpulse not found -- disabling PulseAudio output plugin" >&2;} + enable_pulse=no + elif test x$enable_pulse = xyes; then + as_fn_error $? "PulseAudio output plugin: libpulse not found" "$LINENO" 5 fi fi -if test x$enable_pulse = xyes; then -$as_echo "#define HAVE_PULSE 1" >>confdefs.h -fi - if test x$enable_pulse = xyes; then - HAVE_PULSE_TRUE= - HAVE_PULSE_FALSE='#' + if test x$enable_pulse = xyes; then + ENABLE_PULSE_TRUE= + ENABLE_PULSE_FALSE='#' else - HAVE_PULSE_TRUE='#' - HAVE_PULSE_FALSE= + ENABLE_PULSE_TRUE='#' + ENABLE_PULSE_FALSE= fi + if test x$enable_pulse = xyes; then + +$as_echo "#define ENABLE_PULSE 1" >>confdefs.h + + fi + + if test x$enable_recorder_output = xauto; then # handle recorder auto-detection: disable if no encoder is @@ -16568,12 +17519,7 @@ fi fi -if test x$enable_recorder_output = xyes; then - -$as_echo "#define ENABLE_RECORDER_OUTPUT 1" >>confdefs.h - -fi - if test x$enable_recorder_output = xyes; then + if test x$enable_recorder_output = xyes; then ENABLE_RECORDER_OUTPUT_TRUE= ENABLE_RECORDER_OUTPUT_FALSE='#' else @@ -16581,6 +17527,11 @@ ENABLE_RECORDER_OUTPUT_FALSE= fi + if test x$enable_recorder_output = xyes; then + +$as_echo "#define ENABLE_RECORDER_OUTPUT 1" >>confdefs.h + + fi if test x$enable_shout = xauto; then # handle shout auto-detection: disable if no encoder is @@ -16594,12 +17545,7 @@ fi fi -if test x$enable_shout = xyes; then - -$as_echo "#define HAVE_SHOUT 1" >>confdefs.h - -fi - if test x$enable_shout = xyes; then + if test x$enable_shout = xyes; then HAVE_SHOUT_TRUE= HAVE_SHOUT_FALSE='#' else @@ -16607,15 +17553,14 @@ HAVE_SHOUT_FALSE= fi + if test x$enable_shout = xyes; then +$as_echo "#define HAVE_SHOUT 1" >>confdefs.h -if test x$enable_solaris_output = xyes; then - -$as_echo "#define ENABLE_SOLARIS_OUTPUT 1" >>confdefs.h + fi -fi - if test x$enable_solaris_output = xyes; then + if test x$enable_solaris_output = xyes; then ENABLE_SOLARIS_OUTPUT_TRUE= ENABLE_SOLARIS_OUTPUT_FALSE='#' else @@ -16623,6 +17568,11 @@ ENABLE_SOLARIS_OUTPUT_FALSE= fi + if test x$enable_solaris_output = xyes; then + +$as_echo "#define ENABLE_SOLARIS_OUTPUT 1" >>confdefs.h + + fi if test "x$host_is_windows" = xyes; then @@ -16644,6 +17594,108 @@ fi + +have_ogg=no +if test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_opus = xyes || test x$enable_vorbis_encoder = xyes; then + have_ogg=yes +fi + +have_xiph=no +if test x$have_ogg = xyes || test x$enable_flac = xyes || test x$enable_flac_encoder = xyes; then + have_xiph=yes +fi + +if test x$have_ogg = xyes; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OGG" >&5 +$as_echo_n "checking for OGG... " >&6; } + +if test -n "$OGG_CFLAGS"; then + pkg_cv_OGG_CFLAGS="$OGG_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5 + ($PKG_CONFIG --exists --print-errors "ogg") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OGG_CFLAGS=`$PKG_CONFIG --cflags "ogg" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OGG_LIBS"; then + pkg_cv_OGG_LIBS="$OGG_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ogg\""; } >&5 + ($PKG_CONFIG --exists --print-errors "ogg") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OGG_LIBS=`$PKG_CONFIG --libs "ogg" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + OGG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ogg" 2>&1` + else + OGG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ogg" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OGG_PKG_ERRORS" >&5 + + as_fn_error $? "libogg not found" "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "libogg not found" "$LINENO" 5 +else + OGG_CFLAGS=$pkg_cv_OGG_CFLAGS + OGG_LIBS=$pkg_cv_OGG_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +fi + + if test x$have_ogg = xyes; then + HAVE_OGG_TRUE= + HAVE_OGG_FALSE='#' +else + HAVE_OGG_TRUE='#' + HAVE_OGG_FALSE= +fi + + if test x$have_xiph = xyes; then + HAVE_XIPH_TRUE= + HAVE_XIPH_FALSE='#' +else + HAVE_XIPH_TRUE='#' + HAVE_XIPH_FALSE= +fi + + if test x$enable_documentation = xyes; then # Extract the first word of "xmlto", so it can be a program name with args. set dummy xmlto; ac_word=$2 @@ -16873,27 +17925,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -16938,27 +18000,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17003,164 +18075,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 - (: CFLAGS already contains $flag) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac -else - CFLAGS="$flag" -fi - -else - : -fi - -done - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - - -for flag in -fvisibility=hidden; do - as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags__$flag" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5 -$as_echo_n "checking whether C++ compiler accepts $flag... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CXXFLAGS - CXXFLAGS="$CXXFLAGS $flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : -int -main () -{ +if ${CFLAGS+:} false; then : - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 - (: CXXFLAGS already contains $flag) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 + (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac -else - CXXFLAGS="$flag" -fi - -else - : -fi - -done - - - - - -for flag in -fno-threadsafe-statics; do - as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags__$flag" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5 -$as_echo_n "checking whether C++ compiler accepts $flag... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CXXFLAGS - CXXFLAGS="$CXXFLAGS $flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ + test $ac_status = 0; } ;; #( + *) : - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 - (: CXXFLAGS already contains $flag) 2>&5 + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + ;; +esac + +else + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac -else - CXXFLAGS="$flag" + fi else @@ -17170,10 +18115,17 @@ done +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + -for flag in -fmerge-all-constants; do +for flag in -fvisibility=hidden; do as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5 $as_echo_n "checking whether C++ compiler accepts $flag... " >&6; } @@ -17205,27 +18157,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17235,12 +18197,10 @@ done -if test x$no_exceptions = xyes; then - -for flag in -fno-exceptions; do +for flag in -fno-threadsafe-statics; do as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5 $as_echo_n "checking whether C++ compiler accepts $flag... " >&6; } @@ -17272,27 +18232,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17305,7 +18275,7 @@ -for flag in -fno-rtti; do +for flag in -fmerge-all-constants; do as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5 $as_echo_n "checking whether C++ compiler accepts $flag... " >&6; } @@ -17337,27 +18307,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17366,8 +18346,6 @@ done -fi - @@ -17404,27 +18382,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17469,27 +18457,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17544,27 +18542,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17609,27 +18617,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17681,27 +18699,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17746,27 +18774,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17819,27 +18857,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${LDFLAGS+:} false; then : - case " $LDFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${LDFLAGS+:} false; then : + + case " $LDFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains \$flag"; } >&5 (: LDFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS \$flag\""; } >&5 - (: LDFLAGS="$LDFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append LDFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5 + (: LDFLAGS="$LDFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - LDFLAGS="$LDFLAGS $flag" - ;; - esac + ;; +esac + else - LDFLAGS="$flag" + + LDFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5 + (: LDFLAGS="$LDFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17888,27 +18936,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -17953,27 +19011,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18018,27 +19086,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18083,27 +19161,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + ;; +esac + +else + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac -else - CFLAGS="$flag" + fi else @@ -18148,27 +19236,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18213,27 +19311,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18278,27 +19386,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18343,27 +19461,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18408,27 +19536,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18480,27 +19618,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18545,27 +19693,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18610,27 +19768,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18675,27 +19843,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18740,27 +19918,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18805,27 +19993,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18870,27 +20068,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18935,27 +20143,37 @@ eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CXXFLAGS+:} false; then : - case " $CXXFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CXXFLAGS+:} false; then : + + case " $CXXFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS already contains \$flag"; } >&5 (: CXXFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS \$flag\""; } >&5 - (: CXXFLAGS="$CXXFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CXXFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CXXFLAGS="$CXXFLAGS $flag" - ;; - esac + ;; +esac + else - CXXFLAGS="$flag" + + CXXFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CXXFLAGS=\"\$CXXFLAGS\""; } >&5 + (: CXXFLAGS="$CXXFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -18977,17 +20195,8 @@ printf '\nArchive support:\n\t' - num=`expr bzip2 : 'with'` - if test "$num" != "0"; then - var="`echo '$'bzip2`" - else - var="`echo '$'enable_bzip2`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_bzip2 = xyes; then printf '+' else printf '-' @@ -18995,17 +20204,8 @@ printf '%s) ' "bzip2" - num=`expr iso9660 : 'with'` - if test "$num" != "0"; then - var="`echo '$'iso9660`" - else - var="`echo '$'enable_iso9660`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_iso9660 = xyes; then printf '+' else printf '-' @@ -19013,17 +20213,8 @@ printf '%s) ' "ISO9660" - num=`expr zzip : 'with'` - if test "$num" != "0"; then - var="`echo '$'zzip`" - else - var="`echo '$'enable_zzip`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_zzip = xyes; then printf '+' else printf '-' @@ -19034,17 +20225,8 @@ if test x$with_zeroconf != xno; then printf '\nAutodiscovery support:\n\t' - num=`expr avahi : 'with'` - if test "$num" != "0"; then - var="`echo '$'avahi`" - else - var="`echo '$'enable_avahi`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_avahi = xyes; then printf '+' else printf '-' @@ -19052,17 +20234,8 @@ printf '%s) ' "Avahi" - num=`expr bonjour : 'with'` - if test "$num" != "0"; then - var="`echo '$'bonjour`" - else - var="`echo '$'enable_bonjour`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_bonjour = xyes; then printf '+' else printf '-' @@ -19073,17 +20246,8 @@ printf '\nClient support:\n\t' - num=`expr ipv6 : 'with'` - if test "$num" != "0"; then - var="`echo '$'ipv6`" - else - var="`echo '$'enable_ipv6`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_ipv6 = xyes; then printf '+' else printf '-' @@ -19091,17 +20255,8 @@ printf '%s) ' ""IPv6"" - num=`expr tcp : 'with'` - if test "$num" != "0"; then - var="`echo '$'tcp`" - else - var="`echo '$'enable_tcp`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_tcp = xyes; then printf '+' else printf '-' @@ -19109,17 +20264,8 @@ printf '%s) ' ""TCP"" - num=`expr un : 'with'` - if test "$num" != "0"; then - var="`echo '$'un`" - else - var="`echo '$'enable_un`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_un = xyes; then printf '+' else printf '-' @@ -19129,17 +20275,8 @@ printf '\nStorage support:\n\t' - num=`expr nfs : 'with'` - if test "$num" != "0"; then - var="`echo '$'nfs`" - else - var="`echo '$'enable_nfs`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_nfs = xyes; then printf '+' else printf '-' @@ -19147,17 +20284,8 @@ printf '%s) ' "NFS" - num=`expr smbclient : 'with'` - if test "$num" != "0"; then - var="`echo '$'smbclient`" - else - var="`echo '$'enable_smbclient`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_smbclient = xyes; then printf '+' else printf '-' @@ -19167,17 +20295,8 @@ printf '\nFile format support:\n\t' - num=`expr aac : 'with'` - if test "$num" != "0"; then - var="`echo '$'aac`" - else - var="`echo '$'enable_aac`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_aac = xyes; then printf '+' else printf '-' @@ -19185,17 +20304,8 @@ printf '%s) ' "AAC" - num=`expr adplug : 'with'` - if test "$num" != "0"; then - var="`echo '$'adplug`" - else - var="`echo '$'enable_adplug`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_adplug = xyes; then printf '+' else printf '-' @@ -19203,17 +20313,8 @@ printf '%s) ' "AdPlug" - num=`expr dsd : 'with'` - if test "$num" != "0"; then - var="`echo '$'dsd`" - else - var="`echo '$'enable_dsd`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_dsd = xyes; then printf '+' else printf '-' @@ -19221,17 +20322,8 @@ printf '%s) ' "DSD" - num=`expr sidplay : 'with'` - if test "$num" != "0"; then - var="`echo '$'sidplay`" - else - var="`echo '$'enable_sidplay`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_sidplay = xyes; then printf '+' else printf '-' @@ -19239,17 +20331,8 @@ printf '%s) ' "C64 SID" - num=`expr ffmpeg : 'with'` - if test "$num" != "0"; then - var="`echo '$'ffmpeg`" - else - var="`echo '$'enable_ffmpeg`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_ffmpeg = xyes; then printf '+' else printf '-' @@ -19257,17 +20340,8 @@ printf '%s) ' "FFMPEG" - num=`expr flac : 'with'` - if test "$num" != "0"; then - var="`echo '$'flac`" - else - var="`echo '$'enable_flac`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_flac = xyes; then printf '+' else printf '-' @@ -19275,17 +20349,8 @@ printf '%s) ' "FLAC" - num=`expr fluidsynth : 'with'` - if test "$num" != "0"; then - var="`echo '$'fluidsynth`" - else - var="`echo '$'enable_fluidsynth`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_fluidsynth = xyes; then printf '+' else printf '-' @@ -19293,17 +20358,8 @@ printf '%s) ' "FluidSynth" - num=`expr gme : 'with'` - if test "$num" != "0"; then - var="`echo '$'gme`" - else - var="`echo '$'enable_gme`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_gme = xyes; then printf '+' else printf '-' @@ -19312,17 +20368,8 @@ printf '\n\t' - num=`expr sndfile : 'with'` - if test "$num" != "0"; then - var="`echo '$'sndfile`" - else - var="`echo '$'enable_sndfile`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_sndfile = xyes; then printf '+' else printf '-' @@ -19330,17 +20377,8 @@ printf '%s) ' "libsndfile" - num=`expr mikmod : 'with'` - if test "$num" != "0"; then - var="`echo '$'mikmod`" - else - var="`echo '$'enable_mikmod`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_mikmod = xyes; then printf '+' else printf '-' @@ -19348,17 +20386,8 @@ printf '%s) ' "MikMod" - num=`expr modplug : 'with'` - if test "$num" != "0"; then - var="`echo '$'modplug`" - else - var="`echo '$'enable_modplug`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_modplug = xyes; then printf '+' else printf '-' @@ -19366,17 +20395,8 @@ printf '%s) ' "MODPLUG" - num=`expr mad : 'with'` - if test "$num" != "0"; then - var="`echo '$'mad`" - else - var="`echo '$'enable_mad`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_mad = xyes; then printf '+' else printf '-' @@ -19384,17 +20404,8 @@ printf '%s) ' "MAD" - num=`expr mpg123 : 'with'` - if test "$num" != "0"; then - var="`echo '$'mpg123`" - else - var="`echo '$'enable_mpg123`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_mpg123 = xyes; then printf '+' else printf '-' @@ -19402,17 +20413,8 @@ printf '%s) ' "MPG123" - num=`expr mpc : 'with'` - if test "$num" != "0"; then - var="`echo '$'mpc`" - else - var="`echo '$'enable_mpc`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_mpc = xyes; then printf '+' else printf '-' @@ -19421,17 +20423,8 @@ printf '\n\t' - num=`expr opus : 'with'` - if test "$num" != "0"; then - var="`echo '$'opus`" - else - var="`echo '$'enable_opus`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_opus = xyes; then printf '+' else printf '-' @@ -19439,17 +20432,8 @@ printf '%s) ' "Opus" - num=`expr tremor : 'with'` - if test "$num" != "0"; then - var="`echo '$'tremor`" - else - var="`echo '$'enable_tremor`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_tremor = xyes; then printf '+' else printf '-' @@ -19457,17 +20441,8 @@ printf '%s) ' "OggTremor" - num=`expr vorbis : 'with'` - if test "$num" != "0"; then - var="`echo '$'vorbis`" - else - var="`echo '$'enable_vorbis`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_vorbis = xyes; then printf '+' else printf '-' @@ -19475,17 +20450,8 @@ printf '%s) ' "OggVorbis" - num=`expr audiofile : 'with'` - if test "$num" != "0"; then - var="`echo '$'audiofile`" - else - var="`echo '$'enable_audiofile`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_audiofile = xyes; then printf '+' else printf '-' @@ -19493,17 +20459,8 @@ printf '%s) ' "WAVE" - num=`expr wavpack : 'with'` - if test "$num" != "0"; then - var="`echo '$'wavpack`" - else - var="`echo '$'enable_wavpack`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_wavpack = xyes; then printf '+' else printf '-' @@ -19511,17 +20468,8 @@ printf '%s) ' "WavPack" - num=`expr wildmidi : 'with'` - if test "$num" != "0"; then - var="`echo '$'wildmidi`" - else - var="`echo '$'enable_wildmidi`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_wildmidi = xyes; then printf '+' else printf '-' @@ -19531,17 +20479,8 @@ printf '\nOther features:\n\t' - num=`expr lsr : 'with'` - if test "$num" != "0"; then - var="`echo '$'lsr`" - else - var="`echo '$'enable_lsr`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_lsr = xyes; then printf '+' else printf '-' @@ -19549,17 +20488,8 @@ printf '%s) ' "libsamplerate" - num=`expr soxr : 'with'` - if test "$num" != "0"; then - var="`echo '$'soxr`" - else - var="`echo '$'enable_soxr`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_soxr = xyes; then printf '+' else printf '-' @@ -19567,17 +20497,8 @@ printf '%s) ' "libsoxr" - num=`expr libmpdclient : 'with'` - if test "$num" != "0"; then - var="`echo '$'libmpdclient`" - else - var="`echo '$'enable_libmpdclient`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_libmpdclient = xyes; then printf '+' else printf '-' @@ -19585,17 +20506,8 @@ printf '%s) ' "libmpdclient" - num=`expr inotify : 'with'` - if test "$num" != "0"; then - var="`echo '$'inotify`" - else - var="`echo '$'enable_inotify`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_inotify = xyes; then printf '+' else printf '-' @@ -19603,17 +20515,8 @@ printf '%s) ' "inotify" - num=`expr sqlite : 'with'` - if test "$num" != "0"; then - var="`echo '$'sqlite`" - else - var="`echo '$'enable_sqlite`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_sqlite = xyes; then printf '+' else printf '-' @@ -19623,17 +20526,8 @@ printf '\nMetadata support:\n\t' - num=`expr id3 : 'with'` - if test "$num" != "0"; then - var="`echo '$'id3`" - else - var="`echo '$'enable_id3`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_id3 = xyes; then printf '+' else printf '-' @@ -19643,17 +20537,8 @@ printf '\nPlayback support:\n\t' - num=`expr alsa : 'with'` - if test "$num" != "0"; then - var="`echo '$'alsa`" - else - var="`echo '$'enable_alsa`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_alsa = xyes; then printf '+' else printf '-' @@ -19661,17 +20546,8 @@ printf '%s) ' "ALSA" - num=`expr fifo : 'with'` - if test "$num" != "0"; then - var="`echo '$'fifo`" - else - var="`echo '$'enable_fifo`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_fifo = xyes; then printf '+' else printf '-' @@ -19679,17 +20555,17 @@ printf '%s) ' "FIFO" - num=`expr recorder_output : 'with'` - if test "$num" != "0"; then - var="`echo '$'recorder_output`" + printf '(' + if test x$enable_sndio = xyes; then + printf '+' else - var="`echo '$'enable_recorder_output`" + printf '-' fi + printf '%s) ' "SNDIO" + printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_recorder_output = xyes; then printf '+' else printf '-' @@ -19697,17 +20573,17 @@ printf '%s) ' "File Recorder" - num=`expr httpd_output : 'with'` - if test "$num" != "0"; then - var="`echo '$'httpd_output`" + printf '(' + if test x$enable_haiku = xyes; then + printf '+' else - var="`echo '$'enable_httpd_output`" + printf '-' fi + printf '%s) ' "Haiku" + printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_httpd_output = xyes; then printf '+' else printf '-' @@ -19715,17 +20591,8 @@ printf '%s) ' "HTTP Daemon" - num=`expr jack : 'with'` - if test "$num" != "0"; then - var="`echo '$'jack`" - else - var="`echo '$'enable_jack`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_jack = xyes; then printf '+' else printf '-' @@ -19734,17 +20601,8 @@ printf '\n\t' - num=`expr ao : 'with'` - if test "$num" != "0"; then - var="`echo '$'ao`" - else - var="`echo '$'enable_ao`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_ao = xyes; then printf '+' else printf '-' @@ -19752,17 +20610,8 @@ printf '%s) ' "libao" - num=`expr oss : 'with'` - if test "$num" != "0"; then - var="`echo '$'oss`" - else - var="`echo '$'enable_oss`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_oss = xyes; then printf '+' else printf '-' @@ -19770,17 +20619,8 @@ printf '%s) ' "OSS" - num=`expr openal : 'with'` - if test "$num" != "0"; then - var="`echo '$'openal`" - else - var="`echo '$'enable_openal`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_openal = xyes; then printf '+' else printf '-' @@ -19788,17 +20628,8 @@ printf '%s) ' "OpenAL" - num=`expr osx : 'with'` - if test "$num" != "0"; then - var="`echo '$'osx`" - else - var="`echo '$'enable_osx`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_osx = xyes; then printf '+' else printf '-' @@ -19806,17 +20637,8 @@ printf '%s) ' "OS X" - num=`expr pipe_output : 'with'` - if test "$num" != "0"; then - var="`echo '$'pipe_output`" - else - var="`echo '$'enable_pipe_output`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_pipe_output = xyes; then printf '+' else printf '-' @@ -19825,17 +20647,8 @@ printf '\n\t' - num=`expr pulse : 'with'` - if test "$num" != "0"; then - var="`echo '$'pulse`" - else - var="`echo '$'enable_pulse`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_pulse = xyes; then printf '+' else printf '-' @@ -19843,17 +20656,8 @@ printf '%s) ' "PulseAudio" - num=`expr roar : 'with'` - if test "$num" != "0"; then - var="`echo '$'roar`" - else - var="`echo '$'enable_roar`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_roar = xyes; then printf '+' else printf '-' @@ -19861,17 +20665,8 @@ printf '%s) ' "ROAR" - num=`expr shout : 'with'` - if test "$num" != "0"; then - var="`echo '$'shout`" - else - var="`echo '$'enable_shout`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_shout = xyes; then printf '+' else printf '-' @@ -19879,17 +20674,8 @@ printf '%s) ' "SHOUTcast" - num=`expr solaris_output : 'with'` - if test "$num" != "0"; then - var="`echo '$'solaris_output`" - else - var="`echo '$'enable_solaris_output`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_solaris_output = xyes; then printf '+' else printf '-' @@ -19897,17 +20683,8 @@ printf '%s) ' "Solaris" - num=`expr winmm_output : 'with'` - if test "$num" != "0"; then - var="`echo '$'winmm_output`" - else - var="`echo '$'enable_winmm_output`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_winmm_output = xyes; then printf '+' else printf '-' @@ -19921,17 +20698,8 @@ test x$enable_httpd_output = xyes; then printf '\nStreaming encoder support:\n\t' - num=`expr flac_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'flac_encoder`" - else - var="`echo '$'enable_flac_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_flac_encoder = xyes; then printf '+' else printf '-' @@ -19939,17 +20707,8 @@ printf '%s) ' "FLAC" - num=`expr lame_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'lame_encoder`" - else - var="`echo '$'enable_lame_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_lame_encoder = xyes; then printf '+' else printf '-' @@ -19957,17 +20716,8 @@ printf '%s) ' "LAME" - num=`expr shine_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'shine_encoder`" - else - var="`echo '$'enable_shine_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_shine_encoder = xyes; then printf '+' else printf '-' @@ -19975,17 +20725,8 @@ printf '%s) ' "Shine" - num=`expr vorbis_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'vorbis_encoder`" - else - var="`echo '$'enable_vorbis_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_vorbis_encoder = xyes; then printf '+' else printf '-' @@ -19993,17 +20734,8 @@ printf '%s) ' "Ogg Vorbis" - num=`expr opus : 'with'` - if test "$num" != "0"; then - var="`echo '$'opus`" - else - var="`echo '$'enable_opus`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_opus = xyes; then printf '+' else printf '-' @@ -20011,17 +20743,8 @@ printf '%s) ' "Opus" - num=`expr twolame_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'twolame_encoder`" - else - var="`echo '$'enable_twolame_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_twolame_encoder = xyes; then printf '+' else printf '-' @@ -20029,17 +20752,8 @@ printf '%s) ' "TwoLAME" - num=`expr wave_encoder : 'with'` - if test "$num" != "0"; then - var="`echo '$'wave_encoder`" - else - var="`echo '$'enable_wave_encoder`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_wave_encoder = xyes; then printf '+' else printf '-' @@ -20050,17 +20764,8 @@ printf '\nStreaming support:\n\t' - num=`expr cdio_paranoia : 'with'` - if test "$num" != "0"; then - var="`echo '$'cdio_paranoia`" - else - var="`echo '$'enable_cdio_paranoia`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_cdio_paranoia = xyes; then printf '+' else printf '-' @@ -20068,17 +20773,8 @@ printf '%s) ' "CDIO_PARANOIA" - num=`expr curl : 'with'` - if test "$num" != "0"; then - var="`echo '$'curl`" - else - var="`echo '$'enable_curl`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_curl = xyes; then printf '+' else printf '-' @@ -20086,17 +20782,8 @@ printf '%s) ' "CURL" - num=`expr smbclient : 'with'` - if test "$num" != "0"; then - var="`echo '$'smbclient`" - else - var="`echo '$'enable_smbclient`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_smbclient = xyes; then printf '+' else printf '-' @@ -20104,17 +20791,8 @@ printf '%s) ' "SMBCLIENT" - num=`expr soundcloud : 'with'` - if test "$num" != "0"; then - var="`echo '$'soundcloud`" - else - var="`echo '$'enable_soundcloud`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_soundcloud = xyes; then printf '+' else printf '-' @@ -20123,17 +20801,8 @@ printf '\n\t' - num=`expr mms : 'with'` - if test "$num" != "0"; then - var="`echo '$'mms`" - else - var="`echo '$'enable_mms`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "" && eval "test x$var = x"; then + if test x$enable_mms = xyes; then printf '+' else printf '-' @@ -20313,32 +20982,32 @@ as_fn_error $? "conditional \"ENABLE_DATABASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ICU_TRUE}" && test -z "${HAVE_ICU_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ICU\" was never defined. +if test -z "${ENABLE_DAEMON_TRUE}" && test -z "${ENABLE_DAEMON_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_DAEMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_GLIB_TRUE}" && test -z "${HAVE_GLIB_FALSE}"; then - as_fn_error $? "conditional \"HAVE_GLIB\" was never defined. +if test -z "${HAVE_ICU_TRUE}" && test -z "${HAVE_ICU_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ICU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SYSTEMD_DAEMON_TRUE}" && test -z "${ENABLE_SYSTEMD_DAEMON_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SYSTEMD_DAEMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_LIBMPDCLIENT_TRUE}" && test -z "${HAVE_LIBMPDCLIENT_FALSE}"; then - as_fn_error $? "conditional \"HAVE_LIBMPDCLIENT\" was never defined. +if test -z "${ENABLE_LIBMPDCLIENT_TRUE}" && test -z "${ENABLE_LIBMPDCLIENT_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_LIBMPDCLIENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_EXPAT_TRUE}" && test -z "${HAVE_EXPAT_FALSE}"; then - as_fn_error $? "conditional \"HAVE_EXPAT\" was never defined. +if test -z "${ENABLE_EXPAT_TRUE}" && test -z "${ENABLE_EXPAT_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_EXPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_INOTIFY_TRUE}" && test -z "${ENABLE_INOTIFY_FALSE}"; then as_fn_error $? "conditional \"ENABLE_INOTIFY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ID3TAG_TRUE}" && test -z "${HAVE_ID3TAG_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ID3TAG\" was never defined. +if test -z "${ENABLE_ID3TAG_TRUE}" && test -z "${ENABLE_ID3TAG_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ID3TAG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_TRUE}" && test -z "${HAVE_AVAHI_FALSE}"; then @@ -20357,12 +21026,12 @@ as_fn_error $? "conditional \"ENABLE_SQLITE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_LIBSAMPLERATE_TRUE}" && test -z "${HAVE_LIBSAMPLERATE_FALSE}"; then - as_fn_error $? "conditional \"HAVE_LIBSAMPLERATE\" was never defined. +if test -z "${ENABLE_LIBSAMPLERATE_TRUE}" && test -z "${ENABLE_LIBSAMPLERATE_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_LIBSAMPLERATE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_SOXR_TRUE}" && test -z "${HAVE_SOXR_FALSE}"; then - as_fn_error $? "conditional \"HAVE_SOXR\" was never defined. +if test -z "${ENABLE_SOXR_TRUE}" && test -z "${ENABLE_SOXR_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_SOXR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_CURL_TRUE}" && test -z "${ENABLE_CURL_FALSE}"; then @@ -20389,36 +21058,44 @@ as_fn_error $? "conditional \"ENABLE_MMS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_WEBDAV_TRUE}" && test -z "${ENABLE_WEBDAV_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_WEBDAV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_CUE_TRUE}" && test -z "${ENABLE_CUE_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_CUE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ENABLE_NEIGHBOR_PLUGINS_TRUE}" && test -z "${ENABLE_NEIGHBOR_PLUGINS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_NEIGHBOR_PLUGINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ISO9660_TRUE}" && test -z "${HAVE_ISO9660_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ISO9660\" was never defined. +if test -z "${ENABLE_ISO9660_TRUE}" && test -z "${ENABLE_ISO9660_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ISO9660\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_ISO9660_TEST_TRUE}" && test -z "${ENABLE_ISO9660_TEST_FALSE}"; then as_fn_error $? "conditional \"ENABLE_ISO9660_TEST\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ZLIB_TRUE}" && test -z "${HAVE_ZLIB_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ZLIB\" was never defined. +if test -z "${ENABLE_ZLIB_TRUE}" && test -z "${ENABLE_ZLIB_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ZLIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_BZ2_TRUE}" && test -z "${HAVE_BZ2_FALSE}"; then - as_fn_error $? "conditional \"HAVE_BZ2\" was never defined. +if test -z "${ENABLE_BZ2_TRUE}" && test -z "${ENABLE_BZ2_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_BZ2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_BZIP2_TEST_TRUE}" && test -z "${ENABLE_BZIP2_TEST_FALSE}"; then as_fn_error $? "conditional \"ENABLE_BZIP2_TEST\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_LIBUPNP_TRUE}" && test -z "${HAVE_LIBUPNP_FALSE}"; then - as_fn_error $? "conditional \"HAVE_LIBUPNP\" was never defined. +if test -z "${ENABLE_UPNP_TRUE}" && test -z "${ENABLE_UPNP_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_UPNP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ZZIP_TRUE}" && test -z "${HAVE_ZZIP_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ZZIP\" was never defined. +if test -z "${ENABLE_ZZIP_TRUE}" && test -z "${ENABLE_ZZIP_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ZZIP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_ZZIP_TEST_TRUE}" && test -z "${ENABLE_ZZIP_TEST_FALSE}"; then @@ -20429,64 +21106,64 @@ as_fn_error $? "conditional \"ENABLE_ARCHIVE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ADPLUG_TRUE}" && test -z "${HAVE_ADPLUG_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ADPLUG\" was never defined. +if test -z "${ENABLE_ADPLUG_TRUE}" && test -z "${ENABLE_ADPLUG_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ADPLUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_AUDIOFILE_TRUE}" && test -z "${HAVE_AUDIOFILE_FALSE}"; then - as_fn_error $? "conditional \"HAVE_AUDIOFILE\" was never defined. +if test -z "${ENABLE_AUDIOFILE_TRUE}" && test -z "${ENABLE_AUDIOFILE_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_AUDIOFILE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_DSD_TRUE}" && test -z "${ENABLE_DSD_FALSE}"; then as_fn_error $? "conditional \"ENABLE_DSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_FAAD_TRUE}" && test -z "${HAVE_FAAD_FALSE}"; then - as_fn_error $? "conditional \"HAVE_FAAD\" was never defined. +if test -z "${ENABLE_FAAD_TRUE}" && test -z "${ENABLE_FAAD_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_FAAD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_FFMPEG_TRUE}" && test -z "${HAVE_FFMPEG_FALSE}"; then - as_fn_error $? "conditional \"HAVE_FFMPEG\" was never defined. +if test -z "${ENABLE_FFMPEG_TRUE}" && test -z "${ENABLE_FFMPEG_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_FFMPEG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_FLAC_TRUE}" && test -z "${HAVE_FLAC_FALSE}"; then - as_fn_error $? "conditional \"HAVE_FLAC\" was never defined. +if test -z "${ENABLE_FLAC_TRUE}" && test -z "${ENABLE_FLAC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_FLAC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_FLUIDSYNTH_TRUE}" && test -z "${ENABLE_FLUIDSYNTH_FALSE}"; then as_fn_error $? "conditional \"ENABLE_FLUIDSYNTH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_GME_TRUE}" && test -z "${HAVE_GME_FALSE}"; then - as_fn_error $? "conditional \"HAVE_GME\" was never defined. +if test -z "${ENABLE_GME_TRUE}" && test -z "${ENABLE_GME_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_GME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_MAD_TRUE}" && test -z "${HAVE_MAD_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MAD\" was never defined. +if test -z "${ENABLE_MAD_TRUE}" && test -z "${ENABLE_MAD_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_MAD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_MPG123_TRUE}" && test -z "${HAVE_MPG123_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MPG123\" was never defined. +if test -z "${ENABLE_MPG123_TRUE}" && test -z "${ENABLE_MPG123_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_MPG123\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_MIKMOD_DECODER_TRUE}" && test -z "${ENABLE_MIKMOD_DECODER_FALSE}"; then as_fn_error $? "conditional \"ENABLE_MIKMOD_DECODER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_MODPLUG_TRUE}" && test -z "${HAVE_MODPLUG_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MODPLUG\" was never defined. +if test -z "${ENABLE_MODPLUG_TRUE}" && test -z "${ENABLE_MODPLUG_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_MODPLUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_OPUS_TRUE}" && test -z "${HAVE_OPUS_FALSE}"; then - as_fn_error $? "conditional \"HAVE_OPUS\" was never defined. +if test -z "${ENABLE_OPUS_TRUE}" && test -z "${ENABLE_OPUS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_OPUS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SNDFILE_TRUE}" && test -z "${ENABLE_SNDFILE_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SNDFILE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_MPCDEC_TRUE}" && test -z "${HAVE_MPCDEC_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MPCDEC\" was never defined. +if test -z "${ENABLE_MPCDEC_TRUE}" && test -z "${ENABLE_MPCDEC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_MPCDEC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_VORBIS_DECODER_TRUE}" && test -z "${ENABLE_VORBIS_DECODER_FALSE}"; then @@ -20497,36 +21174,32 @@ as_fn_error $? "conditional \"ENABLE_SIDPLAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_WAVPACK_TRUE}" && test -z "${HAVE_WAVPACK_FALSE}"; then - as_fn_error $? "conditional \"HAVE_WAVPACK\" was never defined. +if test -z "${ENABLE_WAVPACK_TRUE}" && test -z "${ENABLE_WAVPACK_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_WAVPACK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_WILDMIDI_TRUE}" && test -z "${ENABLE_WILDMIDI_FALSE}"; then as_fn_error $? "conditional \"ENABLE_WILDMIDI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_XIPH_TRUE}" && test -z "${HAVE_XIPH_FALSE}"; then - as_fn_error $? "conditional \"HAVE_XIPH\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${ENABLE_FLAC_ENCODER_TRUE}" && test -z "${ENABLE_FLAC_ENCODER_FALSE}"; then as_fn_error $? "conditional \"ENABLE_FLAC_ENCODER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_SHINE_ENCODER_TRUE}" && test -z "${ENABLE_SHINE_ENCODER_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_SHINE_ENCODER\" was never defined. +if test -z "${ENABLE_SHINE_TRUE}" && test -z "${ENABLE_SHINE_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_SHINE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_VORBIS_ENCODER_TRUE}" && test -z "${ENABLE_VORBIS_ENCODER_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_VORBIS_ENCODER\" was never defined. +if test -z "${ENABLE_VORBISENC_TRUE}" && test -z "${ENABLE_VORBISENC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_VORBISENC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_LAME_ENCODER_TRUE}" && test -z "${ENABLE_LAME_ENCODER_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_LAME_ENCODER\" was never defined. +if test -z "${ENABLE_LAME_TRUE}" && test -z "${ENABLE_LAME_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_LAME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_TWOLAME_ENCODER_TRUE}" && test -z "${ENABLE_TWOLAME_ENCODER_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_TWOLAME_ENCODER\" was never defined. +if test -z "${ENABLE_TWOLAME_TRUE}" && test -z "${ENABLE_TWOLAME_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_TWOLAME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_WAVE_ENCODER_TRUE}" && test -z "${ENABLE_WAVE_ENCODER_FALSE}"; then @@ -20537,32 +21210,36 @@ as_fn_error $? "conditional \"ENABLE_ENCODER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_OGG_ENCODER_TRUE}" && test -z "${HAVE_OGG_ENCODER_FALSE}"; then - as_fn_error $? "conditional \"HAVE_OGG_ENCODER\" was never defined. +if test -z "${ENABLE_ALSA_TRUE}" && test -z "${ENABLE_ALSA_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ALSA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_ALSA_TRUE}" && test -z "${HAVE_ALSA_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ALSA\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${HAVE_ROAR_TRUE}" && test -z "${HAVE_ROAR_FALSE}"; then - as_fn_error $? "conditional \"HAVE_ROAR\" was never defined. +if test -z "${ENABLE_ROAR_TRUE}" && test -z "${ENABLE_ROAR_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ROAR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_FIFO_TRUE}" && test -z "${HAVE_FIFO_FALSE}"; then as_fn_error $? "conditional \"HAVE_FIFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_SNDIO_TRUE}" && test -z "${ENABLE_SNDIO_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_SNDIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_HAIKU_TRUE}" && test -z "${ENABLE_HAIKU_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_HAIKU\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ENABLE_HTTPD_OUTPUT_TRUE}" && test -z "${ENABLE_HTTPD_OUTPUT_FALSE}"; then as_fn_error $? "conditional \"ENABLE_HTTPD_OUTPUT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_JACK_TRUE}" && test -z "${HAVE_JACK_FALSE}"; then - as_fn_error $? "conditional \"HAVE_JACK\" was never defined. +if test -z "${ENABLE_JACK_TRUE}" && test -z "${ENABLE_JACK_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_JACK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_AO_TRUE}" && test -z "${HAVE_AO_FALSE}"; then - as_fn_error $? "conditional \"HAVE_AO\" was never defined. +if test -z "${ENABLE_AO_TRUE}" && test -z "${ENABLE_AO_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_AO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_OPENAL_TRUE}" && test -z "${HAVE_OPENAL_FALSE}"; then @@ -20581,8 +21258,8 @@ as_fn_error $? "conditional \"ENABLE_PIPE_OUTPUT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_PULSE_TRUE}" && test -z "${HAVE_PULSE_FALSE}"; then - as_fn_error $? "conditional \"HAVE_PULSE\" was never defined. +if test -z "${ENABLE_PULSE_TRUE}" && test -z "${ENABLE_PULSE_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_PULSE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_RECORDER_OUTPUT_TRUE}" && test -z "${ENABLE_RECORDER_OUTPUT_FALSE}"; then @@ -20601,6 +21278,14 @@ as_fn_error $? "conditional \"ENABLE_WINMM_OUTPUT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_OGG_TRUE}" && test -z "${HAVE_OGG_FALSE}"; then + as_fn_error $? "conditional \"HAVE_OGG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_XIPH_TRUE}" && test -z "${HAVE_XIPH_FALSE}"; then + as_fn_error $? "conditional \"HAVE_XIPH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ENABLE_DOCUMENTATION_TRUE}" && test -z "${ENABLE_DOCUMENTATION_FALSE}"; then as_fn_error $? "conditional \"ENABLE_DOCUMENTATION\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -21006,7 +21691,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mpd $as_me 0.19.21, which was +This file was extended by mpd $as_me 0.20.9, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21072,7 +21757,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mpd config.status 0.19.21 +mpd config.status 0.20.9 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -21203,7 +21888,7 @@ case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "src/win32/mpd_win32_rc.rc") CONFIG_FILES="$CONFIG_FILES src/win32/mpd_win32_rc.rc" ;; + "win32/res/mpd.rc") CONFIG_FILES="$CONFIG_FILES win32/res/mpd.rc" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/doxygen.conf") CONFIG_FILES="$CONFIG_FILES doc/doxygen.conf" ;; "systemd/system/mpd.service") CONFIG_FILES="$CONFIG_FILES systemd/system/mpd.service" ;; diff -Nru mpd-0.19.21/configure.ac mpd-0.20.9/configure.ac --- mpd-0.19.21/configure.ac 2016-12-13 07:54:51.000000000 +0000 +++ mpd-0.20.9/configure.ac 2017-05-29 18:36:08.000000000 +0000 @@ -1,10 +1,10 @@ AC_PREREQ(2.60) -AC_INIT(mpd, 0.19.21, musicpd-dev-team@lists.sourceforge.net) +AC_INIT(mpd, 0.20.9, musicpd-dev-team@lists.sourceforge.net) VERSION_MAJOR=0 -VERSION_MINOR=19 -VERSION_REVISION=21 +VERSION_MINOR=20 +VERSION_REVISION=9 VERSION_EXTRA=0 AC_CONFIG_SRCDIR([src/Main.cxx]) @@ -14,7 +14,7 @@ AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) -AC_DEFINE(PROTOCOL_VERSION, "0.19.0", [The MPD protocol version]) +AC_DEFINE(PROTOCOL_VERSION, "0.20.0", [The MPD protocol version]) GIT_COMMIT=`GIT_DIR="$srcdir/.git" git describe --dirty --always 2>/dev/null` if test x$GIT_COMMIT != x; then @@ -113,11 +113,13 @@ mingw32* | windows*) AC_CONFIG_FILES([ - src/win32/mpd_win32_rc.rc + win32/res/mpd.rc ]) AC_CHECK_TOOL(WINDRES, windres) AM_CPPFLAGS="$AM_CPPFLAGS -DWIN32_LEAN_AND_MEAN" AM_CPPFLAGS="$AM_CPPFLAGS -DWINVER=0x0600 -D_WIN32_WINNT=0x0600" + AM_CPPFLAGS="$AM_CPPFLAGS -DSTRICT" + AM_CPPFLAGS="$AM_CPPFLAGS -DUNICODE -D_UNICODE" LIBS="$LIBS -lws2_32" host_is_windows=yes host_is_unix=no @@ -130,6 +132,10 @@ solaris*) host_is_solaris=yes ;; +haiku*) + AC_CHECK_TOOL(RC, rc) + AC_CHECK_TOOL(XRES, xres) + ;; esac AM_CONDITIONAL([ANDROID], [test x$host_is_android = xyes]) @@ -196,33 +202,44 @@ dnl Language Checks dnl --------------------------------------------------------------------------- -AC_CXX_COMPILE_STDCXX_0X -if test "$ax_cv_cxx_compile_cxx0x_native" != yes; then - if test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then - AM_CXXFLAGS="$AM_CXXFLAGS -std=gnu++0x" - elif test "$ax_cv_cxx_compile_cxx0x_cxx" = yes; then - AM_CXXFLAGS="$AM_CXXFLAGS -std=c++0x" - fi -fi +AX_CXX_COMPILE_STDCXX_14([noext], [mandatory]) dnl --------------------------------------------------------------------------- dnl Header/Library Checks dnl --------------------------------------------------------------------------- +AX_PTHREAD +LIBS="$PTHREAD_LIBS $LIBS" +AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS" +AM_CXXFLAGS="$AM_CXXFLAGS $PTHREAD_CFLAGS" + +MPD_WITH_LIBRARY([PTHREAD], + [AC_CHECK_FUNCS([pthread_setname_np])]) + AC_SEARCH_LIBS([clock_gettime], [rt]) -AC_SEARCH_LIBS([syslog], [bsd socket inet], - [AC_DEFINE(HAVE_SYSLOG, 1, [Define if syslog() is available])]) +AC_ARG_ENABLE(syslog, + AS_HELP_STRING([--enable-syslog], + [enable syslog support (default: auto)]),, + enable_syslog=auto) +MPD_AUTO(syslog, [syslog support], [syslog() not available], + [AC_SEARCH_LIBS([syslog], [bsd socket inet], + [found_syslog=yes], + [found_syslog=no])]) +if test x$enable_syslog = xyes; then + AC_DEFINE(HAVE_SYSLOG, 1, [Define if syslog() is available]) +fi -AC_SEARCH_LIBS([socket], [socket]) +AC_SEARCH_LIBS([socket], [network socket]) AC_SEARCH_LIBS([gethostbyname], [nsl]) if test x$host_is_linux = xyes; then - AC_CHECK_FUNCS(pipe2 accept4) + AC_CHECK_FUNCS(pipe2 accept4 linkat) fi AC_CHECK_FUNCS(getpwnam_r getpwuid_r) AC_CHECK_FUNCS(initgroups) +AC_CHECK_FUNCS(fnmatch) AC_CHECK_FUNCS(strndup) if test x$host_is_linux = xyes; then @@ -238,18 +255,6 @@ AC_CHECK_HEADERS([sys/prctl.h], AC_CHECK_FUNCS([prctl])) -AX_PTHREAD -LIBS="$PTHREAD_LIBS $LIBS" -AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS" -AM_CXXFLAGS="$AM_CXXFLAGS $PTHREAD_CFLAGS" - -AC_CHECK_LIB([pthread], [pthread_setname_np], - [have_pthread_setname_np=yes], - [have_pthread_setname_np=no]) -if test x$have_pthread_setname_np = xyes; then - AC_DEFINE(HAVE_PTHREAD_SETNAME_NP, 1, [Is pthread_setname_np() available?]) -fi - dnl --------------------------------------------------------------------------- dnl Event loop selection dnl --------------------------------------------------------------------------- @@ -300,90 +305,23 @@ AS_HELP_STRING([--enable-database], [enable support for the music database]),, enable_database=yes) -AM_CONDITIONAL(ENABLE_DATABASE, test x$enable_database = xyes) +MPD_DEFINE_CONDITIONAL(enable_database, ENABLE_DATABASE, + [the music database]) if test x$enable_database = xyes; then database_auto=auto - AC_DEFINE(ENABLE_DATABASE, 1, [Define to enable the music database]) else database_auto=no fi -AC_ARG_ENABLE(libmpdclient, - AS_HELP_STRING([--enable-libmpdclient], - [enable support for the MPD client]),, - enable_libmpdclient=auto) -MPD_DEPENDS([enable_libmpdclient], [enable_database], - [Cannot use --enable-libmpdclient with --disable-database]) - -AC_ARG_ENABLE(expat, - AS_HELP_STRING([--enable-expat], - [enable the expat XML parser]),, - enable_expat=auto) - -AC_ARG_ENABLE(upnp, - AS_HELP_STRING([--enable-upnp], - [enable UPnP client support (default: auto)]),, - enable_upnp=auto) -MPD_DEPENDS([enable_upnp], [enable_database], - [Cannot use --enable-upnp with --disable-database]) - -AC_ARG_ENABLE(adplug, - AS_HELP_STRING([--enable-adplug], - [enable the AdPlug decoder plugin (default: auto)]),, - enable_adplug=auto) - -AC_ARG_ENABLE(alsa, - AS_HELP_STRING([--enable-alsa], [enable ALSA support]),, - [enable_alsa=$linux_auto]) - -AC_ARG_ENABLE(roar, - AS_HELP_STRING([--enable-roar], - [enable support for RoarAudio]),, - [enable_roar=auto]) - -AC_ARG_ENABLE(ao, - AS_HELP_STRING([--enable-ao], - [enable support for libao]),, - enable_ao=auto) -MPD_DEPENDS([enable_ao], [enable_glib], - [Cannot use --enable-ao with --disable-glib]) - -AC_ARG_ENABLE(audiofile, - AS_HELP_STRING([--enable-audiofile], - [enable audiofile support (WAV and others)]),, - enable_audiofile=auto) - -AC_ARG_ENABLE(zlib, - AS_HELP_STRING([--enable-zlib], - [enable zlib support (default: auto)]),, - enable_zlib=auto) - -AC_ARG_ENABLE(bzip2, - AS_HELP_STRING([--enable-bzip2], - [enable bzip2 archive support (default: auto)]),, - enable_bzip2=auto) - -AC_ARG_ENABLE(cdio-paranoia, - AS_HELP_STRING([--enable-cdio-paranoia], - [enable support for audio CD support]),, - enable_cdio_paranoia=auto) -MPD_DEPENDS([enable_cdio_paranoia], [enable_glib], - [Cannot use --enable-cdio-paranoia with --disable-glib]) - -AC_ARG_ENABLE(curl, - AS_HELP_STRING([--enable-curl], - [enable support for libcurl HTTP streaming (default: auto)]),, - [enable_curl=auto]) - -AC_ARG_ENABLE(smbclient, - AS_HELP_STRING([--enable-smbclient], - [enable support for libsmbclient (default: auto)]),, - [enable_smbclient=auto]) - -AC_ARG_ENABLE(nfs, - AS_HELP_STRING([--enable-nfs], - [enable support for libnfs (default: auto)]),, - [enable_nfs=auto]) +default_enable_daemon=yes +if test x$host_is_android = xyes || test x$host_is_android = xyes; then + default_enable_daemon=no +fi +AC_ARG_ENABLE(daemon, + AS_HELP_STRING([--enable-daemon], + [enable daemonization (default: enabled)]),, + enable_daemon=$default_enable_daemon) +MPD_DEFINE_CONDITIONAL(enable_daemon, ENABLE_DAEMON, [Enable daemonization?]) AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], @@ -400,44 +338,15 @@ [enable DSD decoder (default: enable)]),, [enable_dsd=yes]) -AC_ARG_ENABLE(ffmpeg, - AS_HELP_STRING([--enable-ffmpeg], - [enable FFMPEG support]),, - enable_ffmpeg=auto) - AC_ARG_ENABLE(fifo, AS_HELP_STRING([--disable-fifo], [disable support for writing audio to a FIFO (default: enable)]),, enable_fifo=yes) -AC_ARG_ENABLE(flac, - AS_HELP_STRING([--enable-flac], - [enable FLAC decoder]),, - enable_flac=auto) - -AC_ARG_ENABLE(fluidsynth, - AS_HELP_STRING([--enable-fluidsynth], - [enable MIDI support via fluidsynth (default: auto)]),, - enable_fluidsynth=auto) - -AC_ARG_ENABLE(gme, - AS_HELP_STRING([--enable-gme], - [enable Blargg's game music emulator plugin]),, - enable_gme=auto) -MPD_DEPENDS([enable_gme], [enable_glib], - [Cannot use --enable-gme with --disable-glib]) - AC_ARG_ENABLE(httpd-output, AS_HELP_STRING([--enable-httpd-output], [enables the HTTP server output]),, [enable_httpd_output=auto]) -MPD_DEPENDS([enable_httpd_output], [enable_glib], - [Cannot use --enable-httpd-output with --disable-glib]) - -AC_ARG_ENABLE(id3, - AS_HELP_STRING([--enable-id3], - [enable id3 support]),, - enable_id3=auto) AC_ARG_ENABLE(inotify, AS_HELP_STRING([--disable-inotify], @@ -449,86 +358,27 @@ [disable IPv6 support (default: enable)]),, [enable_ipv6=yes]) -AC_ARG_ENABLE(iso9660, - AS_HELP_STRING([--enable-iso9660], - [enable iso9660 archive support (default: disabled)]),, - enable_iso9660=no) - -AC_ARG_ENABLE(jack, - AS_HELP_STRING([--enable-jack], - [enable jack support]),, - enable_jack=auto) -MPD_DEPENDS([enable_jack], [enable_glib], - [Cannot use --enable-jack with --disable-glib]) - AC_SYS_LARGEFILE AC_ARG_ENABLE(soundcloud, AS_HELP_STRING([--enable-soundcloud], [enable support for soundcloud.com]),, [enable_soundcloud=auto]) -MPD_DEPENDS([enable_soundcloud], [enable_glib], - [Cannot use --enable-soundcloud with --disable-glib]) - -AC_ARG_ENABLE(lame-encoder, - AS_HELP_STRING([--enable-lame-encoder], - [enable the LAME mp3 encoder]),, - enable_lame_encoder=auto) AC_ARG_ENABLE([libwrap], AS_HELP_STRING([--enable-libwrap], [use libwrap]),, [enable_libwrap=auto]) -AC_ARG_ENABLE(lsr, - AS_HELP_STRING([--enable-lsr], - [enable libsamplerate support]),, - enable_lsr=auto) - -AC_ARG_ENABLE(soxr, - AS_HELP_STRING([--enable-soxr], - [enable the libsoxr resampler]),, - enable_soxr=auto) - -AC_ARG_ENABLE(mad, - AS_HELP_STRING([--enable-mad], - [enable libmad mp3 decoder plugin]),, - enable_mad=auto) - AC_ARG_ENABLE(mikmod, AS_HELP_STRING([--enable-mikmod], [enable the mikmod decoder (default: disable)]),, enable_mikmod=no) -AC_ARG_ENABLE(mms, - AS_HELP_STRING([--enable-mms], - [enable the MMS protocol with libmms]),, - [enable_mms=auto]) - -AC_ARG_ENABLE(modplug, - AS_HELP_STRING([--enable-modplug], - [enable modplug decoder plugin]),, - enable_modplug=auto) - -AC_ARG_ENABLE(mpc, - AS_HELP_STRING([--enable-mpc], - [disable musepack (MPC) support (default: auto)]),, - enable_mpc=auto) - -AC_ARG_ENABLE(mpg123, - AS_HELP_STRING([--enable-mpg123], - [enable libmpg123 decoder plugin]),, - enable_mpg123=auto) - AC_ARG_ENABLE(openal, AS_HELP_STRING([--enable-openal], [enable OpenAL support (default: auto)]),, enable_openal=auto) -AC_ARG_ENABLE(opus, - AS_HELP_STRING([--enable-opus], - [enable Opus codec support (default: auto)]),, - enable_opus=auto) - AC_ARG_ENABLE(oss, AS_HELP_STRING([--disable-oss], [disable OSS support (default: enable)]),, @@ -544,11 +394,6 @@ [enable support for writing audio to a pipe (default: disable)]),, enable_pipe_output=no) -AC_ARG_ENABLE(pulse, - AS_HELP_STRING([--enable-pulse], - [enable support for the PulseAudio sound server]),, - enable_pulse=auto) - AC_ARG_ENABLE(recorder-output, AS_HELP_STRING([--enable-recorder-output], [enables the recorder file output plugin (default: disable)]),, @@ -559,38 +404,16 @@ [enable C64 SID support via libsidplay2]),, enable_sidplay=auto) -AC_ARG_ENABLE(shine-encoder, - AS_HELP_STRING([--enable-shine-encoder], - [enables shine encoder]),, - [enable_shine_encoder=auto]) - AC_ARG_ENABLE(shout, AS_HELP_STRING([--enable-shout], [enables the shoutcast streaming output]),, [enable_shout=auto]) -AC_ARG_ENABLE(sndfile, - AS_HELP_STRING([--enable-sndfile], - [enable sndfile support]),, - enable_sndfile=auto) - AC_ARG_ENABLE(solaris_output, AS_HELP_STRING([--enable-solaris-output], [enables the Solaris /dev/audio output]),, [enable_solaris_output=$host_is_solaris]) -AC_ARG_ENABLE(sqlite, - AS_HELP_STRING([--enable-sqlite], - [enable support for the SQLite database]),, - [enable_sqlite=$database_auto]) -MPD_DEPENDS([enable_sqlite], [enable_glib], - [Cannot use --enable-sqlite with --disable-glib]) - -AC_ARG_ENABLE(systemd-daemon, - AS_HELP_STRING([--enable-systemd-daemon], - [use the systemd daemon library (default=auto)]),, - [enable_systemd_daemon=$linux_auto]) - AC_ARG_ENABLE(tcp, AS_HELP_STRING([--disable-tcp], [disable support for clients connecting via TCP (default: enable)]),, @@ -601,16 +424,6 @@ [build the test programs (default: disabled)]),, enable_test=no) -AC_ARG_WITH(tremor, - AS_HELP_STRING([--with-tremor=PFX], - [use Tremor (vorbisidec) integer Ogg Vorbis decoder (with optional prefix)]),, - with_tremor=no) - -AC_ARG_ENABLE(twolame-encoder, - AS_HELP_STRING([--enable-twolame-encoder], - [enable the TwoLAME mp2 encoder]),, - enable_twolame_encoder=auto) - AC_ARG_ENABLE(un, AS_HELP_STRING([--disable-un], [disable support for clients connecting via unix domain sockets (default: enable)]),, @@ -621,105 +434,48 @@ [enable Ogg Vorbis decoder]),, enable_vorbis=auto) -AC_ARG_ENABLE(vorbis-encoder, - AS_HELP_STRING([--enable-vorbis-encoder], - [enable the Ogg Vorbis encoder]),, - [enable_vorbis_encoder=auto]) -MPD_DEPENDS([enable_vorbis_encoder], [enable_glib], - [Cannot use --enable-vorbis-encoder with --disable-glib]) - AC_ARG_ENABLE(wave-encoder, AS_HELP_STRING([--enable-wave-encoder], [enable the PCM wave encoder]),, enable_wave_encoder=yes) -AC_ARG_ENABLE(wavpack, - AS_HELP_STRING([--enable-wavpack], - [enable WavPack support]),, - enable_wavpack=auto) -MPD_DEPENDS([enable_wavpack], [enable_glib], - [Cannot use --enable-wavpack with --disable-glib]) - AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], [treat warnings as errors (default: disabled)]),, enable_werror=no) -AC_ARG_ENABLE(wildmidi, - AS_HELP_STRING([--enable-wildmidi], - [enable MIDI support via wildmidi (default: auto)]),, - enable_wildmidi=auto) - AC_ARG_WITH(zeroconf, AS_HELP_STRING([--with-zeroconf=@<:@auto|avahi|bonjour|no@:>@], [enable zeroconf backend (default=auto)]),, with_zeroconf="auto") -AC_ARG_ENABLE(zzip, - AS_HELP_STRING([--enable-zzip], - [enable zip archive support (default: disabled)]),, - enable_zzip=no) - - -AC_ARG_WITH(tremor-libraries, - AS_HELP_STRING([--with-tremor-libraries=DIR], - [directory where Tremor library is installed (optional)]),, - tremor_libraries="") - -AC_ARG_WITH(tremor-includes, - AS_HELP_STRING([--with-tremor-includes=DIR], - [directory where Tremor header files are installed (optional)]),, - tremor_includes="") - dnl --------------------------------------------------------------------------- dnl Mandatory Libraries dnl --------------------------------------------------------------------------- -no_exceptions=yes - AX_BOOST_BASE([1.46],, [AC_MSG_ERROR([Boost not found])]) -dnl Don't disable exceptions on Boost older than 1.54, because -dnl Boost.Intrusive supports this compiler mode only since 1.54; -dnl see https://svn.boost.org/trac/boost/ticket/7849 -CPPFLAGS_SAVED="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" -export CPPFLAGS -AC_LANG_PUSH(C++) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -@%:@include -]], [[ -#if BOOST_VERSION < 105400 -#error detected Boost older than 1.54 -#endif -]])],, [no_exceptions=no]) -AC_LANG_POP([C++]) -CPPFLAGS="$CPPFLAGS_SAVED" - AC_ARG_ENABLE(icu, AS_HELP_STRING([--enable-icu], - [enable libicu for Unicode (default: enabled)]),, - enable_icu=yes) + [enable libicu for Unicode (default: auto)]),, + enable_icu=auto) -if test x$enable_icu = xyes; then - PKG_CHECK_MODULES([ICU], [icu-i18n],, - [AC_MSG_ERROR([libicu not found])]) +MPD_AUTO_PKG(icu, ICU, [icu-i18n], [libicu], [libicu not found]) +MPD_DEFINE_CONDITIONAL(enable_icu, HAVE_ICU, [libicu]) - AC_DEFINE(HAVE_ICU, 1, [Define if libicu is used]) -fi -AM_CONDITIONAL(HAVE_ICU, test x$enable_icu = xyes) +AC_ARG_ENABLE(iconv, + AS_HELP_STRING([--enable-iconv], + [enable iconv for character set conversion (default: auto)]),, + enable_iconv=yes) -AC_ARG_ENABLE(glib, - AS_HELP_STRING([--enable-glib], - [enable GLib usage (default: enabled)]),, - enable_glib=yes) +if test x$enable_icu = xyes; then + dnl We don't need iconv() if we have libicu + enable_iconv=no +fi -if test x$enable_glib = xyes; then - PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28 gthread-2.0],, - [AC_MSG_ERROR([GLib 2.28 is required])]) - AC_DEFINE(HAVE_GLIB, 1, [Define if GLib is used]) +if test x$enable_iconv = xyes; then + AC_CHECK_FUNCS(iconv) fi -AM_CONDITIONAL(HAVE_GLIB, test x$enable_glib = xyes) dnl --------------------------------------------------------------------------- dnl Protocol Options @@ -770,12 +526,16 @@ AC_MSG_ERROR([No client interfaces configured!]) fi -MPD_AUTO_PKG(systemd_daemon, SYSTEMD_DAEMON, libsystemd-daemon, - [systemd activation], [libsystemd-daemon not found]) -AM_CONDITIONAL(ENABLE_SYSTEMD_DAEMON, test x$enable_systemd_daemon = xyes) -if test x$enable_systemd_daemon = xyes; then - AC_DEFINE([ENABLE_SYSTEMD_DAEMON], 1, [Define to use the systemd daemon library]) -fi +MPD_ENABLE_AUTO(systemd_daemon, SYSTEMD_DAEMON, [systemd socket activation], + [libsystemd not found], [$linux_auto], [ + dnl Check for libsystemd and fall back to (the older) + dnl libsystemd-daemon + PKG_CHECK_MODULES([SYSTEMD_DAEMON], [libsystemd], + [found_systemd_daemon=yes], + [PKG_CHECK_MODULES([SYSTEMD_DAEMON], [libsystemd-daemon], + [found_systemd_daemon=yes], + [found_systemd_daemon=no])]) +]) dnl --------------------------------------------------------------------------- dnl LIBC Features @@ -789,22 +549,14 @@ dnl --------------------------------------------------------------------------- dnl -------------------------------- libmpdclient -------------------------------- -MPD_AUTO_PKG(libmpdclient, LIBMPDCLIENT, [libmpdclient >= 2.2], - [MPD client library], [libmpdclient not found]) -if test x$enable_libmpdclient = xyes; then - AC_DEFINE(HAVE_LIBMPDCLIENT, 1, [Define to use libmpdclient]) -fi - -AM_CONDITIONAL(HAVE_LIBMPDCLIENT, test x$enable_libmpdclient = xyes) +MPD_ENABLE_AUTO_PKG_DEPENDS(libmpdclient, LIBMPDCLIENT, + [libmpdclient >= 2.2], + [MPD client library], [libmpdclient not found], [], + [enable_database], [Cannot use --enable-libmpdclient with --disable-database]) dnl -------------------------------- expat -------------------------------- -MPD_AUTO_PKG(expat, EXPAT, [expat], +MPD_ENABLE_AUTO_PKG(expat, EXPAT, [expat], [expat XML parser], [expat not found]) -if test x$enable_expat = xyes; then - AC_DEFINE(HAVE_EXPAT, 1, [Define to use the expat XML parser]) -fi - -AM_CONDITIONAL(HAVE_EXPAT, test x$enable_expat = xyes) dnl --------------------------------- inotify --------------------------------- AC_CHECK_FUNCS(inotify_init inotify_init1) @@ -813,10 +565,7 @@ enable_inotify=no fi -if test x$enable_inotify = xyes; then - AC_DEFINE([ENABLE_INOTIFY], 1, [Define to enable inotify support]) -fi -AM_CONDITIONAL(ENABLE_INOTIFY, test x$enable_inotify = xyes) +MPD_DEFINE_CONDITIONAL(enable_inotify, ENABLE_INOTIFY, [inotify support]) dnl --------------------------------- libwrap --------------------------------- if test x$enable_libwrap != xno; then @@ -856,13 +605,9 @@ dnl --------------------------------------------------------------------------- dnl -------------------------------- libid3tag -------------------------------- -MPD_AUTO_PKG_LIB(id3, ID3TAG, id3tag, id3tag, id3_file_open, [-lid3tag -lz], [], - [id3tag], [libid3tag not found]) -if test x$enable_id3 = xyes; then - AC_DEFINE(HAVE_ID3TAG, 1, [Define to use id3tag]) -fi - -AM_CONDITIONAL(HAVE_ID3TAG, test x$enable_id3 = xyes) +MPD_ENABLE_AUTO_PKG_LIB(id3, ID3TAG, + id3tag, id3tag, id3_file_open, [-lid3tag -lz], [], + [ID3 support using libid3tag], [libid3tag not found]) dnl --------------------------------------------------------------------------- dnl Autodiscovery @@ -888,11 +633,10 @@ MPD_AUTO_PKG(avahi, AVAHI, [avahi-client dbus-1], [avahi client library], [avahi-client not found]) if test x$enable_avahi = xyes; then - AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support]) with_zeroconf=avahi fi -AM_CONDITIONAL(HAVE_AVAHI, test x$enable_avahi = xyes) +MPD_DEFINE_CONDITIONAL(enable_avahi, HAVE_AVAHI, [Avahi Zeroconf]) enable_bounjour=no if test x$with_zeroconf != xno; then @@ -925,99 +669,75 @@ dnl ---------------------------------- sqlite --------------------------------- -MPD_AUTO_PKG(sqlite, SQLITE, [sqlite3], - [SQLite database support], [sqlite not found]) -if test x$enable_sqlite = xyes; then - AC_DEFINE([ENABLE_SQLITE], 1, [Define to enable sqlite database support]) -fi - -AM_CONDITIONAL(ENABLE_SQLITE, test x$enable_sqlite = xyes) +MPD_ENABLE_AUTO_PKG(sqlite, SQLITE, [sqlite3 >= 3.7.3], + [SQLite database support], [sqlite not found], + [$database_auto]) dnl --------------------------------------------------------------------------- dnl Converter Plugins dnl --------------------------------------------------------------------------- dnl ------------------------------ libsamplerate ------------------------------ -MPD_AUTO_PKG(lsr, SAMPLERATE, [samplerate >= 0.1.3], +MPD_ENABLE_AUTO_PKG(lsr, LIBSAMPLERATE, [samplerate >= 0.1.3], [libsamplerate resampling], [libsamplerate not found]) -if test x$enable_lsr = xyes; then - AC_DEFINE([HAVE_LIBSAMPLERATE], 1, - [Define to enable libsamplerate]) -fi -AM_CONDITIONAL(HAVE_LIBSAMPLERATE, test x$enable_lsr = xyes) dnl ------------------------------ libsoxr ------------------------------------ -MPD_AUTO_PKG(soxr, SOXR, [soxr], +MPD_ENABLE_AUTO_PKG(soxr, SOXR, [soxr], [libsoxr resampler], [libsoxr not found]) -if test x$enable_soxr = xyes; then - AC_DEFINE([HAVE_SOXR], 1, [Define to enable libsoxr]) -fi - -AM_CONDITIONAL(HAVE_SOXR, test x$enable_soxr = xyes) dnl --------------------------------------------------------------------------- dnl Input Plugins dnl --------------------------------------------------------------------------- dnl ----------------------------------- CURL ---------------------------------- -MPD_AUTO_PKG(curl, CURL, [libcurl >= 7.18], +MPD_ENABLE_AUTO_PKG(curl, CURL, [libcurl >= 7.18], [libcurl HTTP streaming], [libcurl not found]) -if test x$enable_curl = xyes; then - AC_DEFINE(ENABLE_CURL, 1, [Define when libcurl is used for HTTP streaming]) -fi -AM_CONDITIONAL(ENABLE_CURL, test x$enable_curl = xyes) dnl ----------------------------------- smbclient ----------------------------- -MPD_AUTO_PKG_LIB(smbclient, SMBCLIENT, [smbclient >= 0.2], +MPD_ENABLE_AUTO_PKG_LIB(smbclient, SMBCLIENT, [smbclient >= 0.2], [smbclient], [smbc_init], [-lsmbclient], [], [smbclient input plugin], [libsmbclient not found]) -if test x$enable_smbclient = xyes; then - AC_DEFINE(ENABLE_SMBCLIENT, 1, [Define when libsmbclient is used]) -fi -AM_CONDITIONAL(ENABLE_SMBCLIENT, test x$enable_smbclient = xyes) dnl ----------------------------------- NFS ----------------------------- -MPD_AUTO_PKG(nfs, NFS, [libnfs], +MPD_ENABLE_AUTO_PKG(nfs, NFS, [libnfs], [NFS input plugin], [libnfs not found]) -if test x$enable_nfs = xyes; then - AC_DEFINE(ENABLE_NFS, 1, [Define when libnfs is used]) -fi -AM_CONDITIONAL(ENABLE_NFS, test x$enable_nfs = xyes) dnl --------------------------------- Soundcloud ------------------------------ -if test x$enable_soundcloud != xno; then - PKG_CHECK_MODULES([YAJL], [yajl >= 2.0], +MPD_AUTO([soundcloud], [soundcloud.com support], [libyajl not found], + [PKG_CHECK_MODULES([YAJL], [yajl >= 2.0], [found_soundcloud=yes], - AC_CHECK_LIB([yajl], [yajl_parse_complete], - [found_soundcloud=yes YAJL_CFLAGS=-DHAVE_YAJL1 YAJL_LIBS=-lyajl], - [found_soundcloud=no])) -fi -MPD_AUTO_RESULT([soundcloud], [soundcloud.com support], [libyajl not found]) -if test x$enable_soundcloud = xyes; then - AC_DEFINE(ENABLE_SOUNDCLOUD, 1, [Define when soundcloud is enabled]) -fi -AM_CONDITIONAL(ENABLE_SOUNDCLOUD, test x$enable_soundcloud = xyes) -AC_SUBST(YAJL_LIBS) + [found_soundcloud=no])]) +MPD_DEFINE_CONDITIONAL(enable_soundcloud, ENABLE_SOUNDCLOUD, + [soundcloud.com support]) dnl ---------------------------------- cdio --------------------------------- -MPD_AUTO_PKG(cdio_paranoia, CDIO_PARANOIA, [libcdio_paranoia], - [libcdio_paranoia audio CD library], [libcdio_paranoia not found]) +MPD_ENABLE_AUTO_PKG(cdio_paranoia, CDIO_PARANOIA, [libcdio_paranoia], + [libcdio_paranoia input plugin], [libcdio_paranoia not found]) if test x$enable_cdio_paranoia = xyes; then - AC_DEFINE([ENABLE_CDIO_PARANOIA], 1, - [Define to enable libcdio_paranoia support]) AC_CHECK_HEADERS(cdio/paranoia/paranoia.h) fi -AM_CONDITIONAL(ENABLE_CDIO_PARANOIA, test x$enable_cdio_paranoia = xyes) - -dnl ---------------------------------- libmms --------------------------------- -MPD_AUTO_PKG(mms, MMS, [libmms >= 0.4], +MPD_ENABLE_AUTO_PKG(mms, MMS, [libmms >= 0.4], [libmms mms:// protocol support], [libmms not found]) -if test x$enable_mms = xyes; then - AC_DEFINE(ENABLE_MMS, 1, - [Define when libmms is used for the MMS protocol]) -fi -AM_CONDITIONAL(ENABLE_MMS, test x$enable_mms = xyes) + +dnl --------------------------------------------------------------------------- +dnl Storage Plugins +dnl --------------------------------------------------------------------------- + +MPD_ENABLE_AUTO(webdav, WEBDAV, [WebDAV storage plugin], + [WebDAV requires libcurl and libexpat], + [auto], + [if test x$enable_curl = xyes && test x$enable_expat = xyes; then + found_webdav=yes + else + found_webdav=no + fi]) + +dnl --------------------------------------------------------------------------- +dnl Playlist Plugins +dnl --------------------------------------------------------------------------- + +MPD_ARG_ENABLE(cue, CUE, [CUE sheet parser], yes) dnl --------------------------------------------------------------------------- dnl Neighbor Plugins @@ -1037,24 +757,18 @@ fi fi -if test x$enable_neighbor_plugins = xyes; then - AC_DEFINE(ENABLE_NEIGHBOR_PLUGINS, 1, - [Define to enable support for neighbor discovery]) -fi -AM_CONDITIONAL(ENABLE_NEIGHBOR_PLUGINS, test x$enable_neighbor_plugins = xyes) +MPD_DEFINE_CONDITIONAL(enable_neighbor_plugins, ENABLE_NEIGHBOR_PLUGINS, + [neighbor discovery]) dnl --------------------------------------------------------------------------- dnl Archive Plugins dnl --------------------------------------------------------------------------- dnl --------------------------------- iso9660 --------------------------------- -MPD_AUTO_PKG(iso9660, ISO9660, [libiso9660], - [libiso9660 archive library], [libiso9660 not found]) +MPD_ENABLE_AUTO_PKG(iso9660, ISO9660, [libiso9660], + [libiso9660 archive plugin], [libiso9660 not found]) -AM_CONDITIONAL(HAVE_ISO9660, test x$enable_iso9660 = xyes) if test x$enable_iso9660 = xyes; then - AC_DEFINE(HAVE_ISO9660, 1, [Define to have ISO9660 archive support]) - AC_PATH_PROG(MKISOFS, mkisofs, no) else MKISOFS="no" @@ -1064,23 +778,15 @@ dnl ---------------------------------- zlib --------------------------------- -MPD_AUTO_PKG(zlib, ZLIB, [zlib], +MPD_ENABLE_AUTO_PKG(zlib, ZLIB, [zlib], [zlib support], [zlib not found]) -AM_CONDITIONAL(HAVE_ZLIB, test x$enable_zlib = xyes) -if test x$enable_zlib = xyes; then - AC_DEFINE(HAVE_ZLIB, 1, [Define to enable zlib support]) -fi - dnl ---------------------------------- libbz2 --------------------------------- -MPD_AUTO_LIB(bzip2, BZ2, bz2, BZ2_bzDecompressInit, [-lbz2], [], - [bzip2], [libbz2 not found]) +MPD_ENABLE_AUTO_LIB(bzip2, BZ2, bz2, BZ2_bzDecompressInit, [-lbz2], [], + [bzip2 archive plugin], [libbz2 not found]) -AM_CONDITIONAL(HAVE_BZ2, test x$enable_bzip2 = xyes) if test x$enable_bzip2 = xyes; then - AC_DEFINE(HAVE_BZ2, 1, [Define to have bz2 archive support]) - AC_PATH_PROG(BZIP2, bzip2, no) else BZIP2="no" @@ -1099,21 +805,16 @@ fi fi -MPD_AUTO_PKG(upnp, UPNP, [libupnp], - [UPnP client support], [libupnp not found]) -if test x$enable_upnp = xyes; then - AC_DEFINE(HAVE_LIBUPNP, 1, [Define when libupnp is used]) -fi -AM_CONDITIONAL(HAVE_LIBUPNP, test x$enable_upnp = xyes) +MPD_ENABLE_AUTO_PKG_DEPENDS(upnp, UPNP, [libupnp], + [UPnP client support], [libupnp not found], [], + [enable_database], [Cannot use --enable-upnp with --disable-database]) dnl --------------------------------- libzzip --------------------------------- -MPD_AUTO_PKG(zzip, ZZIP, [zziplib >= 0.13], - [libzzip archive library], [libzzip not found]) +MPD_ENABLE_AUTO_PKG(zzip, ZZIP, [zziplib >= 0.13], + [libzzip archive library], [libzzip not found], + [no]) -AM_CONDITIONAL(HAVE_ZZIP, test x$enable_zzip = xyes) if test x$enable_zzip = xyes; then - AC_DEFINE(HAVE_ZZIP, 1, [Define to have zip archive support]) - AC_PATH_PROG(ZIP, zip, no) else ZIP="no" @@ -1127,96 +828,59 @@ test x$enable_zzip = xyes || test x$enable_iso9660 = xyes; then enable_archive=yes - AC_DEFINE(ENABLE_ARCHIVE, 1, [The archive API is available]) else enable_archive=no fi -AM_CONDITIONAL(ENABLE_ARCHIVE, test x$enable_archive = xyes) +MPD_DEFINE_CONDITIONAL(enable_archive, ENABLE_ARCHIVE, [the archive API]) dnl --------------------------------------------------------------------------- dnl Decoder Plugins dnl --------------------------------------------------------------------------- dnl -------------------------------- libadplug -------------------------------- -MPD_AUTO_PKG(adplug, ADPLUG, [adplug], +MPD_ENABLE_AUTO_PKG(adplug, ADPLUG, [adplug], [AdPlug decoder plugin], [libadplug not found]) -if test x$enable_adplug = xyes; then - AC_DEFINE(HAVE_ADPLUG, 1, [Define to use libadplug]) -fi -AM_CONDITIONAL(HAVE_ADPLUG, test x$enable_adplug = xyes) dnl -------------------------------- audiofile -------------------------------- -MPD_AUTO_PKG(audiofile, AUDIOFILE, [audiofile >= 0.3], +MPD_ENABLE_AUTO_PKG(audiofile, AUDIOFILE, [audiofile >= 0.3], [audiofile decoder plugin], [libaudiofile not found]) -AM_CONDITIONAL(HAVE_AUDIOFILE, test x$enable_audiofile = xyes) -if test x$enable_audiofile = xyes; then - AC_DEFINE(HAVE_AUDIOFILE, 1, [Define for audiofile support]) -fi dnl ----------------------------------- DSD ----------------------------------- -if test x$enable_dsd = xyes; then - AC_DEFINE(ENABLE_DSD, 1, [Define for the DSD decoder]) -fi - -AM_CONDITIONAL(ENABLE_DSD, test x$enable_dsd = xyes) +MPD_DEFINE_CONDITIONAL(enable_dsd, ENABLE_DSD, [DSD decoder]) dnl ----------------------------------- FAAD ---------------------------------- -AM_PATH_FAAD() - -AM_CONDITIONAL(HAVE_FAAD, test x$enable_aac = xyes) +MPD_ENABLE_AUTO_LIB(aac, FAAD, faad, NeAACDecOpen, [-lfaad], [], + [FAAD decoder plugin], [libfaad not found]) dnl ---------------------------------- ffmpeg --------------------------------- -MPD_AUTO_PKG(ffmpeg, FFMPEG, [libavformat >= 53.17 libavcodec >= 53.25 libavutil >= 51.17], +MPD_ENABLE_AUTO_PKG(ffmpeg, FFMPEG, + [libavformat >= 53.17 libavcodec >= 53.25 libavutil >= 51.17], [ffmpeg decoder library], [libavformat+libavcodec+libavutil not found]) -if test x$enable_ffmpeg = xyes; then - AC_DEFINE(HAVE_FFMPEG, 1, [Define for FFMPEG support]) -fi - -AM_CONDITIONAL(HAVE_FFMPEG, test x$enable_ffmpeg = xyes) - dnl ----------------------------------- FLAC ---------------------------------- -MPD_AUTO_PKG(flac, FLAC, [flac >= 1.2], +MPD_ENABLE_AUTO_PKG(flac, FLAC, [flac >= 1.2], [FLAC decoder], [libFLAC not found]) -if test x$enable_flac = xyes; then - AC_DEFINE(HAVE_FLAC, 1, [Define for FLAC support]) -fi - -AM_CONDITIONAL(HAVE_FLAC, test x$enable_flac = xyes) - enable_flac_encoder=$enable_flac dnl -------------------------------- FluidSynth ------------------------------- -MPD_AUTO_PKG(fluidsynth, FLUIDSYNTH, [fluidsynth >= 1.1], - [fluidsynth decoder], [fluidsynth not found]) - -if test x$enable_fluidsynth = xyes; then - AC_DEFINE(ENABLE_FLUIDSYNTH, 1, [Define for fluidsynth support]) -fi - -AM_CONDITIONAL(ENABLE_FLUIDSYNTH, test x$enable_fluidsynth = xyes) +MPD_ENABLE_AUTO_PKG(fluidsynth, FLUIDSYNTH, [fluidsynth >= 1.1], + [fluidsynth MIDI decoder plugin], [fluidsynth not found]) dnl ---------------------------------- libgme --------------------------------- -MPD_AUTO_PKG_LIB(gme, GME, [libgme], gme, gme_open_file, [-lgme -lstdc++], [], - [gme decoder plugin], [libgme not found]) -AM_CONDITIONAL(HAVE_GME, test x$enable_gme = xyes) -if test x$enable_gme = xyes; then - AC_DEFINE(HAVE_GME, 1, [Define for gme support]) -fi + +MPD_ENABLE_AUTO_PKG_LIB(gme, GME, [libgme], + gme, gme_open_file, [-lgme], [], + [Game Music Emulator decoder plugin], [libgme not found]) dnl ---------------------------------- libmad --------------------------------- -MPD_AUTO_PKG_LIB(mad, MAD, [mad], +MPD_ENABLE_AUTO_PKG_LIB(mad, MAD, [mad], mad, mad_stream_init, [-lmad], [], [libmad MP3 decoder plugin], [libmad not found]) -if test x$enable_mad = xyes; then - AC_DEFINE(HAVE_MAD, 1, [Define to use libmad]) -fi -AM_CONDITIONAL(HAVE_MAD, test x$enable_mad = xyes) enable_shout2="$enable_shout" MPD_AUTO_PKG(shout, SHOUT, [shout], @@ -1226,12 +890,8 @@ fi dnl -------------------------------- libmpg123 -------------------------------- -MPD_AUTO_PKG(mpg123, MPG123, [libmpg123], +MPD_ENABLE_AUTO_PKG(mpg123, MPG123, [libmpg123], [libmpg123 decoder plugin], [libmpg123 not found]) -if test x$enable_mpg123 = xyes; then - AC_DEFINE(HAVE_MPG123, 1, [Define to use libmpg123]) -fi -AM_CONDITIONAL(HAVE_MPG123, test x$enable_mpg123 = xyes) dnl -------------------------------- libmikmod -------------------------------- if test x$enable_mikmod = xyes; then @@ -1248,72 +908,57 @@ AM_CONDITIONAL(ENABLE_MIKMOD_DECODER, test x$enable_mikmod = xyes) dnl -------------------------------- libmodplug ------------------------------- -MPD_AUTO_PKG(modplug, MODPLUG, [libmodplug], +MPD_ENABLE_AUTO_PKG(modplug, MODPLUG, [libmodplug], [modplug decoder plugin], [libmodplug not found]) -if test x$enable_modplug = xyes; then - AC_DEFINE(HAVE_MODPLUG, 1, [Define for modplug support]) -fi -AM_CONDITIONAL(HAVE_MODPLUG, test x$enable_modplug = xyes) - dnl -------------------------------- libopus ---------------------------------- -MPD_AUTO_PKG(opus, OPUS, [opus ogg], +MPD_ENABLE_AUTO_PKG(opus, OPUS, [opus ogg], [opus decoder plugin], [libopus not found]) -if test x$enable_opus = xyes; then - AC_DEFINE(HAVE_OPUS, 1, [Define to use libopus]) -fi -AM_CONDITIONAL(HAVE_OPUS, test x$enable_opus = xyes) dnl -------------------------------- libsndfile ------------------------------- dnl See above test, which may disable this. -MPD_AUTO_PKG(sndfile, SNDFILE, [sndfile], +MPD_ENABLE_AUTO_PKG(sndfile, SNDFILE, [sndfile], [libsndfile decoder plugin], [libsndfile not found]) -if test x$enable_sndfile = xyes; then - AC_DEFINE(ENABLE_SNDFILE, 1, [Define to enable the sndfile decoder plugin]) -fi -AM_CONDITIONAL(ENABLE_SNDFILE, test x$enable_sndfile = xyes) - dnl --------------------------------- musepack -------------------------------- -MPD_AUTO_LIB(mpc, MPCDEC, mpcdec, mpc_demux_init, [-lmpcdec], [], - [mpcdec], [libmpcdec not found]) -if test x$enable_mpc = xyes; then - AC_DEFINE(HAVE_MPCDEC, 1, [Define to use libmpcdec for MPC decoding]) -fi -AM_CONDITIONAL(HAVE_MPCDEC, test x$enable_mpc = xyes) +MPD_ENABLE_AUTO_LIB(mpc, MPCDEC, mpcdec, mpc_demux_init, [-lmpcdec], [], + [Musepack decoder plugin], [libmpcdec not found]) dnl -------------------------------- Ogg Tremor ------------------------------- + +AC_ARG_WITH(tremor, + AS_HELP_STRING([--with-tremor=PFX], + [use Tremor (vorbisidec) integer Ogg Vorbis decoder (with optional prefix)]),, + with_tremor=no) + +AC_ARG_VAR([TREMOR_CFLAGS], [C compiler flags for Tremor]) +AC_ARG_VAR([TREMOR_LIBS], [linker flags for Tremor]) + if test x$with_tremor = xyes || test x$with_tremor = xno; then enable_tremor="$with_tremor" + tremor_prefix="" else tremor_prefix="$with_tremor" enable_tremor=yes fi if test x$enable_tremor = xyes; then - if test "x$tremor_libraries" != "x" ; then - TREMOR_LIBS="-L$tremor_libraries" - elif test "x$tremor_prefix" != "x" ; then - TREMOR_LIBS="-L$tremor_prefix/lib" - fi - TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec" - if test "x$tremor_includes" != "x" ; then - TREMOR_CFLAGS="-I$tremor_includes" - elif test "x$tremor_prefix" != "x" ; then + if test x$TREMOR_CFLAGS = x && test x$tremor_prefix != x; then TREMOR_CFLAGS="-I$tremor_prefix/include" fi - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $TREMOR_CFLAGS" - LIBS="$LIBS $TREMOR_LIBS" - AC_CHECK_LIB(vorbisidec,ov_read,,enable_tremor=no; - AC_MSG_WARN([vorbisidec lib needed for ogg support with tremor -- disabling ogg support])) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" -fi + if test x$TREMOR_LIBS = x; then + TREMOR_LIBS="-lvorbisidec" + + if test x$tremor_prefix != x; then + TREMOR_LIBS="-L$tremor_prefix/lib $TREMOR_LIBS" + fi + fi + + MPD_WITH_LIBRARY([TREMOR], + [AC_CHECK_FUNC([ov_read],, + [AC_MSG_ERROR([libvorbisidec not found])])]) -if test x$enable_tremor = xyes; then AC_DEFINE(HAVE_TREMOR,1, [Define to use tremor (libvorbisidec) for ogg support]) AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support]) @@ -1322,9 +967,6 @@ TREMOR_LIBS= fi -AC_SUBST(TREMOR_CFLAGS) -AC_SUBST(TREMOR_LIBS) - dnl -------------------------------- Ogg Vorbis ------------------------------- if test x$enable_tremor = xyes; then @@ -1339,7 +981,7 @@ fi fi -MPD_AUTO_PKG(vorbis, VORBIS, [vorbisfile vorbis ogg], +MPD_AUTO_PKG(vorbis, VORBIS, [vorbis ogg], [Ogg Vorbis decoder], [libvorbis not found]) if test x$enable_vorbis = xyes; then AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support]) @@ -1350,7 +992,7 @@ dnl --------------------------------- sidplay --------------------------------- if test x$enable_sidplay != xno; then dnl Check for libsidplayfp first - PKG_CHECK_MODULES([SIDPLAY], [libsidplayfp libsidutils], + PKG_CHECK_MODULES([SIDPLAY], [libsidplayfp], [found_sidplayfp=yes], [found_sidplayfp=no]) found_sidplay=$found_sidplayfp @@ -1384,26 +1026,12 @@ AM_CONDITIONAL(ENABLE_SIDPLAY, test x$enable_sidplay = xyes) dnl --------------------------------- wavpack --------------------------------- -MPD_AUTO_PKG(wavpack, WAVPACK, [wavpack], +MPD_ENABLE_AUTO_PKG(wavpack, WAVPACK, [wavpack], [WavPack decoder plugin], [libwavpack not found]) -AM_CONDITIONAL(HAVE_WAVPACK, test x$enable_wavpack = xyes) -if test x$enable_wavpack = xyes; then - AC_DEFINE([HAVE_WAVPACK], 1, [Define to enable WavPack support]) -fi dnl --------------------------------- WildMidi -------------------------------- -MPD_AUTO_LIB(wildmidi, WILDMIDI, WildMidi, WildMidi_Init, [-lWildMidi], [], - [wildmidi], [libwildmidi not found]) -if test x$enable_wildmidi = xyes; then - AC_DEFINE(ENABLE_WILDMIDI, 1, [Define for wildmidi support]) -fi - -AM_CONDITIONAL(ENABLE_WILDMIDI, test x$enable_wildmidi = xyes) - -dnl ------------------------ Post Decoder Plugins Tests ----------------------- - -AM_CONDITIONAL(HAVE_XIPH, - test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_flac = xyes || test x$enable_opus = xyes) +MPD_ENABLE_AUTO_LIB(wildmidi, WILDMIDI, WildMidi, WildMidi_Init, [-lWildMidi], [], + [WildMidi decoder plugin], [libwildmidi not found]) dnl --------------------------------------------------------------------------- dnl Encoders for Streaming Audio Output Plugins @@ -1433,59 +1061,30 @@ fi dnl ------------------------------- FLAC Encoder ------------------------------ -if test x$enable_flac_encoder = xyes; then - AC_DEFINE(ENABLE_FLAC_ENCODER, 1, - [Define to enable the FLAC encoder plugin]) -fi -AM_CONDITIONAL(ENABLE_FLAC_ENCODER, test x$enable_flac_encoder = xyes) +MPD_DEFINE_CONDITIONAL(enable_flac_encoder, ENABLE_FLAC_ENCODER, + [FLAC encoder plugin]) dnl ------------------------------- Shine Encoder ------------------------------ -MPD_AUTO_PKG(shine_encoder, SHINE, [shine >= 3.1], +MPD_ENABLE_AUTO_PKG(shine_encoder, SHINE, [shine >= 3.1], [shine encoder], [libshine not found]) -if test x$enable_shine_encoder = xyes; then - AC_DEFINE(ENABLE_SHINE_ENCODER, 1, - [Define to enable the shine encoder plugin]) -fi -AM_CONDITIONAL(ENABLE_SHINE_ENCODER, test x$enable_shine_encoder = xyes) - dnl ---------------------------- Ogg Vorbis Encoder --------------------------- -MPD_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc vorbis ogg], +MPD_ENABLE_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc vorbis ogg], [Ogg Vorbis encoder], [libvorbisenc not found]) -if test x$enable_vorbis_encoder = xyes; then - AC_DEFINE(ENABLE_VORBIS_ENCODER, 1, - [Define to enable the vorbis encoder plugin]) -fi -AM_CONDITIONAL(ENABLE_VORBIS_ENCODER, test x$enable_vorbis_encoder = xyes) - dnl ------------------------------- LAME Encoder ------------------------------ -MPD_AUTO_LIB(lame_encoder, LAME, mp3lame, lame_init, [-lmp3lame], [], - [libmp3lame], [libmp3lame not found]) -if test x$enable_lame_encoder = xyes; then - AC_DEFINE(ENABLE_LAME_ENCODER, 1, - [Define to enable the lame encoder plugin]) -fi -AM_CONDITIONAL(ENABLE_LAME_ENCODER, test x$enable_lame_encoder = xyes) +MPD_ENABLE_AUTO_LIB(lame_encoder, LAME, mp3lame, lame_init, [-lmp3lame], [], + [LAME encoder plugin], [libmp3lame not found]) dnl ----------------------------- TwoLAME Encoder ----------------------------- -MPD_AUTO_PKG(twolame_encoder, TWOLAME, [twolame], - [TwoLAME encoder], [libtwolame not found]) - -if test x$enable_twolame_encoder = xyes; then - AC_DEFINE(ENABLE_TWOLAME_ENCODER, 1, - [Define to enable the TwoLAME encoder plugin]) -fi -AM_CONDITIONAL(ENABLE_TWOLAME_ENCODER, test x$enable_twolame_encoder = xyes) +MPD_ENABLE_AUTO_PKG(twolame_encoder, TWOLAME, [twolame], + [TwoLAME encoder plugin], [libtwolame not found]) dnl ------------------------------- WAVE Encoder ------------------------------ -AM_CONDITIONAL(ENABLE_WAVE_ENCODER, test x$enable_wave_encoder = xyes) -if test x$enable_wave_encoder = xyes; then - AC_DEFINE(ENABLE_WAVE_ENCODER, 1, - [Define to enable the PCM wave encoder plugin]) -fi +MPD_DEFINE_CONDITIONAL(enable_wave_encoder, ENABLE_WAVE_ENCODER, + [PCM wave encoder plugin]) dnl --------------------------- encoder plugins test -------------------------- if test x$enable_vorbis_encoder != xno || @@ -1506,46 +1105,43 @@ fi fi -if test x$enable_encoder = xyes; then - AC_DEFINE(ENABLE_ENCODER, 1, - [Define to enable the encoder plugins]) -fi -AM_CONDITIONAL(ENABLE_ENCODER, test x$enable_encoder = xyes) -AM_CONDITIONAL(HAVE_OGG_ENCODER, test x$enable_vorbis_encoder = xyes || test x$enable_opus = xyes) +MPD_DEFINE_CONDITIONAL(enable_encoder, ENABLE_ENCODER, + [the encoder plugins]) dnl --------------------------------------------------------------------------- dnl Audio Output Plugins dnl --------------------------------------------------------------------------- dnl ----------------------------------- ALSA ---------------------------------- -MPD_AUTO_PKG(alsa, ALSA, [alsa >= 0.9.0], - [ALSA output plugin], [libasound not found]) - -if test x$enable_alsa = xyes; then - AC_DEFINE(HAVE_ALSA, 1, [Define to enable ALSA support]) -fi - -AM_CONDITIONAL(HAVE_ALSA, test x$enable_alsa = xyes) +MPD_ENABLE_AUTO_PKG(alsa, ALSA, [alsa >= 0.9.0], + [ALSA output plugin], [libasound not found], + [$linux_auto]) dnl ----------------------------------- ROAR ---------------------------------- -MPD_AUTO_PKG(roar, ROAR, [libroar >= 0.4.0], - [ROAR output plugin], [libroar not found]) - -if test x$enable_roar = xyes; then - AC_DEFINE(HAVE_ROAR, 1, [Define to enable ROAR support]) -fi - -AM_CONDITIONAL(HAVE_ROAR, test x$enable_roar = xyes) +MPD_ENABLE_AUTO_PKG(roar, ROAR, [libroar >= 0.4.0], + [RoarAudio output plugin], [libroar not found]) dnl ----------------------------------- FIFO ---------------------------------- if test x$enable_fifo = xyes; then AC_CHECK_FUNC([mkfifo], - [enable_fifo=yes;AC_DEFINE([HAVE_FIFO], 1, - [Define to enable support for writing audio to a FIFO])], + [enable_fifo=yes], [enable_fifo=no;AC_MSG_WARN([mkfifo not found -- disabling support for writing audio to a FIFO])]) fi -AM_CONDITIONAL(HAVE_FIFO, test x$enable_fifo = xyes) +MPD_DEFINE_CONDITIONAL(enable_fifo, HAVE_FIFO, + [support for writing audio to a FIFO]) + +dnl ----------------------------------- SNDIO ---------------------------------- +MPD_ENABLE_AUTO_HEADER([sndio], [SNDIO], [sndio.h], + [-lsndio], [], + [sndio output plugin], + [libsndio not found]) + +dnl ----------------------------------- Haiku --------------------------------- +MPD_ENABLE_AUTO_HEADER([haiku], [HAIKU], [media/MediaDefs.h], + [-lbe -lmedia], [], + [Haiku output plugin], + [Haiku headers not found]) dnl ------------------------------- HTTPD Output ------------------------------ if test x$enable_httpd_output = xauto; then @@ -1559,17 +1155,12 @@ fi fi -if test x$enable_httpd_output = xyes; then - AC_DEFINE(ENABLE_HTTPD_OUTPUT, 1, [Define to enable the HTTP server output]) -fi -AM_CONDITIONAL(ENABLE_HTTPD_OUTPUT, test x$enable_httpd_output = xyes) +MPD_DEFINE_CONDITIONAL(enable_httpd_output, ENABLE_HTTPD_OUTPUT, + [the HTTP server output]) dnl ----------------------------------- JACK ---------------------------------- -MPD_AUTO_PKG(jack, JACK, [jack >= 0.100], +MPD_ENABLE_AUTO_PKG(jack, JACK, [jack >= 0.100], [JACK output plugin], [libjack not found]) -if test x$enable_jack = xyes; then - AC_DEFINE([HAVE_JACK], 1, [Define to enable JACK support]) -fi if test x$enable_jack = xyes; then # check whether jack_set_info_function() is available @@ -1581,16 +1172,9 @@ LIBS=$old_LIBS fi -AM_CONDITIONAL(HAVE_JACK, test x$enable_jack = xyes) - dnl ---------------------------------- libao ---------------------------------- -MPD_AUTO_PKG(ao, AO, [ao], +MPD_ENABLE_AUTO_PKG(ao, AO, [ao], [libao output plugin], [libao not found]) -if test x$enable_ao = xyes; then - AC_DEFINE(HAVE_AO, 1, [Define to play with ao]) -fi - -AM_CONDITIONAL(HAVE_AO, test x$enable_ao = xyes) dnl ---------------------------------- OpenAL --------------------------------- AC_SUBST(OPENAL_CFLAGS,"") @@ -1612,21 +1196,17 @@ [OpenAL output plugin], [OpenAL not found]) fi -if test x$enable_openal = xyes; then - AC_DEFINE(HAVE_OPENAL, 1, [Define for OpenAL support]) -fi - -AM_CONDITIONAL(HAVE_OPENAL, test x$enable_openal = xyes) +MPD_DEFINE_CONDITIONAL(enable_openal, HAVE_OPENAL, [OpenAL support]) dnl ---------------------------- Open Sound System ---------------------------- if test x$enable_oss = xyes; then AC_CHECK_HEADER(sys/soundcard.h, - [enable_oss=yes;AC_DEFINE(HAVE_OSS,1,[Define to enable OSS])], + [enable_oss=yes], [AC_MSG_WARN(Soundcard headers not found -- disabling OSS support); enable_oss=no]) fi -AM_CONDITIONAL(HAVE_OSS, test x$enable_oss = xyes) +MPD_DEFINE_CONDITIONAL(enable_oss, HAVE_OSS, [Open Sound System]) dnl ----------------------------------- OSX ----------------------------------- if test x$enable_osx = xyes; then @@ -1637,21 +1217,12 @@ AM_CONDITIONAL(HAVE_OSX, test x$enable_osx = xyes) dnl ------------------------------- Pipe Output ------------------------------- -if test x$enable_pipe_output = xyes; then - AC_DEFINE([ENABLE_PIPE_OUTPUT], 1, - [Define to enable support for writing audio to a pipe]) -fi -AM_CONDITIONAL(ENABLE_PIPE_OUTPUT, test x$enable_pipe_output = xyes) +MPD_DEFINE_CONDITIONAL(enable_pipe_output, ENABLE_PIPE_OUTPUT, + [support for writing audio to a pipe]) dnl -------------------------------- PulseAudio ------------------------------- -MPD_AUTO_PKG(pulse, PULSE, [libpulse >= 0.9.16], +MPD_ENABLE_AUTO_PKG(pulse, PULSE, [libpulse >= 0.9.16], [PulseAudio output plugin], [libpulse not found]) -if test x$enable_pulse = xyes; then - AC_DEFINE([HAVE_PULSE], 1, - [Define to enable PulseAudio support]) -fi - -AM_CONDITIONAL(HAVE_PULSE, test x$enable_pulse = xyes) dnl --------------------------------- Recorder -------------------------------- if test x$enable_recorder_output = xauto; then @@ -1665,10 +1236,8 @@ fi fi -if test x$enable_recorder_output = xyes; then - AC_DEFINE(ENABLE_RECORDER_OUTPUT, 1, [Define to enable the recorder output]) -fi -AM_CONDITIONAL(ENABLE_RECORDER_OUTPUT, test x$enable_recorder_output = xyes) +MPD_DEFINE_CONDITIONAL(enable_recorder_output, ENABLE_RECORDER_OUTPUT, + [the recorder output]) dnl -------------------------------- SHOUTcast -------------------------------- if test x$enable_shout = xauto; then @@ -1682,18 +1251,13 @@ fi fi -if test x$enable_shout = xyes; then - AC_DEFINE(HAVE_SHOUT, 1, [Define to enable the shoutcast output]) -fi -AM_CONDITIONAL(HAVE_SHOUT, test x$enable_shout = xyes) +MPD_DEFINE_CONDITIONAL(enable_shout, HAVE_SHOUT, + [shoutcast output]) dnl --------------------------------- Solaris --------------------------------- -if test x$enable_solaris_output = xyes; then - AC_DEFINE(ENABLE_SOLARIS_OUTPUT, 1, [Define to enable Solaris /dev/audio support]) -fi - -AM_CONDITIONAL(ENABLE_SOLARIS_OUTPUT, test x$enable_solaris_output = xyes) +MPD_DEFINE_CONDITIONAL(enable_solaris_output, ENABLE_SOLARIS_OUTPUT, + [Solaris /dev/audio support]) dnl --------------------------------- WinMM --------------------------------- @@ -1708,6 +1272,27 @@ AM_CONDITIONAL(ENABLE_WINMM_OUTPUT, test x$enable_winmm_output = xyes) dnl --------------------------------------------------------------------------- +dnl Option groups +dnl --------------------------------------------------------------------------- + +have_ogg=no +if test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_opus = xyes || test x$enable_vorbis_encoder = xyes; then + have_ogg=yes +fi + +have_xiph=no +if test x$have_ogg = xyes || test x$enable_flac = xyes || test x$enable_flac_encoder = xyes; then + have_xiph=yes +fi + +if test x$have_ogg = xyes; then + PKG_CHECK_MODULES([OGG], [ogg],, [AC_MSG_ERROR([libogg not found])]) +fi + +AM_CONDITIONAL(HAVE_OGG, test x$have_ogg = xyes) +AM_CONDITIONAL(HAVE_XIPH, test x$have_xiph = xyes) + +dnl --------------------------------------------------------------------------- dnl Documentation dnl --------------------------------------------------------------------------- if test x$enable_documentation = xyes; then @@ -1758,12 +1343,6 @@ AX_APPEND_COMPILE_FLAGS([-fvisibility=hidden]) AX_APPEND_COMPILE_FLAGS([-fno-threadsafe-statics]) AX_APPEND_COMPILE_FLAGS([-fmerge-all-constants]) - -if test x$no_exceptions = xyes; then - AX_APPEND_COMPILE_FLAGS([-fno-exceptions]) - AX_APPEND_COMPILE_FLAGS([-fno-rtti]) -fi - AX_APPEND_COMPILE_FLAGS([-ffast-math]) AX_APPEND_COMPILE_FLAGS([-ftree-vectorize]) AC_LANG_POP @@ -1871,7 +1450,9 @@ printf '\nPlayback support:\n\t' results(alsa,ALSA) results(fifo,FIFO) +results(sndio,[SNDIO]) results(recorder_output,[File Recorder]) +results(haiku,[Haiku]) results(httpd_output,[HTTP Daemon]) results(jack,[JACK]) printf '\n\t' diff -Nru mpd-0.19.21/debian/changelog mpd-0.20.9/debian/changelog --- mpd-0.19.21/debian/changelog 2016-12-13 20:36:28.000000000 +0000 +++ mpd-0.20.9/debian/changelog 2017-06-19 21:16:18.000000000 +0000 @@ -1,3 +1,31 @@ +mpd (0.20.9-2) unstable; urgency=medium + + * Drop versions on Build-Dependencies satisfied in oldoldstable + * Update to dh compat level 10 + * Declare compliance with Debian Policy 4.0.0 + * Drop prune-doc-data.patch, we should have few Debian-specific patches + * Upload to unstable + + -- Florian Schlichting Mon, 19 Jun 2017 23:16:18 +0200 + +mpd (0.20.9-1) experimental; urgency=medium + + * debian/watch: switch to 0.20 series + * New upstream version 0.20.9 + + -- Florian Schlichting Mon, 19 Jun 2017 18:47:22 +0200 + +mpd (0.20.4-1) experimental; urgency=medium + + * New upstream version 0.20.4 + * Update copyright years, adding new files and copyright holders + * Refresh patches, dropping those included upstream + * Update our mpd.conf according to mpdconf.example + * Update configure options, not enabling sndio for now + * Clean up START_MPD transition ("obsolete after jessie") + + -- Florian Schlichting Tue, 14 Feb 2017 22:11:31 +0100 + mpd (0.19.21-1) unstable; urgency=medium * New upstream version 0.19.20, 0.19.21 diff -Nru mpd-0.19.21/debian/compat mpd-0.20.9/debian/compat --- mpd-0.19.21/debian/compat 2015-03-09 20:55:30.000000000 +0000 +++ mpd-0.20.9/debian/compat 2017-06-19 20:52:59.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru mpd-0.19.21/debian/control mpd-0.20.9/debian/control --- mpd-0.19.21/debian/control 2016-12-12 21:59:22.000000000 +0000 +++ mpd-0.20.9/debian/control 2017-06-19 20:52:59.000000000 +0000 @@ -3,16 +3,12 @@ Priority: optional Maintainer: mpd maintainers Uploaders: Florian Schlichting -Build-Depends: debhelper (>= 9), - dh-autoreconf, - dh-systemd, - dpkg-dev (>= 1.16.1~), +Build-Depends: debhelper (>= 10), libadplug-dev, libao-dev, libasound2-dev [linux-any], - libaudiofile-dev (>= 0.3), + libaudiofile-dev, libavahi-client-dev, - libavahi-glib-dev, libavcodec-dev, libavformat-dev, libboost-dev, @@ -24,7 +20,6 @@ libfaad-dev, libflac-dev, libfluidsynth-dev, - libglib2.0-dev, libgme-dev, libicu-dev, libid3tag0-dev, @@ -44,7 +39,7 @@ libopus-dev, libpulse-dev, libresid-builder-dev, - libroar-dev (>= 0.4), + libroar-dev, libsamplerate0-dev, libshine-dev [arm armel armeb], libshout3-dev, @@ -64,7 +59,7 @@ libyajl-dev, libzzip-dev, xmlto -Standards-Version: 3.9.8 +Standards-Version: 4.0.0 Homepage: https://www.musicpd.org/ Vcs-Browser: https://anonscm.debian.org/cgit/pkg-mpd/pkg-mpd.git Vcs-Git: https://anonscm.debian.org/git/pkg-mpd/pkg-mpd.git diff -Nru mpd-0.19.21/debian/copyright mpd-0.20.9/debian/copyright --- mpd-0.19.21/debian/copyright 2016-08-30 20:26:14.000000000 +0000 +++ mpd-0.20.9/debian/copyright 2017-02-14 19:03:41.000000000 +0000 @@ -1,39 +1,62 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: MPD Source: https://www.musicpd.org/ -Upstream-Contact: Max Kellermann +Upstream-Contact: Max Kellermann Files: * -Copyright: 2003-2016, The Music Player Daemon Project (see AUTHORS for details) +Copyright: 2003-2017, The Music Player Daemon Project (see AUTHORS for details) License: GPL-2+ -Files: src/mixer/plugins/RoarMixerPlugin.cxx - src/output/plugins/RoarOutputPlugin.cxx -Copyright: 2003-2014, The Music Player Daemon Project +Files: src/mixer/plugins/HaikuMixerPlugin.cxx src/mixer/plugins/RoarMixerPlugin.cxx + src/output/plugins/HaikuOutputPlugin.* src/output/plugins/RoarOutputPlugin.cxx +Copyright: 2003-2017, The Music Player Daemon Project 2010-2011, Philipp 'ph3-der-loewe' Schafft 2010-2011, Hans-Kristian 'maister' Arntzen + 2014-2015, François 'mmu_man' Revol License: GPL-2+ +Files: src/mixer/plugins/volume_mapping.* +Copyright: 2010, Clemens Ladisch +License: ISC + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + . + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + Files: src/system/fd_util.c src/system/fd_util.h src/util/RefCount.hxx -Copyright: 2003-2014, The Music Player Daemon Project +Copyright: 2003-2017, The Music Player Daemon Project License: BSD-2-clause -Files: src/java/* src/output/plugins/sles/AndroidSimpleBufferQueue.hxx +Files: src/java/* src/lib/curl/* src/net/AllocatedSocketAddress.* + src/net/SocketAddress.* src/net/StaticSocketAddress.* src/net/ToString.* + src/output/plugins/sles/AndroidSimpleBufferQueue.hxx src/output/plugins/sles/Engine.hxx src/output/plugins/sles/Object.hxx - src/output/plugins/sles/Play.hxx src/system/ByteOrder.hxx src/thread/Cond.hxx - src/thread/CriticalSection.hxx src/thread/Mutex.hxx src/thread/PosixCond.hxx - src/thread/PosixMutex.hxx src/thread/Util.hxx src/thread/WindowsCond.hxx - src/util/ASCII.hxx src/util/Cast.hxx src/util/CharUtil.hxx - src/util/CircularBuffer.hxx src/util/Clamp.hxx src/util/ConstBuffer.hxx - src/util/Domain.hxx src/util/DynamicFifoBuffer.hxx src/util/Error.cxx - src/util/Error.hxx src/util/ForeignFifoBuffer.hxx src/util/HugeAllocator.cxx - src/util/HugeAllocator.hxx src/util/Macros.hxx src/util/Manual.hxx - src/util/NumberParser.hxx src/util/ReusableArray.hxx src/util/ScopeExit.hxx - src/util/StaticFifoBuffer.hxx src/util/TextFile.hxx src/util/Tokenizer.cxx - src/util/Tokenizer.hxx src/util/UTF8.cxx src/util/UTF8.hxx - src/util/VarSize.hxx src/util/WritableBuffer.hxx -Copyright: 2003-2015, Max Kellermann + src/output/plugins/sles/Play.hxx src/system/ByteOrder.hxx src/system/Error.hxx + src/system/FileDescriptor.* src/thread/Cond.hxx src/thread/CriticalSection.hxx + src/thread/Mutex.hxx src/thread/PosixCond.hxx src/thread/PosixMutex.hxx + src/thread/Util.* src/thread/WindowsCond.hxx src/util/ASCII.hxx + src/util/AllocatedArray.* src/util/AllocatedString.* src/util/BindMethod.hxx + src/util/Cast.hxx src/util/CharUtil.hxx src/util/CircularBuffer.hxx + src/util/Clamp.hxx src/util/ConstBuffer.hxx src/util/DeleteDisposer.hxx + src/util/Domain.hxx src/util/DynamicFifoBuffer.hxx src/util/Exception.* + src/util/ForeignFifoBuffer.hxx src/util/HugeAllocator.* + src/util/IterableSplitString.hxx src/util/Macros.hxx src/util/Manual.hxx + src/util/NumberParser.hxx src/util/ReusableArray.hxx src/util/RuntimeError.hxx + src/util/ScopeExit.hxx src/util/SplitString.* src/util/StaticFifoBuffer.hxx + src/util/StringAPI.hxx src/util/StringBuffer.hxx src/util/StringCompare.* + src/util/StringPointer.hxx src/util/StringView.* src/util/TextFile.hxx + src/util/TimeParser.* src/util/Tokenizer.* src/util/UTF8.* + src/util/VarSize.hxx src/util/WStringAPI.hxx src/util/WStringCompare.hxx + src/util/WritableBuffer.hxx +Copyright: 2003-2017, Max Kellermann License: BSD-2-clause Files: src/pcm/dsd2pcm/* @@ -123,12 +146,17 @@ modified version of the Autoconf Macro, you may extend this special exception to the GPL to apply to your modified version as well. -Files: m4/ax_boost_base.m4 m4/ax_cxx_compile_stdcxx_0x.m4 - m4/ax_require_defined.m4 +Files: m4/ax_boost_base.m4 m4/ax_cxx_compile_stdcxx.m4 + m4/ax_cxx_compile_stdcxx_14.m4 m4/ax_require_defined.m4 Copyright: 2008, Benjamin Kosnik 2008, Thomas Porschberg 2009, Peter Adolphs + 2012, Zack Weinberg + 2013, Roy Stogner 2014, Mike Frysinger + 2014-2015, Google Inc.; contributed by Alexey Sokolov + 2015, Paul Norman + 2015, Moritz Klammler License: permissive Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice @@ -137,6 +165,7 @@ Files: m4/pkg.m4 Copyright: 2004, Scott James Remnant + 2012-2015, Dan Nicholson License: GPL-2+_with_Autoconf_exception Files: debian/* @@ -144,7 +173,7 @@ 2004-2005, Eric Wong 2006-2011, Decklin Foster 2011-2012, Alexander Wirt - 2013-2016, Florian Schlichting + 2013-2017, Florian Schlichting License: GPL-2+ Files: debian/source_mpd.py diff -Nru mpd-0.19.21/debian/mpd.conf mpd-0.20.9/debian/mpd.conf --- mpd-0.19.21/debian/mpd.conf 2016-08-18 21:39:19.000000000 +0000 +++ mpd-0.20.9/debian/mpd.conf 2017-02-14 20:47:33.000000000 +0000 @@ -309,6 +309,14 @@ # device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional #} # +# An example of an sndio output. +# +#audio_output { +# type "sndio" +# name "sndio output" +# mixer_type "software" +#} +# ## Example "pipe" output: # #audio_output { @@ -330,13 +338,6 @@ # mixer_type "none" # optional #} # -# If MPD has been compiled with libsamplerate support, this setting specifies -# the sample rate converter to use. Possible values can be found in the -# mpd.conf man page or the libsamplerate documentation. By default, this is -# setting is disabled. -# -#samplerate_converter "Fastest Sinc Interpolator" -# ############################################################################### @@ -386,34 +387,4 @@ # filesystem_charset "UTF-8" # -# This setting controls the encoding that ID3v1 tags should be converted from. -# -id3v1_encoding "UTF-8" -# ############################################################################### - - -# SIDPlay decoder ############################################################# -# -# songlength_database: -# Location of your songlengths file, as distributed with the HVSC. -# The sidplay plugin checks this for matching MD5 fingerprints. -# See http://www.c64.org/HVSC/DOCUMENTS/Songlengths.faq -# -# default_songlength: -# This is the default playing time in seconds for songs not in the -# songlength database, or in case you're not using a database. -# A value of 0 means play indefinitely. -# -# filter: -# Turns the SID filter emulation on or off. -# -#decoder { -# plugin "sidplay" -# songlength_database "/media/C64Music/DOCUMENTS/Songlengths.txt" -# default_songlength "120" -# filter "true" -#} -# -############################################################################### - diff -Nru mpd-0.19.21/debian/mpd.lintian-overrides mpd-0.20.9/debian/mpd.lintian-overrides --- mpd-0.19.21/debian/mpd.lintian-overrides 2016-08-18 22:12:50.000000000 +0000 +++ mpd-0.20.9/debian/mpd.lintian-overrides 2017-02-14 21:20:36.000000000 +0000 @@ -1,6 +1,2 @@ -# update-rc.d is only called on upgrade, which is not forbidden and actually makes sense here -preinst-calls-updaterc.d mpd -# not setting -e on purpose -maintainer-script-ignores-errors preinst # this is from the Avahi API spelling-error-in-binary usr/bin/mpd UNCOMMITED UNCOMMITTED diff -Nru mpd-0.19.21/debian/mpd.postinst mpd-0.20.9/debian/mpd.postinst --- mpd-0.19.21/debian/mpd.postinst 2015-03-21 00:13:19.000000000 +0000 +++ mpd-0.20.9/debian/mpd.postinst 2017-02-14 21:20:36.000000000 +0000 @@ -28,10 +28,4 @@ fi fi -# disable mpd for (new) systemd units if START_MPD was not true -if [ -f /var/lib/mpd/NO_START ]; then - rm /var/lib/mpd/NO_START - deb-systemd-helper update-state mpd.socket mpd.service -fi - #DEBHELPER# diff -Nru mpd-0.19.21/debian/mpd.preinst mpd-0.20.9/debian/mpd.preinst --- mpd-0.19.21/debian/mpd.preinst 2015-03-21 00:15:11.000000000 +0000 +++ mpd-0.20.9/debian/mpd.preinst 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#!/bin/sh - -# don't fail if this doesn't work -#set -e - -ACTION="$1" -VERSION="$2" - -# transition away from START_MPD=false (obsolete after jessie) -if [ "$ACTION" = "upgrade" ]; then - [ -r /etc/default/mpd ] && . /etc/default/mpd - if grep -q START_MPD /etc/default/mpd && [ "x$START_MPD" != "xtrue" ]; then - touch /var/lib/mpd/NO_START - update-rc.d mpd disable > /dev/null - # attempt to reset /etc/default/mpd to unmodified state - sed -i -e's/^START_MPD=.*$/START_MPD=true/' /etc/default/mpd - fi -fi - -#DEBHELPER# diff -Nru mpd-0.19.21/debian/patches/bind-to-address-socket-activation.patch mpd-0.20.9/debian/patches/bind-to-address-socket-activation.patch --- mpd-0.19.21/debian/patches/bind-to-address-socket-activation.patch 2015-08-10 20:03:11.000000000 +0000 +++ mpd-0.20.9/debian/patches/bind-to-address-socket-activation.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -Description: document that socket activation voids bind_to_address setting -Author: Florian Schlichting -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=785418 -Forwarded: http://mailman.blarg.de/pipermail/mpd-devel/2015-June/000363.html - ---- a/doc/mpdconf.example -+++ b/doc/mpdconf.example -@@ -75,7 +75,8 @@ - # - # This setting sets the address for the daemon to listen on. Careful attention - # should be paid if this is assigned to anything other then the default, any. --# This setting can deny access to control of the daemon. -+# This setting can deny access to control of the daemon. Not effective if -+# systemd socket activiation is in use. - # - # For network - #bind_to_address "any" diff -Nru mpd-0.19.21/debian/patches/curl-proxy.patch mpd-0.20.9/debian/patches/curl-proxy.patch --- mpd-0.19.21/debian/patches/curl-proxy.patch 2016-12-13 20:33:41.000000000 +0000 +++ mpd-0.20.9/debian/patches/curl-proxy.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -Description: document effect of http_proxy envvar on curl plugin -Author: Florian Schlichting -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=624774 -Forwarded: http://mailman.blarg.de/pipermail/mpd-devel/2015-June/000363.html - ---- a/doc/user.xml -+++ b/doc/user.xml -@@ -1804,6 +1804,13 @@ - Opens remote files or streams over HTTP. - - -+ -+ Note that unless overridden by the below settings (e.g. by -+ setting them to a blank value), general curl configuration -+ from environment variables such as http_proxy or specified -+ in ~/.curlrc will be in effect. -+ -+ - - - diff -Nru mpd-0.19.21/debian/patches/hurd_pthread.patch mpd-0.20.9/debian/patches/hurd_pthread.patch --- mpd-0.19.21/debian/patches/hurd_pthread.patch 2016-12-12 21:59:29.000000000 +0000 +++ mpd-0.20.9/debian/patches/hurd_pthread.patch 2017-02-14 20:47:23.000000000 +0000 @@ -3,20 +3,9 @@ is special and cannot be used with constexpr. Hence exclude __gnu_hurd__. Author: Florian Schlichting ---- a/src/notify.hxx -+++ b/src/notify.hxx -@@ -28,7 +28,7 @@ - Cond cond; - bool pending; - --#ifdef __GLIBC__ -+#if defined(__GLIBC__) && !defined(__gnu_hurd__) - constexpr - #endif - notify():pending(false) {} --- a/src/thread/PosixCond.hxx +++ b/src/thread/PosixCond.hxx -@@ -41,7 +41,7 @@ +@@ -43,7 +43,7 @@ pthread_cond_t cond; public: diff -Nru mpd-0.19.21/debian/patches/libsystemd.patch mpd-0.20.9/debian/patches/libsystemd.patch --- mpd-0.19.21/debian/patches/libsystemd.patch 2016-12-13 20:33:20.000000000 +0000 +++ mpd-0.20.9/debian/patches/libsystemd.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -Description: transition to libsystemd from deprecated libsystemd-daemon - systemd 209 merged the various libsystemd-* libraries into a single - libsystemd.so, so we check for that instead and rename the configure - option, define, etc accordingly. -Author: Florian Schlichting -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779762 -Forwarded: not-needed (solved in a less invasive and backward-compatible way upstream) - ---- a/configure.ac -+++ b/configure.ac -@@ -586,10 +586,10 @@ - MPD_DEPENDS([enable_sqlite], [enable_glib], - [Cannot use --enable-sqlite with --disable-glib]) - --AC_ARG_ENABLE(systemd-daemon, -- AS_HELP_STRING([--enable-systemd-daemon], -- [use the systemd daemon library (default=auto)]),, -- [enable_systemd_daemon=$linux_auto]) -+AC_ARG_ENABLE(systemd, -+ AS_HELP_STRING([--enable-systemd], -+ [use the systemd library (default=auto)]),, -+ [enable_systemd=$linux_auto]) - - AC_ARG_ENABLE(tcp, - AS_HELP_STRING([--disable-tcp], -@@ -770,11 +770,11 @@ - AC_MSG_ERROR([No client interfaces configured!]) - fi - --MPD_AUTO_PKG(systemd_daemon, SYSTEMD_DAEMON, libsystemd-daemon, -- [systemd activation], [libsystemd-daemon not found]) --AM_CONDITIONAL(ENABLE_SYSTEMD_DAEMON, test x$enable_systemd_daemon = xyes) --if test x$enable_systemd_daemon = xyes; then -- AC_DEFINE([ENABLE_SYSTEMD_DAEMON], 1, [Define to use the systemd daemon library]) -+MPD_AUTO_PKG(systemd, SYSTEMD, libsystemd, -+ [systemd activation], [libsystemd not found]) -+AM_CONDITIONAL(ENABLE_SYSTEMD, test x$enable_systemd = xyes) -+if test x$enable_systemd = xyes; then -+ AC_DEFINE([ENABLE_SYSTEMD], 1, [Define to use the systemd library]) - fi - - dnl --------------------------------------------------------------------------- ---- a/Makefile.am -+++ b/Makefile.am -@@ -58,7 +58,7 @@ - $(ICU_LDADD) \ - libutil.a \ - $(FS_LIBS) \ -- $(SYSTEMD_DAEMON_LIBS) \ -+ $(SYSTEMD_LIBS) \ - $(GLIB_LIBS) - - src_mpd_SOURCES = \ ---- a/config.h.in -+++ b/config.h.in -@@ -75,8 +75,8 @@ - /* Define to enable sqlite database support */ - #undef ENABLE_SQLITE - --/* Define to use the systemd daemon library */ --#undef ENABLE_SYSTEMD_DAEMON -+/* Define to use the systemd library */ -+#undef ENABLE_SYSTEMD - - /* Define to enable the TwoLAME encoder plugin */ - #undef ENABLE_TWOLAME_ENCODER ---- a/src/Listen.cxx -+++ b/src/Listen.cxx -@@ -32,7 +32,7 @@ - #include - #include - --#ifdef ENABLE_SYSTEMD_DAEMON -+#ifdef ENABLE_SYSTEMD - #include - #endif - -@@ -77,7 +77,7 @@ - } - } - --#ifdef ENABLE_SYSTEMD_DAEMON -+#ifdef ENABLE_SYSTEMD - - static bool - listen_systemd_activation(Error &error_r) -@@ -109,7 +109,7 @@ - - listen_socket = new ClientListener(loop, partition); - --#ifdef ENABLE_SYSTEMD_DAEMON -+#ifdef ENABLE_SYSTEMD - if (listen_systemd_activation(error)) - return true; - ---- a/doc/user.xml -+++ b/doc/user.xml -@@ -110,7 +110,7 @@ - libupnp-dev \ - libavahi-client-dev \ - libsqlite3-dev \ -- libsystemd-daemon-dev libwrap0-dev \ -+ libsystemd-dev libwrap0-dev \ - libcppunit-dev xmlto \ - libboost-dev \ - libglib2.0-dev libicu-dev diff -Nru mpd-0.19.21/debian/patches/mpd.service.documentation.patch mpd-0.20.9/debian/patches/mpd.service.documentation.patch --- mpd-0.19.21/debian/patches/mpd.service.documentation.patch 2016-12-13 20:32:42.000000000 +0000 +++ mpd-0.20.9/debian/patches/mpd.service.documentation.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -Description: mpd.service: Set the Documentation option - This makes references to mpd(1) and mpd(5) appear in systemd status output. -Author: Wieland Hoffmann -Origin: upstream - ---- a/systemd/system/mpd.service.in -+++ b/systemd/system/mpd.service.in -@@ -1,5 +1,6 @@ - [Unit] - Description=Music Player Daemon -+Documentation=man:mpd(1) man:mpd.conf(5) - After=network.target sound.target - - [Service] ---- a/systemd/user/mpd.service.in -+++ b/systemd/user/mpd.service.in -@@ -1,5 +1,6 @@ - [Unit] - Description=Music Player Daemon -+Documentation=man:mpd(1) man:mpd.conf(5) - After=network.target sound.target - - [Service] diff -Nru mpd-0.19.21/debian/patches/prune-doc-data.patch mpd-0.20.9/debian/patches/prune-doc-data.patch --- mpd-0.19.21/debian/patches/prune-doc-data.patch 2016-12-13 20:33:47.000000000 +0000 +++ mpd-0.20.9/debian/patches/prune-doc-data.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Description: only install wanted docs -Author: Florian Schlichting -Forwarded: not-needed - ---- a/Makefile.am -+++ b/Makefile.am -@@ -2109,7 +2109,7 @@ - # - - man_MANS = doc/mpd.1 doc/mpd.conf.5 --doc_DATA = AUTHORS COPYING NEWS README doc/mpdconf.example -+doc_DATA = AUTHORS doc/mpdconf.example - - DOCBOOK_FILES = doc/protocol.xml doc/user.xml doc/developer.xml - diff -Nru mpd-0.19.21/debian/patches/series mpd-0.20.9/debian/patches/series --- mpd-0.19.21/debian/patches/series 2016-12-12 21:59:29.000000000 +0000 +++ mpd-0.20.9/debian/patches/series 2017-06-19 21:16:18.000000000 +0000 @@ -1,8 +1,4 @@ +hurd_pthread.patch +# Debian-specific systemd_honor_MPDCONF.patch -libsystemd.patch -curl-proxy.patch -bind-to-address-socket-activation.patch -prune-doc-data.patch -mpd.service.documentation.patch mpd.service.documentation.user.patch -hurd_pthread.patch diff -Nru mpd-0.19.21/debian/patches/systemd_honor_MPDCONF.patch mpd-0.20.9/debian/patches/systemd_honor_MPDCONF.patch --- mpd-0.19.21/debian/patches/systemd_honor_MPDCONF.patch 2016-12-13 20:29:32.000000000 +0000 +++ mpd-0.20.9/debian/patches/systemd_honor_MPDCONF.patch 2017-02-14 08:31:49.000000000 +0000 @@ -4,10 +4,10 @@ --- a/systemd/system/mpd.service.in +++ b/systemd/system/mpd.service.in -@@ -3,7 +3,8 @@ - After=network.target sound.target +@@ -5,7 +5,8 @@ [Service] + Type=notify -ExecStart=@prefix@/bin/mpd --no-daemon +EnvironmentFile=/etc/default/mpd +ExecStart=@prefix@/bin/mpd --no-daemon $MPDCONF diff -Nru mpd-0.19.21/debian/rules mpd-0.20.9/debian/rules --- mpd-0.19.21/debian/rules 2016-12-13 20:28:11.000000000 +0000 +++ mpd-0.20.9/debian/rules 2017-06-19 21:16:18.000000000 +0000 @@ -14,9 +14,9 @@ # no systemd and no alsa on non-linux arches ifeq ($(DEB_HOST_ARCH_OS), linux) -WITH_SYSTEMD=--enable-systemd --with-systemdsystemunitdir=/lib/systemd/system --with-systemduserunitdir=/usr/lib/systemd/user --enable-alsa +WITH_SYSTEMD=--enable-systemd-daemon --with-systemdsystemunitdir=/lib/systemd/system --with-systemduserunitdir=/usr/lib/systemd/user --enable-alsa else -WITH_SYSTEMD=--disable-systemd --disable-alsa +WITH_SYSTEMD=--disable-systemd-daemon --disable-alsa endif # no smbclient on hurd-i386 (#815441) @@ -38,8 +38,6 @@ # Autodiscovery support ENABLE_AUTODISCOVERY=--enable-neighbor-plugins \ - --enable-nfs \ - ${ENABLE_SMBCLIENT} \ --enable-upnp \ --with-zeroconf=avahi @@ -48,6 +46,11 @@ --enable-tcp \ --enable-un +# Storage support +ENABLE_STORAGE=--enable-nfs \ + ${ENABLE_SMBCLIENT} \ + --enable-webdav + # File format support # Note: OggTremor / OggVorbis are in WITH_TREMOR ENABLE_FILEFORMATS=--enable-aac \ @@ -70,15 +73,17 @@ # Other features ENABLE_OTHER=--with-boost \ + --enable-cue \ --enable-database \ --enable-expat \ - --enable-glib \ --enable-icu \ --enable-lsr \ --enable-libmpdclient \ + --enable-libwrap \ --enable-inotify \ --enable-soxr \ - --enable-sqlite + --enable-sqlite \ + --enable-syslog # Metadata support ENABLE_METADATA=--enable-id3 @@ -86,7 +91,9 @@ # Playback support # Note: ALSA is in WITH_SYSTEMD ENABLE_PLAYBACKS=--enable-fifo \ + --disable-sndio \ --enable-recorder-output \ + --disable-haiku \ --enable-httpd-output \ --enable-jack \ --enable-ao \ @@ -99,8 +106,9 @@ # Streaming encoder support # Note: FLAC and Opus enabled under file formats -ENABLE_ENCODERS= --enable-lame-encoder \ +ENABLE_ENCODERS=--enable-lame-encoder \ --enable-vorbis-encoder \ + --disable-twolame-encoder \ --enable-wave-encoder # Streaming support @@ -116,7 +124,7 @@ LDFLAGS += -Wl,--as-needed %: - dh $@ --with autoreconf --with=systemd --parallel + dh $@ override_dh_auto_configure: dh_auto_configure -- $(WITH_TREMOR) $(WITH_SYSTEMD) \ @@ -124,6 +132,7 @@ $(ENABLE_ARCHIVES) \ $(ENABLE_AUTODISCOVERY) \ $(ENABLE_CLIENTS) \ + $(ENABLE_STORAGE) \ $(ENABLE_FILEFORMATS) \ $(ENABLE_OTHER) \ $(ENABLE_METADATA) \ @@ -143,3 +152,4 @@ override_dh_installchangelogs: dh_installchangelogs NEWS + rm debian/mpd/usr/share/doc/mpd/COPYING debian/mpd/usr/share/doc/mpd/NEWS debian/mpd/usr/share/doc/mpd/README.md diff -Nru mpd-0.19.21/debian/watch mpd-0.20.9/debian/watch --- mpd-0.19.21/debian/watch 2016-08-30 20:23:58.000000000 +0000 +++ mpd-0.20.9/debian/watch 2017-06-19 16:21:12.000000000 +0000 @@ -1,3 +1,3 @@ version=3 opts="pgpsigurlmangle=s/$/.sig/" \ -https://www.musicpd.org/download/mpd/stable/mpd-([0-9.]*).tar.xz +https://www.musicpd.org/download/mpd/0.20/mpd-([0-9.]*).tar.xz diff -Nru mpd-0.19.21/doc/developer.xml mpd-0.20.9/doc/developer.xml --- mpd-0.19.21/doc/developer.xml 2016-07-29 08:01:56.000000000 +0000 +++ mpd-0.20.9/doc/developer.xml 2017-05-15 19:50:24.000000000 +0000 @@ -5,7 +5,7 @@ The Music Player Daemon - Developer's Manual - + Introduction @@ -21,7 +21,7 @@ - + Code Style @@ -40,9 +40,35 @@ - the code should be C++11 compliant, and must compile with - GCC 4.7 and - clang 3.2 + comment your code, document your APIs + + + + + + the code should be C++14 compliant, and must compile with + GCC 4.9 and + clang 3.4 + + + + + + report error conditions with C++ exceptions, preferable + derived from std::runtime_error + + + + + + all code must be exception-safe + + + + + + classes and functions names use CamelCase; variables are + lower-case with words separated by underscore @@ -52,9 +78,9 @@ static inline int -foo(const char *abc, int xyz) +Foo(const char *abc, int xyz) { - if (abc == NULL) { + if (abc == nullptr) { LogWarning("Foo happened!"); return -1; } @@ -66,25 +92,25 @@ - + Hacking The Source MPD sources are managed in a git repository on git.musicpd.org. + url="https://github.com/MusicPlayerDaemon/">GitHub. Always write your code against the latest git: - git clone git://git.musicpd.org/master/mpd.git + git clone git://github.com/MusicPlayerDaemon/MPD If you already have a clone, update it: - git pull --rebase git://git.musicpd.org/master/mpd.git master + git pull --rebase git://github.com/MusicPlayerDaemon/MPD master You can do without "--rebase", but we recommend that you rebase @@ -151,7 +177,7 @@ - + Submitting Patches @@ -162,14 +188,11 @@ - git pull requests are preferred. Regular - contributors can get an account on - git.musicpd.org, but any public git repository will do. + git pull requests are preferred. - + Development Tools
diff -Nru mpd-0.19.21/doc/doxygen.conf mpd-0.20.9/doc/doxygen.conf --- mpd-0.19.21/doc/doxygen.conf 2016-12-13 09:52:11.000000000 +0000 +++ mpd-0.20.9/doc/doxygen.conf 2017-06-03 18:58:53.000000000 +0000 @@ -1,96 +1,129 @@ -# Doxyfile 1.5.6 +# Doxyfile 1.8.11 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = MPD -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.19.21 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 0.20.9 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = doc/api -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, -# and Ukrainian. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -98,484 +131,702 @@ # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = /home/max/git/stable-mpd/src/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. -INPUT = /home/max/git/stable-mpd/src/ +INPUT = /home/max/git/stable-mpd/src/ # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = *.h \ + *.hxx + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. -RECURSIVE = NO +RECURSIVE = YES -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = @@ -584,528 +835,1149 @@ # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = NO -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a # standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_HTMLHELP = NO +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -HTML_DYNAMIC_SECTIONS = NO +GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hiererachy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NONE -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /
@@ -537,6 +538,15 @@ + duration: + Introduced with MPD 0.20 + + Duration of the current song in seconds. + + + + + bitrate: instantaneous bitrate in kbps @@ -563,7 +573,12 @@ audio: - sampleRate:bits:channels + + The format emitted by the decoder plugin during + playback, format: + "samplerate:bits:channels". + Check the user manual for a detailed explanation. + @@ -1171,12 +1186,15 @@ plchanges VERSION + START:END Displays changed songs currently in the playlist since - VERSION. + VERSION. Start and end positions may + be given to limit the output to changes in the given + range. To detect songs that were deleted at the end of the @@ -1189,6 +1207,7 @@ plchangesposid VERSION + START:END @@ -1485,15 +1504,15 @@ playlistmove NAME - SONGID - SONGPOS + FROM + TO - Moves SONGID in the playlist - NAME.m3u to the position - SONGPOS. + Moves the song at position FROM in + the playlist NAME.m3u to the + position TO. @@ -1579,6 +1598,7 @@ TYPE WHAT ... + window START:END @@ -1623,6 +1643,13 @@ WHAT is what to find. + + + window can be used to query only a + portion of the real response. The parameter is two + zero-based record numbers; a start number and an end + number. + @@ -1774,7 +1801,7 @@ Clients that are connected via UNIX domain socket may use this command to read the tags of an arbitrary local - file (URI beginning with "file:///"). + file (URI is an absolute path). @@ -1789,8 +1816,7 @@ Read "comments" (i.e. key-value pairs) from the file specified by "URI". This "URI" can be a path relative - to the music directory or a URL in the form - "file:///foo/bar.ogg". + to the music directory or an absolute path. This command may be used to list metadata of remote @@ -1815,6 +1841,7 @@ TYPE WHAT ... + window START:END @@ -2139,6 +2166,30 @@ + + + + + sticker + find + TYPE + URI + NAME + = + VALUE + + + + + Searches for stickers with the given value. + + + + Other supported operators are: + "<", ">" + + + diff -Nru mpd-0.19.21/doc/user.xml mpd-0.20.9/doc/user.xml --- mpd-0.19.21/doc/user.xml 2016-12-13 09:40:57.000000000 +0000 +++ mpd-0.20.9/doc/user.xml 2017-05-16 05:24:02.000000000 +0000 @@ -80,8 +80,35 @@ cd mpd-version - Make sure that all the required libraries and build tools are - installed. The INSTALL file has a list. + In any case, you need: + + + + + + a C++14 compiler (e.g. gcc 4.9 or clang 3.9) + + + + + + Boost 1.46 + + + + + + pkg-config + + + + + + Each plugin usually needs a codec library, which you also need + to install. Check the plugin reference for details about + required libraries. @@ -113,7 +140,7 @@ libsystemd-daemon-dev libwrap0-dev \ libcppunit-dev xmlto \ libboost-dev \ - libglib2.0-dev libicu-dev + libicu-dev @@ -135,6 +162,91 @@ make install + +
+ Compiling for Windows + + + Even though it does not "feel" like a Windows application, + MPD works well under Windows. + Its build process follows the "Linux style", and may seem + awkward for Windows people (who are not used to compiling + their software, anyway). + + + + Basically, there are three ways to compile + MPD for Windows: + + + + + + Build on Windows for Windows. All you need to do is + described above already: configure and make. + + + + For Windows users, this is kind of unusual, because few + Windows users have a GNU toolchain and a UNIX shell + installed. + + + + + + Build on Linux for Windows. This is described above + already: configure and make. You need the mingw-w64 + cross compiler. Pass + --host=i686-w64-mingw32 (32 bit) + or --host=x86_64-w64-mingw32 (64 + bit) to configure. + + + + This is somewhat natural for Linux users. Many + distributions have mingw-w64 + packages. The remaining difficulty here is installing + all the external libraries. And + MPD usually needs many, + making this method cumbersome for the casual user. + + + + + + Build on Linux for Windows using the + MPD's library build script. + + + + + + This section is about the latter. + + + + Just like with the native build, unpack the + MPD source tarball and change + into the directory. Then, instead of + ./configure, type: + + + ./win32/build.py --64 + + + This downloads various library sources, and then configures + and builds MPD (for x64; to build + a 32 bit binary, pass --32). The + resulting EXE files is linked statically, i.e. it contains + all the libraries already, and you do not need carry DLLs + around. It is large, but easy to use. If you wish to have + a small mpd.exe with DLLs, you need to + compile manually, without the build.py + script. + +
@@ -199,6 +311,47 @@ Configuration +
+ The Configuration File + + + MPD reads its configuration from a + text file. Usually, that is + /etc/mpd.conf, unless a different path is + specified on the command line. If you run + MPD as a user daemon (and not as a + system daemon), the configuration is read from + $XDG_CONFIG_HOME/mpd/mpd.conf (usually + ~/.config/mpd/mpd.conf). + + + + Each line in the configuration file contains a setting name + and its value, e.g.: + + + connection_timeout "5" + + + For settings which specify a filesystem path, the tilde is + expanded: + + + music_directory "~/Music" + + + Some of the settings are grouped in blocks with curly braces, + e.g. per-plugin settings: + + + audio_output { + type "alsa" + name "My ALSA output" + device "iec958:CARD=Intel,DEV=0" + mixer_control "PCM" +} +
+
Configuring the music directory @@ -481,8 +634,8 @@ - To configure an audio output manually, add an - audio_output block to + To configure an audio output manually, add one or more + audio_output blocks to mpd.conf: @@ -535,10 +688,11 @@ - Always open the audio output with the specified audio - format (samplerate:bits:channels), regardless of the - format of the input file. This is optional for most - plugins. + Always open the audio output with the specified + audio format + (samplerate:bits:channels), + regardless of the format of the input file. This is + optional for most plugins. Any of the three attributes may be an asterisk to @@ -555,7 +709,20 @@ 24 bit integer samples padded to 32 bit), 32 (signed 32 bit integer samples), f (32 bit floating - point, -1.0 to 1.0). + point, -1.0 to 1.0), "dsd" means + DSD (Direct Stream Digital). For DSD, there are + special cases such as "dsd64", + which allows you to omit the sample rate + (e.g. dsd512:2 for stereo + DSD512, i.e. 22.5792 MHz). + + + The sample rate is special for DSD: + MPD counts the number of + bytes, not bits. Thus, a DSD "bit" rate of 22.5792 + MHz (DSD512) is 2822400 from + MPD's point of view + (44100*512/8). @@ -567,7 +734,9 @@ Specifies whether this audio output is enabled when MPD is started. By - default, all audio outputs are enabled. + default, all audio outputs are enabled. This is just + the default setting when there is no state file; with + a state file, the previous state is restored. @@ -601,7 +770,7 @@ mixer_type - hardware|software|none + hardware|software|null|none Specifies which mixer should be used for this audio @@ -609,8 +778,12 @@ linkend="alsa_output">ALSA, OSS and PulseAudio), the - software mixer or no mixer - (none). By default, the + software mixer, the "null" mixer + (null; allows setting the + volume, but with no effect; this can be used as a + trick to implement an external mixer) or no + mixer (none). By default, the hardware mixer is used for devices which support it, and none for the others. @@ -695,9 +868,11 @@ Configuring playlist plugins - Playlist plugins are used to load remote playlists. This is - not related to MPD's playlist - directory. + Playlist plugins are used to load remote playlists (protocol + commands load, + listplaylist and + listplaylistinfo). This is not related to + MPD's playlist directory. @@ -795,177 +970,10 @@ - The following resamplers are available (if enabled at - compile time): - - - - - - libsamplerate - a.k.a. Secret Rabbit Code (SRC). - - - - - - libsoxr, - the SoX Resampler library - - - - - - internal: low CPU usage, but very poor quality. This is - the fallback if MPD was - compiled without an external resampler. - - - - - - The setting samplerate_converter controls - how MPD shall resample music. - Possible values: + Check the resampler plugin + reference for a list of resamplers and how to + configure them. - - - - - - - Value - - - Description - - - - - - - "internal" - - - The internal resampler. Low CPU usage, but very - poor quality. - - - - - - "soxr very high" - - - Use libsoxr with "Very - High Quality" setting. - - - - - - "soxr high" or - "soxr" - - - Use libsoxr with "High - Quality" setting. - - - - - - "soxr medium" - - - Use libsoxr with "Medium - Quality" setting. - - - - - - "soxr low" - - - Use libsoxr with "Low - Quality" setting. - - - - - - "soxr quick" - - - Use libsoxr with "Quick" - setting. - - - - - - "Best Sinc Interpolator" or - "0" - - - libsamplerate: Band - limited sinc interpolation, best quality, 97dB SNR, - 96% BW. - - - - - - "Medium Sinc Interpolator" or - "1" - - - libsamplerate: Band - limited sinc interpolation, medium quality, 97dB - SNR, 90% BW. - - - - - - "Fastest Sinc Interpolator" or - "2" - - - libsamplerate: Band - limited sinc interpolation, fastest, 97dB SNR, 80% - BW. - - - - - - "ZOH Sinc Interpolator" or - "3" - - - libsamplerate: Zero order - hold interpolator, very fast, very poor quality with - audible distortions. - - - - - - "Linear Interpolator" or - "4" - - - libsamplerate: Linear - interpolator, very fast, poor quality. - - - - -
@@ -1054,6 +1062,40 @@
+
+ The Sticker Database + + + "Stickers" are pieces of information attached to songs. + Some clients use them to store ratings and other volatile + data. This feature requires SQLite, compile-time + configure option --enable-sqlite. + + + + + + + Setting + Description + + + + + + sticker_file + PATH + + + The location of the sticker database. + + + + + +
+
Resource Limitations @@ -1184,30 +1226,79 @@
- - - - Advanced configuration +
+ Zeroconf -
- Satellite setup + + If Zeroconf support (Avahi or Apple's Bonjour) + was enabled at compile time with + --with-zeroconf=..., MPD can announce + its presence on the network. The following settings control + this feature: + - - MPD runs well on weak machines such - as the Raspberry - Pi. However, such hardware tends to not have storage - big enough to hold a music collection. Mounting music from a - file server can be very slow, especially when updating the - database. - + + + + + Setting + Description + + + - - One approach for optimization is running - MPD on the file server, which not - only exports raw files, but also provides access to a readily - scanned database. Example configuration: - + + + zeroconf_enabled + yes|no + + + Enables or disables this feature. Default is + yes. + + + + + + zeroconf_name + NAME + + + The service name to publish via Zeroconf. The + default is "Music Player". + + + + + + +
+
+
+ + + Advanced configuration + +
+ Satellite setup + + + MPD runs well on weak machines such + as the Raspberry + Pi. However, such hardware tends to not have storage + big enough to hold a music collection. Mounting music from a + file server can be very slow, especially when updating the + database. + + + + One approach for optimization is running + MPD on the file server, which not + only exports raw files, but also provides access to a readily + scanned database. Example configuration: + music_directory "nfs://fileserver.local/srv/mp3" #music_directory "smb://fileserver.local/mp3" @@ -1349,6 +1440,8 @@ To exclude a file from the update, create a file called .mpdignore in its parent directory. Each line of that file may contain a list of shell wildcards. + Matching files in the current directory and all subdirectories + are excluded.
@@ -1375,6 +1468,19 @@ offer an interface to edit the queue. + +
+ Stored Playlists + + + Stored playlists are some kind of secondary playlists which + can be created, saved, edited and deleted by the client. They + are addressed by their names. Its contents can be loaded into + the queue, to be played back. The + playlist_directory setting specifies where + those playlists are stored. + +
@@ -1547,6 +1653,291 @@ + + Client Hacks + +
+ External Mixer + + + The setting 'mixer_type + "null"' asks + MPD to pretend that there is a + mixer, but not actually do something. This allows you to + implement a MPD client which + listens for mixer events, queries the + current (fake) volume, and uses it to program an external + mixer. For example, your client can forward this setting to + your amplifier. + +
+
+ + + Troubleshooting + +
+ Where to start + + + Make sure you have the latest MPD + version (via mpd --version, not + mpc version). All the time, bugs are found + and fixed, and your problem might be a bug that is fixed + already. Do not ask for help unless you have the latest + MPD version. The most common + excuse is when your distribution ships an old + MPD version - in that case, please + ask your distribution for help, and not the + MPD project. + + + + Check the log file. Configure 'log_level + "verbose"' or pass + --verbose to mpd. + + + + Sometimes, it is helpful to run MPD + in a terminal and follow what happens. This is how to do it: + + + mpd --stdout --no-daemon --verbose +
+ +
+ Support + +
+ Getting Help + + + The MPD project runs a forum and an IRC + channel (#mpd on Freenode) for requesting + help. Visit the + MPD help page for details + on how to get help. + +
+ +
+ Common Problems + + + + Database + + + + + I can't see my music in the + MPD database! + + + + + + + Check your music_directory + setting. + + + + + + + Does the MPD user + have read permission on all music files, and + read+execute permission on all music directories + (and all of their parent directories)? + + + + + + + Did you update the database? (mpc + update) + + + + + + + Did you enable all relevant decoder plugins at + compile time? mpd --version + will tell you. + + + + + + + + + + MPD doesn't read ID3 + tags! + + + + + You probably compiled MPD + without libid3tag. + mpd --version will tell you. + + + + + + + Playback + + + + I can't hear music on my client! + + + + That problem usually follows a misunderstanding of the + nature of MPD. + MPD is a remote-controlled + music player, not a music distribution system. + Usually, the speakers are connected to the box where + MPD runs, and the + MPD client only sends + control commands, but the client does not actually + play your music. + + + + MPD has output plugins + which allow hearing music on a remote host (such as + httpd), + but that is not MPD's + primary design goal. + + + + + + + "Device or resource busy" + + + + This ALSA error means that another program uses your + sound hardware exclusively. You can stop that + program to allow MPD to + use it. + + + Sometimes, this other program is + PulseAudio, which can + multiplex sound from several applications, to allow + them to share your sound chip. In this case, it + might be a good idea for MPD + to use PulseAudio + as well, instead of using ALSA directly. + + + + + +
+
+ +
+ Reporting Bugs + + + If you believe you found a bug in + MPD, report it on the bug + tracker. + + + + Your bug report should contain: + + + + + + the output of mpd --version + + + + + + your configuration file + (mpd.conf) + + + + + + relevant portions of the log file (--verbose) + + + + + + be clear about what you expect MPD to do, and what is + actually happening + + + + +
+ <application>MPD</application> crashes + + + All MPD crashes are bugs which + must be fixed by a developer, and you should write a bug + report. (Many crash bugs are caused by codec libraries + used by MPD, and then that + library must be fixed; but in any case, the + MPD bug tracker is a good place + to report it first if you don't know.) + + + + A crash bug report needs to contain a "backtrace". + + + + First of all, your MPD executable + must not be "stripped" (i.e. debug information deleted). + The executables shipped with Linux distributions are usually + stripped, but some have so-called "debug" packages (package + mpd-dbg or + mpd-dbgsym on Debian, + mpd-debug on other distributions). + Make sure this package is installed. + + + + You can extract the backtrace from a core dump, or by + running MPD in a debugger, e.g.: + + + gdb --args mpd --stdout --no-daemon --verbose +run + + + As soon as you have reproduced the crash, type + "bt" on the gdb + command prompt. Copy the output to your bug report. + +
+
+
+ Plugin reference @@ -1620,6 +2011,13 @@ database. + + Note that unless overridden by the below settings (e.g. by + setting them to a blank value), general curl configuration + from environment variables such as http_proxy or specified + in ~/.curlrc will be in effect. + + @@ -1647,6 +2045,19 @@ MPD instance. + + + keepalive + yes|no + + + Send TCP keepalive packets to the "master" + MPD instance? This option can + help avoid certain firewalls dropping inactive + connections, at the expensive of a very small amount of + additional network traffic. Disabled by default. + + @@ -1675,11 +2086,23 @@ +
+ <varname>curl</varname> + + + A WebDAV client using libcurl. It is + used when music_directory contains a + http:// or + https:// URI, for example + "https://the.server/dav/". + +
+
<varname>smbclient</varname> - Load music files from a SMB/CIFS server. It used used when + Load music files from a SMB/CIFS server. It is used when music_directory contains a smb:// URI, for example "smb://myfileserver/Music". @@ -1690,7 +2113,7 @@ <varname>nfs</varname> - Load music files from a NFS server. It used used when + Load music files from a NFS server. It is used when music_directory contains a nfs:// URI according to RFC2224, @@ -1765,7 +2188,9 @@ <varname>cdio_paranoia</varname> - Plays audio CDs. The URI has the form: + Plays audio CDs using libcdio. + The URI has the form: "cdda://[DEVICE][/TRACK]". The simplest form cdda:// plays the whole disc in the default drive. @@ -1801,7 +2226,16 @@ <varname>curl</varname> - Opens remote files or streams over HTTP. + Opens remote files or streams over HTTP using libcurl. + + + + Note that unless overridden by the below settings (e.g. by + setting them to a blank value), general curl configuration + from environment variables such as + http_proxy or specified in + ~/.curlrc will be in effect. @@ -1859,6 +2293,21 @@
+
+ <varname>ffmpeg</varname> + + + Access to various network protocols implemented by the + FFmpeg library: + gopher://, + rtp://, + rtsp://, + rtmp://, + rtmpt://, + rtmps:// + +
+
<varname>file</varname> @@ -1871,7 +2320,8 @@ <varname>mms</varname> - Plays streams with the MMS protocol. + Plays streams with the MMS protocol using libmms.
@@ -1923,11 +2373,12 @@
Decoder plugins -
- <varname>dsdiff</varname> +
+ <varname>adplug</varname> - Decodes DFF files containing DSDIFF data (e.g. SACD rips). + Decodes AdLib files using libadplug. @@ -1941,12 +2392,12 @@ - lsbitfirst - yes|no + sample_rate + - Decode the least significant bit first. Default is - no. + The sample rate that shall be synthesized by the + plugin. Defaults to 48000. @@ -1954,21 +2405,30 @@
-
- <varname>dsf</varname> +
+ <varname>audiofile</varname> - Decodes DSF files containing DSDIFF data (e.g. SACD rips). + Decodes WAV and AIFF files using libaudiofile. +
+
+ <varname>faad</varname> + + + Decodes AAC files using libfaad. +
-
- <varname>fluidsynth</varname> +
+ <varname>ffmpeg</varname> - MIDI decoder based on FluidSynth. + Decodes various codecs using FFmpeg. @@ -1982,21 +2442,31 @@ - sample_rate + analyzeduration + VALUE - The sample rate that shall be synthesized by the - plugin. Defaults to 48000. + Sets the FFmpeg muxer option + analyzeduration, which specifies + how many microseconds are analyzed to probe the + input. The FFmpeg + formats documentation has more information. + - soundfont + probesize + VALUE - The absolute path of the soundfont file. Defaults - to - /usr/share/sounds/sf2/FluidR3_GM.sf2. + Sets the FFmpeg muxer option + probesize, which specifies + probing size in bytes, i.e. the size of the data to + analyze to get stream information. The FFmpeg + formats documentation has more information. @@ -2004,12 +2474,20 @@
-
- <varname>mikmod</varname> +
+ <varname>flac</varname> - Module player based on MikMod. + Decodes FLAC files using + libFLAC. + +
+ +
+ <varname>dsdiff</varname> + + + Decodes DFF files containing DSDIFF data (e.g. SACD rips). @@ -2023,21 +2501,12 @@ - loop + lsbitfirst yes|no - Allow backward loops in modules. Default is - no. - - - - - sample_rate - - - Sets the sample rate generated by - libmikmod. Default is 44100. + Decode the least significant bit first. Default is + no. @@ -2045,11 +2514,21 @@
+
+ <varname>dsf</varname> + + + Decodes DSF files containing DSDIFF data (e.g. SACD rips). + + +
+
- <varname>modplug</varname> + <varname>fluidsynth</varname> - Module player based on MODPlug. + MIDI decoder based on FluidSynth. @@ -2063,22 +2542,266 @@ - loop_count + sample_rate - Number of times to loop the module if it uses backward loops. - Default is 0 which prevents looping. - -1 loops forever. + The sample rate that shall be synthesized by the + plugin. Defaults to 48000. - - - -
- -
- <varname>wildmidi</varname> - + + + soundfont + + + The absolute path of the soundfont file. Defaults + to + /usr/share/sounds/sf2/FluidR3_GM.sf2. + + + + + +
+ +
+ <varname>gme</varname> + + + Video game music file emulator based on game-music-emu. + + + + + + + Setting + Description + + + + + + accuracy + yes|no + + + Enable more accurate sound emulation. + + + + + +
+ +
+ <varname>mad</varname> + + + Decodes MP3 files using libmad. + +
+ +
+ <varname>mikmod</varname> + + + Module player based on MikMod. + + + + + + + Setting + Description + + + + + + loop + yes|no + + + Allow backward loops in modules. Default is + no. + + + + + sample_rate + + + Sets the sample rate generated by + libmikmod. Default is 44100. + + + + + +
+ +
+ <varname>modplug</varname> + + + Module player based on MODPlug. + + + + + + + Setting + Description + + + + + + loop_count + + + Number of times to loop the module if it uses backward loops. + Default is 0 which prevents looping. + -1 loops forever. + + + + + +
+ +
+ <varname>mpcdec</varname> + + + Decodes Musepack files using libmpcdec. + +
+ +
+ <varname>mpg123</varname> + + + Decodes MP3 files using libmpg123. + +
+ +
+ <varname>opus</varname> + + + Decodes Opus files using libopus. + +
+ +
+ <varname>pcm</varname> + + + Read raw PCM samples. It understands the "audio/L16" MIME + type with parameters "rate" and "channels" according to RFC + 2586. It also understands the + MPD-specific MIME type + "audio/x-mpd-float". + +
+ +
+ <varname>sidplay</varname> + + + C64 SID decoder based on libsidplay. + + + + + + + Setting + Description + + + + + + songlength_database + PATH + + + Location of your songlengths file, as distributed + with the HVSC. The sidplay + plugin checks this for matching MD5 fingerprints. + See . + + + + + + default_songlength + SECONDS + + + This is the default playing time in seconds for + songs not in the songlength database, or in case + you're not using a database. A value of 0 means + play indefinitely. + + + + + + filter + yes|no + + + Turns the SID filter emulation on or off. + + + + + +
+ +
+ <varname>sndfile</varname> + + + Decodes WAV and AIFF files using libsndfile. + +
+ +
+ <varname>vorbis</varname> + + + Decodes Ogg-Vorbis files using libvorbis. + +
+ +
+ <varname>wavpack</varname> + + + Decodes WavPack files using + libwavpack. + +
+ +
+ <varname>wildmidi</varname> + MIDI decoder based on libwildmidi. @@ -2190,76 +2913,291 @@ <varname>null</varname> - Does not encode anything, passes the input PCM data as-is. + Does not encode anything, passes the input PCM data as-is. + +
+ +
+ <varname>shine</varname> + + + Encodes into MP3 using the Shine + library. + + + + + + + Setting + Description + + + + + + bitrate + + + Sets the bit rate in kilobit per second. + + + + + +
+ +
+ <varname>twolame</varname> + + + Encodes into MP2 using the TwoLAME + library. + + + + + + + Setting + Description + + + + + + quality + + + Sets the quality for VBR. 0 is the highest quality, + 9 is the lowest quality. Cannot be used with + bitrate. + + + + + bitrate + + + Sets the bit rate in kilobit per second. Cannot be + used with quality. + + + + + +
+ +
+ <varname>vorbis</varname> + + + Encodes into Ogg + Vorbis. + + + + + + + Setting + Description + + + + + + quality + + + Sets the quality for VBR. -1 is the lowest quality, + 10 is the highest quality. Cannot be used with + bitrate. + + + + + bitrate + + + Sets the bit rate in kilobit per second. Cannot be + used with quality. + + + + + +
+ +
+ <varname>wave</varname> + + + Encodes into WAV (lossless). + +
+
+ +
+ Resampler plugins + + + The resampler can be configured in a block named + resampler, for example: + + + resampler { + plugin "soxr" + quality "very high" +} + + + The following table lists the resampler + options valid for all plugins: + + + + + + + + Name + + + Description + + + + + + + plugin + + + The name of the plugin. + + + + + + +
+ <varname>internal</varname> + + + A resampler built into MPD. Its + quality is very poor, but its CPU usage is low. This is the + fallback if MPD was compiled + without an external resampler.
-
- <varname>shine</varname> +
+ <varname>libsamplerate</varname> - Encodes into MP3 using the Shine - library. + A resampler using libsamplerate + a.k.a. Secret Rabbit Code (SRC). - Setting - Description + + Name + + + Description + - bitrate + type - Sets the bit rate in kilobit per second. + The interpolator type. See below for a list of + known types. -
- -
- <varname>twolame</varname> - Encodes into MP2 using the TwoLAME - library. + The following converter types are provided by + libsamplerate: - Setting - Description + + Type + + + Description + - quality + "Best Sinc Interpolator" or + "0" - Sets the quality for VBR. 0 is the highest quality, - 9 is the lowest quality. Cannot be used with - bitrate. + Band limited sinc interpolation, best quality, 97dB + SNR, 96% BW. + - bitrate + "Medium Sinc Interpolator" or + "1" - Sets the bit rate in kilobit per second. Cannot be - used with quality. + Band limited sinc interpolation, medium quality, + 97dB SNR, 90% BW. + + + + + + "Fastest Sinc Interpolator" or + "2" + + + Band limited sinc interpolation, fastest, 97dB SNR, + 80% BW. + + + + + + "ZOH Sinc Interpolator" or + "3" + + + Zero order hold interpolator, very fast, very poor + quality with audible distortions. + + + + + + "Linear Interpolator" or + "4" + + + Linear interpolator, very fast, poor quality. @@ -2267,20 +3205,25 @@
-
- <varname>vorbis</varname> +
+ <varname>soxr</varname> - Encodes into Ogg - Vorbis. + A resampler using libsoxr, + the SoX Resampler library - Setting - Description + + Name + + + Description + @@ -2289,32 +3232,57 @@ quality - Sets the quality for VBR. -1 is the lowest quality, - 10 is the highest quality. Cannot be used with - bitrate. + The libsoxr quality + setting. Valid values are: + + + + + "very high" + + + + + + "high" (the default) + + + + + + "medium" + + + + + + "low" + + + + + + "quick" + + + + - bitrate + threads - Sets the bit rate in kilobit per second. Cannot be - used with quality. + The number of libsoxr + threads. "0" means "automatic". The default is "1" + which disables multi-threading.
- -
- <varname>wave</varname> - - - Encodes into WAV (lossless). - -
@@ -2360,17 +3328,6 @@ - use_mmap - yes|no - - - If set to yes, then - libasound will try to use - memory mapped I/O. - - - - buffer_time US @@ -2572,6 +3529,51 @@
+ <varname>sndio</varname> + + + The sndio plugin uses the sndio library. It should normally be used + on OpenBSD. + + + + + + + Setting + Description + + + + + + device + NAME + + + The audio output device libsndio + will attempt to use. The default is "default" which + causes libsndio to select the first output device. + + + + + + buffer_time + MS + + + Set the application buffer time in milliseconds. + + + + + + +
+ +
<varname>fifo</varname> @@ -2617,7 +3619,7 @@
-
+
<varname>jack</varname> @@ -2897,7 +3899,7 @@
-
+
<varname>openal</varname> @@ -2938,6 +3940,77 @@ The "Mac OS X" plugin uses Apple's CoreAudio API. + + + + + Setting + Description + + + + + + device + NAME + + + Sets the device which should be used. Uses device names as listed in the + "Audio Devices" window of "Audio MIDI Setup". + + + + + hog_device + yes|no + + + Hog the device. This means that it takes exclusive control of the audio + output device it is playing through, and no other program can access it. + + + + + sync_sample_rate + yes|no + + + Synchronize the sample rate. It will try to set the output device sample + rate to the corresponding sample rate of the file playing. If the output + device does not support the sample rate the track has, it will try to + select the best possible for each file. + + + + + channel_map + SOURCE,SOURCE,... + + + Specifies a channel map. If your audio device has more than two + outputs this allows you to route audio to auxillary outputs. For + predictable results you should also specify a "format" with a fixed + number of channels, e.g. "*:*:2". The number of items in the channel + map must match the number of output channels of your output device. + Each list entry specifies the source for that output channel; use "-1" + to silence an output. For example, if you have a four-channel output + device and you wish to send stereo sound (format "*:*:2") to outputs 3 + and 4 while leaving outputs 1 and 2 silent then set the channel map to + "-1,-1,0,1". In this example '0' and '1' denote the left and right + channel respectively. + + + The channel map may not refer to outputs that do not exist according + to the format. If the format is "*:*:1" (mono) and you have a + four-channel sound card then "-1,-1,0,0" (dual mono output on the + second pair of sound card outputs) is a valid channel map but + "-1,-1,0,1" is not because the second channel ('1') does not exist + when the output is mono. + + + + +
@@ -2977,7 +4050,7 @@ The pulse plugin connects to a PulseAudio - server. + server. Requires libpulse. @@ -3091,6 +4164,55 @@ Write to this file. + + + + format_path + P + + + + An alternative to path which + provides a format string referring to tag values. + + The special tag iso8601 emits + the current date and time in ISO8601 + format (UTC). + Every time a new song starts or a new tag gets + received from a radio station, a new file is + opened. If the format does not render a file + name, nothing is recorded. + + + + A tag name enclosed in percent signs ('%') is + replaced with the tag value. Example: + ~/.mpd/recorder/%artist% - + %title%.ogg + + + + Square brackets can be used to group a substring. + If none of the tags referred in the group can be + found, the whole group is omitted. Example: + [~/.mpd/recorder/[%artist% - + ]%title%.ogg] (this omits the dash + when no artist tag exists; if title also doesn't + exist, no file is written) + + + + The operators "|" (logical "or") and "&" + (logical "and") can be used to select portions of + the format string depending on the existing tag + values. Example: + ~/.mpd/recorder/[%title%|%name%].ogg + (use the "name" tag if no title exists) + + + + encoder @@ -3116,7 +4238,8 @@ url="http://www.shoutcast.com/">ShoutCast or IceCast - server. It forwards tags to this server. + server using libshout. It forwards + tags to this server. @@ -3307,6 +4430,22 @@ Playlist plugins
+ <varname>asx</varname> + + + Reads .asx playlist files. + +
+ +
+ <varname>cue</varname> + + + Reads .cue files. + +
+ +
<varname>embcue</varname> @@ -3331,6 +4470,15 @@
+ <varname>flac</varname> + + + Reads the cuesheet metablock from a FLAC + file. + +
+ +
<varname>pls</varname> @@ -3339,6 +4487,45 @@
+ <varname>rss</varname> + + + Reads music links from .rss files. + +
+ +
+ <varname>soundcloud</varname> + + + Download playlist from SoundCloud. It accepts URIs starting + with soundcloud://. + + + + + + + Setting + Description + + + + + + apikey + KEY + + + An API key to access the SoundCloud servers. + + + + + +
+ +
<varname>xspf</varname> diff -Nru mpd-0.19.21/INSTALL mpd-0.20.9/INSTALL --- mpd-0.19.21/INSTALL 2016-07-29 08:01:56.000000000 +0000 +++ mpd-0.20.9/INSTALL 1970-01-01 00:00:00.000000000 +0000 @@ -1,209 +0,0 @@ - Music Player Daemon (MPD) - INSTALL - - -Introduction ------------- - -This document is a very small amount of documentation about what is needed to -install MPD. If more information is desired, read the user manual: - - http://www.musicpd.org/doc/user/ - -Dependencies ------------- - -gcc 4.7 or later - http://gcc.gnu.org/ -clang 3.2 or later - http://clang.llvm.org/ -Any other C++11 compliant compiler should also work. - -Boost 1.46 - http://www.boost.org/ - -GLib 2.28 - http://www.gtk.org/ -General-purpose utility library. - - -Optional Output Dependencies ----------------------------- - -You will need at least one of these to compile MPD. - -Most of these are available as packages on major distributions. Be sure to -install both the library package as well as the development package. - -AO - http://www.xiph.org/ao/ -A portable library that abstracts many audio output types as one API. Should -be used only if there is no native plugin available or if the native plugin -doesn't work. You will need libao. - -ALSA - http://www.alsa-project.org/ -The Advanced Linux Sound Architecture. Recommended audio output if you use -Linux. You will need libasound. - -FIFO -This is a mostly undocumented, developer plugin to transmit raw data. - -OSS - http://www.opensound.com -Open Sound System. - -PulseAudio - http://www.pulseaudio.org/ -An advanced sound daemon. You will need libpulse. - -JACK - http://www.jackaudio.org/ -A low-latency sound daemon. - -libshout - http://www.icecast.org/ -For streaming to an Icecast or Shoutcast server. -You also need an encoder: either libvorbisenc (ogg), or liblame (mp3). - -OpenAL - http://kcat.strangesoft.net/openal.html -Open Audio Library - - -Optional Input Dependencies ---------------------------- - -You will need at least one of these to compile MPD. - -Most of these are available as packages on major distributions. Be sure to -install both the library package as well as the development package. - -MAD - http://www.underbit.com/products/mad/ -For MP3 support. You will need libmad, and optionally libid3tag if you want -ID3 tag support. - -libmpg123 - http://www.mpg123.de/ -Alternative for MP3 support. - -Ogg Vorbis - http://www.xiph.org/ogg/vorbis/ -For Ogg Vorbis support. You will need libogg and libvorbis. - -libopus - http://www.opus-codec.org/ -Opus codec support - -FLAC - http://flac.sourceforge.net/ -For FLAC support. You will need version 1.2 or higher of libFLAC. - -Audio File - http://www.68k.org/~michael/audiofile/ -For WAVE, AIFF, and AU support. You will need libaudiofile. - -FAAD2 - http://www.audiocoding.com/ -For MP4/AAC support. - -libmpcdec - http://www.musepack.net/ -For Musepack support. - -MikMod - http://mikmod.raphnet.net/ -For MOD support. You will need libmikmod. - -libavcodec, libavformat (ffmpeg or libav) - http://ffmpeg.mplayerhq.hu/ http://libav.org/ -Multi-codec library. - -libsidplay2 - http://sidplay2.sourceforge.net/ -For C64 SID support. - -libfluidsynth - http://fluidsynth.resonance.org/ -For MIDI support. - -libwildmidi 0.2.3 - http://wildmidi.sourceforge.net/ -For MIDI support. - -libsndfile - http://www.mega-nerd.com/libsndfile/ -WAVE, AIFF, and many others. - -libwavpack - http://www.wavpack.com/ -For WavPack playback. - -libadplug - http://adplug.sourceforge.net/ -For AdLib playback. - - -Optional Miscellaneous Dependencies ------------------------------------ - -Avahi - http://www.avahi.org/ -For Zeroconf support. - -libsamplerate - http://www.mega-nerd.com/SRC/ -For advanced samplerate conversions. - -libcurl - http://curl.haxx.se/ -For playing HTTP streams. - -libmms - https://launchpad.net/libmms -For playing MMS streams. - -SQLite - http://www.sqlite.org/ -For the sticker database. - -libcdio - http://www.gnu.org/software/libcdio/ -For playing audio CDs. - -libsystemd-daemon - http://freedesktop.org/wiki/Software/systemd/ -For systemd activation. - - -pkg-config ----------- - -MPD uses pkg-config to locate most external libraries. If you do not -have pkg-config, or if your version of the library does not ship the -".pc" file, you have to provide the library's build options in -environment variables. These variables are documented in "./configure ---help". Example: - - FLAC_CFLAGS=-I/usr/include/FLAC FLAC_LIBS=-lFLAC ./configure - - -Download --------- - -Get the latest release from of MPD from . - -Compile -------- - -1) unpack the archive - -$ tar xf mpd-x.x.x.tar.xz - -2) change to directory created - -$ cd mpd-x.x.x - -3) Run configure script (this will determine what dependencies you have) - -$ ./configure - -4) Compile - -$ make - -Install (Optional) -------- - -(as root) -$ make install - -Run ---- - -1) run mpd: - -$ mpd - -First default is $XDG_CONFIG_HOME/mpd/mpd.conf then ~/.mpdconf then -~/.mpd/mpd.conf then /etc/mpd.conf. If neither of these exist a mpd -configuration file must be specified at runtime. - -A sample config file is included with the source of MPD, mpdconf.example. - -The first time MPD is run it will attempt to discover all music in your -music root, recursively. This can be affected by the symbolic link -options specified in the example mpd.conf. - -Using MPD ---------- - -You can download many different interfaces for MPD at - - http://www.musicpd.org/clients/ diff -Nru mpd-0.19.21/m4/ax_append_compile_flags.m4 mpd-0.20.9/m4/ax_append_compile_flags.m4 --- mpd-0.19.21/m4/ax_append_compile_flags.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_append_compile_flags.m4 2017-01-27 07:46:51.000000000 +0000 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS]) +# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -20,6 +20,8 @@ # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: This macro depends on the AX_APPEND_FLAG and # AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with # AX_APPEND_LINK_FLAGS. @@ -54,12 +56,12 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 4 +#serial 5 AC_DEFUN([AX_APPEND_COMPILE_FLAGS], [AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do - AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3]) + AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) done ])dnl AX_APPEND_COMPILE_FLAGS diff -Nru mpd-0.19.21/m4/ax_append_flag.m4 mpd-0.20.9/m4/ax_append_flag.m4 --- mpd-0.19.21/m4/ax_append_flag.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_append_flag.m4 2017-01-27 07:46:51.000000000 +0000 @@ -49,21 +49,23 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 6 AC_DEFUN([AX_APPEND_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl -AS_VAR_SET_IF(FLAGS, - [case " AS_VAR_GET(FLAGS) " in - *" $1 "*) - AC_RUN_LOG([: FLAGS already contains $1]) - ;; - *) - AC_RUN_LOG([: FLAGS="$FLAGS $1"]) - AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) - ;; - esac], - [AS_VAR_SET(FLAGS,["$1"])]) +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG diff -Nru mpd-0.19.21/m4/ax_append_link_flags.m4 mpd-0.20.9/m4/ax_append_link_flags.m4 --- mpd-0.19.21/m4/ax_append_link_flags.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_append_link_flags.m4 2017-01-27 07:46:51.000000000 +0000 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS]) +# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG. # Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS. # @@ -52,12 +54,12 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 4 +#serial 5 AC_DEFUN([AX_APPEND_LINK_FLAGS], [AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do - AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3]) + AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4]) done ])dnl AX_APPEND_LINK_FLAGS diff -Nru mpd-0.19.21/m4/ax_boost_base.m4 mpd-0.20.9/m4/ax_boost_base.m4 --- mpd-0.19.21/m4/ax_boost_base.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_boost_base.m4 2017-01-27 07:46:51.000000000 +0000 @@ -33,7 +33,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 23 +#serial 27 AC_DEFUN([AX_BOOST_BASE], [ @@ -92,7 +92,10 @@ libsubdirs="lib" ax_arch=`uname -m` case $ax_arch in - x86_64|ppc64|s390x|sparc64|aarch64) + x86_64) + libsubdirs="lib64 libx32 lib lib64" + ;; + ppc64|s390x|sparc64|aarch64|ppc64le) libsubdirs="lib64 lib lib64" ;; esac @@ -170,6 +173,10 @@ dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version if test "x$succeeded" != "xyes"; then + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + BOOST_CPPFLAGS= + BOOST_LDFLAGS= _version=0 if test "$ac_boost_path" != ""; then if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then @@ -182,6 +189,12 @@ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" done + dnl if nothing found search for layout used in Windows distributions + if test -z "$BOOST_CPPFLAGS"; then + if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then + BOOST_CPPFLAGS="-I$ac_boost_path" + fi + fi fi else if test "$cross_compiling" != yes; then diff -Nru mpd-0.19.21/m4/ax_check_compile_flag.m4 mpd-0.20.9/m4/ax_check_compile_flag.m4 --- mpd-0.19.21/m4/ax_check_compile_flag.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_check_compile_flag.m4 2017-01-27 07:46:51.000000000 +0000 @@ -55,10 +55,10 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 3 +#serial 4 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS @@ -67,7 +67,7 @@ [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff -Nru mpd-0.19.21/m4/ax_check_link_flag.m4 mpd-0.20.9/m4/ax_check_link_flag.m4 --- mpd-0.19.21/m4/ax_check_link_flag.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_check_link_flag.m4 2017-01-27 07:46:51.000000000 +0000 @@ -55,10 +55,11 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 3 +#serial 4 AC_DEFUN([AX_CHECK_LINK_FLAG], -[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" @@ -66,7 +67,7 @@ [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff -Nru mpd-0.19.21/m4/ax_cxx_compile_stdcxx_0x.m4 mpd-0.20.9/m4/ax_cxx_compile_stdcxx_0x.m4 --- mpd-0.19.21/m4/ax_cxx_compile_stdcxx_0x.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_cxx_compile_stdcxx_0x.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html -# ============================================================================ -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX_0X -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the C++0x -# standard. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 7 - -AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X]) -AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [ - AC_CACHE_CHECK(if g++ supports C++0x features without additional flags, - ax_cv_cxx_compile_cxx0x_native, - [AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_COMPILE([ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c);],, - ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no) - AC_LANG_RESTORE - ]) - - AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x, - ax_cv_cxx_compile_cxx0x_cxx, - [AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -std=c++0x" - AC_TRY_COMPILE([ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c);],, - ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no) - CXXFLAGS="$ac_save_CXXFLAGS" - AC_LANG_RESTORE - ]) - - AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x, - ax_cv_cxx_compile_cxx0x_gxx, - [AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -std=gnu++0x" - AC_TRY_COMPILE([ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c);],, - ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no) - CXXFLAGS="$ac_save_CXXFLAGS" - AC_LANG_RESTORE - ]) - - if test "$ax_cv_cxx_compile_cxx0x_native" = yes || - test "$ax_cv_cxx_compile_cxx0x_cxx" = yes || - test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then - AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ]) - fi -]) diff -Nru mpd-0.19.21/m4/ax_cxx_compile_stdcxx_14.m4 mpd-0.20.9/m4/ax_cxx_compile_stdcxx_14.m4 --- mpd-0.19.21/m4/ax_cxx_compile_stdcxx_14.m4 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/m4/ax_cxx_compile_stdcxx_14.m4 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,34 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++14 +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++14. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 4 + +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])]) diff -Nru mpd-0.19.21/m4/ax_cxx_compile_stdcxx.m4 mpd-0.20.9/m4/ax_cxx_compile_stdcxx.m4 --- mpd-0.19.21/m4/ax_cxx_compile_stdcxx.m4 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/m4/ax_cxx_compile_stdcxx.m4 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,564 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 4 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [], + [$1], [14], [], + [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++$1 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201300L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + +#ifdef DISALLOW_GCC48 + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } +#endif + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) diff -Nru mpd-0.19.21/m4/ax_pthread.m4 mpd-0.20.9/m4/ax_pthread.m4 --- mpd-0.19.21/m4/ax_pthread.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ax_pthread.m4 2017-01-27 07:46:51.000000000 +0000 @@ -19,10 +19,10 @@ # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with +# but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # -# If you are only building threads programs, you may wish to use these +# If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" @@ -30,8 +30,8 @@ # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with @@ -82,35 +82,40 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 21 +#serial 23 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) - if test x"$ax_pthread_ok" = xno; then + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -123,7 +128,7 @@ # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -132,82 +137,225 @@ # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" ;; - darwin*) - ax_pthread_flags="-pthread $ax_pthread_flags" + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" ;; esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac -# Clang doesn't consider unrecognized options an error unless we specify -# -Werror. We throw in some extra Clang-specific options to ensure that -# this doesn't happen for GCC, which also accepts -Werror. - -AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) -save_CFLAGS="$CFLAGS" -ax_pthread_extra_flags="-Werror" -CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], - [AC_MSG_RESULT([yes])], - [ax_pthread_extra_flags= - AC_MSG_RESULT([no])]) -CFLAGS="$save_CFLAGS" +fi # $ax_pthread_clang = yes -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do - case $flag in + case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - if test x"$ax_pthread_config" = xno; then continue; fi + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -218,7 +366,11 @@ # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; @@ -227,16 +379,14 @@ pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) + [ax_pthread_ok=yes], + []) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = xyes; then - break; - fi + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" @@ -244,71 +394,74 @@ fi # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT([$attr_name]) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - # TODO: What about Clang on Solaris? - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT([$flag]) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then + if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi @@ -321,7 +474,7 @@ AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then +if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else diff -Nru mpd-0.19.21/m4/faad.m4 mpd-0.20.9/m4/faad.m4 --- mpd-0.19.21/m4/faad.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/faad.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -AC_DEFUN([AM_PATH_FAAD], -[dnl ## -dnl faad -dnl ## - -AC_ARG_ENABLE(aac, - AS_HELP_STRING([--disable-aac], - [disable AAC support (default: enable)]),, - enable_aac=yes) - -if test x$enable_aac = xyes; then - FAAD_LIBS="-lfaad" - FAAD_CFLAGS="" - - oldcflags=$CFLAGS - oldlibs=$LIBS - oldcppflags=$CPPFLAGS - CFLAGS="$CFLAGS $FAAD_CFLAGS" - LIBS="$LIBS $FAAD_LIBS" - CPPFLAGS=$CFLAGS - AC_CHECK_HEADER(faad.h,,enable_aac=no) - if test x$enable_aac = xyes; then - AC_CHECK_DECL(FAAD2_VERSION,,enable_aac=no,[#include ]) - fi - if test x$enable_aac = xyes; then - AC_CHECK_LIB(faad,NeAACDecInit2,,enable_aac=no) - fi - if test x$enable_aac = xyes; then - AC_MSG_CHECKING(that FAAD2 can even be used) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ -#include - -int main() { - char buffer; - NeAACDecHandle decoder; - NeAACDecFrameInfo frameInfo; - NeAACDecConfigurationPtr config; - unsigned char channels; - long sampleRate; - long bufferlen = 0; - - decoder = NeAACDecOpen(); - config = NeAACDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - NeAACDecSetConfiguration(decoder,config); - NeAACDecInit(decoder,&buffer,bufferlen,&sampleRate,&channels); - NeAACDecInit2(decoder,&buffer,bufferlen,&sampleRate,&channels); - NeAACDecDecode(decoder,&frameInfo,&buffer,bufferlen); - NeAACDecClose(decoder); - - return 0; -} -])],AC_MSG_RESULT(yes),[AC_MSG_RESULT(no);enable_aac=no]) - fi - if test x$enable_aac = xyes; then - AC_DEFINE(HAVE_FAAD,1,[Define to use FAAD2 for AAC decoding]) - else - AC_MSG_WARN([faad2 lib needed for MP4/AAC support -- disabling MP4/AAC support]) - fi - CFLAGS=$oldcflags - LIBS=$oldlibs - CPPFLAGS=$oldcppflags -fi - -if test x$enable_aac = xno; then - FAAD_LIBS="" - FAAD_CFLAGS="" -fi - -AC_SUBST(FAAD_CFLAGS) -AC_SUBST(FAAD_LIBS) - -]) diff -Nru mpd-0.19.21/m4/mpd_auto.m4 mpd-0.20.9/m4/mpd_auto.m4 --- mpd-0.19.21/m4/mpd_auto.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/mpd_auto.m4 2017-01-27 07:46:51.000000000 +0000 @@ -1,23 +1,18 @@ +dnl Parameters: varname1, description AC_DEFUN([MPD_AUTO_ENABLED], [ - var="enable_$1" - feature="$2" - - if eval "test x`echo '$'$var` = xauto"; then - AC_MSG_NOTICE([auto-detected $feature]) - eval "$var=yes" + if test x$[]enable_$1 = xauto; then + AC_MSG_NOTICE([auto-detected $2]) + enable_$1=yes fi ]) +dnl Parameters: varname1, description, errmsg AC_DEFUN([MPD_AUTO_DISABLED], [ - var="enable_$1" - feature="$2" - msg="$3" - - if eval "test x`echo '$'$var` = xauto"; then - AC_MSG_WARN([$msg -- disabling $feature]) - eval "$var=no" - elif eval "test x`echo '$'$var` = xyes"; then - AC_MSG_ERROR([$feature: $msg]) + if test x$[]enable_$1 = xauto; then + AC_MSG_WARN([$3 -- disabling $2]) + enable_$1=no + elif test x$[]enable_$1 = xyes; then + AC_MSG_ERROR([$2: $3]) fi ]) @@ -25,59 +20,59 @@ dnl very similar to MPD_AUTO_RESULT, but does not finalize the dnl detection; it assumes that more checks will follow. AC_DEFUN([MPD_AUTO_PRE], [ - name="$1" - var="enable_$1" - found="found_$name" - feature="$2" - msg="$3" - - if eval "test x`echo '$'$var` != xno" && eval "test x`echo '$'$found` = xno"; then - MPD_AUTO_DISABLED([$name], [$feature], [$msg]) + if test x$[]enable_$1 != xno && test x$[]found_$1 = xno; then + MPD_AUTO_DISABLED([$1], [$2], [$3]) fi ]) +dnl Evaluate a check's result. Abort if the feature was requested +dnl explicitly but is unavailable. +dnl +dnl Parameters: varname1, description, errmsg AC_DEFUN([MPD_AUTO_RESULT], [ - name="$1" - var="enable_$1" - found="found_$name" - feature="$2" - msg="$3" - - if eval "test x`echo '$'$var` = xno"; then - eval "$found=no" + if test x$[]enable_$1 = xno; then + found_$1=no fi - if eval "test x`echo '$'$found` = xyes"; then - MPD_AUTO_ENABLED([$name], [$feature]) + if test x$[]found_$1 = xyes; then + MPD_AUTO_ENABLED([$1], [$2]) else - MPD_AUTO_DISABLED([$name], [$feature], [$msg]) + MPD_AUTO_DISABLED([$1], [$2], [$3]) fi ]) -AC_DEFUN([MPD_AUTO_PKG], [ - if eval "test x`echo '$'enable_$1` != xno"; then - PKG_CHECK_MODULES([$2], [$3], - [eval "found_$1=yes"], - [eval "found_$1=no"]) +dnl Invoke a check if its configuration is "yes" or "auto" and call +dnl MPD_AUTO_RESULT. +dnl +dnl Parameters: varname1, description, errmsg, check +AC_DEFUN([MPD_AUTO], [ + if test x$[]enable_$1 != xno; then + $4 fi + MPD_AUTO_RESULT([$1], [$2], [$3]) +]) - MPD_AUTO_RESULT([$1], [$4], [$5]) +dnl Wrapper for MPD_AUTO and PKG_CHECK_MODULES. +dnl +dnl Parameters: varname1, varname2, pkgname, description, errmsg +AC_DEFUN([MPD_AUTO_PKG], [ + MPD_AUTO([$1], [$4], [$5], + [PKG_CHECK_MODULES([$2], [$3], + [found_$1=yes], + [found_$1=no])]) ]) dnl Check with pkg-config first, fall back to AC_CHECK_LIB. dnl dnl Parameters: varname1, varname2, pkgname, libname, symname, libs, cflags, description, errmsg AC_DEFUN([MPD_AUTO_PKG_LIB], [ - if eval "test x`echo '$'enable_$1` != xno"; then - PKG_CHECK_MODULES([$2], [$3], - [eval "found_$1=yes"], + MPD_AUTO([$1], [$8], [$9], + [PKG_CHECK_MODULES([$2], [$3], + [found_$1=yes], AC_CHECK_LIB($4, $5, - [eval "found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'"], - [eval "found_$1=no"], - [$6])) - fi - - MPD_AUTO_RESULT([$1], [$8], [$9]) + [found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'], + [found_$1=no], + [$6]))]) ]) dnl Wrapper for AC_CHECK_LIB. @@ -87,12 +82,104 @@ AC_SUBST([$2_LIBS], []) AC_SUBST([$2_CFLAGS], []) - if eval "test x`echo '$'enable_$1` != xno"; then - AC_CHECK_LIB($3, $4, - [eval "found_$1=yes $2_LIBS='$5' $2_CFLAGS='$6'"], - [eval "found_$1=no"], - [$5]) - fi + MPD_AUTO([$1], [$7], [$8], + [AC_CHECK_LIB($3, $4, + [found_$1=yes $2_LIBS='$5' $2_CFLAGS='$6'], + [found_$1=no], + [$5])]) +]) + +dnl Wrapper for AC_CHECK_HEADER. +dnl +dnl Parameters: varname1, varname2, header, libs, cflags, description, errmsg +AC_DEFUN([MPD_AUTO_HEADER], [ + AC_SUBST([$2_LIBS], []) + AC_SUBST([$2_CFLAGS], []) + + MPD_AUTO([$1], [$6], [$7], + [AC_CHECK_HEADER([$3], + [found_$1=yes $2_LIBS='$4' $2_CFLAGS='$5'], + [found_$1=no])]) +]) + +dnl Convert the given string into a string for the "default value" in +dnl the help text. If the string is a literal, then it is returned +dnl as-is; if it contains a variable reference, just "auto" is +dnl emitted. +dnl +dnl Parameters: varname1 +AC_DEFUN([MPD_FORMAT_DEFAULT], + [ifelse([$1], [], [auto], + index([$1], [$]), [-1], [$1], + [auto])]) - MPD_AUTO_RESULT([$1], [$7], [$8]) +dnl Wrapper for AC_ARG_ENABLE, AC_DEFINE and AM_CONDITIONAL +dnl +dnl Parameters: varname1, varname2, description, default, check +AC_DEFUN([MPD_ARG_ENABLE], [ + AC_ARG_ENABLE(translit([$1], [_], [-]), + AS_HELP_STRING([--enable-]translit([$1], [_], [-]), + [enable $3 (default: ]MPD_FORMAT_DEFAULT([$4])[)]),, + [enable_$1=]ifelse([$4], [], [auto], [$4])) + + $5 + + MPD_DEFINE_CONDITIONAL(enable_$1, ENABLE_$2, [$3]) +]) + +dnl Wrapper for MPD_ARG_ENABLE and MPD_AUTO +dnl +dnl Parameters: varname1, varname2, description, errmsg, default, check +AC_DEFUN([MPD_ENABLE_AUTO], [ + MPD_ARG_ENABLE([$1], [$2], [$3], [$5], [ + MPD_AUTO([$1], [$3], [$4], [$6]) + ]) +]) + +dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_PKG +dnl +dnl Parameters: varname1, varname2, pkg, description, errmsg, default, pre +AC_DEFUN([MPD_ENABLE_AUTO_PKG], [ + MPD_ARG_ENABLE([$1], [$2], [$4], [$6], [ + $7 + MPD_AUTO_PKG($1, $2, $3, $4, $5) + ]) +]) + +dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_PKG_LIB +dnl +dnl Parameters: varname1, varname2, pkg, libname, symname, libs, cflags, description, errmsg, default, pre +AC_DEFUN([MPD_ENABLE_AUTO_PKG_LIB], [ + MPD_ARG_ENABLE([$1], [$2], [$8], [$10], [ + $11 + MPD_AUTO_PKG_LIB($1, $2, $3, $4, $5, $6, $7, $8, $9) + ]) +]) + +dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_LIB +dnl +dnl Parameters: varname1, varname2, libname, symname, libs, cflags, description, errmsg, default, pre +AC_DEFUN([MPD_ENABLE_AUTO_LIB], [ + MPD_ARG_ENABLE([$1], [$2], [$7], [$9], [ + $10 + MPD_AUTO_LIB($1, $2, $3, $4, $5, $6, $7, $8) + ]) +]) + +dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_HEADER +dnl +dnl Parameters: varname1, varname2, header, libs, cflags, description, errmsg, default, pre +AC_DEFUN([MPD_ENABLE_AUTO_HEADER], [ + MPD_ARG_ENABLE([$1], [$2], [$6], [$8], [ + $9 + MPD_AUTO_HEADER($1, $2, $3, $4, $5, $6, $7) + ]) +]) + +dnl Wrapper for MPD_ENABLE_AUTO_PKG and MPD_DEPENDS +dnl +dnl Parameters: varname1, varname2, pkg, description, errmsg, default, dep_variable, dep_errmsg +AC_DEFUN([MPD_ENABLE_AUTO_PKG_DEPENDS], [ + MPD_ENABLE_AUTO_PKG([$1], [$2], [$3], [$4], [$5], [$6], + [MPD_DEPENDS([enable_$1], [$7], [$8])]) ]) diff -Nru mpd-0.19.21/m4/mpd_define_conditional.m4 mpd-0.20.9/m4/mpd_define_conditional.m4 --- mpd-0.19.21/m4/mpd_define_conditional.m4 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/m4/mpd_define_conditional.m4 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,8 @@ +dnl Wrapper for AC_DEFINE and AM_CONDITIONAL +dnl +dnl Parameters: varname1, varname2, description +AC_DEFUN([MPD_DEFINE_CONDITIONAL], [dnl + AM_CONDITIONAL($2, test x$[]$1 = xyes) + if test x$[]$1 = xyes; then + AC_DEFINE($2, 1, [Define to enable $3]) + fi]) diff -Nru mpd-0.19.21/m4/mpd_func.m4 mpd-0.20.9/m4/mpd_func.m4 --- mpd-0.19.21/m4/mpd_func.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/mpd_func.m4 2017-01-27 07:46:51.000000000 +0000 @@ -6,7 +6,7 @@ AC_ARG_ENABLE([$1], AS_HELP_STRING([--enable-$1], [use the function "$1" (default: auto)]), - [test xenable_$1 = xyes && AC_DEFINE([$3], 1, [Define to use $1])], + [test x$[]enable_$1 = xyes && AC_DEFINE([$3], 1, [Define to use $1])], [AC_CHECK_FUNC([$2], [AC_DEFINE([$3], 1, [Define to use $1])],)]) ]) diff -Nru mpd-0.19.21/m4/mpd_with_flags.m4 mpd-0.20.9/m4/mpd_with_flags.m4 --- mpd-0.19.21/m4/mpd_with_flags.m4 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/m4/mpd_with_flags.m4 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,23 @@ +dnl Run code with the specified CFLAGS/CXXFLAGS and LIBS appended. +dnl Restores the old values afterwards. +dnl +dnl Parameters: cflags, libs, code +AC_DEFUN([MPD_WITH_FLAGS], [ + ac_save_CFLAGS="$[]CFLAGS" + ac_save_CXXFLAGS="$[]CXXFLAGS" + ac_save_LIBS="$[]LIBS" + CFLAGS="$[]CFLAGS $1" + CXXFLAGS="$[]CXXFLAGS $1" + LIBS="$[]LIBS $2" + $3 + CFLAGS="$[]ac_save_CFLAGS" + CXXFLAGS="$[]ac_save_CXXFLAGS" + LIBS="$[]ac_save_LIBS" +]) + +dnl Run code with the specified library's CFLAGS/CXXFLAGS and LIBS +dnl appended. Restores the old values afterwards. +dnl +dnl Parameters: libname, code +AC_DEFUN([MPD_WITH_LIBRARY], + [MPD_WITH_FLAGS([$[]$1_CFLAGS], [$[]$1_LIBS], [$2])]) diff -Nru mpd-0.19.21/m4/pkg.m4 mpd-0.20.9/m4/pkg.m4 --- mpd-0.19.21/m4/pkg.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/pkg.m4 2017-01-27 07:46:51.000000000 +0000 @@ -1,29 +1,60 @@ -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -45,18 +76,19 @@ PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -66,8 +98,10 @@ $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -79,10 +113,11 @@ else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -90,19 +125,17 @@ else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl @@ -156,16 +189,40 @@ AC_MSG_RESULT([yes]) $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES -# PKG_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable pkgconfigdir as the location where a module -# should install pkg-config .pc files. By default the directory is -# $libdir/pkgconfig, but the default can be changed by passing -# DIRECTORY. The user can override through the --with-pkgconfigdir -# parameter. +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -176,16 +233,18 @@ AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_INSTALLDIR +])dnl PKG_INSTALLDIR -# PKG_NOARCH_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable noarch_pkgconfigdir as the location where a -# module should install arch-independent pkg-config .pc files. By -# default the directory is $datadir/pkgconfig, but the default can be -# changed by passing DIRECTORY. The user can override through the -# --with-noarch-pkgconfigdir parameter. +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -196,13 +255,15 @@ AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_NOARCH_INSTALLDIR +])dnl PKG_NOARCH_INSTALLDIR -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# ------------------------------------------- -# Retrieves the value of the pkg-config variable for the given module. +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl @@ -211,4 +272,4 @@ AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl -])# PKG_CHECK_VAR +])dnl PKG_CHECK_VAR diff -Nru mpd-0.19.21/m4/pretty_print.m4 mpd-0.20.9/m4/pretty_print.m4 --- mpd-0.19.21/m4/pretty_print.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/pretty_print.m4 2017-01-27 07:46:51.000000000 +0000 @@ -1,16 +1,6 @@ AC_DEFUN([results], [ - dnl This is a hack to allow "with" names, otherwise "enable". - num=`expr $1 : 'with'` - if test "$num" != "0"; then - var="`echo '$'$1`" - else - var="`echo '$'enable_$1`" - fi - printf '(' - if eval "test x$var = xyes"; then - printf '+' - elif test -n "$3" && eval "test x$var = x$3"; then + if test x$[]enable_$1 = xyes; then printf '+' else printf '-' diff -Nru mpd-0.19.21/m4/ucred.m4 mpd-0.20.9/m4/ucred.m4 --- mpd-0.19.21/m4/ucred.m4 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/m4/ucred.m4 2017-01-27 07:46:51.000000000 +0000 @@ -1,6 +1,6 @@ # Check if "struct ucred" is available. # -# Author: Max Kellermann +# Author: Max Kellermann AC_DEFUN([STRUCT_UCRED],[ AC_MSG_CHECKING([for struct ucred]) diff -Nru mpd-0.19.21/Makefile.am mpd-0.20.9/Makefile.am --- mpd-0.19.21/Makefile.am 2016-12-13 09:53:32.000000000 +0000 +++ mpd-0.20.9/Makefile.am 2017-02-01 20:58:30.000000000 +0000 @@ -1,10 +1,11 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign 1.11 dist-xz subdir-objects -AM_CPPFLAGS += -I$(srcdir)/src $(GLIB_CFLAGS) $(BOOST_CPPFLAGS) +AM_CPPFLAGS += -I$(srcdir)/src $(BOOST_CPPFLAGS) AM_CPPFLAGS += -DSYSTEM_CONFIG_FILE_LOCATION='"$(sysconfdir)/mpd.conf"' +APK_NAME = mpd if ANDROID else bin_PROGRAMS = src/mpd @@ -14,10 +15,12 @@ libmpd.a \ libutil.a \ libthread.a \ + libnet.a \ libsystem.a \ libevent.a \ libicu.a \ libpcm.a \ + libbasic.a \ libconf.a \ libtag.a \ libinput.a \ @@ -46,20 +49,21 @@ $(DECODER_LIBS) \ $(INPUT_LIBS) \ $(ARCHIVE_LIBS) \ - $(TAG_LIBS) \ $(OUTPUT_LIBS) \ + $(TAG_LIBS) \ $(FILTER_LIBS) \ $(ENCODER_LIBS) \ $(MIXER_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ libthread.a \ + libnet.a \ + $(FS_LIBS) \ libsystem.a \ - $(ICU_LDADD) \ libutil.a \ - $(FS_LIBS) \ - $(SYSTEMD_DAEMON_LIBS) \ - $(GLIB_LIBS) + $(ICU_LDADD) \ + $(SYSTEMD_DAEMON_LIBS) src_mpd_SOURCES = \ src/Main.cxx src/Main.hxx @@ -72,13 +76,10 @@ src/open.h \ src/poison.h \ src/notify.cxx src/notify.hxx \ - src/AudioConfig.cxx src/AudioConfig.hxx \ - src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ - src/AudioFormat.cxx src/AudioFormat.hxx \ - src/AudioParser.cxx src/AudioParser.hxx \ src/protocol/Ack.cxx src/protocol/Ack.hxx \ src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \ src/protocol/Result.cxx src/protocol/Result.hxx \ + src/command/Request.hxx \ src/command/CommandResult.hxx \ src/command/CommandError.cxx src/command/CommandError.hxx \ src/command/AllCommands.cxx src/command/AllCommands.hxx \ @@ -92,19 +93,20 @@ src/command/OtherCommands.cxx src/command/OtherCommands.hxx \ src/command/CommandListBuilder.cxx src/command/CommandListBuilder.hxx \ src/Idle.cxx src/Idle.hxx \ - src/CrossFade.cxx src/CrossFade.hxx \ + src/IdleFlags.cxx src/IdleFlags.hxx \ src/decoder/DecoderError.cxx src/decoder/DecoderError.hxx \ src/decoder/DecoderThread.cxx src/decoder/DecoderThread.hxx \ src/decoder/DecoderCommand.hxx \ src/decoder/DecoderControl.cxx src/decoder/DecoderControl.hxx \ - src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx \ + src/decoder/Client.hxx \ src/decoder/DecoderPlugin.hxx \ - src/decoder/DecoderInternal.cxx src/decoder/DecoderInternal.hxx \ + src/decoder/Bridge.cxx src/decoder/Bridge.hxx \ src/decoder/DecoderPrint.cxx src/decoder/DecoderPrint.hxx \ src/filter/FilterConfig.cxx src/filter/FilterConfig.hxx \ src/filter/FilterPlugin.cxx src/filter/FilterPlugin.hxx \ src/filter/FilterInternal.hxx \ src/filter/FilterRegistry.cxx src/filter/FilterRegistry.hxx \ + src/filter/Observer.cxx src/filter/Observer.hxx \ src/client/Client.cxx src/client/Client.hxx \ src/client/ClientInternal.hxx \ src/client/ClientEvent.cxx \ @@ -119,6 +121,7 @@ src/client/ClientMessage.cxx src/client/ClientMessage.hxx \ src/client/ClientSubscribe.cxx \ src/client/ClientFile.cxx \ + src/client/Response.cxx src/client/Response.hxx \ src/Listen.cxx src/Listen.hxx \ src/LogInit.cxx src/LogInit.hxx \ src/LogBackend.cxx src/LogBackend.hxx \ @@ -128,7 +131,6 @@ src/IOThread.cxx src/IOThread.hxx \ src/Instance.cxx src/Instance.hxx \ src/win32/Win32Main.cxx \ - src/GlobalEvents.cxx src/GlobalEvents.hxx \ src/MixRampInfo.hxx \ src/MusicBuffer.cxx src/MusicBuffer.hxx \ src/MusicPipe.cxx src/MusicPipe.hxx \ @@ -136,11 +138,11 @@ src/Mapper.cxx src/Mapper.hxx \ src/Partition.cxx src/Partition.hxx \ src/Permission.cxx src/Permission.hxx \ - src/PlayerThread.cxx src/PlayerThread.hxx \ - src/PlayerControl.cxx src/PlayerControl.hxx \ - src/PlayerListener.hxx \ + src/player/CrossFade.cxx src/player/CrossFade.hxx \ + src/player/Thread.cxx src/player/Thread.hxx \ + src/player/Control.cxx src/player/Control.hxx \ + src/player/Listener.hxx \ src/PlaylistError.cxx src/PlaylistError.hxx \ - src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \ src/PlaylistPrint.cxx src/PlaylistPrint.hxx \ src/PlaylistSave.cxx src/PlaylistSave.hxx \ src/playlist/PlaylistStream.cxx src/playlist/PlaylistStream.hxx \ @@ -161,9 +163,11 @@ src/queue/PlaylistEdit.cxx \ src/queue/PlaylistTag.cxx \ src/queue/PlaylistState.cxx src/queue/PlaylistState.hxx \ - src/ReplayGainConfig.cxx src/ReplayGainConfig.hxx \ - src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx \ + src/queue/Listener.hxx \ + src/PluginUnavailable.hxx \ + src/ReplayGainGlobal.cxx src/ReplayGainGlobal.hxx \ src/DetachedSong.cxx src/DetachedSong.hxx \ + src/LocateUri.cxx src/LocateUri.hxx \ src/SongUpdate.cxx \ src/SongLoader.cxx src/SongLoader.hxx \ src/SongPrint.cxx src/SongPrint.hxx \ @@ -184,9 +188,14 @@ else libmpd_a_SOURCES += \ src/unix/SignalHandlers.cxx src/unix/SignalHandlers.hxx \ - src/unix/Daemon.cxx src/unix/Daemon.hxx \ - src/unix/PidFile.hxx \ src/CommandLine.cxx src/CommandLine.hxx + +if ENABLE_DAEMON +libmpd_a_SOURCES += \ + src/unix/Daemon.cxx src/unix/Daemon.hxx \ + src/unix/PidFile.hxx +endif + endif if ENABLE_DATABASE @@ -214,7 +223,7 @@ src/db/DatabasePrint.cxx src/db/DatabasePrint.hxx \ src/db/DatabaseQueue.cxx src/db/DatabaseQueue.hxx \ src/db/DatabasePlaylist.cxx src/db/DatabasePlaylist.hxx \ - src/db/DatabaseError.cxx src/db/DatabaseError.hxx \ + src/db/DatabaseError.hxx \ src/db/DatabaseLock.cxx src/db/DatabaseLock.hxx \ src/db/DatabasePlugin.hxx \ src/db/Interface.hxx \ @@ -224,16 +233,25 @@ src/db/Selection.cxx src/db/Selection.hxx endif +CURL_SOURCES = \ + src/lib/curl/Version.cxx src/lib/curl/Version.hxx \ + src/lib/curl/Global.cxx src/lib/curl/Global.hxx \ + src/lib/curl/Request.cxx src/lib/curl/Request.hxx \ + src/lib/curl/Handler.hxx \ + src/lib/curl/Easy.hxx \ + src/lib/curl/Multi.hxx \ + src/lib/curl/Slist.hxx + UPNP_SOURCES = \ src/lib/upnp/Init.cxx src/lib/upnp/Init.hxx \ src/lib/upnp/ClientInit.cxx src/lib/upnp/ClientInit.hxx \ src/lib/upnp/Device.cxx src/lib/upnp/Device.hxx \ src/lib/upnp/ContentDirectoryService.cxx src/lib/upnp/ContentDirectoryService.hxx \ src/lib/upnp/Discovery.cxx src/lib/upnp/Discovery.hxx \ - src/lib/upnp/Domain.cxx src/lib/upnp/Domain.hxx \ src/lib/upnp/ixmlwrap.cxx src/lib/upnp/ixmlwrap.hxx \ src/lib/upnp/Callback.hxx \ src/lib/upnp/Util.cxx src/lib/upnp/Util.hxx \ + src/lib/upnp/UniqueIxml.hxx \ src/lib/upnp/WorkQueue.hxx \ src/lib/upnp/Action.hxx @@ -266,7 +284,7 @@ src_mpd_LDADD += libandroid.a libjava.a -all-local: android/build/bin/Main-debug.apk +all-local: android/build/bin/$(APK_NAME)-debug.apk clean-local: rm -rf android/build @@ -278,8 +296,8 @@ mkdir -p android/build/include android/build/res android/build/src/org ln -s $(abs_srcdir)/android/AndroidManifest.xml $(abs_srcdir)/android/custom_rules.xml android/build ln -s $(abs_srcdir)/android/src android/build/src/org/musicpd - ln -s $(abs_srcdir)/android/res/values android/build/res - $(ANDROID_SDK)/tools/android update project --path android/build --target android-17 + ln -s $(abs_srcdir)/android/res/values $(abs_srcdir)/android/res/layout android/build/res + $(ANDROID_SDK)/tools/android update project --path android/build --target android-17 --name $(APK_NAME) android/build/bin/classes/org/musicpd/Bridge.class: android/src/Bridge.java android/build/build.xml android/build/res/drawable/icon.png cd android/build && ant compile-jni-classes @@ -303,18 +321,18 @@ $(wildcard $(srcdir)/android/src/*.java) \ android/build/build.xml -android/build/bin/Main-debug.apk: $(APK_DEPS) +android/build/bin/$(APK_NAME)-debug.apk: $(APK_DEPS) cd android/build && ant nodeps debug -android/build/bin/Main-release-unsigned.apk: $(APK_DEPS) +android/build/bin/$(APK_NAME)-release-unsigned.apk: $(APK_DEPS) cd android/build && ant nodeps release -android/build/bin/Main-release-unaligned.apk: android/build/bin/Main-release-unsigned.apk +android/build/bin/$(APK_NAME)-release-unaligned.apk: android/build/bin/$(APK_NAME)-release-unsigned.apk jarsigner -digestalg SHA1 -sigalg MD5withRSA -storepass:env ANDROID_KEYSTORE_PASS -keystore $(ANDROID_KEYSTORE) -signedjar $@ $< $(ANDROID_KEY_ALIAS) ANDROID_SDK_BUILD_TOOLS_VERSION = 20.0.0 -android/build/bin/Main.apk: android/build/bin/Main-release-unaligned.apk +android/build/bin/$(APK_NAME).apk: android/build/bin/$(APK_NAME)-release-unaligned.apk $(ANDROID_SDK)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/zipalign -f 4 $< $@ endif @@ -323,14 +341,36 @@ # Windows resource file # -src/win32/mpd_win32_rc.$(OBJEXT): src/win32/mpd_win32_rc.rc +win32/res/mpd.$(OBJEXT): %.$(OBJEXT): %.rc $(WINDRES) -i $< -o $@ if HAVE_WINDOWS -noinst_DATA = src/win32/mpd_win32_rc.rc +noinst_DATA = win32/res/mpd.rc + +EXTRA_src_mpd_DEPENDENCIES = win32/res/mpd.$(OBJEXT) +src_mpd_LDFLAGS = -Wl,win32/res/mpd.$(OBJEXT) +endif + +# +# Haiku resource file +# -EXTRA_src_mpd_DEPENDENCIES = src/win32/mpd_win32_rc.$(OBJEXT) -src_mpd_LDFLAGS = -Wl,src/win32/mpd_win32_rc.$(OBJEXT) +src/haiku/mpd.rsrc: src/haiku/mpd.rdef + $(RC) -o $@ $< + +if ENABLE_HAIKU +noinst_DATA = src/haiku/mpd.rdef + +EXTRA_src_mpd_DEPENDENCIES = src/haiku/mpd.rsrc + +src/mpd.haiku-rsrc-done: src/mpd src/haiku/mpd.rsrc + $(XRES) -o src/mpd src/haiku/mpd.rsrc + @touch src/mpd.haiku-rsrc-done + +all-local: src/mpd.haiku-rsrc-done + +clean-local: + rm -rf src/haiku/mpd.rsrc src/mpd.haiku-rsrc-done endif if ENABLE_DATABASE @@ -346,6 +386,9 @@ if ENABLE_SQLITE libmpd_a_SOURCES += \ src/command/StickerCommands.cxx src/command/StickerCommands.hxx \ + src/lib/sqlite/Error.cxx src/lib/sqlite/Error.hxx \ + src/lib/sqlite/Util.hxx \ + src/sticker/Match.hxx \ src/sticker/StickerDatabase.cxx src/sticker/StickerDatabase.hxx \ src/sticker/StickerPrint.cxx src/sticker/StickerPrint.hxx \ src/sticker/SongSticker.cxx src/sticker/SongSticker.hxx @@ -354,24 +397,40 @@ # Generic utility library libutil_a_SOURCES = \ + src/util/Exception.cxx src/util/Exception.hxx \ + src/util/RuntimeError.hxx \ src/util/Macros.hxx \ + src/util/BindMethod.hxx \ src/util/Cast.hxx \ src/util/Clamp.hxx \ + src/util/DeleteDisposer.hxx \ src/util/Alloc.cxx src/util/Alloc.hxx \ + src/util/AllocatedArray.hxx \ src/util/VarSize.hxx \ src/util/ScopeExit.hxx \ - src/util/Error.cxx src/util/Error.hxx \ src/util/Domain.hxx \ src/util/ReusableArray.hxx \ src/util/ASCII.hxx \ src/util/UTF8.cxx src/util/UTF8.hxx \ src/util/CharUtil.hxx \ src/util/NumberParser.hxx \ + src/util/MimeType.cxx src/util/MimeType.hxx \ + src/util/StringBuffer.hxx \ + src/util/StringPointer.hxx \ + src/util/StringView.cxx src/util/StringView.hxx \ + src/util/AllocatedString.cxx src/util/AllocatedString.hxx \ src/util/StringUtil.cxx src/util/StringUtil.hxx \ + src/util/StringCompare.cxx src/util/StringCompare.hxx \ + src/util/WStringCompare.cxx src/util/WStringCompare.hxx \ + src/util/StringAPI.hxx \ + src/util/WStringAPI.hxx \ + src/util/DivideString.cxx src/util/DivideString.hxx \ src/util/SplitString.cxx src/util/SplitString.hxx \ + src/util/IterableSplitString.hxx \ src/util/FormatString.cxx src/util/FormatString.hxx \ src/util/Tokenizer.cxx src/util/Tokenizer.hxx \ src/util/TextFile.hxx \ + src/util/TimeParser.cxx src/util/TimeParser.hxx \ src/util/UriUtil.cxx src/util/UriUtil.hxx \ src/util/Manual.hxx \ src/util/RefCount.hxx \ @@ -388,12 +447,13 @@ src/util/OptionParser.cxx src/util/OptionParser.hxx \ src/util/OptionDef.hxx \ src/util/ByteReverse.cxx src/util/ByteReverse.hxx \ + src/util/format.c src/util/format.h \ src/util/bit_reverse.c src/util/bit_reverse.h # Multi-threading library libthread_a_SOURCES = \ - src/thread/Util.hxx \ + src/thread/Util.cxx src/thread/Util.hxx \ src/thread/Name.hxx \ src/thread/Slack.hxx \ src/thread/Mutex.hxx \ @@ -405,15 +465,26 @@ src/thread/Thread.cxx src/thread/Thread.hxx \ src/thread/Id.hxx +# Networking library + +libnet_a_SOURCES = \ + src/net/Features.hxx \ + src/net/ToString.cxx src/net/ToString.hxx \ + src/net/Resolver.cxx src/net/Resolver.hxx \ + src/net/StaticSocketAddress.cxx src/net/StaticSocketAddress.hxx \ + src/net/AllocatedSocketAddress.cxx src/net/AllocatedSocketAddress.hxx \ + src/net/SocketAddress.cxx src/net/SocketAddress.hxx \ + src/net/SocketUtil.cxx src/net/SocketUtil.hxx \ + src/net/SocketError.cxx src/net/SocketError.hxx + # System library libsystem_a_SOURCES = \ src/system/ByteOrder.hxx \ + src/system/Error.hxx \ src/system/FatalError.cxx src/system/FatalError.hxx \ + src/system/FileDescriptor.cxx src/system/FileDescriptor.hxx \ src/system/fd_util.c src/system/fd_util.h \ - src/system/SocketUtil.cxx src/system/SocketUtil.hxx \ - src/system/SocketError.cxx src/system/SocketError.hxx \ - src/system/Resolver.cxx src/system/Resolver.hxx \ src/system/EventPipe.cxx src/system/EventPipe.hxx \ src/system/EventFD.cxx src/system/EventFD.hxx \ src/system/SignalFD.cxx src/system/SignalFD.hxx \ @@ -434,6 +505,8 @@ src/event/TimeoutMonitor.hxx src/event/TimeoutMonitor.cxx \ src/event/IdleMonitor.hxx src/event/IdleMonitor.cxx \ src/event/DeferredMonitor.hxx src/event/DeferredMonitor.cxx \ + src/event/DeferredCall.hxx \ + src/event/MaskMonitor.hxx src/event/MaskMonitor.cxx \ src/event/SocketMonitor.cxx src/event/SocketMonitor.hxx \ src/event/BufferedSocket.cxx src/event/BufferedSocket.hxx \ src/event/FullyBufferedSocket.cxx src/event/FullyBufferedSocket.hxx \ @@ -446,13 +519,19 @@ libicu_a_SOURCES = \ src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \ - src/lib/icu/Error.cxx src/lib/icu/Error.hxx + src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx if HAVE_ICU libicu_a_SOURCES += \ + src/lib/icu/Util.cxx src/lib/icu/Util.hxx \ src/lib/icu/Init.cxx src/lib/icu/Init.hxx endif +if HAVE_WINDOWS +libicu_a_SOURCES += \ + src/lib/icu/Win32.cxx src/lib/icu/Win32.hxx +endif + libicu_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(ICU_CFLAGS) @@ -461,7 +540,10 @@ # PCM library libpcm_a_SOURCES = \ - src/pcm/Domain.cxx src/pcm/Domain.hxx \ + src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ + src/AudioFormat.cxx src/AudioFormat.hxx \ + src/AudioParser.cxx src/AudioParser.hxx \ + src/pcm/SampleFormat.cxx src/pcm/SampleFormat.hxx \ src/pcm/Traits.hxx \ src/pcm/Interleave.cxx src/pcm/Interleave.hxx \ src/pcm/PcmBuffer.cxx src/pcm/PcmBuffer.hxx \ @@ -479,6 +561,7 @@ src/pcm/Neon.hxx \ src/pcm/FormatConverter.cxx src/pcm/FormatConverter.hxx \ src/pcm/ChannelsConverter.cxx src/pcm/ChannelsConverter.hxx \ + src/pcm/Order.cxx src/pcm/Order.hxx \ src/pcm/Resampler.hxx \ src/pcm/GlueResampler.cxx src/pcm/GlueResampler.hxx \ src/pcm/FallbackResampler.cxx src/pcm/FallbackResampler.hxx \ @@ -488,29 +571,60 @@ src/pcm/PcmUtils.hxx libpcm_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(SOXR_CFLAGS) \ - $(SAMPLERATE_CFLAGS) + $(LIBSAMPLERATE_CFLAGS) PCM_LIBS = \ libpcm.a \ $(SOXR_LIBS) \ - $(SAMPLERATE_LIBS) + $(LIBSAMPLERATE_LIBS) if ENABLE_DSD libpcm_a_SOURCES += \ + src/pcm/Dsd16.cxx src/pcm/Dsd16.hxx \ + src/pcm/Dsd32.cxx src/pcm/Dsd32.hxx \ src/pcm/PcmDsd.cxx src/pcm/PcmDsd.hxx \ src/pcm/dsd2pcm/dsd2pcm.c src/pcm/dsd2pcm/dsd2pcm.h endif -if HAVE_LIBSAMPLERATE +if ENABLE_LIBSAMPLERATE libpcm_a_SOURCES += \ src/pcm/LibsamplerateResampler.cxx src/pcm/LibsamplerateResampler.hxx endif -if HAVE_SOXR +if ENABLE_SOXR libpcm_a_SOURCES += \ src/pcm/SoxrResampler.cxx src/pcm/SoxrResampler.hxx endif +# Xiph codec support library + +if HAVE_XIPH + +noinst_LIBRARIES += libxiph.a + +libxiph_a_SOURCES = \ + src/lib/xiph/VorbisComment.hxx \ + src/lib/xiph/VorbisComments.cxx src/lib/xiph/VorbisComments.hxx \ + src/lib/xiph/XiphTags.cxx src/lib/xiph/XiphTags.hxx +libxiph_a_CPPFLAGS = $(AM_CPPFLAGS) \ + $(OGG_CFLAGS) + +if HAVE_OGG +libxiph_a_SOURCES += \ + src/lib/xiph/OggVisitor.cxx src/lib/xiph/OggVisitor.hxx \ + src/lib/xiph/OggSerial.cxx src/lib/xiph/OggSerial.hxx \ + src/lib/xiph/OggSyncState.cxx src/lib/xiph/OggSyncState.hxx \ + src/lib/xiph/OggFind.cxx src/lib/xiph/OggFind.hxx \ + src/lib/xiph/OggPage.hxx \ + src/lib/xiph/OggPacket.cxx src/lib/xiph/OggPacket.hxx \ + src/lib/xiph/OggStreamState.hxx +endif + +XIPH_LIBS = libxiph.a \ + $(OGG_LIBS) + +endif + # File system library FS_LIBS = libfs.a @@ -532,21 +646,29 @@ src/fs/Charset.cxx src/fs/Charset.hxx \ src/fs/Path.cxx src/fs/Path2.cxx src/fs/Path.hxx \ src/fs/AllocatedPath.cxx src/fs/AllocatedPath.hxx \ + src/fs/NarrowPath.hxx \ src/fs/FileSystem.cxx src/fs/FileSystem.hxx \ + src/fs/FileInfo.hxx \ + src/fs/Glob.hxx \ src/fs/StandardDirectory.cxx src/fs/StandardDirectory.hxx \ src/fs/CheckFile.cxx src/fs/CheckFile.hxx \ - src/fs/DirectoryReader.hxx + src/fs/DirectoryReader.cxx src/fs/DirectoryReader.hxx libfs_a_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) -if HAVE_ZLIB +if ENABLE_ZLIB libfs_a_SOURCES += \ - src/lib/zlib/Domain.cxx src/lib/zlib/Domain.hxx \ + src/lib/zlib/Error.cxx src/lib/zlib/Error.hxx \ src/fs/io/GunzipReader.cxx src/fs/io/GunzipReader.hxx \ src/fs/io/AutoGunzipReader.cxx src/fs/io/AutoGunzipReader.hxx \ src/fs/io/GzipOutputStream.cxx src/fs/io/GzipOutputStream.hxx FS_LIBS += $(ZLIB_LIBS) endif +if HAVE_WINDOWS +# for PathMatchSpec() +FS_LIBS += -lshlwapi +endif + # Storage library SMBCLIENT_SOURCES = \ @@ -563,8 +685,7 @@ src/lib/nfs/Glue.cxx src/lib/nfs/Glue.hxx \ src/lib/nfs/Base.cxx src/lib/nfs/Base.hxx \ src/lib/nfs/FileReader.cxx src/lib/nfs/FileReader.hxx \ - src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx \ - src/lib/nfs/Domain.cxx src/lib/nfs/Domain.hxx + src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx if ENABLE_DATABASE @@ -586,6 +707,8 @@ STORAGE_LIBS = \ libstorage.a \ + $(CURL_LIBS) \ + $(EXPAT_LIBS) \ $(NFS_LIBS) \ $(SMBCLIENT_LIBS) @@ -601,6 +724,12 @@ src/storage/plugins/NfsStorage.cxx src/storage/plugins/NfsStorage.hxx endif +if ENABLE_WEBDAV +libstorage_a_SOURCES += \ + src/lib/expat/ExpatParser.cxx \ + src/storage/plugins/CurlStorage.cxx src/storage/plugins/CurlStorage.hxx +endif + endif # neighbor plugins @@ -634,7 +763,7 @@ $(SMBCLIENT_LIBS) \ libneighbor.a -if HAVE_LIBUPNP +if ENABLE_UPNP libneighbor_a_SOURCES += \ $(UPNP_SOURCES) \ src/neighbor/plugins/UpnpNeighborPlugin.cxx src/neighbor/plugins/UpnpNeighborPlugin.hxx @@ -660,7 +789,6 @@ src/db/plugins/simple/DatabaseSave.hxx \ src/db/plugins/simple/DirectorySave.cxx \ src/db/plugins/simple/DirectorySave.hxx \ - src/db/plugins/LazyDatabase.cxx src/db/plugins/LazyDatabase.hxx \ src/db/plugins/simple/Directory.cxx \ src/db/plugins/simple/Directory.hxx \ src/db/plugins/simple/Song.cxx \ @@ -673,7 +801,7 @@ src/db/plugins/simple/SimpleDatabasePlugin.cxx \ src/db/plugins/simple/SimpleDatabasePlugin.hxx -if HAVE_LIBMPDCLIENT +if ENABLE_LIBMPDCLIENT libdb_plugins_a_SOURCES += \ src/db/plugins/ProxyDatabasePlugin.cxx src/db/plugins/ProxyDatabasePlugin.hxx endif @@ -682,7 +810,7 @@ libdb_plugins.a \ $(LIBMPDCLIENT_LIBS) -if HAVE_LIBUPNP +if ENABLE_UPNP libdb_plugins_a_SOURCES += \ $(UPNP_SOURCES) \ src/db/plugins/upnp/UpnpDatabasePlugin.cxx src/db/plugins/upnp/UpnpDatabasePlugin.hxx \ @@ -704,6 +832,7 @@ noinst_LIBRARIES += libarchive.a libmpd_a_SOURCES += \ + src/TagArchive.cxx src/TagArchive.hxx \ src/db/update/Archive.cxx libarchive_a_SOURCES = \ @@ -725,19 +854,19 @@ $(ISO9660_LIBS) \ $(ZZIP_LIBS) -if HAVE_BZ2 +if ENABLE_BZ2 libarchive_a_SOURCES += \ src/archive/plugins/Bzip2ArchivePlugin.cxx \ src/archive/plugins/Bzip2ArchivePlugin.hxx endif -if HAVE_ZZIP +if ENABLE_ZZIP libarchive_a_SOURCES += \ src/archive/plugins/ZzipArchivePlugin.cxx \ src/archive/plugins/ZzipArchivePlugin.hxx endif -if HAVE_ISO9660 +if ENABLE_ISO9660 libarchive_a_SOURCES += \ src/archive/plugins/Iso9660ArchivePlugin.cxx \ src/archive/plugins/Iso9660ArchivePlugin.hxx @@ -747,12 +876,19 @@ ARCHIVE_LIBS = endif +libbasic_a_SOURCES = \ + src/ReplayGainConfig.hxx \ + src/ReplayGainMode.cxx src/ReplayGainMode.hxx \ + src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx + # configuration library libconf_a_SOURCES = \ src/config/ConfigDefaults.hxx \ src/config/ConfigPath.cxx src/config/ConfigPath.hxx \ - src/config/ConfigData.cxx src/config/ConfigData.hxx \ + src/config/Data.cxx src/config/Data.hxx \ + src/config/Block.cxx src/config/Block.hxx \ + src/config/Param.cxx src/config/Param.hxx \ src/config/ConfigParser.cxx src/config/ConfigParser.hxx \ src/config/ConfigGlobal.cxx src/config/ConfigGlobal.hxx \ src/config/ConfigFile.cxx src/config/ConfigFile.hxx \ @@ -774,22 +910,27 @@ src/tag/TagBuilder.cxx src/tag/TagBuilder.hxx \ src/tag/TagItem.hxx \ src/tag/TagHandler.cxx src/tag/TagHandler.hxx \ - src/tag/TagSettings.c src/tag/TagSettings.h \ + src/tag/Mask.hxx \ + src/tag/Settings.cxx src/tag/Settings.hxx \ src/tag/TagConfig.cxx src/tag/TagConfig.hxx \ src/tag/TagNames.c \ src/tag/TagString.cxx src/tag/TagString.hxx \ src/tag/TagPool.cxx src/tag/TagPool.hxx \ src/tag/TagTable.cxx src/tag/TagTable.hxx \ src/tag/Set.cxx src/tag/Set.hxx \ + src/tag/Format.cxx src/tag/Format.hxx \ src/tag/VorbisComment.cxx src/tag/VorbisComment.hxx \ src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \ src/tag/MixRamp.cxx src/tag/MixRamp.hxx \ + src/tag/Generic.cxx src/tag/Generic.hxx \ src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \ src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \ src/tag/ApeTag.cxx src/tag/ApeTag.hxx -if HAVE_ID3TAG +if ENABLE_ID3TAG libtag_a_SOURCES += \ + src/tag/Id3Load.cxx src/tag/Id3Load.hxx \ + src/tag/Id3Unique.hxx \ src/tag/TagId3.cxx src/tag/TagId3.hxx \ src/tag/TagRva2.cxx src/tag/TagRva2.hxx \ src/tag/Riff.cxx src/tag/Riff.hxx \ @@ -798,7 +939,7 @@ # ffmpeg -if HAVE_FFMPEG +if ENABLE_FFMPEG noinst_LIBRARIES += libffmpeg.a libffmpeg_a_SOURCES = \ src/lib/ffmpeg/Init.cxx src/lib/ffmpeg/Init.hxx \ @@ -818,6 +959,8 @@ libdecoder_a_SOURCES = \ src/decoder/plugins/PcmDecoderPlugin.cxx \ src/decoder/plugins/PcmDecoderPlugin.hxx \ + src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx \ + src/decoder/Reader.cxx src/decoder/Reader.hxx \ src/decoder/DecoderBuffer.cxx src/decoder/DecoderBuffer.hxx \ src/decoder/DecoderPlugin.cxx \ src/decoder/DecoderList.cxx src/decoder/DecoderList.hxx @@ -842,6 +985,7 @@ DECODER_LIBS = \ libdecoder.a \ + $(XIPH_LIBS) \ $(VORBIS_LIBS) $(TREMOR_LIBS) \ $(FLAC_LIBS) \ $(SNDFILE_LIBS) \ @@ -869,30 +1013,26 @@ src/decoder/plugins/DsdLib.hxx endif -if HAVE_MAD +if ENABLE_MAD libdecoder_a_SOURCES += \ src/decoder/plugins/MadDecoderPlugin.cxx \ src/decoder/plugins/MadDecoderPlugin.hxx endif -if HAVE_MPG123 +if ENABLE_MPG123 libdecoder_a_SOURCES += \ src/decoder/plugins/Mpg123DecoderPlugin.cxx \ src/decoder/plugins/Mpg123DecoderPlugin.hxx endif -if HAVE_MPCDEC +if ENABLE_MPCDEC libdecoder_a_SOURCES += \ src/decoder/plugins/MpcdecDecoderPlugin.cxx \ src/decoder/plugins/MpcdecDecoderPlugin.hxx endif -if HAVE_OPUS +if ENABLE_OPUS libdecoder_a_SOURCES += \ - src/decoder/plugins/OggUtil.cxx \ - src/decoder/plugins/OggUtil.hxx \ - src/decoder/plugins/OggSyncState.hxx \ - src/decoder/plugins/OggFind.cxx src/decoder/plugins/OggFind.hxx \ src/decoder/plugins/OpusDomain.cxx src/decoder/plugins/OpusDomain.hxx \ src/decoder/plugins/OpusReader.hxx \ src/decoder/plugins/OpusHead.hxx \ @@ -903,37 +1043,40 @@ src/decoder/plugins/OpusDecoderPlugin.h endif -if HAVE_WAVPACK +if ENABLE_WAVPACK libdecoder_a_SOURCES += \ src/decoder/plugins/WavpackDecoderPlugin.cxx \ src/decoder/plugins/WavpackDecoderPlugin.hxx endif -if HAVE_ADPLUG +if ENABLE_ADPLUG libdecoder_a_SOURCES += \ src/decoder/plugins/AdPlugDecoderPlugin.cxx \ src/decoder/plugins/AdPlugDecoderPlugin.h endif -if HAVE_FAAD +if ENABLE_FAAD libdecoder_a_SOURCES += \ src/decoder/plugins/FaadDecoderPlugin.cxx src/decoder/plugins/FaadDecoderPlugin.hxx endif +if HAVE_OGG +libdecoder_a_SOURCES += \ + src/decoder/plugins/OggDecoder.cxx src/decoder/plugins/OggDecoder.hxx +endif + if HAVE_XIPH libdecoder_a_SOURCES += \ - src/decoder/plugins/XiphTags.cxx src/decoder/plugins/XiphTags.hxx \ src/decoder/plugins/OggCodec.cxx src/decoder/plugins/OggCodec.hxx endif if ENABLE_VORBIS_DECODER libdecoder_a_SOURCES += \ src/decoder/plugins/VorbisDomain.cxx src/decoder/plugins/VorbisDomain.hxx \ - src/decoder/plugins/VorbisComments.cxx src/decoder/plugins/VorbisComments.hxx \ src/decoder/plugins/VorbisDecoderPlugin.cxx src/decoder/plugins/VorbisDecoderPlugin.h endif -if HAVE_FLAC +if ENABLE_FLAC libdecoder_a_SOURCES += \ src/decoder/plugins/FlacInput.cxx src/decoder/plugins/FlacInput.hxx \ src/decoder/plugins/FlacIOHandle.cxx src/decoder/plugins/FlacIOHandle.hxx \ @@ -941,11 +1084,12 @@ src/decoder/plugins/FlacPcm.cxx src/decoder/plugins/FlacPcm.hxx \ src/decoder/plugins/FlacDomain.cxx src/decoder/plugins/FlacDomain.hxx \ src/decoder/plugins/FlacCommon.cxx src/decoder/plugins/FlacCommon.hxx \ + src/decoder/plugins/FlacStreamDecoder.hxx \ src/decoder/plugins/FlacDecoderPlugin.cxx \ src/decoder/plugins/FlacDecoderPlugin.h endif -if HAVE_AUDIOFILE +if ENABLE_AUDIOFILE libdecoder_a_SOURCES += \ src/decoder/plugins/AudiofileDecoderPlugin.cxx \ src/decoder/plugins/AudiofileDecoderPlugin.hxx @@ -957,7 +1101,7 @@ src/decoder/plugins/MikmodDecoderPlugin.hxx endif -if HAVE_MODPLUG +if ENABLE_MODPLUG libmodplug_decoder_plugin_a_SOURCES = \ src/decoder/plugins/ModplugDecoderPlugin.cxx \ src/decoder/plugins/ModplugDecoderPlugin.hxx @@ -985,7 +1129,7 @@ src/decoder/plugins/WildmidiDecoderPlugin.hxx endif -if HAVE_FFMPEG +if ENABLE_FFMPEG libdecoder_a_SOURCES += \ src/decoder/plugins/FfmpegIo.cxx \ src/decoder/plugins/FfmpegIo.hxx \ @@ -1001,7 +1145,7 @@ src/decoder/plugins/SndfileDecoderPlugin.hxx endif -if HAVE_GME +if ENABLE_GME libdecoder_a_SOURCES += \ src/decoder/plugins/GmeDecoderPlugin.cxx src/decoder/plugins/GmeDecoderPlugin.hxx endif @@ -1022,6 +1166,7 @@ ENCODER_LIBS = \ libencoder_plugins.a \ + $(XIPH_LIBS) \ $(LAME_LIBS) \ $(TWOLAME_LIBS) \ $(FLAC_LIBS) \ @@ -1031,44 +1176,43 @@ libencoder_plugins_a_SOURCES = \ src/encoder/EncoderAPI.hxx \ + src/encoder/EncoderInterface.hxx \ src/encoder/EncoderPlugin.hxx \ - src/encoder/plugins/OggStream.hxx \ + src/encoder/ToOutputStream.cxx src/encoder/ToOutputStream.hxx \ src/encoder/plugins/NullEncoderPlugin.cxx \ src/encoder/plugins/NullEncoderPlugin.hxx \ src/encoder/EncoderList.cxx src/encoder/EncoderList.hxx -if HAVE_OGG_ENCODER -libencoder_plugins_a_SOURCES += \ - src/encoder/plugins/OggSerial.cxx \ - src/encoder/plugins/OggSerial.hxx \ - src/encoder/plugins/OggStream.hxx -endif - if ENABLE_WAVE_ENCODER libencoder_plugins_a_SOURCES += \ src/encoder/plugins/WaveEncoderPlugin.cxx \ src/encoder/plugins/WaveEncoderPlugin.hxx endif -if ENABLE_VORBIS_ENCODER +if HAVE_OGG +libencoder_plugins_a_SOURCES += \ + src/encoder/plugins/OggEncoder.hxx +endif + +if ENABLE_VORBISENC libencoder_plugins_a_SOURCES += \ src/encoder/plugins/VorbisEncoderPlugin.cxx \ src/encoder/plugins/VorbisEncoderPlugin.hxx endif -if HAVE_OPUS +if ENABLE_OPUS libencoder_plugins_a_SOURCES += \ src/encoder/plugins/OpusEncoderPlugin.cxx \ src/encoder/plugins/OpusEncoderPlugin.hxx endif -if ENABLE_LAME_ENCODER +if ENABLE_LAME libencoder_plugins_a_SOURCES += \ src/encoder/plugins/LameEncoderPlugin.cxx \ src/encoder/plugins/LameEncoderPlugin.hxx endif -if ENABLE_TWOLAME_ENCODER +if ENABLE_TWOLAME libencoder_plugins_a_SOURCES += \ src/encoder/plugins/TwolameEncoderPlugin.cxx \ src/encoder/plugins/TwolameEncoderPlugin.hxx @@ -1080,7 +1224,7 @@ src/encoder/plugins/FlacEncoderPlugin.hxx endif -if ENABLE_SHINE_ENCODER +if ENABLE_SHINE libencoder_plugins_a_SOURCES += \ src/encoder/plugins/ShineEncoderPlugin.cxx \ src/encoder/plugins/ShineEncoderPlugin.hxx @@ -1119,7 +1263,9 @@ src/input/LocalOpen.cxx src/input/LocalOpen.hxx \ src/input/Offset.hxx \ src/input/InputStream.cxx src/input/InputStream.hxx \ + src/input/Ptr.hxx \ src/input/InputPlugin.hxx \ + src/input/Reader.cxx src/input/Reader.hxx \ src/input/TextInputStream.cxx src/input/TextInputStream.hxx \ src/input/ThreadInputStream.cxx src/input/ThreadInputStream.hxx \ src/input/AsyncInputStream.cxx src/input/AsyncInputStream.hxx \ @@ -1144,7 +1290,7 @@ $(FFMPEG_LIBS2) \ $(MMS_LIBS) -if HAVE_ALSA +if ENABLE_ALSA libinput_a_SOURCES += \ src/input/plugins/AlsaInputPlugin.cxx \ src/input/plugins/AlsaInputPlugin.hxx @@ -1156,6 +1302,7 @@ libinput_a_SOURCES += \ src/input/IcyInputStream.cxx src/input/IcyInputStream.hxx \ src/input/plugins/CurlInputPlugin.cxx src/input/plugins/CurlInputPlugin.hxx \ + $(CURL_SOURCES) \ src/IcyMetaDataParser.cxx src/IcyMetaDataParser.hxx endif @@ -1177,7 +1324,7 @@ src/input/plugins/CdioParanoiaInputPlugin.hxx endif -if HAVE_FFMPEG +if ENABLE_FFMPEG libinput_a_SOURCES += \ src/input/plugins/FfmpegInputPlugin.cxx src/input/plugins/FfmpegInputPlugin.hxx endif @@ -1191,9 +1338,11 @@ $(AO_CFLAGS) \ $(ALSA_CFLAGS) \ $(JACK_CFLAGS) \ + $(HAIKU_CFLAGS) \ $(OPENAL_CFLAGS) \ $(OPENSSL_CFLAGS) \ $(PULSE_CFLAGS) \ + $(SNDIO_CFLAGS) \ $(SHOUT_CFLAGS) OUTPUT_LIBS = \ @@ -1203,15 +1352,21 @@ $(ALSA_LIBS) \ $(ROAR_LIBS) \ $(JACK_LIBS) \ + $(HAIKU_LIBS) \ $(OPENAL_LIBS) \ - $(PULSE_LIBS) \ + $(SNDIO_LIBS) \ $(SHOUT_LIBS) OUTPUT_API_SRC = \ + src/output/Client.hxx \ src/output/OutputAPI.hxx \ + src/output/Internal.cxx \ src/output/Internal.hxx \ + src/output/Wrapper.hxx \ src/output/Registry.cxx src/output/Registry.hxx \ src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ + src/output/SharedPipeConsumer.cxx src/output/SharedPipeConsumer.hxx \ + src/output/Source.cxx src/output/Source.hxx \ src/output/OutputThread.cxx \ src/output/Domain.cxx src/output/Domain.hxx \ src/output/OutputControl.cxx \ @@ -1230,7 +1385,7 @@ MIXER_LIBS = \ libmixer_plugins.a \ $(ALSA_LIBS) \ - $(PULSE_LIBS) + $(PULSE_LIBS2) MIXER_API_SRC = \ src/mixer/Listener.hxx \ @@ -1242,17 +1397,22 @@ src/mixer/MixerInternal.hxx libmixer_plugins_a_SOURCES = \ + src/mixer/plugins/NullMixerPlugin.cxx \ src/mixer/plugins/SoftwareMixerPlugin.cxx \ src/mixer/plugins/SoftwareMixerPlugin.hxx + libmixer_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(ALSA_CFLAGS) \ $(PULSE_CFLAGS) -if HAVE_ALSA +if ENABLE_ALSA liboutput_plugins_a_SOURCES += \ src/output/plugins/AlsaOutputPlugin.cxx \ src/output/plugins/AlsaOutputPlugin.hxx -libmixer_plugins_a_SOURCES += src/mixer/plugins/AlsaMixerPlugin.cxx +libmixer_plugins_a_SOURCES += \ + src/mixer/plugins/volume_mapping.h \ + src/mixer/plugins/volume_mapping.c \ + src/mixer/plugins/AlsaMixerPlugin.cxx endif if ANDROID @@ -1266,14 +1426,14 @@ OUTPUT_LIBS += -lOpenSLES endif -if HAVE_ROAR +if ENABLE_ROAR liboutput_plugins_a_SOURCES += \ src/output/plugins/RoarOutputPlugin.cxx \ src/output/plugins/RoarOutputPlugin.hxx libmixer_plugins_a_SOURCES += src/mixer/plugins/RoarMixerPlugin.cxx endif -if HAVE_AO +if ENABLE_AO liboutput_plugins_a_SOURCES += \ src/output/plugins/AoOutputPlugin.cxx \ src/output/plugins/AoOutputPlugin.hxx @@ -1285,13 +1445,27 @@ src/output/plugins/FifoOutputPlugin.hxx endif +if ENABLE_SNDIO +liboutput_plugins_a_SOURCES += \ + src/output/plugins/SndioOutputPlugin.cxx \ + src/output/plugins/SndioOutputPlugin.hxx +endif + +if ENABLE_HAIKU +liboutput_plugins_a_SOURCES += \ + src/output/plugins/HaikuOutputPlugin.cxx \ + src/output/plugins/HaikuOutputPlugin.hxx +libmixer_plugins_a_SOURCES += \ + src/mixer/plugins/HaikuMixerPlugin.cxx +endif + if ENABLE_PIPE_OUTPUT liboutput_plugins_a_SOURCES += \ src/output/plugins/PipeOutputPlugin.cxx \ src/output/plugins/PipeOutputPlugin.hxx endif -if HAVE_JACK +if ENABLE_JACK liboutput_plugins_a_SOURCES += \ src/output/plugins/JackOutputPlugin.cxx \ src/output/plugins/JackOutputPlugin.hxx @@ -1316,12 +1490,22 @@ src/output/plugins/OSXOutputPlugin.hxx endif -if HAVE_PULSE +if ENABLE_PULSE liboutput_plugins_a_SOURCES += \ src/output/plugins/PulseOutputPlugin.cxx \ src/output/plugins/PulseOutputPlugin.hxx libmixer_plugins_a_SOURCES += \ src/mixer/plugins/PulseMixerPlugin.cxx src/mixer/plugins/PulseMixerPlugin.hxx + +noinst_LIBRARIES += libpulse.a +libpulse_a_SOURCES = \ + src/lib/pulse/LockGuard.hxx \ + src/lib/pulse/LogError.cxx src/lib/pulse/LogError.hxx \ + src/lib/pulse/Error.cxx src/lib/pulse/Error.hxx \ + src/lib/pulse/Domain.cxx src/lib/pulse/Domain.hxx +libpulse_a_CPPFLAGS = $(AM_CPPFLAGS) $(PULSE_CFLAGS) +PULSE_LIBS2 = libpulse.a $(PULSE_LIBS) +OUTPUT_LIBS += $(PULSE_LIBS2) endif if HAVE_SHOUT @@ -1368,19 +1552,14 @@ libplaylist_plugins_a_SOURCES = \ src/playlist/PlaylistPlugin.hxx \ src/playlist/SongEnumerator.hxx \ - src/playlist/CloseSongEnumerator.cxx \ - src/playlist/CloseSongEnumerator.hxx \ src/playlist/MemorySongEnumerator.cxx \ src/playlist/MemorySongEnumerator.hxx \ - src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.cxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.hxx \ src/playlist/plugins/M3uPlaylistPlugin.cxx \ src/playlist/plugins/M3uPlaylistPlugin.hxx \ - src/playlist/plugins/CuePlaylistPlugin.cxx \ - src/playlist/plugins/CuePlaylistPlugin.hxx \ - src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx \ - src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx \ + src/playlist/plugins/PlsPlaylistPlugin.cxx \ + src/playlist/plugins/PlsPlaylistPlugin.hxx \ src/playlist/PlaylistRegistry.cxx src/playlist/PlaylistRegistry.hxx libplaylist_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(EXPAT_CFLAGS) \ @@ -1392,6 +1571,21 @@ $(EXPAT_LIBS) \ $(FLAC_LIBS) +if ENABLE_FLAC +libplaylist_plugins_a_SOURCES += \ + src/playlist/plugins/FlacPlaylistPlugin.cxx \ + src/playlist/plugins/FlacPlaylistPlugin.hxx +endif + +if ENABLE_CUE +libplaylist_plugins_a_SOURCES += \ + src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ + src/playlist/plugins/CuePlaylistPlugin.cxx \ + src/playlist/plugins/CuePlaylistPlugin.hxx \ + src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx \ + src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx +endif + if ENABLE_SOUNDCLOUD libplaylist_plugins_a_SOURCES += \ src/playlist/plugins/SoundCloudPlaylistPlugin.cxx \ @@ -1399,8 +1593,9 @@ PLAYLIST_LIBS += $(YAJL_LIBS) endif -if HAVE_EXPAT +if ENABLE_EXPAT libplaylist_plugins_a_SOURCES += \ + src/lib/expat/StreamExpatParser.cxx \ src/lib/expat/ExpatParser.cxx src/lib/expat/ExpatParser.hxx \ src/playlist/plugins/XspfPlaylistPlugin.cxx \ src/playlist/plugins/XspfPlaylistPlugin.hxx \ @@ -1410,12 +1605,6 @@ src/playlist/plugins/RssPlaylistPlugin.hxx endif -if HAVE_GLIB -libplaylist_plugins_a_SOURCES += \ - src/playlist/plugins/PlsPlaylistPlugin.cxx \ - src/playlist/plugins/PlsPlaylistPlugin.hxx -endif - # # Filter plugins # @@ -1472,7 +1661,9 @@ test/test_mixramp \ test/test_pcm \ test/test_protocol \ - test/test_queue_priority + test/test_queue_priority \ + test/TestFs \ + test/TestIcu if ENABLE_CURL C_TESTS += test/test_icy_parser @@ -1493,10 +1684,13 @@ test/read_conf \ test/run_resolver \ test/run_input \ + test/WriteFile \ test/dump_text_file \ test/dump_playlist \ test/run_decoder \ test/read_tags \ + test/ReadApeTags \ + test/ContainerScan \ test/run_filter \ test/run_output \ test/run_convert \ @@ -1520,11 +1714,11 @@ noinst_PROGRAMS += test/visit_archive endif -if HAVE_ID3TAG +if ENABLE_ID3TAG noinst_PROGRAMS += test/dump_rva2 endif -if HAVE_ALSA +if ENABLE_ALSA # this debug program is still ALSA specific noinst_PROGRAMS += test/read_mixer endif @@ -1532,17 +1726,16 @@ test_read_conf_LDADD = \ libconf.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_read_conf_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ test/read_conf.cxx test_run_resolver_LDADD = \ - libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libnet.a \ + libutil.a test_run_resolver_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ test/run_resolver.cxx @@ -1553,16 +1746,14 @@ $(DB_LIBS) \ $(TAG_LIBS) \ libconf.a \ - libutil.a \ libevent.a \ $(FS_LIBS) \ libsystem.a \ $(ICU_LDADD) \ - $(GLIB_LIBS) + libutil.a test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \ src/protocol/Ack.cxx \ src/Log.cxx src/LogBackend.cxx \ - src/db/DatabaseError.cxx \ src/db/Registry.cxx \ src/db/Selection.cxx \ src/db/PlaylistVector.cxx \ @@ -1572,24 +1763,28 @@ src/TagSave.cxx \ src/SongFilter.cxx -if HAVE_LIBUPNP +if ENABLE_UPNP test_DumpDatabase_SOURCES += src/lib/expat/ExpatParser.cxx endif test_run_storage_LDADD = \ $(STORAGE_LIBS) \ $(FS_LIBS) \ + $(ICU_LDADD) \ libevent.a \ libthread.a \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_run_storage_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ test/ScopeIOThread.hxx \ test/run_storage.cxx +if ENABLE_WEBDAV +test_run_storage_SOURCES += $(CURL_SOURCES) +endif + endif test_run_input_LDADD = \ @@ -1597,15 +1792,14 @@ $(ARCHIVE_LIBS) \ $(TAG_LIBS) \ libconf.a \ - libutil.a \ libevent.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - $(GLIB_LIBS) + libutil.a test_run_input_SOURCES = test/run_input.cxx \ test/ScopeIOThread.hxx \ - test/stdbin.h \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ src/TagSave.cxx @@ -1617,7 +1811,6 @@ src/IOThread.cxx \ test/run_neighbor_explorer.cxx test_run_neighbor_explorer_LDADD = $(AM_LDADD) \ - $(GLIB_LIBS) \ $(NEIGHBOR_LIBS) \ $(INPUT_LIBS) \ $(ARCHIVE_LIBS) \ @@ -1625,11 +1818,12 @@ libconf.a \ libevent.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ libthread.a \ libutil.a -if HAVE_LIBUPNP +if ENABLE_UPNP test_run_neighbor_explorer_SOURCES += src/lib/expat/ExpatParser.cxx endif @@ -1642,12 +1836,12 @@ $(ARCHIVE_LIBS) \ $(TAG_LIBS) \ libconf.a \ - libutil.a \ libevent.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - $(GLIB_LIBS) + libutil.a test_visit_archive_SOURCES = test/visit_archive.cxx \ test/ScopeIOThread.hxx \ src/Log.cxx src/LogBackend.cxx \ @@ -1656,25 +1850,35 @@ endif -if HAVE_ZLIB +if ENABLE_ZLIB noinst_PROGRAMS += test/run_gzip test/run_gunzip test_run_gzip_LDADD = \ libutil.a \ $(FS_LIBS) -test_run_gzip_SOURCES = test/run_gzip.cxx +test_run_gzip_SOURCES = test/run_gzip.cxx \ + src/Log.cxx src/LogBackend.cxx test_run_gunzip_SOURCES = test/run_gunzip.cxx \ src/Log.cxx src/LogBackend.cxx test_run_gunzip_LDADD = \ - $(GLIB_LIBS) \ - libutil.a \ $(FS_LIBS) \ - libsystem.a + $(ICU_LDADD) \ + libsystem.a \ + libutil.a endif +test_WriteFile_LDADD = \ + $(FS_LIBS) \ + $(ICU_LDADD) \ + libsystem.a \ + libutil.a +test_WriteFile_SOURCES = \ + src/Log.cxx src/LogBackend.cxx \ + test/WriteFile.cxx + test_dump_text_file_LDADD = \ $(INPUT_LIBS) \ $(ARCHIVE_LIBS) \ @@ -1682,43 +1886,42 @@ libconf.a \ libevent.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ libthread.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_dump_text_file_SOURCES = test/dump_text_file.cxx \ test/ScopeIOThread.hxx \ - test/stdbin.h \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx test_dump_playlist_LDADD = \ $(PLAYLIST_LIBS) \ $(FLAC_LIBS) \ - $(INPUT_LIBS) \ - $(ARCHIVE_LIBS) \ $(DECODER_LIBS) \ $(TAG_LIBS) \ + $(XIPH_LIBS) \ + $(INPUT_LIBS) \ + $(ARCHIVE_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ libutil.a \ - libpcm.a \ - $(GLIB_LIBS) + libpcm.a test_dump_playlist_SOURCES = test/dump_playlist.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx \ - $(DECODER_SRC) \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ src/TagSave.cxx \ src/TagFile.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ src/DetachedSong.cxx -if HAVE_FLAC +if ENABLE_FLAC test_dump_playlist_SOURCES += \ src/ReplayGainInfo.cxx \ src/decoder/plugins/FlacMetadata.cxx @@ -1731,24 +1934,20 @@ $(ARCHIVE_LIBS) \ $(TAG_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_run_decoder_SOURCES = test/run_decoder.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx \ - test/stdbin.h \ + src/DetachedSong.cxx \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ - src/ReplayGainInfo.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ - $(ARCHIVE_SRC) \ - $(INPUT_SRC) \ - $(TAG_SRC) \ - $(DECODER_SRC) + src/ReplayGainInfo.cxx test_read_tags_LDADD = \ $(DECODER_LIBS) \ @@ -1757,26 +1956,63 @@ $(ARCHIVE_LIBS) \ $(TAG_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_read_tags_SOURCES = test/read_tags.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx \ + src/DetachedSong.cxx \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ + src/ReplayGainInfo.cxx + +test_ReadApeTags_LDADD = \ + $(TAG_LIBS) \ + $(INPUT_LIBS) \ + $(ARCHIVE_LIBS) \ + $(FS_LIBS) \ + $(ICU_LDADD) \ + libsystem.a \ + libutil.a +test_ReadApeTags_SOURCES = \ + src/Log.cxx src/LogBackend.cxx \ + test/ReadApeTags.cxx + +test_ContainerScan_LDADD = \ + $(DECODER_LIBS) \ + libpcm.a \ + $(INPUT_LIBS) \ + $(ARCHIVE_LIBS) \ + $(TAG_LIBS) \ + libconf.a \ + libbasic.a \ + libevent.a \ + libthread.a \ + $(FS_LIBS) \ + $(ICU_LDADD) \ + libsystem.a \ + libutil.a +test_ContainerScan_SOURCES = test/ContainerScan.cxx \ + src/DetachedSong.cxx \ + src/SongSave.cxx src/TagSave.cxx \ + src/Log.cxx src/LogBackend.cxx \ src/ReplayGainInfo.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ $(DECODER_SRC) -if HAVE_ID3TAG +if ENABLE_ID3TAG test_dump_rva2_LDADD = \ $(TAG_LIBS) \ - libutil.a \ - $(GLIB_LIBS) + $(INPUT_LIBS) \ + $(ARCHIVE_LIBS) \ + $(FS_LIBS) \ + $(ICU_LDADD) \ + libsystem.a \ + libutil.a test_dump_rva2_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ test/dump_rva2.cxx @@ -1785,49 +2021,36 @@ test_run_filter_LDADD = \ $(FILTER_LIBS) \ libconf.a \ + libbasic.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_run_filter_SOURCES = test/run_filter.cxx \ - test/FakeReplayGainConfig.cxx \ - test/stdbin.h \ src/Log.cxx src/LogBackend.cxx \ - src/filter/FilterPlugin.cxx src/filter/FilterRegistry.cxx \ - src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx \ - src/AudioParser.cxx \ - src/ReplayGainInfo.cxx + src/filter/FilterPlugin.cxx src/filter/FilterRegistry.cxx if ENABLE_ENCODER noinst_PROGRAMS += test/run_encoder test_run_encoder_SOURCES = test/run_encoder.cxx \ - test/stdbin.h \ - src/Log.cxx src/LogBackend.cxx \ - src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx \ - src/AudioParser.cxx + src/Log.cxx src/LogBackend.cxx test_run_encoder_LDADD = \ $(ENCODER_LIBS) \ $(TAG_LIBS) \ libconf.a \ + libbasic.a \ libpcm.a \ libthread.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a endif -if ENABLE_VORBIS_ENCODER +if ENABLE_VORBISENC noinst_PROGRAMS += test/test_vorbis_encoder test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \ - test/stdbin.h \ - src/Log.cxx src/LogBackend.cxx \ - src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx \ - src/AudioParser.cxx \ - $(ENCODER_SRC) + src/Log.cxx src/LogBackend.cxx test_test_vorbis_encoder_CPPFLAGS = $(AM_CPPFLAGS) \ $(ENCODER_CFLAGS) test_test_vorbis_encoder_LDADD = $(MPD_LIBS) \ @@ -1835,21 +2058,19 @@ $(PCM_LIBS) \ $(TAG_LIBS) \ libconf.a \ + libbasic.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a endif test_software_volume_SOURCES = test/software_volume.cxx \ - test/stdbin.h \ - src/Log.cxx src/LogBackend.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ - src/AudioParser.cxx + src/Log.cxx src/LogBackend.cxx test_software_volume_LDADD = \ $(PCM_LIBS) \ - libutil.a \ - $(GLIB_LIBS) + libbasic.a \ + libutil.a test_run_avahi_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ @@ -1862,28 +2083,26 @@ libevent.a \ libsystem.a \ libutil.a \ - $(GLIB_LIBS) \ $(AVAHI_LIBS) test_run_normalize_SOURCES = test/run_normalize.cxx \ - test/stdbin.h \ + src/Log.cxx src/LogBackend.cxx \ src/CheckAudioFormat.cxx \ src/AudioCompress/compress.c \ src/AudioParser.cxx test_run_normalize_LDADD = \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_run_convert_SOURCES = test/run_convert.cxx \ - src/Log.cxx src/LogBackend.cxx \ - src/AudioFormat.cxx \ - src/CheckAudioFormat.cxx \ - src/AudioParser.cxx + src/Log.cxx src/LogBackend.cxx test_run_convert_LDADD = \ $(PCM_LIBS) \ libconf.a \ - libutil.a \ - $(GLIB_LIBS) + libbasic.a \ + $(FS_LIBS) \ + libsystem.a \ + $(ICU_LDADD) \ + libutil.a test_run_output_LDADD = $(MPD_LIBS) \ $(PCM_LIBS) \ @@ -1893,21 +2112,18 @@ $(FILTER_LIBS) \ $(TAG_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ + libnet.a \ libsystem.a \ libthread.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_run_output_SOURCES = test/run_output.cxx \ - test/FakeReplayGainConfig.cxx \ test/ScopeIOThread.hxx \ - test/stdbin.h \ src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx \ - src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx \ - src/AudioParser.cxx \ src/output/Domain.cxx \ src/output/Init.cxx src/output/Finish.cxx src/output/Registry.cxx \ src/output/OutputPlugin.cxx \ @@ -1915,23 +2131,23 @@ src/mixer/MixerType.cxx \ src/filter/FilterPlugin.cxx \ src/filter/FilterConfig.cxx \ - src/ReplayGainInfo.cxx + src/filter/Observer.cxx test_read_mixer_LDADD = \ libpcm.a \ libmixer_plugins.a \ $(OUTPUT_LIBS) \ libconf.a \ + libbasic.a \ libevent.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a test_read_mixer_SOURCES = test/read_mixer.cxx \ src/Log.cxx src/LogBackend.cxx \ src/mixer/MixerControl.cxx \ src/filter/FilterPlugin.cxx \ - src/AudioFormat.cxx \ src/filter/plugins/VolumeFilterPlugin.cxx if ENABLE_BZIP2_TEST @@ -1956,11 +2172,14 @@ test_run_inotify_LDADD = \ libevent.a \ libsystem.a \ - libutil.a \ - $(GLIB_LIBS) + libutil.a endif test_test_util_SOURCES = \ + test/DivideStringTest.hxx \ + test/SplitStringTest.hxx \ + test/UriUtilTest.hxx \ + test/MimeTypeTest.hxx \ test/TestCircularBuffer.hxx \ test/test_util.cxx test_test_util_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 @@ -1983,7 +2202,6 @@ test_test_rewind_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 test_test_rewind_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations test_test_rewind_LDADD = \ - $(GLIB_LIBS) \ $(INPUT_LIBS) \ libthread.a \ libtag.a \ @@ -1997,7 +2215,6 @@ test_test_mixramp_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations test_test_mixramp_LDADD = \ libutil.a \ - $(GLIB_LIBS) \ $(CPPUNIT_LIBS) if ENABLE_CURL @@ -2009,12 +2226,11 @@ test_test_icy_parser_LDADD = \ libtag.a \ libutil.a \ - $(GLIB_LIBS) \ $(CPPUNIT_LIBS) endif test_test_pcm_SOURCES = \ - src/AudioFormat.cxx \ + test/TestAudioFormat.cxx test/TestAudioFormat.hxx \ test/test_pcm_util.hxx \ test/test_pcm_dither.cxx \ test/test_pcm_pack.cxx \ @@ -2022,6 +2238,7 @@ test/test_pcm_format.cxx \ test/test_pcm_volume.cxx \ test/test_pcm_mix.cxx \ + test/test_pcm_interleave.cxx \ test/test_pcm_export.cxx \ test/test_pcm_all.hxx \ test/test_pcm_main.cxx @@ -2029,9 +2246,9 @@ test_test_pcm_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations test_test_pcm_LDADD = \ $(PCM_LIBS) \ + libbasic.a \ libutil.a \ - $(CPPUNIT_LIBS) \ - $(GLIB_LIBS) + $(CPPUNIT_LIBS) test_test_archive_SOURCES = \ src/Log.cxx src/LogBackend.cxx \ @@ -2041,7 +2258,6 @@ test_test_archive_LDADD = \ libarchive.a \ libutil.a \ - $(GLIB_LIBS) \ $(CPPUNIT_LIBS) if ENABLE_DATABASE @@ -2051,6 +2267,7 @@ src/PlaylistError.cxx \ src/DetachedSong.cxx \ src/SongLoader.cxx \ + src/LocateUri.cxx \ src/Log.cxx \ test/test_translate_song.cxx test_test_translate_song_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 @@ -2059,9 +2276,9 @@ $(STORAGE_LIBS) \ libtag.a \ $(FS_LIBS) \ + $(ICU_LDADD) \ libsystem.a \ libutil.a \ - $(GLIB_LIBS) \ $(CPPUNIT_LIBS) endif @@ -2087,6 +2304,23 @@ libutil.a \ $(CPPUNIT_LIBS) +test_TestFs_SOURCES = \ + test/TestFs.cxx +test_TestFs_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 +test_TestFs_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations +test_TestFs_LDADD = \ + $(FS_LIBS) \ + $(CPPUNIT_LIBS) + +test_TestIcu_SOURCES = \ + test/TestIcu.cxx +test_TestIcu_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 +test_TestIcu_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations +test_TestIcu_LDADD = \ + $(ICU_LDADD) \ + libutil.a \ + $(CPPUNIT_LIBS) + if ENABLE_DSD noinst_PROGRAMS += src/pcm/dsd2pcm/dsd2pcm @@ -2109,7 +2343,7 @@ # man_MANS = doc/mpd.1 doc/mpd.conf.5 -doc_DATA = AUTHORS COPYING NEWS README doc/mpdconf.example +doc_DATA = AUTHORS COPYING NEWS README.md doc/mpdconf.example DOCBOOK_FILES = doc/protocol.xml doc/user.xml doc/developer.xml @@ -2149,7 +2383,7 @@ rm -f $(DESTDIR)$(docdir)/api/html/*.* upload: $(DOCBOOK_HTML) doc/api/html/index.html - rsync -vpruz --delete doc/ www.musicpd.org:/var/www/doc/ \ + rsync -vpruz --delete doc/ www.musicpd.org:/var/www/mpd/doc/ \ --chmod=Dug+rwx,Do+rx,Fug+rw,Fo+r \ --include=protocol --include=protocol/** \ --include=user --include=user/** \ @@ -2179,4 +2413,5 @@ android/src/Bridge.java \ android/src/Loader.java \ android/src/Main.java \ - src/win32/mpd_win32_rc.rc.in src/win32/mpd.ico + win32/res/mpd.rc.in win32/res/mpd.ico \ + src/haiku/App_MusicPD diff -Nru mpd-0.19.21/Makefile.in mpd-0.20.9/Makefile.in --- mpd-0.19.21/Makefile.in 2016-12-13 09:54:19.000000000 +0000 +++ mpd-0.20.9/Makefile.in 2017-06-03 18:58:51.000000000 +0000 @@ -93,11 +93,13 @@ @ANDROID_FALSE@bin_PROGRAMS = src/mpd$(EXEEXT) @ANDROID_FALSE@am__append_1 = \ @ANDROID_FALSE@ src/unix/SignalHandlers.cxx src/unix/SignalHandlers.hxx \ -@ANDROID_FALSE@ src/unix/Daemon.cxx src/unix/Daemon.hxx \ -@ANDROID_FALSE@ src/unix/PidFile.hxx \ @ANDROID_FALSE@ src/CommandLine.cxx src/CommandLine.hxx -@ENABLE_DATABASE_TRUE@am__append_2 = \ +@ANDROID_FALSE@@ENABLE_DAEMON_TRUE@am__append_2 = \ +@ANDROID_FALSE@@ENABLE_DAEMON_TRUE@ src/unix/Daemon.cxx src/unix/Daemon.hxx \ +@ANDROID_FALSE@@ENABLE_DAEMON_TRUE@ src/unix/PidFile.hxx + +@ENABLE_DATABASE_TRUE@am__append_3 = \ @ENABLE_DATABASE_TRUE@ src/queue/PlaylistUpdate.cxx \ @ENABLE_DATABASE_TRUE@ src/command/StorageCommands.cxx src/command/StorageCommands.hxx \ @ENABLE_DATABASE_TRUE@ src/command/DatabaseCommands.cxx src/command/DatabaseCommands.hxx \ @@ -121,7 +123,7 @@ @ENABLE_DATABASE_TRUE@ src/db/DatabasePrint.cxx src/db/DatabasePrint.hxx \ @ENABLE_DATABASE_TRUE@ src/db/DatabaseQueue.cxx src/db/DatabaseQueue.hxx \ @ENABLE_DATABASE_TRUE@ src/db/DatabasePlaylist.cxx src/db/DatabasePlaylist.hxx \ -@ENABLE_DATABASE_TRUE@ src/db/DatabaseError.cxx src/db/DatabaseError.hxx \ +@ENABLE_DATABASE_TRUE@ src/db/DatabaseError.hxx \ @ENABLE_DATABASE_TRUE@ src/db/DatabaseLock.cxx src/db/DatabaseLock.hxx \ @ENABLE_DATABASE_TRUE@ src/db/DatabasePlugin.hxx \ @ENABLE_DATABASE_TRUE@ src/db/Interface.hxx \ @@ -134,114 +136,145 @@ # # Android native library # -@ANDROID_TRUE@am__append_3 = libjava.a libandroid.a libmain.a -@ANDROID_TRUE@am__append_4 = libandroid.a libjava.a -@ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@am__append_5 = \ +@ANDROID_TRUE@am__append_4 = libjava.a libandroid.a libmain.a +@ANDROID_TRUE@am__append_5 = libandroid.a libjava.a +@ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@am__append_6 = \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/InotifyDomain.cxx src/db/update/InotifyDomain.hxx \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/InotifySource.cxx src/db/update/InotifySource.hxx \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/InotifyQueue.cxx src/db/update/InotifyQueue.hxx \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/InotifyUpdate.cxx src/db/update/InotifyUpdate.hxx -@ENABLE_SQLITE_TRUE@am__append_6 = \ +@ENABLE_SQLITE_TRUE@am__append_7 = \ @ENABLE_SQLITE_TRUE@ src/command/StickerCommands.cxx src/command/StickerCommands.hxx \ +@ENABLE_SQLITE_TRUE@ src/lib/sqlite/Error.cxx src/lib/sqlite/Error.hxx \ +@ENABLE_SQLITE_TRUE@ src/lib/sqlite/Util.hxx \ +@ENABLE_SQLITE_TRUE@ src/sticker/Match.hxx \ @ENABLE_SQLITE_TRUE@ src/sticker/StickerDatabase.cxx src/sticker/StickerDatabase.hxx \ @ENABLE_SQLITE_TRUE@ src/sticker/StickerPrint.cxx src/sticker/StickerPrint.hxx \ @ENABLE_SQLITE_TRUE@ src/sticker/SongSticker.cxx src/sticker/SongSticker.hxx -@HAVE_ICU_TRUE@am__append_7 = \ +@HAVE_ICU_TRUE@am__append_8 = \ +@HAVE_ICU_TRUE@ src/lib/icu/Util.cxx src/lib/icu/Util.hxx \ @HAVE_ICU_TRUE@ src/lib/icu/Init.cxx src/lib/icu/Init.hxx -@ENABLE_DSD_TRUE@am__append_8 = \ +@HAVE_WINDOWS_TRUE@am__append_9 = \ +@HAVE_WINDOWS_TRUE@ src/lib/icu/Win32.cxx src/lib/icu/Win32.hxx + +@ENABLE_DSD_TRUE@am__append_10 = \ +@ENABLE_DSD_TRUE@ src/pcm/Dsd16.cxx src/pcm/Dsd16.hxx \ +@ENABLE_DSD_TRUE@ src/pcm/Dsd32.cxx src/pcm/Dsd32.hxx \ @ENABLE_DSD_TRUE@ src/pcm/PcmDsd.cxx src/pcm/PcmDsd.hxx \ @ENABLE_DSD_TRUE@ src/pcm/dsd2pcm/dsd2pcm.c src/pcm/dsd2pcm/dsd2pcm.h -@HAVE_LIBSAMPLERATE_TRUE@am__append_9 = \ -@HAVE_LIBSAMPLERATE_TRUE@ src/pcm/LibsamplerateResampler.cxx src/pcm/LibsamplerateResampler.hxx +@ENABLE_LIBSAMPLERATE_TRUE@am__append_11 = \ +@ENABLE_LIBSAMPLERATE_TRUE@ src/pcm/LibsamplerateResampler.cxx src/pcm/LibsamplerateResampler.hxx + +@ENABLE_SOXR_TRUE@am__append_12 = \ +@ENABLE_SOXR_TRUE@ src/pcm/SoxrResampler.cxx src/pcm/SoxrResampler.hxx -@HAVE_SOXR_TRUE@am__append_10 = \ -@HAVE_SOXR_TRUE@ src/pcm/SoxrResampler.cxx src/pcm/SoxrResampler.hxx -@HAVE_ZLIB_TRUE@am__append_11 = \ -@HAVE_ZLIB_TRUE@ src/lib/zlib/Domain.cxx src/lib/zlib/Domain.hxx \ -@HAVE_ZLIB_TRUE@ src/fs/io/GunzipReader.cxx src/fs/io/GunzipReader.hxx \ -@HAVE_ZLIB_TRUE@ src/fs/io/AutoGunzipReader.cxx src/fs/io/AutoGunzipReader.hxx \ -@HAVE_ZLIB_TRUE@ src/fs/io/GzipOutputStream.cxx src/fs/io/GzipOutputStream.hxx - -@HAVE_ZLIB_TRUE@am__append_12 = $(ZLIB_LIBS) -@ENABLE_DATABASE_TRUE@am__append_13 = libstorage.a -@ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@am__append_14 = \ +# Xiph codec support library +@HAVE_XIPH_TRUE@am__append_13 = libxiph.a +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@am__append_14 = \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggVisitor.cxx src/lib/xiph/OggVisitor.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggSerial.cxx src/lib/xiph/OggSerial.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggSyncState.cxx src/lib/xiph/OggSyncState.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggFind.cxx src/lib/xiph/OggFind.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggPage.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggPacket.cxx src/lib/xiph/OggPacket.hxx \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/OggStreamState.hxx + +@ENABLE_ZLIB_TRUE@am__append_15 = \ +@ENABLE_ZLIB_TRUE@ src/lib/zlib/Error.cxx src/lib/zlib/Error.hxx \ +@ENABLE_ZLIB_TRUE@ src/fs/io/GunzipReader.cxx src/fs/io/GunzipReader.hxx \ +@ENABLE_ZLIB_TRUE@ src/fs/io/AutoGunzipReader.cxx src/fs/io/AutoGunzipReader.hxx \ +@ENABLE_ZLIB_TRUE@ src/fs/io/GzipOutputStream.cxx src/fs/io/GzipOutputStream.hxx + +@ENABLE_ZLIB_TRUE@am__append_16 = $(ZLIB_LIBS) + +# for PathMatchSpec() +@HAVE_WINDOWS_TRUE@am__append_17 = -lshlwapi +@ENABLE_DATABASE_TRUE@am__append_18 = libstorage.a +@ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@am__append_19 = \ @ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@ $(SMBCLIENT_SOURCES) \ @ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@ src/storage/plugins/SmbclientStorage.cxx src/storage/plugins/SmbclientStorage.hxx -@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@am__append_15 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@am__append_20 = \ @ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@ $(NFS_SOURCES) \ @ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@ src/storage/plugins/NfsStorage.cxx src/storage/plugins/NfsStorage.hxx +@ENABLE_DATABASE_TRUE@@ENABLE_WEBDAV_TRUE@am__append_21 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_WEBDAV_TRUE@ src/lib/expat/ExpatParser.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_WEBDAV_TRUE@ src/storage/plugins/CurlStorage.cxx src/storage/plugins/CurlStorage.hxx + # neighbor plugins -@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__append_16 = \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__append_22 = \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/command/NeighborCommands.cxx \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/command/NeighborCommands.hxx -@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__append_17 = libneighbor.a -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@am__append_18 = \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__append_23 = libneighbor.a +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@am__append_24 = \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@ $(SMBCLIENT_SOURCES) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@ src/neighbor/plugins/SmbclientNeighborPlugin.cxx src/neighbor/plugins/SmbclientNeighborPlugin.hxx -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@am__append_19 = \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ $(UPNP_SOURCES) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ src/neighbor/plugins/UpnpNeighborPlugin.cxx src/neighbor/plugins/UpnpNeighborPlugin.hxx - -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@am__append_20 = \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ $(EXPAT_LIBS) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ $(UPNP_LIBS) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@am__append_25 = \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ $(UPNP_SOURCES) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ src/neighbor/plugins/UpnpNeighborPlugin.cxx src/neighbor/plugins/UpnpNeighborPlugin.hxx + +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@am__append_26 = \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ $(EXPAT_LIBS) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ $(UPNP_LIBS) # database plugins -@ENABLE_DATABASE_TRUE@am__append_21 = libdb_plugins.a -@ENABLE_DATABASE_TRUE@@HAVE_LIBMPDCLIENT_TRUE@am__append_22 = \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBMPDCLIENT_TRUE@ src/db/plugins/ProxyDatabasePlugin.cxx src/db/plugins/ProxyDatabasePlugin.hxx - -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@am__append_23 = \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ $(UPNP_SOURCES) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/UpnpDatabasePlugin.cxx src/db/plugins/upnp/UpnpDatabasePlugin.hxx \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Tags.cxx src/db/plugins/upnp/Tags.hxx \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/ContentDirectoryService.cxx \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Directory.cxx src/db/plugins/upnp/Directory.hxx \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Object.cxx src/db/plugins/upnp/Object.hxx - -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@am__append_24 = \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ $(EXPAT_LIBS) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ $(UPNP_LIBS) +@ENABLE_DATABASE_TRUE@am__append_27 = libdb_plugins.a +@ENABLE_DATABASE_TRUE@@ENABLE_LIBMPDCLIENT_TRUE@am__append_28 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_LIBMPDCLIENT_TRUE@ src/db/plugins/ProxyDatabasePlugin.cxx src/db/plugins/ProxyDatabasePlugin.hxx + +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@am__append_29 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(UPNP_SOURCES) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/UpnpDatabasePlugin.cxx src/db/plugins/upnp/UpnpDatabasePlugin.hxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Tags.cxx src/db/plugins/upnp/Tags.hxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/ContentDirectoryService.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Directory.cxx src/db/plugins/upnp/Directory.hxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Object.cxx src/db/plugins/upnp/Object.hxx + +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@am__append_30 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(EXPAT_LIBS) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(UPNP_LIBS) # archive plugins -@ENABLE_ARCHIVE_TRUE@am__append_25 = libarchive.a -@ENABLE_ARCHIVE_TRUE@am__append_26 = \ +@ENABLE_ARCHIVE_TRUE@am__append_31 = libarchive.a +@ENABLE_ARCHIVE_TRUE@am__append_32 = \ +@ENABLE_ARCHIVE_TRUE@ src/TagArchive.cxx src/TagArchive.hxx \ @ENABLE_ARCHIVE_TRUE@ src/db/update/Archive.cxx -@ENABLE_ARCHIVE_TRUE@@HAVE_BZ2_TRUE@am__append_27 = \ -@ENABLE_ARCHIVE_TRUE@@HAVE_BZ2_TRUE@ src/archive/plugins/Bzip2ArchivePlugin.cxx \ -@ENABLE_ARCHIVE_TRUE@@HAVE_BZ2_TRUE@ src/archive/plugins/Bzip2ArchivePlugin.hxx - -@ENABLE_ARCHIVE_TRUE@@HAVE_ZZIP_TRUE@am__append_28 = \ -@ENABLE_ARCHIVE_TRUE@@HAVE_ZZIP_TRUE@ src/archive/plugins/ZzipArchivePlugin.cxx \ -@ENABLE_ARCHIVE_TRUE@@HAVE_ZZIP_TRUE@ src/archive/plugins/ZzipArchivePlugin.hxx - -@ENABLE_ARCHIVE_TRUE@@HAVE_ISO9660_TRUE@am__append_29 = \ -@ENABLE_ARCHIVE_TRUE@@HAVE_ISO9660_TRUE@ src/archive/plugins/Iso9660ArchivePlugin.cxx \ -@ENABLE_ARCHIVE_TRUE@@HAVE_ISO9660_TRUE@ src/archive/plugins/Iso9660ArchivePlugin.hxx - -@HAVE_ID3TAG_TRUE@am__append_30 = \ -@HAVE_ID3TAG_TRUE@ src/tag/TagId3.cxx src/tag/TagId3.hxx \ -@HAVE_ID3TAG_TRUE@ src/tag/TagRva2.cxx src/tag/TagRva2.hxx \ -@HAVE_ID3TAG_TRUE@ src/tag/Riff.cxx src/tag/Riff.hxx \ -@HAVE_ID3TAG_TRUE@ src/tag/Aiff.cxx src/tag/Aiff.hxx +@ENABLE_ARCHIVE_TRUE@@ENABLE_BZ2_TRUE@am__append_33 = \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_BZ2_TRUE@ src/archive/plugins/Bzip2ArchivePlugin.cxx \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_BZ2_TRUE@ src/archive/plugins/Bzip2ArchivePlugin.hxx + +@ENABLE_ARCHIVE_TRUE@@ENABLE_ZZIP_TRUE@am__append_34 = \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_ZZIP_TRUE@ src/archive/plugins/ZzipArchivePlugin.cxx \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_ZZIP_TRUE@ src/archive/plugins/ZzipArchivePlugin.hxx + +@ENABLE_ARCHIVE_TRUE@@ENABLE_ISO9660_TRUE@am__append_35 = \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_ISO9660_TRUE@ src/archive/plugins/Iso9660ArchivePlugin.cxx \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_ISO9660_TRUE@ src/archive/plugins/Iso9660ArchivePlugin.hxx + +@ENABLE_ID3TAG_TRUE@am__append_36 = \ +@ENABLE_ID3TAG_TRUE@ src/tag/Id3Load.cxx src/tag/Id3Load.hxx \ +@ENABLE_ID3TAG_TRUE@ src/tag/Id3Unique.hxx \ +@ENABLE_ID3TAG_TRUE@ src/tag/TagId3.cxx src/tag/TagId3.hxx \ +@ENABLE_ID3TAG_TRUE@ src/tag/TagRva2.cxx src/tag/TagRva2.hxx \ +@ENABLE_ID3TAG_TRUE@ src/tag/Riff.cxx src/tag/Riff.hxx \ +@ENABLE_ID3TAG_TRUE@ src/tag/Aiff.cxx src/tag/Aiff.hxx # ffmpeg -@HAVE_FFMPEG_TRUE@am__append_31 = libffmpeg.a -@ENABLE_DSD_TRUE@am__append_32 = \ +@ENABLE_FFMPEG_TRUE@am__append_37 = libffmpeg.a +@ENABLE_DSD_TRUE@am__append_38 = \ @ENABLE_DSD_TRUE@ src/decoder/plugins/DsdiffDecoderPlugin.cxx \ @ENABLE_DSD_TRUE@ src/decoder/plugins/DsdiffDecoderPlugin.hxx \ @ENABLE_DSD_TRUE@ src/decoder/plugins/DsfDecoderPlugin.cxx \ @@ -249,178 +282,179 @@ @ENABLE_DSD_TRUE@ src/decoder/plugins/DsdLib.cxx \ @ENABLE_DSD_TRUE@ src/decoder/plugins/DsdLib.hxx -@HAVE_MAD_TRUE@am__append_33 = \ -@HAVE_MAD_TRUE@ src/decoder/plugins/MadDecoderPlugin.cxx \ -@HAVE_MAD_TRUE@ src/decoder/plugins/MadDecoderPlugin.hxx - -@HAVE_MPG123_TRUE@am__append_34 = \ -@HAVE_MPG123_TRUE@ src/decoder/plugins/Mpg123DecoderPlugin.cxx \ -@HAVE_MPG123_TRUE@ src/decoder/plugins/Mpg123DecoderPlugin.hxx - -@HAVE_MPCDEC_TRUE@am__append_35 = \ -@HAVE_MPCDEC_TRUE@ src/decoder/plugins/MpcdecDecoderPlugin.cxx \ -@HAVE_MPCDEC_TRUE@ src/decoder/plugins/MpcdecDecoderPlugin.hxx - -@HAVE_OPUS_TRUE@am__append_36 = \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OggUtil.cxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OggUtil.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OggSyncState.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OggFind.cxx src/decoder/plugins/OggFind.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusDomain.cxx src/decoder/plugins/OpusDomain.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusReader.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusHead.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusHead.cxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusTags.cxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusTags.hxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusDecoderPlugin.cxx \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/OpusDecoderPlugin.h - -@HAVE_WAVPACK_TRUE@am__append_37 = \ -@HAVE_WAVPACK_TRUE@ src/decoder/plugins/WavpackDecoderPlugin.cxx \ -@HAVE_WAVPACK_TRUE@ src/decoder/plugins/WavpackDecoderPlugin.hxx - -@HAVE_ADPLUG_TRUE@am__append_38 = \ -@HAVE_ADPLUG_TRUE@ src/decoder/plugins/AdPlugDecoderPlugin.cxx \ -@HAVE_ADPLUG_TRUE@ src/decoder/plugins/AdPlugDecoderPlugin.h +@ENABLE_MAD_TRUE@am__append_39 = \ +@ENABLE_MAD_TRUE@ src/decoder/plugins/MadDecoderPlugin.cxx \ +@ENABLE_MAD_TRUE@ src/decoder/plugins/MadDecoderPlugin.hxx + +@ENABLE_MPG123_TRUE@am__append_40 = \ +@ENABLE_MPG123_TRUE@ src/decoder/plugins/Mpg123DecoderPlugin.cxx \ +@ENABLE_MPG123_TRUE@ src/decoder/plugins/Mpg123DecoderPlugin.hxx + +@ENABLE_MPCDEC_TRUE@am__append_41 = \ +@ENABLE_MPCDEC_TRUE@ src/decoder/plugins/MpcdecDecoderPlugin.cxx \ +@ENABLE_MPCDEC_TRUE@ src/decoder/plugins/MpcdecDecoderPlugin.hxx + +@ENABLE_OPUS_TRUE@am__append_42 = \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusDomain.cxx src/decoder/plugins/OpusDomain.hxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusReader.hxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusHead.hxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusHead.cxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusTags.cxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusTags.hxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusDecoderPlugin.cxx \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/OpusDecoderPlugin.h + +@ENABLE_WAVPACK_TRUE@am__append_43 = \ +@ENABLE_WAVPACK_TRUE@ src/decoder/plugins/WavpackDecoderPlugin.cxx \ +@ENABLE_WAVPACK_TRUE@ src/decoder/plugins/WavpackDecoderPlugin.hxx + +@ENABLE_ADPLUG_TRUE@am__append_44 = \ +@ENABLE_ADPLUG_TRUE@ src/decoder/plugins/AdPlugDecoderPlugin.cxx \ +@ENABLE_ADPLUG_TRUE@ src/decoder/plugins/AdPlugDecoderPlugin.h + +@ENABLE_FAAD_TRUE@am__append_45 = \ +@ENABLE_FAAD_TRUE@ src/decoder/plugins/FaadDecoderPlugin.cxx src/decoder/plugins/FaadDecoderPlugin.hxx -@HAVE_FAAD_TRUE@am__append_39 = \ -@HAVE_FAAD_TRUE@ src/decoder/plugins/FaadDecoderPlugin.cxx src/decoder/plugins/FaadDecoderPlugin.hxx +@HAVE_OGG_TRUE@am__append_46 = \ +@HAVE_OGG_TRUE@ src/decoder/plugins/OggDecoder.cxx src/decoder/plugins/OggDecoder.hxx -@HAVE_XIPH_TRUE@am__append_40 = \ -@HAVE_XIPH_TRUE@ src/decoder/plugins/XiphTags.cxx src/decoder/plugins/XiphTags.hxx \ +@HAVE_XIPH_TRUE@am__append_47 = \ @HAVE_XIPH_TRUE@ src/decoder/plugins/OggCodec.cxx src/decoder/plugins/OggCodec.hxx -@ENABLE_VORBIS_DECODER_TRUE@am__append_41 = \ +@ENABLE_VORBIS_DECODER_TRUE@am__append_48 = \ @ENABLE_VORBIS_DECODER_TRUE@ src/decoder/plugins/VorbisDomain.cxx src/decoder/plugins/VorbisDomain.hxx \ -@ENABLE_VORBIS_DECODER_TRUE@ src/decoder/plugins/VorbisComments.cxx src/decoder/plugins/VorbisComments.hxx \ @ENABLE_VORBIS_DECODER_TRUE@ src/decoder/plugins/VorbisDecoderPlugin.cxx src/decoder/plugins/VorbisDecoderPlugin.h -@HAVE_FLAC_TRUE@am__append_42 = \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacInput.cxx src/decoder/plugins/FlacInput.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacIOHandle.cxx src/decoder/plugins/FlacIOHandle.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacMetadata.cxx src/decoder/plugins/FlacMetadata.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacPcm.cxx src/decoder/plugins/FlacPcm.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacDomain.cxx src/decoder/plugins/FlacDomain.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacCommon.cxx src/decoder/plugins/FlacCommon.hxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacDecoderPlugin.cxx \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacDecoderPlugin.h - -@HAVE_AUDIOFILE_TRUE@am__append_43 = \ -@HAVE_AUDIOFILE_TRUE@ src/decoder/plugins/AudiofileDecoderPlugin.cxx \ -@HAVE_AUDIOFILE_TRUE@ src/decoder/plugins/AudiofileDecoderPlugin.hxx +@ENABLE_FLAC_TRUE@am__append_49 = \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacInput.cxx src/decoder/plugins/FlacInput.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacIOHandle.cxx src/decoder/plugins/FlacIOHandle.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacMetadata.cxx src/decoder/plugins/FlacMetadata.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacPcm.cxx src/decoder/plugins/FlacPcm.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacDomain.cxx src/decoder/plugins/FlacDomain.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacCommon.cxx src/decoder/plugins/FlacCommon.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacStreamDecoder.hxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacDecoderPlugin.cxx \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/FlacDecoderPlugin.h + +@ENABLE_AUDIOFILE_TRUE@am__append_50 = \ +@ENABLE_AUDIOFILE_TRUE@ src/decoder/plugins/AudiofileDecoderPlugin.cxx \ +@ENABLE_AUDIOFILE_TRUE@ src/decoder/plugins/AudiofileDecoderPlugin.hxx -@ENABLE_MIKMOD_DECODER_TRUE@am__append_44 = \ +@ENABLE_MIKMOD_DECODER_TRUE@am__append_51 = \ @ENABLE_MIKMOD_DECODER_TRUE@ src/decoder/plugins/MikmodDecoderPlugin.cxx \ @ENABLE_MIKMOD_DECODER_TRUE@ src/decoder/plugins/MikmodDecoderPlugin.hxx -@HAVE_MODPLUG_TRUE@am__append_45 = libmodplug_decoder_plugin.a -@HAVE_MODPLUG_TRUE@am__append_46 = libmodplug_decoder_plugin.a $(MODPLUG_LIBS) -@ENABLE_SIDPLAY_TRUE@am__append_47 = \ +@ENABLE_MODPLUG_TRUE@am__append_52 = libmodplug_decoder_plugin.a +@ENABLE_MODPLUG_TRUE@am__append_53 = libmodplug_decoder_plugin.a $(MODPLUG_LIBS) +@ENABLE_SIDPLAY_TRUE@am__append_54 = \ @ENABLE_SIDPLAY_TRUE@ src/decoder/plugins/SidplayDecoderPlugin.cxx \ @ENABLE_SIDPLAY_TRUE@ src/decoder/plugins/SidplayDecoderPlugin.hxx -@ENABLE_FLUIDSYNTH_TRUE@am__append_48 = \ +@ENABLE_FLUIDSYNTH_TRUE@am__append_55 = \ @ENABLE_FLUIDSYNTH_TRUE@ src/decoder/plugins/FluidsynthDecoderPlugin.cxx \ @ENABLE_FLUIDSYNTH_TRUE@ src/decoder/plugins/FluidsynthDecoderPlugin.hxx -@ENABLE_WILDMIDI_TRUE@am__append_49 = \ +@ENABLE_WILDMIDI_TRUE@am__append_56 = \ @ENABLE_WILDMIDI_TRUE@ src/decoder/plugins/WildmidiDecoderPlugin.cxx \ @ENABLE_WILDMIDI_TRUE@ src/decoder/plugins/WildmidiDecoderPlugin.hxx -@HAVE_FFMPEG_TRUE@am__append_50 = \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegIo.cxx \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegIo.hxx \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegMetaData.cxx \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegMetaData.hxx \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegDecoderPlugin.cxx \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegDecoderPlugin.hxx +@ENABLE_FFMPEG_TRUE@am__append_57 = \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegIo.cxx \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegIo.hxx \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegMetaData.cxx \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegMetaData.hxx \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegDecoderPlugin.cxx \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegDecoderPlugin.hxx -@ENABLE_SNDFILE_TRUE@am__append_51 = \ +@ENABLE_SNDFILE_TRUE@am__append_58 = \ @ENABLE_SNDFILE_TRUE@ src/decoder/plugins/SndfileDecoderPlugin.cxx \ @ENABLE_SNDFILE_TRUE@ src/decoder/plugins/SndfileDecoderPlugin.hxx -@HAVE_GME_TRUE@am__append_52 = \ -@HAVE_GME_TRUE@ src/decoder/plugins/GmeDecoderPlugin.cxx src/decoder/plugins/GmeDecoderPlugin.hxx +@ENABLE_GME_TRUE@am__append_59 = \ +@ENABLE_GME_TRUE@ src/decoder/plugins/GmeDecoderPlugin.cxx src/decoder/plugins/GmeDecoderPlugin.hxx # encoder plugins -@ENABLE_ENCODER_TRUE@am__append_53 = libencoder_plugins.a -@ENABLE_ENCODER_TRUE@@HAVE_OGG_ENCODER_TRUE@am__append_54 = \ -@ENABLE_ENCODER_TRUE@@HAVE_OGG_ENCODER_TRUE@ src/encoder/plugins/OggSerial.cxx \ -@ENABLE_ENCODER_TRUE@@HAVE_OGG_ENCODER_TRUE@ src/encoder/plugins/OggSerial.hxx \ -@ENABLE_ENCODER_TRUE@@HAVE_OGG_ENCODER_TRUE@ src/encoder/plugins/OggStream.hxx - -@ENABLE_ENCODER_TRUE@@ENABLE_WAVE_ENCODER_TRUE@am__append_55 = \ +@ENABLE_ENCODER_TRUE@am__append_60 = libencoder_plugins.a +@ENABLE_ENCODER_TRUE@@ENABLE_WAVE_ENCODER_TRUE@am__append_61 = \ @ENABLE_ENCODER_TRUE@@ENABLE_WAVE_ENCODER_TRUE@ src/encoder/plugins/WaveEncoderPlugin.cxx \ @ENABLE_ENCODER_TRUE@@ENABLE_WAVE_ENCODER_TRUE@ src/encoder/plugins/WaveEncoderPlugin.hxx -@ENABLE_ENCODER_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@am__append_56 = \ -@ENABLE_ENCODER_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/encoder/plugins/VorbisEncoderPlugin.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/encoder/plugins/VorbisEncoderPlugin.hxx - -@ENABLE_ENCODER_TRUE@@HAVE_OPUS_TRUE@am__append_57 = \ -@ENABLE_ENCODER_TRUE@@HAVE_OPUS_TRUE@ src/encoder/plugins/OpusEncoderPlugin.cxx \ -@ENABLE_ENCODER_TRUE@@HAVE_OPUS_TRUE@ src/encoder/plugins/OpusEncoderPlugin.hxx - -@ENABLE_ENCODER_TRUE@@ENABLE_LAME_ENCODER_TRUE@am__append_58 = \ -@ENABLE_ENCODER_TRUE@@ENABLE_LAME_ENCODER_TRUE@ src/encoder/plugins/LameEncoderPlugin.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_LAME_ENCODER_TRUE@ src/encoder/plugins/LameEncoderPlugin.hxx - -@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_ENCODER_TRUE@am__append_59 = \ -@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_ENCODER_TRUE@ src/encoder/plugins/TwolameEncoderPlugin.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_ENCODER_TRUE@ src/encoder/plugins/TwolameEncoderPlugin.hxx +@ENABLE_ENCODER_TRUE@@HAVE_OGG_TRUE@am__append_62 = \ +@ENABLE_ENCODER_TRUE@@HAVE_OGG_TRUE@ src/encoder/plugins/OggEncoder.hxx + +@ENABLE_ENCODER_TRUE@@ENABLE_VORBISENC_TRUE@am__append_63 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_VORBISENC_TRUE@ src/encoder/plugins/VorbisEncoderPlugin.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_VORBISENC_TRUE@ src/encoder/plugins/VorbisEncoderPlugin.hxx + +@ENABLE_ENCODER_TRUE@@ENABLE_OPUS_TRUE@am__append_64 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_OPUS_TRUE@ src/encoder/plugins/OpusEncoderPlugin.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_OPUS_TRUE@ src/encoder/plugins/OpusEncoderPlugin.hxx + +@ENABLE_ENCODER_TRUE@@ENABLE_LAME_TRUE@am__append_65 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_LAME_TRUE@ src/encoder/plugins/LameEncoderPlugin.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_LAME_TRUE@ src/encoder/plugins/LameEncoderPlugin.hxx + +@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_TRUE@am__append_66 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_TRUE@ src/encoder/plugins/TwolameEncoderPlugin.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_TRUE@ src/encoder/plugins/TwolameEncoderPlugin.hxx -@ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@am__append_60 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@am__append_67 = \ @ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@ src/encoder/plugins/FlacEncoderPlugin.cxx \ @ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@ src/encoder/plugins/FlacEncoderPlugin.hxx -@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_ENCODER_TRUE@am__append_61 = \ -@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_ENCODER_TRUE@ src/encoder/plugins/ShineEncoderPlugin.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_ENCODER_TRUE@ src/encoder/plugins/ShineEncoderPlugin.hxx +@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_TRUE@am__append_68 = \ +@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_TRUE@ src/encoder/plugins/ShineEncoderPlugin.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_TRUE@ src/encoder/plugins/ShineEncoderPlugin.hxx -@HAVE_ZEROCONF_TRUE@am__append_62 = \ +@HAVE_ZEROCONF_TRUE@am__append_69 = \ @HAVE_ZEROCONF_TRUE@ src/zeroconf/ZeroconfInternal.hxx \ @HAVE_ZEROCONF_TRUE@ src/zeroconf/ZeroconfGlue.cxx src/zeroconf/ZeroconfGlue.hxx -@HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@am__append_63 = \ +@HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@am__append_70 = \ @HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@ src/zeroconf/AvahiPoll.cxx src/zeroconf/AvahiPoll.hxx \ @HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@ src/zeroconf/ZeroconfAvahi.cxx src/zeroconf/ZeroconfAvahi.hxx -@HAVE_BONJOUR_TRUE@@HAVE_ZEROCONF_TRUE@am__append_64 = src/zeroconf/ZeroconfBonjour.cxx src/zeroconf/ZeroconfBonjour.hxx -@HAVE_ALSA_TRUE@am__append_65 = \ -@HAVE_ALSA_TRUE@ src/input/plugins/AlsaInputPlugin.cxx \ -@HAVE_ALSA_TRUE@ src/input/plugins/AlsaInputPlugin.hxx +@HAVE_BONJOUR_TRUE@@HAVE_ZEROCONF_TRUE@am__append_71 = src/zeroconf/ZeroconfBonjour.cxx src/zeroconf/ZeroconfBonjour.hxx +@ENABLE_ALSA_TRUE@am__append_72 = \ +@ENABLE_ALSA_TRUE@ src/input/plugins/AlsaInputPlugin.cxx \ +@ENABLE_ALSA_TRUE@ src/input/plugins/AlsaInputPlugin.hxx -@HAVE_ALSA_TRUE@am__append_66 = $(ALSA_LIBS) -@ENABLE_CURL_TRUE@am__append_67 = \ +@ENABLE_ALSA_TRUE@am__append_73 = $(ALSA_LIBS) +@ENABLE_CURL_TRUE@am__append_74 = \ @ENABLE_CURL_TRUE@ src/input/IcyInputStream.cxx src/input/IcyInputStream.hxx \ @ENABLE_CURL_TRUE@ src/input/plugins/CurlInputPlugin.cxx src/input/plugins/CurlInputPlugin.hxx \ +@ENABLE_CURL_TRUE@ $(CURL_SOURCES) \ @ENABLE_CURL_TRUE@ src/IcyMetaDataParser.cxx src/IcyMetaDataParser.hxx -@ENABLE_SMBCLIENT_TRUE@am__append_68 = \ +@ENABLE_SMBCLIENT_TRUE@am__append_75 = \ @ENABLE_SMBCLIENT_TRUE@ $(SMBCLIENT_SOURCES) \ @ENABLE_SMBCLIENT_TRUE@ src/input/plugins/SmbclientInputPlugin.cxx src/input/plugins/SmbclientInputPlugin.hxx -@ENABLE_NFS_TRUE@am__append_69 = \ +@ENABLE_NFS_TRUE@am__append_76 = \ @ENABLE_NFS_TRUE@ $(NFS_SOURCES) \ @ENABLE_NFS_TRUE@ src/input/plugins/NfsInputPlugin.cxx src/input/plugins/NfsInputPlugin.hxx -@ENABLE_CDIO_PARANOIA_TRUE@am__append_70 = \ +@ENABLE_CDIO_PARANOIA_TRUE@am__append_77 = \ @ENABLE_CDIO_PARANOIA_TRUE@ src/input/plugins/CdioParanoiaInputPlugin.cxx \ @ENABLE_CDIO_PARANOIA_TRUE@ src/input/plugins/CdioParanoiaInputPlugin.hxx -@HAVE_FFMPEG_TRUE@am__append_71 = \ -@HAVE_FFMPEG_TRUE@ src/input/plugins/FfmpegInputPlugin.cxx src/input/plugins/FfmpegInputPlugin.hxx +@ENABLE_FFMPEG_TRUE@am__append_78 = \ +@ENABLE_FFMPEG_TRUE@ src/input/plugins/FfmpegInputPlugin.cxx src/input/plugins/FfmpegInputPlugin.hxx -@ENABLE_MMS_TRUE@am__append_72 = \ +@ENABLE_MMS_TRUE@am__append_79 = \ @ENABLE_MMS_TRUE@ src/input/plugins/MmsInputPlugin.cxx src/input/plugins/MmsInputPlugin.hxx -@HAVE_ALSA_TRUE@am__append_73 = \ -@HAVE_ALSA_TRUE@ src/output/plugins/AlsaOutputPlugin.cxx \ -@HAVE_ALSA_TRUE@ src/output/plugins/AlsaOutputPlugin.hxx +@ENABLE_ALSA_TRUE@am__append_80 = \ +@ENABLE_ALSA_TRUE@ src/output/plugins/AlsaOutputPlugin.cxx \ +@ENABLE_ALSA_TRUE@ src/output/plugins/AlsaOutputPlugin.hxx + +@ENABLE_ALSA_TRUE@am__append_81 = \ +@ENABLE_ALSA_TRUE@ src/mixer/plugins/volume_mapping.h \ +@ENABLE_ALSA_TRUE@ src/mixer/plugins/volume_mapping.c \ +@ENABLE_ALSA_TRUE@ src/mixer/plugins/AlsaMixerPlugin.cxx -@HAVE_ALSA_TRUE@am__append_74 = src/mixer/plugins/AlsaMixerPlugin.cxx -@ANDROID_TRUE@am__append_75 = \ +@ANDROID_TRUE@am__append_82 = \ @ANDROID_TRUE@ src/output/plugins/sles/Object.hxx \ @ANDROID_TRUE@ src/output/plugins/sles/Engine.hxx \ @ANDROID_TRUE@ src/output/plugins/sles/Play.hxx \ @@ -428,57 +462,70 @@ @ANDROID_TRUE@ src/output/plugins/sles/SlesOutputPlugin.cxx \ @ANDROID_TRUE@ src/output/plugins/sles/SlesOutputPlugin.hxx -@ANDROID_TRUE@am__append_76 = -lOpenSLES -@HAVE_ROAR_TRUE@am__append_77 = \ -@HAVE_ROAR_TRUE@ src/output/plugins/RoarOutputPlugin.cxx \ -@HAVE_ROAR_TRUE@ src/output/plugins/RoarOutputPlugin.hxx - -@HAVE_ROAR_TRUE@am__append_78 = src/mixer/plugins/RoarMixerPlugin.cxx -@HAVE_AO_TRUE@am__append_79 = \ -@HAVE_AO_TRUE@ src/output/plugins/AoOutputPlugin.cxx \ -@HAVE_AO_TRUE@ src/output/plugins/AoOutputPlugin.hxx +@ANDROID_TRUE@am__append_83 = -lOpenSLES +@ENABLE_ROAR_TRUE@am__append_84 = \ +@ENABLE_ROAR_TRUE@ src/output/plugins/RoarOutputPlugin.cxx \ +@ENABLE_ROAR_TRUE@ src/output/plugins/RoarOutputPlugin.hxx + +@ENABLE_ROAR_TRUE@am__append_85 = src/mixer/plugins/RoarMixerPlugin.cxx +@ENABLE_AO_TRUE@am__append_86 = \ +@ENABLE_AO_TRUE@ src/output/plugins/AoOutputPlugin.cxx \ +@ENABLE_AO_TRUE@ src/output/plugins/AoOutputPlugin.hxx -@HAVE_FIFO_TRUE@am__append_80 = \ +@HAVE_FIFO_TRUE@am__append_87 = \ @HAVE_FIFO_TRUE@ src/output/plugins/FifoOutputPlugin.cxx \ @HAVE_FIFO_TRUE@ src/output/plugins/FifoOutputPlugin.hxx -@ENABLE_PIPE_OUTPUT_TRUE@am__append_81 = \ +@ENABLE_SNDIO_TRUE@am__append_88 = \ +@ENABLE_SNDIO_TRUE@ src/output/plugins/SndioOutputPlugin.cxx \ +@ENABLE_SNDIO_TRUE@ src/output/plugins/SndioOutputPlugin.hxx + +@ENABLE_HAIKU_TRUE@am__append_89 = \ +@ENABLE_HAIKU_TRUE@ src/output/plugins/HaikuOutputPlugin.cxx \ +@ENABLE_HAIKU_TRUE@ src/output/plugins/HaikuOutputPlugin.hxx + +@ENABLE_HAIKU_TRUE@am__append_90 = \ +@ENABLE_HAIKU_TRUE@ src/mixer/plugins/HaikuMixerPlugin.cxx + +@ENABLE_PIPE_OUTPUT_TRUE@am__append_91 = \ @ENABLE_PIPE_OUTPUT_TRUE@ src/output/plugins/PipeOutputPlugin.cxx \ @ENABLE_PIPE_OUTPUT_TRUE@ src/output/plugins/PipeOutputPlugin.hxx -@HAVE_JACK_TRUE@am__append_82 = \ -@HAVE_JACK_TRUE@ src/output/plugins/JackOutputPlugin.cxx \ -@HAVE_JACK_TRUE@ src/output/plugins/JackOutputPlugin.hxx +@ENABLE_JACK_TRUE@am__append_92 = \ +@ENABLE_JACK_TRUE@ src/output/plugins/JackOutputPlugin.cxx \ +@ENABLE_JACK_TRUE@ src/output/plugins/JackOutputPlugin.hxx -@HAVE_OSS_TRUE@am__append_83 = \ +@HAVE_OSS_TRUE@am__append_93 = \ @HAVE_OSS_TRUE@ src/output/plugins/OssOutputPlugin.cxx \ @HAVE_OSS_TRUE@ src/output/plugins/OssOutputPlugin.hxx -@HAVE_OSS_TRUE@am__append_84 = src/mixer/plugins/OssMixerPlugin.cxx -@HAVE_OPENAL_TRUE@am__append_85 = \ +@HAVE_OSS_TRUE@am__append_94 = src/mixer/plugins/OssMixerPlugin.cxx +@HAVE_OPENAL_TRUE@am__append_95 = \ @HAVE_OPENAL_TRUE@ src/output/plugins/OpenALOutputPlugin.cxx \ @HAVE_OPENAL_TRUE@ src/output/plugins/OpenALOutputPlugin.hxx -@HAVE_OSX_TRUE@am__append_86 = \ +@HAVE_OSX_TRUE@am__append_96 = \ @HAVE_OSX_TRUE@ src/output/plugins/OSXOutputPlugin.cxx \ @HAVE_OSX_TRUE@ src/output/plugins/OSXOutputPlugin.hxx -@HAVE_PULSE_TRUE@am__append_87 = \ -@HAVE_PULSE_TRUE@ src/output/plugins/PulseOutputPlugin.cxx \ -@HAVE_PULSE_TRUE@ src/output/plugins/PulseOutputPlugin.hxx - -@HAVE_PULSE_TRUE@am__append_88 = \ -@HAVE_PULSE_TRUE@ src/mixer/plugins/PulseMixerPlugin.cxx src/mixer/plugins/PulseMixerPlugin.hxx - -@HAVE_SHOUT_TRUE@am__append_89 = \ +@ENABLE_PULSE_TRUE@am__append_97 = \ +@ENABLE_PULSE_TRUE@ src/output/plugins/PulseOutputPlugin.cxx \ +@ENABLE_PULSE_TRUE@ src/output/plugins/PulseOutputPlugin.hxx + +@ENABLE_PULSE_TRUE@am__append_98 = \ +@ENABLE_PULSE_TRUE@ src/mixer/plugins/PulseMixerPlugin.cxx src/mixer/plugins/PulseMixerPlugin.hxx + +@ENABLE_PULSE_TRUE@am__append_99 = libpulse.a +@ENABLE_PULSE_TRUE@am__append_100 = $(PULSE_LIBS2) +@HAVE_SHOUT_TRUE@am__append_101 = \ @HAVE_SHOUT_TRUE@ src/output/plugins/ShoutOutputPlugin.cxx \ @HAVE_SHOUT_TRUE@ src/output/plugins/ShoutOutputPlugin.hxx -@ENABLE_RECORDER_OUTPUT_TRUE@am__append_90 = \ +@ENABLE_RECORDER_OUTPUT_TRUE@am__append_102 = \ @ENABLE_RECORDER_OUTPUT_TRUE@ src/output/plugins/RecorderOutputPlugin.cxx \ @ENABLE_RECORDER_OUTPUT_TRUE@ src/output/plugins/RecorderOutputPlugin.hxx -@ENABLE_HTTPD_OUTPUT_TRUE@am__append_91 = \ +@ENABLE_HTTPD_OUTPUT_TRUE@am__append_103 = \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/IcyMetaDataServer.cxx \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/IcyMetaDataServer.hxx \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/Page.cxx src/output/plugins/httpd/Page.hxx \ @@ -488,45 +535,56 @@ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/HttpdOutputPlugin.cxx \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/HttpdOutputPlugin.hxx -@ENABLE_SOLARIS_OUTPUT_TRUE@am__append_92 = \ +@ENABLE_SOLARIS_OUTPUT_TRUE@am__append_104 = \ @ENABLE_SOLARIS_OUTPUT_TRUE@ src/output/plugins/SolarisOutputPlugin.cxx src/output/plugins/SolarisOutputPlugin.hxx -@ENABLE_WINMM_OUTPUT_TRUE@am__append_93 = \ +@ENABLE_WINMM_OUTPUT_TRUE@am__append_105 = \ @ENABLE_WINMM_OUTPUT_TRUE@ src/output/plugins/WinmmOutputPlugin.cxx \ @ENABLE_WINMM_OUTPUT_TRUE@ src/output/plugins/WinmmOutputPlugin.hxx -@ENABLE_WINMM_OUTPUT_TRUE@am__append_94 = src/mixer/plugins/WinmmMixerPlugin.cxx -@ENABLE_SOUNDCLOUD_TRUE@am__append_95 = \ +@ENABLE_WINMM_OUTPUT_TRUE@am__append_106 = src/mixer/plugins/WinmmMixerPlugin.cxx +@ENABLE_FLAC_TRUE@am__append_107 = \ +@ENABLE_FLAC_TRUE@ src/playlist/plugins/FlacPlaylistPlugin.cxx \ +@ENABLE_FLAC_TRUE@ src/playlist/plugins/FlacPlaylistPlugin.hxx + +@ENABLE_CUE_TRUE@am__append_108 = \ +@ENABLE_CUE_TRUE@ src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/CuePlaylistPlugin.cxx \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/CuePlaylistPlugin.hxx \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx + +@ENABLE_SOUNDCLOUD_TRUE@am__append_109 = \ @ENABLE_SOUNDCLOUD_TRUE@ src/playlist/plugins/SoundCloudPlaylistPlugin.cxx \ @ENABLE_SOUNDCLOUD_TRUE@ src/playlist/plugins/SoundCloudPlaylistPlugin.hxx -@ENABLE_SOUNDCLOUD_TRUE@am__append_96 = $(YAJL_LIBS) -@HAVE_EXPAT_TRUE@am__append_97 = \ -@HAVE_EXPAT_TRUE@ src/lib/expat/ExpatParser.cxx src/lib/expat/ExpatParser.hxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/XspfPlaylistPlugin.cxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/XspfPlaylistPlugin.hxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/AsxPlaylistPlugin.cxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/AsxPlaylistPlugin.hxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/RssPlaylistPlugin.cxx \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/RssPlaylistPlugin.hxx - -@HAVE_GLIB_TRUE@am__append_98 = \ -@HAVE_GLIB_TRUE@ src/playlist/plugins/PlsPlaylistPlugin.cxx \ -@HAVE_GLIB_TRUE@ src/playlist/plugins/PlsPlaylistPlugin.hxx - -@ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@am__append_99 = test/test_icy_parser -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am__append_100 = test/test_translate_song -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@am__append_101 = test/test_archive -@ENABLE_TEST_TRUE@TESTS = $(am__EXEEXT_4) $(am__append_114) \ -@ENABLE_TEST_TRUE@ $(am__append_115) $(am__append_116) +@ENABLE_SOUNDCLOUD_TRUE@am__append_110 = $(YAJL_LIBS) +@ENABLE_EXPAT_TRUE@am__append_111 = \ +@ENABLE_EXPAT_TRUE@ src/lib/expat/StreamExpatParser.cxx \ +@ENABLE_EXPAT_TRUE@ src/lib/expat/ExpatParser.cxx src/lib/expat/ExpatParser.hxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/XspfPlaylistPlugin.cxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/XspfPlaylistPlugin.hxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/AsxPlaylistPlugin.cxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/AsxPlaylistPlugin.hxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/RssPlaylistPlugin.cxx \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/RssPlaylistPlugin.hxx + +@ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@am__append_112 = test/test_icy_parser +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am__append_113 = test/test_translate_song +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@am__append_114 = test/test_archive +@ENABLE_TEST_TRUE@TESTS = $(am__EXEEXT_4) $(am__append_128) \ +@ENABLE_TEST_TRUE@ $(am__append_129) $(am__append_130) @ENABLE_TEST_TRUE@noinst_PROGRAMS = $(am__EXEEXT_4) \ @ENABLE_TEST_TRUE@ test/read_conf$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_resolver$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_input$(EXEEXT) \ +@ENABLE_TEST_TRUE@ test/WriteFile$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/dump_text_file$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/dump_playlist$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_decoder$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/read_tags$(EXEEXT) \ +@ENABLE_TEST_TRUE@ test/ReadApeTags$(EXEEXT) \ +@ENABLE_TEST_TRUE@ test/ContainerScan$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_filter$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_output$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/run_convert$(EXEEXT) \ @@ -538,30 +596,31 @@ @ENABLE_TEST_TRUE@ $(am__EXEEXT_11) $(am__EXEEXT_12) \ @ENABLE_TEST_TRUE@ $(am__EXEEXT_13) $(am__EXEEXT_14) \ @ENABLE_TEST_TRUE@ $(am__EXEEXT_15) -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am__append_102 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am__append_115 = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/DumpDatabase \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/run_storage -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@am__append_103 = test/run_neighbor_explorer -@ENABLE_TEST_TRUE@@HAVE_AVAHI_TRUE@am__append_104 = test/run_avahi -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@am__append_105 = test/visit_archive -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@am__append_106 = test/dump_rva2 +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@am__append_116 = test/run_neighbor_explorer +@ENABLE_TEST_TRUE@@HAVE_AVAHI_TRUE@am__append_117 = test/run_avahi +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@am__append_118 = test/visit_archive +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@am__append_119 = test/dump_rva2 # this debug program is still ALSA specific -@ENABLE_TEST_TRUE@@HAVE_ALSA_TRUE@am__append_107 = test/read_mixer -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@HAVE_LIBUPNP_TRUE@am__append_108 = src/lib/expat/ExpatParser.cxx -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@@HAVE_LIBUPNP_TRUE@am__append_109 = src/lib/expat/ExpatParser.cxx -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@am__append_110 = test/run_gzip test/run_gunzip -@ENABLE_TEST_TRUE@@HAVE_FLAC_TRUE@am__append_111 = \ -@ENABLE_TEST_TRUE@@HAVE_FLAC_TRUE@ src/ReplayGainInfo.cxx \ -@ENABLE_TEST_TRUE@@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacMetadata.cxx - -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@am__append_112 = test/run_encoder -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@am__append_113 = test/test_vorbis_encoder -@ENABLE_BZIP2_TEST_TRUE@@ENABLE_TEST_TRUE@am__append_114 = test/test_archive_bzip2.sh -@ENABLE_TEST_TRUE@@ENABLE_ZZIP_TEST_TRUE@am__append_115 = test/test_archive_zzip.sh -@ENABLE_ISO9660_TEST_TRUE@@ENABLE_TEST_TRUE@am__append_116 = test/test_archive_iso9660.sh -@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@am__append_117 = test/run_inotify -@ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@am__append_118 = src/pcm/dsd2pcm/dsd2pcm +@ENABLE_ALSA_TRUE@@ENABLE_TEST_TRUE@am__append_120 = test/read_mixer +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@ENABLE_UPNP_TRUE@am__append_121 = src/lib/expat/ExpatParser.cxx +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@ENABLE_WEBDAV_TRUE@am__append_122 = $(CURL_SOURCES) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@@ENABLE_UPNP_TRUE@am__append_123 = src/lib/expat/ExpatParser.cxx +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@am__append_124 = test/run_gzip test/run_gunzip +@ENABLE_FLAC_TRUE@@ENABLE_TEST_TRUE@am__append_125 = \ +@ENABLE_FLAC_TRUE@@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx \ +@ENABLE_FLAC_TRUE@@ENABLE_TEST_TRUE@ src/decoder/plugins/FlacMetadata.cxx + +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@am__append_126 = test/run_encoder +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@am__append_127 = test/test_vorbis_encoder +@ENABLE_BZIP2_TEST_TRUE@@ENABLE_TEST_TRUE@am__append_128 = test/test_archive_bzip2.sh +@ENABLE_TEST_TRUE@@ENABLE_ZZIP_TEST_TRUE@am__append_129 = test/test_archive_zzip.sh +@ENABLE_ISO9660_TEST_TRUE@@ENABLE_TEST_TRUE@am__append_130 = test/test_archive_iso9660.sh +@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@am__append_131 = test/run_inotify +@ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@am__append_132 = src/pcm/dsd2pcm/dsd2pcm subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_compile_flags.m4 \ @@ -570,12 +629,14 @@ $(top_srcdir)/m4/ax_boost_base.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \ - $(top_srcdir)/m4/ax_cxx_compile_stdcxx_0x.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_14.m4 \ $(top_srcdir)/m4/ax_pthread.m4 \ $(top_srcdir)/m4/ax_require_defined.m4 \ - $(top_srcdir)/m4/faad.m4 $(top_srcdir)/m4/libwrap.m4 \ - $(top_srcdir)/m4/mpd_auto.m4 $(top_srcdir)/m4/mpd_depends.m4 \ - $(top_srcdir)/m4/mpd_func.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/libwrap.m4 $(top_srcdir)/m4/mpd_auto.m4 \ + $(top_srcdir)/m4/mpd_define_conditional.m4 \ + $(top_srcdir)/m4/mpd_depends.m4 $(top_srcdir)/m4/mpd_func.m4 \ + $(top_srcdir)/m4/mpd_with_flags.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/pretty_print.m4 $(top_srcdir)/m4/ucred.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -586,7 +647,7 @@ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = src/win32/mpd_win32_rc.rc doc/doxygen.conf \ +CONFIG_CLEAN_FILES = win32/res/mpd.rc doc/doxygen.conf \ systemd/system/mpd.service systemd/user/mpd.service CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) @@ -621,9 +682,9 @@ src/archive/plugins/ZzipArchivePlugin.hxx \ src/archive/plugins/Iso9660ArchivePlugin.cxx \ src/archive/plugins/Iso9660ArchivePlugin.hxx -@ENABLE_ARCHIVE_TRUE@@HAVE_BZ2_TRUE@am__objects_1 = src/archive/plugins/libarchive_a-Bzip2ArchivePlugin.$(OBJEXT) -@ENABLE_ARCHIVE_TRUE@@HAVE_ZZIP_TRUE@am__objects_2 = src/archive/plugins/libarchive_a-ZzipArchivePlugin.$(OBJEXT) -@ENABLE_ARCHIVE_TRUE@@HAVE_ISO9660_TRUE@am__objects_3 = src/archive/plugins/libarchive_a-Iso9660ArchivePlugin.$(OBJEXT) +@ENABLE_ARCHIVE_TRUE@@ENABLE_BZ2_TRUE@am__objects_1 = src/archive/plugins/libarchive_a-Bzip2ArchivePlugin.$(OBJEXT) +@ENABLE_ARCHIVE_TRUE@@ENABLE_ZZIP_TRUE@am__objects_2 = src/archive/plugins/libarchive_a-ZzipArchivePlugin.$(OBJEXT) +@ENABLE_ARCHIVE_TRUE@@ENABLE_ISO9660_TRUE@am__objects_3 = src/archive/plugins/libarchive_a-Iso9660ArchivePlugin.$(OBJEXT) @ENABLE_ARCHIVE_TRUE@am_libarchive_a_OBJECTS = src/archive/libarchive_a-ArchiveDomain.$(OBJEXT) \ @ENABLE_ARCHIVE_TRUE@ src/archive/libarchive_a-ArchiveLookup.$(OBJEXT) \ @ENABLE_ARCHIVE_TRUE@ src/archive/libarchive_a-ArchiveList.$(OBJEXT) \ @@ -632,11 +693,16 @@ @ENABLE_ARCHIVE_TRUE@ $(am__objects_1) $(am__objects_2) \ @ENABLE_ARCHIVE_TRUE@ $(am__objects_3) libarchive_a_OBJECTS = $(am_libarchive_a_OBJECTS) +libbasic_a_AR = $(AR) $(ARFLAGS) +libbasic_a_LIBADD = +am_libbasic_a_OBJECTS = src/ReplayGainMode.$(OBJEXT) \ + src/ReplayGainInfo.$(OBJEXT) +libbasic_a_OBJECTS = $(am_libbasic_a_OBJECTS) libconf_a_AR = $(AR) $(ARFLAGS) libconf_a_LIBADD = am_libconf_a_OBJECTS = src/config/ConfigPath.$(OBJEXT) \ - src/config/ConfigData.$(OBJEXT) \ - src/config/ConfigParser.$(OBJEXT) \ + src/config/Data.$(OBJEXT) src/config/Block.$(OBJEXT) \ + src/config/Param.$(OBJEXT) src/config/ConfigParser.$(OBJEXT) \ src/config/ConfigGlobal.$(OBJEXT) \ src/config/ConfigFile.$(OBJEXT) \ src/config/ConfigTemplates.$(OBJEXT) \ @@ -652,8 +718,6 @@ src/db/plugins/simple/DatabaseSave.hxx \ src/db/plugins/simple/DirectorySave.cxx \ src/db/plugins/simple/DirectorySave.hxx \ - src/db/plugins/LazyDatabase.cxx \ - src/db/plugins/LazyDatabase.hxx \ src/db/plugins/simple/Directory.cxx \ src/db/plugins/simple/Directory.hxx \ src/db/plugins/simple/Song.cxx src/db/plugins/simple/Song.hxx \ @@ -672,11 +736,10 @@ src/lib/upnp/ContentDirectoryService.cxx \ src/lib/upnp/ContentDirectoryService.hxx \ src/lib/upnp/Discovery.cxx src/lib/upnp/Discovery.hxx \ - src/lib/upnp/Domain.cxx src/lib/upnp/Domain.hxx \ src/lib/upnp/ixmlwrap.cxx src/lib/upnp/ixmlwrap.hxx \ src/lib/upnp/Callback.hxx src/lib/upnp/Util.cxx \ - src/lib/upnp/Util.hxx src/lib/upnp/WorkQueue.hxx \ - src/lib/upnp/Action.hxx \ + src/lib/upnp/Util.hxx src/lib/upnp/UniqueIxml.hxx \ + src/lib/upnp/WorkQueue.hxx src/lib/upnp/Action.hxx \ src/db/plugins/upnp/UpnpDatabasePlugin.cxx \ src/db/plugins/upnp/UpnpDatabasePlugin.hxx \ src/db/plugins/upnp/Tags.cxx src/db/plugins/upnp/Tags.hxx \ @@ -684,20 +747,20 @@ src/db/plugins/upnp/Directory.cxx \ src/db/plugins/upnp/Directory.hxx \ src/db/plugins/upnp/Object.cxx src/db/plugins/upnp/Object.hxx -@ENABLE_DATABASE_TRUE@@HAVE_LIBMPDCLIENT_TRUE@am__objects_4 = src/db/plugins/ProxyDatabasePlugin.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_LIBMPDCLIENT_TRUE@am__objects_4 = src/db/plugins/ProxyDatabasePlugin.$(OBJEXT) am__objects_5 = src/lib/upnp/Init.$(OBJEXT) \ src/lib/upnp/ClientInit.$(OBJEXT) \ src/lib/upnp/Device.$(OBJEXT) \ src/lib/upnp/ContentDirectoryService.$(OBJEXT) \ - src/lib/upnp/Discovery.$(OBJEXT) src/lib/upnp/Domain.$(OBJEXT) \ + src/lib/upnp/Discovery.$(OBJEXT) \ src/lib/upnp/ixmlwrap.$(OBJEXT) src/lib/upnp/Util.$(OBJEXT) -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@am__objects_6 = \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ $(am__objects_5) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/UpnpDatabasePlugin.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Tags.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/ContentDirectoryService.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Directory.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ src/db/plugins/upnp/Object.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@am__objects_6 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(am__objects_5) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/UpnpDatabasePlugin.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Tags.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/ContentDirectoryService.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Directory.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ src/db/plugins/upnp/Object.$(OBJEXT) @ENABLE_DATABASE_TRUE@am_libdb_plugins_a_OBJECTS = \ @ENABLE_DATABASE_TRUE@ src/PlaylistDatabase.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/Registry.$(OBJEXT) \ @@ -705,7 +768,6 @@ @ENABLE_DATABASE_TRUE@ src/db/UniqueTags.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/DatabaseSave.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/DirectorySave.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@ src/db/plugins/LazyDatabase.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/Directory.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/Song.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/SongSort.$(OBJEXT) \ @@ -718,6 +780,8 @@ am__libdecoder_a_SOURCES_DIST = \ src/decoder/plugins/PcmDecoderPlugin.cxx \ src/decoder/plugins/PcmDecoderPlugin.hxx \ + src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx \ + src/decoder/Reader.cxx src/decoder/Reader.hxx \ src/decoder/DecoderBuffer.cxx src/decoder/DecoderBuffer.hxx \ src/decoder/DecoderPlugin.cxx src/decoder/DecoderList.cxx \ src/decoder/DecoderList.hxx \ @@ -732,11 +796,6 @@ src/decoder/plugins/Mpg123DecoderPlugin.hxx \ src/decoder/plugins/MpcdecDecoderPlugin.cxx \ src/decoder/plugins/MpcdecDecoderPlugin.hxx \ - src/decoder/plugins/OggUtil.cxx \ - src/decoder/plugins/OggUtil.hxx \ - src/decoder/plugins/OggSyncState.hxx \ - src/decoder/plugins/OggFind.cxx \ - src/decoder/plugins/OggFind.hxx \ src/decoder/plugins/OpusDomain.cxx \ src/decoder/plugins/OpusDomain.hxx \ src/decoder/plugins/OpusReader.hxx \ @@ -752,14 +811,12 @@ src/decoder/plugins/AdPlugDecoderPlugin.h \ src/decoder/plugins/FaadDecoderPlugin.cxx \ src/decoder/plugins/FaadDecoderPlugin.hxx \ - src/decoder/plugins/XiphTags.cxx \ - src/decoder/plugins/XiphTags.hxx \ + src/decoder/plugins/OggDecoder.cxx \ + src/decoder/plugins/OggDecoder.hxx \ src/decoder/plugins/OggCodec.cxx \ src/decoder/plugins/OggCodec.hxx \ src/decoder/plugins/VorbisDomain.cxx \ src/decoder/plugins/VorbisDomain.hxx \ - src/decoder/plugins/VorbisComments.cxx \ - src/decoder/plugins/VorbisComments.hxx \ src/decoder/plugins/VorbisDecoderPlugin.cxx \ src/decoder/plugins/VorbisDecoderPlugin.h \ src/decoder/plugins/FlacInput.cxx \ @@ -774,6 +831,7 @@ src/decoder/plugins/FlacDomain.hxx \ src/decoder/plugins/FlacCommon.cxx \ src/decoder/plugins/FlacCommon.hxx \ + src/decoder/plugins/FlacStreamDecoder.hxx \ src/decoder/plugins/FlacDecoderPlugin.cxx \ src/decoder/plugins/FlacDecoderPlugin.h \ src/decoder/plugins/AudiofileDecoderPlugin.cxx \ @@ -799,42 +857,41 @@ @ENABLE_DSD_TRUE@am__objects_7 = src/decoder/plugins/libdecoder_a-DsdiffDecoderPlugin.$(OBJEXT) \ @ENABLE_DSD_TRUE@ src/decoder/plugins/libdecoder_a-DsfDecoderPlugin.$(OBJEXT) \ @ENABLE_DSD_TRUE@ src/decoder/plugins/libdecoder_a-DsdLib.$(OBJEXT) -@HAVE_MAD_TRUE@am__objects_8 = src/decoder/plugins/libdecoder_a-MadDecoderPlugin.$(OBJEXT) -@HAVE_MPG123_TRUE@am__objects_9 = src/decoder/plugins/libdecoder_a-Mpg123DecoderPlugin.$(OBJEXT) -@HAVE_MPCDEC_TRUE@am__objects_10 = src/decoder/plugins/libdecoder_a-MpcdecDecoderPlugin.$(OBJEXT) -@HAVE_OPUS_TRUE@am__objects_11 = src/decoder/plugins/libdecoder_a-OggUtil.$(OBJEXT) \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OggFind.$(OBJEXT) \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusDomain.$(OBJEXT) \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusHead.$(OBJEXT) \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusTags.$(OBJEXT) \ -@HAVE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusDecoderPlugin.$(OBJEXT) -@HAVE_WAVPACK_TRUE@am__objects_12 = src/decoder/plugins/libdecoder_a-WavpackDecoderPlugin.$(OBJEXT) -@HAVE_ADPLUG_TRUE@am__objects_13 = src/decoder/plugins/libdecoder_a-AdPlugDecoderPlugin.$(OBJEXT) -@HAVE_FAAD_TRUE@am__objects_14 = src/decoder/plugins/libdecoder_a-FaadDecoderPlugin.$(OBJEXT) -@HAVE_XIPH_TRUE@am__objects_15 = src/decoder/plugins/libdecoder_a-XiphTags.$(OBJEXT) \ -@HAVE_XIPH_TRUE@ src/decoder/plugins/libdecoder_a-OggCodec.$(OBJEXT) -@ENABLE_VORBIS_DECODER_TRUE@am__objects_16 = src/decoder/plugins/libdecoder_a-VorbisDomain.$(OBJEXT) \ -@ENABLE_VORBIS_DECODER_TRUE@ src/decoder/plugins/libdecoder_a-VorbisComments.$(OBJEXT) \ +@ENABLE_MAD_TRUE@am__objects_8 = src/decoder/plugins/libdecoder_a-MadDecoderPlugin.$(OBJEXT) +@ENABLE_MPG123_TRUE@am__objects_9 = src/decoder/plugins/libdecoder_a-Mpg123DecoderPlugin.$(OBJEXT) +@ENABLE_MPCDEC_TRUE@am__objects_10 = src/decoder/plugins/libdecoder_a-MpcdecDecoderPlugin.$(OBJEXT) +@ENABLE_OPUS_TRUE@am__objects_11 = src/decoder/plugins/libdecoder_a-OpusDomain.$(OBJEXT) \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusHead.$(OBJEXT) \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusTags.$(OBJEXT) \ +@ENABLE_OPUS_TRUE@ src/decoder/plugins/libdecoder_a-OpusDecoderPlugin.$(OBJEXT) +@ENABLE_WAVPACK_TRUE@am__objects_12 = src/decoder/plugins/libdecoder_a-WavpackDecoderPlugin.$(OBJEXT) +@ENABLE_ADPLUG_TRUE@am__objects_13 = src/decoder/plugins/libdecoder_a-AdPlugDecoderPlugin.$(OBJEXT) +@ENABLE_FAAD_TRUE@am__objects_14 = src/decoder/plugins/libdecoder_a-FaadDecoderPlugin.$(OBJEXT) +@HAVE_OGG_TRUE@am__objects_15 = src/decoder/plugins/libdecoder_a-OggDecoder.$(OBJEXT) +@HAVE_XIPH_TRUE@am__objects_16 = src/decoder/plugins/libdecoder_a-OggCodec.$(OBJEXT) +@ENABLE_VORBIS_DECODER_TRUE@am__objects_17 = src/decoder/plugins/libdecoder_a-VorbisDomain.$(OBJEXT) \ @ENABLE_VORBIS_DECODER_TRUE@ src/decoder/plugins/libdecoder_a-VorbisDecoderPlugin.$(OBJEXT) -@HAVE_FLAC_TRUE@am__objects_17 = src/decoder/plugins/libdecoder_a-FlacInput.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacIOHandle.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacMetadata.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacPcm.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacDomain.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacCommon.$(OBJEXT) \ -@HAVE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacDecoderPlugin.$(OBJEXT) -@HAVE_AUDIOFILE_TRUE@am__objects_18 = src/decoder/plugins/libdecoder_a-AudiofileDecoderPlugin.$(OBJEXT) -@ENABLE_MIKMOD_DECODER_TRUE@am__objects_19 = src/decoder/plugins/libdecoder_a-MikmodDecoderPlugin.$(OBJEXT) -@ENABLE_SIDPLAY_TRUE@am__objects_20 = src/decoder/plugins/libdecoder_a-SidplayDecoderPlugin.$(OBJEXT) -@ENABLE_FLUIDSYNTH_TRUE@am__objects_21 = src/decoder/plugins/libdecoder_a-FluidsynthDecoderPlugin.$(OBJEXT) -@ENABLE_WILDMIDI_TRUE@am__objects_22 = src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.$(OBJEXT) -@HAVE_FFMPEG_TRUE@am__objects_23 = src/decoder/plugins/libdecoder_a-FfmpegIo.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegMetaData.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegDecoderPlugin.$(OBJEXT) -@ENABLE_SNDFILE_TRUE@am__objects_24 = src/decoder/plugins/libdecoder_a-SndfileDecoderPlugin.$(OBJEXT) -@HAVE_GME_TRUE@am__objects_25 = src/decoder/plugins/libdecoder_a-GmeDecoderPlugin.$(OBJEXT) +@ENABLE_FLAC_TRUE@am__objects_18 = src/decoder/plugins/libdecoder_a-FlacInput.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacIOHandle.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacMetadata.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacPcm.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacDomain.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacCommon.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@ src/decoder/plugins/libdecoder_a-FlacDecoderPlugin.$(OBJEXT) +@ENABLE_AUDIOFILE_TRUE@am__objects_19 = src/decoder/plugins/libdecoder_a-AudiofileDecoderPlugin.$(OBJEXT) +@ENABLE_MIKMOD_DECODER_TRUE@am__objects_20 = src/decoder/plugins/libdecoder_a-MikmodDecoderPlugin.$(OBJEXT) +@ENABLE_SIDPLAY_TRUE@am__objects_21 = src/decoder/plugins/libdecoder_a-SidplayDecoderPlugin.$(OBJEXT) +@ENABLE_FLUIDSYNTH_TRUE@am__objects_22 = src/decoder/plugins/libdecoder_a-FluidsynthDecoderPlugin.$(OBJEXT) +@ENABLE_WILDMIDI_TRUE@am__objects_23 = src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.$(OBJEXT) +@ENABLE_FFMPEG_TRUE@am__objects_24 = src/decoder/plugins/libdecoder_a-FfmpegIo.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegMetaData.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegDecoderPlugin.$(OBJEXT) +@ENABLE_SNDFILE_TRUE@am__objects_25 = src/decoder/plugins/libdecoder_a-SndfileDecoderPlugin.$(OBJEXT) +@ENABLE_GME_TRUE@am__objects_26 = src/decoder/plugins/libdecoder_a-GmeDecoderPlugin.$(OBJEXT) am_libdecoder_a_OBJECTS = \ src/decoder/plugins/libdecoder_a-PcmDecoderPlugin.$(OBJEXT) \ + src/decoder/libdecoder_a-DecoderAPI.$(OBJEXT) \ + src/decoder/libdecoder_a-Reader.$(OBJEXT) \ src/decoder/libdecoder_a-DecoderBuffer.$(OBJEXT) \ src/decoder/libdecoder_a-DecoderPlugin.$(OBJEXT) \ src/decoder/libdecoder_a-DecoderList.$(OBJEXT) \ @@ -844,20 +901,19 @@ $(am__objects_16) $(am__objects_17) $(am__objects_18) \ $(am__objects_19) $(am__objects_20) $(am__objects_21) \ $(am__objects_22) $(am__objects_23) $(am__objects_24) \ - $(am__objects_25) + $(am__objects_25) $(am__objects_26) libdecoder_a_OBJECTS = $(am_libdecoder_a_OBJECTS) libencoder_plugins_a_AR = $(AR) $(ARFLAGS) libencoder_plugins_a_LIBADD = am__libencoder_plugins_a_SOURCES_DIST = src/encoder/EncoderAPI.hxx \ - src/encoder/EncoderPlugin.hxx \ - src/encoder/plugins/OggStream.hxx \ + src/encoder/EncoderInterface.hxx src/encoder/EncoderPlugin.hxx \ + src/encoder/ToOutputStream.cxx src/encoder/ToOutputStream.hxx \ src/encoder/plugins/NullEncoderPlugin.cxx \ src/encoder/plugins/NullEncoderPlugin.hxx \ src/encoder/EncoderList.cxx src/encoder/EncoderList.hxx \ - src/encoder/plugins/OggSerial.cxx \ - src/encoder/plugins/OggSerial.hxx \ src/encoder/plugins/WaveEncoderPlugin.cxx \ src/encoder/plugins/WaveEncoderPlugin.hxx \ + src/encoder/plugins/OggEncoder.hxx \ src/encoder/plugins/VorbisEncoderPlugin.cxx \ src/encoder/plugins/VorbisEncoderPlugin.hxx \ src/encoder/plugins/OpusEncoderPlugin.cxx \ @@ -870,20 +926,21 @@ src/encoder/plugins/FlacEncoderPlugin.hxx \ src/encoder/plugins/ShineEncoderPlugin.cxx \ src/encoder/plugins/ShineEncoderPlugin.hxx -@ENABLE_ENCODER_TRUE@@HAVE_OGG_ENCODER_TRUE@am__objects_26 = src/encoder/plugins/libencoder_plugins_a-OggSerial.$(OBJEXT) @ENABLE_ENCODER_TRUE@@ENABLE_WAVE_ENCODER_TRUE@am__objects_27 = src/encoder/plugins/libencoder_plugins_a-WaveEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@am__objects_28 = src/encoder/plugins/libencoder_plugins_a-VorbisEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@HAVE_OPUS_TRUE@am__objects_29 = src/encoder/plugins/libencoder_plugins_a-OpusEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@ENABLE_LAME_ENCODER_TRUE@am__objects_30 = src/encoder/plugins/libencoder_plugins_a-LameEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_ENCODER_TRUE@am__objects_31 = src/encoder/plugins/libencoder_plugins_a-TwolameEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@am__objects_32 = src/encoder/plugins/libencoder_plugins_a-FlacEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_ENCODER_TRUE@am__objects_33 = src/encoder/plugins/libencoder_plugins_a-ShineEncoderPlugin.$(OBJEXT) -@ENABLE_ENCODER_TRUE@am_libencoder_plugins_a_OBJECTS = src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.$(OBJEXT) \ +am__objects_28 = +@ENABLE_ENCODER_TRUE@@ENABLE_VORBISENC_TRUE@am__objects_29 = src/encoder/plugins/libencoder_plugins_a-VorbisEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_OPUS_TRUE@am__objects_30 = src/encoder/plugins/libencoder_plugins_a-OpusEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_LAME_TRUE@am__objects_31 = src/encoder/plugins/libencoder_plugins_a-LameEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_TWOLAME_TRUE@am__objects_32 = src/encoder/plugins/libencoder_plugins_a-TwolameEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_FLAC_ENCODER_TRUE@am__objects_33 = src/encoder/plugins/libencoder_plugins_a-FlacEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_SHINE_TRUE@am__objects_34 = src/encoder/plugins/libencoder_plugins_a-ShineEncoderPlugin.$(OBJEXT) +@ENABLE_ENCODER_TRUE@am_libencoder_plugins_a_OBJECTS = src/encoder/libencoder_plugins_a-ToOutputStream.$(OBJEXT) \ +@ENABLE_ENCODER_TRUE@ src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.$(OBJEXT) \ @ENABLE_ENCODER_TRUE@ src/encoder/libencoder_plugins_a-EncoderList.$(OBJEXT) \ -@ENABLE_ENCODER_TRUE@ $(am__objects_26) $(am__objects_27) \ -@ENABLE_ENCODER_TRUE@ $(am__objects_28) $(am__objects_29) \ -@ENABLE_ENCODER_TRUE@ $(am__objects_30) $(am__objects_31) \ -@ENABLE_ENCODER_TRUE@ $(am__objects_32) $(am__objects_33) +@ENABLE_ENCODER_TRUE@ $(am__objects_27) $(am__objects_28) \ +@ENABLE_ENCODER_TRUE@ $(am__objects_29) $(am__objects_30) \ +@ENABLE_ENCODER_TRUE@ $(am__objects_31) $(am__objects_32) \ +@ENABLE_ENCODER_TRUE@ $(am__objects_33) $(am__objects_34) libencoder_plugins_a_OBJECTS = $(am_libencoder_plugins_a_OBJECTS) libevent_a_AR = $(AR) $(ARFLAGS) libevent_a_LIBADD = @@ -893,6 +950,7 @@ src/event/TimeoutMonitor.$(OBJEXT) \ src/event/IdleMonitor.$(OBJEXT) \ src/event/DeferredMonitor.$(OBJEXT) \ + src/event/MaskMonitor.$(OBJEXT) \ src/event/SocketMonitor.$(OBJEXT) \ src/event/BufferedSocket.$(OBJEXT) \ src/event/FullyBufferedSocket.$(OBJEXT) \ @@ -909,12 +967,12 @@ src/lib/ffmpeg/LogCallback.hxx src/lib/ffmpeg/Error.cxx \ src/lib/ffmpeg/Error.hxx src/lib/ffmpeg/Domain.cxx \ src/lib/ffmpeg/Domain.hxx -@HAVE_FFMPEG_TRUE@am_libffmpeg_a_OBJECTS = \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Init.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-LogError.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-LogCallback.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Error.$(OBJEXT) \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Domain.$(OBJEXT) +@ENABLE_FFMPEG_TRUE@am_libffmpeg_a_OBJECTS = \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Init.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-LogError.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-LogCallback.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Error.$(OBJEXT) \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Domain.$(OBJEXT) libffmpeg_a_OBJECTS = $(am_libffmpeg_a_OBJECTS) libfilter_plugins_a_AR = $(AR) $(ARFLAGS) libfilter_plugins_a_LIBADD = @@ -943,19 +1001,21 @@ src/fs/Traits.hxx src/fs/Config.cxx src/fs/Config.hxx \ src/fs/Charset.cxx src/fs/Charset.hxx src/fs/Path.cxx \ src/fs/Path2.cxx src/fs/Path.hxx src/fs/AllocatedPath.cxx \ - src/fs/AllocatedPath.hxx src/fs/FileSystem.cxx \ - src/fs/FileSystem.hxx src/fs/StandardDirectory.cxx \ - src/fs/StandardDirectory.hxx src/fs/CheckFile.cxx \ - src/fs/CheckFile.hxx src/fs/DirectoryReader.hxx \ - src/lib/zlib/Domain.cxx src/lib/zlib/Domain.hxx \ + src/fs/AllocatedPath.hxx src/fs/NarrowPath.hxx \ + src/fs/FileSystem.cxx src/fs/FileSystem.hxx \ + src/fs/FileInfo.hxx src/fs/Glob.hxx \ + src/fs/StandardDirectory.cxx src/fs/StandardDirectory.hxx \ + src/fs/CheckFile.cxx src/fs/CheckFile.hxx \ + src/fs/DirectoryReader.cxx src/fs/DirectoryReader.hxx \ + src/lib/zlib/Error.cxx src/lib/zlib/Error.hxx \ src/fs/io/GunzipReader.cxx src/fs/io/GunzipReader.hxx \ src/fs/io/AutoGunzipReader.cxx src/fs/io/AutoGunzipReader.hxx \ src/fs/io/GzipOutputStream.cxx src/fs/io/GzipOutputStream.hxx -@HAVE_ZLIB_TRUE@am__objects_34 = \ -@HAVE_ZLIB_TRUE@ src/lib/zlib/libfs_a-Domain.$(OBJEXT) \ -@HAVE_ZLIB_TRUE@ src/fs/io/libfs_a-GunzipReader.$(OBJEXT) \ -@HAVE_ZLIB_TRUE@ src/fs/io/libfs_a-AutoGunzipReader.$(OBJEXT) \ -@HAVE_ZLIB_TRUE@ src/fs/io/libfs_a-GzipOutputStream.$(OBJEXT) +@ENABLE_ZLIB_TRUE@am__objects_35 = \ +@ENABLE_ZLIB_TRUE@ src/lib/zlib/libfs_a-Error.$(OBJEXT) \ +@ENABLE_ZLIB_TRUE@ src/fs/io/libfs_a-GunzipReader.$(OBJEXT) \ +@ENABLE_ZLIB_TRUE@ src/fs/io/libfs_a-AutoGunzipReader.$(OBJEXT) \ +@ENABLE_ZLIB_TRUE@ src/fs/io/libfs_a-GzipOutputStream.$(OBJEXT) am_libfs_a_OBJECTS = src/fs/io/libfs_a-PeekReader.$(OBJEXT) \ src/fs/io/libfs_a-FileReader.$(OBJEXT) \ src/fs/io/libfs_a-BufferedReader.$(OBJEXT) \ @@ -970,17 +1030,23 @@ src/fs/libfs_a-AllocatedPath.$(OBJEXT) \ src/fs/libfs_a-FileSystem.$(OBJEXT) \ src/fs/libfs_a-StandardDirectory.$(OBJEXT) \ - src/fs/libfs_a-CheckFile.$(OBJEXT) $(am__objects_34) + src/fs/libfs_a-CheckFile.$(OBJEXT) \ + src/fs/libfs_a-DirectoryReader.$(OBJEXT) $(am__objects_35) libfs_a_OBJECTS = $(am_libfs_a_OBJECTS) libicu_a_AR = $(AR) $(ARFLAGS) libicu_a_LIBADD = am__libicu_a_SOURCES_DIST = src/lib/icu/Collate.cxx \ - src/lib/icu/Collate.hxx src/lib/icu/Error.cxx \ - src/lib/icu/Error.hxx src/lib/icu/Init.cxx \ - src/lib/icu/Init.hxx -@HAVE_ICU_TRUE@am__objects_35 = src/lib/icu/libicu_a-Init.$(OBJEXT) + src/lib/icu/Collate.hxx src/lib/icu/Converter.cxx \ + src/lib/icu/Converter.hxx src/lib/icu/Util.cxx \ + src/lib/icu/Util.hxx src/lib/icu/Init.cxx src/lib/icu/Init.hxx \ + src/lib/icu/Win32.cxx src/lib/icu/Win32.hxx +@HAVE_ICU_TRUE@am__objects_36 = src/lib/icu/libicu_a-Util.$(OBJEXT) \ +@HAVE_ICU_TRUE@ src/lib/icu/libicu_a-Init.$(OBJEXT) +@HAVE_WINDOWS_TRUE@am__objects_37 = \ +@HAVE_WINDOWS_TRUE@ src/lib/icu/libicu_a-Win32.$(OBJEXT) am_libicu_a_OBJECTS = src/lib/icu/libicu_a-Collate.$(OBJEXT) \ - src/lib/icu/libicu_a-Error.$(OBJEXT) $(am__objects_35) + src/lib/icu/libicu_a-Converter.$(OBJEXT) $(am__objects_36) \ + $(am__objects_37) libicu_a_OBJECTS = $(am_libicu_a_OBJECTS) libinput_a_AR = $(AR) $(ARFLAGS) libinput_a_LIBADD = @@ -990,8 +1056,10 @@ src/input/Open.cxx src/input/LocalOpen.cxx \ src/input/LocalOpen.hxx src/input/Offset.hxx \ src/input/InputStream.cxx src/input/InputStream.hxx \ - src/input/InputPlugin.hxx src/input/TextInputStream.cxx \ - src/input/TextInputStream.hxx src/input/ThreadInputStream.cxx \ + src/input/Ptr.hxx src/input/InputPlugin.hxx \ + src/input/Reader.cxx src/input/Reader.hxx \ + src/input/TextInputStream.cxx src/input/TextInputStream.hxx \ + src/input/ThreadInputStream.cxx \ src/input/ThreadInputStream.hxx src/input/AsyncInputStream.cxx \ src/input/AsyncInputStream.hxx src/input/ProxyInputStream.cxx \ src/input/ProxyInputStream.hxx \ @@ -1003,11 +1071,16 @@ src/input/plugins/AlsaInputPlugin.hxx \ src/input/IcyInputStream.cxx src/input/IcyInputStream.hxx \ src/input/plugins/CurlInputPlugin.cxx \ - src/input/plugins/CurlInputPlugin.hxx \ - src/IcyMetaDataParser.cxx src/IcyMetaDataParser.hxx \ - src/lib/smbclient/Domain.cxx src/lib/smbclient/Domain.hxx \ - src/lib/smbclient/Mutex.cxx src/lib/smbclient/Mutex.hxx \ - src/lib/smbclient/Init.cxx src/lib/smbclient/Init.hxx \ + src/input/plugins/CurlInputPlugin.hxx src/lib/curl/Version.cxx \ + src/lib/curl/Version.hxx src/lib/curl/Global.cxx \ + src/lib/curl/Global.hxx src/lib/curl/Request.cxx \ + src/lib/curl/Request.hxx src/lib/curl/Handler.hxx \ + src/lib/curl/Easy.hxx src/lib/curl/Multi.hxx \ + src/lib/curl/Slist.hxx src/IcyMetaDataParser.cxx \ + src/IcyMetaDataParser.hxx src/lib/smbclient/Domain.cxx \ + src/lib/smbclient/Domain.hxx src/lib/smbclient/Mutex.cxx \ + src/lib/smbclient/Mutex.hxx src/lib/smbclient/Init.cxx \ + src/lib/smbclient/Init.hxx \ src/input/plugins/SmbclientInputPlugin.cxx \ src/input/plugins/SmbclientInputPlugin.hxx \ src/lib/nfs/Callback.hxx src/lib/nfs/Cancellable.hxx \ @@ -1017,7 +1090,6 @@ src/lib/nfs/Glue.hxx src/lib/nfs/Base.cxx src/lib/nfs/Base.hxx \ src/lib/nfs/FileReader.cxx src/lib/nfs/FileReader.hxx \ src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx \ - src/lib/nfs/Domain.cxx src/lib/nfs/Domain.hxx \ src/input/plugins/NfsInputPlugin.cxx \ src/input/plugins/NfsInputPlugin.hxx \ src/input/plugins/CdioParanoiaInputPlugin.cxx \ @@ -1026,42 +1098,46 @@ src/input/plugins/FfmpegInputPlugin.hxx \ src/input/plugins/MmsInputPlugin.cxx \ src/input/plugins/MmsInputPlugin.hxx -@HAVE_ALSA_TRUE@am__objects_36 = src/input/plugins/libinput_a-AlsaInputPlugin.$(OBJEXT) -@ENABLE_CURL_TRUE@am__objects_37 = src/input/libinput_a-IcyInputStream.$(OBJEXT) \ +@ENABLE_ALSA_TRUE@am__objects_38 = src/input/plugins/libinput_a-AlsaInputPlugin.$(OBJEXT) +am__objects_39 = src/lib/curl/libinput_a-Version.$(OBJEXT) \ + src/lib/curl/libinput_a-Global.$(OBJEXT) \ + src/lib/curl/libinput_a-Request.$(OBJEXT) +@ENABLE_CURL_TRUE@am__objects_40 = src/input/libinput_a-IcyInputStream.$(OBJEXT) \ @ENABLE_CURL_TRUE@ src/input/plugins/libinput_a-CurlInputPlugin.$(OBJEXT) \ +@ENABLE_CURL_TRUE@ $(am__objects_39) \ @ENABLE_CURL_TRUE@ src/libinput_a-IcyMetaDataParser.$(OBJEXT) -am__objects_38 = src/lib/smbclient/libinput_a-Domain.$(OBJEXT) \ +am__objects_41 = src/lib/smbclient/libinput_a-Domain.$(OBJEXT) \ src/lib/smbclient/libinput_a-Mutex.$(OBJEXT) \ src/lib/smbclient/libinput_a-Init.$(OBJEXT) -@ENABLE_SMBCLIENT_TRUE@am__objects_39 = $(am__objects_38) \ +@ENABLE_SMBCLIENT_TRUE@am__objects_42 = $(am__objects_41) \ @ENABLE_SMBCLIENT_TRUE@ src/input/plugins/libinput_a-SmbclientInputPlugin.$(OBJEXT) -am__objects_40 = src/lib/nfs/libinput_a-Connection.$(OBJEXT) \ +am__objects_43 = src/lib/nfs/libinput_a-Connection.$(OBJEXT) \ src/lib/nfs/libinput_a-Manager.$(OBJEXT) \ src/lib/nfs/libinput_a-Glue.$(OBJEXT) \ src/lib/nfs/libinput_a-Base.$(OBJEXT) \ src/lib/nfs/libinput_a-FileReader.$(OBJEXT) \ - src/lib/nfs/libinput_a-Blocking.$(OBJEXT) \ - src/lib/nfs/libinput_a-Domain.$(OBJEXT) -@ENABLE_NFS_TRUE@am__objects_41 = $(am__objects_40) \ + src/lib/nfs/libinput_a-Blocking.$(OBJEXT) +@ENABLE_NFS_TRUE@am__objects_44 = $(am__objects_43) \ @ENABLE_NFS_TRUE@ src/input/plugins/libinput_a-NfsInputPlugin.$(OBJEXT) -@ENABLE_CDIO_PARANOIA_TRUE@am__objects_42 = src/input/plugins/libinput_a-CdioParanoiaInputPlugin.$(OBJEXT) -@HAVE_FFMPEG_TRUE@am__objects_43 = src/input/plugins/libinput_a-FfmpegInputPlugin.$(OBJEXT) -@ENABLE_MMS_TRUE@am__objects_44 = src/input/plugins/libinput_a-MmsInputPlugin.$(OBJEXT) +@ENABLE_CDIO_PARANOIA_TRUE@am__objects_45 = src/input/plugins/libinput_a-CdioParanoiaInputPlugin.$(OBJEXT) +@ENABLE_FFMPEG_TRUE@am__objects_46 = src/input/plugins/libinput_a-FfmpegInputPlugin.$(OBJEXT) +@ENABLE_MMS_TRUE@am__objects_47 = src/input/plugins/libinput_a-MmsInputPlugin.$(OBJEXT) am_libinput_a_OBJECTS = src/input/libinput_a-Domain.$(OBJEXT) \ src/input/libinput_a-Init.$(OBJEXT) \ src/input/libinput_a-Registry.$(OBJEXT) \ src/input/libinput_a-Open.$(OBJEXT) \ src/input/libinput_a-LocalOpen.$(OBJEXT) \ src/input/libinput_a-InputStream.$(OBJEXT) \ + src/input/libinput_a-Reader.$(OBJEXT) \ src/input/libinput_a-TextInputStream.$(OBJEXT) \ src/input/libinput_a-ThreadInputStream.$(OBJEXT) \ src/input/libinput_a-AsyncInputStream.$(OBJEXT) \ src/input/libinput_a-ProxyInputStream.$(OBJEXT) \ src/input/plugins/libinput_a-RewindInputPlugin.$(OBJEXT) \ src/input/plugins/libinput_a-FileInputPlugin.$(OBJEXT) \ - $(am__objects_36) $(am__objects_37) $(am__objects_39) \ - $(am__objects_41) $(am__objects_42) $(am__objects_43) \ - $(am__objects_44) + $(am__objects_38) $(am__objects_40) $(am__objects_42) \ + $(am__objects_44) $(am__objects_45) $(am__objects_46) \ + $(am__objects_47) libinput_a_OBJECTS = $(am_libinput_a_OBJECTS) libjava_a_AR = $(AR) $(ARFLAGS) libjava_a_LIBADD = @@ -1081,37 +1157,48 @@ libmixer_plugins_a_AR = $(AR) $(ARFLAGS) libmixer_plugins_a_LIBADD = am__libmixer_plugins_a_SOURCES_DIST = \ + src/mixer/plugins/NullMixerPlugin.cxx \ src/mixer/plugins/SoftwareMixerPlugin.cxx \ src/mixer/plugins/SoftwareMixerPlugin.hxx \ + src/mixer/plugins/volume_mapping.h \ + src/mixer/plugins/volume_mapping.c \ src/mixer/plugins/AlsaMixerPlugin.cxx \ src/mixer/plugins/RoarMixerPlugin.cxx \ + src/mixer/plugins/HaikuMixerPlugin.cxx \ src/mixer/plugins/OssMixerPlugin.cxx \ src/mixer/plugins/PulseMixerPlugin.cxx \ src/mixer/plugins/PulseMixerPlugin.hxx \ src/mixer/plugins/WinmmMixerPlugin.cxx -@HAVE_ALSA_TRUE@am__objects_45 = src/mixer/plugins/libmixer_plugins_a-AlsaMixerPlugin.$(OBJEXT) -@HAVE_ROAR_TRUE@am__objects_46 = src/mixer/plugins/libmixer_plugins_a-RoarMixerPlugin.$(OBJEXT) -@HAVE_OSS_TRUE@am__objects_47 = src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.$(OBJEXT) -@HAVE_PULSE_TRUE@am__objects_48 = src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.$(OBJEXT) -@ENABLE_WINMM_OUTPUT_TRUE@am__objects_49 = src/mixer/plugins/libmixer_plugins_a-WinmmMixerPlugin.$(OBJEXT) -am_libmixer_plugins_a_OBJECTS = src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.$(OBJEXT) \ - $(am__objects_45) $(am__objects_46) $(am__objects_47) \ - $(am__objects_48) $(am__objects_49) +@ENABLE_ALSA_TRUE@am__objects_48 = src/mixer/plugins/libmixer_plugins_a-volume_mapping.$(OBJEXT) \ +@ENABLE_ALSA_TRUE@ src/mixer/plugins/libmixer_plugins_a-AlsaMixerPlugin.$(OBJEXT) +@ENABLE_ROAR_TRUE@am__objects_49 = src/mixer/plugins/libmixer_plugins_a-RoarMixerPlugin.$(OBJEXT) +@ENABLE_HAIKU_TRUE@am__objects_50 = src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.$(OBJEXT) +@HAVE_OSS_TRUE@am__objects_51 = src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.$(OBJEXT) +@ENABLE_PULSE_TRUE@am__objects_52 = src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.$(OBJEXT) +@ENABLE_WINMM_OUTPUT_TRUE@am__objects_53 = src/mixer/plugins/libmixer_plugins_a-WinmmMixerPlugin.$(OBJEXT) +am_libmixer_plugins_a_OBJECTS = src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.$(OBJEXT) \ + src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.$(OBJEXT) \ + $(am__objects_48) $(am__objects_49) $(am__objects_50) \ + $(am__objects_51) $(am__objects_52) $(am__objects_53) libmixer_plugins_a_OBJECTS = $(am_libmixer_plugins_a_OBJECTS) libmodplug_decoder_plugin_a_AR = $(AR) $(ARFLAGS) libmodplug_decoder_plugin_a_LIBADD = am__libmodplug_decoder_plugin_a_SOURCES_DIST = \ src/decoder/plugins/ModplugDecoderPlugin.cxx \ src/decoder/plugins/ModplugDecoderPlugin.hxx -@HAVE_MODPLUG_TRUE@am_libmodplug_decoder_plugin_a_OBJECTS = src/decoder/plugins/libmodplug_decoder_plugin_a-ModplugDecoderPlugin.$(OBJEXT) +@ENABLE_MODPLUG_TRUE@am_libmodplug_decoder_plugin_a_OBJECTS = src/decoder/plugins/libmodplug_decoder_plugin_a-ModplugDecoderPlugin.$(OBJEXT) libmodplug_decoder_plugin_a_OBJECTS = \ $(am_libmodplug_decoder_plugin_a_OBJECTS) libmpd_a_AR = $(AR) $(ARFLAGS) libmpd_a_LIBADD = -am__libmpd_a_SOURCES_DIST = src/output/OutputAPI.hxx \ - src/output/Internal.hxx src/output/Registry.cxx \ - src/output/Registry.hxx src/output/MultipleOutputs.cxx \ - src/output/MultipleOutputs.hxx src/output/OutputThread.cxx \ +am__libmpd_a_SOURCES_DIST = src/output/Client.hxx \ + src/output/OutputAPI.hxx src/output/Internal.cxx \ + src/output/Internal.hxx src/output/Wrapper.hxx \ + src/output/Registry.cxx src/output/Registry.hxx \ + src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ + src/output/SharedPipeConsumer.cxx \ + src/output/SharedPipeConsumer.hxx src/output/Source.cxx \ + src/output/Source.hxx src/output/OutputThread.cxx \ src/output/Domain.cxx src/output/Domain.hxx \ src/output/OutputControl.cxx src/output/OutputState.cxx \ src/output/OutputState.hxx src/output/OutputPrint.cxx \ @@ -1124,18 +1211,15 @@ src/mixer/MixerType.cxx src/mixer/MixerType.hxx \ src/mixer/MixerAll.cxx src/mixer/MixerInternal.hxx src/check.h \ src/Compiler.h src/open.h src/poison.h src/notify.cxx \ - src/notify.hxx src/AudioConfig.cxx src/AudioConfig.hxx \ - src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ - src/AudioFormat.cxx src/AudioFormat.hxx src/AudioParser.cxx \ - src/AudioParser.hxx src/protocol/Ack.cxx src/protocol/Ack.hxx \ + src/notify.hxx src/protocol/Ack.cxx src/protocol/Ack.hxx \ src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \ src/protocol/Result.cxx src/protocol/Result.hxx \ - src/command/CommandResult.hxx src/command/CommandError.cxx \ - src/command/CommandError.hxx src/command/AllCommands.cxx \ - src/command/AllCommands.hxx src/command/QueueCommands.cxx \ - src/command/QueueCommands.hxx src/command/TagCommands.cxx \ - src/command/TagCommands.hxx src/command/PlayerCommands.cxx \ - src/command/PlayerCommands.hxx \ + src/command/Request.hxx src/command/CommandResult.hxx \ + src/command/CommandError.cxx src/command/CommandError.hxx \ + src/command/AllCommands.cxx src/command/AllCommands.hxx \ + src/command/QueueCommands.cxx src/command/QueueCommands.hxx \ + src/command/TagCommands.cxx src/command/TagCommands.hxx \ + src/command/PlayerCommands.cxx src/command/PlayerCommands.hxx \ src/command/PlaylistCommands.cxx \ src/command/PlaylistCommands.hxx src/command/FileCommands.cxx \ src/command/FileCommands.hxx src/command/OutputCommands.cxx \ @@ -1144,18 +1228,18 @@ src/command/OtherCommands.hxx \ src/command/CommandListBuilder.cxx \ src/command/CommandListBuilder.hxx src/Idle.cxx src/Idle.hxx \ - src/CrossFade.cxx src/CrossFade.hxx \ + src/IdleFlags.cxx src/IdleFlags.hxx \ src/decoder/DecoderError.cxx src/decoder/DecoderError.hxx \ src/decoder/DecoderThread.cxx src/decoder/DecoderThread.hxx \ src/decoder/DecoderCommand.hxx src/decoder/DecoderControl.cxx \ - src/decoder/DecoderControl.hxx src/decoder/DecoderAPI.cxx \ - src/decoder/DecoderAPI.hxx src/decoder/DecoderPlugin.hxx \ - src/decoder/DecoderInternal.cxx \ - src/decoder/DecoderInternal.hxx src/decoder/DecoderPrint.cxx \ + src/decoder/DecoderControl.hxx src/decoder/Client.hxx \ + src/decoder/DecoderPlugin.hxx src/decoder/Bridge.cxx \ + src/decoder/Bridge.hxx src/decoder/DecoderPrint.cxx \ src/decoder/DecoderPrint.hxx src/filter/FilterConfig.cxx \ src/filter/FilterConfig.hxx src/filter/FilterPlugin.cxx \ src/filter/FilterPlugin.hxx src/filter/FilterInternal.hxx \ src/filter/FilterRegistry.cxx src/filter/FilterRegistry.hxx \ + src/filter/Observer.cxx src/filter/Observer.hxx \ src/client/Client.cxx src/client/Client.hxx \ src/client/ClientInternal.hxx src/client/ClientEvent.cxx \ src/client/ClientExpire.cxx src/client/ClientGlobal.cxx \ @@ -1164,24 +1248,24 @@ src/client/ClientProcess.cxx src/client/ClientRead.cxx \ src/client/ClientWrite.cxx src/client/ClientMessage.cxx \ src/client/ClientMessage.hxx src/client/ClientSubscribe.cxx \ - src/client/ClientFile.cxx src/Listen.cxx src/Listen.hxx \ + src/client/ClientFile.cxx src/client/Response.cxx \ + src/client/Response.hxx src/Listen.cxx src/Listen.hxx \ src/LogInit.cxx src/LogInit.hxx src/LogBackend.cxx \ src/LogBackend.hxx src/Log.cxx src/Log.hxx src/LogV.hxx \ src/LogLevel.hxx src/ls.cxx src/ls.hxx src/IOThread.cxx \ src/IOThread.hxx src/Instance.cxx src/Instance.hxx \ - src/win32/Win32Main.cxx src/GlobalEvents.cxx \ - src/GlobalEvents.hxx src/MixRampInfo.hxx src/MusicBuffer.cxx \ - src/MusicBuffer.hxx src/MusicPipe.cxx src/MusicPipe.hxx \ - src/MusicChunk.cxx src/MusicChunk.hxx src/Mapper.cxx \ - src/Mapper.hxx src/Partition.cxx src/Partition.hxx \ - src/Permission.cxx src/Permission.hxx src/PlayerThread.cxx \ - src/PlayerThread.hxx src/PlayerControl.cxx \ - src/PlayerControl.hxx src/PlayerListener.hxx \ - src/PlaylistError.cxx src/PlaylistError.hxx \ - src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \ - src/PlaylistPrint.cxx src/PlaylistPrint.hxx \ - src/PlaylistSave.cxx src/PlaylistSave.hxx \ - src/playlist/PlaylistStream.cxx \ + src/win32/Win32Main.cxx src/MixRampInfo.hxx \ + src/MusicBuffer.cxx src/MusicBuffer.hxx src/MusicPipe.cxx \ + src/MusicPipe.hxx src/MusicChunk.cxx src/MusicChunk.hxx \ + src/Mapper.cxx src/Mapper.hxx src/Partition.cxx \ + src/Partition.hxx src/Permission.cxx src/Permission.hxx \ + src/player/CrossFade.cxx src/player/CrossFade.hxx \ + src/player/Thread.cxx src/player/Thread.hxx \ + src/player/Control.cxx src/player/Control.hxx \ + src/player/Listener.hxx src/PlaylistError.cxx \ + src/PlaylistError.hxx src/PlaylistPrint.cxx \ + src/PlaylistPrint.hxx src/PlaylistSave.cxx \ + src/PlaylistSave.hxx src/playlist/PlaylistStream.cxx \ src/playlist/PlaylistStream.hxx \ src/playlist/PlaylistMapper.cxx \ src/playlist/PlaylistMapper.hxx src/playlist/PlaylistAny.cxx \ @@ -1197,23 +1281,23 @@ src/queue/Playlist.cxx src/queue/Playlist.hxx \ src/queue/PlaylistControl.cxx src/queue/PlaylistEdit.cxx \ src/queue/PlaylistTag.cxx src/queue/PlaylistState.cxx \ - src/queue/PlaylistState.hxx src/ReplayGainConfig.cxx \ - src/ReplayGainConfig.hxx src/ReplayGainInfo.cxx \ - src/ReplayGainInfo.hxx src/DetachedSong.cxx \ - src/DetachedSong.hxx src/SongUpdate.cxx src/SongLoader.cxx \ - src/SongLoader.hxx src/SongPrint.cxx src/SongPrint.hxx \ - src/SongSave.cxx src/SongSave.hxx src/StateFile.cxx \ - src/StateFile.hxx src/Stats.cxx src/Stats.hxx src/TagPrint.cxx \ - src/TagPrint.hxx src/TagSave.cxx src/TagSave.hxx \ - src/TagFile.cxx src/TagFile.hxx src/TagStream.cxx \ - src/TagStream.hxx src/TimePrint.cxx src/TimePrint.hxx \ - src/mixer/Volume.cxx src/mixer/Volume.hxx src/Chrono.hxx \ - src/SongFilter.cxx src/SongFilter.hxx src/PlaylistFile.cxx \ - src/PlaylistFile.hxx src/unix/SignalHandlers.cxx \ - src/unix/SignalHandlers.hxx src/unix/Daemon.cxx \ - src/unix/Daemon.hxx src/unix/PidFile.hxx src/CommandLine.cxx \ - src/CommandLine.hxx src/queue/PlaylistUpdate.cxx \ - src/command/StorageCommands.cxx \ + src/queue/PlaylistState.hxx src/queue/Listener.hxx \ + src/PluginUnavailable.hxx src/ReplayGainGlobal.cxx \ + src/ReplayGainGlobal.hxx src/DetachedSong.cxx \ + src/DetachedSong.hxx src/LocateUri.cxx src/LocateUri.hxx \ + src/SongUpdate.cxx src/SongLoader.cxx src/SongLoader.hxx \ + src/SongPrint.cxx src/SongPrint.hxx src/SongSave.cxx \ + src/SongSave.hxx src/StateFile.cxx src/StateFile.hxx \ + src/Stats.cxx src/Stats.hxx src/TagPrint.cxx src/TagPrint.hxx \ + src/TagSave.cxx src/TagSave.hxx src/TagFile.cxx \ + src/TagFile.hxx src/TagStream.cxx src/TagStream.hxx \ + src/TimePrint.cxx src/TimePrint.hxx src/mixer/Volume.cxx \ + src/mixer/Volume.hxx src/Chrono.hxx src/SongFilter.cxx \ + src/SongFilter.hxx src/PlaylistFile.cxx src/PlaylistFile.hxx \ + src/unix/SignalHandlers.cxx src/unix/SignalHandlers.hxx \ + src/CommandLine.cxx src/CommandLine.hxx src/unix/Daemon.cxx \ + src/unix/Daemon.hxx src/unix/PidFile.hxx \ + src/queue/PlaylistUpdate.cxx src/command/StorageCommands.cxx \ src/command/StorageCommands.hxx \ src/command/DatabaseCommands.cxx \ src/command/DatabaseCommands.hxx src/db/Count.cxx \ @@ -1234,11 +1318,11 @@ src/db/DatabasePrint.cxx src/db/DatabasePrint.hxx \ src/db/DatabaseQueue.cxx src/db/DatabaseQueue.hxx \ src/db/DatabasePlaylist.cxx src/db/DatabasePlaylist.hxx \ - src/db/DatabaseError.cxx src/db/DatabaseError.hxx \ - src/db/DatabaseLock.cxx src/db/DatabaseLock.hxx \ - src/db/DatabasePlugin.hxx src/db/Interface.hxx \ - src/db/Stats.hxx src/db/DatabaseListener.hxx \ - src/db/Visitor.hxx src/db/Selection.cxx src/db/Selection.hxx \ + src/db/DatabaseError.hxx src/db/DatabaseLock.cxx \ + src/db/DatabaseLock.hxx src/db/DatabasePlugin.hxx \ + src/db/Interface.hxx src/db/Stats.hxx \ + src/db/DatabaseListener.hxx src/db/Visitor.hxx \ + src/db/Selection.cxx src/db/Selection.hxx \ src/db/update/InotifyDomain.cxx \ src/db/update/InotifyDomain.hxx \ src/db/update/InotifySource.cxx \ @@ -1246,20 +1330,25 @@ src/db/update/InotifyQueue.hxx src/db/update/InotifyUpdate.cxx \ src/db/update/InotifyUpdate.hxx \ src/command/StickerCommands.cxx \ - src/command/StickerCommands.hxx \ - src/sticker/StickerDatabase.cxx \ + src/command/StickerCommands.hxx src/lib/sqlite/Error.cxx \ + src/lib/sqlite/Error.hxx src/lib/sqlite/Util.hxx \ + src/sticker/Match.hxx src/sticker/StickerDatabase.cxx \ src/sticker/StickerDatabase.hxx src/sticker/StickerPrint.cxx \ src/sticker/StickerPrint.hxx src/sticker/SongSticker.cxx \ src/sticker/SongSticker.hxx src/command/NeighborCommands.cxx \ - src/command/NeighborCommands.hxx src/db/update/Archive.cxx \ + src/command/NeighborCommands.hxx src/TagArchive.cxx \ + src/TagArchive.hxx src/db/update/Archive.cxx \ src/zeroconf/ZeroconfInternal.hxx \ src/zeroconf/ZeroconfGlue.cxx src/zeroconf/ZeroconfGlue.hxx \ src/zeroconf/AvahiPoll.cxx src/zeroconf/AvahiPoll.hxx \ src/zeroconf/ZeroconfAvahi.cxx src/zeroconf/ZeroconfAvahi.hxx \ src/zeroconf/ZeroconfBonjour.cxx \ src/zeroconf/ZeroconfBonjour.hxx -am__objects_50 = src/output/libmpd_a-Registry.$(OBJEXT) \ +am__objects_54 = src/output/libmpd_a-Internal.$(OBJEXT) \ + src/output/libmpd_a-Registry.$(OBJEXT) \ src/output/libmpd_a-MultipleOutputs.$(OBJEXT) \ + src/output/libmpd_a-SharedPipeConsumer.$(OBJEXT) \ + src/output/libmpd_a-Source.$(OBJEXT) \ src/output/libmpd_a-OutputThread.$(OBJEXT) \ src/output/libmpd_a-Domain.$(OBJEXT) \ src/output/libmpd_a-OutputControl.$(OBJEXT) \ @@ -1269,14 +1358,14 @@ src/output/libmpd_a-OutputPlugin.$(OBJEXT) \ src/output/libmpd_a-Finish.$(OBJEXT) \ src/output/libmpd_a-Init.$(OBJEXT) -am__objects_51 = src/mixer/libmpd_a-MixerControl.$(OBJEXT) \ +am__objects_55 = src/mixer/libmpd_a-MixerControl.$(OBJEXT) \ src/mixer/libmpd_a-MixerType.$(OBJEXT) \ src/mixer/libmpd_a-MixerAll.$(OBJEXT) -@ANDROID_FALSE@am__objects_52 = \ +@ANDROID_FALSE@am__objects_56 = \ @ANDROID_FALSE@ src/unix/libmpd_a-SignalHandlers.$(OBJEXT) \ -@ANDROID_FALSE@ src/unix/libmpd_a-Daemon.$(OBJEXT) \ @ANDROID_FALSE@ src/libmpd_a-CommandLine.$(OBJEXT) -@ENABLE_DATABASE_TRUE@am__objects_53 = src/queue/libmpd_a-PlaylistUpdate.$(OBJEXT) \ +@ANDROID_FALSE@@ENABLE_DAEMON_TRUE@am__objects_57 = src/unix/libmpd_a-Daemon.$(OBJEXT) +@ENABLE_DATABASE_TRUE@am__objects_58 = src/queue/libmpd_a-PlaylistUpdate.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/command/libmpd_a-StorageCommands.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/command/libmpd_a-DatabaseCommands.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-Count.$(OBJEXT) \ @@ -1297,30 +1386,27 @@ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-DatabasePrint.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-DatabaseQueue.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-DatabasePlaylist.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@ src/db/libmpd_a-DatabaseError.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-DatabaseLock.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/db/libmpd_a-Selection.$(OBJEXT) -@ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@am__objects_54 = src/db/update/libmpd_a-InotifyDomain.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@am__objects_59 = src/db/update/libmpd_a-InotifyDomain.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/libmpd_a-InotifySource.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/libmpd_a-InotifyQueue.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_INOTIFY_TRUE@ src/db/update/libmpd_a-InotifyUpdate.$(OBJEXT) -@ENABLE_SQLITE_TRUE@am__objects_55 = src/command/libmpd_a-StickerCommands.$(OBJEXT) \ +@ENABLE_SQLITE_TRUE@am__objects_60 = src/command/libmpd_a-StickerCommands.$(OBJEXT) \ +@ENABLE_SQLITE_TRUE@ src/lib/sqlite/libmpd_a-Error.$(OBJEXT) \ @ENABLE_SQLITE_TRUE@ src/sticker/libmpd_a-StickerDatabase.$(OBJEXT) \ @ENABLE_SQLITE_TRUE@ src/sticker/libmpd_a-StickerPrint.$(OBJEXT) \ @ENABLE_SQLITE_TRUE@ src/sticker/libmpd_a-SongSticker.$(OBJEXT) -@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__objects_56 = src/command/libmpd_a-NeighborCommands.$(OBJEXT) -@ENABLE_ARCHIVE_TRUE@am__objects_57 = \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@am__objects_61 = src/command/libmpd_a-NeighborCommands.$(OBJEXT) +@ENABLE_ARCHIVE_TRUE@am__objects_62 = \ +@ENABLE_ARCHIVE_TRUE@ src/libmpd_a-TagArchive.$(OBJEXT) \ @ENABLE_ARCHIVE_TRUE@ src/db/update/libmpd_a-Archive.$(OBJEXT) -@HAVE_ZEROCONF_TRUE@am__objects_58 = src/zeroconf/libmpd_a-ZeroconfGlue.$(OBJEXT) -@HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@am__objects_59 = src/zeroconf/libmpd_a-AvahiPoll.$(OBJEXT) \ +@HAVE_ZEROCONF_TRUE@am__objects_63 = src/zeroconf/libmpd_a-ZeroconfGlue.$(OBJEXT) +@HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@am__objects_64 = src/zeroconf/libmpd_a-AvahiPoll.$(OBJEXT) \ @HAVE_AVAHI_TRUE@@HAVE_ZEROCONF_TRUE@ src/zeroconf/libmpd_a-ZeroconfAvahi.$(OBJEXT) -@HAVE_BONJOUR_TRUE@@HAVE_ZEROCONF_TRUE@am__objects_60 = src/zeroconf/libmpd_a-ZeroconfBonjour.$(OBJEXT) -am_libmpd_a_OBJECTS = $(am__objects_50) $(am__objects_51) \ +@HAVE_BONJOUR_TRUE@@HAVE_ZEROCONF_TRUE@am__objects_65 = src/zeroconf/libmpd_a-ZeroconfBonjour.$(OBJEXT) +am_libmpd_a_OBJECTS = $(am__objects_54) $(am__objects_55) \ src/libmpd_a-notify.$(OBJEXT) \ - src/libmpd_a-AudioConfig.$(OBJEXT) \ - src/libmpd_a-CheckAudioFormat.$(OBJEXT) \ - src/libmpd_a-AudioFormat.$(OBJEXT) \ - src/libmpd_a-AudioParser.$(OBJEXT) \ src/protocol/libmpd_a-Ack.$(OBJEXT) \ src/protocol/libmpd_a-ArgParser.$(OBJEXT) \ src/protocol/libmpd_a-Result.$(OBJEXT) \ @@ -1335,16 +1421,16 @@ src/command/libmpd_a-MessageCommands.$(OBJEXT) \ src/command/libmpd_a-OtherCommands.$(OBJEXT) \ src/command/libmpd_a-CommandListBuilder.$(OBJEXT) \ - src/libmpd_a-Idle.$(OBJEXT) src/libmpd_a-CrossFade.$(OBJEXT) \ + src/libmpd_a-Idle.$(OBJEXT) src/libmpd_a-IdleFlags.$(OBJEXT) \ src/decoder/libmpd_a-DecoderError.$(OBJEXT) \ src/decoder/libmpd_a-DecoderThread.$(OBJEXT) \ src/decoder/libmpd_a-DecoderControl.$(OBJEXT) \ - src/decoder/libmpd_a-DecoderAPI.$(OBJEXT) \ - src/decoder/libmpd_a-DecoderInternal.$(OBJEXT) \ + src/decoder/libmpd_a-Bridge.$(OBJEXT) \ src/decoder/libmpd_a-DecoderPrint.$(OBJEXT) \ src/filter/libmpd_a-FilterConfig.$(OBJEXT) \ src/filter/libmpd_a-FilterPlugin.$(OBJEXT) \ src/filter/libmpd_a-FilterRegistry.$(OBJEXT) \ + src/filter/libmpd_a-Observer.$(OBJEXT) \ src/client/libmpd_a-Client.$(OBJEXT) \ src/client/libmpd_a-ClientEvent.$(OBJEXT) \ src/client/libmpd_a-ClientExpire.$(OBJEXT) \ @@ -1358,21 +1444,21 @@ src/client/libmpd_a-ClientMessage.$(OBJEXT) \ src/client/libmpd_a-ClientSubscribe.$(OBJEXT) \ src/client/libmpd_a-ClientFile.$(OBJEXT) \ + src/client/libmpd_a-Response.$(OBJEXT) \ src/libmpd_a-Listen.$(OBJEXT) src/libmpd_a-LogInit.$(OBJEXT) \ src/libmpd_a-LogBackend.$(OBJEXT) src/libmpd_a-Log.$(OBJEXT) \ src/libmpd_a-ls.$(OBJEXT) src/libmpd_a-IOThread.$(OBJEXT) \ src/libmpd_a-Instance.$(OBJEXT) \ src/win32/libmpd_a-Win32Main.$(OBJEXT) \ - src/libmpd_a-GlobalEvents.$(OBJEXT) \ src/libmpd_a-MusicBuffer.$(OBJEXT) \ src/libmpd_a-MusicPipe.$(OBJEXT) \ src/libmpd_a-MusicChunk.$(OBJEXT) \ src/libmpd_a-Mapper.$(OBJEXT) src/libmpd_a-Partition.$(OBJEXT) \ src/libmpd_a-Permission.$(OBJEXT) \ - src/libmpd_a-PlayerThread.$(OBJEXT) \ - src/libmpd_a-PlayerControl.$(OBJEXT) \ + src/player/libmpd_a-CrossFade.$(OBJEXT) \ + src/player/libmpd_a-Thread.$(OBJEXT) \ + src/player/libmpd_a-Control.$(OBJEXT) \ src/libmpd_a-PlaylistError.$(OBJEXT) \ - src/libmpd_a-PlaylistGlobal.$(OBJEXT) \ src/libmpd_a-PlaylistPrint.$(OBJEXT) \ src/libmpd_a-PlaylistSave.$(OBJEXT) \ src/playlist/libmpd_a-PlaylistStream.$(OBJEXT) \ @@ -1390,9 +1476,9 @@ src/queue/libmpd_a-PlaylistEdit.$(OBJEXT) \ src/queue/libmpd_a-PlaylistTag.$(OBJEXT) \ src/queue/libmpd_a-PlaylistState.$(OBJEXT) \ - src/libmpd_a-ReplayGainConfig.$(OBJEXT) \ - src/libmpd_a-ReplayGainInfo.$(OBJEXT) \ + src/libmpd_a-ReplayGainGlobal.$(OBJEXT) \ src/libmpd_a-DetachedSong.$(OBJEXT) \ + src/libmpd_a-LocateUri.$(OBJEXT) \ src/libmpd_a-SongUpdate.$(OBJEXT) \ src/libmpd_a-SongLoader.$(OBJEXT) \ src/libmpd_a-SongPrint.$(OBJEXT) \ @@ -1404,10 +1490,10 @@ src/libmpd_a-TimePrint.$(OBJEXT) \ src/mixer/libmpd_a-Volume.$(OBJEXT) \ src/libmpd_a-SongFilter.$(OBJEXT) \ - src/libmpd_a-PlaylistFile.$(OBJEXT) $(am__objects_52) \ - $(am__objects_53) $(am__objects_54) $(am__objects_55) \ - $(am__objects_56) $(am__objects_57) $(am__objects_58) \ - $(am__objects_59) $(am__objects_60) + src/libmpd_a-PlaylistFile.$(OBJEXT) $(am__objects_56) \ + $(am__objects_57) $(am__objects_58) $(am__objects_59) \ + $(am__objects_60) $(am__objects_61) $(am__objects_62) \ + $(am__objects_63) $(am__objects_64) $(am__objects_65) libmpd_a_OBJECTS = $(am_libmpd_a_OBJECTS) libneighbor_a_AR = $(AR) $(ARFLAGS) libneighbor_a_LIBADD = @@ -1427,33 +1513,40 @@ src/lib/upnp/ContentDirectoryService.cxx \ src/lib/upnp/ContentDirectoryService.hxx \ src/lib/upnp/Discovery.cxx src/lib/upnp/Discovery.hxx \ - src/lib/upnp/Domain.cxx src/lib/upnp/Domain.hxx \ src/lib/upnp/ixmlwrap.cxx src/lib/upnp/ixmlwrap.hxx \ src/lib/upnp/Callback.hxx src/lib/upnp/Util.cxx \ - src/lib/upnp/Util.hxx src/lib/upnp/WorkQueue.hxx \ - src/lib/upnp/Action.hxx \ + src/lib/upnp/Util.hxx src/lib/upnp/UniqueIxml.hxx \ + src/lib/upnp/WorkQueue.hxx src/lib/upnp/Action.hxx \ src/neighbor/plugins/UpnpNeighborPlugin.cxx \ src/neighbor/plugins/UpnpNeighborPlugin.hxx -am__objects_61 = src/lib/smbclient/libneighbor_a-Domain.$(OBJEXT) \ +am__objects_66 = src/lib/smbclient/libneighbor_a-Domain.$(OBJEXT) \ src/lib/smbclient/libneighbor_a-Mutex.$(OBJEXT) \ src/lib/smbclient/libneighbor_a-Init.$(OBJEXT) -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@am__objects_62 = $(am__objects_61) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@am__objects_67 = $(am__objects_66) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_SMBCLIENT_TRUE@ src/neighbor/plugins/libneighbor_a-SmbclientNeighborPlugin.$(OBJEXT) -am__objects_63 = src/lib/upnp/libneighbor_a-Init.$(OBJEXT) \ +am__objects_68 = src/lib/upnp/libneighbor_a-Init.$(OBJEXT) \ src/lib/upnp/libneighbor_a-ClientInit.$(OBJEXT) \ src/lib/upnp/libneighbor_a-Device.$(OBJEXT) \ src/lib/upnp/libneighbor_a-ContentDirectoryService.$(OBJEXT) \ src/lib/upnp/libneighbor_a-Discovery.$(OBJEXT) \ - src/lib/upnp/libneighbor_a-Domain.$(OBJEXT) \ src/lib/upnp/libneighbor_a-ixmlwrap.$(OBJEXT) \ src/lib/upnp/libneighbor_a-Util.$(OBJEXT) -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@am__objects_64 = $(am__objects_63) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ src/neighbor/plugins/libneighbor_a-UpnpNeighborPlugin.$(OBJEXT) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@am__objects_69 = $(am__objects_68) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ src/neighbor/plugins/libneighbor_a-UpnpNeighborPlugin.$(OBJEXT) @ENABLE_NEIGHBOR_PLUGINS_TRUE@am_libneighbor_a_OBJECTS = src/neighbor/libneighbor_a-Registry.$(OBJEXT) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/neighbor/libneighbor_a-Glue.$(OBJEXT) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__objects_62) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__objects_64) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__objects_67) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__objects_69) libneighbor_a_OBJECTS = $(am_libneighbor_a_OBJECTS) +libnet_a_AR = $(AR) $(ARFLAGS) +libnet_a_LIBADD = +am_libnet_a_OBJECTS = src/net/ToString.$(OBJEXT) \ + src/net/Resolver.$(OBJEXT) \ + src/net/StaticSocketAddress.$(OBJEXT) \ + src/net/AllocatedSocketAddress.$(OBJEXT) \ + src/net/SocketAddress.$(OBJEXT) src/net/SocketUtil.$(OBJEXT) \ + src/net/SocketError.$(OBJEXT) +libnet_a_OBJECTS = $(am_libnet_a_OBJECTS) liboutput_plugins_a_AR = $(AR) $(ARFLAGS) liboutput_plugins_a_LIBADD = am__liboutput_plugins_a_SOURCES_DIST = src/output/Timer.cxx \ @@ -1473,6 +1566,10 @@ src/output/plugins/AoOutputPlugin.hxx \ src/output/plugins/FifoOutputPlugin.cxx \ src/output/plugins/FifoOutputPlugin.hxx \ + src/output/plugins/SndioOutputPlugin.cxx \ + src/output/plugins/SndioOutputPlugin.hxx \ + src/output/plugins/HaikuOutputPlugin.cxx \ + src/output/plugins/HaikuOutputPlugin.hxx \ src/output/plugins/PipeOutputPlugin.cxx \ src/output/plugins/PipeOutputPlugin.hxx \ src/output/plugins/JackOutputPlugin.cxx \ @@ -1502,38 +1599,43 @@ src/output/plugins/SolarisOutputPlugin.hxx \ src/output/plugins/WinmmOutputPlugin.cxx \ src/output/plugins/WinmmOutputPlugin.hxx -@HAVE_ALSA_TRUE@am__objects_65 = src/output/plugins/liboutput_plugins_a-AlsaOutputPlugin.$(OBJEXT) -@ANDROID_TRUE@am__objects_66 = src/output/plugins/sles/liboutput_plugins_a-SlesOutputPlugin.$(OBJEXT) -@HAVE_ROAR_TRUE@am__objects_67 = src/output/plugins/liboutput_plugins_a-RoarOutputPlugin.$(OBJEXT) -@HAVE_AO_TRUE@am__objects_68 = src/output/plugins/liboutput_plugins_a-AoOutputPlugin.$(OBJEXT) -@HAVE_FIFO_TRUE@am__objects_69 = src/output/plugins/liboutput_plugins_a-FifoOutputPlugin.$(OBJEXT) -@ENABLE_PIPE_OUTPUT_TRUE@am__objects_70 = src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.$(OBJEXT) -@HAVE_JACK_TRUE@am__objects_71 = src/output/plugins/liboutput_plugins_a-JackOutputPlugin.$(OBJEXT) -@HAVE_OSS_TRUE@am__objects_72 = src/output/plugins/liboutput_plugins_a-OssOutputPlugin.$(OBJEXT) -@HAVE_OPENAL_TRUE@am__objects_73 = src/output/plugins/liboutput_plugins_a-OpenALOutputPlugin.$(OBJEXT) -@HAVE_OSX_TRUE@am__objects_74 = src/output/plugins/liboutput_plugins_a-OSXOutputPlugin.$(OBJEXT) -@HAVE_PULSE_TRUE@am__objects_75 = src/output/plugins/liboutput_plugins_a-PulseOutputPlugin.$(OBJEXT) -@HAVE_SHOUT_TRUE@am__objects_76 = src/output/plugins/liboutput_plugins_a-ShoutOutputPlugin.$(OBJEXT) -@ENABLE_RECORDER_OUTPUT_TRUE@am__objects_77 = src/output/plugins/liboutput_plugins_a-RecorderOutputPlugin.$(OBJEXT) -@ENABLE_HTTPD_OUTPUT_TRUE@am__objects_78 = src/output/plugins/httpd/liboutput_plugins_a-IcyMetaDataServer.$(OBJEXT) \ +@ENABLE_ALSA_TRUE@am__objects_70 = src/output/plugins/liboutput_plugins_a-AlsaOutputPlugin.$(OBJEXT) +@ANDROID_TRUE@am__objects_71 = src/output/plugins/sles/liboutput_plugins_a-SlesOutputPlugin.$(OBJEXT) +@ENABLE_ROAR_TRUE@am__objects_72 = src/output/plugins/liboutput_plugins_a-RoarOutputPlugin.$(OBJEXT) +@ENABLE_AO_TRUE@am__objects_73 = src/output/plugins/liboutput_plugins_a-AoOutputPlugin.$(OBJEXT) +@HAVE_FIFO_TRUE@am__objects_74 = src/output/plugins/liboutput_plugins_a-FifoOutputPlugin.$(OBJEXT) +@ENABLE_SNDIO_TRUE@am__objects_75 = src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.$(OBJEXT) +@ENABLE_HAIKU_TRUE@am__objects_76 = src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.$(OBJEXT) +@ENABLE_PIPE_OUTPUT_TRUE@am__objects_77 = src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.$(OBJEXT) +@ENABLE_JACK_TRUE@am__objects_78 = src/output/plugins/liboutput_plugins_a-JackOutputPlugin.$(OBJEXT) +@HAVE_OSS_TRUE@am__objects_79 = src/output/plugins/liboutput_plugins_a-OssOutputPlugin.$(OBJEXT) +@HAVE_OPENAL_TRUE@am__objects_80 = src/output/plugins/liboutput_plugins_a-OpenALOutputPlugin.$(OBJEXT) +@HAVE_OSX_TRUE@am__objects_81 = src/output/plugins/liboutput_plugins_a-OSXOutputPlugin.$(OBJEXT) +@ENABLE_PULSE_TRUE@am__objects_82 = src/output/plugins/liboutput_plugins_a-PulseOutputPlugin.$(OBJEXT) +@HAVE_SHOUT_TRUE@am__objects_83 = src/output/plugins/liboutput_plugins_a-ShoutOutputPlugin.$(OBJEXT) +@ENABLE_RECORDER_OUTPUT_TRUE@am__objects_84 = src/output/plugins/liboutput_plugins_a-RecorderOutputPlugin.$(OBJEXT) +@ENABLE_HTTPD_OUTPUT_TRUE@am__objects_85 = src/output/plugins/httpd/liboutput_plugins_a-IcyMetaDataServer.$(OBJEXT) \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/liboutput_plugins_a-Page.$(OBJEXT) \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/liboutput_plugins_a-HttpdClient.$(OBJEXT) \ @ENABLE_HTTPD_OUTPUT_TRUE@ src/output/plugins/httpd/liboutput_plugins_a-HttpdOutputPlugin.$(OBJEXT) -@ENABLE_SOLARIS_OUTPUT_TRUE@am__objects_79 = src/output/plugins/liboutput_plugins_a-SolarisOutputPlugin.$(OBJEXT) -@ENABLE_WINMM_OUTPUT_TRUE@am__objects_80 = src/output/plugins/liboutput_plugins_a-WinmmOutputPlugin.$(OBJEXT) +@ENABLE_SOLARIS_OUTPUT_TRUE@am__objects_86 = src/output/plugins/liboutput_plugins_a-SolarisOutputPlugin.$(OBJEXT) +@ENABLE_WINMM_OUTPUT_TRUE@am__objects_87 = src/output/plugins/liboutput_plugins_a-WinmmOutputPlugin.$(OBJEXT) am_liboutput_plugins_a_OBJECTS = \ src/output/liboutput_plugins_a-Timer.$(OBJEXT) \ src/output/plugins/liboutput_plugins_a-NullOutputPlugin.$(OBJEXT) \ - $(am__objects_65) $(am__objects_66) $(am__objects_67) \ - $(am__objects_68) $(am__objects_69) $(am__objects_70) \ - $(am__objects_71) $(am__objects_72) $(am__objects_73) \ - $(am__objects_74) $(am__objects_75) $(am__objects_76) \ - $(am__objects_77) $(am__objects_78) $(am__objects_79) \ - $(am__objects_80) + $(am__objects_70) $(am__objects_71) $(am__objects_72) \ + $(am__objects_73) $(am__objects_74) $(am__objects_75) \ + $(am__objects_76) $(am__objects_77) $(am__objects_78) \ + $(am__objects_79) $(am__objects_80) $(am__objects_81) \ + $(am__objects_82) $(am__objects_83) $(am__objects_84) \ + $(am__objects_85) $(am__objects_86) $(am__objects_87) liboutput_plugins_a_OBJECTS = $(am_liboutput_plugins_a_OBJECTS) libpcm_a_AR = $(AR) $(ARFLAGS) libpcm_a_LIBADD = -am__libpcm_a_SOURCES_DIST = src/pcm/Domain.cxx src/pcm/Domain.hxx \ +am__libpcm_a_SOURCES_DIST = src/CheckAudioFormat.cxx \ + src/CheckAudioFormat.hxx src/AudioFormat.cxx \ + src/AudioFormat.hxx src/AudioParser.cxx src/AudioParser.hxx \ + src/pcm/SampleFormat.cxx src/pcm/SampleFormat.hxx \ src/pcm/Traits.hxx src/pcm/Interleave.cxx \ src/pcm/Interleave.hxx src/pcm/PcmBuffer.cxx \ src/pcm/PcmBuffer.hxx src/pcm/PcmExport.cxx \ @@ -1547,22 +1649,29 @@ src/pcm/ShiftConvert.hxx src/pcm/Neon.hxx \ src/pcm/FormatConverter.cxx src/pcm/FormatConverter.hxx \ src/pcm/ChannelsConverter.cxx src/pcm/ChannelsConverter.hxx \ - src/pcm/Resampler.hxx src/pcm/GlueResampler.cxx \ - src/pcm/GlueResampler.hxx src/pcm/FallbackResampler.cxx \ - src/pcm/FallbackResampler.hxx src/pcm/ConfiguredResampler.cxx \ + src/pcm/Order.cxx src/pcm/Order.hxx src/pcm/Resampler.hxx \ + src/pcm/GlueResampler.cxx src/pcm/GlueResampler.hxx \ + src/pcm/FallbackResampler.cxx src/pcm/FallbackResampler.hxx \ + src/pcm/ConfiguredResampler.cxx \ src/pcm/ConfiguredResampler.hxx src/pcm/PcmDither.cxx \ src/pcm/PcmDither.hxx src/pcm/PcmPrng.hxx src/pcm/PcmUtils.hxx \ - src/pcm/PcmDsd.cxx src/pcm/PcmDsd.hxx \ + src/pcm/Dsd16.cxx src/pcm/Dsd16.hxx src/pcm/Dsd32.cxx \ + src/pcm/Dsd32.hxx src/pcm/PcmDsd.cxx src/pcm/PcmDsd.hxx \ src/pcm/dsd2pcm/dsd2pcm.c src/pcm/dsd2pcm/dsd2pcm.h \ src/pcm/LibsamplerateResampler.cxx \ src/pcm/LibsamplerateResampler.hxx src/pcm/SoxrResampler.cxx \ src/pcm/SoxrResampler.hxx -@ENABLE_DSD_TRUE@am__objects_81 = src/pcm/libpcm_a-PcmDsd.$(OBJEXT) \ +@ENABLE_DSD_TRUE@am__objects_88 = src/pcm/libpcm_a-Dsd16.$(OBJEXT) \ +@ENABLE_DSD_TRUE@ src/pcm/libpcm_a-Dsd32.$(OBJEXT) \ +@ENABLE_DSD_TRUE@ src/pcm/libpcm_a-PcmDsd.$(OBJEXT) \ @ENABLE_DSD_TRUE@ src/pcm/dsd2pcm/libpcm_a-dsd2pcm.$(OBJEXT) -@HAVE_LIBSAMPLERATE_TRUE@am__objects_82 = src/pcm/libpcm_a-LibsamplerateResampler.$(OBJEXT) -@HAVE_SOXR_TRUE@am__objects_83 = \ -@HAVE_SOXR_TRUE@ src/pcm/libpcm_a-SoxrResampler.$(OBJEXT) -am_libpcm_a_OBJECTS = src/pcm/libpcm_a-Domain.$(OBJEXT) \ +@ENABLE_LIBSAMPLERATE_TRUE@am__objects_89 = src/pcm/libpcm_a-LibsamplerateResampler.$(OBJEXT) +@ENABLE_SOXR_TRUE@am__objects_90 = \ +@ENABLE_SOXR_TRUE@ src/pcm/libpcm_a-SoxrResampler.$(OBJEXT) +am_libpcm_a_OBJECTS = src/libpcm_a-CheckAudioFormat.$(OBJEXT) \ + src/libpcm_a-AudioFormat.$(OBJEXT) \ + src/libpcm_a-AudioParser.$(OBJEXT) \ + src/pcm/libpcm_a-SampleFormat.$(OBJEXT) \ src/pcm/libpcm_a-Interleave.$(OBJEXT) \ src/pcm/libpcm_a-PcmBuffer.$(OBJEXT) \ src/pcm/libpcm_a-PcmExport.$(OBJEXT) \ @@ -1576,59 +1685,73 @@ src/pcm/libpcm_a-PcmFormat.$(OBJEXT) \ src/pcm/libpcm_a-FormatConverter.$(OBJEXT) \ src/pcm/libpcm_a-ChannelsConverter.$(OBJEXT) \ + src/pcm/libpcm_a-Order.$(OBJEXT) \ src/pcm/libpcm_a-GlueResampler.$(OBJEXT) \ src/pcm/libpcm_a-FallbackResampler.$(OBJEXT) \ src/pcm/libpcm_a-ConfiguredResampler.$(OBJEXT) \ - src/pcm/libpcm_a-PcmDither.$(OBJEXT) $(am__objects_81) \ - $(am__objects_82) $(am__objects_83) + src/pcm/libpcm_a-PcmDither.$(OBJEXT) $(am__objects_88) \ + $(am__objects_89) $(am__objects_90) libpcm_a_OBJECTS = $(am_libpcm_a_OBJECTS) libplaylist_plugins_a_AR = $(AR) $(ARFLAGS) libplaylist_plugins_a_LIBADD = am__libplaylist_plugins_a_SOURCES_DIST = \ src/playlist/PlaylistPlugin.hxx \ src/playlist/SongEnumerator.hxx \ - src/playlist/CloseSongEnumerator.cxx \ - src/playlist/CloseSongEnumerator.hxx \ src/playlist/MemorySongEnumerator.cxx \ src/playlist/MemorySongEnumerator.hxx \ - src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.cxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.hxx \ src/playlist/plugins/M3uPlaylistPlugin.cxx \ src/playlist/plugins/M3uPlaylistPlugin.hxx \ + src/playlist/plugins/PlsPlaylistPlugin.cxx \ + src/playlist/plugins/PlsPlaylistPlugin.hxx \ + src/playlist/PlaylistRegistry.cxx \ + src/playlist/PlaylistRegistry.hxx \ + src/playlist/plugins/FlacPlaylistPlugin.cxx \ + src/playlist/plugins/FlacPlaylistPlugin.hxx \ + src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ src/playlist/plugins/CuePlaylistPlugin.cxx \ src/playlist/plugins/CuePlaylistPlugin.hxx \ src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx \ src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx \ - src/playlist/PlaylistRegistry.cxx \ - src/playlist/PlaylistRegistry.hxx \ src/playlist/plugins/SoundCloudPlaylistPlugin.cxx \ src/playlist/plugins/SoundCloudPlaylistPlugin.hxx \ + src/lib/expat/StreamExpatParser.cxx \ src/lib/expat/ExpatParser.cxx src/lib/expat/ExpatParser.hxx \ src/playlist/plugins/XspfPlaylistPlugin.cxx \ src/playlist/plugins/XspfPlaylistPlugin.hxx \ src/playlist/plugins/AsxPlaylistPlugin.cxx \ src/playlist/plugins/AsxPlaylistPlugin.hxx \ src/playlist/plugins/RssPlaylistPlugin.cxx \ - src/playlist/plugins/RssPlaylistPlugin.hxx \ - src/playlist/plugins/PlsPlaylistPlugin.cxx \ - src/playlist/plugins/PlsPlaylistPlugin.hxx -@ENABLE_SOUNDCLOUD_TRUE@am__objects_84 = src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.$(OBJEXT) -@HAVE_EXPAT_TRUE@am__objects_85 = src/lib/expat/libplaylist_plugins_a-ExpatParser.$(OBJEXT) \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-XspfPlaylistPlugin.$(OBJEXT) \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-AsxPlaylistPlugin.$(OBJEXT) \ -@HAVE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-RssPlaylistPlugin.$(OBJEXT) -@HAVE_GLIB_TRUE@am__objects_86 = src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.$(OBJEXT) -am_libplaylist_plugins_a_OBJECTS = src/playlist/libplaylist_plugins_a-CloseSongEnumerator.$(OBJEXT) \ - src/playlist/libplaylist_plugins_a-MemorySongEnumerator.$(OBJEXT) \ - src/playlist/cue/libplaylist_plugins_a-CueParser.$(OBJEXT) \ + src/playlist/plugins/RssPlaylistPlugin.hxx +@ENABLE_FLAC_TRUE@am__objects_91 = src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.$(OBJEXT) +@ENABLE_CUE_TRUE@am__objects_92 = src/playlist/cue/libplaylist_plugins_a-CueParser.$(OBJEXT) \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.$(OBJEXT) \ +@ENABLE_CUE_TRUE@ src/playlist/plugins/libplaylist_plugins_a-EmbeddedCuePlaylistPlugin.$(OBJEXT) +@ENABLE_SOUNDCLOUD_TRUE@am__objects_93 = src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.$(OBJEXT) +@ENABLE_EXPAT_TRUE@am__objects_94 = src/lib/expat/libplaylist_plugins_a-StreamExpatParser.$(OBJEXT) \ +@ENABLE_EXPAT_TRUE@ src/lib/expat/libplaylist_plugins_a-ExpatParser.$(OBJEXT) \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-XspfPlaylistPlugin.$(OBJEXT) \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-AsxPlaylistPlugin.$(OBJEXT) \ +@ENABLE_EXPAT_TRUE@ src/playlist/plugins/libplaylist_plugins_a-RssPlaylistPlugin.$(OBJEXT) +am_libplaylist_plugins_a_OBJECTS = src/playlist/libplaylist_plugins_a-MemorySongEnumerator.$(OBJEXT) \ src/playlist/plugins/libplaylist_plugins_a-ExtM3uPlaylistPlugin.$(OBJEXT) \ src/playlist/plugins/libplaylist_plugins_a-M3uPlaylistPlugin.$(OBJEXT) \ - src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.$(OBJEXT) \ - src/playlist/plugins/libplaylist_plugins_a-EmbeddedCuePlaylistPlugin.$(OBJEXT) \ + src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.$(OBJEXT) \ src/playlist/libplaylist_plugins_a-PlaylistRegistry.$(OBJEXT) \ - $(am__objects_84) $(am__objects_85) $(am__objects_86) + $(am__objects_91) $(am__objects_92) $(am__objects_93) \ + $(am__objects_94) libplaylist_plugins_a_OBJECTS = $(am_libplaylist_plugins_a_OBJECTS) +libpulse_a_AR = $(AR) $(ARFLAGS) +libpulse_a_LIBADD = +am__libpulse_a_SOURCES_DIST = src/lib/pulse/LockGuard.hxx \ + src/lib/pulse/LogError.cxx src/lib/pulse/LogError.hxx \ + src/lib/pulse/Error.cxx src/lib/pulse/Error.hxx \ + src/lib/pulse/Domain.cxx src/lib/pulse/Domain.hxx +@ENABLE_PULSE_TRUE@am_libpulse_a_OBJECTS = src/lib/pulse/libpulse_a-LogError.$(OBJEXT) \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/libpulse_a-Error.$(OBJEXT) \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/libpulse_a-Domain.$(OBJEXT) +libpulse_a_OBJECTS = $(am_libpulse_a_OBJECTS) libstorage_a_AR = $(AR) $(ARFLAGS) libstorage_a_LIBADD = am__libstorage_a_SOURCES_DIST = src/storage/StoragePlugin.hxx \ @@ -1654,96 +1777,132 @@ src/lib/nfs/Glue.hxx src/lib/nfs/Base.cxx src/lib/nfs/Base.hxx \ src/lib/nfs/FileReader.cxx src/lib/nfs/FileReader.hxx \ src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx \ - src/lib/nfs/Domain.cxx src/lib/nfs/Domain.hxx \ src/storage/plugins/NfsStorage.cxx \ - src/storage/plugins/NfsStorage.hxx -am__objects_87 = src/lib/smbclient/libstorage_a-Domain.$(OBJEXT) \ + src/storage/plugins/NfsStorage.hxx \ + src/lib/expat/ExpatParser.cxx \ + src/storage/plugins/CurlStorage.cxx \ + src/storage/plugins/CurlStorage.hxx +am__objects_95 = src/lib/smbclient/libstorage_a-Domain.$(OBJEXT) \ src/lib/smbclient/libstorage_a-Mutex.$(OBJEXT) \ src/lib/smbclient/libstorage_a-Init.$(OBJEXT) -@ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@am__objects_88 = $(am__objects_87) \ +@ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@am__objects_96 = $(am__objects_95) \ @ENABLE_DATABASE_TRUE@@ENABLE_SMBCLIENT_TRUE@ src/storage/plugins/libstorage_a-SmbclientStorage.$(OBJEXT) -am__objects_89 = src/lib/nfs/libstorage_a-Connection.$(OBJEXT) \ +am__objects_97 = src/lib/nfs/libstorage_a-Connection.$(OBJEXT) \ src/lib/nfs/libstorage_a-Manager.$(OBJEXT) \ src/lib/nfs/libstorage_a-Glue.$(OBJEXT) \ src/lib/nfs/libstorage_a-Base.$(OBJEXT) \ src/lib/nfs/libstorage_a-FileReader.$(OBJEXT) \ - src/lib/nfs/libstorage_a-Blocking.$(OBJEXT) \ - src/lib/nfs/libstorage_a-Domain.$(OBJEXT) -@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@am__objects_90 = \ -@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@ $(am__objects_89) \ + src/lib/nfs/libstorage_a-Blocking.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@am__objects_98 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@ $(am__objects_97) \ @ENABLE_DATABASE_TRUE@@ENABLE_NFS_TRUE@ src/storage/plugins/libstorage_a-NfsStorage.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_WEBDAV_TRUE@am__objects_99 = src/lib/expat/libstorage_a-ExpatParser.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_WEBDAV_TRUE@ src/storage/plugins/libstorage_a-CurlStorage.$(OBJEXT) @ENABLE_DATABASE_TRUE@am_libstorage_a_OBJECTS = src/storage/libstorage_a-Registry.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/storage/libstorage_a-StorageInterface.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/storage/libstorage_a-CompositeStorage.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/storage/libstorage_a-MemoryDirectoryReader.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/storage/libstorage_a-Configured.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@ src/storage/plugins/libstorage_a-LocalStorage.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@ $(am__objects_88) $(am__objects_90) +@ENABLE_DATABASE_TRUE@ $(am__objects_96) $(am__objects_98) \ +@ENABLE_DATABASE_TRUE@ $(am__objects_99) libstorage_a_OBJECTS = $(am_libstorage_a_OBJECTS) libsystem_a_AR = $(AR) $(ARFLAGS) libsystem_a_LIBADD = am_libsystem_a_OBJECTS = src/system/FatalError.$(OBJEXT) \ - src/system/fd_util.$(OBJEXT) src/system/SocketUtil.$(OBJEXT) \ - src/system/SocketError.$(OBJEXT) src/system/Resolver.$(OBJEXT) \ - src/system/EventPipe.$(OBJEXT) src/system/EventFD.$(OBJEXT) \ - src/system/SignalFD.$(OBJEXT) src/system/EPollFD.$(OBJEXT) \ - src/system/Clock.$(OBJEXT) + src/system/FileDescriptor.$(OBJEXT) \ + src/system/fd_util.$(OBJEXT) src/system/EventPipe.$(OBJEXT) \ + src/system/EventFD.$(OBJEXT) src/system/SignalFD.$(OBJEXT) \ + src/system/EPollFD.$(OBJEXT) src/system/Clock.$(OBJEXT) libsystem_a_OBJECTS = $(am_libsystem_a_OBJECTS) libtag_a_AR = $(AR) $(ARFLAGS) libtag_a_LIBADD = am__libtag_a_SOURCES_DIST = src/tag/TagType.h src/tag/Tag.cxx \ src/tag/Tag.hxx src/tag/TagBuilder.cxx src/tag/TagBuilder.hxx \ src/tag/TagItem.hxx src/tag/TagHandler.cxx \ - src/tag/TagHandler.hxx src/tag/TagSettings.c \ - src/tag/TagSettings.h src/tag/TagConfig.cxx \ + src/tag/TagHandler.hxx src/tag/Mask.hxx src/tag/Settings.cxx \ + src/tag/Settings.hxx src/tag/TagConfig.cxx \ src/tag/TagConfig.hxx src/tag/TagNames.c src/tag/TagString.cxx \ src/tag/TagString.hxx src/tag/TagPool.cxx src/tag/TagPool.hxx \ src/tag/TagTable.cxx src/tag/TagTable.hxx src/tag/Set.cxx \ - src/tag/Set.hxx src/tag/VorbisComment.cxx \ - src/tag/VorbisComment.hxx src/tag/ReplayGain.cxx \ - src/tag/ReplayGain.hxx src/tag/MixRamp.cxx src/tag/MixRamp.hxx \ - src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \ - src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \ - src/tag/ApeTag.cxx src/tag/ApeTag.hxx src/tag/TagId3.cxx \ - src/tag/TagId3.hxx src/tag/TagRva2.cxx src/tag/TagRva2.hxx \ - src/tag/Riff.cxx src/tag/Riff.hxx src/tag/Aiff.cxx \ - src/tag/Aiff.hxx -@HAVE_ID3TAG_TRUE@am__objects_91 = src/tag/libtag_a-TagId3.$(OBJEXT) \ -@HAVE_ID3TAG_TRUE@ src/tag/libtag_a-TagRva2.$(OBJEXT) \ -@HAVE_ID3TAG_TRUE@ src/tag/libtag_a-Riff.$(OBJEXT) \ -@HAVE_ID3TAG_TRUE@ src/tag/libtag_a-Aiff.$(OBJEXT) + src/tag/Set.hxx src/tag/Format.cxx src/tag/Format.hxx \ + src/tag/VorbisComment.cxx src/tag/VorbisComment.hxx \ + src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \ + src/tag/MixRamp.cxx src/tag/MixRamp.hxx src/tag/Generic.cxx \ + src/tag/Generic.hxx src/tag/ApeLoader.cxx \ + src/tag/ApeLoader.hxx src/tag/ApeReplayGain.cxx \ + src/tag/ApeReplayGain.hxx src/tag/ApeTag.cxx \ + src/tag/ApeTag.hxx src/tag/Id3Load.cxx src/tag/Id3Load.hxx \ + src/tag/Id3Unique.hxx src/tag/TagId3.cxx src/tag/TagId3.hxx \ + src/tag/TagRva2.cxx src/tag/TagRva2.hxx src/tag/Riff.cxx \ + src/tag/Riff.hxx src/tag/Aiff.cxx src/tag/Aiff.hxx +@ENABLE_ID3TAG_TRUE@am__objects_100 = \ +@ENABLE_ID3TAG_TRUE@ src/tag/libtag_a-Id3Load.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@ src/tag/libtag_a-TagId3.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@ src/tag/libtag_a-TagRva2.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@ src/tag/libtag_a-Riff.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@ src/tag/libtag_a-Aiff.$(OBJEXT) am_libtag_a_OBJECTS = src/tag/libtag_a-Tag.$(OBJEXT) \ src/tag/libtag_a-TagBuilder.$(OBJEXT) \ src/tag/libtag_a-TagHandler.$(OBJEXT) \ - src/tag/libtag_a-TagSettings.$(OBJEXT) \ + src/tag/libtag_a-Settings.$(OBJEXT) \ src/tag/libtag_a-TagConfig.$(OBJEXT) \ src/tag/libtag_a-TagNames.$(OBJEXT) \ src/tag/libtag_a-TagString.$(OBJEXT) \ src/tag/libtag_a-TagPool.$(OBJEXT) \ src/tag/libtag_a-TagTable.$(OBJEXT) \ src/tag/libtag_a-Set.$(OBJEXT) \ + src/tag/libtag_a-Format.$(OBJEXT) \ src/tag/libtag_a-VorbisComment.$(OBJEXT) \ src/tag/libtag_a-ReplayGain.$(OBJEXT) \ src/tag/libtag_a-MixRamp.$(OBJEXT) \ + src/tag/libtag_a-Generic.$(OBJEXT) \ src/tag/libtag_a-ApeLoader.$(OBJEXT) \ src/tag/libtag_a-ApeReplayGain.$(OBJEXT) \ - src/tag/libtag_a-ApeTag.$(OBJEXT) $(am__objects_91) + src/tag/libtag_a-ApeTag.$(OBJEXT) $(am__objects_100) libtag_a_OBJECTS = $(am_libtag_a_OBJECTS) libthread_a_AR = $(AR) $(ARFLAGS) libthread_a_LIBADD = -am_libthread_a_OBJECTS = src/thread/Thread.$(OBJEXT) +am_libthread_a_OBJECTS = src/thread/Util.$(OBJEXT) \ + src/thread/Thread.$(OBJEXT) libthread_a_OBJECTS = $(am_libthread_a_OBJECTS) libutil_a_AR = $(AR) $(ARFLAGS) libutil_a_LIBADD = -am_libutil_a_OBJECTS = src/util/Alloc.$(OBJEXT) \ - src/util/Error.$(OBJEXT) src/util/UTF8.$(OBJEXT) \ - src/util/StringUtil.$(OBJEXT) src/util/SplitString.$(OBJEXT) \ +am_libutil_a_OBJECTS = src/util/Exception.$(OBJEXT) \ + src/util/Alloc.$(OBJEXT) src/util/UTF8.$(OBJEXT) \ + src/util/MimeType.$(OBJEXT) src/util/StringView.$(OBJEXT) \ + src/util/AllocatedString.$(OBJEXT) \ + src/util/StringUtil.$(OBJEXT) src/util/StringCompare.$(OBJEXT) \ + src/util/WStringCompare.$(OBJEXT) \ + src/util/DivideString.$(OBJEXT) src/util/SplitString.$(OBJEXT) \ src/util/FormatString.$(OBJEXT) src/util/Tokenizer.$(OBJEXT) \ - src/util/UriUtil.$(OBJEXT) src/util/LazyRandomEngine.$(OBJEXT) \ + src/util/TimeParser.$(OBJEXT) src/util/UriUtil.$(OBJEXT) \ + src/util/LazyRandomEngine.$(OBJEXT) \ src/util/HugeAllocator.$(OBJEXT) src/util/PeakBuffer.$(OBJEXT) \ src/util/OptionParser.$(OBJEXT) src/util/ByteReverse.$(OBJEXT) \ - src/util/bit_reverse.$(OBJEXT) + src/util/format.$(OBJEXT) src/util/bit_reverse.$(OBJEXT) libutil_a_OBJECTS = $(am_libutil_a_OBJECTS) +libxiph_a_AR = $(AR) $(ARFLAGS) +libxiph_a_LIBADD = +am__libxiph_a_SOURCES_DIST = src/lib/xiph/VorbisComment.hxx \ + src/lib/xiph/VorbisComments.cxx \ + src/lib/xiph/VorbisComments.hxx src/lib/xiph/XiphTags.cxx \ + src/lib/xiph/XiphTags.hxx src/lib/xiph/OggVisitor.cxx \ + src/lib/xiph/OggVisitor.hxx src/lib/xiph/OggSerial.cxx \ + src/lib/xiph/OggSerial.hxx src/lib/xiph/OggSyncState.cxx \ + src/lib/xiph/OggSyncState.hxx src/lib/xiph/OggFind.cxx \ + src/lib/xiph/OggFind.hxx src/lib/xiph/OggPage.hxx \ + src/lib/xiph/OggPacket.cxx src/lib/xiph/OggPacket.hxx \ + src/lib/xiph/OggStreamState.hxx +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@am__objects_101 = src/lib/xiph/libxiph_a-OggVisitor.$(OBJEXT) \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/libxiph_a-OggSerial.$(OBJEXT) \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/libxiph_a-OggSyncState.$(OBJEXT) \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/libxiph_a-OggFind.$(OBJEXT) \ +@HAVE_OGG_TRUE@@HAVE_XIPH_TRUE@ src/lib/xiph/libxiph_a-OggPacket.$(OBJEXT) +@HAVE_XIPH_TRUE@am_libxiph_a_OBJECTS = src/lib/xiph/libxiph_a-VorbisComments.$(OBJEXT) \ +@HAVE_XIPH_TRUE@ src/lib/xiph/libxiph_a-XiphTags.$(OBJEXT) \ +@HAVE_XIPH_TRUE@ $(am__objects_101) +libxiph_a_OBJECTS = $(am_libxiph_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(developerdir)" \ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(protocoldir)" \ @@ -1759,6 +1918,7 @@ @ENABLE_TEST_TRUE@ test/test_pcm$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/test_protocol$(EXEEXT) \ @ENABLE_TEST_TRUE@ test/test_queue_priority$(EXEEXT) \ +@ENABLE_TEST_TRUE@ test/TestFs$(EXEEXT) test/TestIcu$(EXEEXT) \ @ENABLE_TEST_TRUE@ $(am__EXEEXT_1) $(am__EXEEXT_2) \ @ENABLE_TEST_TRUE@ $(am__EXEEXT_3) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_5 = test/DumpDatabase$(EXEEXT) \ @@ -1767,93 +1927,105 @@ @ENABLE_TEST_TRUE@@HAVE_AVAHI_TRUE@am__EXEEXT_7 = \ @ENABLE_TEST_TRUE@@HAVE_AVAHI_TRUE@ test/run_avahi$(EXEEXT) @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_8 = test/visit_archive$(EXEEXT) -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@am__EXEEXT_9 = \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ test/dump_rva2$(EXEEXT) -@ENABLE_TEST_TRUE@@HAVE_ALSA_TRUE@am__EXEEXT_10 = \ -@ENABLE_TEST_TRUE@@HAVE_ALSA_TRUE@ test/read_mixer$(EXEEXT) -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@am__EXEEXT_11 = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ test/run_gzip$(EXEEXT) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ test/run_gunzip$(EXEEXT) +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_9 = \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ test/dump_rva2$(EXEEXT) +@ENABLE_ALSA_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_10 = \ +@ENABLE_ALSA_TRUE@@ENABLE_TEST_TRUE@ test/read_mixer$(EXEEXT) +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@am__EXEEXT_11 = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ test/run_gzip$(EXEEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ test/run_gunzip$(EXEEXT) @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_12 = test/run_encoder$(EXEEXT) -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@am__EXEEXT_13 = test/test_vorbis_encoder$(EXEEXT) +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@am__EXEEXT_13 = test/test_vorbis_encoder$(EXEEXT) @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_14 = test/run_inotify$(EXEEXT) @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@am__EXEEXT_15 = src/pcm/dsd2pcm/dsd2pcm$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_src_mpd_OBJECTS = src/Main.$(OBJEXT) src_mpd_OBJECTS = $(am_src_mpd_OBJECTS) am__DEPENDENCIES_1 = -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@HAVE_LIBUPNP_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_UPNP_TRUE@ $(am__DEPENDENCIES_1) @ENABLE_NEIGHBOR_PLUGINS_TRUE@am__DEPENDENCIES_3 = \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ libneighbor.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__DEPENDENCIES_2) -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) \ -@ENABLE_DATABASE_TRUE@@HAVE_LIBUPNP_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@am__DEPENDENCIES_4 = \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(am__DEPENDENCIES_1) \ +@ENABLE_DATABASE_TRUE@@ENABLE_UPNP_TRUE@ $(am__DEPENDENCIES_1) @ENABLE_DATABASE_TRUE@am__DEPENDENCIES_5 = libdb_plugins.a \ @ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_4) @ENABLE_DATABASE_TRUE@am__DEPENDENCIES_6 = libstorage.a \ @ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_1) \ +@ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_1) \ +@ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_DATABASE_TRUE@ $(am__DEPENDENCIES_1) @ENABLE_SOUNDCLOUD_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1) am__DEPENDENCIES_8 = libplaylist_plugins.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_7) -@HAVE_FFMPEG_TRUE@am__DEPENDENCIES_9 = libffmpeg.a \ -@HAVE_FFMPEG_TRUE@ $(am__DEPENDENCIES_1) -@HAVE_MODPLUG_TRUE@am__DEPENDENCIES_10 = libmodplug_decoder_plugin.a \ -@HAVE_MODPLUG_TRUE@ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_11 = libdecoder.a $(am__DEPENDENCIES_1) \ +@HAVE_XIPH_TRUE@am__DEPENDENCIES_9 = libxiph.a $(am__DEPENDENCIES_1) +@ENABLE_FFMPEG_TRUE@am__DEPENDENCIES_10 = libffmpeg.a \ +@ENABLE_FFMPEG_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_MODPLUG_TRUE@am__DEPENDENCIES_11 = \ +@ENABLE_MODPLUG_TRUE@ libmodplug_decoder_plugin.a \ +@ENABLE_MODPLUG_TRUE@ $(am__DEPENDENCIES_1) +am__DEPENDENCIES_12 = libdecoder.a $(am__DEPENDENCIES_9) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_9) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_10) -@HAVE_ALSA_TRUE@am__DEPENDENCIES_12 = $(am__DEPENDENCIES_1) -am__DEPENDENCIES_13 = libinput.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_10) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_9) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_12) -@ENABLE_ARCHIVE_TRUE@am__DEPENDENCIES_14 = libarchive.a \ + $(am__DEPENDENCIES_11) +@ENABLE_ALSA_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_1) +am__DEPENDENCIES_14 = libinput.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_10) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_13) +@ENABLE_ARCHIVE_TRUE@am__DEPENDENCIES_15 = libarchive.a \ @ENABLE_ARCHIVE_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ARCHIVE_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ARCHIVE_TRUE@ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_15 = libtag.a $(am__DEPENDENCIES_1) -am__DEPENDENCIES_16 = liboutput_plugins.a $(am__DEPENDENCIES_1) \ +@ENABLE_PULSE_TRUE@am__DEPENDENCIES_16 = libpulse.a \ +@ENABLE_PULSE_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_PULSE_TRUE@am__DEPENDENCIES_17 = $(am__DEPENDENCIES_16) +am__DEPENDENCIES_18 = liboutput_plugins.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am__DEPENDENCIES_17 = libpcm.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_17) +am__DEPENDENCIES_19 = libtag.a $(am__DEPENDENCIES_1) +am__DEPENDENCIES_20 = libpcm.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_18 = libfilter_plugins.a $(am__DEPENDENCIES_17) -@ENABLE_ENCODER_TRUE@am__DEPENDENCIES_19 = libencoder_plugins.a \ +am__DEPENDENCIES_21 = libfilter_plugins.a $(am__DEPENDENCIES_20) +@ENABLE_ENCODER_TRUE@am__DEPENDENCIES_22 = libencoder_plugins.a \ +@ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_9) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_ENCODER_TRUE@ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_20 = libmixer_plugins.a $(am__DEPENDENCIES_1) \ +am__DEPENDENCIES_23 = libmixer_plugins.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_16) +@ENABLE_ZLIB_TRUE@am__DEPENDENCIES_24 = $(am__DEPENDENCIES_1) +am__DEPENDENCIES_25 = libfs.a $(am__DEPENDENCIES_24) \ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_21 = libicu.a $(am__DEPENDENCIES_1) -@HAVE_ZLIB_TRUE@am__DEPENDENCIES_22 = $(am__DEPENDENCIES_1) -am__DEPENDENCIES_23 = libfs.a $(am__DEPENDENCIES_22) +am__DEPENDENCIES_26 = libicu.a $(am__DEPENDENCIES_1) src_mpd_DEPENDENCIES = libmpd.a $(am__DEPENDENCIES_3) \ $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \ $(am__DEPENDENCIES_8) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_11) $(am__DEPENDENCIES_13) \ - $(am__DEPENDENCIES_14) $(am__DEPENDENCIES_15) \ - $(am__DEPENDENCIES_16) $(am__DEPENDENCIES_18) \ - $(am__DEPENDENCIES_19) $(am__DEPENDENCIES_20) libconf.a \ - libevent.a libthread.a libsystem.a $(am__DEPENDENCIES_21) \ - libutil.a $(am__DEPENDENCIES_23) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__append_4) + $(am__DEPENDENCIES_12) $(am__DEPENDENCIES_14) \ + $(am__DEPENDENCIES_15) $(am__DEPENDENCIES_18) \ + $(am__DEPENDENCIES_19) $(am__DEPENDENCIES_21) \ + $(am__DEPENDENCIES_22) $(am__DEPENDENCIES_23) libconf.a \ + libbasic.a libevent.a libthread.a libnet.a \ + $(am__DEPENDENCIES_25) libsystem.a libutil.a \ + $(am__DEPENDENCIES_26) $(am__DEPENDENCIES_1) $(am__append_5) src_mpd_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(src_mpd_LDFLAGS) \ $(LDFLAGS) -o $@ am__src_pcm_dsd2pcm_dsd2pcm_SOURCES_DIST = src/pcm/dsd2pcm/dsd2pcm.c \ @@ -1867,19 +2039,35 @@ $(am_src_pcm_dsd2pcm_dsd2pcm_OBJECTS) @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@src_pcm_dsd2pcm_dsd2pcm_DEPENDENCIES = \ @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@ libutil.a +am__test_ContainerScan_SOURCES_DIST = test/ContainerScan.cxx \ + src/DetachedSong.cxx src/SongSave.cxx src/TagSave.cxx \ + src/Log.cxx src/LogBackend.cxx src/ReplayGainInfo.cxx +@ENABLE_TEST_TRUE@am_test_ContainerScan_OBJECTS = \ +@ENABLE_TEST_TRUE@ test/ContainerScan.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/SongSave.$(OBJEXT) src/TagSave.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) +test_ContainerScan_OBJECTS = $(am_test_ContainerScan_OBJECTS) +@ENABLE_TEST_TRUE@test_ContainerScan_DEPENDENCIES = \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_12) libpcm.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a libthread.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_DumpDatabase_SOURCES_DIST = test/DumpDatabase.cxx \ src/protocol/Ack.cxx src/Log.cxx src/LogBackend.cxx \ - src/db/DatabaseError.cxx src/db/Registry.cxx \ - src/db/Selection.cxx src/db/PlaylistVector.cxx \ - src/db/DatabaseLock.cxx src/SongSave.cxx src/DetachedSong.cxx \ - src/TagSave.cxx src/SongFilter.cxx \ - src/lib/expat/ExpatParser.cxx -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@HAVE_LIBUPNP_TRUE@am__objects_92 = src/lib/expat/ExpatParser.$(OBJEXT) + src/db/Registry.cxx src/db/Selection.cxx \ + src/db/PlaylistVector.cxx src/db/DatabaseLock.cxx \ + src/SongSave.cxx src/DetachedSong.cxx src/TagSave.cxx \ + src/SongFilter.cxx src/lib/expat/ExpatParser.cxx +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@ENABLE_UPNP_TRUE@am__objects_102 = src/lib/expat/ExpatParser.$(OBJEXT) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am_test_DumpDatabase_OBJECTS = test/DumpDatabase.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/protocol/Ack.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/DatabaseError.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/Registry.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/Selection.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/PlaylistVector.$(OBJEXT) \ @@ -1888,70 +2076,109 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/TagSave.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/SongFilter.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__objects_92) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__objects_102) test_DumpDatabase_OBJECTS = $(am_test_DumpDatabase_OBJECTS) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_DumpDatabase_DEPENDENCIES = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_5) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libconf.a libutil.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libconf.a libevent.a \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_21) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a +am__test_ReadApeTags_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ + test/ReadApeTags.cxx +@ENABLE_TEST_TRUE@am_test_ReadApeTags_OBJECTS = src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ test/ReadApeTags.$(OBJEXT) +test_ReadApeTags_OBJECTS = $(am_test_ReadApeTags_OBJECTS) +@ENABLE_TEST_TRUE@test_ReadApeTags_DEPENDENCIES = \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a +am__test_TestFs_SOURCES_DIST = test/TestFs.cxx +@ENABLE_TEST_TRUE@am_test_TestFs_OBJECTS = \ +@ENABLE_TEST_TRUE@ test/test_TestFs-TestFs.$(OBJEXT) +test_TestFs_OBJECTS = $(am_test_TestFs_OBJECTS) +@ENABLE_TEST_TRUE@test_TestFs_DEPENDENCIES = $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +test_TestFs_LINK = $(CXXLD) $(test_TestFs_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am__test_TestIcu_SOURCES_DIST = test/TestIcu.cxx +@ENABLE_TEST_TRUE@am_test_TestIcu_OBJECTS = \ +@ENABLE_TEST_TRUE@ test/test_TestIcu-TestIcu.$(OBJEXT) +test_TestIcu_OBJECTS = $(am_test_TestIcu_OBJECTS) +@ENABLE_TEST_TRUE@test_TestIcu_DEPENDENCIES = $(am__DEPENDENCIES_26) \ +@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) +test_TestIcu_LINK = $(CXXLD) $(test_TestIcu_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am__test_WriteFile_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ + test/WriteFile.cxx +@ENABLE_TEST_TRUE@am_test_WriteFile_OBJECTS = src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ test/WriteFile.$(OBJEXT) +test_WriteFile_OBJECTS = $(am_test_WriteFile_OBJECTS) +@ENABLE_TEST_TRUE@test_WriteFile_DEPENDENCIES = \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_dump_playlist_SOURCES_DIST = test/dump_playlist.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx src/TagSave.cxx src/TagFile.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ src/DetachedSong.cxx src/ReplayGainInfo.cxx \ src/decoder/plugins/FlacMetadata.cxx -@ENABLE_TEST_TRUE@@HAVE_FLAC_TRUE@am__objects_93 = src/ReplayGainInfo.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@HAVE_FLAC_TRUE@ src/decoder/plugins/FlacMetadata.$(OBJEXT) +@ENABLE_FLAC_TRUE@@ENABLE_TEST_TRUE@am__objects_103 = src/ReplayGainInfo.$(OBJEXT) \ +@ENABLE_FLAC_TRUE@@ENABLE_TEST_TRUE@ src/decoder/plugins/FlacMetadata.$(OBJEXT) @ENABLE_TEST_TRUE@am_test_dump_playlist_OBJECTS = \ @ENABLE_TEST_TRUE@ test/dump_playlist.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) src/TagSave.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/TagFile.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) $(am__objects_93) +@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ $(am__objects_103) test_dump_playlist_OBJECTS = $(am_test_dump_playlist_OBJECTS) @ENABLE_TEST_TRUE@test_dump_playlist_DEPENDENCIES = \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_8) $(am__DEPENDENCIES_1) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_12) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) $(am__DEPENDENCIES_9) \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_11) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libevent.a \ -@ENABLE_TEST_TRUE@ libthread.a $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@ libsystem.a libutil.a libpcm.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a libthread.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a \ +@ENABLE_TEST_TRUE@ libpcm.a am__test_dump_rva2_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ test/dump_rva2.cxx -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@am_test_dump_rva2_OBJECTS = \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ src/Log.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ src/LogBackend.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ test/dump_rva2.$(OBJEXT) +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@am_test_dump_rva2_OBJECTS = \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ test/dump_rva2.$(OBJEXT) test_dump_rva2_OBJECTS = $(am_test_dump_rva2_OBJECTS) -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@test_dump_rva2_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ $(am__DEPENDENCIES_15) \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@test_dump_rva2_DEPENDENCIES = \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a am__test_dump_text_file_SOURCES_DIST = test/dump_text_file.cxx \ - test/ScopeIOThread.hxx test/stdbin.h src/Log.cxx \ - src/LogBackend.cxx src/IOThread.cxx + test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ + src/IOThread.cxx @ENABLE_TEST_TRUE@am_test_dump_text_file_OBJECTS = \ @ENABLE_TEST_TRUE@ test/dump_text_file.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) test_dump_text_file_OBJECTS = $(am_test_dump_text_file_OBJECTS) @ENABLE_TEST_TRUE@test_dump_text_file_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libevent.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) libsystem.a \ -@ENABLE_TEST_TRUE@ libthread.a libutil.a $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libevent.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a \ +@ENABLE_TEST_TRUE@ libthread.a libutil.a am__test_read_conf_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ test/read_conf.cxx @ENABLE_TEST_TRUE@am_test_read_conf_OBJECTS = src/Log.$(OBJEXT) \ @@ -1959,45 +2186,44 @@ @ENABLE_TEST_TRUE@ test/read_conf.$(OBJEXT) test_read_conf_OBJECTS = $(am_test_read_conf_OBJECTS) @ENABLE_TEST_TRUE@test_read_conf_DEPENDENCIES = libconf.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) libsystem.a libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_read_mixer_SOURCES_DIST = test/read_mixer.cxx src/Log.cxx \ src/LogBackend.cxx src/mixer/MixerControl.cxx \ - src/filter/FilterPlugin.cxx src/AudioFormat.cxx \ + src/filter/FilterPlugin.cxx \ src/filter/plugins/VolumeFilterPlugin.cxx @ENABLE_TEST_TRUE@am_test_read_mixer_OBJECTS = \ @ENABLE_TEST_TRUE@ test/read_mixer.$(OBJEXT) src/Log.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/mixer/MixerControl.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/filter/FilterPlugin.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/filter/plugins/VolumeFilterPlugin.$(OBJEXT) test_read_mixer_OBJECTS = $(am_test_read_mixer_OBJECTS) @ENABLE_TEST_TRUE@test_read_mixer_DEPENDENCIES = libpcm.a \ -@ENABLE_TEST_TRUE@ libmixer_plugins.a $(am__DEPENDENCIES_16) \ -@ENABLE_TEST_TRUE@ libconf.a libevent.a $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@ libsystem.a libutil.a $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ libmixer_plugins.a $(am__DEPENDENCIES_18) \ +@ENABLE_TEST_TRUE@ libconf.a libbasic.a libevent.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_read_tags_SOURCES_DIST = test/read_tags.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ - test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ - src/IOThread.cxx src/ReplayGainInfo.cxx src/AudioFormat.cxx \ - src/CheckAudioFormat.cxx + test/ScopeIOThread.hxx src/DetachedSong.cxx src/Log.cxx \ + src/LogBackend.cxx src/IOThread.cxx src/ReplayGainInfo.cxx @ENABLE_TEST_TRUE@am_test_read_tags_OBJECTS = \ @ENABLE_TEST_TRUE@ test/read_tags.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) test_read_tags_OBJECTS = $(am_test_read_tags_OBJECTS) @ENABLE_TEST_TRUE@test_read_tags_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_11) libpcm.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_12) libpcm.a \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libevent.a \ -@ENABLE_TEST_TRUE@ libthread.a $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@ libsystem.a libutil.a $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a libthread.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_run_avahi_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ src/zeroconf/ZeroconfAvahi.cxx src/zeroconf/AvahiPoll.cxx \ test/ShutdownHandler.cxx test/ShutdownHandler.hxx \ @@ -2011,99 +2237,85 @@ @ENABLE_TEST_TRUE@ test/test_run_avahi-run_avahi.$(OBJEXT) test_run_avahi_OBJECTS = $(am_test_run_avahi_OBJECTS) @ENABLE_TEST_TRUE@test_run_avahi_DEPENDENCIES = libevent.a libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) am__test_run_convert_SOURCES_DIST = test/run_convert.cxx src/Log.cxx \ - src/LogBackend.cxx src/AudioFormat.cxx \ - src/CheckAudioFormat.cxx src/AudioParser.cxx + src/LogBackend.cxx @ENABLE_TEST_TRUE@am_test_run_convert_OBJECTS = \ @ENABLE_TEST_TRUE@ test/run_convert.$(OBJEXT) src/Log.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) test_run_convert_OBJECTS = $(am_test_run_convert_OBJECTS) @ENABLE_TEST_TRUE@test_run_convert_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_17) libconf.a libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_20) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) libsystem.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libutil.a am__test_run_decoder_SOURCES_DIST = test/run_decoder.cxx \ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ - test/ScopeIOThread.hxx test/stdbin.h src/Log.cxx \ - src/LogBackend.cxx src/IOThread.cxx src/ReplayGainInfo.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx + test/ScopeIOThread.hxx src/DetachedSong.cxx src/Log.cxx \ + src/LogBackend.cxx src/IOThread.cxx src/ReplayGainInfo.cxx @ENABLE_TEST_TRUE@am_test_run_decoder_OBJECTS = \ @ENABLE_TEST_TRUE@ test/run_decoder.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/DetachedSong.$(OBJEXT) src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) test_run_decoder_OBJECTS = $(am_test_run_decoder_OBJECTS) @ENABLE_TEST_TRUE@test_run_decoder_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_11) libpcm.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_12) libpcm.a \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libevent.a \ -@ENABLE_TEST_TRUE@ libthread.a $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@ libsystem.a libutil.a $(am__DEPENDENCIES_1) -am__test_run_encoder_SOURCES_DIST = test/run_encoder.cxx test/stdbin.h \ - src/Log.cxx src/LogBackend.cxx src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx src/AudioParser.cxx +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a libthread.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a +am__test_run_encoder_SOURCES_DIST = test/run_encoder.cxx src/Log.cxx \ + src/LogBackend.cxx @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@am_test_run_encoder_OBJECTS = test/run_encoder.$(OBJEXT) \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) test_run_encoder_OBJECTS = $(am_test_run_encoder_OBJECTS) @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@test_run_encoder_DEPENDENCIES = \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_22) \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libconf.a libpcm.a \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) -am__test_run_filter_SOURCES_DIST = test/run_filter.cxx \ - test/FakeReplayGainConfig.cxx test/stdbin.h src/Log.cxx \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libconf.a libbasic.a \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libpcm.a libthread.a \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a +am__test_run_filter_SOURCES_DIST = test/run_filter.cxx src/Log.cxx \ src/LogBackend.cxx src/filter/FilterPlugin.cxx \ - src/filter/FilterRegistry.cxx src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx src/AudioParser.cxx src/ReplayGainInfo.cxx + src/filter/FilterRegistry.cxx @ENABLE_TEST_TRUE@am_test_run_filter_OBJECTS = \ -@ENABLE_TEST_TRUE@ test/run_filter.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ test/FakeReplayGainConfig.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ test/run_filter.$(OBJEXT) src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/filter/FilterPlugin.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/filter/FilterRegistry.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/filter/FilterRegistry.$(OBJEXT) test_run_filter_OBJECTS = $(am_test_run_filter_OBJECTS) @ENABLE_TEST_TRUE@test_run_filter_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_18) libconf.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) libsystem.a libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_21) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_run_gunzip_SOURCES_DIST = test/run_gunzip.cxx src/Log.cxx \ src/LogBackend.cxx -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@am_test_run_gunzip_OBJECTS = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ test/run_gunzip.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ src/Log.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ src/LogBackend.$(OBJEXT) +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@am_test_run_gunzip_OBJECTS = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ test/run_gunzip.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/LogBackend.$(OBJEXT) test_run_gunzip_OBJECTS = $(am_test_run_gunzip_OBJECTS) -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gunzip_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libsystem.a -am__test_run_gzip_SOURCES_DIST = test/run_gzip.cxx -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@am_test_run_gzip_OBJECTS = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ test/run_gzip.$(OBJEXT) +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gunzip_DEPENDENCIES = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ libsystem.a libutil.a +am__test_run_gzip_SOURCES_DIST = test/run_gzip.cxx src/Log.cxx \ + src/LogBackend.cxx +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@am_test_run_gzip_OBJECTS = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ test/run_gzip.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/LogBackend.$(OBJEXT) test_run_gzip_OBJECTS = $(am_test_run_gzip_OBJECTS) -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gzip_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(am__DEPENDENCIES_23) +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gzip_DEPENDENCIES = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ libutil.a \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(am__DEPENDENCIES_25) am__test_run_inotify_SOURCES_DIST = test/run_inotify.cxx \ test/ShutdownHandler.cxx test/ShutdownHandler.hxx src/Log.cxx \ src/LogBackend.cxx src/db/update/InotifyDomain.cxx \ @@ -2117,73 +2329,65 @@ test_run_inotify_OBJECTS = $(am_test_run_inotify_OBJECTS) @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@test_run_inotify_DEPENDENCIES = \ @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libevent.a libsystem.a \ -@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libutil.a am__test_run_input_SOURCES_DIST = test/run_input.cxx \ - test/ScopeIOThread.hxx test/stdbin.h src/Log.cxx \ - src/LogBackend.cxx src/IOThread.cxx src/TagSave.cxx + test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ + src/IOThread.cxx src/TagSave.cxx @ENABLE_TEST_TRUE@am_test_run_input_OBJECTS = \ @ENABLE_TEST_TRUE@ test/run_input.$(OBJEXT) src/Log.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) src/TagSave.$(OBJEXT) test_run_input_OBJECTS = $(am_test_run_input_OBJECTS) @ENABLE_TEST_TRUE@test_run_input_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libutil.a \ -@ENABLE_TEST_TRUE@ libevent.a libthread.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) libsystem.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libevent.a \ +@ENABLE_TEST_TRUE@ libthread.a $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libsystem.a libutil.a am__test_run_neighbor_explorer_SOURCES_DIST = src/Log.cxx \ src/LogBackend.cxx src/IOThread.cxx \ test/run_neighbor_explorer.cxx src/lib/expat/ExpatParser.cxx -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@@HAVE_LIBUPNP_TRUE@am__objects_94 = src/lib/expat/ExpatParser.$(OBJEXT) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@@ENABLE_UPNP_TRUE@am__objects_104 = src/lib/expat/ExpatParser.$(OBJEXT) @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@am_test_run_neighbor_explorer_OBJECTS = src/Log.$(OBJEXT) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ test/run_neighbor_explorer.$(OBJEXT) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__objects_94) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__objects_104) test_run_neighbor_explorer_OBJECTS = \ $(am_test_run_neighbor_explorer_OBJECTS) -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@test_run_neighbor_explorer_DEPENDENCIES = $(am__DEPENDENCIES_1) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_3) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@test_run_neighbor_explorer_DEPENDENCIES = $(am__DEPENDENCIES_3) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libtag.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libconf.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libutil.a am__test_run_normalize_SOURCES_DIST = test/run_normalize.cxx \ - test/stdbin.h src/CheckAudioFormat.cxx \ + src/Log.cxx src/LogBackend.cxx src/CheckAudioFormat.cxx \ src/AudioCompress/compress.c src/AudioParser.cxx @ENABLE_TEST_TRUE@am_test_run_normalize_OBJECTS = \ @ENABLE_TEST_TRUE@ test/run_normalize.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/AudioCompress/compress.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) test_run_normalize_OBJECTS = $(am_test_run_normalize_OBJECTS) -@ENABLE_TEST_TRUE@test_run_normalize_DEPENDENCIES = libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@test_run_normalize_DEPENDENCIES = libutil.a am__test_run_output_SOURCES_DIST = test/run_output.cxx \ - test/FakeReplayGainConfig.cxx test/ScopeIOThread.hxx \ - test/stdbin.h src/Log.cxx src/LogBackend.cxx src/IOThread.cxx \ - src/CheckAudioFormat.cxx src/AudioFormat.cxx \ - src/AudioParser.cxx src/output/Domain.cxx src/output/Init.cxx \ + test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ + src/IOThread.cxx src/output/Domain.cxx src/output/Init.cxx \ src/output/Finish.cxx src/output/Registry.cxx \ src/output/OutputPlugin.cxx src/mixer/MixerControl.cxx \ src/mixer/MixerType.cxx src/filter/FilterPlugin.cxx \ - src/filter/FilterConfig.cxx src/ReplayGainInfo.cxx + src/filter/FilterConfig.cxx src/filter/Observer.cxx @ENABLE_TEST_TRUE@am_test_run_output_OBJECTS = \ -@ENABLE_TEST_TRUE@ test/run_output.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ test/FakeReplayGainConfig.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ test/run_output.$(OBJEXT) src/Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/output/Domain.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/output/Init.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/output/Finish.$(OBJEXT) \ @@ -2193,52 +2397,55 @@ @ENABLE_TEST_TRUE@ src/mixer/MixerType.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/filter/FilterPlugin.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/filter/FilterConfig.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/filter/Observer.$(OBJEXT) test_run_output_OBJECTS = $(am_test_run_output_OBJECTS) @ENABLE_TEST_TRUE@test_run_output_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_17) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_16) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libmixer_plugins.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_20) \ @ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_18) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) libconf.a libevent.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) libsystem.a \ -@ENABLE_TEST_TRUE@ libthread.a libutil.a $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_22) libmixer_plugins.a \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_21) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) libnet.a libsystem.a \ +@ENABLE_TEST_TRUE@ libthread.a libutil.a am__test_run_resolver_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ test/run_resolver.cxx @ENABLE_TEST_TRUE@am_test_run_resolver_OBJECTS = src/Log.$(OBJEXT) \ @ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/run_resolver.$(OBJEXT) test_run_resolver_OBJECTS = $(am_test_run_resolver_OBJECTS) -@ENABLE_TEST_TRUE@test_run_resolver_DEPENDENCIES = libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@test_run_resolver_DEPENDENCIES = libnet.a libutil.a am__test_run_storage_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ - src/IOThread.cxx test/ScopeIOThread.hxx test/run_storage.cxx + src/IOThread.cxx test/ScopeIOThread.hxx test/run_storage.cxx \ + src/lib/curl/Version.cxx src/lib/curl/Version.hxx \ + src/lib/curl/Global.cxx src/lib/curl/Global.hxx \ + src/lib/curl/Request.cxx src/lib/curl/Request.hxx \ + src/lib/curl/Handler.hxx src/lib/curl/Easy.hxx \ + src/lib/curl/Multi.hxx src/lib/curl/Slist.hxx +am__objects_105 = src/lib/curl/Version.$(OBJEXT) \ + src/lib/curl/Global.$(OBJEXT) src/lib/curl/Request.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@@ENABLE_WEBDAV_TRUE@am__objects_106 = $(am__objects_105) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am_test_run_storage_OBJECTS = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/IOThread.$(OBJEXT) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/run_storage.$(OBJEXT) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/run_storage.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__objects_106) test_run_storage_OBJECTS = $(am_test_run_storage_OBJECTS) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_run_storage_DEPENDENCIES = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_6) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libevent.a libthread.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a am__test_software_volume_SOURCES_DIST = test/software_volume.cxx \ - test/stdbin.h src/Log.cxx src/LogBackend.cxx \ - src/AudioFormat.cxx src/CheckAudioFormat.cxx \ - src/AudioParser.cxx + src/Log.cxx src/LogBackend.cxx @ENABLE_TEST_TRUE@am_test_software_volume_OBJECTS = \ @ENABLE_TEST_TRUE@ test/software_volume.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT) +@ENABLE_TEST_TRUE@ src/Log.$(OBJEXT) src/LogBackend.$(OBJEXT) test_software_volume_OBJECTS = $(am_test_software_volume_OBJECTS) @ENABLE_TEST_TRUE@test_software_volume_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_17) libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_20) libbasic.a libutil.a am__test_test_archive_SOURCES_DIST = src/Log.cxx src/LogBackend.cxx \ test/test_archive.cxx @ENABLE_TEST_TRUE@am_test_test_archive_OBJECTS = \ @@ -2247,8 +2454,7 @@ @ENABLE_TEST_TRUE@ test/test_test_archive-test_archive.$(OBJEXT) test_test_archive_OBJECTS = $(am_test_test_archive_OBJECTS) @ENABLE_TEST_TRUE@test_test_archive_DEPENDENCIES = libarchive.a \ -@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) test_test_archive_LINK = $(CXXLD) $(test_test_archive_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__test_test_byte_reverse_SOURCES_DIST = test/test_byte_reverse.cxx @@ -2267,7 +2473,6 @@ test_test_icy_parser_OBJECTS = $(am_test_test_icy_parser_OBJECTS) @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@test_test_icy_parser_DEPENDENCIES = \ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ libtag.a libutil.a \ -@ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) test_test_icy_parser_LINK = $(CXXLD) $(test_test_icy_parser_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @@ -2279,29 +2484,29 @@ @ENABLE_TEST_TRUE@ test/test_test_mixramp-test_mixramp.$(OBJEXT) test_test_mixramp_OBJECTS = $(am_test_test_mixramp_OBJECTS) @ENABLE_TEST_TRUE@test_test_mixramp_DEPENDENCIES = libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) test_test_mixramp_LINK = $(CXXLD) $(test_test_mixramp_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -am__test_test_pcm_SOURCES_DIST = src/AudioFormat.cxx \ - test/test_pcm_util.hxx test/test_pcm_dither.cxx \ - test/test_pcm_pack.cxx test/test_pcm_channels.cxx \ - test/test_pcm_format.cxx test/test_pcm_volume.cxx \ - test/test_pcm_mix.cxx test/test_pcm_export.cxx \ +am__test_test_pcm_SOURCES_DIST = test/TestAudioFormat.cxx \ + test/TestAudioFormat.hxx test/test_pcm_util.hxx \ + test/test_pcm_dither.cxx test/test_pcm_pack.cxx \ + test/test_pcm_channels.cxx test/test_pcm_format.cxx \ + test/test_pcm_volume.cxx test/test_pcm_mix.cxx \ + test/test_pcm_interleave.cxx test/test_pcm_export.cxx \ test/test_pcm_all.hxx test/test_pcm_main.cxx -@ENABLE_TEST_TRUE@am_test_test_pcm_OBJECTS = \ -@ENABLE_TEST_TRUE@ src/test_test_pcm-AudioFormat.$(OBJEXT) \ +@ENABLE_TEST_TRUE@am_test_test_pcm_OBJECTS = test/test_test_pcm-TestAudioFormat.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_dither.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_pack.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_channels.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_format.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_volume.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_mix.$(OBJEXT) \ +@ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_interleave.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_export.$(OBJEXT) \ @ENABLE_TEST_TRUE@ test/test_test_pcm-test_pcm_main.$(OBJEXT) test_test_pcm_OBJECTS = $(am_test_test_pcm_OBJECTS) -@ENABLE_TEST_TRUE@test_test_pcm_DEPENDENCIES = $(am__DEPENDENCIES_17) \ -@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@test_test_pcm_DEPENDENCIES = $(am__DEPENDENCIES_20) \ +@ENABLE_TEST_TRUE@ libbasic.a libutil.a $(am__DEPENDENCIES_1) test_test_pcm_LINK = $(CXXLD) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__test_test_protocol_SOURCES_DIST = src/protocol/ArgParser.cxx \ @@ -2333,19 +2538,19 @@ @ENABLE_TEST_TRUE@ test/test_test_rewind-test_rewind.$(OBJEXT) test_test_rewind_OBJECTS = $(am_test_test_rewind_OBJECTS) @ENABLE_TEST_TRUE@test_test_rewind_DEPENDENCIES = \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_13) \ -@ENABLE_TEST_TRUE@ libthread.a libtag.a libutil.a \ -@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) libthread.a libtag.a \ +@ENABLE_TEST_TRUE@ libutil.a $(am__DEPENDENCIES_1) test_test_rewind_LINK = $(CXXLD) $(test_test_rewind_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__test_test_translate_song_SOURCES_DIST = \ src/playlist/PlaylistSong.cxx src/PlaylistError.cxx \ - src/DetachedSong.cxx src/SongLoader.cxx src/Log.cxx \ - test/test_translate_song.cxx + src/DetachedSong.cxx src/SongLoader.cxx src/LocateUri.cxx \ + src/Log.cxx test/test_translate_song.cxx @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@am_test_test_translate_song_OBJECTS = src/playlist/test_test_translate_song-PlaylistSong.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/test_test_translate_song-PlaylistError.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/test_test_translate_song-DetachedSong.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/test_test_translate_song-SongLoader.$(OBJEXT) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/test_test_translate_song-LocateUri.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/test_test_translate_song-Log.$(OBJEXT) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/test_test_translate_song-test_translate_song.$(OBJEXT) test_test_translate_song_OBJECTS = \ @@ -2353,14 +2558,16 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_test_translate_song_DEPENDENCIES = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_6) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libtag.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) test_test_translate_song_LINK = $(CXXLD) \ $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -am__test_test_util_SOURCES_DIST = test/TestCircularBuffer.hxx \ +am__test_test_util_SOURCES_DIST = test/DivideStringTest.hxx \ + test/SplitStringTest.hxx test/UriUtilTest.hxx \ + test/MimeTypeTest.hxx test/TestCircularBuffer.hxx \ test/test_util.cxx @ENABLE_TEST_TRUE@am_test_test_util_OBJECTS = \ @ENABLE_TEST_TRUE@ test/test_test_util-test_util.$(OBJEXT) @@ -2370,25 +2577,19 @@ test_test_util_LINK = $(CXXLD) $(test_test_util_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__test_test_vorbis_encoder_SOURCES_DIST = \ - test/test_vorbis_encoder.cxx test/stdbin.h src/Log.cxx \ - src/LogBackend.cxx src/CheckAudioFormat.cxx \ - src/AudioFormat.cxx src/AudioParser.cxx -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@am_test_test_vorbis_encoder_OBJECTS = test/test_test_vorbis_encoder-test_vorbis_encoder.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/test_test_vorbis_encoder-Log.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/test_test_vorbis_encoder-LogBackend.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/test_test_vorbis_encoder-CheckAudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/test_test_vorbis_encoder-AudioFormat.$(OBJEXT) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/test_test_vorbis_encoder-AudioParser.$(OBJEXT) + test/test_vorbis_encoder.cxx src/Log.cxx src/LogBackend.cxx +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@am_test_test_vorbis_encoder_OBJECTS = test/test_test_vorbis_encoder-test_vorbis_encoder.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ src/test_test_vorbis_encoder-Log.$(OBJEXT) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ src/test_test_vorbis_encoder-LogBackend.$(OBJEXT) test_test_vorbis_encoder_OBJECTS = \ $(am_test_test_vorbis_encoder_OBJECTS) -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@test_test_vorbis_encoder_DEPENDENCIES = $(am__DEPENDENCIES_19) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(am__DEPENDENCIES_17) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(am__DEPENDENCIES_15) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libconf.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(am__DEPENDENCIES_23) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@test_test_vorbis_encoder_DEPENDENCIES = $(am__DEPENDENCIES_22) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(am__DEPENDENCIES_20) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(am__DEPENDENCIES_19) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libconf.a libbasic.a \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libsystem.a libutil.a am__test_visit_archive_SOURCES_DIST = test/visit_archive.cxx \ test/ScopeIOThread.hxx src/Log.cxx src/LogBackend.cxx \ src/IOThread.cxx src/input/Open.cxx @@ -2399,14 +2600,14 @@ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ src/input/Open.$(OBJEXT) test_visit_archive_OBJECTS = $(am_test_visit_archive_OBJECTS) @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@test_visit_archive_DEPENDENCIES = \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_13) \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_14) \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_15) \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libconf.a libutil.a \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libevent.a libthread.a \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_23) \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1) +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_19) \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libconf.a libevent.a \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_25) \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_26) \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a libutil.a AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -2453,27 +2654,32 @@ am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libandroid_a_SOURCES) $(libarchive_a_SOURCES) \ - $(libconf_a_SOURCES) $(libdb_plugins_a_SOURCES) \ - $(libdecoder_a_SOURCES) $(libencoder_plugins_a_SOURCES) \ - $(libevent_a_SOURCES) $(libffmpeg_a_SOURCES) \ - $(libfilter_plugins_a_SOURCES) $(libfs_a_SOURCES) \ - $(libicu_a_SOURCES) $(libinput_a_SOURCES) $(libjava_a_SOURCES) \ - $(libmain_a_SOURCES) $(libmixer_plugins_a_SOURCES) \ + $(libbasic_a_SOURCES) $(libconf_a_SOURCES) \ + $(libdb_plugins_a_SOURCES) $(libdecoder_a_SOURCES) \ + $(libencoder_plugins_a_SOURCES) $(libevent_a_SOURCES) \ + $(libffmpeg_a_SOURCES) $(libfilter_plugins_a_SOURCES) \ + $(libfs_a_SOURCES) $(libicu_a_SOURCES) $(libinput_a_SOURCES) \ + $(libjava_a_SOURCES) $(libmain_a_SOURCES) \ + $(libmixer_plugins_a_SOURCES) \ $(libmodplug_decoder_plugin_a_SOURCES) $(libmpd_a_SOURCES) \ - $(libneighbor_a_SOURCES) $(liboutput_plugins_a_SOURCES) \ - $(libpcm_a_SOURCES) $(libplaylist_plugins_a_SOURCES) \ + $(libneighbor_a_SOURCES) $(libnet_a_SOURCES) \ + $(liboutput_plugins_a_SOURCES) $(libpcm_a_SOURCES) \ + $(libplaylist_plugins_a_SOURCES) $(libpulse_a_SOURCES) \ $(libstorage_a_SOURCES) $(libsystem_a_SOURCES) \ $(libtag_a_SOURCES) $(libthread_a_SOURCES) \ - $(libutil_a_SOURCES) $(src_mpd_SOURCES) \ + $(libutil_a_SOURCES) $(libxiph_a_SOURCES) $(src_mpd_SOURCES) \ $(src_pcm_dsd2pcm_dsd2pcm_SOURCES) \ - $(test_DumpDatabase_SOURCES) $(test_dump_playlist_SOURCES) \ - $(test_dump_rva2_SOURCES) $(test_dump_text_file_SOURCES) \ - $(test_read_conf_SOURCES) $(test_read_mixer_SOURCES) \ - $(test_read_tags_SOURCES) $(test_run_avahi_SOURCES) \ - $(test_run_convert_SOURCES) $(test_run_decoder_SOURCES) \ - $(test_run_encoder_SOURCES) $(test_run_filter_SOURCES) \ - $(test_run_gunzip_SOURCES) $(test_run_gzip_SOURCES) \ - $(test_run_inotify_SOURCES) $(test_run_input_SOURCES) \ + $(test_ContainerScan_SOURCES) $(test_DumpDatabase_SOURCES) \ + $(test_ReadApeTags_SOURCES) $(test_TestFs_SOURCES) \ + $(test_TestIcu_SOURCES) $(test_WriteFile_SOURCES) \ + $(test_dump_playlist_SOURCES) $(test_dump_rva2_SOURCES) \ + $(test_dump_text_file_SOURCES) $(test_read_conf_SOURCES) \ + $(test_read_mixer_SOURCES) $(test_read_tags_SOURCES) \ + $(test_run_avahi_SOURCES) $(test_run_convert_SOURCES) \ + $(test_run_decoder_SOURCES) $(test_run_encoder_SOURCES) \ + $(test_run_filter_SOURCES) $(test_run_gunzip_SOURCES) \ + $(test_run_gzip_SOURCES) $(test_run_inotify_SOURCES) \ + $(test_run_input_SOURCES) \ $(test_run_neighbor_explorer_SOURCES) \ $(test_run_normalize_SOURCES) $(test_run_output_SOURCES) \ $(test_run_resolver_SOURCES) $(test_run_storage_SOURCES) \ @@ -2487,8 +2693,8 @@ $(test_test_vorbis_encoder_SOURCES) \ $(test_visit_archive_SOURCES) DIST_SOURCES = $(am__libandroid_a_SOURCES_DIST) \ - $(am__libarchive_a_SOURCES_DIST) $(libconf_a_SOURCES) \ - $(am__libdb_plugins_a_SOURCES_DIST) \ + $(am__libarchive_a_SOURCES_DIST) $(libbasic_a_SOURCES) \ + $(libconf_a_SOURCES) $(am__libdb_plugins_a_SOURCES_DIST) \ $(am__libdecoder_a_SOURCES_DIST) \ $(am__libencoder_plugins_a_SOURCES_DIST) $(libevent_a_SOURCES) \ $(am__libffmpeg_a_SOURCES_DIST) $(libfilter_plugins_a_SOURCES) \ @@ -2498,14 +2704,20 @@ $(am__libmixer_plugins_a_SOURCES_DIST) \ $(am__libmodplug_decoder_plugin_a_SOURCES_DIST) \ $(am__libmpd_a_SOURCES_DIST) $(am__libneighbor_a_SOURCES_DIST) \ - $(am__liboutput_plugins_a_SOURCES_DIST) \ + $(libnet_a_SOURCES) $(am__liboutput_plugins_a_SOURCES_DIST) \ $(am__libpcm_a_SOURCES_DIST) \ $(am__libplaylist_plugins_a_SOURCES_DIST) \ + $(am__libpulse_a_SOURCES_DIST) \ $(am__libstorage_a_SOURCES_DIST) $(libsystem_a_SOURCES) \ $(am__libtag_a_SOURCES_DIST) $(libthread_a_SOURCES) \ - $(libutil_a_SOURCES) $(src_mpd_SOURCES) \ - $(am__src_pcm_dsd2pcm_dsd2pcm_SOURCES_DIST) \ + $(libutil_a_SOURCES) $(am__libxiph_a_SOURCES_DIST) \ + $(src_mpd_SOURCES) $(am__src_pcm_dsd2pcm_dsd2pcm_SOURCES_DIST) \ + $(am__test_ContainerScan_SOURCES_DIST) \ $(am__test_DumpDatabase_SOURCES_DIST) \ + $(am__test_ReadApeTags_SOURCES_DIST) \ + $(am__test_TestFs_SOURCES_DIST) \ + $(am__test_TestIcu_SOURCES_DIST) \ + $(am__test_WriteFile_SOURCES_DIST) \ $(am__test_dump_playlist_SOURCES_DIST) \ $(am__test_dump_rva2_SOURCES_DIST) \ $(am__test_dump_text_file_SOURCES_DIST) \ @@ -2781,11 +2993,11 @@ $(top_srcdir)/build/install-sh $(top_srcdir)/build/missing \ $(top_srcdir)/build/test-driver \ $(top_srcdir)/doc/doxygen.conf.in \ - $(top_srcdir)/src/win32/mpd_win32_rc.rc.in \ $(top_srcdir)/systemd/system/mpd.service.in \ - $(top_srcdir)/systemd/user/mpd.service.in AUTHORS COPYING \ - INSTALL NEWS README build/compile build/config.guess \ - build/config.sub build/depcomp build/install-sh build/missing + $(top_srcdir)/systemd/user/mpd.service.in \ + $(top_srcdir)/win32/res/mpd.rc.in AUTHORS COPYING NEWS \ + build/compile build/config.guess build/config.sub \ + build/depcomp build/install-sh build/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -2810,8 +3022,7 @@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ -AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/src $(GLIB_CFLAGS) \ - $(BOOST_CPPFLAGS) \ +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/src $(BOOST_CPPFLAGS) \ -DSYSTEM_CONFIG_FILE_LOCATION='"$(sysconfdir)/mpd.conf"' AM_CXXFLAGS = @AM_CXXFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -2865,11 +3076,12 @@ FLAC_LIBS = @FLAC_LIBS@ FLUIDSYNTH_CFLAGS = @FLUIDSYNTH_CFLAGS@ FLUIDSYNTH_LIBS = @FLUIDSYNTH_LIBS@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_LIBS = @GLIB_LIBS@ GME_CFLAGS = @GME_CFLAGS@ GME_LIBS = @GME_LIBS@ GREP = @GREP@ +HAIKU_CFLAGS = @HAIKU_CFLAGS@ +HAIKU_LIBS = @HAIKU_LIBS@ +HAVE_CXX14 = @HAVE_CXX14@ ICU_CFLAGS = @ICU_CFLAGS@ ICU_LIBS = @ICU_LIBS@ ID3TAG_CFLAGS = @ID3TAG_CFLAGS@ @@ -2893,6 +3105,8 @@ LIBMPDCLIENT_LIBS = @LIBMPDCLIENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ +LIBSAMPLERATE_CFLAGS = @LIBSAMPLERATE_CFLAGS@ +LIBSAMPLERATE_LIBS = @LIBSAMPLERATE_LIBS@ LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@ LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@ LTLIBOBJS = @LTLIBOBJS@ @@ -2912,6 +3126,8 @@ NFS_CFLAGS = @NFS_CFLAGS@ NFS_LIBS = @NFS_LIBS@ OBJEXT = @OBJEXT@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ OPENAL_CFLAGS = @OPENAL_CFLAGS@ OPENAL_LIBS = @OPENAL_LIBS@ OPUS_CFLAGS = @OPUS_CFLAGS@ @@ -2933,10 +3149,10 @@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ RANLIB = @RANLIB@ +RC = @RC@ ROAR_CFLAGS = @ROAR_CFLAGS@ ROAR_LIBS = @ROAR_LIBS@ -SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@ -SAMPLERATE_LIBS = @SAMPLERATE_LIBS@ +SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHINE_CFLAGS = @SHINE_CFLAGS@ @@ -2949,6 +3165,8 @@ SMBCLIENT_LIBS = @SMBCLIENT_LIBS@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ +SNDIO_CFLAGS = @SNDIO_CFLAGS@ +SNDIO_LIBS = @SNDIO_LIBS@ SOXR_CFLAGS = @SOXR_CFLAGS@ SOXR_LIBS = @SOXR_LIBS@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ @@ -2977,6 +3195,7 @@ WILDMIDI_LIBS = @WILDMIDI_LIBS@ WINDRES = @WINDRES@ XMLTO = @XMLTO@ +XRES = @XRES@ YAJL_CFLAGS = @YAJL_CFLAGS@ YAJL_LIBS = @YAJL_LIBS@ ZIP = @ZIP@ @@ -3041,13 +3260,15 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign 1.11 dist-xz subdir-objects -noinst_LIBRARIES = libmpd.a libutil.a libthread.a libsystem.a \ - libevent.a libicu.a libpcm.a libconf.a libtag.a libinput.a \ - libfs.a libplaylist_plugins.a libdecoder.a libfilter_plugins.a \ - libmixer_plugins.a liboutput_plugins.a $(am__append_3) \ - $(am__append_13) $(am__append_17) $(am__append_21) \ - $(am__append_25) $(am__append_31) $(am__append_45) \ - $(am__append_53) +APK_NAME = mpd +noinst_LIBRARIES = libmpd.a libutil.a libthread.a libnet.a libsystem.a \ + libevent.a libicu.a libpcm.a libbasic.a libconf.a libtag.a \ + libinput.a libfs.a libplaylist_plugins.a libdecoder.a \ + libfilter_plugins.a libmixer_plugins.a liboutput_plugins.a \ + $(am__append_4) $(am__append_13) $(am__append_18) \ + $(am__append_23) $(am__append_27) $(am__append_31) \ + $(am__append_37) $(am__append_52) $(am__append_60) \ + $(am__append_99) libmpd_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(LIBMPDCLIENT_CFLAGS) \ $(AVAHI_CFLAGS) \ @@ -3057,27 +3278,24 @@ src_mpd_LDADD = libmpd.a $(NEIGHBOR_LIBS) $(DB_LIBS) $(STORAGE_LIBS) \ $(PLAYLIST_LIBS) $(AVAHI_LIBS) $(LIBWRAP_LDFLAGS) \ $(SQLITE_LIBS) $(DECODER_LIBS) $(INPUT_LIBS) $(ARCHIVE_LIBS) \ - $(TAG_LIBS) $(OUTPUT_LIBS) $(FILTER_LIBS) $(ENCODER_LIBS) \ - $(MIXER_LIBS) libconf.a libevent.a libthread.a libsystem.a \ - $(ICU_LDADD) libutil.a $(FS_LIBS) $(SYSTEMD_DAEMON_LIBS) \ - $(GLIB_LIBS) $(am__append_4) + $(OUTPUT_LIBS) $(TAG_LIBS) $(FILTER_LIBS) $(ENCODER_LIBS) \ + $(MIXER_LIBS) libconf.a libbasic.a libevent.a libthread.a \ + libnet.a $(FS_LIBS) libsystem.a libutil.a $(ICU_LDADD) \ + $(SYSTEMD_DAEMON_LIBS) $(am__append_5) src_mpd_SOURCES = \ src/Main.cxx src/Main.hxx libmpd_a_SOURCES = $(OUTPUT_API_SRC) $(MIXER_API_SRC) src/check.h \ src/Compiler.h src/open.h src/poison.h src/notify.cxx \ - src/notify.hxx src/AudioConfig.cxx src/AudioConfig.hxx \ - src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ - src/AudioFormat.cxx src/AudioFormat.hxx src/AudioParser.cxx \ - src/AudioParser.hxx src/protocol/Ack.cxx src/protocol/Ack.hxx \ + src/notify.hxx src/protocol/Ack.cxx src/protocol/Ack.hxx \ src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \ src/protocol/Result.cxx src/protocol/Result.hxx \ - src/command/CommandResult.hxx src/command/CommandError.cxx \ - src/command/CommandError.hxx src/command/AllCommands.cxx \ - src/command/AllCommands.hxx src/command/QueueCommands.cxx \ - src/command/QueueCommands.hxx src/command/TagCommands.cxx \ - src/command/TagCommands.hxx src/command/PlayerCommands.cxx \ - src/command/PlayerCommands.hxx \ + src/command/Request.hxx src/command/CommandResult.hxx \ + src/command/CommandError.cxx src/command/CommandError.hxx \ + src/command/AllCommands.cxx src/command/AllCommands.hxx \ + src/command/QueueCommands.cxx src/command/QueueCommands.hxx \ + src/command/TagCommands.cxx src/command/TagCommands.hxx \ + src/command/PlayerCommands.cxx src/command/PlayerCommands.hxx \ src/command/PlaylistCommands.cxx \ src/command/PlaylistCommands.hxx src/command/FileCommands.cxx \ src/command/FileCommands.hxx src/command/OutputCommands.cxx \ @@ -3086,18 +3304,18 @@ src/command/OtherCommands.hxx \ src/command/CommandListBuilder.cxx \ src/command/CommandListBuilder.hxx src/Idle.cxx src/Idle.hxx \ - src/CrossFade.cxx src/CrossFade.hxx \ + src/IdleFlags.cxx src/IdleFlags.hxx \ src/decoder/DecoderError.cxx src/decoder/DecoderError.hxx \ src/decoder/DecoderThread.cxx src/decoder/DecoderThread.hxx \ src/decoder/DecoderCommand.hxx src/decoder/DecoderControl.cxx \ - src/decoder/DecoderControl.hxx src/decoder/DecoderAPI.cxx \ - src/decoder/DecoderAPI.hxx src/decoder/DecoderPlugin.hxx \ - src/decoder/DecoderInternal.cxx \ - src/decoder/DecoderInternal.hxx src/decoder/DecoderPrint.cxx \ + src/decoder/DecoderControl.hxx src/decoder/Client.hxx \ + src/decoder/DecoderPlugin.hxx src/decoder/Bridge.cxx \ + src/decoder/Bridge.hxx src/decoder/DecoderPrint.cxx \ src/decoder/DecoderPrint.hxx src/filter/FilterConfig.cxx \ src/filter/FilterConfig.hxx src/filter/FilterPlugin.cxx \ src/filter/FilterPlugin.hxx src/filter/FilterInternal.hxx \ src/filter/FilterRegistry.cxx src/filter/FilterRegistry.hxx \ + src/filter/Observer.cxx src/filter/Observer.hxx \ src/client/Client.cxx src/client/Client.hxx \ src/client/ClientInternal.hxx src/client/ClientEvent.cxx \ src/client/ClientExpire.cxx src/client/ClientGlobal.cxx \ @@ -3106,24 +3324,24 @@ src/client/ClientProcess.cxx src/client/ClientRead.cxx \ src/client/ClientWrite.cxx src/client/ClientMessage.cxx \ src/client/ClientMessage.hxx src/client/ClientSubscribe.cxx \ - src/client/ClientFile.cxx src/Listen.cxx src/Listen.hxx \ + src/client/ClientFile.cxx src/client/Response.cxx \ + src/client/Response.hxx src/Listen.cxx src/Listen.hxx \ src/LogInit.cxx src/LogInit.hxx src/LogBackend.cxx \ src/LogBackend.hxx src/Log.cxx src/Log.hxx src/LogV.hxx \ src/LogLevel.hxx src/ls.cxx src/ls.hxx src/IOThread.cxx \ src/IOThread.hxx src/Instance.cxx src/Instance.hxx \ - src/win32/Win32Main.cxx src/GlobalEvents.cxx \ - src/GlobalEvents.hxx src/MixRampInfo.hxx src/MusicBuffer.cxx \ - src/MusicBuffer.hxx src/MusicPipe.cxx src/MusicPipe.hxx \ - src/MusicChunk.cxx src/MusicChunk.hxx src/Mapper.cxx \ - src/Mapper.hxx src/Partition.cxx src/Partition.hxx \ - src/Permission.cxx src/Permission.hxx src/PlayerThread.cxx \ - src/PlayerThread.hxx src/PlayerControl.cxx \ - src/PlayerControl.hxx src/PlayerListener.hxx \ - src/PlaylistError.cxx src/PlaylistError.hxx \ - src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \ - src/PlaylistPrint.cxx src/PlaylistPrint.hxx \ - src/PlaylistSave.cxx src/PlaylistSave.hxx \ - src/playlist/PlaylistStream.cxx \ + src/win32/Win32Main.cxx src/MixRampInfo.hxx \ + src/MusicBuffer.cxx src/MusicBuffer.hxx src/MusicPipe.cxx \ + src/MusicPipe.hxx src/MusicChunk.cxx src/MusicChunk.hxx \ + src/Mapper.cxx src/Mapper.hxx src/Partition.cxx \ + src/Partition.hxx src/Permission.cxx src/Permission.hxx \ + src/player/CrossFade.cxx src/player/CrossFade.hxx \ + src/player/Thread.cxx src/player/Thread.hxx \ + src/player/Control.cxx src/player/Control.hxx \ + src/player/Listener.hxx src/PlaylistError.cxx \ + src/PlaylistError.hxx src/PlaylistPrint.cxx \ + src/PlaylistPrint.hxx src/PlaylistSave.cxx \ + src/PlaylistSave.hxx src/playlist/PlaylistStream.cxx \ src/playlist/PlaylistStream.hxx \ src/playlist/PlaylistMapper.cxx \ src/playlist/PlaylistMapper.hxx src/playlist/PlaylistAny.cxx \ @@ -3139,32 +3357,42 @@ src/queue/Playlist.cxx src/queue/Playlist.hxx \ src/queue/PlaylistControl.cxx src/queue/PlaylistEdit.cxx \ src/queue/PlaylistTag.cxx src/queue/PlaylistState.cxx \ - src/queue/PlaylistState.hxx src/ReplayGainConfig.cxx \ - src/ReplayGainConfig.hxx src/ReplayGainInfo.cxx \ - src/ReplayGainInfo.hxx src/DetachedSong.cxx \ - src/DetachedSong.hxx src/SongUpdate.cxx src/SongLoader.cxx \ - src/SongLoader.hxx src/SongPrint.cxx src/SongPrint.hxx \ - src/SongSave.cxx src/SongSave.hxx src/StateFile.cxx \ - src/StateFile.hxx src/Stats.cxx src/Stats.hxx src/TagPrint.cxx \ - src/TagPrint.hxx src/TagSave.cxx src/TagSave.hxx \ - src/TagFile.cxx src/TagFile.hxx src/TagStream.cxx \ - src/TagStream.hxx src/TimePrint.cxx src/TimePrint.hxx \ - src/mixer/Volume.cxx src/mixer/Volume.hxx src/Chrono.hxx \ - src/SongFilter.cxx src/SongFilter.hxx src/PlaylistFile.cxx \ - src/PlaylistFile.hxx $(am__append_1) $(am__append_2) \ - $(am__append_5) $(am__append_6) $(am__append_16) \ - $(am__append_26) $(am__append_62) $(am__append_63) \ - $(am__append_64) + src/queue/PlaylistState.hxx src/queue/Listener.hxx \ + src/PluginUnavailable.hxx src/ReplayGainGlobal.cxx \ + src/ReplayGainGlobal.hxx src/DetachedSong.cxx \ + src/DetachedSong.hxx src/LocateUri.cxx src/LocateUri.hxx \ + src/SongUpdate.cxx src/SongLoader.cxx src/SongLoader.hxx \ + src/SongPrint.cxx src/SongPrint.hxx src/SongSave.cxx \ + src/SongSave.hxx src/StateFile.cxx src/StateFile.hxx \ + src/Stats.cxx src/Stats.hxx src/TagPrint.cxx src/TagPrint.hxx \ + src/TagSave.cxx src/TagSave.hxx src/TagFile.cxx \ + src/TagFile.hxx src/TagStream.cxx src/TagStream.hxx \ + src/TimePrint.cxx src/TimePrint.hxx src/mixer/Volume.cxx \ + src/mixer/Volume.hxx src/Chrono.hxx src/SongFilter.cxx \ + src/SongFilter.hxx src/PlaylistFile.cxx src/PlaylistFile.hxx \ + $(am__append_1) $(am__append_2) $(am__append_3) \ + $(am__append_6) $(am__append_7) $(am__append_22) \ + $(am__append_32) $(am__append_69) $(am__append_70) \ + $(am__append_71) +CURL_SOURCES = \ + src/lib/curl/Version.cxx src/lib/curl/Version.hxx \ + src/lib/curl/Global.cxx src/lib/curl/Global.hxx \ + src/lib/curl/Request.cxx src/lib/curl/Request.hxx \ + src/lib/curl/Handler.hxx \ + src/lib/curl/Easy.hxx \ + src/lib/curl/Multi.hxx \ + src/lib/curl/Slist.hxx + UPNP_SOURCES = \ src/lib/upnp/Init.cxx src/lib/upnp/Init.hxx \ src/lib/upnp/ClientInit.cxx src/lib/upnp/ClientInit.hxx \ src/lib/upnp/Device.cxx src/lib/upnp/Device.hxx \ src/lib/upnp/ContentDirectoryService.cxx src/lib/upnp/ContentDirectoryService.hxx \ src/lib/upnp/Discovery.cxx src/lib/upnp/Discovery.hxx \ - src/lib/upnp/Domain.cxx src/lib/upnp/Domain.hxx \ src/lib/upnp/ixmlwrap.cxx src/lib/upnp/ixmlwrap.hxx \ src/lib/upnp/Callback.hxx \ src/lib/upnp/Util.cxx src/lib/upnp/Util.hxx \ + src/lib/upnp/UniqueIxml.hxx \ src/lib/upnp/WorkQueue.hxx \ src/lib/upnp/Action.hxx @@ -3193,30 +3421,48 @@ @ANDROID_TRUE@ android/build/build.xml @ANDROID_TRUE@ANDROID_SDK_BUILD_TOOLS_VERSION = 20.0.0 -@HAVE_WINDOWS_TRUE@noinst_DATA = src/win32/mpd_win32_rc.rc -@HAVE_WINDOWS_TRUE@EXTRA_src_mpd_DEPENDENCIES = src/win32/mpd_win32_rc.$(OBJEXT) -@HAVE_WINDOWS_TRUE@src_mpd_LDFLAGS = -Wl,src/win32/mpd_win32_rc.$(OBJEXT) +@ENABLE_HAIKU_TRUE@noinst_DATA = src/haiku/mpd.rdef +@HAVE_WINDOWS_TRUE@noinst_DATA = win32/res/mpd.rc +@ENABLE_HAIKU_TRUE@EXTRA_src_mpd_DEPENDENCIES = src/haiku/mpd.rsrc +@HAVE_WINDOWS_TRUE@EXTRA_src_mpd_DEPENDENCIES = win32/res/mpd.$(OBJEXT) +@HAVE_WINDOWS_TRUE@src_mpd_LDFLAGS = -Wl,win32/res/mpd.$(OBJEXT) # Generic utility library libutil_a_SOURCES = \ + src/util/Exception.cxx src/util/Exception.hxx \ + src/util/RuntimeError.hxx \ src/util/Macros.hxx \ + src/util/BindMethod.hxx \ src/util/Cast.hxx \ src/util/Clamp.hxx \ + src/util/DeleteDisposer.hxx \ src/util/Alloc.cxx src/util/Alloc.hxx \ + src/util/AllocatedArray.hxx \ src/util/VarSize.hxx \ src/util/ScopeExit.hxx \ - src/util/Error.cxx src/util/Error.hxx \ src/util/Domain.hxx \ src/util/ReusableArray.hxx \ src/util/ASCII.hxx \ src/util/UTF8.cxx src/util/UTF8.hxx \ src/util/CharUtil.hxx \ src/util/NumberParser.hxx \ + src/util/MimeType.cxx src/util/MimeType.hxx \ + src/util/StringBuffer.hxx \ + src/util/StringPointer.hxx \ + src/util/StringView.cxx src/util/StringView.hxx \ + src/util/AllocatedString.cxx src/util/AllocatedString.hxx \ src/util/StringUtil.cxx src/util/StringUtil.hxx \ + src/util/StringCompare.cxx src/util/StringCompare.hxx \ + src/util/WStringCompare.cxx src/util/WStringCompare.hxx \ + src/util/StringAPI.hxx \ + src/util/WStringAPI.hxx \ + src/util/DivideString.cxx src/util/DivideString.hxx \ src/util/SplitString.cxx src/util/SplitString.hxx \ + src/util/IterableSplitString.hxx \ src/util/FormatString.cxx src/util/FormatString.hxx \ src/util/Tokenizer.cxx src/util/Tokenizer.hxx \ src/util/TextFile.hxx \ + src/util/TimeParser.cxx src/util/TimeParser.hxx \ src/util/UriUtil.cxx src/util/UriUtil.hxx \ src/util/Manual.hxx \ src/util/RefCount.hxx \ @@ -3233,12 +3479,13 @@ src/util/OptionParser.cxx src/util/OptionParser.hxx \ src/util/OptionDef.hxx \ src/util/ByteReverse.cxx src/util/ByteReverse.hxx \ + src/util/format.c src/util/format.h \ src/util/bit_reverse.c src/util/bit_reverse.h # Multi-threading library libthread_a_SOURCES = \ - src/thread/Util.hxx \ + src/thread/Util.cxx src/thread/Util.hxx \ src/thread/Name.hxx \ src/thread/Slack.hxx \ src/thread/Mutex.hxx \ @@ -3251,14 +3498,25 @@ src/thread/Id.hxx +# Networking library +libnet_a_SOURCES = \ + src/net/Features.hxx \ + src/net/ToString.cxx src/net/ToString.hxx \ + src/net/Resolver.cxx src/net/Resolver.hxx \ + src/net/StaticSocketAddress.cxx src/net/StaticSocketAddress.hxx \ + src/net/AllocatedSocketAddress.cxx src/net/AllocatedSocketAddress.hxx \ + src/net/SocketAddress.cxx src/net/SocketAddress.hxx \ + src/net/SocketUtil.cxx src/net/SocketUtil.hxx \ + src/net/SocketError.cxx src/net/SocketError.hxx + + # System library libsystem_a_SOURCES = \ src/system/ByteOrder.hxx \ + src/system/Error.hxx \ src/system/FatalError.cxx src/system/FatalError.hxx \ + src/system/FileDescriptor.cxx src/system/FileDescriptor.hxx \ src/system/fd_util.c src/system/fd_util.h \ - src/system/SocketUtil.cxx src/system/SocketUtil.hxx \ - src/system/SocketError.cxx src/system/SocketError.hxx \ - src/system/Resolver.cxx src/system/Resolver.hxx \ src/system/EventPipe.cxx src/system/EventPipe.hxx \ src/system/EventFD.cxx src/system/EventFD.hxx \ src/system/SignalFD.cxx src/system/SignalFD.hxx \ @@ -3279,6 +3537,8 @@ src/event/TimeoutMonitor.hxx src/event/TimeoutMonitor.cxx \ src/event/IdleMonitor.hxx src/event/IdleMonitor.cxx \ src/event/DeferredMonitor.hxx src/event/DeferredMonitor.cxx \ + src/event/DeferredCall.hxx \ + src/event/MaskMonitor.hxx src/event/MaskMonitor.cxx \ src/event/SocketMonitor.cxx src/event/SocketMonitor.hxx \ src/event/BufferedSocket.cxx src/event/BufferedSocket.hxx \ src/event/FullyBufferedSocket.cxx src/event/FullyBufferedSocket.hxx \ @@ -3290,45 +3550,61 @@ # UTF-8 library libicu_a_SOURCES = src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \ - src/lib/icu/Error.cxx src/lib/icu/Error.hxx $(am__append_7) + src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx \ + $(am__append_8) $(am__append_9) libicu_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(ICU_CFLAGS) ICU_LDADD = libicu.a $(ICU_LIBS) # PCM library -libpcm_a_SOURCES = src/pcm/Domain.cxx src/pcm/Domain.hxx \ - src/pcm/Traits.hxx src/pcm/Interleave.cxx \ - src/pcm/Interleave.hxx src/pcm/PcmBuffer.cxx \ - src/pcm/PcmBuffer.hxx src/pcm/PcmExport.cxx \ - src/pcm/PcmExport.hxx src/pcm/PcmConvert.cxx \ - src/pcm/PcmConvert.hxx src/pcm/PcmDop.cxx src/pcm/PcmDop.hxx \ - src/pcm/Volume.cxx src/pcm/Volume.hxx src/pcm/Silence.cxx \ - src/pcm/Silence.hxx src/pcm/PcmMix.cxx src/pcm/PcmMix.hxx \ - src/pcm/PcmChannels.cxx src/pcm/PcmChannels.hxx \ - src/pcm/PcmPack.cxx src/pcm/PcmPack.hxx src/pcm/PcmFormat.cxx \ +libpcm_a_SOURCES = src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ + src/AudioFormat.cxx src/AudioFormat.hxx src/AudioParser.cxx \ + src/AudioParser.hxx src/pcm/SampleFormat.cxx \ + src/pcm/SampleFormat.hxx src/pcm/Traits.hxx \ + src/pcm/Interleave.cxx src/pcm/Interleave.hxx \ + src/pcm/PcmBuffer.cxx src/pcm/PcmBuffer.hxx \ + src/pcm/PcmExport.cxx src/pcm/PcmExport.hxx \ + src/pcm/PcmConvert.cxx src/pcm/PcmConvert.hxx \ + src/pcm/PcmDop.cxx src/pcm/PcmDop.hxx src/pcm/Volume.cxx \ + src/pcm/Volume.hxx src/pcm/Silence.cxx src/pcm/Silence.hxx \ + src/pcm/PcmMix.cxx src/pcm/PcmMix.hxx src/pcm/PcmChannels.cxx \ + src/pcm/PcmChannels.hxx src/pcm/PcmPack.cxx \ + src/pcm/PcmPack.hxx src/pcm/PcmFormat.cxx \ src/pcm/PcmFormat.hxx src/pcm/FloatConvert.hxx \ src/pcm/ShiftConvert.hxx src/pcm/Neon.hxx \ src/pcm/FormatConverter.cxx src/pcm/FormatConverter.hxx \ src/pcm/ChannelsConverter.cxx src/pcm/ChannelsConverter.hxx \ - src/pcm/Resampler.hxx src/pcm/GlueResampler.cxx \ - src/pcm/GlueResampler.hxx src/pcm/FallbackResampler.cxx \ - src/pcm/FallbackResampler.hxx src/pcm/ConfiguredResampler.cxx \ + src/pcm/Order.cxx src/pcm/Order.hxx src/pcm/Resampler.hxx \ + src/pcm/GlueResampler.cxx src/pcm/GlueResampler.hxx \ + src/pcm/FallbackResampler.cxx src/pcm/FallbackResampler.hxx \ + src/pcm/ConfiguredResampler.cxx \ src/pcm/ConfiguredResampler.hxx src/pcm/PcmDither.cxx \ src/pcm/PcmDither.hxx src/pcm/PcmPrng.hxx src/pcm/PcmUtils.hxx \ - $(am__append_8) $(am__append_9) $(am__append_10) + $(am__append_10) $(am__append_11) $(am__append_12) libpcm_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(SOXR_CFLAGS) \ - $(SAMPLERATE_CFLAGS) + $(LIBSAMPLERATE_CFLAGS) PCM_LIBS = \ libpcm.a \ $(SOXR_LIBS) \ - $(SAMPLERATE_LIBS) + $(LIBSAMPLERATE_LIBS) + +@HAVE_XIPH_TRUE@libxiph_a_SOURCES = src/lib/xiph/VorbisComment.hxx \ +@HAVE_XIPH_TRUE@ src/lib/xiph/VorbisComments.cxx \ +@HAVE_XIPH_TRUE@ src/lib/xiph/VorbisComments.hxx \ +@HAVE_XIPH_TRUE@ src/lib/xiph/XiphTags.cxx \ +@HAVE_XIPH_TRUE@ src/lib/xiph/XiphTags.hxx $(am__append_14) +@HAVE_XIPH_TRUE@libxiph_a_CPPFLAGS = $(AM_CPPFLAGS) \ +@HAVE_XIPH_TRUE@ $(OGG_CFLAGS) + +@HAVE_XIPH_TRUE@XIPH_LIBS = libxiph.a \ +@HAVE_XIPH_TRUE@ $(OGG_LIBS) # File system library -FS_LIBS = libfs.a $(am__append_12) +FS_LIBS = libfs.a $(am__append_16) $(am__append_17) libfs_a_SOURCES = src/fs/io/Reader.hxx src/fs/io/PeekReader.cxx \ src/fs/io/PeekReader.hxx src/fs/io/FileReader.cxx \ src/fs/io/FileReader.hxx src/fs/io/BufferedReader.cxx \ @@ -3342,11 +3618,13 @@ src/fs/Traits.hxx src/fs/Config.cxx src/fs/Config.hxx \ src/fs/Charset.cxx src/fs/Charset.hxx src/fs/Path.cxx \ src/fs/Path2.cxx src/fs/Path.hxx src/fs/AllocatedPath.cxx \ - src/fs/AllocatedPath.hxx src/fs/FileSystem.cxx \ - src/fs/FileSystem.hxx src/fs/StandardDirectory.cxx \ - src/fs/StandardDirectory.hxx src/fs/CheckFile.cxx \ - src/fs/CheckFile.hxx src/fs/DirectoryReader.hxx \ - $(am__append_11) + src/fs/AllocatedPath.hxx src/fs/NarrowPath.hxx \ + src/fs/FileSystem.cxx src/fs/FileSystem.hxx \ + src/fs/FileInfo.hxx src/fs/Glob.hxx \ + src/fs/StandardDirectory.cxx src/fs/StandardDirectory.hxx \ + src/fs/CheckFile.cxx src/fs/CheckFile.hxx \ + src/fs/DirectoryReader.cxx src/fs/DirectoryReader.hxx \ + $(am__append_15) libfs_a_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) # Storage library @@ -3364,8 +3642,7 @@ src/lib/nfs/Glue.cxx src/lib/nfs/Glue.hxx \ src/lib/nfs/Base.cxx src/lib/nfs/Base.hxx \ src/lib/nfs/FileReader.cxx src/lib/nfs/FileReader.hxx \ - src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx \ - src/lib/nfs/Domain.cxx src/lib/nfs/Domain.hxx + src/lib/nfs/Blocking.cxx src/lib/nfs/Blocking.hxx @ENABLE_DATABASE_TRUE@libstorage_a_SOURCES = \ @ENABLE_DATABASE_TRUE@ src/storage/StoragePlugin.hxx \ @@ -3382,13 +3659,16 @@ @ENABLE_DATABASE_TRUE@ src/storage/plugins/LocalStorage.cxx \ @ENABLE_DATABASE_TRUE@ src/storage/plugins/LocalStorage.hxx \ @ENABLE_DATABASE_TRUE@ src/storage/FileInfo.hxx \ -@ENABLE_DATABASE_TRUE@ $(am__append_14) $(am__append_15) +@ENABLE_DATABASE_TRUE@ $(am__append_19) $(am__append_20) \ +@ENABLE_DATABASE_TRUE@ $(am__append_21) @ENABLE_DATABASE_TRUE@libstorage_a_CPPFLAGS = $(AM_CPPFLAGS) \ @ENABLE_DATABASE_TRUE@ $(NFS_CFLAGS) \ @ENABLE_DATABASE_TRUE@ $(SMBCLIENT_CFLAGS) @ENABLE_DATABASE_TRUE@STORAGE_LIBS = \ @ENABLE_DATABASE_TRUE@ libstorage.a \ +@ENABLE_DATABASE_TRUE@ $(CURL_LIBS) \ +@ENABLE_DATABASE_TRUE@ $(EXPAT_LIBS) \ @ENABLE_DATABASE_TRUE@ $(NFS_LIBS) \ @ENABLE_DATABASE_TRUE@ $(SMBCLIENT_LIBS) @@ -3401,13 +3681,13 @@ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/neighbor/Listener.hxx \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/neighbor/Explorer.hxx \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ src/neighbor/NeighborPlugin.hxx \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__append_18) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__append_19) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__append_24) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(am__append_25) @ENABLE_NEIGHBOR_PLUGINS_TRUE@libneighbor_a_CPPFLAGS = $(AM_CPPFLAGS) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@ $(SMBCLIENT_CFLAGS) @ENABLE_NEIGHBOR_PLUGINS_TRUE@NEIGHBOR_LIBS = $(SMBCLIENT_LIBS) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@ libneighbor.a $(am__append_20) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@ libneighbor.a $(am__append_26) @ENABLE_DATABASE_TRUE@libdb_plugins_a_SOURCES = \ @ENABLE_DATABASE_TRUE@ src/PlaylistDatabase.cxx \ @ENABLE_DATABASE_TRUE@ src/PlaylistDatabase.hxx \ @@ -3419,8 +3699,6 @@ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/DatabaseSave.hxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/DirectorySave.cxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/DirectorySave.hxx \ -@ENABLE_DATABASE_TRUE@ src/db/plugins/LazyDatabase.cxx \ -@ENABLE_DATABASE_TRUE@ src/db/plugins/LazyDatabase.hxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/Directory.cxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/Directory.hxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/Song.cxx \ @@ -3432,9 +3710,9 @@ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/PrefixedLightSong.hxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/SimpleDatabasePlugin.cxx \ @ENABLE_DATABASE_TRUE@ src/db/plugins/simple/SimpleDatabasePlugin.hxx \ -@ENABLE_DATABASE_TRUE@ $(am__append_22) $(am__append_23) +@ENABLE_DATABASE_TRUE@ $(am__append_28) $(am__append_29) @ENABLE_DATABASE_TRUE@DB_LIBS = libdb_plugins.a $(LIBMPDCLIENT_LIBS) \ -@ENABLE_DATABASE_TRUE@ $(am__append_24) +@ENABLE_DATABASE_TRUE@ $(am__append_30) @ENABLE_ARCHIVE_TRUE@libarchive_a_SOURCES = \ @ENABLE_ARCHIVE_TRUE@ src/archive/ArchiveDomain.cxx \ @ENABLE_ARCHIVE_TRUE@ src/archive/ArchiveDomain.hxx \ @@ -3448,8 +3726,8 @@ @ENABLE_ARCHIVE_TRUE@ src/archive/ArchiveFile.hxx \ @ENABLE_ARCHIVE_TRUE@ src/input/plugins/ArchiveInputPlugin.cxx \ @ENABLE_ARCHIVE_TRUE@ src/input/plugins/ArchiveInputPlugin.hxx \ -@ENABLE_ARCHIVE_TRUE@ $(am__append_27) $(am__append_28) \ -@ENABLE_ARCHIVE_TRUE@ $(am__append_29) +@ENABLE_ARCHIVE_TRUE@ $(am__append_33) $(am__append_34) \ +@ENABLE_ARCHIVE_TRUE@ $(am__append_35) @ENABLE_ARCHIVE_TRUE@libarchive_a_CPPFLAGS = $(AM_CPPFLAGS) \ @ENABLE_ARCHIVE_TRUE@ $(BZ2_CFLAGS) \ @ENABLE_ARCHIVE_TRUE@ $(ISO9660_CFLAGS) \ @@ -3462,12 +3740,19 @@ @ENABLE_ARCHIVE_TRUE@ $(ISO9660_LIBS) \ @ENABLE_ARCHIVE_TRUE@ $(ZZIP_LIBS) +libbasic_a_SOURCES = \ + src/ReplayGainConfig.hxx \ + src/ReplayGainMode.cxx src/ReplayGainMode.hxx \ + src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx + # configuration library libconf_a_SOURCES = \ src/config/ConfigDefaults.hxx \ src/config/ConfigPath.cxx src/config/ConfigPath.hxx \ - src/config/ConfigData.cxx src/config/ConfigData.hxx \ + src/config/Data.cxx src/config/Data.hxx \ + src/config/Block.cxx src/config/Block.hxx \ + src/config/Param.cxx src/config/Param.hxx \ src/config/ConfigParser.cxx src/config/ConfigParser.hxx \ src/config/ConfigGlobal.cxx src/config/ConfigGlobal.hxx \ src/config/ConfigFile.cxx src/config/ConfigFile.hxx \ @@ -3487,43 +3772,47 @@ libtag_a_SOURCES = src/tag/TagType.h src/tag/Tag.cxx src/tag/Tag.hxx \ src/tag/TagBuilder.cxx src/tag/TagBuilder.hxx \ src/tag/TagItem.hxx src/tag/TagHandler.cxx \ - src/tag/TagHandler.hxx src/tag/TagSettings.c \ - src/tag/TagSettings.h src/tag/TagConfig.cxx \ + src/tag/TagHandler.hxx src/tag/Mask.hxx src/tag/Settings.cxx \ + src/tag/Settings.hxx src/tag/TagConfig.cxx \ src/tag/TagConfig.hxx src/tag/TagNames.c src/tag/TagString.cxx \ src/tag/TagString.hxx src/tag/TagPool.cxx src/tag/TagPool.hxx \ src/tag/TagTable.cxx src/tag/TagTable.hxx src/tag/Set.cxx \ - src/tag/Set.hxx src/tag/VorbisComment.cxx \ - src/tag/VorbisComment.hxx src/tag/ReplayGain.cxx \ - src/tag/ReplayGain.hxx src/tag/MixRamp.cxx src/tag/MixRamp.hxx \ - src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \ - src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \ - src/tag/ApeTag.cxx src/tag/ApeTag.hxx $(am__append_30) -@HAVE_FFMPEG_TRUE@libffmpeg_a_SOURCES = \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Init.cxx src/lib/ffmpeg/Init.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Time.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Buffer.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/LogError.cxx src/lib/ffmpeg/LogError.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/LogCallback.cxx src/lib/ffmpeg/LogCallback.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Error.cxx src/lib/ffmpeg/Error.hxx \ -@HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Domain.cxx src/lib/ffmpeg/Domain.hxx + src/tag/Set.hxx src/tag/Format.cxx src/tag/Format.hxx \ + src/tag/VorbisComment.cxx src/tag/VorbisComment.hxx \ + src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \ + src/tag/MixRamp.cxx src/tag/MixRamp.hxx src/tag/Generic.cxx \ + src/tag/Generic.hxx src/tag/ApeLoader.cxx \ + src/tag/ApeLoader.hxx src/tag/ApeReplayGain.cxx \ + src/tag/ApeReplayGain.hxx src/tag/ApeTag.cxx \ + src/tag/ApeTag.hxx $(am__append_36) +@ENABLE_FFMPEG_TRUE@libffmpeg_a_SOURCES = \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/Init.cxx src/lib/ffmpeg/Init.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/Time.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/Buffer.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/LogError.cxx src/lib/ffmpeg/LogError.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/LogCallback.cxx src/lib/ffmpeg/LogCallback.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/Error.cxx src/lib/ffmpeg/Error.hxx \ +@ENABLE_FFMPEG_TRUE@ src/lib/ffmpeg/Domain.cxx src/lib/ffmpeg/Domain.hxx -@HAVE_FFMPEG_TRUE@libffmpeg_a_CPPFLAGS = $(AM_CPPFLAGS) \ -@HAVE_FFMPEG_TRUE@ $(FFMPEG_CFLAGS) +@ENABLE_FFMPEG_TRUE@libffmpeg_a_CPPFLAGS = $(AM_CPPFLAGS) \ +@ENABLE_FFMPEG_TRUE@ $(FFMPEG_CFLAGS) -@HAVE_FFMPEG_TRUE@FFMPEG_LIBS2 = libffmpeg.a $(FFMPEG_LIBS) +@ENABLE_FFMPEG_TRUE@FFMPEG_LIBS2 = libffmpeg.a $(FFMPEG_LIBS) # decoder plugins libdecoder_a_SOURCES = src/decoder/plugins/PcmDecoderPlugin.cxx \ src/decoder/plugins/PcmDecoderPlugin.hxx \ + src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx \ + src/decoder/Reader.cxx src/decoder/Reader.hxx \ src/decoder/DecoderBuffer.cxx src/decoder/DecoderBuffer.hxx \ src/decoder/DecoderPlugin.cxx src/decoder/DecoderList.cxx \ - src/decoder/DecoderList.hxx $(am__append_32) $(am__append_33) \ - $(am__append_34) $(am__append_35) $(am__append_36) \ - $(am__append_37) $(am__append_38) $(am__append_39) \ + src/decoder/DecoderList.hxx $(am__append_38) $(am__append_39) \ $(am__append_40) $(am__append_41) $(am__append_42) \ - $(am__append_43) $(am__append_44) $(am__append_47) \ - $(am__append_48) $(am__append_49) $(am__append_50) \ - $(am__append_51) $(am__append_52) + $(am__append_43) $(am__append_44) $(am__append_45) \ + $(am__append_46) $(am__append_47) $(am__append_48) \ + $(am__append_49) $(am__append_50) $(am__append_51) \ + $(am__append_54) $(am__append_55) $(am__append_56) \ + $(am__append_57) $(am__append_58) $(am__append_59) libdecoder_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(VORBIS_CFLAGS) $(TREMOR_CFLAGS) \ $(patsubst -I%/FLAC,-I%,$(FLAC_CFLAGS)) \ @@ -3543,18 +3832,18 @@ $(ADPLUG_CFLAGS) \ $(FAAD_CFLAGS) -DECODER_LIBS = libdecoder.a $(VORBIS_LIBS) $(TREMOR_LIBS) $(FLAC_LIBS) \ - $(SNDFILE_LIBS) $(AUDIOFILE_LIBS) $(LIBMIKMOD_LIBS) \ - $(GME_LIBS) $(SIDPLAY_LIBS) $(FLUIDSYNTH_LIBS) \ - $(WILDMIDI_LIBS) $(WAVPACK_LIBS) $(MAD_LIBS) $(MPG123_LIBS) \ - $(OPUS_LIBS) $(FFMPEG_LIBS2) $(MPCDEC_LIBS) $(ADPLUG_LIBS) \ - $(FAAD_LIBS) $(am__append_46) -@HAVE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_SOURCES = \ -@HAVE_MODPLUG_TRUE@ src/decoder/plugins/ModplugDecoderPlugin.cxx \ -@HAVE_MODPLUG_TRUE@ src/decoder/plugins/ModplugDecoderPlugin.hxx +DECODER_LIBS = libdecoder.a $(XIPH_LIBS) $(VORBIS_LIBS) $(TREMOR_LIBS) \ + $(FLAC_LIBS) $(SNDFILE_LIBS) $(AUDIOFILE_LIBS) \ + $(LIBMIKMOD_LIBS) $(GME_LIBS) $(SIDPLAY_LIBS) \ + $(FLUIDSYNTH_LIBS) $(WILDMIDI_LIBS) $(WAVPACK_LIBS) \ + $(MAD_LIBS) $(MPG123_LIBS) $(OPUS_LIBS) $(FFMPEG_LIBS2) \ + $(MPCDEC_LIBS) $(ADPLUG_LIBS) $(FAAD_LIBS) $(am__append_53) +@ENABLE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_SOURCES = \ +@ENABLE_MODPLUG_TRUE@ src/decoder/plugins/ModplugDecoderPlugin.cxx \ +@ENABLE_MODPLUG_TRUE@ src/decoder/plugins/ModplugDecoderPlugin.hxx -@HAVE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_CXXFLAGS = $(AM_CXXFLAGS) $(MODPLUG_CFLAGS) -@HAVE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_CPPFLAGS = $(AM_CPPFLAGS) +@ENABLE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_CXXFLAGS = $(AM_CXXFLAGS) $(MODPLUG_CFLAGS) +@ENABLE_MODPLUG_TRUE@libmodplug_decoder_plugin_a_CPPFLAGS = $(AM_CPPFLAGS) @ENABLE_ENCODER_TRUE@libencoder_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ @ENABLE_ENCODER_TRUE@ $(LAME_CFLAGS) \ @ENABLE_ENCODER_TRUE@ $(TWOLAME_CFLAGS) \ @@ -3566,6 +3855,7 @@ @ENABLE_ENCODER_FALSE@ENCODER_LIBS = @ENABLE_ENCODER_TRUE@ENCODER_LIBS = \ @ENABLE_ENCODER_TRUE@ libencoder_plugins.a \ +@ENABLE_ENCODER_TRUE@ $(XIPH_LIBS) \ @ENABLE_ENCODER_TRUE@ $(LAME_LIBS) \ @ENABLE_ENCODER_TRUE@ $(TWOLAME_LIBS) \ @ENABLE_ENCODER_TRUE@ $(FLAC_LIBS) \ @@ -3575,16 +3865,18 @@ @ENABLE_ENCODER_TRUE@libencoder_plugins_a_SOURCES = \ @ENABLE_ENCODER_TRUE@ src/encoder/EncoderAPI.hxx \ +@ENABLE_ENCODER_TRUE@ src/encoder/EncoderInterface.hxx \ @ENABLE_ENCODER_TRUE@ src/encoder/EncoderPlugin.hxx \ -@ENABLE_ENCODER_TRUE@ src/encoder/plugins/OggStream.hxx \ +@ENABLE_ENCODER_TRUE@ src/encoder/ToOutputStream.cxx \ +@ENABLE_ENCODER_TRUE@ src/encoder/ToOutputStream.hxx \ @ENABLE_ENCODER_TRUE@ src/encoder/plugins/NullEncoderPlugin.cxx \ @ENABLE_ENCODER_TRUE@ src/encoder/plugins/NullEncoderPlugin.hxx \ @ENABLE_ENCODER_TRUE@ src/encoder/EncoderList.cxx \ @ENABLE_ENCODER_TRUE@ src/encoder/EncoderList.hxx \ -@ENABLE_ENCODER_TRUE@ $(am__append_54) $(am__append_55) \ -@ENABLE_ENCODER_TRUE@ $(am__append_56) $(am__append_57) \ -@ENABLE_ENCODER_TRUE@ $(am__append_58) $(am__append_59) \ -@ENABLE_ENCODER_TRUE@ $(am__append_60) $(am__append_61) +@ENABLE_ENCODER_TRUE@ $(am__append_61) $(am__append_62) \ +@ENABLE_ENCODER_TRUE@ $(am__append_63) $(am__append_64) \ +@ENABLE_ENCODER_TRUE@ $(am__append_65) $(am__append_66) \ +@ENABLE_ENCODER_TRUE@ $(am__append_67) $(am__append_68) # # input plugins @@ -3594,18 +3886,19 @@ src/input/Registry.hxx src/input/Open.cxx \ src/input/LocalOpen.cxx src/input/LocalOpen.hxx \ src/input/Offset.hxx src/input/InputStream.cxx \ - src/input/InputStream.hxx src/input/InputPlugin.hxx \ - src/input/TextInputStream.cxx src/input/TextInputStream.hxx \ - src/input/ThreadInputStream.cxx \ + src/input/InputStream.hxx src/input/Ptr.hxx \ + src/input/InputPlugin.hxx src/input/Reader.cxx \ + src/input/Reader.hxx src/input/TextInputStream.cxx \ + src/input/TextInputStream.hxx src/input/ThreadInputStream.cxx \ src/input/ThreadInputStream.hxx src/input/AsyncInputStream.cxx \ src/input/AsyncInputStream.hxx src/input/ProxyInputStream.cxx \ src/input/ProxyInputStream.hxx \ src/input/plugins/RewindInputPlugin.cxx \ src/input/plugins/RewindInputPlugin.hxx \ src/input/plugins/FileInputPlugin.cxx \ - src/input/plugins/FileInputPlugin.hxx $(am__append_65) \ - $(am__append_67) $(am__append_68) $(am__append_69) \ - $(am__append_70) $(am__append_71) $(am__append_72) + src/input/plugins/FileInputPlugin.hxx $(am__append_72) \ + $(am__append_74) $(am__append_75) $(am__append_76) \ + $(am__append_77) $(am__append_78) $(am__append_79) libinput_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(CURL_CFLAGS) \ $(SMBCLIENT_CFLAGS) \ @@ -3616,24 +3909,32 @@ INPUT_LIBS = libinput.a $(CURL_LIBS) $(SMBCLIENT_LIBS) $(NFS_LIBS) \ $(CDIO_PARANOIA_LIBS) $(FFMPEG_LIBS2) $(MMS_LIBS) \ - $(am__append_66) + $(am__append_73) liboutput_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(AO_CFLAGS) \ $(ALSA_CFLAGS) \ $(JACK_CFLAGS) \ + $(HAIKU_CFLAGS) \ $(OPENAL_CFLAGS) \ $(OPENSSL_CFLAGS) \ $(PULSE_CFLAGS) \ + $(SNDIO_CFLAGS) \ $(SHOUT_CFLAGS) OUTPUT_LIBS = liboutput_plugins.a $(LIBWRAP_LDFLAGS) $(AO_LIBS) \ - $(ALSA_LIBS) $(ROAR_LIBS) $(JACK_LIBS) $(OPENAL_LIBS) \ - $(PULSE_LIBS) $(SHOUT_LIBS) $(am__append_76) + $(ALSA_LIBS) $(ROAR_LIBS) $(JACK_LIBS) $(HAIKU_LIBS) \ + $(OPENAL_LIBS) $(SNDIO_LIBS) $(SHOUT_LIBS) $(am__append_83) \ + $(am__append_100) OUTPUT_API_SRC = \ + src/output/Client.hxx \ src/output/OutputAPI.hxx \ + src/output/Internal.cxx \ src/output/Internal.hxx \ + src/output/Wrapper.hxx \ src/output/Registry.cxx src/output/Registry.hxx \ src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ + src/output/SharedPipeConsumer.cxx src/output/SharedPipeConsumer.hxx \ + src/output/Source.cxx src/output/Source.hxx \ src/output/OutputThread.cxx \ src/output/Domain.cxx src/output/Domain.hxx \ src/output/OutputControl.cxx \ @@ -3646,16 +3947,17 @@ liboutput_plugins_a_SOURCES = src/output/Timer.cxx \ src/output/Timer.hxx src/output/plugins/NullOutputPlugin.cxx \ - src/output/plugins/NullOutputPlugin.hxx $(am__append_73) \ - $(am__append_75) $(am__append_77) $(am__append_79) \ - $(am__append_80) $(am__append_81) $(am__append_82) \ - $(am__append_83) $(am__append_85) $(am__append_86) \ - $(am__append_87) $(am__append_89) $(am__append_90) \ - $(am__append_91) $(am__append_92) $(am__append_93) + src/output/plugins/NullOutputPlugin.hxx $(am__append_80) \ + $(am__append_82) $(am__append_84) $(am__append_86) \ + $(am__append_87) $(am__append_88) $(am__append_89) \ + $(am__append_91) $(am__append_92) $(am__append_93) \ + $(am__append_95) $(am__append_96) $(am__append_97) \ + $(am__append_101) $(am__append_102) $(am__append_103) \ + $(am__append_104) $(am__append_105) MIXER_LIBS = \ libmixer_plugins.a \ $(ALSA_LIBS) \ - $(PULSE_LIBS) + $(PULSE_LIBS2) MIXER_API_SRC = \ src/mixer/Listener.hxx \ @@ -3666,44 +3968,47 @@ src/mixer/MixerAll.cxx \ src/mixer/MixerInternal.hxx -libmixer_plugins_a_SOURCES = \ +libmixer_plugins_a_SOURCES = src/mixer/plugins/NullMixerPlugin.cxx \ src/mixer/plugins/SoftwareMixerPlugin.cxx \ - src/mixer/plugins/SoftwareMixerPlugin.hxx $(am__append_74) \ - $(am__append_78) $(am__append_84) $(am__append_88) \ - $(am__append_94) + src/mixer/plugins/SoftwareMixerPlugin.hxx $(am__append_81) \ + $(am__append_85) $(am__append_90) $(am__append_94) \ + $(am__append_98) $(am__append_106) libmixer_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(ALSA_CFLAGS) \ $(PULSE_CFLAGS) +@ENABLE_PULSE_TRUE@libpulse_a_SOURCES = \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/LockGuard.hxx \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/LogError.cxx src/lib/pulse/LogError.hxx \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/Error.cxx src/lib/pulse/Error.hxx \ +@ENABLE_PULSE_TRUE@ src/lib/pulse/Domain.cxx src/lib/pulse/Domain.hxx + +@ENABLE_PULSE_TRUE@libpulse_a_CPPFLAGS = $(AM_CPPFLAGS) $(PULSE_CFLAGS) +@ENABLE_PULSE_TRUE@PULSE_LIBS2 = libpulse.a $(PULSE_LIBS) # # Playlist plugins # libplaylist_plugins_a_SOURCES = src/playlist/PlaylistPlugin.hxx \ src/playlist/SongEnumerator.hxx \ - src/playlist/CloseSongEnumerator.cxx \ - src/playlist/CloseSongEnumerator.hxx \ src/playlist/MemorySongEnumerator.cxx \ src/playlist/MemorySongEnumerator.hxx \ - src/playlist/cue/CueParser.cxx src/playlist/cue/CueParser.hxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.cxx \ src/playlist/plugins/ExtM3uPlaylistPlugin.hxx \ src/playlist/plugins/M3uPlaylistPlugin.cxx \ src/playlist/plugins/M3uPlaylistPlugin.hxx \ - src/playlist/plugins/CuePlaylistPlugin.cxx \ - src/playlist/plugins/CuePlaylistPlugin.hxx \ - src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx \ - src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx \ + src/playlist/plugins/PlsPlaylistPlugin.cxx \ + src/playlist/plugins/PlsPlaylistPlugin.hxx \ src/playlist/PlaylistRegistry.cxx \ - src/playlist/PlaylistRegistry.hxx $(am__append_95) \ - $(am__append_97) $(am__append_98) + src/playlist/PlaylistRegistry.hxx $(am__append_107) \ + $(am__append_108) $(am__append_109) $(am__append_111) libplaylist_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(EXPAT_CFLAGS) \ $(YAJL_CFLAGS) \ $(patsubst -I%/FLAC,-I%,$(FLAC_CFLAGS)) PLAYLIST_LIBS = libplaylist_plugins.a $(EXPAT_LIBS) $(FLAC_LIBS) \ - $(am__append_96) + $(am__append_110) # # Filter plugins @@ -3748,23 +4053,23 @@ @ENABLE_TEST_TRUE@C_TESTS = test/test_util test/test_byte_reverse \ @ENABLE_TEST_TRUE@ test/test_rewind test/test_mixramp \ @ENABLE_TEST_TRUE@ test/test_pcm test/test_protocol \ -@ENABLE_TEST_TRUE@ test/test_queue_priority $(am__append_99) \ -@ENABLE_TEST_TRUE@ $(am__append_100) $(am__append_101) +@ENABLE_TEST_TRUE@ test/test_queue_priority test/TestFs \ +@ENABLE_TEST_TRUE@ test/TestIcu $(am__append_112) \ +@ENABLE_TEST_TRUE@ $(am__append_113) $(am__append_114) @ENABLE_TEST_TRUE@test_read_conf_LDADD = \ @ENABLE_TEST_TRUE@ libconf.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_read_conf_SOURCES = \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ test/read_conf.cxx @ENABLE_TEST_TRUE@test_run_resolver_LDADD = \ -@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libnet.a \ +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_resolver_SOURCES = \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @@ -3774,19 +4079,17 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(DB_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libconf.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_DumpDatabase_SOURCES = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/DumpDatabase.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/protocol/Ack.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.cxx \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/DatabaseError.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/Registry.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/Selection.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/db/PlaylistVector.cxx \ @@ -3795,37 +4098,37 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/DetachedSong.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/TagSave.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/SongFilter.cxx \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__append_108) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__append_121) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_run_storage_LDADD = \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(STORAGE_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_run_storage_SOURCES = \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_run_storage_SOURCES = \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/IOThread.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/run_storage.cxx - +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/run_storage.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(am__append_122) @ENABLE_TEST_TRUE@test_run_input_LDADD = \ @ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ @ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ -@ENABLE_TEST_TRUE@ libutil.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_input_SOURCES = test/run_input.cxx \ @ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/IOThread.cxx \ @ENABLE_TEST_TRUE@ src/TagSave.cxx @@ -3835,9 +4138,8 @@ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ src/LogBackend.cxx \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ src/IOThread.cxx \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ test/run_neighbor_explorer.cxx \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__append_109) +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(am__append_123) @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@test_run_neighbor_explorer_LDADD = $(AM_LDADD) \ -@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(NEIGHBOR_LIBS) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @@ -3845,6 +4147,7 @@ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libconf.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_NEIGHBOR_PLUGINS_TRUE@@ENABLE_TEST_TRUE@ libutil.a @@ -3854,12 +4157,12 @@ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libconf.a \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ libutil.a @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@test_visit_archive_SOURCES = test/visit_archive.cxx \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ @@ -3867,19 +4170,31 @@ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ src/IOThread.cxx \ @ENABLE_ARCHIVE_TRUE@@ENABLE_TEST_TRUE@ src/input/Open.cxx -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gzip_LDADD = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(FS_LIBS) - -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gzip_SOURCES = test/run_gzip.cxx -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gunzip_SOURCES = test/run_gunzip.cxx \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ src/Log.cxx src/LogBackend.cxx - -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@test_run_gunzip_LDADD = \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(GLIB_LIBS) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ $(FS_LIBS) \ -@ENABLE_TEST_TRUE@@HAVE_ZLIB_TRUE@ libsystem.a +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gzip_LDADD = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ libutil.a \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(FS_LIBS) + +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gzip_SOURCES = test/run_gzip.cxx \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/Log.cxx src/LogBackend.cxx + +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gunzip_SOURCES = test/run_gunzip.cxx \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ src/Log.cxx src/LogBackend.cxx + +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@test_run_gunzip_LDADD = \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@@ENABLE_ZLIB_TRUE@ libutil.a + +@ENABLE_TEST_TRUE@test_WriteFile_LDADD = \ +@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@ libutil.a + +@ENABLE_TEST_TRUE@test_WriteFile_SOURCES = \ +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ +@ENABLE_TEST_TRUE@ test/WriteFile.cxx @ENABLE_TEST_TRUE@test_dump_text_file_LDADD = \ @ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ @@ -3888,42 +4203,41 @@ @ENABLE_TEST_TRUE@ libconf.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_TEST_TRUE@ libthread.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_dump_text_file_SOURCES = test/dump_text_file.cxx \ @ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/IOThread.cxx @ENABLE_TEST_TRUE@test_dump_playlist_LDADD = \ @ENABLE_TEST_TRUE@ $(PLAYLIST_LIBS) \ @ENABLE_TEST_TRUE@ $(FLAC_LIBS) \ -@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ -@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_TEST_TRUE@ $(DECODER_LIBS) \ @ENABLE_TEST_TRUE@ $(TAG_LIBS) \ +@ENABLE_TEST_TRUE@ $(XIPH_LIBS) \ +@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ +@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ libpcm.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libpcm.a @ENABLE_TEST_TRUE@test_dump_playlist_SOURCES = test/dump_playlist.cxx \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.cxx \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.hxx \ -@ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx $(DECODER_SRC) \ -@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@ src/IOThread.cxx src/TagSave.cxx \ -@ENABLE_TEST_TRUE@ src/TagFile.cxx src/AudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/DetachedSong.cxx $(am__append_111) +@ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx src/Log.cxx \ +@ENABLE_TEST_TRUE@ src/LogBackend.cxx src/IOThread.cxx \ +@ENABLE_TEST_TRUE@ src/TagSave.cxx src/TagFile.cxx \ +@ENABLE_TEST_TRUE@ src/DetachedSong.cxx $(am__append_125) @ENABLE_TEST_TRUE@test_run_decoder_LDADD = \ @ENABLE_TEST_TRUE@ $(DECODER_LIBS) \ @ENABLE_TEST_TRUE@ libpcm.a \ @@ -3931,25 +4245,21 @@ @ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_decoder_SOURCES = test/run_decoder.cxx \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ @ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ +@ENABLE_TEST_TRUE@ src/DetachedSong.cxx \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/IOThread.cxx \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ $(ARCHIVE_SRC) \ -@ENABLE_TEST_TRUE@ $(INPUT_SRC) \ -@ENABLE_TEST_TRUE@ $(TAG_SRC) \ -@ENABLE_TEST_TRUE@ $(DECODER_SRC) +@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx @ENABLE_TEST_TRUE@test_read_tags_LDADD = \ @ENABLE_TEST_TRUE@ $(DECODER_LIBS) \ @@ -3958,98 +4268,122 @@ @ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ @ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_read_tags_SOURCES = test/read_tags.cxx \ @ENABLE_TEST_TRUE@ test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \ @ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ +@ENABLE_TEST_TRUE@ src/DetachedSong.cxx \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/IOThread.cxx \ +@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx + +@ENABLE_TEST_TRUE@test_ReadApeTags_LDADD = \ +@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ +@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ +@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ +@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@ libutil.a + +@ENABLE_TEST_TRUE@test_ReadApeTags_SOURCES = \ +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ +@ENABLE_TEST_TRUE@ test/ReadApeTags.cxx + +@ENABLE_TEST_TRUE@test_ContainerScan_LDADD = \ +@ENABLE_TEST_TRUE@ $(DECODER_LIBS) \ +@ENABLE_TEST_TRUE@ libpcm.a \ +@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ +@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ +@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ +@ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ +@ENABLE_TEST_TRUE@ libevent.a \ +@ENABLE_TEST_TRUE@ libthread.a \ +@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@ libutil.a + +@ENABLE_TEST_TRUE@test_ContainerScan_SOURCES = test/ContainerScan.cxx \ +@ENABLE_TEST_TRUE@ src/DetachedSong.cxx \ +@ENABLE_TEST_TRUE@ src/SongSave.cxx src/TagSave.cxx \ +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx src/CheckAudioFormat.cxx \ @ENABLE_TEST_TRUE@ $(DECODER_SRC) -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@test_dump_rva2_LDADD = \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ $(TAG_LIBS) \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ $(GLIB_LIBS) - -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@test_dump_rva2_SOURCES = \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@@HAVE_ID3TAG_TRUE@ test/dump_rva2.cxx +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@test_dump_rva2_LDADD = \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(ARCHIVE_LIBS) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ libutil.a + +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@test_dump_rva2_SOURCES = \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ +@ENABLE_ID3TAG_TRUE@@ENABLE_TEST_TRUE@ test/dump_rva2.cxx @ENABLE_TEST_TRUE@test_run_filter_LDADD = \ @ENABLE_TEST_TRUE@ $(FILTER_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_filter_SOURCES = test/run_filter.cxx \ -@ENABLE_TEST_TRUE@ test/FakeReplayGainConfig.cxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@ src/filter/FilterPlugin.cxx src/filter/FilterRegistry.cxx \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioParser.cxx \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx +@ENABLE_TEST_TRUE@ src/filter/FilterPlugin.cxx src/filter/FilterRegistry.cxx @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@test_run_encoder_SOURCES = test/run_encoder.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ test/stdbin.h \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/AudioParser.cxx +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@test_run_encoder_LDADD = \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(ENCODER_LIBS) \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libpcm.a \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_ENCODER_TRUE@@ENABLE_TEST_TRUE@ libutil.a -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ test/stdbin.h \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/AudioFormat.cxx \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ src/AudioParser.cxx \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(ENCODER_SRC) - -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@test_test_vorbis_encoder_CPPFLAGS = $(AM_CPPFLAGS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(ENCODER_CFLAGS) - -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@test_test_vorbis_encoder_LDADD = $(MPD_LIBS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(ENCODER_LIBS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(PCM_LIBS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(TAG_LIBS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libconf.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(FS_LIBS) \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@@ENABLE_VORBIS_ENCODER_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ src/Log.cxx src/LogBackend.cxx + +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@test_test_vorbis_encoder_CPPFLAGS = $(AM_CPPFLAGS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(ENCODER_CFLAGS) + +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@test_test_vorbis_encoder_LDADD = $(MPD_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(ENCODER_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(PCM_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(TAG_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libbasic.a \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@@ENABLE_VORBISENC_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_software_volume_SOURCES = test/software_volume.cxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ -@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioParser.cxx +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx @ENABLE_TEST_TRUE@test_software_volume_LDADD = \ @ENABLE_TEST_TRUE@ $(PCM_LIBS) \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libbasic.a \ +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_avahi_SOURCES = \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @@ -4064,30 +4398,28 @@ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_TEST_TRUE@ $(AVAHI_LIBS) @ENABLE_TEST_TRUE@test_run_normalize_SOURCES = test/run_normalize.cxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ @ENABLE_TEST_TRUE@ src/AudioCompress/compress.c \ @ENABLE_TEST_TRUE@ src/AudioParser.cxx @ENABLE_TEST_TRUE@test_run_normalize_LDADD = \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_convert_SOURCES = test/run_convert.cxx \ -@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioParser.cxx +@ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx @ENABLE_TEST_TRUE@test_run_convert_LDADD = \ @ENABLE_TEST_TRUE@ $(PCM_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libbasic.a \ +@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ libsystem.a \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_output_LDADD = $(MPD_LIBS) \ @ENABLE_TEST_TRUE@ $(PCM_LIBS) \ @@ -4097,22 +4429,19 @@ @ENABLE_TEST_TRUE@ $(FILTER_LIBS) \ @ENABLE_TEST_TRUE@ $(TAG_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libnet.a \ @ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_TEST_TRUE@ libthread.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_run_output_SOURCES = test/run_output.cxx \ -@ENABLE_TEST_TRUE@ test/FakeReplayGainConfig.cxx \ @ENABLE_TEST_TRUE@ test/ScopeIOThread.hxx \ -@ENABLE_TEST_TRUE@ test/stdbin.h \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/IOThread.cxx \ -@ENABLE_TEST_TRUE@ src/CheckAudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ -@ENABLE_TEST_TRUE@ src/AudioParser.cxx \ @ENABLE_TEST_TRUE@ src/output/Domain.cxx \ @ENABLE_TEST_TRUE@ src/output/Init.cxx src/output/Finish.cxx src/output/Registry.cxx \ @ENABLE_TEST_TRUE@ src/output/OutputPlugin.cxx \ @@ -4120,24 +4449,24 @@ @ENABLE_TEST_TRUE@ src/mixer/MixerType.cxx \ @ENABLE_TEST_TRUE@ src/filter/FilterPlugin.cxx \ @ENABLE_TEST_TRUE@ src/filter/FilterConfig.cxx \ -@ENABLE_TEST_TRUE@ src/ReplayGainInfo.cxx +@ENABLE_TEST_TRUE@ src/filter/Observer.cxx @ENABLE_TEST_TRUE@test_read_mixer_LDADD = \ @ENABLE_TEST_TRUE@ libpcm.a \ @ENABLE_TEST_TRUE@ libmixer_plugins.a \ @ENABLE_TEST_TRUE@ $(OUTPUT_LIBS) \ @ENABLE_TEST_TRUE@ libconf.a \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_read_mixer_SOURCES = test/read_mixer.cxx \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @ENABLE_TEST_TRUE@ src/mixer/MixerControl.cxx \ @ENABLE_TEST_TRUE@ src/filter/FilterPlugin.cxx \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ @ENABLE_TEST_TRUE@ src/filter/plugins/VolumeFilterPlugin.cxx @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@test_run_inotify_SOURCES = test/run_inotify.cxx \ @@ -4149,10 +4478,13 @@ @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@test_run_inotify_LDADD = \ @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libevent.a \ @ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ -@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_INOTIFY_TRUE@@ENABLE_TEST_TRUE@ libutil.a @ENABLE_TEST_TRUE@test_test_util_SOURCES = \ +@ENABLE_TEST_TRUE@ test/DivideStringTest.hxx \ +@ENABLE_TEST_TRUE@ test/SplitStringTest.hxx \ +@ENABLE_TEST_TRUE@ test/UriUtilTest.hxx \ +@ENABLE_TEST_TRUE@ test/MimeTypeTest.hxx \ @ENABLE_TEST_TRUE@ test/TestCircularBuffer.hxx \ @ENABLE_TEST_TRUE@ test/test_util.cxx @@ -4178,7 +4510,6 @@ @ENABLE_TEST_TRUE@test_test_rewind_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 @ENABLE_TEST_TRUE@test_test_rewind_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations @ENABLE_TEST_TRUE@test_test_rewind_LDADD = \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_TEST_TRUE@ $(INPUT_LIBS) \ @ENABLE_TEST_TRUE@ libthread.a \ @ENABLE_TEST_TRUE@ libtag.a \ @@ -4193,7 +4524,6 @@ @ENABLE_TEST_TRUE@test_test_mixramp_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations @ENABLE_TEST_TRUE@test_test_mixramp_LDADD = \ @ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@test_test_icy_parser_SOURCES = \ @@ -4205,11 +4535,10 @@ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@test_test_icy_parser_LDADD = \ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ libtag.a \ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_CURL_TRUE@@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) @ENABLE_TEST_TRUE@test_test_pcm_SOURCES = \ -@ENABLE_TEST_TRUE@ src/AudioFormat.cxx \ +@ENABLE_TEST_TRUE@ test/TestAudioFormat.cxx test/TestAudioFormat.hxx \ @ENABLE_TEST_TRUE@ test/test_pcm_util.hxx \ @ENABLE_TEST_TRUE@ test/test_pcm_dither.cxx \ @ENABLE_TEST_TRUE@ test/test_pcm_pack.cxx \ @@ -4217,6 +4546,7 @@ @ENABLE_TEST_TRUE@ test/test_pcm_format.cxx \ @ENABLE_TEST_TRUE@ test/test_pcm_volume.cxx \ @ENABLE_TEST_TRUE@ test/test_pcm_mix.cxx \ +@ENABLE_TEST_TRUE@ test/test_pcm_interleave.cxx \ @ENABLE_TEST_TRUE@ test/test_pcm_export.cxx \ @ENABLE_TEST_TRUE@ test/test_pcm_all.hxx \ @ENABLE_TEST_TRUE@ test/test_pcm_main.cxx @@ -4225,9 +4555,9 @@ @ENABLE_TEST_TRUE@test_test_pcm_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations @ENABLE_TEST_TRUE@test_test_pcm_LDADD = \ @ENABLE_TEST_TRUE@ $(PCM_LIBS) \ +@ENABLE_TEST_TRUE@ libbasic.a \ @ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) +@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) @ENABLE_TEST_TRUE@test_test_archive_SOURCES = \ @ENABLE_TEST_TRUE@ src/Log.cxx src/LogBackend.cxx \ @@ -4238,7 +4568,6 @@ @ENABLE_TEST_TRUE@test_test_archive_LDADD = \ @ENABLE_TEST_TRUE@ libarchive.a \ @ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@test_test_translate_song_SOURCES = \ @@ -4246,6 +4575,7 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/PlaylistError.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/DetachedSong.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/SongLoader.cxx \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/LocateUri.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ src/Log.cxx \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ test/test_translate_song.cxx @@ -4255,9 +4585,9 @@ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(STORAGE_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libtag.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libsystem.a \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ libutil.a \ -@ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(GLIB_LIBS) \ @ENABLE_DATABASE_TRUE@@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) @ENABLE_TEST_TRUE@test_test_protocol_SOURCES = \ @@ -4283,6 +4613,25 @@ @ENABLE_TEST_TRUE@ libutil.a \ @ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) +@ENABLE_TEST_TRUE@test_TestFs_SOURCES = \ +@ENABLE_TEST_TRUE@ test/TestFs.cxx + +@ENABLE_TEST_TRUE@test_TestFs_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 +@ENABLE_TEST_TRUE@test_TestFs_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations +@ENABLE_TEST_TRUE@test_TestFs_LDADD = \ +@ENABLE_TEST_TRUE@ $(FS_LIBS) \ +@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) + +@ENABLE_TEST_TRUE@test_TestIcu_SOURCES = \ +@ENABLE_TEST_TRUE@ test/TestIcu.cxx + +@ENABLE_TEST_TRUE@test_TestIcu_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 +@ENABLE_TEST_TRUE@test_TestIcu_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations +@ENABLE_TEST_TRUE@test_TestIcu_LDADD = \ +@ENABLE_TEST_TRUE@ $(ICU_LDADD) \ +@ENABLE_TEST_TRUE@ libutil.a \ +@ENABLE_TEST_TRUE@ $(CPPUNIT_LIBS) + @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@src_pcm_dsd2pcm_dsd2pcm_SOURCES = \ @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@ src/pcm/dsd2pcm/dsd2pcm.c src/pcm/dsd2pcm/dsd2pcm.h \ @ENABLE_DSD_TRUE@@ENABLE_TEST_TRUE@ src/pcm/dsd2pcm/dsd2pcm.hpp \ @@ -4296,7 +4645,7 @@ # Documentation # man_MANS = doc/mpd.1 doc/mpd.conf.5 -doc_DATA = AUTHORS COPYING NEWS README doc/mpdconf.example +doc_DATA = AUTHORS COPYING NEWS README.md doc/mpdconf.example DOCBOOK_FILES = doc/protocol.xml doc/user.xml doc/developer.xml @ENABLE_DOCUMENTATION_TRUE@protocoldir = $(docdir)/protocol @ENABLE_DOCUMENTATION_TRUE@protocol_DATA = $(wildcard doc/protocol/*.html) @@ -4325,7 +4674,8 @@ android/src/Bridge.java \ android/src/Loader.java \ android/src/Main.java \ - src/win32/mpd_win32_rc.rc.in src/win32/mpd.ico + win32/res/mpd.rc.in win32/res/mpd.ico \ + src/haiku/App_MusicPD all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -4380,7 +4730,7 @@ distclean-hdr: -rm -f config.h stamp-h1 -src/win32/mpd_win32_rc.rc: $(top_builddir)/config.status $(top_srcdir)/src/win32/mpd_win32_rc.rc.in +win32/res/mpd.rc: $(top_builddir)/config.status $(top_srcdir)/win32/res/mpd.rc.in cd $(top_builddir) && $(SHELL) ./config.status $@ doc/doxygen.conf: $(top_builddir)/config.status $(top_srcdir)/doc/doxygen.conf.in cd $(top_builddir) && $(SHELL) ./config.status $@ @@ -4455,6 +4805,21 @@ $(AM_V_at)-rm -f libarchive.a $(AM_V_AR)$(libarchive_a_AR) libarchive.a $(libarchive_a_OBJECTS) $(libarchive_a_LIBADD) $(AM_V_at)$(RANLIB) libarchive.a +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/ReplayGainMode.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/ReplayGainInfo.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libbasic.a: $(libbasic_a_OBJECTS) $(libbasic_a_DEPENDENCIES) $(EXTRA_libbasic_a_DEPENDENCIES) + $(AM_V_at)-rm -f libbasic.a + $(AM_V_AR)$(libbasic_a_AR) libbasic.a $(libbasic_a_OBJECTS) $(libbasic_a_LIBADD) + $(AM_V_at)$(RANLIB) libbasic.a src/config/$(am__dirstamp): @$(MKDIR_P) src/config @: > src/config/$(am__dirstamp) @@ -4463,7 +4828,11 @@ @: > src/config/$(DEPDIR)/$(am__dirstamp) src/config/ConfigPath.$(OBJEXT): src/config/$(am__dirstamp) \ src/config/$(DEPDIR)/$(am__dirstamp) -src/config/ConfigData.$(OBJEXT): src/config/$(am__dirstamp) \ +src/config/Data.$(OBJEXT): src/config/$(am__dirstamp) \ + src/config/$(DEPDIR)/$(am__dirstamp) +src/config/Block.$(OBJEXT): src/config/$(am__dirstamp) \ + src/config/$(DEPDIR)/$(am__dirstamp) +src/config/Param.$(OBJEXT): src/config/$(am__dirstamp) \ src/config/$(DEPDIR)/$(am__dirstamp) src/config/ConfigParser.$(OBJEXT): src/config/$(am__dirstamp) \ src/config/$(DEPDIR)/$(am__dirstamp) @@ -4480,12 +4849,6 @@ $(AM_V_at)-rm -f libconf.a $(AM_V_AR)$(libconf_a_AR) libconf.a $(libconf_a_OBJECTS) $(libconf_a_LIBADD) $(AM_V_at)$(RANLIB) libconf.a -src/$(am__dirstamp): - @$(MKDIR_P) src - @: > src/$(am__dirstamp) -src/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/$(DEPDIR) - @: > src/$(DEPDIR)/$(am__dirstamp) src/PlaylistDatabase.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/db/$(am__dirstamp): @@ -4512,14 +4875,6 @@ src/db/plugins/simple/DirectorySave.$(OBJEXT): \ src/db/plugins/simple/$(am__dirstamp) \ src/db/plugins/simple/$(DEPDIR)/$(am__dirstamp) -src/db/plugins/$(am__dirstamp): - @$(MKDIR_P) src/db/plugins - @: > src/db/plugins/$(am__dirstamp) -src/db/plugins/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/db/plugins/$(DEPDIR) - @: > src/db/plugins/$(DEPDIR)/$(am__dirstamp) -src/db/plugins/LazyDatabase.$(OBJEXT): src/db/plugins/$(am__dirstamp) \ - src/db/plugins/$(DEPDIR)/$(am__dirstamp) src/db/plugins/simple/Directory.$(OBJEXT): \ src/db/plugins/simple/$(am__dirstamp) \ src/db/plugins/simple/$(DEPDIR)/$(am__dirstamp) @@ -4535,6 +4890,12 @@ src/db/plugins/simple/SimpleDatabasePlugin.$(OBJEXT): \ src/db/plugins/simple/$(am__dirstamp) \ src/db/plugins/simple/$(DEPDIR)/$(am__dirstamp) +src/db/plugins/$(am__dirstamp): + @$(MKDIR_P) src/db/plugins + @: > src/db/plugins/$(am__dirstamp) +src/db/plugins/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/db/plugins/$(DEPDIR) + @: > src/db/plugins/$(DEPDIR)/$(am__dirstamp) src/db/plugins/ProxyDatabasePlugin.$(OBJEXT): \ src/db/plugins/$(am__dirstamp) \ src/db/plugins/$(DEPDIR)/$(am__dirstamp) @@ -4555,8 +4916,6 @@ src/lib/upnp/$(DEPDIR)/$(am__dirstamp) src/lib/upnp/Discovery.$(OBJEXT): src/lib/upnp/$(am__dirstamp) \ src/lib/upnp/$(DEPDIR)/$(am__dirstamp) -src/lib/upnp/Domain.$(OBJEXT): src/lib/upnp/$(am__dirstamp) \ - src/lib/upnp/$(DEPDIR)/$(am__dirstamp) src/lib/upnp/ixmlwrap.$(OBJEXT): src/lib/upnp/$(am__dirstamp) \ src/lib/upnp/$(DEPDIR)/$(am__dirstamp) src/lib/upnp/Util.$(OBJEXT): src/lib/upnp/$(am__dirstamp) \ @@ -4602,6 +4961,12 @@ src/decoder/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/decoder/$(DEPDIR) @: > src/decoder/$(DEPDIR)/$(am__dirstamp) +src/decoder/libdecoder_a-DecoderAPI.$(OBJEXT): \ + src/decoder/$(am__dirstamp) \ + src/decoder/$(DEPDIR)/$(am__dirstamp) +src/decoder/libdecoder_a-Reader.$(OBJEXT): \ + src/decoder/$(am__dirstamp) \ + src/decoder/$(DEPDIR)/$(am__dirstamp) src/decoder/libdecoder_a-DecoderBuffer.$(OBJEXT): \ src/decoder/$(am__dirstamp) \ src/decoder/$(DEPDIR)/$(am__dirstamp) @@ -4629,12 +4994,6 @@ src/decoder/plugins/libdecoder_a-MpcdecDecoderPlugin.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) -src/decoder/plugins/libdecoder_a-OggUtil.$(OBJEXT): \ - src/decoder/plugins/$(am__dirstamp) \ - src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) -src/decoder/plugins/libdecoder_a-OggFind.$(OBJEXT): \ - src/decoder/plugins/$(am__dirstamp) \ - src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) src/decoder/plugins/libdecoder_a-OpusDomain.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) @@ -4656,7 +5015,7 @@ src/decoder/plugins/libdecoder_a-FaadDecoderPlugin.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) -src/decoder/plugins/libdecoder_a-XiphTags.$(OBJEXT): \ +src/decoder/plugins/libdecoder_a-OggDecoder.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) src/decoder/plugins/libdecoder_a-OggCodec.$(OBJEXT): \ @@ -4665,9 +5024,6 @@ src/decoder/plugins/libdecoder_a-VorbisDomain.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) -src/decoder/plugins/libdecoder_a-VorbisComments.$(OBJEXT): \ - src/decoder/plugins/$(am__dirstamp) \ - src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) src/decoder/plugins/libdecoder_a-VorbisDecoderPlugin.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) @@ -4727,6 +5083,15 @@ $(AM_V_at)-rm -f libdecoder.a $(AM_V_AR)$(libdecoder_a_AR) libdecoder.a $(libdecoder_a_OBJECTS) $(libdecoder_a_LIBADD) $(AM_V_at)$(RANLIB) libdecoder.a +src/encoder/$(am__dirstamp): + @$(MKDIR_P) src/encoder + @: > src/encoder/$(am__dirstamp) +src/encoder/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/encoder/$(DEPDIR) + @: > src/encoder/$(DEPDIR)/$(am__dirstamp) +src/encoder/libencoder_plugins_a-ToOutputStream.$(OBJEXT): \ + src/encoder/$(am__dirstamp) \ + src/encoder/$(DEPDIR)/$(am__dirstamp) src/encoder/plugins/$(am__dirstamp): @$(MKDIR_P) src/encoder/plugins @: > src/encoder/plugins/$(am__dirstamp) @@ -4736,18 +5101,9 @@ src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.$(OBJEXT): \ src/encoder/plugins/$(am__dirstamp) \ src/encoder/plugins/$(DEPDIR)/$(am__dirstamp) -src/encoder/$(am__dirstamp): - @$(MKDIR_P) src/encoder - @: > src/encoder/$(am__dirstamp) -src/encoder/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/encoder/$(DEPDIR) - @: > src/encoder/$(DEPDIR)/$(am__dirstamp) src/encoder/libencoder_plugins_a-EncoderList.$(OBJEXT): \ src/encoder/$(am__dirstamp) \ src/encoder/$(DEPDIR)/$(am__dirstamp) -src/encoder/plugins/libencoder_plugins_a-OggSerial.$(OBJEXT): \ - src/encoder/plugins/$(am__dirstamp) \ - src/encoder/plugins/$(DEPDIR)/$(am__dirstamp) src/encoder/plugins/libencoder_plugins_a-WaveEncoderPlugin.$(OBJEXT): \ src/encoder/plugins/$(am__dirstamp) \ src/encoder/plugins/$(DEPDIR)/$(am__dirstamp) @@ -4792,6 +5148,8 @@ src/event/$(DEPDIR)/$(am__dirstamp) src/event/DeferredMonitor.$(OBJEXT): src/event/$(am__dirstamp) \ src/event/$(DEPDIR)/$(am__dirstamp) +src/event/MaskMonitor.$(OBJEXT): src/event/$(am__dirstamp) \ + src/event/$(DEPDIR)/$(am__dirstamp) src/event/SocketMonitor.$(OBJEXT): src/event/$(am__dirstamp) \ src/event/$(DEPDIR)/$(am__dirstamp) src/event/BufferedSocket.$(OBJEXT): src/event/$(am__dirstamp) \ @@ -4925,13 +5283,15 @@ src/fs/$(DEPDIR)/$(am__dirstamp) src/fs/libfs_a-CheckFile.$(OBJEXT): src/fs/$(am__dirstamp) \ src/fs/$(DEPDIR)/$(am__dirstamp) +src/fs/libfs_a-DirectoryReader.$(OBJEXT): src/fs/$(am__dirstamp) \ + src/fs/$(DEPDIR)/$(am__dirstamp) src/lib/zlib/$(am__dirstamp): @$(MKDIR_P) src/lib/zlib @: > src/lib/zlib/$(am__dirstamp) src/lib/zlib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/lib/zlib/$(DEPDIR) @: > src/lib/zlib/$(DEPDIR)/$(am__dirstamp) -src/lib/zlib/libfs_a-Domain.$(OBJEXT): src/lib/zlib/$(am__dirstamp) \ +src/lib/zlib/libfs_a-Error.$(OBJEXT): src/lib/zlib/$(am__dirstamp) \ src/lib/zlib/$(DEPDIR)/$(am__dirstamp) src/fs/io/libfs_a-GunzipReader.$(OBJEXT): src/fs/io/$(am__dirstamp) \ src/fs/io/$(DEPDIR)/$(am__dirstamp) @@ -4952,10 +5312,14 @@ @: > src/lib/icu/$(DEPDIR)/$(am__dirstamp) src/lib/icu/libicu_a-Collate.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ src/lib/icu/$(DEPDIR)/$(am__dirstamp) -src/lib/icu/libicu_a-Error.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ +src/lib/icu/libicu_a-Converter.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ + src/lib/icu/$(DEPDIR)/$(am__dirstamp) +src/lib/icu/libicu_a-Util.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ src/lib/icu/$(DEPDIR)/$(am__dirstamp) src/lib/icu/libicu_a-Init.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ src/lib/icu/$(DEPDIR)/$(am__dirstamp) +src/lib/icu/libicu_a-Win32.$(OBJEXT): src/lib/icu/$(am__dirstamp) \ + src/lib/icu/$(DEPDIR)/$(am__dirstamp) libicu.a: $(libicu_a_OBJECTS) $(libicu_a_DEPENDENCIES) $(EXTRA_libicu_a_DEPENDENCIES) $(AM_V_at)-rm -f libicu.a @@ -4979,6 +5343,8 @@ src/input/$(DEPDIR)/$(am__dirstamp) src/input/libinput_a-InputStream.$(OBJEXT): src/input/$(am__dirstamp) \ src/input/$(DEPDIR)/$(am__dirstamp) +src/input/libinput_a-Reader.$(OBJEXT): src/input/$(am__dirstamp) \ + src/input/$(DEPDIR)/$(am__dirstamp) src/input/libinput_a-TextInputStream.$(OBJEXT): \ src/input/$(am__dirstamp) src/input/$(DEPDIR)/$(am__dirstamp) src/input/libinput_a-ThreadInputStream.$(OBJEXT): \ @@ -5001,6 +5367,21 @@ src/input/plugins/libinput_a-CurlInputPlugin.$(OBJEXT): \ src/input/plugins/$(am__dirstamp) \ src/input/plugins/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/$(am__dirstamp): + @$(MKDIR_P) src/lib/curl + @: > src/lib/curl/$(am__dirstamp) +src/lib/curl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/lib/curl/$(DEPDIR) + @: > src/lib/curl/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/libinput_a-Version.$(OBJEXT): \ + src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/libinput_a-Global.$(OBJEXT): \ + src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/libinput_a-Request.$(OBJEXT): \ + src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) src/libinput_a-IcyMetaDataParser.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/lib/smbclient/$(am__dirstamp): @@ -5042,8 +5423,6 @@ src/lib/nfs/libinput_a-Blocking.$(OBJEXT): \ src/lib/nfs/$(am__dirstamp) \ src/lib/nfs/$(DEPDIR)/$(am__dirstamp) -src/lib/nfs/libinput_a-Domain.$(OBJEXT): src/lib/nfs/$(am__dirstamp) \ - src/lib/nfs/$(DEPDIR)/$(am__dirstamp) src/input/plugins/libinput_a-NfsInputPlugin.$(OBJEXT): \ src/input/plugins/$(am__dirstamp) \ src/input/plugins/$(DEPDIR)/$(am__dirstamp) @@ -5091,13 +5470,22 @@ src/mixer/plugins/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/mixer/plugins/$(DEPDIR) @: > src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) +src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.$(OBJEXT): \ + src/mixer/plugins/$(am__dirstamp) \ + src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.$(OBJEXT): \ src/mixer/plugins/$(am__dirstamp) \ src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) +src/mixer/plugins/libmixer_plugins_a-volume_mapping.$(OBJEXT): \ + src/mixer/plugins/$(am__dirstamp) \ + src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) src/mixer/plugins/libmixer_plugins_a-AlsaMixerPlugin.$(OBJEXT): \ src/mixer/plugins/$(am__dirstamp) \ src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) -src/mixer/plugins/libmixer_plugins_a-RoarMixerPlugin.$(OBJEXT): \ +src/mixer/plugins/libmixer_plugins_a-RoarMixerPlugin.$(OBJEXT): \ + src/mixer/plugins/$(am__dirstamp) \ + src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) +src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.$(OBJEXT): \ src/mixer/plugins/$(am__dirstamp) \ src/mixer/plugins/$(DEPDIR)/$(am__dirstamp) src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.$(OBJEXT): \ @@ -5128,11 +5516,18 @@ src/output/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/output/$(DEPDIR) @: > src/output/$(DEPDIR)/$(am__dirstamp) +src/output/libmpd_a-Internal.$(OBJEXT): src/output/$(am__dirstamp) \ + src/output/$(DEPDIR)/$(am__dirstamp) src/output/libmpd_a-Registry.$(OBJEXT): src/output/$(am__dirstamp) \ src/output/$(DEPDIR)/$(am__dirstamp) src/output/libmpd_a-MultipleOutputs.$(OBJEXT): \ src/output/$(am__dirstamp) \ src/output/$(DEPDIR)/$(am__dirstamp) +src/output/libmpd_a-SharedPipeConsumer.$(OBJEXT): \ + src/output/$(am__dirstamp) \ + src/output/$(DEPDIR)/$(am__dirstamp) +src/output/libmpd_a-Source.$(OBJEXT): src/output/$(am__dirstamp) \ + src/output/$(DEPDIR)/$(am__dirstamp) src/output/libmpd_a-OutputThread.$(OBJEXT): \ src/output/$(am__dirstamp) \ src/output/$(DEPDIR)/$(am__dirstamp) @@ -5169,14 +5564,6 @@ src/mixer/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-notify.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-AudioConfig.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-CheckAudioFormat.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-AudioFormat.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-AudioParser.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/protocol/$(am__dirstamp): @$(MKDIR_P) src/protocol @: > src/protocol/$(am__dirstamp) @@ -5231,7 +5618,7 @@ src/command/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-Idle.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-CrossFade.$(OBJEXT): src/$(am__dirstamp) \ +src/libmpd_a-IdleFlags.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/decoder/libmpd_a-DecoderError.$(OBJEXT): \ src/decoder/$(am__dirstamp) \ @@ -5242,11 +5629,7 @@ src/decoder/libmpd_a-DecoderControl.$(OBJEXT): \ src/decoder/$(am__dirstamp) \ src/decoder/$(DEPDIR)/$(am__dirstamp) -src/decoder/libmpd_a-DecoderAPI.$(OBJEXT): \ - src/decoder/$(am__dirstamp) \ - src/decoder/$(DEPDIR)/$(am__dirstamp) -src/decoder/libmpd_a-DecoderInternal.$(OBJEXT): \ - src/decoder/$(am__dirstamp) \ +src/decoder/libmpd_a-Bridge.$(OBJEXT): src/decoder/$(am__dirstamp) \ src/decoder/$(DEPDIR)/$(am__dirstamp) src/decoder/libmpd_a-DecoderPrint.$(OBJEXT): \ src/decoder/$(am__dirstamp) \ @@ -5266,6 +5649,8 @@ src/filter/libmpd_a-FilterRegistry.$(OBJEXT): \ src/filter/$(am__dirstamp) \ src/filter/$(DEPDIR)/$(am__dirstamp) +src/filter/libmpd_a-Observer.$(OBJEXT): src/filter/$(am__dirstamp) \ + src/filter/$(DEPDIR)/$(am__dirstamp) src/client/$(am__dirstamp): @$(MKDIR_P) src/client @: > src/client/$(am__dirstamp) @@ -5303,6 +5688,8 @@ src/client/$(DEPDIR)/$(am__dirstamp) src/client/libmpd_a-ClientFile.$(OBJEXT): src/client/$(am__dirstamp) \ src/client/$(DEPDIR)/$(am__dirstamp) +src/client/libmpd_a-Response.$(OBJEXT): src/client/$(am__dirstamp) \ + src/client/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-Listen.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-LogInit.$(OBJEXT): src/$(am__dirstamp) \ @@ -5325,8 +5712,6 @@ @: > src/win32/$(DEPDIR)/$(am__dirstamp) src/win32/libmpd_a-Win32Main.$(OBJEXT): src/win32/$(am__dirstamp) \ src/win32/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-GlobalEvents.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-MusicBuffer.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-MusicPipe.$(OBJEXT): src/$(am__dirstamp) \ @@ -5339,14 +5724,20 @@ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-Permission.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-PlayerThread.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-PlayerControl.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) +src/player/$(am__dirstamp): + @$(MKDIR_P) src/player + @: > src/player/$(am__dirstamp) +src/player/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/player/$(DEPDIR) + @: > src/player/$(DEPDIR)/$(am__dirstamp) +src/player/libmpd_a-CrossFade.$(OBJEXT): src/player/$(am__dirstamp) \ + src/player/$(DEPDIR)/$(am__dirstamp) +src/player/libmpd_a-Thread.$(OBJEXT): src/player/$(am__dirstamp) \ + src/player/$(DEPDIR)/$(am__dirstamp) +src/player/libmpd_a-Control.$(OBJEXT): src/player/$(am__dirstamp) \ + src/player/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-PlaylistError.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-PlaylistGlobal.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-PlaylistPrint.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-PlaylistSave.$(OBJEXT): src/$(am__dirstamp) \ @@ -5398,12 +5789,12 @@ src/queue/$(DEPDIR)/$(am__dirstamp) src/queue/libmpd_a-PlaylistState.$(OBJEXT): src/queue/$(am__dirstamp) \ src/queue/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-ReplayGainConfig.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/libmpd_a-ReplayGainInfo.$(OBJEXT): src/$(am__dirstamp) \ +src/libmpd_a-ReplayGainGlobal.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-DetachedSong.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) +src/libmpd_a-LocateUri.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-SongUpdate.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-SongLoader.$(OBJEXT): src/$(am__dirstamp) \ @@ -5440,10 +5831,10 @@ @: > src/unix/$(DEPDIR)/$(am__dirstamp) src/unix/libmpd_a-SignalHandlers.$(OBJEXT): src/unix/$(am__dirstamp) \ src/unix/$(DEPDIR)/$(am__dirstamp) -src/unix/libmpd_a-Daemon.$(OBJEXT): src/unix/$(am__dirstamp) \ - src/unix/$(DEPDIR)/$(am__dirstamp) src/libmpd_a-CommandLine.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) +src/unix/libmpd_a-Daemon.$(OBJEXT): src/unix/$(am__dirstamp) \ + src/unix/$(DEPDIR)/$(am__dirstamp) src/queue/libmpd_a-PlaylistUpdate.$(OBJEXT): \ src/queue/$(am__dirstamp) src/queue/$(DEPDIR)/$(am__dirstamp) src/command/libmpd_a-StorageCommands.$(OBJEXT): \ @@ -5502,8 +5893,6 @@ src/db/$(DEPDIR)/$(am__dirstamp) src/db/libmpd_a-DatabasePlaylist.$(OBJEXT): src/db/$(am__dirstamp) \ src/db/$(DEPDIR)/$(am__dirstamp) -src/db/libmpd_a-DatabaseError.$(OBJEXT): src/db/$(am__dirstamp) \ - src/db/$(DEPDIR)/$(am__dirstamp) src/db/libmpd_a-DatabaseLock.$(OBJEXT): src/db/$(am__dirstamp) \ src/db/$(DEPDIR)/$(am__dirstamp) src/db/libmpd_a-Selection.$(OBJEXT): src/db/$(am__dirstamp) \ @@ -5523,6 +5912,15 @@ src/command/libmpd_a-StickerCommands.$(OBJEXT): \ src/command/$(am__dirstamp) \ src/command/$(DEPDIR)/$(am__dirstamp) +src/lib/sqlite/$(am__dirstamp): + @$(MKDIR_P) src/lib/sqlite + @: > src/lib/sqlite/$(am__dirstamp) +src/lib/sqlite/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/lib/sqlite/$(DEPDIR) + @: > src/lib/sqlite/$(DEPDIR)/$(am__dirstamp) +src/lib/sqlite/libmpd_a-Error.$(OBJEXT): \ + src/lib/sqlite/$(am__dirstamp) \ + src/lib/sqlite/$(DEPDIR)/$(am__dirstamp) src/sticker/$(am__dirstamp): @$(MKDIR_P) src/sticker @: > src/sticker/$(am__dirstamp) @@ -5541,6 +5939,8 @@ src/command/libmpd_a-NeighborCommands.$(OBJEXT): \ src/command/$(am__dirstamp) \ src/command/$(DEPDIR)/$(am__dirstamp) +src/libmpd_a-TagArchive.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) src/db/update/libmpd_a-Archive.$(OBJEXT): \ src/db/update/$(am__dirstamp) \ src/db/update/$(DEPDIR)/$(am__dirstamp) @@ -5612,9 +6012,6 @@ src/lib/upnp/libneighbor_a-Discovery.$(OBJEXT): \ src/lib/upnp/$(am__dirstamp) \ src/lib/upnp/$(DEPDIR)/$(am__dirstamp) -src/lib/upnp/libneighbor_a-Domain.$(OBJEXT): \ - src/lib/upnp/$(am__dirstamp) \ - src/lib/upnp/$(DEPDIR)/$(am__dirstamp) src/lib/upnp/libneighbor_a-ixmlwrap.$(OBJEXT): \ src/lib/upnp/$(am__dirstamp) \ src/lib/upnp/$(DEPDIR)/$(am__dirstamp) @@ -5629,6 +6026,31 @@ $(AM_V_at)-rm -f libneighbor.a $(AM_V_AR)$(libneighbor_a_AR) libneighbor.a $(libneighbor_a_OBJECTS) $(libneighbor_a_LIBADD) $(AM_V_at)$(RANLIB) libneighbor.a +src/net/$(am__dirstamp): + @$(MKDIR_P) src/net + @: > src/net/$(am__dirstamp) +src/net/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/net/$(DEPDIR) + @: > src/net/$(DEPDIR)/$(am__dirstamp) +src/net/ToString.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/Resolver.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/StaticSocketAddress.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/AllocatedSocketAddress.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/SocketAddress.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/SocketUtil.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) +src/net/SocketError.$(OBJEXT): src/net/$(am__dirstamp) \ + src/net/$(DEPDIR)/$(am__dirstamp) + +libnet.a: $(libnet_a_OBJECTS) $(libnet_a_DEPENDENCIES) $(EXTRA_libnet_a_DEPENDENCIES) + $(AM_V_at)-rm -f libnet.a + $(AM_V_AR)$(libnet_a_AR) libnet.a $(libnet_a_OBJECTS) $(libnet_a_LIBADD) + $(AM_V_at)$(RANLIB) libnet.a src/output/liboutput_plugins_a-Timer.$(OBJEXT): \ src/output/$(am__dirstamp) \ src/output/$(DEPDIR)/$(am__dirstamp) @@ -5662,6 +6084,12 @@ src/output/plugins/liboutput_plugins_a-FifoOutputPlugin.$(OBJEXT): \ src/output/plugins/$(am__dirstamp) \ src/output/plugins/$(DEPDIR)/$(am__dirstamp) +src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.$(OBJEXT): \ + src/output/plugins/$(am__dirstamp) \ + src/output/plugins/$(DEPDIR)/$(am__dirstamp) +src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.$(OBJEXT): \ + src/output/plugins/$(am__dirstamp) \ + src/output/plugins/$(DEPDIR)/$(am__dirstamp) src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.$(OBJEXT): \ src/output/plugins/$(am__dirstamp) \ src/output/plugins/$(DEPDIR)/$(am__dirstamp) @@ -5715,13 +6143,19 @@ $(AM_V_at)-rm -f liboutput_plugins.a $(AM_V_AR)$(liboutput_plugins_a_AR) liboutput_plugins.a $(liboutput_plugins_a_OBJECTS) $(liboutput_plugins_a_LIBADD) $(AM_V_at)$(RANLIB) liboutput_plugins.a +src/libpcm_a-CheckAudioFormat.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libpcm_a-AudioFormat.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libpcm_a-AudioParser.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) src/pcm/$(am__dirstamp): @$(MKDIR_P) src/pcm @: > src/pcm/$(am__dirstamp) src/pcm/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/pcm/$(DEPDIR) @: > src/pcm/$(DEPDIR)/$(am__dirstamp) -src/pcm/libpcm_a-Domain.$(OBJEXT): src/pcm/$(am__dirstamp) \ +src/pcm/libpcm_a-SampleFormat.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-Interleave.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) @@ -5749,6 +6183,8 @@ src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-ChannelsConverter.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) +src/pcm/libpcm_a-Order.$(OBJEXT): src/pcm/$(am__dirstamp) \ + src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-GlueResampler.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-FallbackResampler.$(OBJEXT): src/pcm/$(am__dirstamp) \ @@ -5757,6 +6193,10 @@ src/pcm/$(am__dirstamp) src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-PcmDither.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) +src/pcm/libpcm_a-Dsd16.$(OBJEXT): src/pcm/$(am__dirstamp) \ + src/pcm/$(DEPDIR)/$(am__dirstamp) +src/pcm/libpcm_a-Dsd32.$(OBJEXT): src/pcm/$(am__dirstamp) \ + src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/libpcm_a-PcmDsd.$(OBJEXT): src/pcm/$(am__dirstamp) \ src/pcm/$(DEPDIR)/$(am__dirstamp) src/pcm/dsd2pcm/$(am__dirstamp): @@ -5777,21 +6217,9 @@ $(AM_V_at)-rm -f libpcm.a $(AM_V_AR)$(libpcm_a_AR) libpcm.a $(libpcm_a_OBJECTS) $(libpcm_a_LIBADD) $(AM_V_at)$(RANLIB) libpcm.a -src/playlist/libplaylist_plugins_a-CloseSongEnumerator.$(OBJEXT): \ - src/playlist/$(am__dirstamp) \ - src/playlist/$(DEPDIR)/$(am__dirstamp) src/playlist/libplaylist_plugins_a-MemorySongEnumerator.$(OBJEXT): \ src/playlist/$(am__dirstamp) \ src/playlist/$(DEPDIR)/$(am__dirstamp) -src/playlist/cue/$(am__dirstamp): - @$(MKDIR_P) src/playlist/cue - @: > src/playlist/cue/$(am__dirstamp) -src/playlist/cue/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/playlist/cue/$(DEPDIR) - @: > src/playlist/cue/$(DEPDIR)/$(am__dirstamp) -src/playlist/cue/libplaylist_plugins_a-CueParser.$(OBJEXT): \ - src/playlist/cue/$(am__dirstamp) \ - src/playlist/cue/$(DEPDIR)/$(am__dirstamp) src/playlist/plugins/$(am__dirstamp): @$(MKDIR_P) src/playlist/plugins @: > src/playlist/plugins/$(am__dirstamp) @@ -5804,15 +6232,30 @@ src/playlist/plugins/libplaylist_plugins_a-M3uPlaylistPlugin.$(OBJEXT): \ src/playlist/plugins/$(am__dirstamp) \ src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) +src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.$(OBJEXT): \ + src/playlist/plugins/$(am__dirstamp) \ + src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) +src/playlist/libplaylist_plugins_a-PlaylistRegistry.$(OBJEXT): \ + src/playlist/$(am__dirstamp) \ + src/playlist/$(DEPDIR)/$(am__dirstamp) +src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.$(OBJEXT): \ + src/playlist/plugins/$(am__dirstamp) \ + src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) +src/playlist/cue/$(am__dirstamp): + @$(MKDIR_P) src/playlist/cue + @: > src/playlist/cue/$(am__dirstamp) +src/playlist/cue/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/playlist/cue/$(DEPDIR) + @: > src/playlist/cue/$(DEPDIR)/$(am__dirstamp) +src/playlist/cue/libplaylist_plugins_a-CueParser.$(OBJEXT): \ + src/playlist/cue/$(am__dirstamp) \ + src/playlist/cue/$(DEPDIR)/$(am__dirstamp) src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.$(OBJEXT): \ src/playlist/plugins/$(am__dirstamp) \ src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) src/playlist/plugins/libplaylist_plugins_a-EmbeddedCuePlaylistPlugin.$(OBJEXT): \ src/playlist/plugins/$(am__dirstamp) \ src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) -src/playlist/libplaylist_plugins_a-PlaylistRegistry.$(OBJEXT): \ - src/playlist/$(am__dirstamp) \ - src/playlist/$(DEPDIR)/$(am__dirstamp) src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.$(OBJEXT): \ src/playlist/plugins/$(am__dirstamp) \ src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) @@ -5822,6 +6265,9 @@ src/lib/expat/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/lib/expat/$(DEPDIR) @: > src/lib/expat/$(DEPDIR)/$(am__dirstamp) +src/lib/expat/libplaylist_plugins_a-StreamExpatParser.$(OBJEXT): \ + src/lib/expat/$(am__dirstamp) \ + src/lib/expat/$(DEPDIR)/$(am__dirstamp) src/lib/expat/libplaylist_plugins_a-ExpatParser.$(OBJEXT): \ src/lib/expat/$(am__dirstamp) \ src/lib/expat/$(DEPDIR)/$(am__dirstamp) @@ -5834,14 +6280,31 @@ src/playlist/plugins/libplaylist_plugins_a-RssPlaylistPlugin.$(OBJEXT): \ src/playlist/plugins/$(am__dirstamp) \ src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) -src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.$(OBJEXT): \ - src/playlist/plugins/$(am__dirstamp) \ - src/playlist/plugins/$(DEPDIR)/$(am__dirstamp) libplaylist_plugins.a: $(libplaylist_plugins_a_OBJECTS) $(libplaylist_plugins_a_DEPENDENCIES) $(EXTRA_libplaylist_plugins_a_DEPENDENCIES) $(AM_V_at)-rm -f libplaylist_plugins.a $(AM_V_AR)$(libplaylist_plugins_a_AR) libplaylist_plugins.a $(libplaylist_plugins_a_OBJECTS) $(libplaylist_plugins_a_LIBADD) $(AM_V_at)$(RANLIB) libplaylist_plugins.a +src/lib/pulse/$(am__dirstamp): + @$(MKDIR_P) src/lib/pulse + @: > src/lib/pulse/$(am__dirstamp) +src/lib/pulse/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/lib/pulse/$(DEPDIR) + @: > src/lib/pulse/$(DEPDIR)/$(am__dirstamp) +src/lib/pulse/libpulse_a-LogError.$(OBJEXT): \ + src/lib/pulse/$(am__dirstamp) \ + src/lib/pulse/$(DEPDIR)/$(am__dirstamp) +src/lib/pulse/libpulse_a-Error.$(OBJEXT): \ + src/lib/pulse/$(am__dirstamp) \ + src/lib/pulse/$(DEPDIR)/$(am__dirstamp) +src/lib/pulse/libpulse_a-Domain.$(OBJEXT): \ + src/lib/pulse/$(am__dirstamp) \ + src/lib/pulse/$(DEPDIR)/$(am__dirstamp) + +libpulse.a: $(libpulse_a_OBJECTS) $(libpulse_a_DEPENDENCIES) $(EXTRA_libpulse_a_DEPENDENCIES) + $(AM_V_at)-rm -f libpulse.a + $(AM_V_AR)$(libpulse_a_AR) libpulse.a $(libpulse_a_OBJECTS) $(libpulse_a_LIBADD) + $(AM_V_at)$(RANLIB) libpulse.a src/storage/$(am__dirstamp): @$(MKDIR_P) src/storage @: > src/storage/$(am__dirstamp) @@ -5900,12 +6363,15 @@ src/lib/nfs/libstorage_a-Blocking.$(OBJEXT): \ src/lib/nfs/$(am__dirstamp) \ src/lib/nfs/$(DEPDIR)/$(am__dirstamp) -src/lib/nfs/libstorage_a-Domain.$(OBJEXT): \ - src/lib/nfs/$(am__dirstamp) \ - src/lib/nfs/$(DEPDIR)/$(am__dirstamp) src/storage/plugins/libstorage_a-NfsStorage.$(OBJEXT): \ src/storage/plugins/$(am__dirstamp) \ src/storage/plugins/$(DEPDIR)/$(am__dirstamp) +src/lib/expat/libstorage_a-ExpatParser.$(OBJEXT): \ + src/lib/expat/$(am__dirstamp) \ + src/lib/expat/$(DEPDIR)/$(am__dirstamp) +src/storage/plugins/libstorage_a-CurlStorage.$(OBJEXT): \ + src/storage/plugins/$(am__dirstamp) \ + src/storage/plugins/$(DEPDIR)/$(am__dirstamp) libstorage.a: $(libstorage_a_OBJECTS) $(libstorage_a_DEPENDENCIES) $(EXTRA_libstorage_a_DEPENDENCIES) $(AM_V_at)-rm -f libstorage.a @@ -5919,13 +6385,9 @@ @: > src/system/$(DEPDIR)/$(am__dirstamp) src/system/FatalError.$(OBJEXT): src/system/$(am__dirstamp) \ src/system/$(DEPDIR)/$(am__dirstamp) -src/system/fd_util.$(OBJEXT): src/system/$(am__dirstamp) \ - src/system/$(DEPDIR)/$(am__dirstamp) -src/system/SocketUtil.$(OBJEXT): src/system/$(am__dirstamp) \ +src/system/FileDescriptor.$(OBJEXT): src/system/$(am__dirstamp) \ src/system/$(DEPDIR)/$(am__dirstamp) -src/system/SocketError.$(OBJEXT): src/system/$(am__dirstamp) \ - src/system/$(DEPDIR)/$(am__dirstamp) -src/system/Resolver.$(OBJEXT): src/system/$(am__dirstamp) \ +src/system/fd_util.$(OBJEXT): src/system/$(am__dirstamp) \ src/system/$(DEPDIR)/$(am__dirstamp) src/system/EventPipe.$(OBJEXT): src/system/$(am__dirstamp) \ src/system/$(DEPDIR)/$(am__dirstamp) @@ -5954,7 +6416,7 @@ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-TagHandler.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) -src/tag/libtag_a-TagSettings.$(OBJEXT): src/tag/$(am__dirstamp) \ +src/tag/libtag_a-Settings.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-TagConfig.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) @@ -5968,18 +6430,24 @@ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-Set.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) +src/tag/libtag_a-Format.$(OBJEXT): src/tag/$(am__dirstamp) \ + src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-VorbisComment.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-ReplayGain.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-MixRamp.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) +src/tag/libtag_a-Generic.$(OBJEXT): src/tag/$(am__dirstamp) \ + src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-ApeLoader.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-ApeReplayGain.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-ApeTag.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) +src/tag/libtag_a-Id3Load.$(OBJEXT): src/tag/$(am__dirstamp) \ + src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-TagId3.$(OBJEXT): src/tag/$(am__dirstamp) \ src/tag/$(DEPDIR)/$(am__dirstamp) src/tag/libtag_a-TagRva2.$(OBJEXT): src/tag/$(am__dirstamp) \ @@ -5999,6 +6467,8 @@ src/thread/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thread/$(DEPDIR) @: > src/thread/$(DEPDIR)/$(am__dirstamp) +src/thread/Util.$(OBJEXT): src/thread/$(am__dirstamp) \ + src/thread/$(DEPDIR)/$(am__dirstamp) src/thread/Thread.$(OBJEXT): src/thread/$(am__dirstamp) \ src/thread/$(DEPDIR)/$(am__dirstamp) @@ -6012,20 +6482,34 @@ src/util/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/util/$(DEPDIR) @: > src/util/$(DEPDIR)/$(am__dirstamp) -src/util/Alloc.$(OBJEXT): src/util/$(am__dirstamp) \ +src/util/Exception.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) -src/util/Error.$(OBJEXT): src/util/$(am__dirstamp) \ +src/util/Alloc.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) src/util/UTF8.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) +src/util/MimeType.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) +src/util/StringView.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) +src/util/AllocatedString.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) src/util/StringUtil.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) +src/util/StringCompare.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) +src/util/WStringCompare.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) +src/util/DivideString.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) src/util/SplitString.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) src/util/FormatString.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) src/util/Tokenizer.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) +src/util/TimeParser.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) src/util/UriUtil.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) src/util/LazyRandomEngine.$(OBJEXT): src/util/$(am__dirstamp) \ @@ -6038,6 +6522,8 @@ src/util/$(DEPDIR)/$(am__dirstamp) src/util/ByteReverse.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) +src/util/format.$(OBJEXT): src/util/$(am__dirstamp) \ + src/util/$(DEPDIR)/$(am__dirstamp) src/util/bit_reverse.$(OBJEXT): src/util/$(am__dirstamp) \ src/util/$(DEPDIR)/$(am__dirstamp) @@ -6045,6 +6531,38 @@ $(AM_V_at)-rm -f libutil.a $(AM_V_AR)$(libutil_a_AR) libutil.a $(libutil_a_OBJECTS) $(libutil_a_LIBADD) $(AM_V_at)$(RANLIB) libutil.a +src/lib/xiph/$(am__dirstamp): + @$(MKDIR_P) src/lib/xiph + @: > src/lib/xiph/$(am__dirstamp) +src/lib/xiph/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/lib/xiph/$(DEPDIR) + @: > src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-VorbisComments.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-XiphTags.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-OggVisitor.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-OggSerial.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-OggSyncState.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-OggFind.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) +src/lib/xiph/libxiph_a-OggPacket.$(OBJEXT): \ + src/lib/xiph/$(am__dirstamp) \ + src/lib/xiph/$(DEPDIR)/$(am__dirstamp) + +libxiph.a: $(libxiph_a_OBJECTS) $(libxiph_a_DEPENDENCIES) $(EXTRA_libxiph_a_DEPENDENCIES) + $(AM_V_at)-rm -f libxiph.a + $(AM_V_AR)$(libxiph_a_AR) libxiph.a $(libxiph_a_OBJECTS) $(libxiph_a_LIBADD) + $(AM_V_at)$(RANLIB) libxiph.a install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ @@ -6111,27 +6629,31 @@ test/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) test/$(DEPDIR) @: > test/$(DEPDIR)/$(am__dirstamp) -test/DumpDatabase.$(OBJEXT): test/$(am__dirstamp) \ +test/ContainerScan.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) -src/protocol/Ack.$(OBJEXT): src/protocol/$(am__dirstamp) \ - src/protocol/$(DEPDIR)/$(am__dirstamp) +src/DetachedSong.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/SongSave.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/TagSave.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) src/Log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/LogBackend.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/db/DatabaseError.$(OBJEXT): src/db/$(am__dirstamp) \ - src/db/$(DEPDIR)/$(am__dirstamp) + +test/ContainerScan$(EXEEXT): $(test_ContainerScan_OBJECTS) $(test_ContainerScan_DEPENDENCIES) $(EXTRA_test_ContainerScan_DEPENDENCIES) test/$(am__dirstamp) + @rm -f test/ContainerScan$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_ContainerScan_OBJECTS) $(test_ContainerScan_LDADD) $(LIBS) +test/DumpDatabase.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) +src/protocol/Ack.$(OBJEXT): src/protocol/$(am__dirstamp) \ + src/protocol/$(DEPDIR)/$(am__dirstamp) src/db/Selection.$(OBJEXT): src/db/$(am__dirstamp) \ src/db/$(DEPDIR)/$(am__dirstamp) src/db/PlaylistVector.$(OBJEXT): src/db/$(am__dirstamp) \ src/db/$(DEPDIR)/$(am__dirstamp) src/db/DatabaseLock.$(OBJEXT): src/db/$(am__dirstamp) \ src/db/$(DEPDIR)/$(am__dirstamp) -src/SongSave.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/DetachedSong.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/TagSave.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/SongFilter.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/lib/expat/ExpatParser.$(OBJEXT): src/lib/expat/$(am__dirstamp) \ @@ -6140,6 +6662,30 @@ test/DumpDatabase$(EXEEXT): $(test_DumpDatabase_OBJECTS) $(test_DumpDatabase_DEPENDENCIES) $(EXTRA_test_DumpDatabase_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/DumpDatabase$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_DumpDatabase_OBJECTS) $(test_DumpDatabase_LDADD) $(LIBS) +test/ReadApeTags.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) + +test/ReadApeTags$(EXEEXT): $(test_ReadApeTags_OBJECTS) $(test_ReadApeTags_DEPENDENCIES) $(EXTRA_test_ReadApeTags_DEPENDENCIES) test/$(am__dirstamp) + @rm -f test/ReadApeTags$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_ReadApeTags_OBJECTS) $(test_ReadApeTags_LDADD) $(LIBS) +test/test_TestFs-TestFs.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) + +test/TestFs$(EXEEXT): $(test_TestFs_OBJECTS) $(test_TestFs_DEPENDENCIES) $(EXTRA_test_TestFs_DEPENDENCIES) test/$(am__dirstamp) + @rm -f test/TestFs$(EXEEXT) + $(AM_V_CXXLD)$(test_TestFs_LINK) $(test_TestFs_OBJECTS) $(test_TestFs_LDADD) $(LIBS) +test/test_TestIcu-TestIcu.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) + +test/TestIcu$(EXEEXT): $(test_TestIcu_OBJECTS) $(test_TestIcu_DEPENDENCIES) $(EXTRA_test_TestIcu_DEPENDENCIES) test/$(am__dirstamp) + @rm -f test/TestIcu$(EXEEXT) + $(AM_V_CXXLD)$(test_TestIcu_LINK) $(test_TestIcu_OBJECTS) $(test_TestIcu_LDADD) $(LIBS) +test/WriteFile.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) + +test/WriteFile$(EXEEXT): $(test_WriteFile_OBJECTS) $(test_WriteFile_DEPENDENCIES) $(EXTRA_test_WriteFile_DEPENDENCIES) test/$(am__dirstamp) + @rm -f test/WriteFile$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_WriteFile_OBJECTS) $(test_WriteFile_LDADD) $(LIBS) test/dump_playlist.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/FakeDecoderAPI.$(OBJEXT): test/$(am__dirstamp) \ @@ -6148,12 +6694,6 @@ src/$(DEPDIR)/$(am__dirstamp) src/TagFile.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/AudioFormat.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/CheckAudioFormat.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/ReplayGainInfo.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/decoder/plugins/FlacMetadata.$(OBJEXT): \ src/decoder/plugins/$(am__dirstamp) \ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp) @@ -6215,8 +6755,6 @@ $(AM_V_CXXLD)$(CXXLINK) $(test_run_avahi_OBJECTS) $(test_run_avahi_LDADD) $(LIBS) test/run_convert.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) -src/AudioParser.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) test/run_convert$(EXEEXT): $(test_run_convert_OBJECTS) $(test_run_convert_DEPENDENCIES) $(EXTRA_test_run_convert_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/run_convert$(EXEEXT) @@ -6235,8 +6773,6 @@ $(AM_V_CXXLD)$(CXXLINK) $(test_run_encoder_OBJECTS) $(test_run_encoder_LDADD) $(LIBS) test/run_filter.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) -test/FakeReplayGainConfig.$(OBJEXT): test/$(am__dirstamp) \ - test/$(DEPDIR)/$(am__dirstamp) src/filter/FilterRegistry.$(OBJEXT): src/filter/$(am__dirstamp) \ src/filter/$(DEPDIR)/$(am__dirstamp) @@ -6281,6 +6817,10 @@ $(AM_V_CXXLD)$(CXXLINK) $(test_run_neighbor_explorer_OBJECTS) $(test_run_neighbor_explorer_LDADD) $(LIBS) test/run_normalize.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) +src/CheckAudioFormat.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/AudioParser.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) test/run_normalize$(EXEEXT): $(test_run_normalize_OBJECTS) $(test_run_normalize_DEPENDENCIES) $(EXTRA_test_run_normalize_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/run_normalize$(EXEEXT) @@ -6301,6 +6841,8 @@ src/mixer/$(DEPDIR)/$(am__dirstamp) src/filter/FilterConfig.$(OBJEXT): src/filter/$(am__dirstamp) \ src/filter/$(DEPDIR)/$(am__dirstamp) +src/filter/Observer.$(OBJEXT): src/filter/$(am__dirstamp) \ + src/filter/$(DEPDIR)/$(am__dirstamp) test/run_output$(EXEEXT): $(test_run_output_OBJECTS) $(test_run_output_DEPENDENCIES) $(EXTRA_test_run_output_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/run_output$(EXEEXT) @@ -6313,6 +6855,12 @@ $(AM_V_CXXLD)$(CXXLINK) $(test_run_resolver_OBJECTS) $(test_run_resolver_LDADD) $(LIBS) test/run_storage.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/Version.$(OBJEXT): src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/Global.$(OBJEXT): src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) +src/lib/curl/Request.$(OBJEXT): src/lib/curl/$(am__dirstamp) \ + src/lib/curl/$(DEPDIR)/$(am__dirstamp) test/run_storage$(EXEEXT): $(test_run_storage_OBJECTS) $(test_run_storage_DEPENDENCIES) $(EXTRA_test_run_storage_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/run_storage$(EXEEXT) @@ -6359,8 +6907,8 @@ test/test_mixramp$(EXEEXT): $(test_test_mixramp_OBJECTS) $(test_test_mixramp_DEPENDENCIES) $(EXTRA_test_test_mixramp_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/test_mixramp$(EXEEXT) $(AM_V_CXXLD)$(test_test_mixramp_LINK) $(test_test_mixramp_OBJECTS) $(test_test_mixramp_LDADD) $(LIBS) -src/test_test_pcm-AudioFormat.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) +test/test_test_pcm-TestAudioFormat.$(OBJEXT): test/$(am__dirstamp) \ + test/$(DEPDIR)/$(am__dirstamp) test/test_test_pcm-test_pcm_dither.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_test_pcm-test_pcm_pack.$(OBJEXT): test/$(am__dirstamp) \ @@ -6373,6 +6921,8 @@ test/$(DEPDIR)/$(am__dirstamp) test/test_test_pcm-test_pcm_mix.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) +test/test_test_pcm-test_pcm_interleave.$(OBJEXT): \ + test/$(am__dirstamp) test/$(DEPDIR)/$(am__dirstamp) test/test_test_pcm-test_pcm_export.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_test_pcm-test_pcm_main.$(OBJEXT): test/$(am__dirstamp) \ @@ -6419,6 +6969,8 @@ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/test_test_translate_song-SongLoader.$(OBJEXT): \ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/test_test_translate_song-LocateUri.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) src/test_test_translate_song-Log.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) test/test_test_translate_song-test_translate_song.$(OBJEXT): \ @@ -6439,12 +6991,6 @@ src/$(DEPDIR)/$(am__dirstamp) src/test_test_vorbis_encoder-LogBackend.$(OBJEXT): \ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/test_test_vorbis_encoder-CheckAudioFormat.$(OBJEXT): \ - src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/test_test_vorbis_encoder-AudioFormat.$(OBJEXT): \ - src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/test_test_vorbis_encoder-AudioParser.$(OBJEXT): \ - src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) test/test_vorbis_encoder$(EXEEXT): $(test_test_vorbis_encoder_OBJECTS) $(test_test_vorbis_encoder_DEPENDENCIES) $(EXTRA_test_test_vorbis_encoder_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/test_vorbis_encoder$(EXEEXT) @@ -6485,23 +7031,29 @@ -rm -f src/input/*.$(OBJEXT) -rm -f src/input/plugins/*.$(OBJEXT) -rm -f src/java/*.$(OBJEXT) + -rm -f src/lib/curl/*.$(OBJEXT) -rm -f src/lib/expat/*.$(OBJEXT) -rm -f src/lib/ffmpeg/*.$(OBJEXT) -rm -f src/lib/icu/*.$(OBJEXT) -rm -f src/lib/nfs/*.$(OBJEXT) + -rm -f src/lib/pulse/*.$(OBJEXT) -rm -f src/lib/smbclient/*.$(OBJEXT) + -rm -f src/lib/sqlite/*.$(OBJEXT) -rm -f src/lib/upnp/*.$(OBJEXT) + -rm -f src/lib/xiph/*.$(OBJEXT) -rm -f src/lib/zlib/*.$(OBJEXT) -rm -f src/mixer/*.$(OBJEXT) -rm -f src/mixer/plugins/*.$(OBJEXT) -rm -f src/neighbor/*.$(OBJEXT) -rm -f src/neighbor/plugins/*.$(OBJEXT) + -rm -f src/net/*.$(OBJEXT) -rm -f src/output/*.$(OBJEXT) -rm -f src/output/plugins/*.$(OBJEXT) -rm -f src/output/plugins/httpd/*.$(OBJEXT) -rm -f src/output/plugins/sles/*.$(OBJEXT) -rm -f src/pcm/*.$(OBJEXT) -rm -f src/pcm/dsd2pcm/*.$(OBJEXT) + -rm -f src/player/*.$(OBJEXT) -rm -f src/playlist/*.$(OBJEXT) -rm -f src/playlist/cue/*.$(OBJEXT) -rm -f src/playlist/plugins/*.$(OBJEXT) @@ -6522,7 +7074,6 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/AudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/AudioParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/CheckAudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/DetachedSong.Po@am__quote@ @@ -6532,24 +7083,21 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/Main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/PlaylistDatabase.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ReplayGainInfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ReplayGainMode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/SongFilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/SongSave.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/TagFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/TagSave.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libinput_a-IcyMetaDataParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmain_a-Main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-AudioConfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-AudioFormat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-AudioParser.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-CommandLine.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-CrossFade.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-DetachedSong.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-GlobalEvents.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-IOThread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Idle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-IdleFlags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Instance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Listen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-LocateUri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-LogBackend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-LogInit.Po@am__quote@ @@ -6559,15 +7107,11 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-MusicPipe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Partition.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Permission.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlayerControl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlayerThread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlaylistError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlaylistFile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlaylistPrint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-PlaylistSave.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-SongFilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-SongLoader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-SongPrint.Po@am__quote@ @@ -6575,6 +7119,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-SongUpdate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-StateFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-Stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-TagArchive.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-TagFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-TagPrint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-TagSave.Po@am__quote@ @@ -6582,6 +7127,9 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-TimePrint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-ls.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libmpd_a-notify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcm_a-AudioFormat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcm_a-AudioParser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_run_avahi-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_run_avahi-LogBackend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_archive-Log.Po@am__quote@ @@ -6590,17 +7138,14 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_icy_parser-LogBackend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_mixramp-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_mixramp-LogBackend.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_pcm-AudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_queue_priority-DetachedSong.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_rewind-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_rewind-LogBackend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_translate_song-DetachedSong.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_translate_song-LocateUri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_translate_song-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_translate_song-PlaylistError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_translate_song-SongLoader.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_vorbis_encoder-Log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_test_vorbis_encoder-LogBackend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/AudioCompress/$(DEPDIR)/compress.Po@am__quote@ @@ -6626,6 +7171,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/$(DEPDIR)/libmpd_a-ClientRead.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/$(DEPDIR)/libmpd_a-ClientSubscribe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/$(DEPDIR)/libmpd_a-ClientWrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/client/$(DEPDIR)/libmpd_a-Response.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-AllCommands.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-CommandError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-CommandListBuilder.Po@am__quote@ @@ -6641,14 +7187,15 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-StickerCommands.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-StorageCommands.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/command/$(DEPDIR)/libmpd_a-TagCommands.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigData.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/Block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigGlobal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigPath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/ConfigTemplates.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/DatabaseError.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/Data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/config/$(DEPDIR)/Param.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/DatabaseLock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/Helpers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/PlaylistVector.Po@am__quote@ @@ -6657,7 +7204,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/UniqueTags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-Configured.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-Count.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-DatabaseError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-DatabaseGlue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-DatabaseLock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-DatabasePlaylist.Po@am__quote@ @@ -6667,7 +7213,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-LightSong.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-PlaylistVector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/$(DEPDIR)/libmpd_a-Selection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/db/plugins/$(DEPDIR)/LazyDatabase.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/plugins/$(DEPDIR)/ProxyDatabasePlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/plugins/simple/$(DEPDIR)/DatabaseSave.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/plugins/simple/$(DEPDIR)/Directory.Po@am__quote@ @@ -6698,13 +7243,14 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/update/$(DEPDIR)/libmpd_a-UpdateIO.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/update/$(DEPDIR)/libmpd_a-UpdateSong.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/db/update/$(DEPDIR)/libmpd_a-Walk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libdecoder_a-DecoderBuffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libdecoder_a-DecoderList.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libdecoder_a-DecoderPlugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libdecoder_a-Reader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-Bridge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderControl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderError.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderPrint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/$(DEPDIR)/libmpd_a-DecoderThread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/FlacMetadata.Po@am__quote@ @@ -6731,8 +7277,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-MpcdecDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-Mpg123DecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggCodec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusDomain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusHead.Po@am__quote@ @@ -6740,18 +7285,16 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-PcmDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-SidplayDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-SndfileDecoderPlugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisDomain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-WavpackDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-WildmidiDecoderPlugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/decoder/plugins/$(DEPDIR)/libmodplug_decoder_plugin_a-ModplugDecoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/$(DEPDIR)/libencoder_plugins_a-EncoderList.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-FlacEncoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-LameEncoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-NullEncoderPlugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OpusEncoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-ShineEncoderPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-TwolameEncoderPlugin.Po@am__quote@ @@ -6763,6 +7306,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/FullyBufferedSocket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/IdleMonitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/Loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/MaskMonitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/MultiSocketMonitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/PollGroupPoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/event/$(DEPDIR)/PollGroupWinSelect.Po@am__quote@ @@ -6773,9 +7317,11 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/FilterConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/FilterPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/FilterRegistry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/Observer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/libmpd_a-FilterConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/libmpd_a-FilterPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/libmpd_a-FilterRegistry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/filter/$(DEPDIR)/libmpd_a-Observer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/plugins/$(DEPDIR)/AutoConvertFilterPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/plugins/$(DEPDIR)/ChainFilterPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/filter/plugins/$(DEPDIR)/ConvertFilterPlugin.Po@am__quote@ @@ -6788,6 +7334,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-Charset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-CheckFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-Config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-FileSystem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/fs/$(DEPDIR)/libfs_a-Path.Po@am__quote@ @@ -6812,6 +7359,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-LocalOpen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-Open.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-ProxyInputStream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-Reader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-Registry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-TextInputStream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/input/$(DEPDIR)/libinput_a-ThreadInputStream.Po@am__quote@ @@ -6828,30 +7376,41 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/java/$(DEPDIR)/File.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/java/$(DEPDIR)/Global.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/java/$(DEPDIR)/String.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/Global.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/Request.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/Version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/libinput_a-Global.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/libinput_a-Request.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/curl/$(DEPDIR)/libinput_a-Version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/expat/$(DEPDIR)/ExpatParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-ExpatParser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Collate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Converter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/icu/$(DEPDIR)/libicu_a-Win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Base.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Blocking.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-FileReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Glue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libinput_a-Manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Base.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Blocking.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-FileReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Glue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/nfs/$(DEPDIR)/libstorage_a-Manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libinput_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libinput_a-Init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libinput_a-Mutex.Po@am__quote@ @@ -6861,11 +7420,11 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libstorage_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libstorage_a-Init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/smbclient/$(DEPDIR)/libstorage_a-Mutex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/ClientInit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/ContentDirectoryService.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/Device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/Discovery.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/Init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/Util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/ixmlwrap.Po@am__quote@ @@ -6873,11 +7432,17 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-ContentDirectoryService.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-Device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-Discovery.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-Init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-Util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/lib/upnp/$(DEPDIR)/libneighbor_a-ixmlwrap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/zlib/$(DEPDIR)/libfs_a-Error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/$(DEPDIR)/MixerControl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/$(DEPDIR)/MixerType.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/$(DEPDIR)/libmpd_a-MixerAll.Po@am__quote@ @@ -6885,15 +7450,25 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/$(DEPDIR)/libmpd_a-MixerType.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/$(DEPDIR)/libmpd_a-Volume.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-AlsaMixerPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OssMixerPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-PulseMixerPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-RoarMixerPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-SoftwareMixerPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-WinmmMixerPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/neighbor/$(DEPDIR)/libneighbor_a-Glue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/neighbor/$(DEPDIR)/libneighbor_a-Registry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/neighbor/plugins/$(DEPDIR)/libneighbor_a-SmbclientNeighborPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/neighbor/plugins/$(DEPDIR)/libneighbor_a-UpnpNeighborPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/AllocatedSocketAddress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/Resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/SocketAddress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/SocketError.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/SocketUtil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/StaticSocketAddress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/net/$(DEPDIR)/ToString.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/Finish.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/Init.Po@am__quote@ @@ -6902,6 +7477,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Domain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Finish.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Internal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-MultipleOutputs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-OutputCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-OutputControl.Po@am__quote@ @@ -6910,10 +7486,13 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-OutputState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-OutputThread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Registry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/libmpd_a-Source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/$(DEPDIR)/liboutput_plugins_a-Timer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-AlsaOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-AoOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-FifoOutputPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-JackOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-NullOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-OSXOutputPlugin.Po@am__quote@ @@ -6924,6 +7503,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-RecorderOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-RoarOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-ShoutOutputPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SolarisOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/$(DEPDIR)/liboutput_plugins_a-WinmmOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/httpd/$(DEPDIR)/liboutput_plugins_a-HttpdClient.Po@am__quote@ @@ -6933,12 +7513,14 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/output/plugins/sles/$(DEPDIR)/liboutput_plugins_a-SlesOutputPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-ChannelsConverter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-ConfiguredResampler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Domain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-FallbackResampler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-FormatConverter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-GlueResampler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Interleave.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-LibsamplerateResampler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Order.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmBuffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmChannels.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmConvert.Po@am__quote@ @@ -6949,6 +7531,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmMix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-PcmPack.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Silence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-SoxrResampler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/$(DEPDIR)/libpcm_a-Volume.Po@am__quote@ @@ -6956,13 +7539,15 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/dsd2pcm/$(DEPDIR)/libpcm_a-dsd2pcm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/dsd2pcm/$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/pcm/dsd2pcm/$(DEPDIR)/noiseshape.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/player/$(DEPDIR)/libmpd_a-Control.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/player/$(DEPDIR)/libmpd_a-CrossFade.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/player/$(DEPDIR)/libmpd_a-Thread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-PlaylistAny.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-PlaylistMapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-PlaylistQueue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-PlaylistSong.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-PlaylistStream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libmpd_a-Print.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libplaylist_plugins_a-MemorySongEnumerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/$(DEPDIR)/test_test_translate_song-PlaylistSong.Po@am__quote@ @@ -6971,6 +7556,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-CuePlaylistPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-EmbeddedCuePlaylistPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-ExtM3uPlaylistPlugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-M3uPlaylistPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-RssPlaylistPlugin.Po@am__quote@ @@ -6999,6 +7585,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/$(DEPDIR)/libstorage_a-MemoryDirectoryReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/$(DEPDIR)/libstorage_a-Registry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/$(DEPDIR)/libstorage_a-StorageInterface.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/plugins/$(DEPDIR)/libstorage_a-LocalStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/plugins/$(DEPDIR)/libstorage_a-NfsStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/storage/plugins/$(DEPDIR)/libstorage_a-SmbclientStorage.Po@am__quote@ @@ -7007,19 +7594,21 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/EventFD.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/EventPipe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/FatalError.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/Resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/FileDescriptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/SignalFD.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/SocketError.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/SocketUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/system/$(DEPDIR)/fd_util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Aiff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-ApeLoader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-ApeReplayGain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-ApeTag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Format.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Generic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Id3Load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-MixRamp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-ReplayGain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Riff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Set.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Settings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-Tag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagBuilder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagConfig.Po@am__quote@ @@ -7028,27 +7617,35 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagNames.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagPool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagRva2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagSettings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagString.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-TagTable.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tag/$(DEPDIR)/libtag_a-VorbisComment.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thread/$(DEPDIR)/Thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/thread/$(DEPDIR)/Util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/unix/$(DEPDIR)/libmpd_a-Daemon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/unix/$(DEPDIR)/libmpd_a-SignalHandlers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/Alloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/AllocatedString.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/ByteReverse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/Error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/DivideString.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/Exception.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/FormatString.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/HugeAllocator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/LazyRandomEngine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/MimeType.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/OptionParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/PeakBuffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/SplitString.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/StringCompare.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/StringUtil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/StringView.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/TimeParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/Tokenizer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/UTF8.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/UriUtil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/WStringCompare.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/bit_reverse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/util/$(DEPDIR)/format.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/win32/$(DEPDIR)/libmpd_a-Win32Main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/zeroconf/$(DEPDIR)/libmpd_a-AvahiPoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/zeroconf/$(DEPDIR)/libmpd_a-ZeroconfAvahi.Po@am__quote@ @@ -7056,10 +7653,12 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/zeroconf/$(DEPDIR)/libmpd_a-ZeroconfGlue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/zeroconf/$(DEPDIR)/test_run_avahi-AvahiPoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/zeroconf/$(DEPDIR)/test_run_avahi-ZeroconfAvahi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/ContainerScan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/DumpDatabase.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/FakeDecoderAPI.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/FakeReplayGainConfig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/ReadApeTags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/ShutdownHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/WriteFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/dump_playlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/dump_rva2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/dump_text_file.Po@am__quote@ @@ -7080,16 +7679,20 @@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/run_resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/run_storage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/software_volume.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_TestFs-TestFs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_TestIcu-TestIcu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_run_avahi-ShutdownHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_run_avahi-run_avahi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_archive-test_archive.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_byte_reverse-test_byte_reverse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_icy_parser-test_icy_parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_mixramp-test_mixramp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_channels.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_dither.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_export.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_format.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_mix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_test_pcm-test_pcm_pack.Po@am__quote@ @@ -7118,6 +7721,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +src/mixer/plugins/libmixer_plugins_a-volume_mapping.o: src/mixer/plugins/volume_mapping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-volume_mapping.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-volume_mapping.o `test -f 'src/mixer/plugins/volume_mapping.c' || echo '$(srcdir)/'`src/mixer/plugins/volume_mapping.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/mixer/plugins/volume_mapping.c' object='src/mixer/plugins/libmixer_plugins_a-volume_mapping.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-volume_mapping.o `test -f 'src/mixer/plugins/volume_mapping.c' || echo '$(srcdir)/'`src/mixer/plugins/volume_mapping.c + +src/mixer/plugins/libmixer_plugins_a-volume_mapping.obj: src/mixer/plugins/volume_mapping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-volume_mapping.obj -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-volume_mapping.obj `if test -f 'src/mixer/plugins/volume_mapping.c'; then $(CYGPATH_W) 'src/mixer/plugins/volume_mapping.c'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/volume_mapping.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-volume_mapping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/mixer/plugins/volume_mapping.c' object='src/mixer/plugins/libmixer_plugins_a-volume_mapping.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-volume_mapping.obj `if test -f 'src/mixer/plugins/volume_mapping.c'; then $(CYGPATH_W) 'src/mixer/plugins/volume_mapping.c'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/volume_mapping.c'; fi` + src/pcm/dsd2pcm/libpcm_a-dsd2pcm.o: src/pcm/dsd2pcm/dsd2pcm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/pcm/dsd2pcm/libpcm_a-dsd2pcm.o -MD -MP -MF src/pcm/dsd2pcm/$(DEPDIR)/libpcm_a-dsd2pcm.Tpo -c -o src/pcm/dsd2pcm/libpcm_a-dsd2pcm.o `test -f 'src/pcm/dsd2pcm/dsd2pcm.c' || echo '$(srcdir)/'`src/pcm/dsd2pcm/dsd2pcm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/pcm/dsd2pcm/$(DEPDIR)/libpcm_a-dsd2pcm.Tpo src/pcm/dsd2pcm/$(DEPDIR)/libpcm_a-dsd2pcm.Po @@ -7132,20 +7749,6 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/pcm/dsd2pcm/libpcm_a-dsd2pcm.obj `if test -f 'src/pcm/dsd2pcm/dsd2pcm.c'; then $(CYGPATH_W) 'src/pcm/dsd2pcm/dsd2pcm.c'; else $(CYGPATH_W) '$(srcdir)/src/pcm/dsd2pcm/dsd2pcm.c'; fi` -src/tag/libtag_a-TagSettings.o: src/tag/TagSettings.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/tag/libtag_a-TagSettings.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-TagSettings.Tpo -c -o src/tag/libtag_a-TagSettings.o `test -f 'src/tag/TagSettings.c' || echo '$(srcdir)/'`src/tag/TagSettings.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-TagSettings.Tpo src/tag/$(DEPDIR)/libtag_a-TagSettings.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tag/TagSettings.c' object='src/tag/libtag_a-TagSettings.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/tag/libtag_a-TagSettings.o `test -f 'src/tag/TagSettings.c' || echo '$(srcdir)/'`src/tag/TagSettings.c - -src/tag/libtag_a-TagSettings.obj: src/tag/TagSettings.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/tag/libtag_a-TagSettings.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-TagSettings.Tpo -c -o src/tag/libtag_a-TagSettings.obj `if test -f 'src/tag/TagSettings.c'; then $(CYGPATH_W) 'src/tag/TagSettings.c'; else $(CYGPATH_W) '$(srcdir)/src/tag/TagSettings.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-TagSettings.Tpo src/tag/$(DEPDIR)/libtag_a-TagSettings.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tag/TagSettings.c' object='src/tag/libtag_a-TagSettings.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/tag/libtag_a-TagSettings.obj `if test -f 'src/tag/TagSettings.c'; then $(CYGPATH_W) 'src/tag/TagSettings.c'; else $(CYGPATH_W) '$(srcdir)/src/tag/TagSettings.c'; fi` - src/tag/libtag_a-TagNames.o: src/tag/TagNames.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/tag/libtag_a-TagNames.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-TagNames.Tpo -c -o src/tag/libtag_a-TagNames.o `test -f 'src/tag/TagNames.c' || echo '$(srcdir)/'`src/tag/TagNames.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-TagNames.Tpo src/tag/$(DEPDIR)/libtag_a-TagNames.Po @@ -7330,6 +7933,34 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-PcmDecoderPlugin.obj `if test -f 'src/decoder/plugins/PcmDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/PcmDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/PcmDecoderPlugin.cxx'; fi` +src/decoder/libdecoder_a-DecoderAPI.o: src/decoder/DecoderAPI.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libdecoder_a-DecoderAPI.o -MD -MP -MF src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Tpo -c -o src/decoder/libdecoder_a-DecoderAPI.o `test -f 'src/decoder/DecoderAPI.cxx' || echo '$(srcdir)/'`src/decoder/DecoderAPI.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Tpo src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderAPI.cxx' object='src/decoder/libdecoder_a-DecoderAPI.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libdecoder_a-DecoderAPI.o `test -f 'src/decoder/DecoderAPI.cxx' || echo '$(srcdir)/'`src/decoder/DecoderAPI.cxx + +src/decoder/libdecoder_a-DecoderAPI.obj: src/decoder/DecoderAPI.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libdecoder_a-DecoderAPI.obj -MD -MP -MF src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Tpo -c -o src/decoder/libdecoder_a-DecoderAPI.obj `if test -f 'src/decoder/DecoderAPI.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderAPI.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderAPI.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Tpo src/decoder/$(DEPDIR)/libdecoder_a-DecoderAPI.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderAPI.cxx' object='src/decoder/libdecoder_a-DecoderAPI.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libdecoder_a-DecoderAPI.obj `if test -f 'src/decoder/DecoderAPI.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderAPI.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderAPI.cxx'; fi` + +src/decoder/libdecoder_a-Reader.o: src/decoder/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libdecoder_a-Reader.o -MD -MP -MF src/decoder/$(DEPDIR)/libdecoder_a-Reader.Tpo -c -o src/decoder/libdecoder_a-Reader.o `test -f 'src/decoder/Reader.cxx' || echo '$(srcdir)/'`src/decoder/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libdecoder_a-Reader.Tpo src/decoder/$(DEPDIR)/libdecoder_a-Reader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/Reader.cxx' object='src/decoder/libdecoder_a-Reader.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libdecoder_a-Reader.o `test -f 'src/decoder/Reader.cxx' || echo '$(srcdir)/'`src/decoder/Reader.cxx + +src/decoder/libdecoder_a-Reader.obj: src/decoder/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libdecoder_a-Reader.obj -MD -MP -MF src/decoder/$(DEPDIR)/libdecoder_a-Reader.Tpo -c -o src/decoder/libdecoder_a-Reader.obj `if test -f 'src/decoder/Reader.cxx'; then $(CYGPATH_W) 'src/decoder/Reader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/Reader.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libdecoder_a-Reader.Tpo src/decoder/$(DEPDIR)/libdecoder_a-Reader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/Reader.cxx' object='src/decoder/libdecoder_a-Reader.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libdecoder_a-Reader.obj `if test -f 'src/decoder/Reader.cxx'; then $(CYGPATH_W) 'src/decoder/Reader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/Reader.cxx'; fi` + src/decoder/libdecoder_a-DecoderBuffer.o: src/decoder/DecoderBuffer.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libdecoder_a-DecoderBuffer.o -MD -MP -MF src/decoder/$(DEPDIR)/libdecoder_a-DecoderBuffer.Tpo -c -o src/decoder/libdecoder_a-DecoderBuffer.o `test -f 'src/decoder/DecoderBuffer.cxx' || echo '$(srcdir)/'`src/decoder/DecoderBuffer.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libdecoder_a-DecoderBuffer.Tpo src/decoder/$(DEPDIR)/libdecoder_a-DecoderBuffer.Po @@ -7456,34 +8087,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-MpcdecDecoderPlugin.obj `if test -f 'src/decoder/plugins/MpcdecDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/MpcdecDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/MpcdecDecoderPlugin.cxx'; fi` -src/decoder/plugins/libdecoder_a-OggUtil.o: src/decoder/plugins/OggUtil.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggUtil.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Tpo -c -o src/decoder/plugins/libdecoder_a-OggUtil.o `test -f 'src/decoder/plugins/OggUtil.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggUtil.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggUtil.cxx' object='src/decoder/plugins/libdecoder_a-OggUtil.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggUtil.o `test -f 'src/decoder/plugins/OggUtil.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggUtil.cxx - -src/decoder/plugins/libdecoder_a-OggUtil.obj: src/decoder/plugins/OggUtil.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggUtil.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Tpo -c -o src/decoder/plugins/libdecoder_a-OggUtil.obj `if test -f 'src/decoder/plugins/OggUtil.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggUtil.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggUtil.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggUtil.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggUtil.cxx' object='src/decoder/plugins/libdecoder_a-OggUtil.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggUtil.obj `if test -f 'src/decoder/plugins/OggUtil.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggUtil.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggUtil.cxx'; fi` - -src/decoder/plugins/libdecoder_a-OggFind.o: src/decoder/plugins/OggFind.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggFind.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Tpo -c -o src/decoder/plugins/libdecoder_a-OggFind.o `test -f 'src/decoder/plugins/OggFind.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggFind.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggFind.cxx' object='src/decoder/plugins/libdecoder_a-OggFind.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggFind.o `test -f 'src/decoder/plugins/OggFind.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggFind.cxx - -src/decoder/plugins/libdecoder_a-OggFind.obj: src/decoder/plugins/OggFind.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggFind.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Tpo -c -o src/decoder/plugins/libdecoder_a-OggFind.obj `if test -f 'src/decoder/plugins/OggFind.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggFind.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggFind.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggFind.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggFind.cxx' object='src/decoder/plugins/libdecoder_a-OggFind.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggFind.obj `if test -f 'src/decoder/plugins/OggFind.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggFind.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggFind.cxx'; fi` - src/decoder/plugins/libdecoder_a-OpusDomain.o: src/decoder/plugins/OpusDomain.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OpusDomain.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusDomain.Tpo -c -o src/decoder/plugins/libdecoder_a-OpusDomain.o `test -f 'src/decoder/plugins/OpusDomain.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OpusDomain.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusDomain.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OpusDomain.Po @@ -7582,19 +8185,19 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-FaadDecoderPlugin.obj `if test -f 'src/decoder/plugins/FaadDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/FaadDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/FaadDecoderPlugin.cxx'; fi` -src/decoder/plugins/libdecoder_a-XiphTags.o: src/decoder/plugins/XiphTags.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-XiphTags.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Tpo -c -o src/decoder/plugins/libdecoder_a-XiphTags.o `test -f 'src/decoder/plugins/XiphTags.cxx' || echo '$(srcdir)/'`src/decoder/plugins/XiphTags.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/XiphTags.cxx' object='src/decoder/plugins/libdecoder_a-XiphTags.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-XiphTags.o `test -f 'src/decoder/plugins/XiphTags.cxx' || echo '$(srcdir)/'`src/decoder/plugins/XiphTags.cxx - -src/decoder/plugins/libdecoder_a-XiphTags.obj: src/decoder/plugins/XiphTags.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-XiphTags.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Tpo -c -o src/decoder/plugins/libdecoder_a-XiphTags.obj `if test -f 'src/decoder/plugins/XiphTags.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/XiphTags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/XiphTags.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-XiphTags.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/XiphTags.cxx' object='src/decoder/plugins/libdecoder_a-XiphTags.obj' libtool=no @AMDEPBACKSLASH@ +src/decoder/plugins/libdecoder_a-OggDecoder.o: src/decoder/plugins/OggDecoder.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggDecoder.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Tpo -c -o src/decoder/plugins/libdecoder_a-OggDecoder.o `test -f 'src/decoder/plugins/OggDecoder.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggDecoder.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggDecoder.cxx' object='src/decoder/plugins/libdecoder_a-OggDecoder.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggDecoder.o `test -f 'src/decoder/plugins/OggDecoder.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggDecoder.cxx + +src/decoder/plugins/libdecoder_a-OggDecoder.obj: src/decoder/plugins/OggDecoder.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggDecoder.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Tpo -c -o src/decoder/plugins/libdecoder_a-OggDecoder.obj `if test -f 'src/decoder/plugins/OggDecoder.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggDecoder.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggDecoder.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggDecoder.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/OggDecoder.cxx' object='src/decoder/plugins/libdecoder_a-OggDecoder.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-XiphTags.obj `if test -f 'src/decoder/plugins/XiphTags.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/XiphTags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/XiphTags.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-OggDecoder.obj `if test -f 'src/decoder/plugins/OggDecoder.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/OggDecoder.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/OggDecoder.cxx'; fi` src/decoder/plugins/libdecoder_a-OggCodec.o: src/decoder/plugins/OggCodec.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-OggCodec.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-OggCodec.Tpo -c -o src/decoder/plugins/libdecoder_a-OggCodec.o `test -f 'src/decoder/plugins/OggCodec.cxx' || echo '$(srcdir)/'`src/decoder/plugins/OggCodec.cxx @@ -7624,20 +8227,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-VorbisDomain.obj `if test -f 'src/decoder/plugins/VorbisDomain.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/VorbisDomain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/VorbisDomain.cxx'; fi` -src/decoder/plugins/libdecoder_a-VorbisComments.o: src/decoder/plugins/VorbisComments.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-VorbisComments.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Tpo -c -o src/decoder/plugins/libdecoder_a-VorbisComments.o `test -f 'src/decoder/plugins/VorbisComments.cxx' || echo '$(srcdir)/'`src/decoder/plugins/VorbisComments.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/VorbisComments.cxx' object='src/decoder/plugins/libdecoder_a-VorbisComments.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-VorbisComments.o `test -f 'src/decoder/plugins/VorbisComments.cxx' || echo '$(srcdir)/'`src/decoder/plugins/VorbisComments.cxx - -src/decoder/plugins/libdecoder_a-VorbisComments.obj: src/decoder/plugins/VorbisComments.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-VorbisComments.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Tpo -c -o src/decoder/plugins/libdecoder_a-VorbisComments.obj `if test -f 'src/decoder/plugins/VorbisComments.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/VorbisComments.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/VorbisComments.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisComments.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/VorbisComments.cxx' object='src/decoder/plugins/libdecoder_a-VorbisComments.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-VorbisComments.obj `if test -f 'src/decoder/plugins/VorbisComments.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/VorbisComments.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/VorbisComments.cxx'; fi` - src/decoder/plugins/libdecoder_a-VorbisDecoderPlugin.o: src/decoder/plugins/VorbisDecoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-VorbisDecoderPlugin.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisDecoderPlugin.Tpo -c -o src/decoder/plugins/libdecoder_a-VorbisDecoderPlugin.o `test -f 'src/decoder/plugins/VorbisDecoderPlugin.cxx' || echo '$(srcdir)/'`src/decoder/plugins/VorbisDecoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisDecoderPlugin.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-VorbisDecoderPlugin.Po @@ -7890,6 +8479,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-GmeDecoderPlugin.obj `if test -f 'src/decoder/plugins/GmeDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/GmeDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/GmeDecoderPlugin.cxx'; fi` +src/encoder/libencoder_plugins_a-ToOutputStream.o: src/encoder/ToOutputStream.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/libencoder_plugins_a-ToOutputStream.o -MD -MP -MF src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Tpo -c -o src/encoder/libencoder_plugins_a-ToOutputStream.o `test -f 'src/encoder/ToOutputStream.cxx' || echo '$(srcdir)/'`src/encoder/ToOutputStream.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Tpo src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/encoder/ToOutputStream.cxx' object='src/encoder/libencoder_plugins_a-ToOutputStream.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/libencoder_plugins_a-ToOutputStream.o `test -f 'src/encoder/ToOutputStream.cxx' || echo '$(srcdir)/'`src/encoder/ToOutputStream.cxx + +src/encoder/libencoder_plugins_a-ToOutputStream.obj: src/encoder/ToOutputStream.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/libencoder_plugins_a-ToOutputStream.obj -MD -MP -MF src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Tpo -c -o src/encoder/libencoder_plugins_a-ToOutputStream.obj `if test -f 'src/encoder/ToOutputStream.cxx'; then $(CYGPATH_W) 'src/encoder/ToOutputStream.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/ToOutputStream.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Tpo src/encoder/$(DEPDIR)/libencoder_plugins_a-ToOutputStream.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/encoder/ToOutputStream.cxx' object='src/encoder/libencoder_plugins_a-ToOutputStream.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/libencoder_plugins_a-ToOutputStream.obj `if test -f 'src/encoder/ToOutputStream.cxx'; then $(CYGPATH_W) 'src/encoder/ToOutputStream.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/ToOutputStream.cxx'; fi` + src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.o: src/encoder/plugins/NullEncoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.o -MD -MP -MF src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-NullEncoderPlugin.Tpo -c -o src/encoder/plugins/libencoder_plugins_a-NullEncoderPlugin.o `test -f 'src/encoder/plugins/NullEncoderPlugin.cxx' || echo '$(srcdir)/'`src/encoder/plugins/NullEncoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-NullEncoderPlugin.Tpo src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-NullEncoderPlugin.Po @@ -7918,20 +8521,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/libencoder_plugins_a-EncoderList.obj `if test -f 'src/encoder/EncoderList.cxx'; then $(CYGPATH_W) 'src/encoder/EncoderList.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/EncoderList.cxx'; fi` -src/encoder/plugins/libencoder_plugins_a-OggSerial.o: src/encoder/plugins/OggSerial.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/plugins/libencoder_plugins_a-OggSerial.o -MD -MP -MF src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Tpo -c -o src/encoder/plugins/libencoder_plugins_a-OggSerial.o `test -f 'src/encoder/plugins/OggSerial.cxx' || echo '$(srcdir)/'`src/encoder/plugins/OggSerial.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Tpo src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/encoder/plugins/OggSerial.cxx' object='src/encoder/plugins/libencoder_plugins_a-OggSerial.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/plugins/libencoder_plugins_a-OggSerial.o `test -f 'src/encoder/plugins/OggSerial.cxx' || echo '$(srcdir)/'`src/encoder/plugins/OggSerial.cxx - -src/encoder/plugins/libencoder_plugins_a-OggSerial.obj: src/encoder/plugins/OggSerial.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/plugins/libencoder_plugins_a-OggSerial.obj -MD -MP -MF src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Tpo -c -o src/encoder/plugins/libencoder_plugins_a-OggSerial.obj `if test -f 'src/encoder/plugins/OggSerial.cxx'; then $(CYGPATH_W) 'src/encoder/plugins/OggSerial.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/plugins/OggSerial.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Tpo src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-OggSerial.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/encoder/plugins/OggSerial.cxx' object='src/encoder/plugins/libencoder_plugins_a-OggSerial.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/plugins/libencoder_plugins_a-OggSerial.obj `if test -f 'src/encoder/plugins/OggSerial.cxx'; then $(CYGPATH_W) 'src/encoder/plugins/OggSerial.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/plugins/OggSerial.cxx'; fi` - src/encoder/plugins/libencoder_plugins_a-WaveEncoderPlugin.o: src/encoder/plugins/WaveEncoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/encoder/plugins/libencoder_plugins_a-WaveEncoderPlugin.o -MD -MP -MF src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-WaveEncoderPlugin.Tpo -c -o src/encoder/plugins/libencoder_plugins_a-WaveEncoderPlugin.o `test -f 'src/encoder/plugins/WaveEncoderPlugin.cxx' || echo '$(srcdir)/'`src/encoder/plugins/WaveEncoderPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-WaveEncoderPlugin.Tpo src/encoder/plugins/$(DEPDIR)/libencoder_plugins_a-WaveEncoderPlugin.Po @@ -8324,19 +8913,33 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-CheckFile.obj `if test -f 'src/fs/CheckFile.cxx'; then $(CYGPATH_W) 'src/fs/CheckFile.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/CheckFile.cxx'; fi` -src/lib/zlib/libfs_a-Domain.o: src/lib/zlib/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/zlib/libfs_a-Domain.o -MD -MP -MF src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Tpo -c -o src/lib/zlib/libfs_a-Domain.o `test -f 'src/lib/zlib/Domain.cxx' || echo '$(srcdir)/'`src/lib/zlib/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Tpo src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/zlib/Domain.cxx' object='src/lib/zlib/libfs_a-Domain.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/zlib/libfs_a-Domain.o `test -f 'src/lib/zlib/Domain.cxx' || echo '$(srcdir)/'`src/lib/zlib/Domain.cxx - -src/lib/zlib/libfs_a-Domain.obj: src/lib/zlib/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/zlib/libfs_a-Domain.obj -MD -MP -MF src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Tpo -c -o src/lib/zlib/libfs_a-Domain.obj `if test -f 'src/lib/zlib/Domain.cxx'; then $(CYGPATH_W) 'src/lib/zlib/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/zlib/Domain.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Tpo src/lib/zlib/$(DEPDIR)/libfs_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/zlib/Domain.cxx' object='src/lib/zlib/libfs_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ +src/fs/libfs_a-DirectoryReader.o: src/fs/DirectoryReader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/libfs_a-DirectoryReader.o -MD -MP -MF src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Tpo -c -o src/fs/libfs_a-DirectoryReader.o `test -f 'src/fs/DirectoryReader.cxx' || echo '$(srcdir)/'`src/fs/DirectoryReader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Tpo src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fs/DirectoryReader.cxx' object='src/fs/libfs_a-DirectoryReader.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-DirectoryReader.o `test -f 'src/fs/DirectoryReader.cxx' || echo '$(srcdir)/'`src/fs/DirectoryReader.cxx + +src/fs/libfs_a-DirectoryReader.obj: src/fs/DirectoryReader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/libfs_a-DirectoryReader.obj -MD -MP -MF src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Tpo -c -o src/fs/libfs_a-DirectoryReader.obj `if test -f 'src/fs/DirectoryReader.cxx'; then $(CYGPATH_W) 'src/fs/DirectoryReader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/DirectoryReader.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Tpo src/fs/$(DEPDIR)/libfs_a-DirectoryReader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fs/DirectoryReader.cxx' object='src/fs/libfs_a-DirectoryReader.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-DirectoryReader.obj `if test -f 'src/fs/DirectoryReader.cxx'; then $(CYGPATH_W) 'src/fs/DirectoryReader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/DirectoryReader.cxx'; fi` + +src/lib/zlib/libfs_a-Error.o: src/lib/zlib/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/zlib/libfs_a-Error.o -MD -MP -MF src/lib/zlib/$(DEPDIR)/libfs_a-Error.Tpo -c -o src/lib/zlib/libfs_a-Error.o `test -f 'src/lib/zlib/Error.cxx' || echo '$(srcdir)/'`src/lib/zlib/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/zlib/$(DEPDIR)/libfs_a-Error.Tpo src/lib/zlib/$(DEPDIR)/libfs_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/zlib/Error.cxx' object='src/lib/zlib/libfs_a-Error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/zlib/libfs_a-Error.o `test -f 'src/lib/zlib/Error.cxx' || echo '$(srcdir)/'`src/lib/zlib/Error.cxx + +src/lib/zlib/libfs_a-Error.obj: src/lib/zlib/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/zlib/libfs_a-Error.obj -MD -MP -MF src/lib/zlib/$(DEPDIR)/libfs_a-Error.Tpo -c -o src/lib/zlib/libfs_a-Error.obj `if test -f 'src/lib/zlib/Error.cxx'; then $(CYGPATH_W) 'src/lib/zlib/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/zlib/Error.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/zlib/$(DEPDIR)/libfs_a-Error.Tpo src/lib/zlib/$(DEPDIR)/libfs_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/zlib/Error.cxx' object='src/lib/zlib/libfs_a-Error.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/zlib/libfs_a-Domain.obj `if test -f 'src/lib/zlib/Domain.cxx'; then $(CYGPATH_W) 'src/lib/zlib/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/zlib/Domain.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/zlib/libfs_a-Error.obj `if test -f 'src/lib/zlib/Error.cxx'; then $(CYGPATH_W) 'src/lib/zlib/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/zlib/Error.cxx'; fi` src/fs/io/libfs_a-GunzipReader.o: src/fs/io/GunzipReader.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/io/libfs_a-GunzipReader.o -MD -MP -MF src/fs/io/$(DEPDIR)/libfs_a-GunzipReader.Tpo -c -o src/fs/io/libfs_a-GunzipReader.o `test -f 'src/fs/io/GunzipReader.cxx' || echo '$(srcdir)/'`src/fs/io/GunzipReader.cxx @@ -8394,19 +8997,33 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Collate.obj `if test -f 'src/lib/icu/Collate.cxx'; then $(CYGPATH_W) 'src/lib/icu/Collate.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Collate.cxx'; fi` -src/lib/icu/libicu_a-Error.o: src/lib/icu/Error.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Error.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Error.Tpo -c -o src/lib/icu/libicu_a-Error.o `test -f 'src/lib/icu/Error.cxx' || echo '$(srcdir)/'`src/lib/icu/Error.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Error.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Error.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Error.cxx' object='src/lib/icu/libicu_a-Error.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Error.o `test -f 'src/lib/icu/Error.cxx' || echo '$(srcdir)/'`src/lib/icu/Error.cxx - -src/lib/icu/libicu_a-Error.obj: src/lib/icu/Error.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Error.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Error.Tpo -c -o src/lib/icu/libicu_a-Error.obj `if test -f 'src/lib/icu/Error.cxx'; then $(CYGPATH_W) 'src/lib/icu/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Error.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Error.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Error.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Error.cxx' object='src/lib/icu/libicu_a-Error.obj' libtool=no @AMDEPBACKSLASH@ +src/lib/icu/libicu_a-Converter.o: src/lib/icu/Converter.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Converter.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Converter.Tpo -c -o src/lib/icu/libicu_a-Converter.o `test -f 'src/lib/icu/Converter.cxx' || echo '$(srcdir)/'`src/lib/icu/Converter.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Converter.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Converter.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Converter.cxx' object='src/lib/icu/libicu_a-Converter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Converter.o `test -f 'src/lib/icu/Converter.cxx' || echo '$(srcdir)/'`src/lib/icu/Converter.cxx + +src/lib/icu/libicu_a-Converter.obj: src/lib/icu/Converter.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Converter.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Converter.Tpo -c -o src/lib/icu/libicu_a-Converter.obj `if test -f 'src/lib/icu/Converter.cxx'; then $(CYGPATH_W) 'src/lib/icu/Converter.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Converter.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Converter.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Converter.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Converter.cxx' object='src/lib/icu/libicu_a-Converter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Converter.obj `if test -f 'src/lib/icu/Converter.cxx'; then $(CYGPATH_W) 'src/lib/icu/Converter.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Converter.cxx'; fi` + +src/lib/icu/libicu_a-Util.o: src/lib/icu/Util.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Util.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Util.Tpo -c -o src/lib/icu/libicu_a-Util.o `test -f 'src/lib/icu/Util.cxx' || echo '$(srcdir)/'`src/lib/icu/Util.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Util.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Util.cxx' object='src/lib/icu/libicu_a-Util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Util.o `test -f 'src/lib/icu/Util.cxx' || echo '$(srcdir)/'`src/lib/icu/Util.cxx + +src/lib/icu/libicu_a-Util.obj: src/lib/icu/Util.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Util.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Util.Tpo -c -o src/lib/icu/libicu_a-Util.obj `if test -f 'src/lib/icu/Util.cxx'; then $(CYGPATH_W) 'src/lib/icu/Util.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Util.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Util.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Util.cxx' object='src/lib/icu/libicu_a-Util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Error.obj `if test -f 'src/lib/icu/Error.cxx'; then $(CYGPATH_W) 'src/lib/icu/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Error.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Util.obj `if test -f 'src/lib/icu/Util.cxx'; then $(CYGPATH_W) 'src/lib/icu/Util.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Util.cxx'; fi` src/lib/icu/libicu_a-Init.o: src/lib/icu/Init.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Init.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Init.Tpo -c -o src/lib/icu/libicu_a-Init.o `test -f 'src/lib/icu/Init.cxx' || echo '$(srcdir)/'`src/lib/icu/Init.cxx @@ -8422,6 +9039,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Init.obj `if test -f 'src/lib/icu/Init.cxx'; then $(CYGPATH_W) 'src/lib/icu/Init.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Init.cxx'; fi` +src/lib/icu/libicu_a-Win32.o: src/lib/icu/Win32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Win32.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Win32.Tpo -c -o src/lib/icu/libicu_a-Win32.o `test -f 'src/lib/icu/Win32.cxx' || echo '$(srcdir)/'`src/lib/icu/Win32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Win32.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Win32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Win32.cxx' object='src/lib/icu/libicu_a-Win32.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Win32.o `test -f 'src/lib/icu/Win32.cxx' || echo '$(srcdir)/'`src/lib/icu/Win32.cxx + +src/lib/icu/libicu_a-Win32.obj: src/lib/icu/Win32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Win32.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Win32.Tpo -c -o src/lib/icu/libicu_a-Win32.obj `if test -f 'src/lib/icu/Win32.cxx'; then $(CYGPATH_W) 'src/lib/icu/Win32.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Win32.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Win32.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Win32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/icu/Win32.cxx' object='src/lib/icu/libicu_a-Win32.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Win32.obj `if test -f 'src/lib/icu/Win32.cxx'; then $(CYGPATH_W) 'src/lib/icu/Win32.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Win32.cxx'; fi` + src/input/libinput_a-Domain.o: src/input/Domain.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/input/libinput_a-Domain.o -MD -MP -MF src/input/$(DEPDIR)/libinput_a-Domain.Tpo -c -o src/input/libinput_a-Domain.o `test -f 'src/input/Domain.cxx' || echo '$(srcdir)/'`src/input/Domain.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/input/$(DEPDIR)/libinput_a-Domain.Tpo src/input/$(DEPDIR)/libinput_a-Domain.Po @@ -8506,6 +9137,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/input/libinput_a-InputStream.obj `if test -f 'src/input/InputStream.cxx'; then $(CYGPATH_W) 'src/input/InputStream.cxx'; else $(CYGPATH_W) '$(srcdir)/src/input/InputStream.cxx'; fi` +src/input/libinput_a-Reader.o: src/input/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/input/libinput_a-Reader.o -MD -MP -MF src/input/$(DEPDIR)/libinput_a-Reader.Tpo -c -o src/input/libinput_a-Reader.o `test -f 'src/input/Reader.cxx' || echo '$(srcdir)/'`src/input/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/input/$(DEPDIR)/libinput_a-Reader.Tpo src/input/$(DEPDIR)/libinput_a-Reader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/input/Reader.cxx' object='src/input/libinput_a-Reader.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/input/libinput_a-Reader.o `test -f 'src/input/Reader.cxx' || echo '$(srcdir)/'`src/input/Reader.cxx + +src/input/libinput_a-Reader.obj: src/input/Reader.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/input/libinput_a-Reader.obj -MD -MP -MF src/input/$(DEPDIR)/libinput_a-Reader.Tpo -c -o src/input/libinput_a-Reader.obj `if test -f 'src/input/Reader.cxx'; then $(CYGPATH_W) 'src/input/Reader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/input/Reader.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/input/$(DEPDIR)/libinput_a-Reader.Tpo src/input/$(DEPDIR)/libinput_a-Reader.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/input/Reader.cxx' object='src/input/libinput_a-Reader.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/input/libinput_a-Reader.obj `if test -f 'src/input/Reader.cxx'; then $(CYGPATH_W) 'src/input/Reader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/input/Reader.cxx'; fi` + src/input/libinput_a-TextInputStream.o: src/input/TextInputStream.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/input/libinput_a-TextInputStream.o -MD -MP -MF src/input/$(DEPDIR)/libinput_a-TextInputStream.Tpo -c -o src/input/libinput_a-TextInputStream.o `test -f 'src/input/TextInputStream.cxx' || echo '$(srcdir)/'`src/input/TextInputStream.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/input/$(DEPDIR)/libinput_a-TextInputStream.Tpo src/input/$(DEPDIR)/libinput_a-TextInputStream.Po @@ -8632,6 +9277,48 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/input/plugins/libinput_a-CurlInputPlugin.obj `if test -f 'src/input/plugins/CurlInputPlugin.cxx'; then $(CYGPATH_W) 'src/input/plugins/CurlInputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/input/plugins/CurlInputPlugin.cxx'; fi` +src/lib/curl/libinput_a-Version.o: src/lib/curl/Version.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Version.o -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Version.Tpo -c -o src/lib/curl/libinput_a-Version.o `test -f 'src/lib/curl/Version.cxx' || echo '$(srcdir)/'`src/lib/curl/Version.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Version.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Version.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Version.cxx' object='src/lib/curl/libinput_a-Version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Version.o `test -f 'src/lib/curl/Version.cxx' || echo '$(srcdir)/'`src/lib/curl/Version.cxx + +src/lib/curl/libinput_a-Version.obj: src/lib/curl/Version.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Version.obj -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Version.Tpo -c -o src/lib/curl/libinput_a-Version.obj `if test -f 'src/lib/curl/Version.cxx'; then $(CYGPATH_W) 'src/lib/curl/Version.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Version.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Version.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Version.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Version.cxx' object='src/lib/curl/libinput_a-Version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Version.obj `if test -f 'src/lib/curl/Version.cxx'; then $(CYGPATH_W) 'src/lib/curl/Version.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Version.cxx'; fi` + +src/lib/curl/libinput_a-Global.o: src/lib/curl/Global.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Global.o -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Global.Tpo -c -o src/lib/curl/libinput_a-Global.o `test -f 'src/lib/curl/Global.cxx' || echo '$(srcdir)/'`src/lib/curl/Global.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Global.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Global.cxx' object='src/lib/curl/libinput_a-Global.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Global.o `test -f 'src/lib/curl/Global.cxx' || echo '$(srcdir)/'`src/lib/curl/Global.cxx + +src/lib/curl/libinput_a-Global.obj: src/lib/curl/Global.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Global.obj -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Global.Tpo -c -o src/lib/curl/libinput_a-Global.obj `if test -f 'src/lib/curl/Global.cxx'; then $(CYGPATH_W) 'src/lib/curl/Global.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Global.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Global.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Global.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Global.cxx' object='src/lib/curl/libinput_a-Global.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Global.obj `if test -f 'src/lib/curl/Global.cxx'; then $(CYGPATH_W) 'src/lib/curl/Global.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Global.cxx'; fi` + +src/lib/curl/libinput_a-Request.o: src/lib/curl/Request.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Request.o -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Request.Tpo -c -o src/lib/curl/libinput_a-Request.o `test -f 'src/lib/curl/Request.cxx' || echo '$(srcdir)/'`src/lib/curl/Request.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Request.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Request.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Request.cxx' object='src/lib/curl/libinput_a-Request.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Request.o `test -f 'src/lib/curl/Request.cxx' || echo '$(srcdir)/'`src/lib/curl/Request.cxx + +src/lib/curl/libinput_a-Request.obj: src/lib/curl/Request.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/curl/libinput_a-Request.obj -MD -MP -MF src/lib/curl/$(DEPDIR)/libinput_a-Request.Tpo -c -o src/lib/curl/libinput_a-Request.obj `if test -f 'src/lib/curl/Request.cxx'; then $(CYGPATH_W) 'src/lib/curl/Request.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Request.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/curl/$(DEPDIR)/libinput_a-Request.Tpo src/lib/curl/$(DEPDIR)/libinput_a-Request.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/curl/Request.cxx' object='src/lib/curl/libinput_a-Request.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/curl/libinput_a-Request.obj `if test -f 'src/lib/curl/Request.cxx'; then $(CYGPATH_W) 'src/lib/curl/Request.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/curl/Request.cxx'; fi` + src/libinput_a-IcyMetaDataParser.o: src/IcyMetaDataParser.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libinput_a-IcyMetaDataParser.o -MD -MP -MF src/$(DEPDIR)/libinput_a-IcyMetaDataParser.Tpo -c -o src/libinput_a-IcyMetaDataParser.o `test -f 'src/IcyMetaDataParser.cxx' || echo '$(srcdir)/'`src/IcyMetaDataParser.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libinput_a-IcyMetaDataParser.Tpo src/$(DEPDIR)/libinput_a-IcyMetaDataParser.Po @@ -8786,20 +9473,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libinput_a-Blocking.obj `if test -f 'src/lib/nfs/Blocking.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Blocking.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Blocking.cxx'; fi` -src/lib/nfs/libinput_a-Domain.o: src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/nfs/libinput_a-Domain.o -MD -MP -MF src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Tpo -c -o src/lib/nfs/libinput_a-Domain.o `test -f 'src/lib/nfs/Domain.cxx' || echo '$(srcdir)/'`src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Tpo src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/nfs/Domain.cxx' object='src/lib/nfs/libinput_a-Domain.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libinput_a-Domain.o `test -f 'src/lib/nfs/Domain.cxx' || echo '$(srcdir)/'`src/lib/nfs/Domain.cxx - -src/lib/nfs/libinput_a-Domain.obj: src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/nfs/libinput_a-Domain.obj -MD -MP -MF src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Tpo -c -o src/lib/nfs/libinput_a-Domain.obj `if test -f 'src/lib/nfs/Domain.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Domain.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Tpo src/lib/nfs/$(DEPDIR)/libinput_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/nfs/Domain.cxx' object='src/lib/nfs/libinput_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libinput_a-Domain.obj `if test -f 'src/lib/nfs/Domain.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Domain.cxx'; fi` - src/input/plugins/libinput_a-NfsInputPlugin.o: src/input/plugins/NfsInputPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinput_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/input/plugins/libinput_a-NfsInputPlugin.o -MD -MP -MF src/input/plugins/$(DEPDIR)/libinput_a-NfsInputPlugin.Tpo -c -o src/input/plugins/libinput_a-NfsInputPlugin.o `test -f 'src/input/plugins/NfsInputPlugin.cxx' || echo '$(srcdir)/'`src/input/plugins/NfsInputPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/input/plugins/$(DEPDIR)/libinput_a-NfsInputPlugin.Tpo src/input/plugins/$(DEPDIR)/libinput_a-NfsInputPlugin.Po @@ -8870,6 +9543,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmain_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmain_a-Main.obj `if test -f 'src/Main.cxx'; then $(CYGPATH_W) 'src/Main.cxx'; else $(CYGPATH_W) '$(srcdir)/src/Main.cxx'; fi` +src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.o: src/mixer/plugins/NullMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.o `test -f 'src/mixer/plugins/NullMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/NullMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/mixer/plugins/NullMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.o `test -f 'src/mixer/plugins/NullMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/NullMixerPlugin.cxx + +src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.obj: src/mixer/plugins/NullMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.obj -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.obj `if test -f 'src/mixer/plugins/NullMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/NullMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/NullMixerPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/mixer/plugins/NullMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.obj `if test -f 'src/mixer/plugins/NullMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/NullMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/NullMixerPlugin.cxx'; fi` + src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.o: src/mixer/plugins/SoftwareMixerPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-SoftwareMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.o `test -f 'src/mixer/plugins/SoftwareMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/SoftwareMixerPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-SoftwareMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-SoftwareMixerPlugin.Po @@ -8912,6 +9599,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-RoarMixerPlugin.obj `if test -f 'src/mixer/plugins/RoarMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/RoarMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/RoarMixerPlugin.cxx'; fi` +src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.o: src/mixer/plugins/HaikuMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.o `test -f 'src/mixer/plugins/HaikuMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/HaikuMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/mixer/plugins/HaikuMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.o `test -f 'src/mixer/plugins/HaikuMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/HaikuMixerPlugin.cxx + +src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.obj: src/mixer/plugins/HaikuMixerPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.obj -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.obj `if test -f 'src/mixer/plugins/HaikuMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/HaikuMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/HaikuMixerPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/mixer/plugins/HaikuMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.obj `if test -f 'src/mixer/plugins/HaikuMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/HaikuMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/HaikuMixerPlugin.cxx'; fi` + src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.o: src/mixer/plugins/OssMixerPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OssMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.o `test -f 'src/mixer/plugins/OssMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/OssMixerPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OssMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OssMixerPlugin.Po @@ -8968,6 +9669,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodplug_decoder_plugin_a_CPPFLAGS) $(CPPFLAGS) $(libmodplug_decoder_plugin_a_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libmodplug_decoder_plugin_a-ModplugDecoderPlugin.obj `if test -f 'src/decoder/plugins/ModplugDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/ModplugDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/ModplugDecoderPlugin.cxx'; fi` +src/output/libmpd_a-Internal.o: src/output/Internal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-Internal.o -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-Internal.Tpo -c -o src/output/libmpd_a-Internal.o `test -f 'src/output/Internal.cxx' || echo '$(srcdir)/'`src/output/Internal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-Internal.Tpo src/output/$(DEPDIR)/libmpd_a-Internal.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/Internal.cxx' object='src/output/libmpd_a-Internal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-Internal.o `test -f 'src/output/Internal.cxx' || echo '$(srcdir)/'`src/output/Internal.cxx + +src/output/libmpd_a-Internal.obj: src/output/Internal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-Internal.obj -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-Internal.Tpo -c -o src/output/libmpd_a-Internal.obj `if test -f 'src/output/Internal.cxx'; then $(CYGPATH_W) 'src/output/Internal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/Internal.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-Internal.Tpo src/output/$(DEPDIR)/libmpd_a-Internal.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/Internal.cxx' object='src/output/libmpd_a-Internal.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-Internal.obj `if test -f 'src/output/Internal.cxx'; then $(CYGPATH_W) 'src/output/Internal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/Internal.cxx'; fi` + src/output/libmpd_a-Registry.o: src/output/Registry.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-Registry.o -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-Registry.Tpo -c -o src/output/libmpd_a-Registry.o `test -f 'src/output/Registry.cxx' || echo '$(srcdir)/'`src/output/Registry.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-Registry.Tpo src/output/$(DEPDIR)/libmpd_a-Registry.Po @@ -8996,6 +9711,34 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-MultipleOutputs.obj `if test -f 'src/output/MultipleOutputs.cxx'; then $(CYGPATH_W) 'src/output/MultipleOutputs.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/MultipleOutputs.cxx'; fi` +src/output/libmpd_a-SharedPipeConsumer.o: src/output/SharedPipeConsumer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-SharedPipeConsumer.o -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Tpo -c -o src/output/libmpd_a-SharedPipeConsumer.o `test -f 'src/output/SharedPipeConsumer.cxx' || echo '$(srcdir)/'`src/output/SharedPipeConsumer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Tpo src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/SharedPipeConsumer.cxx' object='src/output/libmpd_a-SharedPipeConsumer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-SharedPipeConsumer.o `test -f 'src/output/SharedPipeConsumer.cxx' || echo '$(srcdir)/'`src/output/SharedPipeConsumer.cxx + +src/output/libmpd_a-SharedPipeConsumer.obj: src/output/SharedPipeConsumer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-SharedPipeConsumer.obj -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Tpo -c -o src/output/libmpd_a-SharedPipeConsumer.obj `if test -f 'src/output/SharedPipeConsumer.cxx'; then $(CYGPATH_W) 'src/output/SharedPipeConsumer.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/SharedPipeConsumer.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Tpo src/output/$(DEPDIR)/libmpd_a-SharedPipeConsumer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/SharedPipeConsumer.cxx' object='src/output/libmpd_a-SharedPipeConsumer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-SharedPipeConsumer.obj `if test -f 'src/output/SharedPipeConsumer.cxx'; then $(CYGPATH_W) 'src/output/SharedPipeConsumer.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/SharedPipeConsumer.cxx'; fi` + +src/output/libmpd_a-Source.o: src/output/Source.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-Source.o -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-Source.Tpo -c -o src/output/libmpd_a-Source.o `test -f 'src/output/Source.cxx' || echo '$(srcdir)/'`src/output/Source.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-Source.Tpo src/output/$(DEPDIR)/libmpd_a-Source.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/Source.cxx' object='src/output/libmpd_a-Source.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-Source.o `test -f 'src/output/Source.cxx' || echo '$(srcdir)/'`src/output/Source.cxx + +src/output/libmpd_a-Source.obj: src/output/Source.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-Source.obj -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-Source.Tpo -c -o src/output/libmpd_a-Source.obj `if test -f 'src/output/Source.cxx'; then $(CYGPATH_W) 'src/output/Source.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/Source.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-Source.Tpo src/output/$(DEPDIR)/libmpd_a-Source.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/Source.cxx' object='src/output/libmpd_a-Source.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/libmpd_a-Source.obj `if test -f 'src/output/Source.cxx'; then $(CYGPATH_W) 'src/output/Source.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/Source.cxx'; fi` + src/output/libmpd_a-OutputThread.o: src/output/OutputThread.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/libmpd_a-OutputThread.o -MD -MP -MF src/output/$(DEPDIR)/libmpd_a-OutputThread.Tpo -c -o src/output/libmpd_a-OutputThread.o `test -f 'src/output/OutputThread.cxx' || echo '$(srcdir)/'`src/output/OutputThread.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/$(DEPDIR)/libmpd_a-OutputThread.Tpo src/output/$(DEPDIR)/libmpd_a-OutputThread.Po @@ -9178,62 +9921,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-notify.obj `if test -f 'src/notify.cxx'; then $(CYGPATH_W) 'src/notify.cxx'; else $(CYGPATH_W) '$(srcdir)/src/notify.cxx'; fi` -src/libmpd_a-AudioConfig.o: src/AudioConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioConfig.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioConfig.Tpo -c -o src/libmpd_a-AudioConfig.o `test -f 'src/AudioConfig.cxx' || echo '$(srcdir)/'`src/AudioConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioConfig.Tpo src/$(DEPDIR)/libmpd_a-AudioConfig.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioConfig.cxx' object='src/libmpd_a-AudioConfig.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioConfig.o `test -f 'src/AudioConfig.cxx' || echo '$(srcdir)/'`src/AudioConfig.cxx - -src/libmpd_a-AudioConfig.obj: src/AudioConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioConfig.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioConfig.Tpo -c -o src/libmpd_a-AudioConfig.obj `if test -f 'src/AudioConfig.cxx'; then $(CYGPATH_W) 'src/AudioConfig.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioConfig.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioConfig.Tpo src/$(DEPDIR)/libmpd_a-AudioConfig.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioConfig.cxx' object='src/libmpd_a-AudioConfig.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioConfig.obj `if test -f 'src/AudioConfig.cxx'; then $(CYGPATH_W) 'src/AudioConfig.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioConfig.cxx'; fi` - -src/libmpd_a-CheckAudioFormat.o: src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-CheckAudioFormat.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Tpo -c -o src/libmpd_a-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Tpo src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/libmpd_a-CheckAudioFormat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx - -src/libmpd_a-CheckAudioFormat.obj: src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-CheckAudioFormat.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Tpo -c -o src/libmpd_a-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Tpo src/$(DEPDIR)/libmpd_a-CheckAudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/libmpd_a-CheckAudioFormat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` - -src/libmpd_a-AudioFormat.o: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioFormat.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioFormat.Tpo -c -o src/libmpd_a-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioFormat.Tpo src/$(DEPDIR)/libmpd_a-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/libmpd_a-AudioFormat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx - -src/libmpd_a-AudioFormat.obj: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioFormat.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioFormat.Tpo -c -o src/libmpd_a-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioFormat.Tpo src/$(DEPDIR)/libmpd_a-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/libmpd_a-AudioFormat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` - -src/libmpd_a-AudioParser.o: src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioParser.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioParser.Tpo -c -o src/libmpd_a-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioParser.Tpo src/$(DEPDIR)/libmpd_a-AudioParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/libmpd_a-AudioParser.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx - -src/libmpd_a-AudioParser.obj: src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-AudioParser.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-AudioParser.Tpo -c -o src/libmpd_a-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-AudioParser.Tpo src/$(DEPDIR)/libmpd_a-AudioParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/libmpd_a-AudioParser.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` - src/protocol/libmpd_a-Ack.o: src/protocol/Ack.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/protocol/libmpd_a-Ack.o -MD -MP -MF src/protocol/$(DEPDIR)/libmpd_a-Ack.Tpo -c -o src/protocol/libmpd_a-Ack.o `test -f 'src/protocol/Ack.cxx' || echo '$(srcdir)/'`src/protocol/Ack.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/protocol/$(DEPDIR)/libmpd_a-Ack.Tpo src/protocol/$(DEPDIR)/libmpd_a-Ack.Po @@ -9444,19 +10131,19 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-Idle.obj `if test -f 'src/Idle.cxx'; then $(CYGPATH_W) 'src/Idle.cxx'; else $(CYGPATH_W) '$(srcdir)/src/Idle.cxx'; fi` -src/libmpd_a-CrossFade.o: src/CrossFade.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-CrossFade.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-CrossFade.Tpo -c -o src/libmpd_a-CrossFade.o `test -f 'src/CrossFade.cxx' || echo '$(srcdir)/'`src/CrossFade.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-CrossFade.Tpo src/$(DEPDIR)/libmpd_a-CrossFade.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CrossFade.cxx' object='src/libmpd_a-CrossFade.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-CrossFade.o `test -f 'src/CrossFade.cxx' || echo '$(srcdir)/'`src/CrossFade.cxx - -src/libmpd_a-CrossFade.obj: src/CrossFade.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-CrossFade.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-CrossFade.Tpo -c -o src/libmpd_a-CrossFade.obj `if test -f 'src/CrossFade.cxx'; then $(CYGPATH_W) 'src/CrossFade.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CrossFade.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-CrossFade.Tpo src/$(DEPDIR)/libmpd_a-CrossFade.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CrossFade.cxx' object='src/libmpd_a-CrossFade.obj' libtool=no @AMDEPBACKSLASH@ +src/libmpd_a-IdleFlags.o: src/IdleFlags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-IdleFlags.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-IdleFlags.Tpo -c -o src/libmpd_a-IdleFlags.o `test -f 'src/IdleFlags.cxx' || echo '$(srcdir)/'`src/IdleFlags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-IdleFlags.Tpo src/$(DEPDIR)/libmpd_a-IdleFlags.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/IdleFlags.cxx' object='src/libmpd_a-IdleFlags.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-IdleFlags.o `test -f 'src/IdleFlags.cxx' || echo '$(srcdir)/'`src/IdleFlags.cxx + +src/libmpd_a-IdleFlags.obj: src/IdleFlags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-IdleFlags.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-IdleFlags.Tpo -c -o src/libmpd_a-IdleFlags.obj `if test -f 'src/IdleFlags.cxx'; then $(CYGPATH_W) 'src/IdleFlags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/IdleFlags.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-IdleFlags.Tpo src/$(DEPDIR)/libmpd_a-IdleFlags.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/IdleFlags.cxx' object='src/libmpd_a-IdleFlags.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-CrossFade.obj `if test -f 'src/CrossFade.cxx'; then $(CYGPATH_W) 'src/CrossFade.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CrossFade.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-IdleFlags.obj `if test -f 'src/IdleFlags.cxx'; then $(CYGPATH_W) 'src/IdleFlags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/IdleFlags.cxx'; fi` src/decoder/libmpd_a-DecoderError.o: src/decoder/DecoderError.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderError.o -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderError.Tpo -c -o src/decoder/libmpd_a-DecoderError.o `test -f 'src/decoder/DecoderError.cxx' || echo '$(srcdir)/'`src/decoder/DecoderError.cxx @@ -9500,33 +10187,19 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-DecoderControl.obj `if test -f 'src/decoder/DecoderControl.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderControl.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderControl.cxx'; fi` -src/decoder/libmpd_a-DecoderAPI.o: src/decoder/DecoderAPI.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderAPI.o -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Tpo -c -o src/decoder/libmpd_a-DecoderAPI.o `test -f 'src/decoder/DecoderAPI.cxx' || echo '$(srcdir)/'`src/decoder/DecoderAPI.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Tpo src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderAPI.cxx' object='src/decoder/libmpd_a-DecoderAPI.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-DecoderAPI.o `test -f 'src/decoder/DecoderAPI.cxx' || echo '$(srcdir)/'`src/decoder/DecoderAPI.cxx - -src/decoder/libmpd_a-DecoderAPI.obj: src/decoder/DecoderAPI.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderAPI.obj -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Tpo -c -o src/decoder/libmpd_a-DecoderAPI.obj `if test -f 'src/decoder/DecoderAPI.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderAPI.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderAPI.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Tpo src/decoder/$(DEPDIR)/libmpd_a-DecoderAPI.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderAPI.cxx' object='src/decoder/libmpd_a-DecoderAPI.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-DecoderAPI.obj `if test -f 'src/decoder/DecoderAPI.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderAPI.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderAPI.cxx'; fi` - -src/decoder/libmpd_a-DecoderInternal.o: src/decoder/DecoderInternal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderInternal.o -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Tpo -c -o src/decoder/libmpd_a-DecoderInternal.o `test -f 'src/decoder/DecoderInternal.cxx' || echo '$(srcdir)/'`src/decoder/DecoderInternal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Tpo src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderInternal.cxx' object='src/decoder/libmpd_a-DecoderInternal.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-DecoderInternal.o `test -f 'src/decoder/DecoderInternal.cxx' || echo '$(srcdir)/'`src/decoder/DecoderInternal.cxx - -src/decoder/libmpd_a-DecoderInternal.obj: src/decoder/DecoderInternal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderInternal.obj -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Tpo -c -o src/decoder/libmpd_a-DecoderInternal.obj `if test -f 'src/decoder/DecoderInternal.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderInternal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderInternal.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Tpo src/decoder/$(DEPDIR)/libmpd_a-DecoderInternal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/DecoderInternal.cxx' object='src/decoder/libmpd_a-DecoderInternal.obj' libtool=no @AMDEPBACKSLASH@ +src/decoder/libmpd_a-Bridge.o: src/decoder/Bridge.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-Bridge.o -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-Bridge.Tpo -c -o src/decoder/libmpd_a-Bridge.o `test -f 'src/decoder/Bridge.cxx' || echo '$(srcdir)/'`src/decoder/Bridge.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-Bridge.Tpo src/decoder/$(DEPDIR)/libmpd_a-Bridge.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/Bridge.cxx' object='src/decoder/libmpd_a-Bridge.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-Bridge.o `test -f 'src/decoder/Bridge.cxx' || echo '$(srcdir)/'`src/decoder/Bridge.cxx + +src/decoder/libmpd_a-Bridge.obj: src/decoder/Bridge.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-Bridge.obj -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-Bridge.Tpo -c -o src/decoder/libmpd_a-Bridge.obj `if test -f 'src/decoder/Bridge.cxx'; then $(CYGPATH_W) 'src/decoder/Bridge.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/Bridge.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/$(DEPDIR)/libmpd_a-Bridge.Tpo src/decoder/$(DEPDIR)/libmpd_a-Bridge.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/Bridge.cxx' object='src/decoder/libmpd_a-Bridge.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-DecoderInternal.obj `if test -f 'src/decoder/DecoderInternal.cxx'; then $(CYGPATH_W) 'src/decoder/DecoderInternal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/DecoderInternal.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/libmpd_a-Bridge.obj `if test -f 'src/decoder/Bridge.cxx'; then $(CYGPATH_W) 'src/decoder/Bridge.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/Bridge.cxx'; fi` src/decoder/libmpd_a-DecoderPrint.o: src/decoder/DecoderPrint.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/libmpd_a-DecoderPrint.o -MD -MP -MF src/decoder/$(DEPDIR)/libmpd_a-DecoderPrint.Tpo -c -o src/decoder/libmpd_a-DecoderPrint.o `test -f 'src/decoder/DecoderPrint.cxx' || echo '$(srcdir)/'`src/decoder/DecoderPrint.cxx @@ -9584,6 +10257,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/filter/libmpd_a-FilterRegistry.obj `if test -f 'src/filter/FilterRegistry.cxx'; then $(CYGPATH_W) 'src/filter/FilterRegistry.cxx'; else $(CYGPATH_W) '$(srcdir)/src/filter/FilterRegistry.cxx'; fi` +src/filter/libmpd_a-Observer.o: src/filter/Observer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/filter/libmpd_a-Observer.o -MD -MP -MF src/filter/$(DEPDIR)/libmpd_a-Observer.Tpo -c -o src/filter/libmpd_a-Observer.o `test -f 'src/filter/Observer.cxx' || echo '$(srcdir)/'`src/filter/Observer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/filter/$(DEPDIR)/libmpd_a-Observer.Tpo src/filter/$(DEPDIR)/libmpd_a-Observer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/filter/Observer.cxx' object='src/filter/libmpd_a-Observer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/filter/libmpd_a-Observer.o `test -f 'src/filter/Observer.cxx' || echo '$(srcdir)/'`src/filter/Observer.cxx + +src/filter/libmpd_a-Observer.obj: src/filter/Observer.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/filter/libmpd_a-Observer.obj -MD -MP -MF src/filter/$(DEPDIR)/libmpd_a-Observer.Tpo -c -o src/filter/libmpd_a-Observer.obj `if test -f 'src/filter/Observer.cxx'; then $(CYGPATH_W) 'src/filter/Observer.cxx'; else $(CYGPATH_W) '$(srcdir)/src/filter/Observer.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/filter/$(DEPDIR)/libmpd_a-Observer.Tpo src/filter/$(DEPDIR)/libmpd_a-Observer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/filter/Observer.cxx' object='src/filter/libmpd_a-Observer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/filter/libmpd_a-Observer.obj `if test -f 'src/filter/Observer.cxx'; then $(CYGPATH_W) 'src/filter/Observer.cxx'; else $(CYGPATH_W) '$(srcdir)/src/filter/Observer.cxx'; fi` + src/client/libmpd_a-Client.o: src/client/Client.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/libmpd_a-Client.o -MD -MP -MF src/client/$(DEPDIR)/libmpd_a-Client.Tpo -c -o src/client/libmpd_a-Client.o `test -f 'src/client/Client.cxx' || echo '$(srcdir)/'`src/client/Client.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/$(DEPDIR)/libmpd_a-Client.Tpo src/client/$(DEPDIR)/libmpd_a-Client.Po @@ -9766,6 +10453,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/libmpd_a-ClientFile.obj `if test -f 'src/client/ClientFile.cxx'; then $(CYGPATH_W) 'src/client/ClientFile.cxx'; else $(CYGPATH_W) '$(srcdir)/src/client/ClientFile.cxx'; fi` +src/client/libmpd_a-Response.o: src/client/Response.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/libmpd_a-Response.o -MD -MP -MF src/client/$(DEPDIR)/libmpd_a-Response.Tpo -c -o src/client/libmpd_a-Response.o `test -f 'src/client/Response.cxx' || echo '$(srcdir)/'`src/client/Response.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/$(DEPDIR)/libmpd_a-Response.Tpo src/client/$(DEPDIR)/libmpd_a-Response.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/Response.cxx' object='src/client/libmpd_a-Response.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/libmpd_a-Response.o `test -f 'src/client/Response.cxx' || echo '$(srcdir)/'`src/client/Response.cxx + +src/client/libmpd_a-Response.obj: src/client/Response.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/libmpd_a-Response.obj -MD -MP -MF src/client/$(DEPDIR)/libmpd_a-Response.Tpo -c -o src/client/libmpd_a-Response.obj `if test -f 'src/client/Response.cxx'; then $(CYGPATH_W) 'src/client/Response.cxx'; else $(CYGPATH_W) '$(srcdir)/src/client/Response.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/$(DEPDIR)/libmpd_a-Response.Tpo src/client/$(DEPDIR)/libmpd_a-Response.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/Response.cxx' object='src/client/libmpd_a-Response.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/libmpd_a-Response.obj `if test -f 'src/client/Response.cxx'; then $(CYGPATH_W) 'src/client/Response.cxx'; else $(CYGPATH_W) '$(srcdir)/src/client/Response.cxx'; fi` + src/libmpd_a-Listen.o: src/Listen.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-Listen.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-Listen.Tpo -c -o src/libmpd_a-Listen.o `test -f 'src/Listen.cxx' || echo '$(srcdir)/'`src/Listen.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-Listen.Tpo src/$(DEPDIR)/libmpd_a-Listen.Po @@ -9878,20 +10579,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/win32/libmpd_a-Win32Main.obj `if test -f 'src/win32/Win32Main.cxx'; then $(CYGPATH_W) 'src/win32/Win32Main.cxx'; else $(CYGPATH_W) '$(srcdir)/src/win32/Win32Main.cxx'; fi` -src/libmpd_a-GlobalEvents.o: src/GlobalEvents.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-GlobalEvents.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-GlobalEvents.Tpo -c -o src/libmpd_a-GlobalEvents.o `test -f 'src/GlobalEvents.cxx' || echo '$(srcdir)/'`src/GlobalEvents.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-GlobalEvents.Tpo src/$(DEPDIR)/libmpd_a-GlobalEvents.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/GlobalEvents.cxx' object='src/libmpd_a-GlobalEvents.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-GlobalEvents.o `test -f 'src/GlobalEvents.cxx' || echo '$(srcdir)/'`src/GlobalEvents.cxx - -src/libmpd_a-GlobalEvents.obj: src/GlobalEvents.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-GlobalEvents.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-GlobalEvents.Tpo -c -o src/libmpd_a-GlobalEvents.obj `if test -f 'src/GlobalEvents.cxx'; then $(CYGPATH_W) 'src/GlobalEvents.cxx'; else $(CYGPATH_W) '$(srcdir)/src/GlobalEvents.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-GlobalEvents.Tpo src/$(DEPDIR)/libmpd_a-GlobalEvents.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/GlobalEvents.cxx' object='src/libmpd_a-GlobalEvents.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-GlobalEvents.obj `if test -f 'src/GlobalEvents.cxx'; then $(CYGPATH_W) 'src/GlobalEvents.cxx'; else $(CYGPATH_W) '$(srcdir)/src/GlobalEvents.cxx'; fi` - src/libmpd_a-MusicBuffer.o: src/MusicBuffer.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-MusicBuffer.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-MusicBuffer.Tpo -c -o src/libmpd_a-MusicBuffer.o `test -f 'src/MusicBuffer.cxx' || echo '$(srcdir)/'`src/MusicBuffer.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-MusicBuffer.Tpo src/$(DEPDIR)/libmpd_a-MusicBuffer.Po @@ -9976,33 +10663,47 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-Permission.obj `if test -f 'src/Permission.cxx'; then $(CYGPATH_W) 'src/Permission.cxx'; else $(CYGPATH_W) '$(srcdir)/src/Permission.cxx'; fi` -src/libmpd_a-PlayerThread.o: src/PlayerThread.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlayerThread.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlayerThread.Tpo -c -o src/libmpd_a-PlayerThread.o `test -f 'src/PlayerThread.cxx' || echo '$(srcdir)/'`src/PlayerThread.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlayerThread.Tpo src/$(DEPDIR)/libmpd_a-PlayerThread.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlayerThread.cxx' object='src/libmpd_a-PlayerThread.o' libtool=no @AMDEPBACKSLASH@ +src/player/libmpd_a-CrossFade.o: src/player/CrossFade.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-CrossFade.o -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-CrossFade.Tpo -c -o src/player/libmpd_a-CrossFade.o `test -f 'src/player/CrossFade.cxx' || echo '$(srcdir)/'`src/player/CrossFade.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-CrossFade.Tpo src/player/$(DEPDIR)/libmpd_a-CrossFade.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/CrossFade.cxx' object='src/player/libmpd_a-CrossFade.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-CrossFade.o `test -f 'src/player/CrossFade.cxx' || echo '$(srcdir)/'`src/player/CrossFade.cxx + +src/player/libmpd_a-CrossFade.obj: src/player/CrossFade.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-CrossFade.obj -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-CrossFade.Tpo -c -o src/player/libmpd_a-CrossFade.obj `if test -f 'src/player/CrossFade.cxx'; then $(CYGPATH_W) 'src/player/CrossFade.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/CrossFade.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-CrossFade.Tpo src/player/$(DEPDIR)/libmpd_a-CrossFade.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/CrossFade.cxx' object='src/player/libmpd_a-CrossFade.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-CrossFade.obj `if test -f 'src/player/CrossFade.cxx'; then $(CYGPATH_W) 'src/player/CrossFade.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/CrossFade.cxx'; fi` + +src/player/libmpd_a-Thread.o: src/player/Thread.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-Thread.o -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-Thread.Tpo -c -o src/player/libmpd_a-Thread.o `test -f 'src/player/Thread.cxx' || echo '$(srcdir)/'`src/player/Thread.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-Thread.Tpo src/player/$(DEPDIR)/libmpd_a-Thread.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/Thread.cxx' object='src/player/libmpd_a-Thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlayerThread.o `test -f 'src/PlayerThread.cxx' || echo '$(srcdir)/'`src/PlayerThread.cxx +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-Thread.o `test -f 'src/player/Thread.cxx' || echo '$(srcdir)/'`src/player/Thread.cxx -src/libmpd_a-PlayerThread.obj: src/PlayerThread.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlayerThread.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlayerThread.Tpo -c -o src/libmpd_a-PlayerThread.obj `if test -f 'src/PlayerThread.cxx'; then $(CYGPATH_W) 'src/PlayerThread.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlayerThread.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlayerThread.Tpo src/$(DEPDIR)/libmpd_a-PlayerThread.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlayerThread.cxx' object='src/libmpd_a-PlayerThread.obj' libtool=no @AMDEPBACKSLASH@ +src/player/libmpd_a-Thread.obj: src/player/Thread.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-Thread.obj -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-Thread.Tpo -c -o src/player/libmpd_a-Thread.obj `if test -f 'src/player/Thread.cxx'; then $(CYGPATH_W) 'src/player/Thread.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/Thread.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-Thread.Tpo src/player/$(DEPDIR)/libmpd_a-Thread.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/Thread.cxx' object='src/player/libmpd_a-Thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlayerThread.obj `if test -f 'src/PlayerThread.cxx'; then $(CYGPATH_W) 'src/PlayerThread.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlayerThread.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-Thread.obj `if test -f 'src/player/Thread.cxx'; then $(CYGPATH_W) 'src/player/Thread.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/Thread.cxx'; fi` -src/libmpd_a-PlayerControl.o: src/PlayerControl.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlayerControl.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlayerControl.Tpo -c -o src/libmpd_a-PlayerControl.o `test -f 'src/PlayerControl.cxx' || echo '$(srcdir)/'`src/PlayerControl.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlayerControl.Tpo src/$(DEPDIR)/libmpd_a-PlayerControl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlayerControl.cxx' object='src/libmpd_a-PlayerControl.o' libtool=no @AMDEPBACKSLASH@ +src/player/libmpd_a-Control.o: src/player/Control.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-Control.o -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-Control.Tpo -c -o src/player/libmpd_a-Control.o `test -f 'src/player/Control.cxx' || echo '$(srcdir)/'`src/player/Control.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-Control.Tpo src/player/$(DEPDIR)/libmpd_a-Control.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/Control.cxx' object='src/player/libmpd_a-Control.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlayerControl.o `test -f 'src/PlayerControl.cxx' || echo '$(srcdir)/'`src/PlayerControl.cxx +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-Control.o `test -f 'src/player/Control.cxx' || echo '$(srcdir)/'`src/player/Control.cxx -src/libmpd_a-PlayerControl.obj: src/PlayerControl.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlayerControl.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlayerControl.Tpo -c -o src/libmpd_a-PlayerControl.obj `if test -f 'src/PlayerControl.cxx'; then $(CYGPATH_W) 'src/PlayerControl.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlayerControl.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlayerControl.Tpo src/$(DEPDIR)/libmpd_a-PlayerControl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlayerControl.cxx' object='src/libmpd_a-PlayerControl.obj' libtool=no @AMDEPBACKSLASH@ +src/player/libmpd_a-Control.obj: src/player/Control.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/player/libmpd_a-Control.obj -MD -MP -MF src/player/$(DEPDIR)/libmpd_a-Control.Tpo -c -o src/player/libmpd_a-Control.obj `if test -f 'src/player/Control.cxx'; then $(CYGPATH_W) 'src/player/Control.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/Control.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/player/$(DEPDIR)/libmpd_a-Control.Tpo src/player/$(DEPDIR)/libmpd_a-Control.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/player/Control.cxx' object='src/player/libmpd_a-Control.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlayerControl.obj `if test -f 'src/PlayerControl.cxx'; then $(CYGPATH_W) 'src/PlayerControl.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlayerControl.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/player/libmpd_a-Control.obj `if test -f 'src/player/Control.cxx'; then $(CYGPATH_W) 'src/player/Control.cxx'; else $(CYGPATH_W) '$(srcdir)/src/player/Control.cxx'; fi` src/libmpd_a-PlaylistError.o: src/PlaylistError.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlaylistError.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlaylistError.Tpo -c -o src/libmpd_a-PlaylistError.o `test -f 'src/PlaylistError.cxx' || echo '$(srcdir)/'`src/PlaylistError.cxx @@ -10016,21 +10717,7 @@ @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlaylistError.Tpo src/$(DEPDIR)/libmpd_a-PlaylistError.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlaylistError.cxx' object='src/libmpd_a-PlaylistError.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlaylistError.obj `if test -f 'src/PlaylistError.cxx'; then $(CYGPATH_W) 'src/PlaylistError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlaylistError.cxx'; fi` - -src/libmpd_a-PlaylistGlobal.o: src/PlaylistGlobal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlaylistGlobal.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Tpo -c -o src/libmpd_a-PlaylistGlobal.o `test -f 'src/PlaylistGlobal.cxx' || echo '$(srcdir)/'`src/PlaylistGlobal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Tpo src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlaylistGlobal.cxx' object='src/libmpd_a-PlaylistGlobal.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlaylistGlobal.o `test -f 'src/PlaylistGlobal.cxx' || echo '$(srcdir)/'`src/PlaylistGlobal.cxx - -src/libmpd_a-PlaylistGlobal.obj: src/PlaylistGlobal.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlaylistGlobal.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Tpo -c -o src/libmpd_a-PlaylistGlobal.obj `if test -f 'src/PlaylistGlobal.cxx'; then $(CYGPATH_W) 'src/PlaylistGlobal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlaylistGlobal.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Tpo src/$(DEPDIR)/libmpd_a-PlaylistGlobal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/PlaylistGlobal.cxx' object='src/libmpd_a-PlaylistGlobal.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlaylistGlobal.obj `if test -f 'src/PlaylistGlobal.cxx'; then $(CYGPATH_W) 'src/PlaylistGlobal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlaylistGlobal.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-PlaylistError.obj `if test -f 'src/PlaylistError.cxx'; then $(CYGPATH_W) 'src/PlaylistError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/PlaylistError.cxx'; fi` src/libmpd_a-PlaylistPrint.o: src/PlaylistPrint.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-PlaylistPrint.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-PlaylistPrint.Tpo -c -o src/libmpd_a-PlaylistPrint.o `test -f 'src/PlaylistPrint.cxx' || echo '$(srcdir)/'`src/PlaylistPrint.cxx @@ -10270,33 +10957,19 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/queue/libmpd_a-PlaylistState.obj `if test -f 'src/queue/PlaylistState.cxx'; then $(CYGPATH_W) 'src/queue/PlaylistState.cxx'; else $(CYGPATH_W) '$(srcdir)/src/queue/PlaylistState.cxx'; fi` -src/libmpd_a-ReplayGainConfig.o: src/ReplayGainConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainConfig.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Tpo -c -o src/libmpd_a-ReplayGainConfig.o `test -f 'src/ReplayGainConfig.cxx' || echo '$(srcdir)/'`src/ReplayGainConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainConfig.cxx' object='src/libmpd_a-ReplayGainConfig.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainConfig.o `test -f 'src/ReplayGainConfig.cxx' || echo '$(srcdir)/'`src/ReplayGainConfig.cxx - -src/libmpd_a-ReplayGainConfig.obj: src/ReplayGainConfig.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainConfig.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Tpo -c -o src/libmpd_a-ReplayGainConfig.obj `if test -f 'src/ReplayGainConfig.cxx'; then $(CYGPATH_W) 'src/ReplayGainConfig.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainConfig.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainConfig.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainConfig.cxx' object='src/libmpd_a-ReplayGainConfig.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainConfig.obj `if test -f 'src/ReplayGainConfig.cxx'; then $(CYGPATH_W) 'src/ReplayGainConfig.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainConfig.cxx'; fi` - -src/libmpd_a-ReplayGainInfo.o: src/ReplayGainInfo.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainInfo.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Tpo -c -o src/libmpd_a-ReplayGainInfo.o `test -f 'src/ReplayGainInfo.cxx' || echo '$(srcdir)/'`src/ReplayGainInfo.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainInfo.cxx' object='src/libmpd_a-ReplayGainInfo.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainInfo.o `test -f 'src/ReplayGainInfo.cxx' || echo '$(srcdir)/'`src/ReplayGainInfo.cxx - -src/libmpd_a-ReplayGainInfo.obj: src/ReplayGainInfo.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainInfo.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Tpo -c -o src/libmpd_a-ReplayGainInfo.obj `if test -f 'src/ReplayGainInfo.cxx'; then $(CYGPATH_W) 'src/ReplayGainInfo.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainInfo.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainInfo.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainInfo.cxx' object='src/libmpd_a-ReplayGainInfo.obj' libtool=no @AMDEPBACKSLASH@ +src/libmpd_a-ReplayGainGlobal.o: src/ReplayGainGlobal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainGlobal.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Tpo -c -o src/libmpd_a-ReplayGainGlobal.o `test -f 'src/ReplayGainGlobal.cxx' || echo '$(srcdir)/'`src/ReplayGainGlobal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainGlobal.cxx' object='src/libmpd_a-ReplayGainGlobal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainGlobal.o `test -f 'src/ReplayGainGlobal.cxx' || echo '$(srcdir)/'`src/ReplayGainGlobal.cxx + +src/libmpd_a-ReplayGainGlobal.obj: src/ReplayGainGlobal.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-ReplayGainGlobal.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Tpo -c -o src/libmpd_a-ReplayGainGlobal.obj `if test -f 'src/ReplayGainGlobal.cxx'; then $(CYGPATH_W) 'src/ReplayGainGlobal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainGlobal.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Tpo src/$(DEPDIR)/libmpd_a-ReplayGainGlobal.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/ReplayGainGlobal.cxx' object='src/libmpd_a-ReplayGainGlobal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainInfo.obj `if test -f 'src/ReplayGainInfo.cxx'; then $(CYGPATH_W) 'src/ReplayGainInfo.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainInfo.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-ReplayGainGlobal.obj `if test -f 'src/ReplayGainGlobal.cxx'; then $(CYGPATH_W) 'src/ReplayGainGlobal.cxx'; else $(CYGPATH_W) '$(srcdir)/src/ReplayGainGlobal.cxx'; fi` src/libmpd_a-DetachedSong.o: src/DetachedSong.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-DetachedSong.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-DetachedSong.Tpo -c -o src/libmpd_a-DetachedSong.o `test -f 'src/DetachedSong.cxx' || echo '$(srcdir)/'`src/DetachedSong.cxx @@ -10312,6 +10985,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-DetachedSong.obj `if test -f 'src/DetachedSong.cxx'; then $(CYGPATH_W) 'src/DetachedSong.cxx'; else $(CYGPATH_W) '$(srcdir)/src/DetachedSong.cxx'; fi` +src/libmpd_a-LocateUri.o: src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-LocateUri.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-LocateUri.Tpo -c -o src/libmpd_a-LocateUri.o `test -f 'src/LocateUri.cxx' || echo '$(srcdir)/'`src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-LocateUri.Tpo src/$(DEPDIR)/libmpd_a-LocateUri.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/LocateUri.cxx' object='src/libmpd_a-LocateUri.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-LocateUri.o `test -f 'src/LocateUri.cxx' || echo '$(srcdir)/'`src/LocateUri.cxx + +src/libmpd_a-LocateUri.obj: src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-LocateUri.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-LocateUri.Tpo -c -o src/libmpd_a-LocateUri.obj `if test -f 'src/LocateUri.cxx'; then $(CYGPATH_W) 'src/LocateUri.cxx'; else $(CYGPATH_W) '$(srcdir)/src/LocateUri.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-LocateUri.Tpo src/$(DEPDIR)/libmpd_a-LocateUri.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/LocateUri.cxx' object='src/libmpd_a-LocateUri.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-LocateUri.obj `if test -f 'src/LocateUri.cxx'; then $(CYGPATH_W) 'src/LocateUri.cxx'; else $(CYGPATH_W) '$(srcdir)/src/LocateUri.cxx'; fi` + src/libmpd_a-SongUpdate.o: src/SongUpdate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-SongUpdate.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-SongUpdate.Tpo -c -o src/libmpd_a-SongUpdate.o `test -f 'src/SongUpdate.cxx' || echo '$(srcdir)/'`src/SongUpdate.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-SongUpdate.Tpo src/$(DEPDIR)/libmpd_a-SongUpdate.Po @@ -10522,20 +11209,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/unix/libmpd_a-SignalHandlers.obj `if test -f 'src/unix/SignalHandlers.cxx'; then $(CYGPATH_W) 'src/unix/SignalHandlers.cxx'; else $(CYGPATH_W) '$(srcdir)/src/unix/SignalHandlers.cxx'; fi` -src/unix/libmpd_a-Daemon.o: src/unix/Daemon.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/unix/libmpd_a-Daemon.o -MD -MP -MF src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo -c -o src/unix/libmpd_a-Daemon.o `test -f 'src/unix/Daemon.cxx' || echo '$(srcdir)/'`src/unix/Daemon.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo src/unix/$(DEPDIR)/libmpd_a-Daemon.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/unix/Daemon.cxx' object='src/unix/libmpd_a-Daemon.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/unix/libmpd_a-Daemon.o `test -f 'src/unix/Daemon.cxx' || echo '$(srcdir)/'`src/unix/Daemon.cxx - -src/unix/libmpd_a-Daemon.obj: src/unix/Daemon.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/unix/libmpd_a-Daemon.obj -MD -MP -MF src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo -c -o src/unix/libmpd_a-Daemon.obj `if test -f 'src/unix/Daemon.cxx'; then $(CYGPATH_W) 'src/unix/Daemon.cxx'; else $(CYGPATH_W) '$(srcdir)/src/unix/Daemon.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo src/unix/$(DEPDIR)/libmpd_a-Daemon.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/unix/Daemon.cxx' object='src/unix/libmpd_a-Daemon.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/unix/libmpd_a-Daemon.obj `if test -f 'src/unix/Daemon.cxx'; then $(CYGPATH_W) 'src/unix/Daemon.cxx'; else $(CYGPATH_W) '$(srcdir)/src/unix/Daemon.cxx'; fi` - src/libmpd_a-CommandLine.o: src/CommandLine.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-CommandLine.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-CommandLine.Tpo -c -o src/libmpd_a-CommandLine.o `test -f 'src/CommandLine.cxx' || echo '$(srcdir)/'`src/CommandLine.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-CommandLine.Tpo src/$(DEPDIR)/libmpd_a-CommandLine.Po @@ -10550,6 +11223,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-CommandLine.obj `if test -f 'src/CommandLine.cxx'; then $(CYGPATH_W) 'src/CommandLine.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CommandLine.cxx'; fi` +src/unix/libmpd_a-Daemon.o: src/unix/Daemon.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/unix/libmpd_a-Daemon.o -MD -MP -MF src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo -c -o src/unix/libmpd_a-Daemon.o `test -f 'src/unix/Daemon.cxx' || echo '$(srcdir)/'`src/unix/Daemon.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo src/unix/$(DEPDIR)/libmpd_a-Daemon.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/unix/Daemon.cxx' object='src/unix/libmpd_a-Daemon.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/unix/libmpd_a-Daemon.o `test -f 'src/unix/Daemon.cxx' || echo '$(srcdir)/'`src/unix/Daemon.cxx + +src/unix/libmpd_a-Daemon.obj: src/unix/Daemon.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/unix/libmpd_a-Daemon.obj -MD -MP -MF src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo -c -o src/unix/libmpd_a-Daemon.obj `if test -f 'src/unix/Daemon.cxx'; then $(CYGPATH_W) 'src/unix/Daemon.cxx'; else $(CYGPATH_W) '$(srcdir)/src/unix/Daemon.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/unix/$(DEPDIR)/libmpd_a-Daemon.Tpo src/unix/$(DEPDIR)/libmpd_a-Daemon.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/unix/Daemon.cxx' object='src/unix/libmpd_a-Daemon.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/unix/libmpd_a-Daemon.obj `if test -f 'src/unix/Daemon.cxx'; then $(CYGPATH_W) 'src/unix/Daemon.cxx'; else $(CYGPATH_W) '$(srcdir)/src/unix/Daemon.cxx'; fi` + src/queue/libmpd_a-PlaylistUpdate.o: src/queue/PlaylistUpdate.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/queue/libmpd_a-PlaylistUpdate.o -MD -MP -MF src/queue/$(DEPDIR)/libmpd_a-PlaylistUpdate.Tpo -c -o src/queue/libmpd_a-PlaylistUpdate.o `test -f 'src/queue/PlaylistUpdate.cxx' || echo '$(srcdir)/'`src/queue/PlaylistUpdate.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/queue/$(DEPDIR)/libmpd_a-PlaylistUpdate.Tpo src/queue/$(DEPDIR)/libmpd_a-PlaylistUpdate.Po @@ -10844,20 +11531,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/db/libmpd_a-DatabasePlaylist.obj `if test -f 'src/db/DatabasePlaylist.cxx'; then $(CYGPATH_W) 'src/db/DatabasePlaylist.cxx'; else $(CYGPATH_W) '$(srcdir)/src/db/DatabasePlaylist.cxx'; fi` -src/db/libmpd_a-DatabaseError.o: src/db/DatabaseError.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/db/libmpd_a-DatabaseError.o -MD -MP -MF src/db/$(DEPDIR)/libmpd_a-DatabaseError.Tpo -c -o src/db/libmpd_a-DatabaseError.o `test -f 'src/db/DatabaseError.cxx' || echo '$(srcdir)/'`src/db/DatabaseError.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/db/$(DEPDIR)/libmpd_a-DatabaseError.Tpo src/db/$(DEPDIR)/libmpd_a-DatabaseError.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/db/DatabaseError.cxx' object='src/db/libmpd_a-DatabaseError.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/db/libmpd_a-DatabaseError.o `test -f 'src/db/DatabaseError.cxx' || echo '$(srcdir)/'`src/db/DatabaseError.cxx - -src/db/libmpd_a-DatabaseError.obj: src/db/DatabaseError.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/db/libmpd_a-DatabaseError.obj -MD -MP -MF src/db/$(DEPDIR)/libmpd_a-DatabaseError.Tpo -c -o src/db/libmpd_a-DatabaseError.obj `if test -f 'src/db/DatabaseError.cxx'; then $(CYGPATH_W) 'src/db/DatabaseError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/db/DatabaseError.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/db/$(DEPDIR)/libmpd_a-DatabaseError.Tpo src/db/$(DEPDIR)/libmpd_a-DatabaseError.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/db/DatabaseError.cxx' object='src/db/libmpd_a-DatabaseError.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/db/libmpd_a-DatabaseError.obj `if test -f 'src/db/DatabaseError.cxx'; then $(CYGPATH_W) 'src/db/DatabaseError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/db/DatabaseError.cxx'; fi` - src/db/libmpd_a-DatabaseLock.o: src/db/DatabaseLock.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/db/libmpd_a-DatabaseLock.o -MD -MP -MF src/db/$(DEPDIR)/libmpd_a-DatabaseLock.Tpo -c -o src/db/libmpd_a-DatabaseLock.o `test -f 'src/db/DatabaseLock.cxx' || echo '$(srcdir)/'`src/db/DatabaseLock.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/db/$(DEPDIR)/libmpd_a-DatabaseLock.Tpo src/db/$(DEPDIR)/libmpd_a-DatabaseLock.Po @@ -10956,6 +11629,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/command/libmpd_a-StickerCommands.obj `if test -f 'src/command/StickerCommands.cxx'; then $(CYGPATH_W) 'src/command/StickerCommands.cxx'; else $(CYGPATH_W) '$(srcdir)/src/command/StickerCommands.cxx'; fi` +src/lib/sqlite/libmpd_a-Error.o: src/lib/sqlite/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/sqlite/libmpd_a-Error.o -MD -MP -MF src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Tpo -c -o src/lib/sqlite/libmpd_a-Error.o `test -f 'src/lib/sqlite/Error.cxx' || echo '$(srcdir)/'`src/lib/sqlite/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Tpo src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/sqlite/Error.cxx' object='src/lib/sqlite/libmpd_a-Error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/sqlite/libmpd_a-Error.o `test -f 'src/lib/sqlite/Error.cxx' || echo '$(srcdir)/'`src/lib/sqlite/Error.cxx + +src/lib/sqlite/libmpd_a-Error.obj: src/lib/sqlite/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/sqlite/libmpd_a-Error.obj -MD -MP -MF src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Tpo -c -o src/lib/sqlite/libmpd_a-Error.obj `if test -f 'src/lib/sqlite/Error.cxx'; then $(CYGPATH_W) 'src/lib/sqlite/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/sqlite/Error.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Tpo src/lib/sqlite/$(DEPDIR)/libmpd_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/sqlite/Error.cxx' object='src/lib/sqlite/libmpd_a-Error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/sqlite/libmpd_a-Error.obj `if test -f 'src/lib/sqlite/Error.cxx'; then $(CYGPATH_W) 'src/lib/sqlite/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/sqlite/Error.cxx'; fi` + src/sticker/libmpd_a-StickerDatabase.o: src/sticker/StickerDatabase.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/sticker/libmpd_a-StickerDatabase.o -MD -MP -MF src/sticker/$(DEPDIR)/libmpd_a-StickerDatabase.Tpo -c -o src/sticker/libmpd_a-StickerDatabase.o `test -f 'src/sticker/StickerDatabase.cxx' || echo '$(srcdir)/'`src/sticker/StickerDatabase.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/sticker/$(DEPDIR)/libmpd_a-StickerDatabase.Tpo src/sticker/$(DEPDIR)/libmpd_a-StickerDatabase.Po @@ -11012,6 +11699,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/command/libmpd_a-NeighborCommands.obj `if test -f 'src/command/NeighborCommands.cxx'; then $(CYGPATH_W) 'src/command/NeighborCommands.cxx'; else $(CYGPATH_W) '$(srcdir)/src/command/NeighborCommands.cxx'; fi` +src/libmpd_a-TagArchive.o: src/TagArchive.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-TagArchive.o -MD -MP -MF src/$(DEPDIR)/libmpd_a-TagArchive.Tpo -c -o src/libmpd_a-TagArchive.o `test -f 'src/TagArchive.cxx' || echo '$(srcdir)/'`src/TagArchive.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-TagArchive.Tpo src/$(DEPDIR)/libmpd_a-TagArchive.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/TagArchive.cxx' object='src/libmpd_a-TagArchive.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-TagArchive.o `test -f 'src/TagArchive.cxx' || echo '$(srcdir)/'`src/TagArchive.cxx + +src/libmpd_a-TagArchive.obj: src/TagArchive.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libmpd_a-TagArchive.obj -MD -MP -MF src/$(DEPDIR)/libmpd_a-TagArchive.Tpo -c -o src/libmpd_a-TagArchive.obj `if test -f 'src/TagArchive.cxx'; then $(CYGPATH_W) 'src/TagArchive.cxx'; else $(CYGPATH_W) '$(srcdir)/src/TagArchive.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libmpd_a-TagArchive.Tpo src/$(DEPDIR)/libmpd_a-TagArchive.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/TagArchive.cxx' object='src/libmpd_a-TagArchive.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libmpd_a-TagArchive.obj `if test -f 'src/TagArchive.cxx'; then $(CYGPATH_W) 'src/TagArchive.cxx'; else $(CYGPATH_W) '$(srcdir)/src/TagArchive.cxx'; fi` + src/db/update/libmpd_a-Archive.o: src/db/update/Archive.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmpd_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/db/update/libmpd_a-Archive.o -MD -MP -MF src/db/update/$(DEPDIR)/libmpd_a-Archive.Tpo -c -o src/db/update/libmpd_a-Archive.o `test -f 'src/db/update/Archive.cxx' || echo '$(srcdir)/'`src/db/update/Archive.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/db/update/$(DEPDIR)/libmpd_a-Archive.Tpo src/db/update/$(DEPDIR)/libmpd_a-Archive.Po @@ -11236,20 +11937,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/upnp/libneighbor_a-Discovery.obj `if test -f 'src/lib/upnp/Discovery.cxx'; then $(CYGPATH_W) 'src/lib/upnp/Discovery.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/upnp/Discovery.cxx'; fi` -src/lib/upnp/libneighbor_a-Domain.o: src/lib/upnp/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/upnp/libneighbor_a-Domain.o -MD -MP -MF src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Tpo -c -o src/lib/upnp/libneighbor_a-Domain.o `test -f 'src/lib/upnp/Domain.cxx' || echo '$(srcdir)/'`src/lib/upnp/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Tpo src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/upnp/Domain.cxx' object='src/lib/upnp/libneighbor_a-Domain.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/upnp/libneighbor_a-Domain.o `test -f 'src/lib/upnp/Domain.cxx' || echo '$(srcdir)/'`src/lib/upnp/Domain.cxx - -src/lib/upnp/libneighbor_a-Domain.obj: src/lib/upnp/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/upnp/libneighbor_a-Domain.obj -MD -MP -MF src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Tpo -c -o src/lib/upnp/libneighbor_a-Domain.obj `if test -f 'src/lib/upnp/Domain.cxx'; then $(CYGPATH_W) 'src/lib/upnp/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/upnp/Domain.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Tpo src/lib/upnp/$(DEPDIR)/libneighbor_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/upnp/Domain.cxx' object='src/lib/upnp/libneighbor_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/upnp/libneighbor_a-Domain.obj `if test -f 'src/lib/upnp/Domain.cxx'; then $(CYGPATH_W) 'src/lib/upnp/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/upnp/Domain.cxx'; fi` - src/lib/upnp/libneighbor_a-ixmlwrap.o: src/lib/upnp/ixmlwrap.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneighbor_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/upnp/libneighbor_a-ixmlwrap.o -MD -MP -MF src/lib/upnp/$(DEPDIR)/libneighbor_a-ixmlwrap.Tpo -c -o src/lib/upnp/libneighbor_a-ixmlwrap.o `test -f 'src/lib/upnp/ixmlwrap.cxx' || echo '$(srcdir)/'`src/lib/upnp/ixmlwrap.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/upnp/$(DEPDIR)/libneighbor_a-ixmlwrap.Tpo src/lib/upnp/$(DEPDIR)/libneighbor_a-ixmlwrap.Po @@ -11390,6 +12077,34 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-FifoOutputPlugin.obj `if test -f 'src/output/plugins/FifoOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/FifoOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/FifoOutputPlugin.cxx'; fi` +src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.o: src/output/plugins/SndioOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.o -MD -MP -MF src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Tpo -c -o src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.o `test -f 'src/output/plugins/SndioOutputPlugin.cxx' || echo '$(srcdir)/'`src/output/plugins/SndioOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Tpo src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/plugins/SndioOutputPlugin.cxx' object='src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.o `test -f 'src/output/plugins/SndioOutputPlugin.cxx' || echo '$(srcdir)/'`src/output/plugins/SndioOutputPlugin.cxx + +src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.obj: src/output/plugins/SndioOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.obj -MD -MP -MF src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Tpo -c -o src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.obj `if test -f 'src/output/plugins/SndioOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/SndioOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/SndioOutputPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Tpo src/output/plugins/$(DEPDIR)/liboutput_plugins_a-SndioOutputPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/plugins/SndioOutputPlugin.cxx' object='src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-SndioOutputPlugin.obj `if test -f 'src/output/plugins/SndioOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/SndioOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/SndioOutputPlugin.cxx'; fi` + +src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.o: src/output/plugins/HaikuOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.o -MD -MP -MF src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Tpo -c -o src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.o `test -f 'src/output/plugins/HaikuOutputPlugin.cxx' || echo '$(srcdir)/'`src/output/plugins/HaikuOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Tpo src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/plugins/HaikuOutputPlugin.cxx' object='src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.o `test -f 'src/output/plugins/HaikuOutputPlugin.cxx' || echo '$(srcdir)/'`src/output/plugins/HaikuOutputPlugin.cxx + +src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.obj: src/output/plugins/HaikuOutputPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.obj -MD -MP -MF src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Tpo -c -o src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.obj `if test -f 'src/output/plugins/HaikuOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/HaikuOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/HaikuOutputPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Tpo src/output/plugins/$(DEPDIR)/liboutput_plugins_a-HaikuOutputPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/output/plugins/HaikuOutputPlugin.cxx' object='src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-HaikuOutputPlugin.obj `if test -f 'src/output/plugins/HaikuOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/HaikuOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/HaikuOutputPlugin.cxx'; fi` + src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.o: src/output/plugins/PipeOutputPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.o -MD -MP -MF src/output/plugins/$(DEPDIR)/liboutput_plugins_a-PipeOutputPlugin.Tpo -c -o src/output/plugins/liboutput_plugins_a-PipeOutputPlugin.o `test -f 'src/output/plugins/PipeOutputPlugin.cxx' || echo '$(srcdir)/'`src/output/plugins/PipeOutputPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/output/plugins/$(DEPDIR)/liboutput_plugins_a-PipeOutputPlugin.Tpo src/output/plugins/$(DEPDIR)/liboutput_plugins_a-PipeOutputPlugin.Po @@ -11586,19 +12301,61 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liboutput_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/output/plugins/liboutput_plugins_a-WinmmOutputPlugin.obj `if test -f 'src/output/plugins/WinmmOutputPlugin.cxx'; then $(CYGPATH_W) 'src/output/plugins/WinmmOutputPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/output/plugins/WinmmOutputPlugin.cxx'; fi` -src/pcm/libpcm_a-Domain.o: src/pcm/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Domain.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Domain.Tpo -c -o src/pcm/libpcm_a-Domain.o `test -f 'src/pcm/Domain.cxx' || echo '$(srcdir)/'`src/pcm/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Domain.Tpo src/pcm/$(DEPDIR)/libpcm_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Domain.cxx' object='src/pcm/libpcm_a-Domain.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Domain.o `test -f 'src/pcm/Domain.cxx' || echo '$(srcdir)/'`src/pcm/Domain.cxx - -src/pcm/libpcm_a-Domain.obj: src/pcm/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Domain.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Domain.Tpo -c -o src/pcm/libpcm_a-Domain.obj `if test -f 'src/pcm/Domain.cxx'; then $(CYGPATH_W) 'src/pcm/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Domain.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Domain.Tpo src/pcm/$(DEPDIR)/libpcm_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Domain.cxx' object='src/pcm/libpcm_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ +src/libpcm_a-CheckAudioFormat.o: src/CheckAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-CheckAudioFormat.o -MD -MP -MF src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Tpo -c -o src/libpcm_a-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Tpo src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/libpcm_a-CheckAudioFormat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx + +src/libpcm_a-CheckAudioFormat.obj: src/CheckAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-CheckAudioFormat.obj -MD -MP -MF src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Tpo -c -o src/libpcm_a-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Tpo src/$(DEPDIR)/libpcm_a-CheckAudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/libpcm_a-CheckAudioFormat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` + +src/libpcm_a-AudioFormat.o: src/AudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-AudioFormat.o -MD -MP -MF src/$(DEPDIR)/libpcm_a-AudioFormat.Tpo -c -o src/libpcm_a-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-AudioFormat.Tpo src/$(DEPDIR)/libpcm_a-AudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/libpcm_a-AudioFormat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx + +src/libpcm_a-AudioFormat.obj: src/AudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-AudioFormat.obj -MD -MP -MF src/$(DEPDIR)/libpcm_a-AudioFormat.Tpo -c -o src/libpcm_a-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-AudioFormat.Tpo src/$(DEPDIR)/libpcm_a-AudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/libpcm_a-AudioFormat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` + +src/libpcm_a-AudioParser.o: src/AudioParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-AudioParser.o -MD -MP -MF src/$(DEPDIR)/libpcm_a-AudioParser.Tpo -c -o src/libpcm_a-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-AudioParser.Tpo src/$(DEPDIR)/libpcm_a-AudioParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/libpcm_a-AudioParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx + +src/libpcm_a-AudioParser.obj: src/AudioParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/libpcm_a-AudioParser.obj -MD -MP -MF src/$(DEPDIR)/libpcm_a-AudioParser.Tpo -c -o src/libpcm_a-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcm_a-AudioParser.Tpo src/$(DEPDIR)/libpcm_a-AudioParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/libpcm_a-AudioParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/libpcm_a-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` + +src/pcm/libpcm_a-SampleFormat.o: src/pcm/SampleFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-SampleFormat.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Tpo -c -o src/pcm/libpcm_a-SampleFormat.o `test -f 'src/pcm/SampleFormat.cxx' || echo '$(srcdir)/'`src/pcm/SampleFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Tpo src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/SampleFormat.cxx' object='src/pcm/libpcm_a-SampleFormat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-SampleFormat.o `test -f 'src/pcm/SampleFormat.cxx' || echo '$(srcdir)/'`src/pcm/SampleFormat.cxx + +src/pcm/libpcm_a-SampleFormat.obj: src/pcm/SampleFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-SampleFormat.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Tpo -c -o src/pcm/libpcm_a-SampleFormat.obj `if test -f 'src/pcm/SampleFormat.cxx'; then $(CYGPATH_W) 'src/pcm/SampleFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/SampleFormat.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Tpo src/pcm/$(DEPDIR)/libpcm_a-SampleFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/SampleFormat.cxx' object='src/pcm/libpcm_a-SampleFormat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Domain.obj `if test -f 'src/pcm/Domain.cxx'; then $(CYGPATH_W) 'src/pcm/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Domain.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-SampleFormat.obj `if test -f 'src/pcm/SampleFormat.cxx'; then $(CYGPATH_W) 'src/pcm/SampleFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/SampleFormat.cxx'; fi` src/pcm/libpcm_a-Interleave.o: src/pcm/Interleave.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Interleave.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Interleave.Tpo -c -o src/pcm/libpcm_a-Interleave.o `test -f 'src/pcm/Interleave.cxx' || echo '$(srcdir)/'`src/pcm/Interleave.cxx @@ -11782,6 +12539,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-ChannelsConverter.obj `if test -f 'src/pcm/ChannelsConverter.cxx'; then $(CYGPATH_W) 'src/pcm/ChannelsConverter.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/ChannelsConverter.cxx'; fi` +src/pcm/libpcm_a-Order.o: src/pcm/Order.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Order.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Order.Tpo -c -o src/pcm/libpcm_a-Order.o `test -f 'src/pcm/Order.cxx' || echo '$(srcdir)/'`src/pcm/Order.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Order.Tpo src/pcm/$(DEPDIR)/libpcm_a-Order.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Order.cxx' object='src/pcm/libpcm_a-Order.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Order.o `test -f 'src/pcm/Order.cxx' || echo '$(srcdir)/'`src/pcm/Order.cxx + +src/pcm/libpcm_a-Order.obj: src/pcm/Order.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Order.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Order.Tpo -c -o src/pcm/libpcm_a-Order.obj `if test -f 'src/pcm/Order.cxx'; then $(CYGPATH_W) 'src/pcm/Order.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Order.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Order.Tpo src/pcm/$(DEPDIR)/libpcm_a-Order.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Order.cxx' object='src/pcm/libpcm_a-Order.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Order.obj `if test -f 'src/pcm/Order.cxx'; then $(CYGPATH_W) 'src/pcm/Order.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Order.cxx'; fi` + src/pcm/libpcm_a-GlueResampler.o: src/pcm/GlueResampler.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-GlueResampler.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-GlueResampler.Tpo -c -o src/pcm/libpcm_a-GlueResampler.o `test -f 'src/pcm/GlueResampler.cxx' || echo '$(srcdir)/'`src/pcm/GlueResampler.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-GlueResampler.Tpo src/pcm/$(DEPDIR)/libpcm_a-GlueResampler.Po @@ -11838,6 +12609,34 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-PcmDither.obj `if test -f 'src/pcm/PcmDither.cxx'; then $(CYGPATH_W) 'src/pcm/PcmDither.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/PcmDither.cxx'; fi` +src/pcm/libpcm_a-Dsd16.o: src/pcm/Dsd16.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Dsd16.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Tpo -c -o src/pcm/libpcm_a-Dsd16.o `test -f 'src/pcm/Dsd16.cxx' || echo '$(srcdir)/'`src/pcm/Dsd16.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Tpo src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Dsd16.cxx' object='src/pcm/libpcm_a-Dsd16.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Dsd16.o `test -f 'src/pcm/Dsd16.cxx' || echo '$(srcdir)/'`src/pcm/Dsd16.cxx + +src/pcm/libpcm_a-Dsd16.obj: src/pcm/Dsd16.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Dsd16.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Tpo -c -o src/pcm/libpcm_a-Dsd16.obj `if test -f 'src/pcm/Dsd16.cxx'; then $(CYGPATH_W) 'src/pcm/Dsd16.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Dsd16.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Tpo src/pcm/$(DEPDIR)/libpcm_a-Dsd16.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Dsd16.cxx' object='src/pcm/libpcm_a-Dsd16.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Dsd16.obj `if test -f 'src/pcm/Dsd16.cxx'; then $(CYGPATH_W) 'src/pcm/Dsd16.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Dsd16.cxx'; fi` + +src/pcm/libpcm_a-Dsd32.o: src/pcm/Dsd32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Dsd32.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Tpo -c -o src/pcm/libpcm_a-Dsd32.o `test -f 'src/pcm/Dsd32.cxx' || echo '$(srcdir)/'`src/pcm/Dsd32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Tpo src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Dsd32.cxx' object='src/pcm/libpcm_a-Dsd32.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Dsd32.o `test -f 'src/pcm/Dsd32.cxx' || echo '$(srcdir)/'`src/pcm/Dsd32.cxx + +src/pcm/libpcm_a-Dsd32.obj: src/pcm/Dsd32.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Dsd32.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Tpo -c -o src/pcm/libpcm_a-Dsd32.obj `if test -f 'src/pcm/Dsd32.cxx'; then $(CYGPATH_W) 'src/pcm/Dsd32.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Dsd32.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Tpo src/pcm/$(DEPDIR)/libpcm_a-Dsd32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Dsd32.cxx' object='src/pcm/libpcm_a-Dsd32.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Dsd32.obj `if test -f 'src/pcm/Dsd32.cxx'; then $(CYGPATH_W) 'src/pcm/Dsd32.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Dsd32.cxx'; fi` + src/pcm/libpcm_a-PcmDsd.o: src/pcm/PcmDsd.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-PcmDsd.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-PcmDsd.Tpo -c -o src/pcm/libpcm_a-PcmDsd.o `test -f 'src/pcm/PcmDsd.cxx' || echo '$(srcdir)/'`src/pcm/PcmDsd.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-PcmDsd.Tpo src/pcm/$(DEPDIR)/libpcm_a-PcmDsd.Po @@ -11880,20 +12679,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-SoxrResampler.obj `if test -f 'src/pcm/SoxrResampler.cxx'; then $(CYGPATH_W) 'src/pcm/SoxrResampler.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/SoxrResampler.cxx'; fi` -src/playlist/libplaylist_plugins_a-CloseSongEnumerator.o: src/playlist/CloseSongEnumerator.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-CloseSongEnumerator.o -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Tpo -c -o src/playlist/libplaylist_plugins_a-CloseSongEnumerator.o `test -f 'src/playlist/CloseSongEnumerator.cxx' || echo '$(srcdir)/'`src/playlist/CloseSongEnumerator.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/CloseSongEnumerator.cxx' object='src/playlist/libplaylist_plugins_a-CloseSongEnumerator.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-CloseSongEnumerator.o `test -f 'src/playlist/CloseSongEnumerator.cxx' || echo '$(srcdir)/'`src/playlist/CloseSongEnumerator.cxx - -src/playlist/libplaylist_plugins_a-CloseSongEnumerator.obj: src/playlist/CloseSongEnumerator.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-CloseSongEnumerator.obj -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Tpo -c -o src/playlist/libplaylist_plugins_a-CloseSongEnumerator.obj `if test -f 'src/playlist/CloseSongEnumerator.cxx'; then $(CYGPATH_W) 'src/playlist/CloseSongEnumerator.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/CloseSongEnumerator.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-CloseSongEnumerator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/CloseSongEnumerator.cxx' object='src/playlist/libplaylist_plugins_a-CloseSongEnumerator.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-CloseSongEnumerator.obj `if test -f 'src/playlist/CloseSongEnumerator.cxx'; then $(CYGPATH_W) 'src/playlist/CloseSongEnumerator.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/CloseSongEnumerator.cxx'; fi` - src/playlist/libplaylist_plugins_a-MemorySongEnumerator.o: src/playlist/MemorySongEnumerator.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-MemorySongEnumerator.o -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-MemorySongEnumerator.Tpo -c -o src/playlist/libplaylist_plugins_a-MemorySongEnumerator.o `test -f 'src/playlist/MemorySongEnumerator.cxx' || echo '$(srcdir)/'`src/playlist/MemorySongEnumerator.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-MemorySongEnumerator.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-MemorySongEnumerator.Po @@ -11908,20 +12693,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-MemorySongEnumerator.obj `if test -f 'src/playlist/MemorySongEnumerator.cxx'; then $(CYGPATH_W) 'src/playlist/MemorySongEnumerator.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/MemorySongEnumerator.cxx'; fi` -src/playlist/cue/libplaylist_plugins_a-CueParser.o: src/playlist/cue/CueParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/cue/libplaylist_plugins_a-CueParser.o -MD -MP -MF src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.o `test -f 'src/playlist/cue/CueParser.cxx' || echo '$(srcdir)/'`src/playlist/cue/CueParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/cue/CueParser.cxx' object='src/playlist/cue/libplaylist_plugins_a-CueParser.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.o `test -f 'src/playlist/cue/CueParser.cxx' || echo '$(srcdir)/'`src/playlist/cue/CueParser.cxx - -src/playlist/cue/libplaylist_plugins_a-CueParser.obj: src/playlist/cue/CueParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/cue/libplaylist_plugins_a-CueParser.obj -MD -MP -MF src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.obj `if test -f 'src/playlist/cue/CueParser.cxx'; then $(CYGPATH_W) 'src/playlist/cue/CueParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/cue/CueParser.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/cue/CueParser.cxx' object='src/playlist/cue/libplaylist_plugins_a-CueParser.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.obj `if test -f 'src/playlist/cue/CueParser.cxx'; then $(CYGPATH_W) 'src/playlist/cue/CueParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/cue/CueParser.cxx'; fi` - src/playlist/plugins/libplaylist_plugins_a-ExtM3uPlaylistPlugin.o: src/playlist/plugins/ExtM3uPlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-ExtM3uPlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-ExtM3uPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-ExtM3uPlaylistPlugin.o `test -f 'src/playlist/plugins/ExtM3uPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/ExtM3uPlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-ExtM3uPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-ExtM3uPlaylistPlugin.Po @@ -11950,6 +12721,62 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-M3uPlaylistPlugin.obj `if test -f 'src/playlist/plugins/M3uPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/M3uPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/M3uPlaylistPlugin.cxx'; fi` +src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o: src/playlist/plugins/PlsPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o `test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/PlsPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/PlsPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o `test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/PlsPlaylistPlugin.cxx + +src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj: src/playlist/plugins/PlsPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj `if test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/PlsPlaylistPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/PlsPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj `if test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/PlsPlaylistPlugin.cxx'; fi` + +src/playlist/libplaylist_plugins_a-PlaylistRegistry.o: src/playlist/PlaylistRegistry.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-PlaylistRegistry.o -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.o `test -f 'src/playlist/PlaylistRegistry.cxx' || echo '$(srcdir)/'`src/playlist/PlaylistRegistry.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/PlaylistRegistry.cxx' object='src/playlist/libplaylist_plugins_a-PlaylistRegistry.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.o `test -f 'src/playlist/PlaylistRegistry.cxx' || echo '$(srcdir)/'`src/playlist/PlaylistRegistry.cxx + +src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj: src/playlist/PlaylistRegistry.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj `if test -f 'src/playlist/PlaylistRegistry.cxx'; then $(CYGPATH_W) 'src/playlist/PlaylistRegistry.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/PlaylistRegistry.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/PlaylistRegistry.cxx' object='src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj `if test -f 'src/playlist/PlaylistRegistry.cxx'; then $(CYGPATH_W) 'src/playlist/PlaylistRegistry.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/PlaylistRegistry.cxx'; fi` + +src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.o: src/playlist/plugins/FlacPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.o `test -f 'src/playlist/plugins/FlacPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/FlacPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/FlacPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.o `test -f 'src/playlist/plugins/FlacPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/FlacPlaylistPlugin.cxx + +src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.obj: src/playlist/plugins/FlacPlaylistPlugin.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.obj -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.obj `if test -f 'src/playlist/plugins/FlacPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/FlacPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/FlacPlaylistPlugin.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-FlacPlaylistPlugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/FlacPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-FlacPlaylistPlugin.obj `if test -f 'src/playlist/plugins/FlacPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/FlacPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/FlacPlaylistPlugin.cxx'; fi` + +src/playlist/cue/libplaylist_plugins_a-CueParser.o: src/playlist/cue/CueParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/cue/libplaylist_plugins_a-CueParser.o -MD -MP -MF src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.o `test -f 'src/playlist/cue/CueParser.cxx' || echo '$(srcdir)/'`src/playlist/cue/CueParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/cue/CueParser.cxx' object='src/playlist/cue/libplaylist_plugins_a-CueParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.o `test -f 'src/playlist/cue/CueParser.cxx' || echo '$(srcdir)/'`src/playlist/cue/CueParser.cxx + +src/playlist/cue/libplaylist_plugins_a-CueParser.obj: src/playlist/cue/CueParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/cue/libplaylist_plugins_a-CueParser.obj -MD -MP -MF src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.obj `if test -f 'src/playlist/cue/CueParser.cxx'; then $(CYGPATH_W) 'src/playlist/cue/CueParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/cue/CueParser.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Tpo src/playlist/cue/$(DEPDIR)/libplaylist_plugins_a-CueParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/cue/CueParser.cxx' object='src/playlist/cue/libplaylist_plugins_a-CueParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/cue/libplaylist_plugins_a-CueParser.obj `if test -f 'src/playlist/cue/CueParser.cxx'; then $(CYGPATH_W) 'src/playlist/cue/CueParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/cue/CueParser.cxx'; fi` + src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.o: src/playlist/plugins/CuePlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-CuePlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-CuePlaylistPlugin.o `test -f 'src/playlist/plugins/CuePlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/CuePlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-CuePlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-CuePlaylistPlugin.Po @@ -11978,20 +12805,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-EmbeddedCuePlaylistPlugin.obj `if test -f 'src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx'; fi` -src/playlist/libplaylist_plugins_a-PlaylistRegistry.o: src/playlist/PlaylistRegistry.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-PlaylistRegistry.o -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.o `test -f 'src/playlist/PlaylistRegistry.cxx' || echo '$(srcdir)/'`src/playlist/PlaylistRegistry.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/PlaylistRegistry.cxx' object='src/playlist/libplaylist_plugins_a-PlaylistRegistry.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.o `test -f 'src/playlist/PlaylistRegistry.cxx' || echo '$(srcdir)/'`src/playlist/PlaylistRegistry.cxx - -src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj: src/playlist/PlaylistRegistry.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj -MD -MP -MF src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj `if test -f 'src/playlist/PlaylistRegistry.cxx'; then $(CYGPATH_W) 'src/playlist/PlaylistRegistry.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/PlaylistRegistry.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Tpo src/playlist/$(DEPDIR)/libplaylist_plugins_a-PlaylistRegistry.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/PlaylistRegistry.cxx' object='src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/libplaylist_plugins_a-PlaylistRegistry.obj `if test -f 'src/playlist/PlaylistRegistry.cxx'; then $(CYGPATH_W) 'src/playlist/PlaylistRegistry.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/PlaylistRegistry.cxx'; fi` - src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.o: src/playlist/plugins/SoundCloudPlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-SoundCloudPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.o `test -f 'src/playlist/plugins/SoundCloudPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/SoundCloudPlaylistPlugin.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-SoundCloudPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-SoundCloudPlaylistPlugin.Po @@ -12006,6 +12819,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-SoundCloudPlaylistPlugin.obj `if test -f 'src/playlist/plugins/SoundCloudPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/SoundCloudPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx'; fi` +src/lib/expat/libplaylist_plugins_a-StreamExpatParser.o: src/lib/expat/StreamExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/expat/libplaylist_plugins_a-StreamExpatParser.o -MD -MP -MF src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Tpo -c -o src/lib/expat/libplaylist_plugins_a-StreamExpatParser.o `test -f 'src/lib/expat/StreamExpatParser.cxx' || echo '$(srcdir)/'`src/lib/expat/StreamExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Tpo src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/expat/StreamExpatParser.cxx' object='src/lib/expat/libplaylist_plugins_a-StreamExpatParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/expat/libplaylist_plugins_a-StreamExpatParser.o `test -f 'src/lib/expat/StreamExpatParser.cxx' || echo '$(srcdir)/'`src/lib/expat/StreamExpatParser.cxx + +src/lib/expat/libplaylist_plugins_a-StreamExpatParser.obj: src/lib/expat/StreamExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/expat/libplaylist_plugins_a-StreamExpatParser.obj -MD -MP -MF src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Tpo -c -o src/lib/expat/libplaylist_plugins_a-StreamExpatParser.obj `if test -f 'src/lib/expat/StreamExpatParser.cxx'; then $(CYGPATH_W) 'src/lib/expat/StreamExpatParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/expat/StreamExpatParser.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Tpo src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-StreamExpatParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/expat/StreamExpatParser.cxx' object='src/lib/expat/libplaylist_plugins_a-StreamExpatParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/expat/libplaylist_plugins_a-StreamExpatParser.obj `if test -f 'src/lib/expat/StreamExpatParser.cxx'; then $(CYGPATH_W) 'src/lib/expat/StreamExpatParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/expat/StreamExpatParser.cxx'; fi` + src/lib/expat/libplaylist_plugins_a-ExpatParser.o: src/lib/expat/ExpatParser.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/expat/libplaylist_plugins_a-ExpatParser.o -MD -MP -MF src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-ExpatParser.Tpo -c -o src/lib/expat/libplaylist_plugins_a-ExpatParser.o `test -f 'src/lib/expat/ExpatParser.cxx' || echo '$(srcdir)/'`src/lib/expat/ExpatParser.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-ExpatParser.Tpo src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-ExpatParser.Po @@ -12062,19 +12889,47 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-RssPlaylistPlugin.obj `if test -f 'src/playlist/plugins/RssPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/RssPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/RssPlaylistPlugin.cxx'; fi` -src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o: src/playlist/plugins/PlsPlaylistPlugin.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o `test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/PlsPlaylistPlugin.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/PlsPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o' libtool=no @AMDEPBACKSLASH@ +src/lib/pulse/libpulse_a-LogError.o: src/lib/pulse/LogError.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-LogError.o -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Tpo -c -o src/lib/pulse/libpulse_a-LogError.o `test -f 'src/lib/pulse/LogError.cxx' || echo '$(srcdir)/'`src/lib/pulse/LogError.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/LogError.cxx' object='src/lib/pulse/libpulse_a-LogError.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.o `test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx' || echo '$(srcdir)/'`src/playlist/plugins/PlsPlaylistPlugin.cxx +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-LogError.o `test -f 'src/lib/pulse/LogError.cxx' || echo '$(srcdir)/'`src/lib/pulse/LogError.cxx -src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj: src/playlist/plugins/PlsPlaylistPlugin.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj -MD -MP -MF src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj `if test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/PlsPlaylistPlugin.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Tpo src/playlist/plugins/$(DEPDIR)/libplaylist_plugins_a-PlsPlaylistPlugin.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/playlist/plugins/PlsPlaylistPlugin.cxx' object='src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj' libtool=no @AMDEPBACKSLASH@ +src/lib/pulse/libpulse_a-LogError.obj: src/lib/pulse/LogError.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-LogError.obj -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Tpo -c -o src/lib/pulse/libpulse_a-LogError.obj `if test -f 'src/lib/pulse/LogError.cxx'; then $(CYGPATH_W) 'src/lib/pulse/LogError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/LogError.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-LogError.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/LogError.cxx' object='src/lib/pulse/libpulse_a-LogError.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplaylist_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/playlist/plugins/libplaylist_plugins_a-PlsPlaylistPlugin.obj `if test -f 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; then $(CYGPATH_W) 'src/playlist/plugins/PlsPlaylistPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/playlist/plugins/PlsPlaylistPlugin.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-LogError.obj `if test -f 'src/lib/pulse/LogError.cxx'; then $(CYGPATH_W) 'src/lib/pulse/LogError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/LogError.cxx'; fi` + +src/lib/pulse/libpulse_a-Error.o: src/lib/pulse/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-Error.o -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Tpo -c -o src/lib/pulse/libpulse_a-Error.o `test -f 'src/lib/pulse/Error.cxx' || echo '$(srcdir)/'`src/lib/pulse/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/Error.cxx' object='src/lib/pulse/libpulse_a-Error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-Error.o `test -f 'src/lib/pulse/Error.cxx' || echo '$(srcdir)/'`src/lib/pulse/Error.cxx + +src/lib/pulse/libpulse_a-Error.obj: src/lib/pulse/Error.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-Error.obj -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Tpo -c -o src/lib/pulse/libpulse_a-Error.obj `if test -f 'src/lib/pulse/Error.cxx'; then $(CYGPATH_W) 'src/lib/pulse/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/Error.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-Error.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/Error.cxx' object='src/lib/pulse/libpulse_a-Error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-Error.obj `if test -f 'src/lib/pulse/Error.cxx'; then $(CYGPATH_W) 'src/lib/pulse/Error.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/Error.cxx'; fi` + +src/lib/pulse/libpulse_a-Domain.o: src/lib/pulse/Domain.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-Domain.o -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Tpo -c -o src/lib/pulse/libpulse_a-Domain.o `test -f 'src/lib/pulse/Domain.cxx' || echo '$(srcdir)/'`src/lib/pulse/Domain.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/Domain.cxx' object='src/lib/pulse/libpulse_a-Domain.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-Domain.o `test -f 'src/lib/pulse/Domain.cxx' || echo '$(srcdir)/'`src/lib/pulse/Domain.cxx + +src/lib/pulse/libpulse_a-Domain.obj: src/lib/pulse/Domain.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/pulse/libpulse_a-Domain.obj -MD -MP -MF src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Tpo -c -o src/lib/pulse/libpulse_a-Domain.obj `if test -f 'src/lib/pulse/Domain.cxx'; then $(CYGPATH_W) 'src/lib/pulse/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/Domain.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Tpo src/lib/pulse/$(DEPDIR)/libpulse_a-Domain.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/pulse/Domain.cxx' object='src/lib/pulse/libpulse_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpulse_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/pulse/libpulse_a-Domain.obj `if test -f 'src/lib/pulse/Domain.cxx'; then $(CYGPATH_W) 'src/lib/pulse/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/pulse/Domain.cxx'; fi` src/storage/libstorage_a-Registry.o: src/storage/Registry.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/storage/libstorage_a-Registry.o -MD -MP -MF src/storage/$(DEPDIR)/libstorage_a-Registry.Tpo -c -o src/storage/libstorage_a-Registry.o `test -f 'src/storage/Registry.cxx' || echo '$(srcdir)/'`src/storage/Registry.cxx @@ -12300,20 +13155,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libstorage_a-Blocking.obj `if test -f 'src/lib/nfs/Blocking.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Blocking.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Blocking.cxx'; fi` -src/lib/nfs/libstorage_a-Domain.o: src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/nfs/libstorage_a-Domain.o -MD -MP -MF src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Tpo -c -o src/lib/nfs/libstorage_a-Domain.o `test -f 'src/lib/nfs/Domain.cxx' || echo '$(srcdir)/'`src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Tpo src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/nfs/Domain.cxx' object='src/lib/nfs/libstorage_a-Domain.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libstorage_a-Domain.o `test -f 'src/lib/nfs/Domain.cxx' || echo '$(srcdir)/'`src/lib/nfs/Domain.cxx - -src/lib/nfs/libstorage_a-Domain.obj: src/lib/nfs/Domain.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/nfs/libstorage_a-Domain.obj -MD -MP -MF src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Tpo -c -o src/lib/nfs/libstorage_a-Domain.obj `if test -f 'src/lib/nfs/Domain.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Domain.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Tpo src/lib/nfs/$(DEPDIR)/libstorage_a-Domain.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/nfs/Domain.cxx' object='src/lib/nfs/libstorage_a-Domain.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/nfs/libstorage_a-Domain.obj `if test -f 'src/lib/nfs/Domain.cxx'; then $(CYGPATH_W) 'src/lib/nfs/Domain.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/nfs/Domain.cxx'; fi` - src/storage/plugins/libstorage_a-NfsStorage.o: src/storage/plugins/NfsStorage.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/storage/plugins/libstorage_a-NfsStorage.o -MD -MP -MF src/storage/plugins/$(DEPDIR)/libstorage_a-NfsStorage.Tpo -c -o src/storage/plugins/libstorage_a-NfsStorage.o `test -f 'src/storage/plugins/NfsStorage.cxx' || echo '$(srcdir)/'`src/storage/plugins/NfsStorage.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/storage/plugins/$(DEPDIR)/libstorage_a-NfsStorage.Tpo src/storage/plugins/$(DEPDIR)/libstorage_a-NfsStorage.Po @@ -12328,6 +13169,34 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/storage/plugins/libstorage_a-NfsStorage.obj `if test -f 'src/storage/plugins/NfsStorage.cxx'; then $(CYGPATH_W) 'src/storage/plugins/NfsStorage.cxx'; else $(CYGPATH_W) '$(srcdir)/src/storage/plugins/NfsStorage.cxx'; fi` +src/lib/expat/libstorage_a-ExpatParser.o: src/lib/expat/ExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/expat/libstorage_a-ExpatParser.o -MD -MP -MF src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Tpo -c -o src/lib/expat/libstorage_a-ExpatParser.o `test -f 'src/lib/expat/ExpatParser.cxx' || echo '$(srcdir)/'`src/lib/expat/ExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Tpo src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/expat/ExpatParser.cxx' object='src/lib/expat/libstorage_a-ExpatParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/expat/libstorage_a-ExpatParser.o `test -f 'src/lib/expat/ExpatParser.cxx' || echo '$(srcdir)/'`src/lib/expat/ExpatParser.cxx + +src/lib/expat/libstorage_a-ExpatParser.obj: src/lib/expat/ExpatParser.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/expat/libstorage_a-ExpatParser.obj -MD -MP -MF src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Tpo -c -o src/lib/expat/libstorage_a-ExpatParser.obj `if test -f 'src/lib/expat/ExpatParser.cxx'; then $(CYGPATH_W) 'src/lib/expat/ExpatParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/expat/ExpatParser.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Tpo src/lib/expat/$(DEPDIR)/libstorage_a-ExpatParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/expat/ExpatParser.cxx' object='src/lib/expat/libstorage_a-ExpatParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/expat/libstorage_a-ExpatParser.obj `if test -f 'src/lib/expat/ExpatParser.cxx'; then $(CYGPATH_W) 'src/lib/expat/ExpatParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/expat/ExpatParser.cxx'; fi` + +src/storage/plugins/libstorage_a-CurlStorage.o: src/storage/plugins/CurlStorage.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/storage/plugins/libstorage_a-CurlStorage.o -MD -MP -MF src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Tpo -c -o src/storage/plugins/libstorage_a-CurlStorage.o `test -f 'src/storage/plugins/CurlStorage.cxx' || echo '$(srcdir)/'`src/storage/plugins/CurlStorage.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Tpo src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/storage/plugins/CurlStorage.cxx' object='src/storage/plugins/libstorage_a-CurlStorage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/storage/plugins/libstorage_a-CurlStorage.o `test -f 'src/storage/plugins/CurlStorage.cxx' || echo '$(srcdir)/'`src/storage/plugins/CurlStorage.cxx + +src/storage/plugins/libstorage_a-CurlStorage.obj: src/storage/plugins/CurlStorage.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/storage/plugins/libstorage_a-CurlStorage.obj -MD -MP -MF src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Tpo -c -o src/storage/plugins/libstorage_a-CurlStorage.obj `if test -f 'src/storage/plugins/CurlStorage.cxx'; then $(CYGPATH_W) 'src/storage/plugins/CurlStorage.cxx'; else $(CYGPATH_W) '$(srcdir)/src/storage/plugins/CurlStorage.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Tpo src/storage/plugins/$(DEPDIR)/libstorage_a-CurlStorage.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/storage/plugins/CurlStorage.cxx' object='src/storage/plugins/libstorage_a-CurlStorage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstorage_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/storage/plugins/libstorage_a-CurlStorage.obj `if test -f 'src/storage/plugins/CurlStorage.cxx'; then $(CYGPATH_W) 'src/storage/plugins/CurlStorage.cxx'; else $(CYGPATH_W) '$(srcdir)/src/storage/plugins/CurlStorage.cxx'; fi` + src/tag/libtag_a-Tag.o: src/tag/Tag.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Tag.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Tag.Tpo -c -o src/tag/libtag_a-Tag.o `test -f 'src/tag/Tag.cxx' || echo '$(srcdir)/'`src/tag/Tag.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Tag.Tpo src/tag/$(DEPDIR)/libtag_a-Tag.Po @@ -12370,6 +13239,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-TagHandler.obj `if test -f 'src/tag/TagHandler.cxx'; then $(CYGPATH_W) 'src/tag/TagHandler.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/TagHandler.cxx'; fi` +src/tag/libtag_a-Settings.o: src/tag/Settings.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Settings.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Settings.Tpo -c -o src/tag/libtag_a-Settings.o `test -f 'src/tag/Settings.cxx' || echo '$(srcdir)/'`src/tag/Settings.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Settings.Tpo src/tag/$(DEPDIR)/libtag_a-Settings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Settings.cxx' object='src/tag/libtag_a-Settings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Settings.o `test -f 'src/tag/Settings.cxx' || echo '$(srcdir)/'`src/tag/Settings.cxx + +src/tag/libtag_a-Settings.obj: src/tag/Settings.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Settings.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Settings.Tpo -c -o src/tag/libtag_a-Settings.obj `if test -f 'src/tag/Settings.cxx'; then $(CYGPATH_W) 'src/tag/Settings.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Settings.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Settings.Tpo src/tag/$(DEPDIR)/libtag_a-Settings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Settings.cxx' object='src/tag/libtag_a-Settings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Settings.obj `if test -f 'src/tag/Settings.cxx'; then $(CYGPATH_W) 'src/tag/Settings.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Settings.cxx'; fi` + src/tag/libtag_a-TagConfig.o: src/tag/TagConfig.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-TagConfig.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-TagConfig.Tpo -c -o src/tag/libtag_a-TagConfig.o `test -f 'src/tag/TagConfig.cxx' || echo '$(srcdir)/'`src/tag/TagConfig.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-TagConfig.Tpo src/tag/$(DEPDIR)/libtag_a-TagConfig.Po @@ -12440,6 +13323,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Set.obj `if test -f 'src/tag/Set.cxx'; then $(CYGPATH_W) 'src/tag/Set.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Set.cxx'; fi` +src/tag/libtag_a-Format.o: src/tag/Format.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Format.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Format.Tpo -c -o src/tag/libtag_a-Format.o `test -f 'src/tag/Format.cxx' || echo '$(srcdir)/'`src/tag/Format.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Format.Tpo src/tag/$(DEPDIR)/libtag_a-Format.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Format.cxx' object='src/tag/libtag_a-Format.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Format.o `test -f 'src/tag/Format.cxx' || echo '$(srcdir)/'`src/tag/Format.cxx + +src/tag/libtag_a-Format.obj: src/tag/Format.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Format.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Format.Tpo -c -o src/tag/libtag_a-Format.obj `if test -f 'src/tag/Format.cxx'; then $(CYGPATH_W) 'src/tag/Format.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Format.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Format.Tpo src/tag/$(DEPDIR)/libtag_a-Format.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Format.cxx' object='src/tag/libtag_a-Format.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Format.obj `if test -f 'src/tag/Format.cxx'; then $(CYGPATH_W) 'src/tag/Format.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Format.cxx'; fi` + src/tag/libtag_a-VorbisComment.o: src/tag/VorbisComment.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-VorbisComment.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-VorbisComment.Tpo -c -o src/tag/libtag_a-VorbisComment.o `test -f 'src/tag/VorbisComment.cxx' || echo '$(srcdir)/'`src/tag/VorbisComment.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-VorbisComment.Tpo src/tag/$(DEPDIR)/libtag_a-VorbisComment.Po @@ -12482,6 +13379,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-MixRamp.obj `if test -f 'src/tag/MixRamp.cxx'; then $(CYGPATH_W) 'src/tag/MixRamp.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/MixRamp.cxx'; fi` +src/tag/libtag_a-Generic.o: src/tag/Generic.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Generic.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Generic.Tpo -c -o src/tag/libtag_a-Generic.o `test -f 'src/tag/Generic.cxx' || echo '$(srcdir)/'`src/tag/Generic.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Generic.Tpo src/tag/$(DEPDIR)/libtag_a-Generic.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Generic.cxx' object='src/tag/libtag_a-Generic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Generic.o `test -f 'src/tag/Generic.cxx' || echo '$(srcdir)/'`src/tag/Generic.cxx + +src/tag/libtag_a-Generic.obj: src/tag/Generic.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Generic.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Generic.Tpo -c -o src/tag/libtag_a-Generic.obj `if test -f 'src/tag/Generic.cxx'; then $(CYGPATH_W) 'src/tag/Generic.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Generic.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Generic.Tpo src/tag/$(DEPDIR)/libtag_a-Generic.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Generic.cxx' object='src/tag/libtag_a-Generic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Generic.obj `if test -f 'src/tag/Generic.cxx'; then $(CYGPATH_W) 'src/tag/Generic.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Generic.cxx'; fi` + src/tag/libtag_a-ApeLoader.o: src/tag/ApeLoader.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-ApeLoader.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-ApeLoader.Tpo -c -o src/tag/libtag_a-ApeLoader.o `test -f 'src/tag/ApeLoader.cxx' || echo '$(srcdir)/'`src/tag/ApeLoader.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-ApeLoader.Tpo src/tag/$(DEPDIR)/libtag_a-ApeLoader.Po @@ -12524,6 +13435,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-ApeTag.obj `if test -f 'src/tag/ApeTag.cxx'; then $(CYGPATH_W) 'src/tag/ApeTag.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/ApeTag.cxx'; fi` +src/tag/libtag_a-Id3Load.o: src/tag/Id3Load.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Id3Load.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Id3Load.Tpo -c -o src/tag/libtag_a-Id3Load.o `test -f 'src/tag/Id3Load.cxx' || echo '$(srcdir)/'`src/tag/Id3Load.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Id3Load.Tpo src/tag/$(DEPDIR)/libtag_a-Id3Load.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Id3Load.cxx' object='src/tag/libtag_a-Id3Load.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Id3Load.o `test -f 'src/tag/Id3Load.cxx' || echo '$(srcdir)/'`src/tag/Id3Load.cxx + +src/tag/libtag_a-Id3Load.obj: src/tag/Id3Load.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Id3Load.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Id3Load.Tpo -c -o src/tag/libtag_a-Id3Load.obj `if test -f 'src/tag/Id3Load.cxx'; then $(CYGPATH_W) 'src/tag/Id3Load.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Id3Load.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Id3Load.Tpo src/tag/$(DEPDIR)/libtag_a-Id3Load.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tag/Id3Load.cxx' object='src/tag/libtag_a-Id3Load.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Id3Load.obj `if test -f 'src/tag/Id3Load.cxx'; then $(CYGPATH_W) 'src/tag/Id3Load.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Id3Load.cxx'; fi` + src/tag/libtag_a-TagId3.o: src/tag/TagId3.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-TagId3.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-TagId3.Tpo -c -o src/tag/libtag_a-TagId3.o `test -f 'src/tag/TagId3.cxx' || echo '$(srcdir)/'`src/tag/TagId3.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-TagId3.Tpo src/tag/$(DEPDIR)/libtag_a-TagId3.Po @@ -12580,6 +13505,132 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Aiff.obj `if test -f 'src/tag/Aiff.cxx'; then $(CYGPATH_W) 'src/tag/Aiff.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Aiff.cxx'; fi` +src/lib/xiph/libxiph_a-VorbisComments.o: src/lib/xiph/VorbisComments.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-VorbisComments.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Tpo -c -o src/lib/xiph/libxiph_a-VorbisComments.o `test -f 'src/lib/xiph/VorbisComments.cxx' || echo '$(srcdir)/'`src/lib/xiph/VorbisComments.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/VorbisComments.cxx' object='src/lib/xiph/libxiph_a-VorbisComments.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-VorbisComments.o `test -f 'src/lib/xiph/VorbisComments.cxx' || echo '$(srcdir)/'`src/lib/xiph/VorbisComments.cxx + +src/lib/xiph/libxiph_a-VorbisComments.obj: src/lib/xiph/VorbisComments.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-VorbisComments.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Tpo -c -o src/lib/xiph/libxiph_a-VorbisComments.obj `if test -f 'src/lib/xiph/VorbisComments.cxx'; then $(CYGPATH_W) 'src/lib/xiph/VorbisComments.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/VorbisComments.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-VorbisComments.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/VorbisComments.cxx' object='src/lib/xiph/libxiph_a-VorbisComments.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-VorbisComments.obj `if test -f 'src/lib/xiph/VorbisComments.cxx'; then $(CYGPATH_W) 'src/lib/xiph/VorbisComments.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/VorbisComments.cxx'; fi` + +src/lib/xiph/libxiph_a-XiphTags.o: src/lib/xiph/XiphTags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-XiphTags.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Tpo -c -o src/lib/xiph/libxiph_a-XiphTags.o `test -f 'src/lib/xiph/XiphTags.cxx' || echo '$(srcdir)/'`src/lib/xiph/XiphTags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/XiphTags.cxx' object='src/lib/xiph/libxiph_a-XiphTags.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-XiphTags.o `test -f 'src/lib/xiph/XiphTags.cxx' || echo '$(srcdir)/'`src/lib/xiph/XiphTags.cxx + +src/lib/xiph/libxiph_a-XiphTags.obj: src/lib/xiph/XiphTags.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-XiphTags.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Tpo -c -o src/lib/xiph/libxiph_a-XiphTags.obj `if test -f 'src/lib/xiph/XiphTags.cxx'; then $(CYGPATH_W) 'src/lib/xiph/XiphTags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/XiphTags.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-XiphTags.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/XiphTags.cxx' object='src/lib/xiph/libxiph_a-XiphTags.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-XiphTags.obj `if test -f 'src/lib/xiph/XiphTags.cxx'; then $(CYGPATH_W) 'src/lib/xiph/XiphTags.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/XiphTags.cxx'; fi` + +src/lib/xiph/libxiph_a-OggVisitor.o: src/lib/xiph/OggVisitor.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggVisitor.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Tpo -c -o src/lib/xiph/libxiph_a-OggVisitor.o `test -f 'src/lib/xiph/OggVisitor.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggVisitor.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggVisitor.cxx' object='src/lib/xiph/libxiph_a-OggVisitor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggVisitor.o `test -f 'src/lib/xiph/OggVisitor.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggVisitor.cxx + +src/lib/xiph/libxiph_a-OggVisitor.obj: src/lib/xiph/OggVisitor.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggVisitor.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Tpo -c -o src/lib/xiph/libxiph_a-OggVisitor.obj `if test -f 'src/lib/xiph/OggVisitor.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggVisitor.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggVisitor.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggVisitor.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggVisitor.cxx' object='src/lib/xiph/libxiph_a-OggVisitor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggVisitor.obj `if test -f 'src/lib/xiph/OggVisitor.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggVisitor.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggVisitor.cxx'; fi` + +src/lib/xiph/libxiph_a-OggSerial.o: src/lib/xiph/OggSerial.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggSerial.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Tpo -c -o src/lib/xiph/libxiph_a-OggSerial.o `test -f 'src/lib/xiph/OggSerial.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggSerial.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggSerial.cxx' object='src/lib/xiph/libxiph_a-OggSerial.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggSerial.o `test -f 'src/lib/xiph/OggSerial.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggSerial.cxx + +src/lib/xiph/libxiph_a-OggSerial.obj: src/lib/xiph/OggSerial.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggSerial.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Tpo -c -o src/lib/xiph/libxiph_a-OggSerial.obj `if test -f 'src/lib/xiph/OggSerial.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggSerial.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggSerial.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggSerial.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggSerial.cxx' object='src/lib/xiph/libxiph_a-OggSerial.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggSerial.obj `if test -f 'src/lib/xiph/OggSerial.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggSerial.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggSerial.cxx'; fi` + +src/lib/xiph/libxiph_a-OggSyncState.o: src/lib/xiph/OggSyncState.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggSyncState.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Tpo -c -o src/lib/xiph/libxiph_a-OggSyncState.o `test -f 'src/lib/xiph/OggSyncState.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggSyncState.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggSyncState.cxx' object='src/lib/xiph/libxiph_a-OggSyncState.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggSyncState.o `test -f 'src/lib/xiph/OggSyncState.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggSyncState.cxx + +src/lib/xiph/libxiph_a-OggSyncState.obj: src/lib/xiph/OggSyncState.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggSyncState.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Tpo -c -o src/lib/xiph/libxiph_a-OggSyncState.obj `if test -f 'src/lib/xiph/OggSyncState.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggSyncState.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggSyncState.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggSyncState.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggSyncState.cxx' object='src/lib/xiph/libxiph_a-OggSyncState.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggSyncState.obj `if test -f 'src/lib/xiph/OggSyncState.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggSyncState.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggSyncState.cxx'; fi` + +src/lib/xiph/libxiph_a-OggFind.o: src/lib/xiph/OggFind.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggFind.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Tpo -c -o src/lib/xiph/libxiph_a-OggFind.o `test -f 'src/lib/xiph/OggFind.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggFind.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggFind.cxx' object='src/lib/xiph/libxiph_a-OggFind.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggFind.o `test -f 'src/lib/xiph/OggFind.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggFind.cxx + +src/lib/xiph/libxiph_a-OggFind.obj: src/lib/xiph/OggFind.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggFind.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Tpo -c -o src/lib/xiph/libxiph_a-OggFind.obj `if test -f 'src/lib/xiph/OggFind.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggFind.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggFind.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggFind.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggFind.cxx' object='src/lib/xiph/libxiph_a-OggFind.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggFind.obj `if test -f 'src/lib/xiph/OggFind.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggFind.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggFind.cxx'; fi` + +src/lib/xiph/libxiph_a-OggPacket.o: src/lib/xiph/OggPacket.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggPacket.o -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Tpo -c -o src/lib/xiph/libxiph_a-OggPacket.o `test -f 'src/lib/xiph/OggPacket.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggPacket.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggPacket.cxx' object='src/lib/xiph/libxiph_a-OggPacket.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggPacket.o `test -f 'src/lib/xiph/OggPacket.cxx' || echo '$(srcdir)/'`src/lib/xiph/OggPacket.cxx + +src/lib/xiph/libxiph_a-OggPacket.obj: src/lib/xiph/OggPacket.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/xiph/libxiph_a-OggPacket.obj -MD -MP -MF src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Tpo -c -o src/lib/xiph/libxiph_a-OggPacket.obj `if test -f 'src/lib/xiph/OggPacket.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggPacket.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggPacket.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Tpo src/lib/xiph/$(DEPDIR)/libxiph_a-OggPacket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/xiph/OggPacket.cxx' object='src/lib/xiph/libxiph_a-OggPacket.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxiph_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/xiph/libxiph_a-OggPacket.obj `if test -f 'src/lib/xiph/OggPacket.cxx'; then $(CYGPATH_W) 'src/lib/xiph/OggPacket.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/xiph/OggPacket.cxx'; fi` + +test/test_TestFs-TestFs.o: test/TestFs.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestFs_CPPFLAGS) $(CPPFLAGS) $(test_TestFs_CXXFLAGS) $(CXXFLAGS) -MT test/test_TestFs-TestFs.o -MD -MP -MF test/$(DEPDIR)/test_TestFs-TestFs.Tpo -c -o test/test_TestFs-TestFs.o `test -f 'test/TestFs.cxx' || echo '$(srcdir)/'`test/TestFs.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_TestFs-TestFs.Tpo test/$(DEPDIR)/test_TestFs-TestFs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestFs.cxx' object='test/test_TestFs-TestFs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestFs_CPPFLAGS) $(CPPFLAGS) $(test_TestFs_CXXFLAGS) $(CXXFLAGS) -c -o test/test_TestFs-TestFs.o `test -f 'test/TestFs.cxx' || echo '$(srcdir)/'`test/TestFs.cxx + +test/test_TestFs-TestFs.obj: test/TestFs.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestFs_CPPFLAGS) $(CPPFLAGS) $(test_TestFs_CXXFLAGS) $(CXXFLAGS) -MT test/test_TestFs-TestFs.obj -MD -MP -MF test/$(DEPDIR)/test_TestFs-TestFs.Tpo -c -o test/test_TestFs-TestFs.obj `if test -f 'test/TestFs.cxx'; then $(CYGPATH_W) 'test/TestFs.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestFs.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_TestFs-TestFs.Tpo test/$(DEPDIR)/test_TestFs-TestFs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestFs.cxx' object='test/test_TestFs-TestFs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestFs_CPPFLAGS) $(CPPFLAGS) $(test_TestFs_CXXFLAGS) $(CXXFLAGS) -c -o test/test_TestFs-TestFs.obj `if test -f 'test/TestFs.cxx'; then $(CYGPATH_W) 'test/TestFs.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestFs.cxx'; fi` + +test/test_TestIcu-TestIcu.o: test/TestIcu.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestIcu_CPPFLAGS) $(CPPFLAGS) $(test_TestIcu_CXXFLAGS) $(CXXFLAGS) -MT test/test_TestIcu-TestIcu.o -MD -MP -MF test/$(DEPDIR)/test_TestIcu-TestIcu.Tpo -c -o test/test_TestIcu-TestIcu.o `test -f 'test/TestIcu.cxx' || echo '$(srcdir)/'`test/TestIcu.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_TestIcu-TestIcu.Tpo test/$(DEPDIR)/test_TestIcu-TestIcu.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestIcu.cxx' object='test/test_TestIcu-TestIcu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestIcu_CPPFLAGS) $(CPPFLAGS) $(test_TestIcu_CXXFLAGS) $(CXXFLAGS) -c -o test/test_TestIcu-TestIcu.o `test -f 'test/TestIcu.cxx' || echo '$(srcdir)/'`test/TestIcu.cxx + +test/test_TestIcu-TestIcu.obj: test/TestIcu.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestIcu_CPPFLAGS) $(CPPFLAGS) $(test_TestIcu_CXXFLAGS) $(CXXFLAGS) -MT test/test_TestIcu-TestIcu.obj -MD -MP -MF test/$(DEPDIR)/test_TestIcu-TestIcu.Tpo -c -o test/test_TestIcu-TestIcu.obj `if test -f 'test/TestIcu.cxx'; then $(CYGPATH_W) 'test/TestIcu.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestIcu.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_TestIcu-TestIcu.Tpo test/$(DEPDIR)/test_TestIcu-TestIcu.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestIcu.cxx' object='test/test_TestIcu-TestIcu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_TestIcu_CPPFLAGS) $(CPPFLAGS) $(test_TestIcu_CXXFLAGS) $(CXXFLAGS) -c -o test/test_TestIcu-TestIcu.obj `if test -f 'test/TestIcu.cxx'; then $(CYGPATH_W) 'test/TestIcu.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestIcu.cxx'; fi` + src/test_run_avahi-Log.o: src/Log.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_run_avahi_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_run_avahi-Log.o -MD -MP -MF src/$(DEPDIR)/test_run_avahi-Log.Tpo -c -o src/test_run_avahi-Log.o `test -f 'src/Log.cxx' || echo '$(srcdir)/'`src/Log.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_run_avahi-Log.Tpo src/$(DEPDIR)/test_run_avahi-Log.Po @@ -12804,19 +13855,19 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_mixramp_CPPFLAGS) $(CPPFLAGS) $(test_test_mixramp_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_mixramp-test_mixramp.obj `if test -f 'test/test_mixramp.cxx'; then $(CYGPATH_W) 'test/test_mixramp.cxx'; else $(CYGPATH_W) '$(srcdir)/test/test_mixramp.cxx'; fi` -src/test_test_pcm-AudioFormat.o: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_pcm-AudioFormat.o -MD -MP -MF src/$(DEPDIR)/test_test_pcm-AudioFormat.Tpo -c -o src/test_test_pcm-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_pcm-AudioFormat.Tpo src/$(DEPDIR)/test_test_pcm-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/test_test_pcm-AudioFormat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_pcm-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx - -src/test_test_pcm-AudioFormat.obj: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_pcm-AudioFormat.obj -MD -MP -MF src/$(DEPDIR)/test_test_pcm-AudioFormat.Tpo -c -o src/test_test_pcm-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_pcm-AudioFormat.Tpo src/$(DEPDIR)/test_test_pcm-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/test_test_pcm-AudioFormat.obj' libtool=no @AMDEPBACKSLASH@ +test/test_test_pcm-TestAudioFormat.o: test/TestAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-TestAudioFormat.o -MD -MP -MF test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Tpo -c -o test/test_test_pcm-TestAudioFormat.o `test -f 'test/TestAudioFormat.cxx' || echo '$(srcdir)/'`test/TestAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Tpo test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestAudioFormat.cxx' object='test/test_test_pcm-TestAudioFormat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_pcm-TestAudioFormat.o `test -f 'test/TestAudioFormat.cxx' || echo '$(srcdir)/'`test/TestAudioFormat.cxx + +test/test_test_pcm-TestAudioFormat.obj: test/TestAudioFormat.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-TestAudioFormat.obj -MD -MP -MF test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Tpo -c -o test/test_test_pcm-TestAudioFormat.obj `if test -f 'test/TestAudioFormat.cxx'; then $(CYGPATH_W) 'test/TestAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestAudioFormat.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Tpo test/$(DEPDIR)/test_test_pcm-TestAudioFormat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/TestAudioFormat.cxx' object='test/test_test_pcm-TestAudioFormat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_pcm-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_pcm-TestAudioFormat.obj `if test -f 'test/TestAudioFormat.cxx'; then $(CYGPATH_W) 'test/TestAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/test/TestAudioFormat.cxx'; fi` test/test_test_pcm-test_pcm_dither.o: test/test_pcm_dither.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-test_pcm_dither.o -MD -MP -MF test/$(DEPDIR)/test_test_pcm-test_pcm_dither.Tpo -c -o test/test_test_pcm-test_pcm_dither.o `test -f 'test/test_pcm_dither.cxx' || echo '$(srcdir)/'`test/test_pcm_dither.cxx @@ -12902,6 +13953,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_pcm-test_pcm_mix.obj `if test -f 'test/test_pcm_mix.cxx'; then $(CYGPATH_W) 'test/test_pcm_mix.cxx'; else $(CYGPATH_W) '$(srcdir)/test/test_pcm_mix.cxx'; fi` +test/test_test_pcm-test_pcm_interleave.o: test/test_pcm_interleave.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-test_pcm_interleave.o -MD -MP -MF test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Tpo -c -o test/test_test_pcm-test_pcm_interleave.o `test -f 'test/test_pcm_interleave.cxx' || echo '$(srcdir)/'`test/test_pcm_interleave.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Tpo test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/test_pcm_interleave.cxx' object='test/test_test_pcm-test_pcm_interleave.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_pcm-test_pcm_interleave.o `test -f 'test/test_pcm_interleave.cxx' || echo '$(srcdir)/'`test/test_pcm_interleave.cxx + +test/test_test_pcm-test_pcm_interleave.obj: test/test_pcm_interleave.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-test_pcm_interleave.obj -MD -MP -MF test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Tpo -c -o test/test_test_pcm-test_pcm_interleave.obj `if test -f 'test/test_pcm_interleave.cxx'; then $(CYGPATH_W) 'test/test_pcm_interleave.cxx'; else $(CYGPATH_W) '$(srcdir)/test/test_pcm_interleave.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Tpo test/$(DEPDIR)/test_test_pcm-test_pcm_interleave.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='test/test_pcm_interleave.cxx' object='test/test_test_pcm-test_pcm_interleave.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -c -o test/test_test_pcm-test_pcm_interleave.obj `if test -f 'test/test_pcm_interleave.cxx'; then $(CYGPATH_W) 'test/test_pcm_interleave.cxx'; else $(CYGPATH_W) '$(srcdir)/test/test_pcm_interleave.cxx'; fi` + test/test_test_pcm-test_pcm_export.o: test/test_pcm_export.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_pcm_CPPFLAGS) $(CPPFLAGS) $(test_test_pcm_CXXFLAGS) $(CXXFLAGS) -MT test/test_test_pcm-test_pcm_export.o -MD -MP -MF test/$(DEPDIR)/test_test_pcm-test_pcm_export.Tpo -c -o test/test_test_pcm-test_pcm_export.o `test -f 'test/test_pcm_export.cxx' || echo '$(srcdir)/'`test/test_pcm_export.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) test/$(DEPDIR)/test_test_pcm-test_pcm_export.Tpo test/$(DEPDIR)/test_test_pcm-test_pcm_export.Po @@ -13098,6 +14163,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_translate_song-SongLoader.obj `if test -f 'src/SongLoader.cxx'; then $(CYGPATH_W) 'src/SongLoader.cxx'; else $(CYGPATH_W) '$(srcdir)/src/SongLoader.cxx'; fi` +src/test_test_translate_song-LocateUri.o: src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_translate_song-LocateUri.o -MD -MP -MF src/$(DEPDIR)/test_test_translate_song-LocateUri.Tpo -c -o src/test_test_translate_song-LocateUri.o `test -f 'src/LocateUri.cxx' || echo '$(srcdir)/'`src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_translate_song-LocateUri.Tpo src/$(DEPDIR)/test_test_translate_song-LocateUri.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/LocateUri.cxx' object='src/test_test_translate_song-LocateUri.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_translate_song-LocateUri.o `test -f 'src/LocateUri.cxx' || echo '$(srcdir)/'`src/LocateUri.cxx + +src/test_test_translate_song-LocateUri.obj: src/LocateUri.cxx +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_translate_song-LocateUri.obj -MD -MP -MF src/$(DEPDIR)/test_test_translate_song-LocateUri.Tpo -c -o src/test_test_translate_song-LocateUri.obj `if test -f 'src/LocateUri.cxx'; then $(CYGPATH_W) 'src/LocateUri.cxx'; else $(CYGPATH_W) '$(srcdir)/src/LocateUri.cxx'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_translate_song-LocateUri.Tpo src/$(DEPDIR)/test_test_translate_song-LocateUri.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/LocateUri.cxx' object='src/test_test_translate_song-LocateUri.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_translate_song-LocateUri.obj `if test -f 'src/LocateUri.cxx'; then $(CYGPATH_W) 'src/LocateUri.cxx'; else $(CYGPATH_W) '$(srcdir)/src/LocateUri.cxx'; fi` + src/test_test_translate_song-Log.o: src/Log.cxx @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_translate_song_CPPFLAGS) $(CPPFLAGS) $(test_test_translate_song_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_translate_song-Log.o -MD -MP -MF src/$(DEPDIR)/test_test_translate_song-Log.Tpo -c -o src/test_test_translate_song-Log.o `test -f 'src/Log.cxx' || echo '$(srcdir)/'`src/Log.cxx @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_translate_song-Log.Tpo src/$(DEPDIR)/test_test_translate_song-Log.Po @@ -13182,48 +14261,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-LogBackend.obj `if test -f 'src/LogBackend.cxx'; then $(CYGPATH_W) 'src/LogBackend.cxx'; else $(CYGPATH_W) '$(srcdir)/src/LogBackend.cxx'; fi` -src/test_test_vorbis_encoder-CheckAudioFormat.o: src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-CheckAudioFormat.o -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Tpo -c -o src/test_test_vorbis_encoder-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/test_test_vorbis_encoder-CheckAudioFormat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-CheckAudioFormat.o `test -f 'src/CheckAudioFormat.cxx' || echo '$(srcdir)/'`src/CheckAudioFormat.cxx - -src/test_test_vorbis_encoder-CheckAudioFormat.obj: src/CheckAudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-CheckAudioFormat.obj -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Tpo -c -o src/test_test_vorbis_encoder-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-CheckAudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/CheckAudioFormat.cxx' object='src/test_test_vorbis_encoder-CheckAudioFormat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-CheckAudioFormat.obj `if test -f 'src/CheckAudioFormat.cxx'; then $(CYGPATH_W) 'src/CheckAudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/CheckAudioFormat.cxx'; fi` - -src/test_test_vorbis_encoder-AudioFormat.o: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-AudioFormat.o -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Tpo -c -o src/test_test_vorbis_encoder-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/test_test_vorbis_encoder-AudioFormat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-AudioFormat.o `test -f 'src/AudioFormat.cxx' || echo '$(srcdir)/'`src/AudioFormat.cxx - -src/test_test_vorbis_encoder-AudioFormat.obj: src/AudioFormat.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-AudioFormat.obj -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Tpo -c -o src/test_test_vorbis_encoder-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-AudioFormat.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioFormat.cxx' object='src/test_test_vorbis_encoder-AudioFormat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-AudioFormat.obj `if test -f 'src/AudioFormat.cxx'; then $(CYGPATH_W) 'src/AudioFormat.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioFormat.cxx'; fi` - -src/test_test_vorbis_encoder-AudioParser.o: src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-AudioParser.o -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Tpo -c -o src/test_test_vorbis_encoder-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/test_test_vorbis_encoder-AudioParser.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-AudioParser.o `test -f 'src/AudioParser.cxx' || echo '$(srcdir)/'`src/AudioParser.cxx - -src/test_test_vorbis_encoder-AudioParser.obj: src/AudioParser.cxx -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/test_test_vorbis_encoder-AudioParser.obj -MD -MP -MF src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Tpo -c -o src/test_test_vorbis_encoder-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Tpo src/$(DEPDIR)/test_test_vorbis_encoder-AudioParser.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/AudioParser.cxx' object='src/test_test_vorbis_encoder-AudioParser.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_test_vorbis_encoder_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/test_test_vorbis_encoder-AudioParser.obj `if test -f 'src/AudioParser.cxx'; then $(CYGPATH_W) 'src/AudioParser.cxx'; else $(CYGPATH_W) '$(srcdir)/src/AudioParser.cxx'; fi` - .cxx.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @@ -13701,6 +14738,20 @@ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +test/TestFs.log: test/TestFs$(EXEEXT) + @p='test/TestFs$(EXEEXT)'; \ + b='test/TestFs'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +test/TestIcu.log: test/TestIcu$(EXEEXT) + @p='test/TestIcu$(EXEEXT)'; \ + b='test/TestIcu'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) test/test_icy_parser.log: test/test_icy_parser$(EXEEXT) @p='test/test_icy_parser$(EXEEXT)'; \ b='test/test_icy_parser'; \ @@ -13924,7 +14975,7 @@ $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am -@ANDROID_FALSE@@ENABLE_DOCUMENTATION_FALSE@all-local: +@ANDROID_FALSE@@ENABLE_DOCUMENTATION_FALSE@@ENABLE_HAIKU_FALSE@all-local: all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) $(DATA) config.h \ all-local installdirs: @@ -14011,6 +15062,8 @@ -rm -f src/input/plugins/$(am__dirstamp) -rm -f src/java/$(DEPDIR)/$(am__dirstamp) -rm -f src/java/$(am__dirstamp) + -rm -f src/lib/curl/$(DEPDIR)/$(am__dirstamp) + -rm -f src/lib/curl/$(am__dirstamp) -rm -f src/lib/expat/$(DEPDIR)/$(am__dirstamp) -rm -f src/lib/expat/$(am__dirstamp) -rm -f src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp) @@ -14019,10 +15072,16 @@ -rm -f src/lib/icu/$(am__dirstamp) -rm -f src/lib/nfs/$(DEPDIR)/$(am__dirstamp) -rm -f src/lib/nfs/$(am__dirstamp) + -rm -f src/lib/pulse/$(DEPDIR)/$(am__dirstamp) + -rm -f src/lib/pulse/$(am__dirstamp) -rm -f src/lib/smbclient/$(DEPDIR)/$(am__dirstamp) -rm -f src/lib/smbclient/$(am__dirstamp) + -rm -f src/lib/sqlite/$(DEPDIR)/$(am__dirstamp) + -rm -f src/lib/sqlite/$(am__dirstamp) -rm -f src/lib/upnp/$(DEPDIR)/$(am__dirstamp) -rm -f src/lib/upnp/$(am__dirstamp) + -rm -f src/lib/xiph/$(DEPDIR)/$(am__dirstamp) + -rm -f src/lib/xiph/$(am__dirstamp) -rm -f src/lib/zlib/$(DEPDIR)/$(am__dirstamp) -rm -f src/lib/zlib/$(am__dirstamp) -rm -f src/mixer/$(DEPDIR)/$(am__dirstamp) @@ -14033,6 +15092,8 @@ -rm -f src/neighbor/$(am__dirstamp) -rm -f src/neighbor/plugins/$(DEPDIR)/$(am__dirstamp) -rm -f src/neighbor/plugins/$(am__dirstamp) + -rm -f src/net/$(DEPDIR)/$(am__dirstamp) + -rm -f src/net/$(am__dirstamp) -rm -f src/output/$(DEPDIR)/$(am__dirstamp) -rm -f src/output/$(am__dirstamp) -rm -f src/output/plugins/$(DEPDIR)/$(am__dirstamp) @@ -14045,6 +15106,8 @@ -rm -f src/pcm/$(am__dirstamp) -rm -f src/pcm/dsd2pcm/$(DEPDIR)/$(am__dirstamp) -rm -f src/pcm/dsd2pcm/$(am__dirstamp) + -rm -f src/player/$(DEPDIR)/$(am__dirstamp) + -rm -f src/player/$(am__dirstamp) -rm -f src/playlist/$(DEPDIR)/$(am__dirstamp) -rm -f src/playlist/$(am__dirstamp) -rm -f src/playlist/cue/$(DEPDIR)/$(am__dirstamp) @@ -14083,8 +15146,8 @@ @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) @ENABLE_DOCUMENTATION_FALSE@uninstall-local: +@ANDROID_FALSE@@ENABLE_DOCUMENTATION_FALSE@@ENABLE_HAIKU_FALSE@clean-local: @ENABLE_DOCUMENTATION_FALSE@install-data-local: -@ANDROID_FALSE@@ENABLE_DOCUMENTATION_FALSE@clean-local: clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-local \ @@ -14092,7 +15155,7 @@ distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/AudioCompress/$(DEPDIR) src/android/$(DEPDIR) src/archive/$(DEPDIR) src/archive/plugins/$(DEPDIR) src/client/$(DEPDIR) src/command/$(DEPDIR) src/config/$(DEPDIR) src/db/$(DEPDIR) src/db/plugins/$(DEPDIR) src/db/plugins/simple/$(DEPDIR) src/db/plugins/upnp/$(DEPDIR) src/db/update/$(DEPDIR) src/decoder/$(DEPDIR) src/decoder/plugins/$(DEPDIR) src/encoder/$(DEPDIR) src/encoder/plugins/$(DEPDIR) src/event/$(DEPDIR) src/filter/$(DEPDIR) src/filter/plugins/$(DEPDIR) src/fs/$(DEPDIR) src/fs/io/$(DEPDIR) src/input/$(DEPDIR) src/input/plugins/$(DEPDIR) src/java/$(DEPDIR) src/lib/expat/$(DEPDIR) src/lib/ffmpeg/$(DEPDIR) src/lib/icu/$(DEPDIR) src/lib/nfs/$(DEPDIR) src/lib/smbclient/$(DEPDIR) src/lib/upnp/$(DEPDIR) src/lib/zlib/$(DEPDIR) src/mixer/$(DEPDIR) src/mixer/plugins/$(DEPDIR) src/neighbor/$(DEPDIR) src/neighbor/plugins/$(DEPDIR) src/output/$(DEPDIR) src/output/plugins/$(DEPDIR) src/output/plugins/httpd/$(DEPDIR) src/output/plugins/sles/$(DEPDIR) src/pcm/$(DEPDIR) src/pcm/dsd2pcm/$(DEPDIR) src/playlist/$(DEPDIR) src/playlist/cue/$(DEPDIR) src/playlist/plugins/$(DEPDIR) src/protocol/$(DEPDIR) src/queue/$(DEPDIR) src/sticker/$(DEPDIR) src/storage/$(DEPDIR) src/storage/plugins/$(DEPDIR) src/system/$(DEPDIR) src/tag/$(DEPDIR) src/thread/$(DEPDIR) src/unix/$(DEPDIR) src/util/$(DEPDIR) src/win32/$(DEPDIR) src/zeroconf/$(DEPDIR) test/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/AudioCompress/$(DEPDIR) src/android/$(DEPDIR) src/archive/$(DEPDIR) src/archive/plugins/$(DEPDIR) src/client/$(DEPDIR) src/command/$(DEPDIR) src/config/$(DEPDIR) src/db/$(DEPDIR) src/db/plugins/$(DEPDIR) src/db/plugins/simple/$(DEPDIR) src/db/plugins/upnp/$(DEPDIR) src/db/update/$(DEPDIR) src/decoder/$(DEPDIR) src/decoder/plugins/$(DEPDIR) src/encoder/$(DEPDIR) src/encoder/plugins/$(DEPDIR) src/event/$(DEPDIR) src/filter/$(DEPDIR) src/filter/plugins/$(DEPDIR) src/fs/$(DEPDIR) src/fs/io/$(DEPDIR) src/input/$(DEPDIR) src/input/plugins/$(DEPDIR) src/java/$(DEPDIR) src/lib/curl/$(DEPDIR) src/lib/expat/$(DEPDIR) src/lib/ffmpeg/$(DEPDIR) src/lib/icu/$(DEPDIR) src/lib/nfs/$(DEPDIR) src/lib/pulse/$(DEPDIR) src/lib/smbclient/$(DEPDIR) src/lib/sqlite/$(DEPDIR) src/lib/upnp/$(DEPDIR) src/lib/xiph/$(DEPDIR) src/lib/zlib/$(DEPDIR) src/mixer/$(DEPDIR) src/mixer/plugins/$(DEPDIR) src/neighbor/$(DEPDIR) src/neighbor/plugins/$(DEPDIR) src/net/$(DEPDIR) src/output/$(DEPDIR) src/output/plugins/$(DEPDIR) src/output/plugins/httpd/$(DEPDIR) src/output/plugins/sles/$(DEPDIR) src/pcm/$(DEPDIR) src/pcm/dsd2pcm/$(DEPDIR) src/player/$(DEPDIR) src/playlist/$(DEPDIR) src/playlist/cue/$(DEPDIR) src/playlist/plugins/$(DEPDIR) src/protocol/$(DEPDIR) src/queue/$(DEPDIR) src/sticker/$(DEPDIR) src/storage/$(DEPDIR) src/storage/plugins/$(DEPDIR) src/system/$(DEPDIR) src/tag/$(DEPDIR) src/thread/$(DEPDIR) src/unix/$(DEPDIR) src/util/$(DEPDIR) src/win32/$(DEPDIR) src/zeroconf/$(DEPDIR) test/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -14143,7 +15206,7 @@ maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf src/$(DEPDIR) src/AudioCompress/$(DEPDIR) src/android/$(DEPDIR) src/archive/$(DEPDIR) src/archive/plugins/$(DEPDIR) src/client/$(DEPDIR) src/command/$(DEPDIR) src/config/$(DEPDIR) src/db/$(DEPDIR) src/db/plugins/$(DEPDIR) src/db/plugins/simple/$(DEPDIR) src/db/plugins/upnp/$(DEPDIR) src/db/update/$(DEPDIR) src/decoder/$(DEPDIR) src/decoder/plugins/$(DEPDIR) src/encoder/$(DEPDIR) src/encoder/plugins/$(DEPDIR) src/event/$(DEPDIR) src/filter/$(DEPDIR) src/filter/plugins/$(DEPDIR) src/fs/$(DEPDIR) src/fs/io/$(DEPDIR) src/input/$(DEPDIR) src/input/plugins/$(DEPDIR) src/java/$(DEPDIR) src/lib/expat/$(DEPDIR) src/lib/ffmpeg/$(DEPDIR) src/lib/icu/$(DEPDIR) src/lib/nfs/$(DEPDIR) src/lib/smbclient/$(DEPDIR) src/lib/upnp/$(DEPDIR) src/lib/zlib/$(DEPDIR) src/mixer/$(DEPDIR) src/mixer/plugins/$(DEPDIR) src/neighbor/$(DEPDIR) src/neighbor/plugins/$(DEPDIR) src/output/$(DEPDIR) src/output/plugins/$(DEPDIR) src/output/plugins/httpd/$(DEPDIR) src/output/plugins/sles/$(DEPDIR) src/pcm/$(DEPDIR) src/pcm/dsd2pcm/$(DEPDIR) src/playlist/$(DEPDIR) src/playlist/cue/$(DEPDIR) src/playlist/plugins/$(DEPDIR) src/protocol/$(DEPDIR) src/queue/$(DEPDIR) src/sticker/$(DEPDIR) src/storage/$(DEPDIR) src/storage/plugins/$(DEPDIR) src/system/$(DEPDIR) src/tag/$(DEPDIR) src/thread/$(DEPDIR) src/unix/$(DEPDIR) src/util/$(DEPDIR) src/win32/$(DEPDIR) src/zeroconf/$(DEPDIR) test/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/AudioCompress/$(DEPDIR) src/android/$(DEPDIR) src/archive/$(DEPDIR) src/archive/plugins/$(DEPDIR) src/client/$(DEPDIR) src/command/$(DEPDIR) src/config/$(DEPDIR) src/db/$(DEPDIR) src/db/plugins/$(DEPDIR) src/db/plugins/simple/$(DEPDIR) src/db/plugins/upnp/$(DEPDIR) src/db/update/$(DEPDIR) src/decoder/$(DEPDIR) src/decoder/plugins/$(DEPDIR) src/encoder/$(DEPDIR) src/encoder/plugins/$(DEPDIR) src/event/$(DEPDIR) src/filter/$(DEPDIR) src/filter/plugins/$(DEPDIR) src/fs/$(DEPDIR) src/fs/io/$(DEPDIR) src/input/$(DEPDIR) src/input/plugins/$(DEPDIR) src/java/$(DEPDIR) src/lib/curl/$(DEPDIR) src/lib/expat/$(DEPDIR) src/lib/ffmpeg/$(DEPDIR) src/lib/icu/$(DEPDIR) src/lib/nfs/$(DEPDIR) src/lib/pulse/$(DEPDIR) src/lib/smbclient/$(DEPDIR) src/lib/sqlite/$(DEPDIR) src/lib/upnp/$(DEPDIR) src/lib/xiph/$(DEPDIR) src/lib/zlib/$(DEPDIR) src/mixer/$(DEPDIR) src/mixer/plugins/$(DEPDIR) src/neighbor/$(DEPDIR) src/neighbor/plugins/$(DEPDIR) src/net/$(DEPDIR) src/output/$(DEPDIR) src/output/plugins/$(DEPDIR) src/output/plugins/httpd/$(DEPDIR) src/output/plugins/sles/$(DEPDIR) src/pcm/$(DEPDIR) src/pcm/dsd2pcm/$(DEPDIR) src/player/$(DEPDIR) src/playlist/$(DEPDIR) src/playlist/cue/$(DEPDIR) src/playlist/plugins/$(DEPDIR) src/protocol/$(DEPDIR) src/queue/$(DEPDIR) src/sticker/$(DEPDIR) src/storage/$(DEPDIR) src/storage/plugins/$(DEPDIR) src/system/$(DEPDIR) src/tag/$(DEPDIR) src/thread/$(DEPDIR) src/unix/$(DEPDIR) src/util/$(DEPDIR) src/win32/$(DEPDIR) src/zeroconf/$(DEPDIR) test/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -14196,7 +15259,7 @@ .PRECIOUS: Makefile -@ANDROID_TRUE@all-local: android/build/bin/Main-debug.apk +@ANDROID_TRUE@all-local: android/build/bin/$(APK_NAME)-debug.apk @ANDROID_TRUE@clean-local: @ANDROID_TRUE@ rm -rf android/build @@ -14208,8 +15271,8 @@ @ANDROID_TRUE@ mkdir -p android/build/include android/build/res android/build/src/org @ANDROID_TRUE@ ln -s $(abs_srcdir)/android/AndroidManifest.xml $(abs_srcdir)/android/custom_rules.xml android/build @ANDROID_TRUE@ ln -s $(abs_srcdir)/android/src android/build/src/org/musicpd -@ANDROID_TRUE@ ln -s $(abs_srcdir)/android/res/values android/build/res -@ANDROID_TRUE@ $(ANDROID_SDK)/tools/android update project --path android/build --target android-17 +@ANDROID_TRUE@ ln -s $(abs_srcdir)/android/res/values $(abs_srcdir)/android/res/layout android/build/res +@ANDROID_TRUE@ $(ANDROID_SDK)/tools/android update project --path android/build --target android-17 --name $(APK_NAME) @ANDROID_TRUE@android/build/bin/classes/org/musicpd/Bridge.class: android/src/Bridge.java android/build/build.xml android/build/res/drawable/icon.png @ANDROID_TRUE@ cd android/build && ant compile-jni-classes @@ -14226,25 +15289,41 @@ @ANDROID_TRUE@ mkdir -p $(@D) @ANDROID_TRUE@ rsvg-convert --width=48 --height=48 $< -o $@ -@ANDROID_TRUE@android/build/bin/Main-debug.apk: $(APK_DEPS) +@ANDROID_TRUE@android/build/bin/$(APK_NAME)-debug.apk: $(APK_DEPS) @ANDROID_TRUE@ cd android/build && ant nodeps debug -@ANDROID_TRUE@android/build/bin/Main-release-unsigned.apk: $(APK_DEPS) +@ANDROID_TRUE@android/build/bin/$(APK_NAME)-release-unsigned.apk: $(APK_DEPS) @ANDROID_TRUE@ cd android/build && ant nodeps release -@ANDROID_TRUE@android/build/bin/Main-release-unaligned.apk: android/build/bin/Main-release-unsigned.apk +@ANDROID_TRUE@android/build/bin/$(APK_NAME)-release-unaligned.apk: android/build/bin/$(APK_NAME)-release-unsigned.apk @ANDROID_TRUE@ jarsigner -digestalg SHA1 -sigalg MD5withRSA -storepass:env ANDROID_KEYSTORE_PASS -keystore $(ANDROID_KEYSTORE) -signedjar $@ $< $(ANDROID_KEY_ALIAS) -@ANDROID_TRUE@android/build/bin/Main.apk: android/build/bin/Main-release-unaligned.apk +@ANDROID_TRUE@android/build/bin/$(APK_NAME).apk: android/build/bin/$(APK_NAME)-release-unaligned.apk @ANDROID_TRUE@ $(ANDROID_SDK)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/zipalign -f 4 $< $@ # # Windows resource file # -src/win32/mpd_win32_rc.$(OBJEXT): src/win32/mpd_win32_rc.rc +win32/res/mpd.$(OBJEXT): %.$(OBJEXT): %.rc $(WINDRES) -i $< -o $@ +# +# Haiku resource file +# + +src/haiku/mpd.rsrc: src/haiku/mpd.rdef + $(RC) -o $@ $< + +@ENABLE_HAIKU_TRUE@src/mpd.haiku-rsrc-done: src/mpd src/haiku/mpd.rsrc +@ENABLE_HAIKU_TRUE@ $(XRES) -o src/mpd src/haiku/mpd.rsrc +@ENABLE_HAIKU_TRUE@ @touch src/mpd.haiku-rsrc-done + +@ENABLE_HAIKU_TRUE@all-local: src/mpd.haiku-rsrc-done + +@ENABLE_HAIKU_TRUE@clean-local: +@ENABLE_HAIKU_TRUE@ rm -rf src/haiku/mpd.rsrc src/mpd.haiku-rsrc-done + @ENABLE_DOCUMENTATION_TRUE@$(DOCBOOK_HTML): %/index.html: %.xml $(DOCBOOK_INCLUDES) @ENABLE_DOCUMENTATION_TRUE@ $(XMLTO) -o $(@D) --stringparam chunker.output.encoding=utf-8 html --stringparam use.id.as.filename=1 $< @@ -14267,7 +15346,7 @@ @ENABLE_DOCUMENTATION_TRUE@ rm -f $(DESTDIR)$(docdir)/api/html/*.* @ENABLE_DOCUMENTATION_TRUE@upload: $(DOCBOOK_HTML) doc/api/html/index.html -@ENABLE_DOCUMENTATION_TRUE@ rsync -vpruz --delete doc/ www.musicpd.org:/var/www/doc/ \ +@ENABLE_DOCUMENTATION_TRUE@ rsync -vpruz --delete doc/ www.musicpd.org:/var/www/mpd/doc/ \ @ENABLE_DOCUMENTATION_TRUE@ --chmod=Dug+rwx,Do+rx,Fug+rw,Fo+r \ @ENABLE_DOCUMENTATION_TRUE@ --include=protocol --include=protocol/** \ @ENABLE_DOCUMENTATION_TRUE@ --include=user --include=user/** \ diff -Nru mpd-0.19.21/NEWS mpd-0.20.9/NEWS --- mpd-0.19.21/NEWS 2016-12-13 09:54:11.000000000 +0000 +++ mpd-0.20.9/NEWS 2017-06-04 10:51:36.000000000 +0000 @@ -1,3 +1,160 @@ +ver 0.20.9 (2017/06/04) +* decoder + - ffmpeg: support *.adx +* fix byte order detection on FreeBSD/aarch64 +* fix more random crashes when compiled with clang + +ver 0.20.8 (2017/05/19) +* output + - osx: fix build failure due to missing "noexcept" +* playlist + - m3u: support MIME type `audio/mpegurl` +* fix build failure with GCC 4.x + +ver 0.20.7 (2017/05/15) +* database + - simple: fix false positive directory loop detection with NFS +* enforce a reasonable minimum audio_buffer_size setting +* cap buffer_before_play at 80% to prevent deadlock +* fix random crashes when compiled with clang + +ver 0.20.6 (2017/03/10) +* input + - curl: fix headers after HTTP redirect to Shoutcast server +* decoder + - ffmpeg: re-enable as fallback + - mpcdec: fix crash (division by zero) after seeking + - sidplay: make compatible with libsidplayfp < 1.8 +* fix stream tags after automatic song change +* workaround for GCC 4.9.4 / libstdc++ bug (build failure) + +ver 0.20.5 (2017/02/20) +* tags + - id3: fix memory leak on corrupt ID3 tags +* decoder + - sidplay: don't require libsidutils when building with libsidplayfp +* output + - httpd: fix two buffer overflows in IcyMetaData length calculation +* mixer + - alsa: fix crash bug + +ver 0.20.4 (2017/02/01) +* input + - nfs: fix freeze after reconnect +* output + - sndio: work around a libroar C++ incompatibility +* workaround for GCC 4.9 "constexpr" bug +* fix FreeBSD build failure + +ver 0.20.3 (2017/01/25) +* protocol + - "playlistadd" creates new playlist if it does not exist, as documented +* database + - proxy: fix error "terminate called after throwing ..." + - proxy: make connect errors during startup non-fatal +* neighbor + - upnp: fix premature expiry +* replay gain: don't reset ReplayGain levels when unpausing playback +* silence surround channels when converting from stereo +* use shortcuts such as "dsd64" in log messages + +ver 0.20.2 (2017/01/15) +* input + - alsa: fix crash bug + - alsa: fix buffer overruns +* decoder + - flac: add options "probesize" and "analyzeduration" +* resampler + - libsamplerate: reset state after seeking +* output + - fix static noise after changing to a different audio format + - alsa: fix the DSD_U32 sample rate + - alsa: fix the DSD_U32 byte order + - alsa: support DSD_U16 + - recorder: fix error "Failed to create : No such file or directory" +* playlist + - cue: fix skipping songs + +ver 0.20.1 (2017/01/09) +* input + - curl: fix crash bug + - curl: fix freeze bug +* decoder + - wavpack: fix crash bug +* storage + - curl: new storage plugin for WebDAV (work in progress) +* mixer + - alsa: normalize displayed volume according to human perception +* fix crash with volume_normalization enabled + +ver 0.20 (2017/01/04) +* protocol + - "commands" returns playlist commands only if playlist_directory configured + - "search"/"find" have a "window" parameter + - report song duration with milliseconds precision + - "sticker find" can match sticker values + - drop the "file:///" prefix for absolute file paths + - add range parameter to command "plchanges" and "plchangesposid" + - send verbose error message to client +* input + - curl: fix memory leak +* tags + - ape, ogg: drop support for non-standard tag "album artist" + affected filetypes: vorbis, flac, opus & all files with ape2 tags + (most importantly some mp3s) + - id3: remove the "id3v1_encoding" setting; by definition, all ID3v1 tags + are ISO-Latin-1 + - ape: support APE replay gain on remote files + - read ID3 tags from NFS/SMB +* decoder + - improved error logging + - report I/O errors to clients + - ffmpeg: support ReplayGain and MixRamp + - ffmpeg: support stream tags + - gme: add option "accuracy" + - gme: provide the TRACK tag + - gme: faster scanning + - mad: reduce memory usage while scanning tags + - mpcdec: read the bit rate + - pcm: support audio/L16 (RFC 2586) and audio/x-mpd-float + - sidplay: faster scanning + - wavpack: large file support + - wavpack: support DSD (WavPack 5) + - wavpack: archive support +* playlist + - cue: don't skip pregap + - embcue: fix last track + - flac: new plugin which reads the "CUESHEET" metadata block +* output + - alsa: fix multi-channel order + - alsa: remove option "use_mmap" + - alsa: support DSD_U32 + - alsa: disable DoP if it fails + - jack: reduce CPU usage + - pulse: set channel map to WAVE-EX + - recorder: record tags + - recorder: allow dynamic file names + - sndio: new output plugin +* mixer + - null: new plugin +* resampler + - new block "resampler" in configuration file + replacing the old "samplerate_converter" setting + - soxr: allow multi-threaded resampling +* player + - reset song priority on playback + - reduce xruns +* write database and state file atomically +* always write UTF-8 to the log file. +* remove dependency on GLib +* support libsystemd (instead of the older libsystemd-daemon) +* database + - proxy: add TCP keepalive option +* update + - apply .mpdignore matches to subdirectories +* switch the code base to C++14 + - GCC 4.9 or clang 3.4 (or newer) recommended + ver 0.19.21 (2016/12/13) * decoder - ffmpeg: fix crash bug diff -Nru mpd-0.19.21/README mpd-0.20.9/README --- mpd-0.19.21/README 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - - Music Player Daemon (MPD) - http://www.musicpd.org - -A daemon for playing music of various formats. Music is played through the -server's audio device. The daemon stores info about all available music, -and this info can be easily searched and retrieved. Player control, info -retrieval, and playlist management can all be managed remotely. - -For basic installation information see the INSTALL file. - -MPD is released under the GNU General Public License version 2, which is -distributed in the COPYING file. - -You should have received a copy of the GNU General Public License along with -this program. If not, see . - diff -Nru mpd-0.19.21/README.md mpd-0.20.9/README.md --- mpd-0.19.21/README.md 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/README.md 2017-05-16 05:24:02.000000000 +0000 @@ -0,0 +1,29 @@ +# Music Player Daemon + +http://www.musicpd.org + +A daemon for playing music of various formats. Music is played through the +server's audio device. The daemon stores info about all available music, +and this info can be easily searched and retrieved. Player control, info +retrieval, and playlist management can all be managed remotely. + +For basic installation instructions +[read the manual](https://www.musicpd.org/doc/user/install.html). + +# Users + +- [Manual](http://www.musicpd.org/doc/user/) +- [Forum](http://forum.musicpd.org/) +- [IRC](irc://chat.freenode.net/#mpd) +- [Bug tracker](https://github.com/MusicPlayerDaemon/MPD/issues/) + +# Developers + +- [Protocol specification](http://www.musicpd.org/doc/protocol/) +- [Developer manual](http://www.musicpd.org/doc/developer/) + +# Legal + +MPD is released under the +[GNU General Public License version 2](https://www.gnu.org/licenses/gpl-2.0.txt), +which is distributed in the COPYING file. diff -Nru mpd-0.19.21/src/android/Context.cxx mpd-0.20.9/src/android/Context.cxx --- mpd-0.19.21/src/android/Context.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/android/Context.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/android/Context.hxx mpd-0.20.9/src/android/Context.hxx --- mpd-0.19.21/src/android/Context.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/android/Context.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/android/Environment.cxx mpd-0.20.9/src/android/Environment.cxx --- mpd-0.19.21/src/android/Environment.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/android/Environment.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/android/Environment.hxx mpd-0.20.9/src/android/Environment.hxx --- mpd-0.19.21/src/android/Environment.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/android/Environment.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/ArchiveDomain.cxx mpd-0.20.9/src/archive/ArchiveDomain.cxx --- mpd-0.19.21/src/archive/ArchiveDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/ArchiveDomain.hxx mpd-0.20.9/src/archive/ArchiveDomain.hxx --- mpd-0.19.21/src/archive/ArchiveDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/ArchiveFile.hxx mpd-0.20.9/src/archive/ArchiveFile.hxx --- mpd-0.19.21/src/archive/ArchiveFile.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveFile.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ class Mutex; class Cond; -class Error; struct ArchivePlugin; class ArchiveVisitor; class InputStream; @@ -51,11 +50,12 @@ /** * Opens an InputStream of a file within the archive. * + * Throws std::runtime_error on error. + * * @param path the path within the archive */ virtual InputStream *OpenStream(const char *path, - Mutex &mutex, Cond &cond, - Error &error) = 0; + Mutex &mutex, Cond &cond) = 0; }; #endif diff -Nru mpd-0.19.21/src/archive/ArchiveList.cxx mpd-0.20.9/src/archive/ArchiveList.cxx --- mpd-0.19.21/src/archive/ArchiveList.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveList.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,13 +29,13 @@ #include const ArchivePlugin *const archive_plugins[] = { -#ifdef HAVE_BZ2 +#ifdef ENABLE_BZ2 &bz2_archive_plugin, #endif -#ifdef HAVE_ZZIP +#ifdef ENABLE_ZZIP &zzip_archive_plugin, #endif -#ifdef HAVE_ISO9660 +#ifdef ENABLE_ISO9660 &iso9660_archive_plugin, #endif nullptr @@ -56,7 +56,7 @@ archive_plugins_for_each_enabled(plugin) if (plugin->suffixes != nullptr && - string_array_contains(plugin->suffixes, suffix)) + StringArrayContainsCase(plugin->suffixes, suffix)) return plugin; return nullptr; diff -Nru mpd-0.19.21/src/archive/ArchiveList.hxx mpd-0.20.9/src/archive/ArchiveList.hxx --- mpd-0.19.21/src/archive/ArchiveList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveList.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -39,9 +39,11 @@ archive_plugin_from_name(const char *name); /* this is where we "load" all the "plugins" ;-) */ -void archive_plugin_init_all(void); +void +archive_plugin_init_all(); /* this is where we "unload" all the "plugins" */ -void archive_plugin_deinit_all(void); +void +archive_plugin_deinit_all(); #endif diff -Nru mpd-0.19.21/src/archive/ArchiveLookup.cxx mpd-0.20.9/src/archive/ArchiveLookup.cxx --- mpd-0.19.21/src/archive/ArchiveLookup.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveLookup.cxx 2017-05-08 15:17:19.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ gcc_pure static char * -FindSlash(char *p, size_t i) +FindSlash(char *p, size_t i) noexcept { for (; i > 0; --i) if (p[i] == '/') @@ -39,7 +39,7 @@ gcc_pure static const char * -FindSuffix(const char *p, const char *i) +FindSuffix(const char *p, const char *i) noexcept { for (; i > p; --i) { if (*i == '.') diff -Nru mpd-0.19.21/src/archive/ArchiveLookup.hxx mpd-0.20.9/src/archive/ArchiveLookup.hxx --- mpd-0.19.21/src/archive/ArchiveLookup.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveLookup.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/ArchivePlugin.cxx mpd-0.20.9/src/archive/ArchivePlugin.cxx --- mpd-0.19.21/src/archive/ArchivePlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchivePlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,22 +19,16 @@ #include "config.h" #include "ArchivePlugin.hxx" -#include "ArchiveFile.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" #include ArchiveFile * -archive_file_open(const ArchivePlugin *plugin, Path path, - Error &error) +archive_file_open(const ArchivePlugin *plugin, Path path) { assert(plugin != nullptr); assert(plugin->open != nullptr); assert(!path.IsNull()); - ArchiveFile *file = plugin->open(path, error); - assert((file == nullptr) == error.IsDefined()); - - return file; + return plugin->open(path); } diff -Nru mpd-0.19.21/src/archive/ArchivePlugin.hxx mpd-0.20.9/src/archive/ArchivePlugin.hxx --- mpd-0.19.21/src/archive/ArchivePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchivePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ class ArchiveFile; class Path; -class Error; struct ArchivePlugin { const char *name; @@ -32,20 +31,21 @@ * have/need one this must false if there is an error and * true otherwise */ - bool (*init)(void); + bool (*init)(); /** * optional, set this to nullptr if the archive plugin doesn't * have/need one */ - void (*finish)(void); + void (*finish)(); /** * tryes to open archive file and associates handle with archive * returns pointer to handle used is all operations with this archive - * or nullptr when opening fails + * + * Throws std::runtime_error on error. */ - ArchiveFile *(*open)(Path path_fs, Error &error); + ArchiveFile *(*open)(Path path_fs); /** * suffixes handled by this plugin. @@ -55,7 +55,6 @@ }; ArchiveFile * -archive_file_open(const ArchivePlugin *plugin, Path path, - Error &error); +archive_file_open(const ArchivePlugin *plugin, Path path); #endif diff -Nru mpd-0.19.21/src/archive/ArchiveVisitor.hxx mpd-0.20.9/src/archive/ArchiveVisitor.hxx --- mpd-0.19.21/src/archive/ArchiveVisitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/ArchiveVisitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/plugins/Bzip2ArchivePlugin.cxx mpd-0.20.9/src/archive/plugins/Bzip2ArchivePlugin.cxx --- mpd-0.19.21/src/archive/plugins/Bzip2ArchivePlugin.cxx 2016-07-29 12:51:34.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/Bzip2ArchivePlugin.cxx 2017-05-08 14:50:25.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,44 +27,34 @@ #include "../ArchiveFile.hxx" #include "../ArchiveVisitor.hxx" #include "input/InputStream.hxx" -#include "input/InputPlugin.hxx" #include "input/LocalOpen.hxx" +#include "thread/Cond.hxx" #include "util/RefCount.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" -#include "fs/Traits.hxx" #include "fs/Path.hxx" #include -#include +#include -#ifdef HAVE_OLDER_BZIP2 -#define BZ2_bzDecompressInit bzDecompressInit -#define BZ2_bzDecompress bzDecompress -#endif +#include class Bzip2ArchiveFile final : public ArchiveFile { public: RefCount ref; std::string name; - InputStream *const istream; + const InputStreamPtr istream; - Bzip2ArchiveFile(Path path, InputStream *_is) + Bzip2ArchiveFile(Path path, InputStreamPtr &&_is) :ArchiveFile(bz2_archive_plugin), name(path.GetBase().c_str()), - istream(_is) { + istream(std::move(_is)) { // remove .bz2 suffix const size_t len = name.length(); if (len > 4) name.erase(len - 4); } - ~Bzip2ArchiveFile() { - delete istream; - } - void Ref() { ref.Increment(); } @@ -84,37 +74,37 @@ visitor.VisitArchiveEntry(name.c_str()); } - virtual InputStream *OpenStream(const char *path, - Mutex &mutex, Cond &cond, - Error &error) override; + InputStream *OpenStream(const char *path, + Mutex &mutex, Cond &cond) override; }; -struct Bzip2InputStream final : public InputStream { +class Bzip2InputStream final : public InputStream { Bzip2ArchiveFile *archive; - bool eof; + bool eof = false; bz_stream bzstream; char buffer[5000]; +public: Bzip2InputStream(Bzip2ArchiveFile &context, const char *uri, Mutex &mutex, Cond &cond); ~Bzip2InputStream(); - bool Open(Error &error); - /* virtual methods from InputStream */ - bool IsEOF() override; - size_t Read(void *ptr, size_t size, Error &error) override; -}; + bool IsEOF() noexcept override; + size_t Read(void *ptr, size_t size) override; -static constexpr Domain bz2_domain("bz2"); +private: + void Open(); + bool FillBuffer(); +}; /* single archive handling allocation helpers */ -inline bool -Bzip2InputStream::Open(Error &error) +inline void +Bzip2InputStream::Open() { bzstream.bzalloc = nullptr; bzstream.bzfree = nullptr; @@ -124,28 +114,21 @@ bzstream.avail_in = 0; int ret = BZ2_bzDecompressInit(&bzstream, 0, 0); - if (ret != BZ_OK) { - error.Set(bz2_domain, ret, - "BZ2_bzDecompressInit() has failed"); - return false; - } + if (ret != BZ_OK) + throw std::runtime_error("BZ2_bzDecompressInit() has failed"); SetReady(); - return true; } /* archive open && listing routine */ static ArchiveFile * -bz2_open(Path pathname, Error &error) +bz2_open(Path pathname) { static Mutex mutex; static Cond cond; - InputStream *is = OpenLocalInputStream(pathname, mutex, cond, error); - if (is == nullptr) - return nullptr; - - return new Bzip2ArchiveFile(pathname, is); + auto is = OpenLocalInputStream(pathname, mutex, cond); + return new Bzip2ArchiveFile(pathname, std::move(is)); } /* single archive handling */ @@ -154,8 +137,9 @@ const char *_uri, Mutex &_mutex, Cond &_cond) :InputStream(_uri, _mutex, _cond), - archive(&_context), eof(false) + archive(&_context) { + Open(); archive->Ref(); } @@ -167,41 +151,28 @@ InputStream * Bzip2ArchiveFile::OpenStream(const char *path, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { - Bzip2InputStream *bis = new Bzip2InputStream(*this, path, mutex, cond); - if (!bis->Open(error)) { - delete bis; - return nullptr; - } - - return bis; + return new Bzip2InputStream(*this, path, mutex, cond); } -static bool -bz2_fillbuffer(Bzip2InputStream *bis, Error &error) +inline bool +Bzip2InputStream::FillBuffer() { - size_t count; - bz_stream *bzstream; - - bzstream = &bis->bzstream; - - if (bzstream->avail_in > 0) + if (bzstream.avail_in > 0) return true; - count = bis->archive->istream->Read(bis->buffer, sizeof(bis->buffer), - error); + size_t count = archive->istream->Read(buffer, sizeof(buffer)); if (count == 0) return false; - bzstream->next_in = bis->buffer; - bzstream->avail_in = count; + bzstream.next_in = buffer; + bzstream.avail_in = count; return true; } size_t -Bzip2InputStream::Read(void *ptr, size_t length, Error &error) +Bzip2InputStream::Read(void *ptr, size_t length) { int bz_result; size_t nbytes = 0; @@ -213,7 +184,7 @@ bzstream.avail_out = length; do { - if (!bz2_fillbuffer(this, error)) + if (!FillBuffer()) return 0; bz_result = BZ2_bzDecompress(&bzstream); @@ -223,11 +194,8 @@ break; } - if (bz_result != BZ_OK) { - error.Set(bz2_domain, bz_result, - "BZ2_bzDecompress() has failed"); - return 0; - } + if (bz_result != BZ_OK) + throw std::runtime_error("BZ2_bzDecompress() has failed"); } while (bzstream.avail_out == length); nbytes = length - bzstream.avail_out; @@ -237,7 +205,7 @@ } bool -Bzip2InputStream::IsEOF() +Bzip2InputStream::IsEOF() noexcept { return eof; } diff -Nru mpd-0.19.21/src/archive/plugins/Bzip2ArchivePlugin.hxx mpd-0.20.9/src/archive/plugins/Bzip2ArchivePlugin.hxx --- mpd-0.19.21/src/archive/plugins/Bzip2ArchivePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/Bzip2ArchivePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/plugins/Iso9660ArchivePlugin.cxx mpd-0.20.9/src/archive/plugins/Iso9660ArchivePlugin.cxx --- mpd-0.19.21/src/archive/plugins/Iso9660ArchivePlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/Iso9660ArchivePlugin.cxx 2017-05-08 14:50:43.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,11 +27,9 @@ #include "../ArchiveFile.hxx" #include "../ArchiveVisitor.hxx" #include "input/InputStream.hxx" -#include "input/InputPlugin.hxx" #include "fs/Path.hxx" #include "util/RefCount.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include @@ -78,13 +76,10 @@ virtual void Visit(ArchiveVisitor &visitor) override; - virtual InputStream *OpenStream(const char *path, - Mutex &mutex, Cond &cond, - Error &error) override; + InputStream *OpenStream(const char *path, + Mutex &mutex, Cond &cond) override; }; -static constexpr Domain iso9660_domain("iso9660"); - /* archive open && listing routine */ inline void @@ -124,16 +119,13 @@ } static ArchiveFile * -iso9660_archive_open(Path pathname, Error &error) +iso9660_archive_open(Path pathname) { /* open archive */ auto iso = iso9660_open(pathname.c_str()); - if (iso == nullptr) { - error.Format(iso9660_domain, - "Failed to open ISO9660 file %s", - pathname.c_str()); - return nullptr; - } + if (iso == nullptr) + throw FormatRuntimeError("Failed to open ISO9660 file %s", + pathname.c_str()); return new Iso9660ArchiveFile(iso); } @@ -170,28 +162,25 @@ } /* virtual methods from InputStream */ - bool IsEOF() override; - size_t Read(void *ptr, size_t size, Error &error) override; + bool IsEOF() noexcept override; + size_t Read(void *ptr, size_t size) override; }; InputStream * Iso9660ArchiveFile::OpenStream(const char *pathname, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { auto statbuf = iso9660_ifs_stat_translate(iso, pathname); - if (statbuf == nullptr) { - error.Format(iso9660_domain, - "not found in the ISO file: %s", pathname); - return nullptr; - } + if (statbuf == nullptr) + throw FormatRuntimeError("not found in the ISO file: %s", + pathname); return new Iso9660InputStream(*this, pathname, mutex, cond, statbuf); } size_t -Iso9660InputStream::Read(void *ptr, size_t read_size, Error &error) +Iso9660InputStream::Read(void *ptr, size_t read_size) { int readed = 0; int no_blocks, cur_block; @@ -211,12 +200,10 @@ readed = archive.SeekRead(ptr, statbuf->lsn + cur_block, no_blocks); - if (readed != no_blocks * ISO_BLOCKSIZE) { - error.Format(iso9660_domain, - "error reading ISO file at lsn %lu", - (unsigned long)cur_block); - return 0; - } + if (readed != no_blocks * ISO_BLOCKSIZE) + throw FormatRuntimeError("error reading ISO file at lsn %lu", + (unsigned long)cur_block); + if (left_bytes < read_size) { readed = left_bytes; } @@ -226,7 +213,7 @@ } bool -Iso9660InputStream::IsEOF() +Iso9660InputStream::IsEOF() noexcept { return offset == size; } diff -Nru mpd-0.19.21/src/archive/plugins/Iso9660ArchivePlugin.hxx mpd-0.20.9/src/archive/plugins/Iso9660ArchivePlugin.hxx --- mpd-0.19.21/src/archive/plugins/Iso9660ArchivePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/Iso9660ArchivePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/archive/plugins/ZzipArchivePlugin.cxx mpd-0.20.9/src/archive/plugins/ZzipArchivePlugin.cxx --- mpd-0.19.21/src/archive/plugins/ZzipArchivePlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/ZzipArchivePlugin.cxx 2017-05-08 14:50:32.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,11 +27,9 @@ #include "../ArchiveFile.hxx" #include "../ArchiveVisitor.hxx" #include "input/InputStream.hxx" -#include "input/InputPlugin.hxx" #include "fs/Path.hxx" #include "util/RefCount.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include @@ -59,24 +57,19 @@ virtual void Visit(ArchiveVisitor &visitor) override; - virtual InputStream *OpenStream(const char *path, - Mutex &mutex, Cond &cond, - Error &error) override; + InputStream *OpenStream(const char *path, + Mutex &mutex, Cond &cond) override; }; -static constexpr Domain zzip_domain("zzip"); - /* archive open && listing routine */ static ArchiveFile * -zzip_archive_open(Path pathname, Error &error) +zzip_archive_open(Path pathname) { ZZIP_DIR *dir = zzip_dir_open(pathname.c_str(), nullptr); - if (dir == nullptr) { - error.Format(zzip_domain, "Failed to open ZIP file %s", - pathname.c_str()); - return nullptr; - } + if (dir == nullptr) + throw FormatRuntimeError("Failed to open ZIP file %s", + pathname.c_str()); return new ZzipArchiveFile(dir); } @@ -123,22 +116,19 @@ } /* virtual methods from InputStream */ - bool IsEOF() override; - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + bool IsEOF() noexcept override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; }; InputStream * ZzipArchiveFile::OpenStream(const char *pathname, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { ZZIP_FILE *_file = zzip_file_open(dir, pathname, 0); - if (_file == nullptr) { - error.Format(zzip_domain, "not found in the ZIP file: %s", - pathname); - return nullptr; - } + if (_file == nullptr) + throw FormatRuntimeError("not found in the ZIP file: %s", + pathname); return new ZzipInputStream(*this, pathname, mutex, cond, @@ -146,35 +136,30 @@ } size_t -ZzipInputStream::Read(void *ptr, size_t read_size, Error &error) +ZzipInputStream::Read(void *ptr, size_t read_size) { int ret = zzip_file_read(file, ptr, read_size); - if (ret < 0) { - error.Set(zzip_domain, "zzip_file_read() has failed"); - return 0; - } + if (ret < 0) + throw std::runtime_error("zzip_file_read() has failed"); offset = zzip_tell(file); return ret; } bool -ZzipInputStream::IsEOF() +ZzipInputStream::IsEOF() noexcept { return offset_type(zzip_tell(file)) == size; } -bool -ZzipInputStream::Seek(offset_type new_offset, Error &error) +void +ZzipInputStream::Seek(offset_type new_offset) { zzip_off_t ofs = zzip_seek(file, new_offset, SEEK_SET); - if (ofs < 0) { - error.Set(zzip_domain, "zzip_seek() has failed"); - return false; - } + if (ofs < 0) + throw std::runtime_error("zzip_seek() has failed"); offset = ofs; - return true; } /* exported structures */ diff -Nru mpd-0.19.21/src/archive/plugins/ZzipArchivePlugin.hxx mpd-0.20.9/src/archive/plugins/ZzipArchivePlugin.hxx --- mpd-0.19.21/src/archive/plugins/ZzipArchivePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/archive/plugins/ZzipArchivePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/AudioConfig.cxx mpd-0.20.9/src/AudioConfig.cxx --- mpd-0.19.21/src/AudioConfig.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioConfig.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "AudioConfig.hxx" -#include "AudioFormat.hxx" -#include "AudioParser.hxx" -#include "config/ConfigData.hxx" -#include "config/ConfigGlobal.hxx" -#include "config/ConfigOption.hxx" -#include "util/Error.hxx" -#include "system/FatalError.hxx" - -static AudioFormat configured_audio_format; - -AudioFormat -getOutputAudioFormat(AudioFormat inAudioFormat) -{ - AudioFormat out_audio_format = inAudioFormat; - out_audio_format.ApplyMask(configured_audio_format); - return out_audio_format; -} - -void initAudioConfig(void) -{ - const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT); - - if (param == nullptr) - return; - - Error error; - if (!audio_format_parse(configured_audio_format, param->value.c_str(), - true, error)) - FormatFatalError("error parsing line %i: %s", - param->line, error.GetMessage()); -} diff -Nru mpd-0.19.21/src/AudioConfig.hxx mpd-0.20.9/src/AudioConfig.hxx --- mpd-0.19.21/src/AudioConfig.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioConfig.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_AUDIO_CONFIG_HXX -#define MPD_AUDIO_CONFIG_HXX - -struct AudioFormat; - -AudioFormat -getOutputAudioFormat(AudioFormat inFormat); - -/* make sure initPlayerData is called before this function!! */ -void initAudioConfig(void); - -#endif diff -Nru mpd-0.19.21/src/AudioFormat.cxx mpd-0.20.9/src/AudioFormat.cxx --- mpd-0.19.21/src/AudioFormat.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioFormat.cxx 2017-05-08 12:48:45.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,12 +18,13 @@ */ #include "AudioFormat.hxx" +#include "util/StringBuffer.hxx" #include #include void -AudioFormat::ApplyMask(AudioFormat mask) +AudioFormat::ApplyMask(AudioFormat mask) noexcept { assert(IsValid()); assert(mask.IsMaskValid()); @@ -40,46 +41,24 @@ assert(IsValid()); } -const char * -sample_format_to_string(SampleFormat format) +StringBuffer<24> +ToString(const AudioFormat af) noexcept { - switch (format) { - case SampleFormat::UNDEFINED: - return "?"; + StringBuffer<24> buffer; - case SampleFormat::S8: - return "8"; - - case SampleFormat::S16: - return "16"; - - case SampleFormat::S24_P32: - return "24"; - - case SampleFormat::S32: - return "32"; - - case SampleFormat::FLOAT: - return "f"; - - case SampleFormat::DSD: - return "dsd"; + if (af.format == SampleFormat::DSD && af.sample_rate > 0 && + af.sample_rate % 44100 == 0) { + /* use shortcuts such as "dsd64" which implies the + sample rate */ + snprintf(buffer.data(), buffer.capacity(), "dsd%u:%u", + af.sample_rate * 8 / 44100, + af.channels); + return buffer; } - /* unreachable */ - assert(false); - gcc_unreachable(); -} - -const char * -audio_format_to_string(const AudioFormat af, - struct audio_format_string *s) -{ - assert(s != nullptr); - - snprintf(s->buffer, sizeof(s->buffer), "%u:%s:%u", + snprintf(buffer.data(), buffer.capacity(), "%u:%s:%u", af.sample_rate, sample_format_to_string(af.format), af.channels); - return s->buffer; + return buffer; } diff -Nru mpd-0.19.21/src/AudioFormat.hxx mpd-0.20.9/src/AudioFormat.hxx --- mpd-0.19.21/src/AudioFormat.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioFormat.hxx 2017-06-03 19:34:15.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,47 +20,14 @@ #ifndef MPD_AUDIO_FORMAT_HXX #define MPD_AUDIO_FORMAT_HXX +#include "pcm/SampleFormat.hxx" #include "Compiler.h" -#include #include +#include +#include -#if defined(WIN32) && GCC_CHECK_VERSION(4,6) -/* on WIN32, "FLOAT" is already defined, and this triggers -Wshadow */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#endif - -enum class SampleFormat : uint8_t { - UNDEFINED = 0, - - S8, - S16, - - /** - * Signed 24 bit integer samples, packed in 32 bit integers - * (the most significant byte is filled with the sign bit). - */ - S24_P32, - - S32, - - /** - * 32 bit floating point samples in the host's format. The - * range is -1.0f to +1.0f. - */ - FLOAT, - - /** - * Direct Stream Digital. 1-bit samples; each frame has one - * byte (8 samples) per channel. - */ - DSD, -}; - -#if defined(WIN32) && GCC_CHECK_VERSION(4,6) -#pragma GCC diagnostic pop -#endif +template class StringBuffer; static constexpr unsigned MAX_CHANNELS = 8; @@ -82,8 +49,19 @@ SampleFormat format; /** - * The number of channels. Only mono (1) and stereo (2) are - * fully supported currently. + * The number of channels. + * + * Channel order follows the FLAC convention + * (https://xiph.org/flac/format.html): + * + * - 1 channel: mono + * - 2 channels: left, right + * - 3 channels: left, right, center + * - 4 channels: front left, front right, back left, back right + * - 5 channels: front left, front right, front center, back/surround left, back/surround right + * - 6 channels: front left, front right, front center, LFE, back/surround left, back/surround right + * - 7 channels: front left, front right, front center, LFE, back center, side left, side right + * - 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right */ uint8_t channels; @@ -99,8 +77,8 @@ } /** - * Clears the #audio_format object, i.e. sets all attributes to an - * undefined (invalid) value. + * Clears the object, i.e. sets all attributes to an undefined + * (invalid) value. */ void Clear() { sample_rate = 0; @@ -146,7 +124,14 @@ return !(*this == other); } - void ApplyMask(AudioFormat mask); + void ApplyMask(AudioFormat mask) noexcept; + + gcc_pure + AudioFormat WithMask(AudioFormat mask) const noexcept { + AudioFormat result = *this; + result.ApplyMask(mask); + return result; + } /** * Returns the size of each (mono) sample in bytes. @@ -166,13 +151,6 @@ }; /** - * Buffer for audio_format_string(). - */ -struct audio_format_string { - char buffer[24]; -}; - -/** * Checks whether the sample rate is valid. * * @param sample_rate the sample rate in Hz @@ -184,30 +162,6 @@ } /** - * Checks whether the sample format is valid. - * - * @param bits the number of significant bits per sample - */ -static inline bool -audio_valid_sample_format(SampleFormat format) -{ - switch (format) { - case SampleFormat::S8: - case SampleFormat::S16: - case SampleFormat::S24_P32: - case SampleFormat::S32: - case SampleFormat::FLOAT: - case SampleFormat::DSD: - return true; - - case SampleFormat::UNDEFINED: - break; - } - - return false; -} - -/** * Checks whether the number of channels is valid. */ static constexpr inline bool @@ -242,34 +196,6 @@ (channels == 0 || audio_valid_channel_count(channels)); } -gcc_const -static inline unsigned -sample_format_size(SampleFormat format) -{ - switch (format) { - case SampleFormat::S8: - return 1; - - case SampleFormat::S16: - return 2; - - case SampleFormat::S24_P32: - case SampleFormat::S32: - case SampleFormat::FLOAT: - return 4; - - case SampleFormat::DSD: - /* each frame has 8 samples per channel */ - return 1; - - case SampleFormat::UNDEFINED: - return 0; - } - - assert(false); - gcc_unreachable(); -} - inline unsigned AudioFormat::GetSampleSize() const { @@ -289,27 +215,14 @@ } /** - * Renders a #sample_format enum into a string, e.g. for printing it - * in a log file. - * - * @param format a #sample_format enum value - * @return the string - */ -gcc_pure gcc_malloc -const char * -sample_format_to_string(SampleFormat format); - -/** - * Renders the #audio_format object into a string, e.g. for printing + * Renders the #AudioFormat object into a string, e.g. for printing * it in a log file. * - * @param af the #audio_format object - * @param s a buffer to print into - * @return the string, or nullptr if the #audio_format object is invalid + * @param af the #AudioFormat object + * @return the string buffer */ -gcc_pure gcc_malloc -const char * -audio_format_to_string(AudioFormat af, - struct audio_format_string *s); +gcc_const +StringBuffer<24> +ToString(AudioFormat af) noexcept; #endif diff -Nru mpd-0.19.21/src/AudioParser.cxx mpd-0.20.9/src/AudioParser.cxx --- mpd-0.19.21/src/AudioParser.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioParser.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,73 +25,59 @@ #include "config.h" #include "AudioParser.hxx" #include "AudioFormat.hxx" -#include "CheckAudioFormat.hxx" -#include "util/Error.hxx" -#include "Compiler.h" +#include "util/RuntimeError.hxx" #include #include #include -static bool -parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, - const char **endptr_r, Error &error) +static uint32_t +ParseSampleRate(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; if (mask && *src == '*') { - *sample_rate_r = 0; *endptr_r = src + 1; - return true; + return 0; } value = strtoul(src, &endptr, 10); if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the sample rate"); - return false; - } else if (!audio_check_sample_rate(value, error)) - return false; + throw std::runtime_error("Failed to parse the sample rate"); + } else if (!audio_valid_sample_rate(value)) + throw FormatRuntimeError("Invalid sample rate: %lu", + value); - *sample_rate_r = value; *endptr_r = endptr; - return true; + return value; } -static bool -parse_sample_format(const char *src, bool mask, - SampleFormat *sample_format_r, - const char **endptr_r, Error &error) +static SampleFormat +ParseSampleFormat(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; SampleFormat sample_format; if (mask && *src == '*') { - *sample_format_r = SampleFormat::UNDEFINED; *endptr_r = src + 1; - return true; + return SampleFormat::UNDEFINED; } if (*src == 'f') { - *sample_format_r = SampleFormat::FLOAT; *endptr_r = src + 1; - return true; + return SampleFormat::FLOAT; } if (memcmp(src, "dsd", 3) == 0) { - *sample_format_r = SampleFormat::DSD; *endptr_r = src + 3; - return true; + return SampleFormat::DSD; } value = strtoul(src, &endptr, 10); - if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the sample format"); - return false; - } + if (endptr == src) + throw std::runtime_error("Failed to parse the sample format"); switch (value) { case 8: @@ -115,99 +101,85 @@ break; default: - error.Format(audio_format_domain, - "Invalid sample format: %lu", value); - return false; + throw FormatRuntimeError("Invalid sample format: %lu", value); } assert(audio_valid_sample_format(sample_format)); - *sample_format_r = sample_format; *endptr_r = endptr; - return true; + return sample_format; } -static bool -parse_channel_count(const char *src, bool mask, uint8_t *channels_r, - const char **endptr_r, Error &error) +static uint8_t +ParseChannelCount(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; if (mask && *src == '*') { - *channels_r = 0; *endptr_r = src + 1; - return true; + return 0; } value = strtoul(src, &endptr, 10); - if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the channel count"); - return false; - } else if (!audio_check_channel_count(value, error)) - return false; + if (endptr == src) + throw std::runtime_error("Failed to parse the channel count"); + else if (!audio_valid_channel_count(value)) + throw FormatRuntimeError("Invalid channel count: %u", value); - *channels_r = value; *endptr_r = endptr; - return true; + return value; } -bool -audio_format_parse(AudioFormat &dest, const char *src, - bool mask, Error &error) +AudioFormat +ParseAudioFormat(const char *src, bool mask) { - uint32_t rate; - SampleFormat sample_format; - uint8_t channels; - + AudioFormat dest; dest.Clear(); - /* parse sample rate */ + if (strncmp(src, "dsd", 3) == 0) { + /* allow format specifications such as "dsd64" which + implies the sample rate */ + + char *endptr; + auto dsd = strtoul(src + 3, &endptr, 10); + if (endptr > src + 3 && *endptr == ':' && + dsd >= 32 && dsd <= 4096 && dsd % 2 == 0) { + dest.sample_rate = dsd * 44100 / 8; + dest.format = SampleFormat::DSD; + + src = endptr + 1; + dest.channels = ParseChannelCount(src, mask, &src); + if (*src != 0) + throw FormatRuntimeError("Extra data after channel count: %s", src); -#if GCC_CHECK_VERSION(4,7) - /* workaround -Wmaybe-uninitialized false positive */ - rate = 0; -#endif - - if (!parse_sample_rate(src, mask, &rate, &src, error)) - return false; - - if (*src++ != ':') { - error.Set(audio_format_domain, "Sample format missing"); - return false; + return dest; + } } + /* parse sample rate */ + + dest.sample_rate = ParseSampleRate(src, mask, &src); + + if (*src++ != ':') + throw std::runtime_error("Sample format missing"); + /* parse sample format */ -#if GCC_CHECK_VERSION(4,7) - /* workaround -Wmaybe-uninitialized false positive */ - sample_format = SampleFormat::UNDEFINED; -#endif - - if (!parse_sample_format(src, mask, &sample_format, &src, error)) - return false; - - if (*src++ != ':') { - error.Set(audio_format_domain, "Channel count missing"); - return false; - } + dest.format = ParseSampleFormat(src, mask, &src); + + if (*src++ != ':') + throw std::runtime_error("Channel count missing"); /* parse channel count */ - if (!parse_channel_count(src, mask, &channels, &src, error)) - return false; + dest.channels = ParseChannelCount(src, mask, &src); - if (*src != 0) { - error.Format(audio_format_domain, - "Extra data after channel count: %s", src); - return false; - } + if (*src != 0) + throw FormatRuntimeError("Extra data after channel count: %s", src); - dest = AudioFormat(rate, sample_format, channels); assert(mask ? dest.IsMaskValid() : dest.IsValid()); - - return true; + return dest; } diff -Nru mpd-0.19.21/src/AudioParser.hxx mpd-0.20.9/src/AudioParser.hxx --- mpd-0.19.21/src/AudioParser.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/AudioParser.hxx 2017-05-08 13:04:11.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,21 +26,17 @@ #define MPD_AUDIO_PARSER_HXX struct AudioFormat; -class Error; /** * Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an - * #audio_format. + * #AudioFormat. + * + * Throws #std::runtime_error on error. * - * @param dest the destination #audio_format struct * @param src the input string * @param mask if true, then "*" is allowed for any number of items - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return true on success */ -bool -audio_format_parse(AudioFormat &dest, const char *src, - bool mask, Error &error); +AudioFormat +ParseAudioFormat(const char *src, bool mask); #endif diff -Nru mpd-0.19.21/src/BulkEdit.hxx mpd-0.20.9/src/BulkEdit.hxx --- mpd-0.19.21/src/BulkEdit.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/BulkEdit.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/CheckAudioFormat.cxx mpd-0.20.9/src/CheckAudioFormat.cxx --- mpd-0.19.21/src/CheckAudioFormat.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CheckAudioFormat.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,61 +20,43 @@ #include "config.h" #include "CheckAudioFormat.hxx" #include "AudioFormat.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" -#include +#include -const Domain audio_format_domain("audio_format"); +#include -bool -audio_check_sample_rate(unsigned long sample_rate, Error &error) +void +CheckSampleRate(unsigned long sample_rate) { - if (!audio_valid_sample_rate(sample_rate)) { - error.Format(audio_format_domain, - "Invalid sample rate: %lu", sample_rate); - return false; - } - - return true; + if (!audio_valid_sample_rate(sample_rate)) + throw FormatRuntimeError("Invalid sample rate: %lu", + sample_rate); } -bool -audio_check_sample_format(SampleFormat sample_format, Error &error) +void +CheckSampleFormat(SampleFormat sample_format) { - if (!audio_valid_sample_format(sample_format)) { - error.Format(audio_format_domain, - "Invalid sample format: %u", - unsigned(sample_format)); - return false; - } - - return true; + if (!audio_valid_sample_format(sample_format)) + throw FormatRuntimeError("Invalid sample format: %u", + unsigned(sample_format)); } -bool -audio_check_channel_count(unsigned channels, Error &error) +void +CheckChannelCount(unsigned channels) { - if (!audio_valid_channel_count(channels)) { - error.Format(audio_format_domain, - "Invalid channel count: %u", channels); - return false; - } - - return true; + if (!audio_valid_channel_count(channels)) + throw FormatRuntimeError("Invalid channel count: %u", + channels); } -bool -audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, - SampleFormat sample_format, unsigned channels, - Error &error) +AudioFormat +CheckAudioFormat(unsigned long sample_rate, + SampleFormat sample_format, unsigned channels) { - if (audio_check_sample_rate(sample_rate, error) && - audio_check_sample_format(sample_format, error) && - audio_check_channel_count(channels, error)) { - af = AudioFormat(sample_rate, sample_format, channels); - assert(af.IsValid()); - return true; - } else - return false; + CheckSampleRate(sample_rate); + CheckSampleFormat(sample_format); + CheckChannelCount(channels); + + return AudioFormat(sample_rate, sample_format, channels); } diff -Nru mpd-0.19.21/src/CheckAudioFormat.hxx mpd-0.20.9/src/CheckAudioFormat.hxx --- mpd-0.19.21/src/CheckAudioFormat.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CheckAudioFormat.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,25 +22,23 @@ #include "AudioFormat.hxx" -class Error; +void +CheckSampleRate(unsigned long sample_rate); -extern const class Domain audio_format_domain; +void +CheckSampleFormat(SampleFormat sample_format); -bool -audio_check_sample_rate(unsigned long sample_rate, Error &error); - -bool -audio_check_sample_format(SampleFormat sample_format, Error &error); - -bool -audio_check_channel_count(unsigned sample_format, Error &error); +void +CheckChannelCount(unsigned sample_format); /** - * Wrapper for audio_format_init(), which checks all attributes. + * Check #AudioFormat attributes and construct an #AudioFormat + * instance. + * + * Throws #std::runtime_error on error. */ -bool -audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, - SampleFormat sample_format, unsigned channels, - Error &error); +AudioFormat +CheckAudioFormat(unsigned long sample_rate, + SampleFormat sample_format, unsigned channels); #endif diff -Nru mpd-0.19.21/src/check.h mpd-0.20.9/src/check.h --- mpd-0.19.21/src/check.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/check.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/Chrono.hxx mpd-0.20.9/src/Chrono.hxx --- mpd-0.19.21/src/Chrono.hxx 2016-08-23 07:51:41.000000000 +0000 +++ mpd-0.20.9/src/Chrono.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,19 +20,10 @@ #ifndef MPD_CHRONO_HXX #define MPD_CHRONO_HXX -#include "Compiler.h" - #include #include #include -#if GCC_OLDER_THAN(4,7) -/* std::chrono::duration operators are "constexpr" since gcc 4.7 */ -#define chrono_constexpr gcc_pure -#else -#define chrono_constexpr constexpr -#endif - /** * A time stamp within a song. Granularity is 1 millisecond and the * maximum value is about 49 days. @@ -108,11 +99,11 @@ return count() > 0; } - chrono_constexpr SongTime operator+(const SongTime &other) const { + constexpr SongTime operator+(const SongTime &other) const { return SongTime(*(const Base *)this + (const Base &)other); } - chrono_constexpr SongTime operator-(const SongTime &other) const { + constexpr SongTime operator-(const SongTime &other) const { return SongTime(*(const Base *)this - (const Base &)other); } }; @@ -212,15 +203,13 @@ return count() < 0; } - chrono_constexpr SignedSongTime operator+(const SignedSongTime &other) const { + constexpr SignedSongTime operator+(const SignedSongTime &other) const { return SignedSongTime(*(const Base *)this + (const Base &)other); } - chrono_constexpr SignedSongTime operator-(const SignedSongTime &other) const { + constexpr SignedSongTime operator-(const SignedSongTime &other) const { return SignedSongTime(*(const Base *)this - (const Base &)other); } }; -#undef chrono_constexpr - #endif diff -Nru mpd-0.19.21/src/client/Client.cxx mpd-0.20.9/src/client/Client.cxx --- mpd-0.19.21/src/client/Client.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/Client.cxx 2017-05-08 13:19:36.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,13 +28,19 @@ #ifdef ENABLE_DATABASE const Database * -Client::GetDatabase(Error &error) const +Client::GetDatabase() const noexcept { - return partition.instance.GetDatabase(error); + return partition.instance.GetDatabase(); +} + +const Database & +Client::GetDatabaseOrThrow() const +{ + return partition.instance.GetDatabaseOrThrow(); } const Storage * -Client::GetStorage() const +Client::GetStorage() const noexcept { return partition.instance.storage; } diff -Nru mpd-0.19.21/src/client/ClientEvent.cxx mpd-0.20.9/src/client/ClientEvent.cxx --- mpd-0.19.21/src/client/ClientEvent.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientEvent.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,14 +18,13 @@ */ #include "config.h" -#include "ClientInternal.hxx" -#include "util/Error.hxx" +#include "Client.hxx" #include "Log.hxx" void -Client::OnSocketError(Error &&error) +Client::OnSocketError(std::exception_ptr ep) { - FormatError(error, "error on client %d", num); + FormatError(ep, "error on client %d", num); SetExpired(); } diff -Nru mpd-0.19.21/src/client/ClientExpire.cxx mpd-0.20.9/src/client/ClientExpire.cxx --- mpd-0.19.21/src/client/ClientExpire.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientExpire.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ return; FullyBufferedSocket::Close(); - TimeoutMonitor::Schedule(0); + TimeoutMonitor::Schedule(std::chrono::steady_clock::duration::zero()); } void diff -Nru mpd-0.19.21/src/client/ClientFile.cxx mpd-0.20.9/src/client/ClientFile.cxx --- mpd-0.19.21/src/client/ClientFile.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientFile.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,44 +21,31 @@ #include "Client.hxx" #include "protocol/Ack.hxx" #include "fs/Path.hxx" -#include "fs/FileSystem.hxx" -#include "util/Error.hxx" +#include "fs/FileInfo.hxx" -#include #include -bool -Client::AllowFile(Path path_fs, Error &error) const +void +Client::AllowFile(Path path_fs) const { #ifdef WIN32 (void)path_fs; - error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); - return false; + throw ProtocolError(ACK_ERROR_PERMISSION, "Access denied"); #else if (uid >= 0 && (uid_t)uid == geteuid()) /* always allow access if user runs his own MPD instance */ - return true; + return; - if (uid < 0) { + if (uid < 0) /* unauthenticated client */ - error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); - return false; - } - - struct stat st; - if (!StatFile(path_fs, st)) { - error.SetErrno(); - return false; - } + throw ProtocolError(ACK_ERROR_PERMISSION, "Access denied"); - if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) { - /* client is not owner */ - error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); - return false; - } + const FileInfo fi(path_fs); - return true; + if (fi.GetUid() != (uid_t)uid && (fi.GetMode() & 0444) != 0444) + /* client is not owner */ + throw ProtocolError(ACK_ERROR_PERMISSION, "Access denied"); #endif } diff -Nru mpd-0.19.21/src/client/ClientGlobal.cxx mpd-0.20.9/src/client/ClientGlobal.cxx --- mpd-0.19.21/src/client/ClientGlobal.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientGlobal.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,21 +25,23 @@ #define CLIENT_MAX_COMMAND_LIST_DEFAULT (2048*1024) #define CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024) -int client_timeout; +std::chrono::steady_clock::duration client_timeout; size_t client_max_command_list_size; size_t client_max_output_buffer_size; void client_manager_init(void) { - client_timeout = config_get_positive(CONF_CONN_TIMEOUT, - CLIENT_TIMEOUT_DEFAULT); + unsigned client_timeout_s = config_get_positive(ConfigOption::CONN_TIMEOUT, + CLIENT_TIMEOUT_DEFAULT); + client_timeout = std::chrono::seconds(client_timeout_s); + client_max_command_list_size = - config_get_positive(CONF_MAX_COMMAND_LIST_SIZE, + config_get_positive(ConfigOption::MAX_COMMAND_LIST_SIZE, CLIENT_MAX_COMMAND_LIST_DEFAULT / 1024) * 1024; client_max_output_buffer_size = - config_get_positive(CONF_MAX_OUTPUT_BUFFER_SIZE, + config_get_positive(ConfigOption::MAX_OUTPUT_BUFFER_SIZE, CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT / 1024) * 1024; } diff -Nru mpd-0.19.21/src/client/Client.hxx mpd-0.20.9/src/client/Client.hxx --- mpd-0.19.21/src/client/Client.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/Client.hxx 2017-06-03 19:50:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,8 @@ #include "event/TimeoutMonitor.hxx" #include "Compiler.h" -#include +#include +#include #include #include @@ -36,7 +37,7 @@ #include #include -struct sockaddr; +class SocketAddress; class EventLoop; class Path; struct Partition; @@ -51,12 +52,6 @@ struct playlist &playlist; struct PlayerControl &player_control; - struct Disposer { - void operator()(Client *client) const { - delete client; - } - }; - unsigned permission; /** the uid of the client process, or -1 if unknown */ @@ -105,14 +100,19 @@ } gcc_pure - bool IsExpired() const { + bool IsExpired() const noexcept { return !FullyBufferedSocket::IsDefined(); } void Close(); void SetExpired(); - using FullyBufferedSocket::Write; + bool Write(const void *data, size_t length); + + /** + * Write a null-terminated string. + */ + bool Write(const char *data); /** * returns the uid of the client process, or a negative value @@ -160,7 +160,7 @@ }; gcc_pure - bool IsSubscribed(const char *channel_name) const { + bool IsSubscribed(const char *channel_name) const noexcept { return subscriptions.find(channel_name) != subscriptions.end(); } @@ -176,35 +176,42 @@ * We cannot fix this as long as there are plugins that open a file by * its name, and not by file descriptor / callbacks. * + * Throws #std::runtime_error on error. + * * @param path_fs the absolute path name in filesystem encoding - * @return true if access is allowed */ - bool AllowFile(Path path_fs, Error &error) const; + void AllowFile(Path path_fs) const; /** * Wrapper for Instance::GetDatabase(). */ gcc_pure - const Database *GetDatabase(Error &error) const; + const Database *GetDatabase() const noexcept; + + /** + * Wrapper for Instance::GetDatabaseOrThrow(). + */ + const Database &GetDatabaseOrThrow() const; gcc_pure - const Storage *GetStorage() const; + const Storage *GetStorage() const noexcept; private: /* virtual methods from class BufferedSocket */ virtual InputResult OnSocketInput(void *data, size_t length) override; - virtual void OnSocketError(Error &&error) override; + void OnSocketError(std::exception_ptr ep) override; virtual void OnSocketClosed() override; /* virtual methods from class TimeoutMonitor */ virtual void OnTimeout() override; }; -void client_manager_init(void); +void +client_manager_init(); void client_new(EventLoop &loop, Partition &partition, - int fd, const sockaddr *sa, size_t sa_length, int uid); + int fd, SocketAddress address, int uid); /** * Write a C string to the client. diff -Nru mpd-0.19.21/src/client/ClientIdle.cxx mpd-0.20.9/src/client/ClientIdle.cxx --- mpd-0.19.21/src/client/ClientIdle.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientIdle.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -42,7 +42,7 @@ client_puts(*this, "OK\n"); - TimeoutMonitor::ScheduleSeconds(client_timeout); + TimeoutMonitor::Schedule(client_timeout); } void diff -Nru mpd-0.19.21/src/client/ClientInternal.hxx mpd-0.20.9/src/client/ClientInternal.hxx --- mpd-0.19.21/src/client/ClientInternal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientInternal.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,12 +24,14 @@ #include "Client.hxx" #include "command/CommandResult.hxx" +#include + static constexpr unsigned CLIENT_MAX_SUBSCRIPTIONS = 16; static constexpr unsigned CLIENT_MAX_MESSAGES = 64; extern const class Domain client_domain; -extern int client_timeout; +extern std::chrono::steady_clock::duration client_timeout; extern size_t client_max_command_list_size; extern size_t client_max_output_buffer_size; diff -Nru mpd-0.19.21/src/client/ClientList.cxx mpd-0.20.9/src/client/ClientList.cxx --- mpd-0.19.21/src/client/ClientList.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientList.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,7 @@ #include "config.h" #include "ClientList.hxx" #include "ClientInternal.hxx" - -#include +#include "util/DeleteDisposer.hxx" #include @@ -36,7 +35,7 @@ void ClientList::CloseAll() { - list.clear_and_dispose(Client::Disposer()); + list.clear_and_dispose(DeleteDisposer()); } void diff -Nru mpd-0.19.21/src/client/ClientList.hxx mpd-0.20.9/src/client/ClientList.hxx --- mpd-0.19.21/src/client/ClientList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientList.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ #include "Client.hxx" -class Client; +#include class ClientList { typedef boost::intrusive::list @@ -53,20 +53,20 @@ idle_waiting(false), idle_flags(0), num_subscriptions(0) { - TimeoutMonitor::ScheduleSeconds(client_timeout); + TimeoutMonitor::Schedule(client_timeout); } void client_new(EventLoop &loop, Partition &partition, - int fd, const struct sockaddr *sa, size_t sa_length, int uid) + int fd, SocketAddress address, int uid) { static unsigned int next_client_num; - const auto remote = sockaddr_to_string(sa, sa_length); + const auto remote = ToString(address); assert(fd >= 0); #ifdef HAVE_LIBWRAP - if (sa->sa_family != AF_UNIX) { + if (address.GetFamily() != AF_UNIX) { // TODO: shall we obtain the program name from argv[0]? const char *progname = "mpd"; diff -Nru mpd-0.19.21/src/client/ClientProcess.cxx mpd-0.20.9/src/client/ClientProcess.cxx --- mpd-0.19.21/src/client/ClientProcess.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientProcess.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,8 +22,7 @@ #include "protocol/Result.hxx" #include "command/AllCommands.hxx" #include "Log.hxx" - -#include +#include "util/StringAPI.hxx" #define CLIENT_LIST_MODE_BEGIN "command_list_begin" #define CLIENT_LIST_OK_MODE_BEGIN "command_list_ok_begin" @@ -56,7 +55,7 @@ { CommandResult ret; - if (strcmp(line, "noidle") == 0) { + if (StringIsEqual(line, "noidle")) { if (client.idle_waiting) { /* send empty idle response and leave idle mode */ client.idle_waiting = false; @@ -78,7 +77,7 @@ } if (client.cmd_list.IsActive()) { - if (strcmp(line, CLIENT_LIST_MODE_END) == 0) { + if (StringIsEqual(line, CLIENT_LIST_MODE_END)) { FormatDebug(client_domain, "[%u] process command list", client.num); @@ -113,10 +112,10 @@ ret = CommandResult::OK; } } else { - if (strcmp(line, CLIENT_LIST_MODE_BEGIN) == 0) { + if (StringIsEqual(line, CLIENT_LIST_MODE_BEGIN)) { client.cmd_list.Begin(false); ret = CommandResult::OK; - } else if (strcmp(line, CLIENT_LIST_OK_MODE_BEGIN) == 0) { + } else if (StringIsEqual(line, CLIENT_LIST_OK_MODE_BEGIN)) { client.cmd_list.Begin(true); ret = CommandResult::OK; } else { diff -Nru mpd-0.19.21/src/client/ClientRead.cxx mpd-0.20.9/src/client/ClientRead.cxx --- mpd-0.19.21/src/client/ClientRead.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientRead.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ if (newline == nullptr) return InputResult::MORE; - TimeoutMonitor::ScheduleSeconds(client_timeout); + TimeoutMonitor::Schedule(client_timeout); BufferedSocket::ConsumeInput(newline + 1 - p); @@ -52,7 +52,7 @@ break; case CommandResult::KILL: - partition.instance.event_loop->Break(); + partition.instance.Shutdown(); Close(); return InputResult::CLOSED; diff -Nru mpd-0.19.21/src/client/ClientSubscribe.cxx mpd-0.20.9/src/client/ClientSubscribe.cxx --- mpd-0.19.21/src/client/ClientSubscribe.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientSubscribe.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,6 +19,7 @@ #include "config.h" #include "ClientInternal.hxx" +#include "Partition.hxx" #include "Idle.hxx" #include @@ -40,7 +41,7 @@ ++num_subscriptions; - idle_add(IDLE_SUBSCRIPTION); + partition.EmitIdle(IDLE_SUBSCRIPTION); return Client::SubscribeResult::OK; } @@ -57,7 +58,7 @@ subscriptions.erase(i); --num_subscriptions; - idle_add(IDLE_SUBSCRIPTION); + partition.EmitIdle(IDLE_SUBSCRIPTION); assert((num_subscriptions == 0) == subscriptions.empty()); diff -Nru mpd-0.19.21/src/client/ClientWrite.cxx mpd-0.20.9/src/client/ClientWrite.cxx --- mpd-0.19.21/src/client/ClientWrite.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/client/ClientWrite.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,36 +18,35 @@ */ #include "config.h" -#include "ClientInternal.hxx" +#include "Client.hxx" #include "util/FormatString.hxx" +#include "util/AllocatedString.hxx" #include -/** - * Write a block of data to the client. - */ -static void -client_write(Client &client, const char *data, size_t length) +bool +Client::Write(const void *data, size_t length) { /* if the client is going to be closed, do nothing */ - if (client.IsExpired() || length == 0) - return; + return !IsExpired() && FullyBufferedSocket::Write(data, length); +} - client.Write(data, length); +bool +Client::Write(const char *data) +{ + return Write(data, strlen(data)); } void client_puts(Client &client, const char *s) { - client_write(client, s, strlen(s)); + client.Write(s); } void client_vprintf(Client &client, const char *fmt, va_list args) { - char *p = FormatNewV(fmt, args); - client_write(client, p, strlen(p)); - delete[] p; + client.Write(FormatStringV(fmt, args).c_str()); } void diff -Nru mpd-0.19.21/src/client/Response.cxx mpd-0.20.9/src/client/Response.cxx --- mpd-0.19.21/src/client/Response.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/client/Response.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Response.hxx" +#include "Client.hxx" +#include "util/FormatString.hxx" +#include "util/AllocatedString.hxx" + +bool +Response::Write(const void *data, size_t length) +{ + return client.Write(data, length); +} + +bool +Response::Write(const char *data) +{ + return client.Write(data); +} + +bool +Response::FormatV(const char *fmt, va_list args) +{ + return Write(FormatStringV(fmt, args).c_str()); +} + +bool +Response::Format(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool success = FormatV(fmt, args); + va_end(args); + return success; +} + +void +Response::Error(enum ack code, const char *msg) +{ + FormatError(code, "%s", msg); +} + +void +Response::FormatError(enum ack code, const char *fmt, ...) +{ + Format("ACK [%i@%u] {%s} ", + (int)code, list_index, command); + + va_list args; + va_start(args, fmt); + FormatV(fmt, args); + va_end(args); + + Write("\n"); +} diff -Nru mpd-0.19.21/src/client/Response.hxx mpd-0.20.9/src/client/Response.hxx --- mpd-0.19.21/src/client/Response.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/client/Response.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_RESPONSE_HXX +#define MPD_RESPONSE_HXX + +#include "check.h" +#include "protocol/Ack.hxx" + +#include +#include + +class Client; + +class Response { + Client &client; + + /** + * This command's index in the command list. Used to generate + * error messages. + */ + const unsigned list_index; + + /** + * This command's name. Used to generate error messages. + */ + const char *command; + +public: + Response(Client &_client, unsigned _list_index) + :client(_client), list_index(_list_index), command("") {} + + Response(const Response &) = delete; + Response &operator=(const Response &) = delete; + + void SetCommand(const char *_command) { + command = _command; + } + + bool Write(const void *data, size_t length); + bool Write(const char *data); + bool FormatV(const char *fmt, va_list args); + bool Format(const char *fmt, ...); + + void Error(enum ack code, const char *msg); + void FormatError(enum ack code, const char *fmt, ...); +}; + +#endif diff -Nru mpd-0.19.21/src/command/AllCommands.cxx mpd-0.20.9/src/command/AllCommands.cxx --- mpd-0.19.21/src/command/AllCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/AllCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,6 +19,8 @@ #include "config.h" #include "AllCommands.hxx" +#include "CommandError.hxx" +#include "Request.hxx" #include "QueueCommands.hxx" #include "TagCommands.hxx" #include "PlayerCommands.hxx" @@ -32,11 +34,12 @@ #include "OtherCommands.hxx" #include "Permission.hxx" #include "tag/TagType.h" -#include "protocol/Result.hxx" #include "Partition.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" +#include "util/Macros.hxx" #include "util/Tokenizer.hxx" -#include "util/Error.hxx" +#include "util/StringAPI.hxx" #ifdef ENABLE_SQLITE #include "StickerCommands.hxx" @@ -60,22 +63,22 @@ unsigned permission; int min; int max; - CommandResult (*handler)(Client &client, unsigned argc, char **argv); + CommandResult (*handler)(Client &client, Request request, Response &response); }; /* don't be fooled, this is the command handler for "commands" command */ static CommandResult -handle_commands(Client &client, unsigned argc, char *argv[]); +handle_commands(Client &client, Request request, Response &response); static CommandResult -handle_not_commands(Client &client, unsigned argc, char *argv[]); +handle_not_commands(Client &client, Request request, Response &response); /** * The command registry. * * This array must be sorted! */ -static const struct command commands[] = { +static constexpr struct command commands[] = { { "add", PERMISSION_ADD, 1, 1, handle_add }, { "addid", PERMISSION_ADD, 1, 2, handle_addid }, { "addtagid", PERMISSION_ADD, 3, 3, handle_addtagid }, @@ -144,8 +147,8 @@ { "playlistinfo", PERMISSION_READ, 0, 1, handle_playlistinfo }, { "playlistmove", PERMISSION_CONTROL, 3, 3, handle_playlistmove }, { "playlistsearch", PERMISSION_READ, 2, -1, handle_playlistsearch }, - { "plchanges", PERMISSION_READ, 1, 1, handle_plchanges }, - { "plchangesposid", PERMISSION_READ, 1, 1, handle_plchangesposid }, + { "plchanges", PERMISSION_READ, 1, 2, handle_plchanges }, + { "plchangesposid", PERMISSION_READ, 1, 2, handle_plchangesposid }, { "previous", PERMISSION_CONTROL, 0, 0, handle_previous }, { "prio", PERMISSION_CONTROL, 2, -1, handle_prio }, { "prioid", PERMISSION_CONTROL, 2, -1, handle_prioid }, @@ -194,62 +197,79 @@ { "volume", PERMISSION_CONTROL, 1, 1, handle_volume }, }; -static const unsigned num_commands = sizeof(commands) / sizeof(commands[0]); +static constexpr unsigned num_commands = ARRAY_SIZE(commands); static bool command_available(gcc_unused const Partition &partition, gcc_unused const struct command *cmd) { #ifdef ENABLE_SQLITE - if (strcmp(cmd->cmd, "sticker") == 0) + if (StringIsEqual(cmd->cmd, "sticker")) return sticker_enabled(); #endif #ifdef ENABLE_NEIGHBOR_PLUGINS - if (strcmp(cmd->cmd, "listneighbors") == 0) + if (StringIsEqual(cmd->cmd, "listneighbors")) return neighbor_commands_available(partition.instance); #endif + if (StringIsEqual(cmd->cmd, "save") || + StringIsEqual(cmd->cmd, "rm") || + StringIsEqual(cmd->cmd, "rename") || + StringIsEqual(cmd->cmd, "playlistdelete") || + StringIsEqual(cmd->cmd, "playlistmove") || + StringIsEqual(cmd->cmd, "playlistclear") || + StringIsEqual(cmd->cmd, "playlistadd") || + StringIsEqual(cmd->cmd, "listplaylists")) + return playlist_commands_available(); + return true; } -/* don't be fooled, this is the command handler for "commands" command */ static CommandResult -handle_commands(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +PrintAvailableCommands(Response &r, const Partition &partition, + unsigned permission) { - const unsigned permission = client.GetPermission(); - const struct command *cmd; - for (unsigned i = 0; i < num_commands; ++i) { - cmd = &commands[i]; + const struct command *cmd = &commands[i]; if (cmd->permission == (permission & cmd->permission) && - command_available(client.partition, cmd)) - client_printf(client, "command: %s\n", cmd->cmd); + command_available(partition, cmd)) + r.Format("command: %s\n", cmd->cmd); } return CommandResult::OK; } static CommandResult -handle_not_commands(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +PrintUnavailableCommands(Response &r, unsigned permission) { - const unsigned permission = client.GetPermission(); - const struct command *cmd; - for (unsigned i = 0; i < num_commands; ++i) { - cmd = &commands[i]; + const struct command *cmd = &commands[i]; if (cmd->permission != (permission & cmd->permission)) - client_printf(client, "command: %s\n", cmd->cmd); + r.Format("command: %s\n", cmd->cmd); } return CommandResult::OK; } -void command_init(void) +/* don't be fooled, this is the command handler for "commands" command */ +static CommandResult +handle_commands(Client &client, gcc_unused Request request, Response &r) +{ + return PrintAvailableCommands(r, client.partition, + client.GetPermission()); +} + +static CommandResult +handle_not_commands(Client &client, gcc_unused Request request, Response &r) +{ + return PrintUnavailableCommands(r, client.GetPermission()); +} + +void +command_init() { #ifndef NDEBUG /* ensure that the command list is sorted */ @@ -258,7 +278,8 @@ #endif } -void command_finish(void) +void +command_finish() { } @@ -266,13 +287,12 @@ command_lookup(const char *name) { unsigned a = 0, b = num_commands, i; - int cmp; /* binary search */ do { i = (a + b) / 2; - cmp = strcmp(name, commands[i].cmd); + const auto cmp = strcmp(name, commands[i].cmd); if (cmp == 0) return &commands[i]; else if (cmp < 0) @@ -285,60 +305,53 @@ } static bool -command_check_request(const struct command *cmd, Client &client, - unsigned permission, unsigned argc, char *argv[]) +command_check_request(const struct command *cmd, Response &r, + unsigned permission, Request args) { - const unsigned min = cmd->min + 1; - const unsigned max = cmd->max + 1; - if (cmd->permission != (permission & cmd->permission)) { - command_error(client, ACK_ERROR_PERMISSION, + r.FormatError(ACK_ERROR_PERMISSION, "you don't have permission for \"%s\"", cmd->cmd); return false; } - if (min == 0) + const int min = cmd->min; + const int max = cmd->max; + + if (min < 0) return true; - if (min == max && max != argc) { - command_error(client, ACK_ERROR_ARG, + if (min == max && unsigned(max) != args.size) { + r.FormatError(ACK_ERROR_ARG, "wrong number of arguments for \"%s\"", - argv[0]); + cmd->cmd); return false; - } else if (argc < min) { - command_error(client, ACK_ERROR_ARG, - "too few arguments for \"%s\"", argv[0]); + } else if (args.size < unsigned(min)) { + r.FormatError(ACK_ERROR_ARG, + "too few arguments for \"%s\"", cmd->cmd); return false; - } else if (argc > max && max /* != 0 */ ) { - command_error(client, ACK_ERROR_ARG, - "too many arguments for \"%s\"", argv[0]); + } else if (max >= 0 && args.size > unsigned(max)) { + r.FormatError(ACK_ERROR_ARG, + "too many arguments for \"%s\"", cmd->cmd); return false; } else return true; } static const struct command * -command_checked_lookup(Client &client, unsigned permission, - unsigned argc, char *argv[]) +command_checked_lookup(Response &r, unsigned permission, + const char *cmd_name, Request args) { - const struct command *cmd; - - current_command = ""; - - if (argc == 0) - return nullptr; - - cmd = command_lookup(argv[0]); + const struct command *cmd = command_lookup(cmd_name); if (cmd == nullptr) { - command_error(client, ACK_ERROR_UNKNOWN, - "unknown command \"%s\"", argv[0]); + r.FormatError(ACK_ERROR_UNKNOWN, + "unknown command \"%s\"", cmd_name); return nullptr; } - current_command = cmd->cmd; + r.SetCommand(cmd->cmd); - if (!command_check_request(cmd, client, permission, argc, argv)) + if (!command_check_request(cmd, r, permission, args)) return nullptr; return cmd; @@ -346,69 +359,62 @@ CommandResult command_process(Client &client, unsigned num, char *line) -{ - Error error; - char *argv[COMMAND_ARGV_MAX] = { nullptr }; - const struct command *cmd; - CommandResult ret = CommandResult::ERROR; - - command_list_num = num; +try { + Response r(client, num); /* get the command name (first word on the line) */ + /* we have to set current_command because Response::Error() + expects it to be set */ Tokenizer tokenizer(line); - argv[0] = tokenizer.NextWord(error); - if (argv[0] == nullptr) { - current_command = ""; - if (tokenizer.IsEnd()) - command_error(client, ACK_ERROR_UNKNOWN, - "No command given"); - else - command_error(client, ACK_ERROR_UNKNOWN, - "%s", error.GetMessage()); - - current_command = nullptr; + const char *cmd_name; + try { + cmd_name = tokenizer.NextWord(); + if (cmd_name == nullptr) { + r.Error(ACK_ERROR_UNKNOWN, "No command given"); + /* this client does not speak the MPD + protocol; kick the connection */ + return CommandResult::FINISH; + } + } catch (const std::exception &e) { + r.Error(ACK_ERROR_UNKNOWN, e.what()); /* this client does not speak the MPD protocol; kick the connection */ return CommandResult::FINISH; } - unsigned argc = 1; + char *argv[COMMAND_ARGV_MAX]; + Request args(argv, 0); /* now parse the arguments (quoted or unquoted) */ - while (argc < COMMAND_ARGV_MAX && - (argv[argc] = - tokenizer.NextParam(error)) != nullptr) - ++argc; - - /* some error checks; we have to set current_command because - command_error() expects it to be set */ - - current_command = argv[0]; - - if (argc >= COMMAND_ARGV_MAX) { - command_error(client, ACK_ERROR_ARG, "Too many arguments"); - current_command = nullptr; - return CommandResult::ERROR; - } + while (true) { + if (args.size == COMMAND_ARGV_MAX) { + r.Error(ACK_ERROR_ARG, "Too many arguments"); + return CommandResult::ERROR; + } + + char *a = tokenizer.NextParam(); + if (a == nullptr) + break; - if (!tokenizer.IsEnd()) { - command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage()); - current_command = nullptr; - return CommandResult::ERROR; + argv[args.size++] = a; } /* look up and invoke the command handler */ - cmd = command_checked_lookup(client, client.GetPermission(), - argc, argv); - if (cmd) - ret = cmd->handler(client, argc, argv); - - current_command = nullptr; - command_list_num = 0; + const struct command *cmd = + command_checked_lookup(r, client.GetPermission(), + cmd_name, args); + + CommandResult ret = cmd + ? cmd->handler(client, args, r) + : CommandResult::ERROR; return ret; +} catch (const std::exception &e) { + Response r(client, num); + PrintError(r, std::current_exception()); + return CommandResult::ERROR; } diff -Nru mpd-0.19.21/src/command/AllCommands.hxx mpd-0.20.9/src/command/AllCommands.hxx --- mpd-0.19.21/src/command/AllCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/AllCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,9 +24,11 @@ class Client; -void command_init(void); +void +command_init(); -void command_finish(void); +void +command_finish(); CommandResult command_process(Client &client, unsigned num, char *line); diff -Nru mpd-0.19.21/src/command/CommandError.cxx mpd-0.20.9/src/command/CommandError.cxx --- mpd-0.19.21/src/command/CommandError.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/CommandError.cxx 2017-05-08 13:07:11.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,111 +19,133 @@ #include "config.h" #include "CommandError.hxx" +#include "PlaylistError.hxx" #include "db/DatabaseError.hxx" -#include "protocol/Result.hxx" -#include "util/Error.hxx" +#include "client/Response.hxx" #include "Log.hxx" +#include "util/Exception.hxx" + +#include #include -#include -#include -CommandResult -print_playlist_result(Client &client, PlaylistResult result) +#define GLIBCXX_490 20140422 +#define GLIBCXX_491 20140716 +#define GLIBCXX_492 20141030 +#define GLIBCXX_492_Debian_9 20141220 +#define GLIBCXX_493 20150626 +#define GLIBCXX_494 20160803 +#define GLIBCXX_49X_NDK_r13b 20150123 + +/* the big mess attempts to detect whether we're compiling with + libstdc++ 4.9.x; __GLIBCXX__ is a date tag and cannot be used to + check the major version; and just checking the compiler version + isn't enough, because somebody could use an old libstdc++ with + clang - SIGH! */ +#if GCC_OLDER_THAN(5,0) || (defined(__GLIBCXX__) && \ + (__GLIBCXX__ == GLIBCXX_490 || __GLIBCXX__ == GLIBCXX_491 || \ + __GLIBCXX__ == GLIBCXX_492 || \ + __GLIBCXX__ == GLIBCXX_492_Debian_9 || \ + __GLIBCXX__ == GLIBCXX_493 || \ + __GLIBCXX__ == GLIBCXX_494 || \ + __GLIBCXX__ == GLIBCXX_49X_NDK_r13b)) +#define GLIBCXX_49X +#endif + +gcc_const +static enum ack +ToAck(PlaylistResult result) noexcept { switch (result) { case PlaylistResult::SUCCESS: - return CommandResult::OK; - - case PlaylistResult::ERRNO: - command_error(client, ACK_ERROR_SYSTEM, "%s", - strerror(errno)); - return CommandResult::ERROR; + break; case PlaylistResult::DENIED: - command_error(client, ACK_ERROR_PERMISSION, "Access denied"); - return CommandResult::ERROR; + return ACK_ERROR_PERMISSION; case PlaylistResult::NO_SUCH_SONG: - command_error(client, ACK_ERROR_NO_EXIST, "No such song"); - return CommandResult::ERROR; - case PlaylistResult::NO_SUCH_LIST: - command_error(client, ACK_ERROR_NO_EXIST, "No such playlist"); - return CommandResult::ERROR; + return ACK_ERROR_NO_EXIST; case PlaylistResult::LIST_EXISTS: - command_error(client, ACK_ERROR_EXIST, - "Playlist already exists"); - return CommandResult::ERROR; + return ACK_ERROR_EXIST; case PlaylistResult::BAD_NAME: - command_error(client, ACK_ERROR_ARG, - "playlist name is invalid: " - "playlist names may not contain slashes," - " newlines or carriage returns"); - return CommandResult::ERROR; - case PlaylistResult::BAD_RANGE: - command_error(client, ACK_ERROR_ARG, "Bad song index"); - return CommandResult::ERROR; + return ACK_ERROR_ARG; case PlaylistResult::NOT_PLAYING: - command_error(client, ACK_ERROR_PLAYER_SYNC, "Not playing"); - return CommandResult::ERROR; + return ACK_ERROR_PLAYER_SYNC; case PlaylistResult::TOO_LARGE: - command_error(client, ACK_ERROR_PLAYLIST_MAX, - "playlist is at the max size"); - return CommandResult::ERROR; + return ACK_ERROR_PLAYLIST_MAX; case PlaylistResult::DISABLED: - command_error(client, ACK_ERROR_UNKNOWN, - "stored playlist support is disabled"); - return CommandResult::ERROR; + break; } - assert(0); - return CommandResult::ERROR; + return ACK_ERROR_UNKNOWN; } -CommandResult -print_error(Client &client, const Error &error) +#ifdef ENABLE_DATABASE +gcc_const +static enum ack +ToAck(DatabaseErrorCode code) noexcept { - assert(error.IsDefined()); + switch (code) { + case DatabaseErrorCode::DISABLED: + case DatabaseErrorCode::NOT_FOUND: + return ACK_ERROR_NO_EXIST; + + case DatabaseErrorCode::CONFLICT: + return ACK_ERROR_ARG; + } - LogError(error); + return ACK_ERROR_UNKNOWN; +} +#endif - if (error.IsDomain(playlist_domain)) { - return print_playlist_result(client, - PlaylistResult(error.GetCode())); - } else if (error.IsDomain(ack_domain)) { - command_error(client, (ack)error.GetCode(), - "%s", error.GetMessage()); - return CommandResult::ERROR; +gcc_pure +static enum ack +ToAck(std::exception_ptr ep) noexcept +{ + try { + std::rethrow_exception(ep); + } catch (const ProtocolError &pe) { + return pe.GetCode(); + } catch (const PlaylistError &pe) { + return ToAck(pe.GetCode()); #ifdef ENABLE_DATABASE - } else if (error.IsDomain(db_domain)) { - switch ((enum db_error)error.GetCode()) { - case DB_DISABLED: - command_error(client, ACK_ERROR_NO_EXIST, "%s", - error.GetMessage()); - return CommandResult::ERROR; - - case DB_NOT_FOUND: - command_error(client, ACK_ERROR_NO_EXIST, "Not found"); - return CommandResult::ERROR; - - case DB_CONFLICT: - command_error(client, ACK_ERROR_ARG, "Conflict"); - return CommandResult::ERROR; - } + } catch (const DatabaseError &de) { + return ToAck(de.GetCode()); +#endif + } catch (const std::system_error &e) { + return ACK_ERROR_SYSTEM; + } catch (const std::invalid_argument &e) { + return ACK_ERROR_ARG; +#ifdef GLIBCXX_49X + } catch (const std::exception &e) { +#else + } catch (...) { #endif - } else if (error.IsDomain(errno_domain)) { - command_error(client, ACK_ERROR_SYSTEM, "%s", - strerror(error.GetCode())); - return CommandResult::ERROR; + try { +#ifdef GLIBCXX_49X + /* workaround for g++ 4.x: no overload for + rethrow_exception(exception_ptr) */ + std::rethrow_if_nested(e); +#else + std::rethrow_if_nested(ep); +#endif + return ACK_ERROR_UNKNOWN; + } catch (...) { + return ToAck(std::current_exception()); + } } +} - command_error(client, ACK_ERROR_UNKNOWN, "error"); - return CommandResult::ERROR; +void +PrintError(Response &r, std::exception_ptr ep) +{ + LogError(ep); + r.Error(ToAck(ep), FullMessage(ep).c_str()); } diff -Nru mpd-0.19.21/src/command/CommandError.hxx mpd-0.20.9/src/command/CommandError.hxx --- mpd-0.19.21/src/command/CommandError.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/CommandError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,18 +21,15 @@ #define MPD_COMMAND_ERROR_HXX #include "CommandResult.hxx" -#include "PlaylistError.hxx" -class Client; -class Error; +#include -CommandResult -print_playlist_result(Client &client, PlaylistResult result); +class Response; /** - * Send the #Error to the client. + * Send the exception to the client. */ -CommandResult -print_error(Client &client, const Error &error); +void +PrintError(Response &r, std::exception_ptr ep); #endif diff -Nru mpd-0.19.21/src/command/CommandListBuilder.cxx mpd-0.20.9/src/command/CommandListBuilder.cxx --- mpd-0.19.21/src/command/CommandListBuilder.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/CommandListBuilder.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,6 @@ CommandListBuilder::Reset() { list.clear(); - size = 0; mode = Mode::DISABLED; } diff -Nru mpd-0.19.21/src/command/CommandListBuilder.hxx mpd-0.20.9/src/command/CommandListBuilder.hxx --- mpd-0.19.21/src/command/CommandListBuilder.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/CommandListBuilder.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -58,7 +58,7 @@ public: CommandListBuilder() - :mode(Mode::DISABLED), size(0) {} + :mode(Mode::DISABLED) {} /** * Is a command list currently being built? @@ -89,6 +89,7 @@ assert(mode == Mode::DISABLED); mode = (Mode)ok; + size = 0; } /** diff -Nru mpd-0.19.21/src/command/CommandResult.hxx mpd-0.20.9/src/command/CommandResult.hxx --- mpd-0.19.21/src/command/CommandResult.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/CommandResult.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/command/DatabaseCommands.cxx mpd-0.20.9/src/command/DatabaseCommands.cxx --- mpd-0.19.21/src/command/DatabaseCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/DatabaseCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "config.h" #include "DatabaseCommands.hxx" -#include "db/DatabaseGlue.hxx" +#include "Request.hxx" #include "db/DatabaseQueue.hxx" #include "db/DatabasePlaylist.hxx" #include "db/DatabasePrint.hxx" @@ -27,141 +27,126 @@ #include "db/Selection.hxx" #include "CommandError.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "tag/Tag.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" +#include "util/StringAPI.hxx" #include "SongFilter.hxx" -#include "protocol/Result.hxx" #include "BulkEdit.hxx" -#include +#include CommandResult -handle_listfiles_db(Client &client, const char *uri) +handle_listfiles_db(Client &client, Response &r, const char *uri) { const DatabaseSelection selection(uri, false); - - Error error; - if (!db_selection_print(client, selection, false, true, error)) - return print_error(client, error); - + db_selection_print(r, client.partition, + selection, false, true); return CommandResult::OK; } CommandResult -handle_lsinfo2(Client &client, unsigned argc, char *argv[]) +handle_lsinfo2(Client &client, const char *uri, Response &r) { - const char *const uri = argc == 2 - ? argv[1] - /* default is root directory */ - : ""; - const DatabaseSelection selection(uri, false); - - Error error; - if (!db_selection_print(client, selection, true, false, error)) - return print_error(client, error); - + db_selection_print(r, client.partition, + selection, true, false); return CommandResult::OK; } static CommandResult -handle_match(Client &client, unsigned argc, char *argv[], bool fold_case) +handle_match(Client &client, Request args, Response &r, bool fold_case) { - ConstBuffer args(argv + 1, argc - 1); + RangeArg window; + if (args.size >= 2 && StringIsEqual(args[args.size - 2], "window")) { + window = args.ParseRange(args.size - 1); + + args.pop_back(); + args.pop_back(); + } else + window.SetAll(); SongFilter filter; if (!filter.Parse(args, fold_case)) { - command_error(client, ACK_ERROR_ARG, "incorrect arguments"); + r.Error(ACK_ERROR_ARG, "incorrect arguments"); return CommandResult::ERROR; } const DatabaseSelection selection("", true, &filter); - Error error; - return db_selection_print(client, selection, true, false, error) - ? CommandResult::OK - : print_error(client, error); + db_selection_print(r, client.partition, + selection, true, false, + window.start, window.end); + return CommandResult::OK; } CommandResult -handle_find(Client &client, unsigned argc, char *argv[]) +handle_find(Client &client, Request args, Response &r) { - return handle_match(client, argc, argv, false); + return handle_match(client, args, r, false); } CommandResult -handle_search(Client &client, unsigned argc, char *argv[]) +handle_search(Client &client, Request args, Response &r) { - return handle_match(client, argc, argv, true); + return handle_match(client, args, r, true); } static CommandResult -handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case) +handle_match_add(Client &client, Request args, Response &r, bool fold_case) { - ConstBuffer args(argv + 1, argc - 1); - SongFilter filter; if (!filter.Parse(args, fold_case)) { - command_error(client, ACK_ERROR_ARG, "incorrect arguments"); + r.Error(ACK_ERROR_ARG, "incorrect arguments"); return CommandResult::ERROR; } const ScopeBulkEdit bulk_edit(client.partition); const DatabaseSelection selection("", true, &filter); - Error error; - return AddFromDatabase(client.partition, selection, error) - ? CommandResult::OK - : print_error(client, error); + AddFromDatabase(client.partition, selection); + return CommandResult::OK; } CommandResult -handle_findadd(Client &client, unsigned argc, char *argv[]) +handle_findadd(Client &client, Request args, Response &r) { - return handle_match_add(client, argc, argv, false); + return handle_match_add(client, args, r, false); } CommandResult -handle_searchadd(Client &client, unsigned argc, char *argv[]) +handle_searchadd(Client &client, Request args, Response &r) { - return handle_match_add(client, argc, argv, true); + return handle_match_add(client, args, r, true); } CommandResult -handle_searchaddpl(Client &client, unsigned argc, char *argv[]) +handle_searchaddpl(Client &client, Request args, Response &r) { - ConstBuffer args(argv + 1, argc - 1); const char *playlist = args.shift(); SongFilter filter; if (!filter.Parse(args, true)) { - command_error(client, ACK_ERROR_ARG, "incorrect arguments"); + r.Error(ACK_ERROR_ARG, "incorrect arguments"); return CommandResult::ERROR; } - Error error; - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return print_error(client, error); + const Database &db = client.GetDatabaseOrThrow(); - return search_add_to_playlist(*db, *client.GetStorage(), - "", playlist, &filter, error) - ? CommandResult::OK - : print_error(client, error); + search_add_to_playlist(db, *client.GetStorage(), + "", playlist, &filter); + return CommandResult::OK; } CommandResult -handle_count(Client &client, unsigned argc, char *argv[]) +handle_count(Client &client, Request args, Response &r) { - ConstBuffer args(argv + 1, argc - 1); - TagType group = TAG_NUM_OF_ITEM_TYPES; - if (args.size >= 2 && strcmp(args[args.size - 2], "group") == 0) { + if (args.size >= 2 && StringIsEqual(args[args.size - 2], "group")) { const char *s = args[args.size - 1]; group = tag_name_parse_i(s); if (group == TAG_NUM_OF_ITEM_TYPES) { - command_error(client, ACK_ERROR_ARG, + r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", s); return CommandResult::ERROR; } @@ -172,115 +157,98 @@ SongFilter filter; if (!args.IsEmpty() && !filter.Parse(args, false)) { - command_error(client, ACK_ERROR_ARG, "incorrect arguments"); + r.Error(ACK_ERROR_ARG, "incorrect arguments"); return CommandResult::ERROR; } - Error error; - return PrintSongCount(client, "", &filter, group, error) - ? CommandResult::OK - : print_error(client, error); + PrintSongCount(r, client.partition, "", &filter, group); + return CommandResult::OK; } CommandResult -handle_listall(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_listall(Client &client, Request args, Response &r) { - const char *directory = ""; + /* default is root directory */ + const auto uri = args.GetOptional(0, ""); - if (argc == 2) - directory = argv[1]; - - Error error; - return db_selection_print(client, DatabaseSelection(directory, true), - false, false, error) - ? CommandResult::OK - : print_error(client, error); + db_selection_print(r, client.partition, + DatabaseSelection(uri, true), + false, false); + return CommandResult::OK; } CommandResult -handle_list(Client &client, unsigned argc, char *argv[]) +handle_list(Client &client, Request args, Response &r) { - ConstBuffer args(argv + 1, argc - 1); const char *tag_name = args.shift(); unsigned tagType = locate_parse_type(tag_name); if (tagType >= TAG_NUM_OF_ITEM_TYPES && tagType != LOCATE_TAG_FILE_TYPE) { - command_error(client, ACK_ERROR_ARG, + r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", tag_name); return CommandResult::ERROR; } - SongFilter *filter = nullptr; - uint32_t group_mask = 0; + std::unique_ptr filter; + tag_mask_t group_mask = 0; if (args.size == 1) { /* for compatibility with < 0.12.0 */ if (tagType != TAG_ALBUM) { - command_error(client, ACK_ERROR_ARG, + r.FormatError(ACK_ERROR_ARG, "should be \"%s\" for 3 arguments", tag_item_names[TAG_ALBUM]); return CommandResult::ERROR; } - filter = new SongFilter((unsigned)TAG_ARTIST, args.shift()); + filter.reset(new SongFilter((unsigned)TAG_ARTIST, + args.shift())); } while (args.size >= 2 && - strcmp(args[args.size - 2], "group") == 0) { + StringIsEqual(args[args.size - 2], "group")) { const char *s = args[args.size - 1]; TagType gt = tag_name_parse_i(s); if (gt == TAG_NUM_OF_ITEM_TYPES) { - command_error(client, ACK_ERROR_ARG, + r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", s); return CommandResult::ERROR; } - group_mask |= 1u << unsigned(gt); + group_mask |= tag_mask_t(1) << unsigned(gt); args.pop_back(); args.pop_back(); } if (!args.IsEmpty()) { - filter = new SongFilter(); + filter.reset(new SongFilter()); if (!filter->Parse(args, false)) { - delete filter; - command_error(client, ACK_ERROR_ARG, - "not able to parse args"); + r.Error(ACK_ERROR_ARG, "not able to parse args"); return CommandResult::ERROR; } } if (tagType < TAG_NUM_OF_ITEM_TYPES && - group_mask & (1u << tagType)) { - delete filter; - command_error(client, ACK_ERROR_ARG, "Conflicting group"); + group_mask & (tag_mask_t(1) << tagType)) { + r.Error(ACK_ERROR_ARG, "Conflicting group"); return CommandResult::ERROR; } - Error error; - CommandResult ret = - PrintUniqueTags(client, tagType, group_mask, filter, error) - ? CommandResult::OK - : print_error(client, error); - - delete filter; - - return ret; + PrintUniqueTags(r, client.partition, + tagType, group_mask, filter.get()); + return CommandResult::OK; } CommandResult -handle_listallinfo(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_listallinfo(Client &client, Request args, Response &r) { - const char *directory = ""; + /* default is root directory */ + const auto uri = args.GetOptional(0, ""); - if (argc == 2) - directory = argv[1]; - - Error error; - return db_selection_print(client, DatabaseSelection(directory, true), - true, false, error) - ? CommandResult::OK - : print_error(client, error); + db_selection_print(r, client.partition, + DatabaseSelection(uri, true), + true, false); + return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/DatabaseCommands.hxx mpd-0.20.9/src/command/DatabaseCommands.hxx --- mpd-0.19.21/src/command/DatabaseCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/DatabaseCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,38 +23,40 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_listfiles_db(Client &client, const char *uri); +handle_listfiles_db(Client &client, Response &r, const char *uri); CommandResult -handle_lsinfo2(Client &client, unsigned argc, char *argv[]); +handle_lsinfo2(Client &client, const char *uri, Response &response); CommandResult -handle_find(Client &client, unsigned argc, char *argv[]); +handle_find(Client &client, Request request, Response &response); CommandResult -handle_findadd(Client &client, unsigned argc, char *argv[]); +handle_findadd(Client &client, Request request, Response &response); CommandResult -handle_search(Client &client, unsigned argc, char *argv[]); +handle_search(Client &client, Request request, Response &response); CommandResult -handle_searchadd(Client &client, unsigned argc, char *argv[]); +handle_searchadd(Client &client, Request request, Response &response); CommandResult -handle_searchaddpl(Client &client, unsigned argc, char *argv[]); +handle_searchaddpl(Client &client, Request request, Response &response); CommandResult -handle_count(Client &client, unsigned argc, char *argv[]); +handle_count(Client &client, Request request, Response &response); CommandResult -handle_listall(Client &client, unsigned argc, char *argv[]); +handle_listall(Client &client, Request request, Response &response); CommandResult -handle_list(Client &client, unsigned argc, char *argv[]); +handle_list(Client &client, Request request, Response &response); CommandResult -handle_listallinfo(Client &client, unsigned argc, char *argv[]); +handle_listallinfo(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/FileCommands.cxx mpd-0.20.9/src/command/FileCommands.cxx --- mpd-0.19.21/src/command/FileCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/FileCommands.cxx 2017-05-08 13:15:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,32 +21,30 @@ #include "config.h" #include "FileCommands.hxx" +#include "Request.hxx" #include "CommandError.hxx" #include "protocol/Ack.hxx" -#include "protocol/Result.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "util/CharUtil.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" #include "tag/TagHandler.hxx" -#include "tag/ApeTag.hxx" -#include "tag/TagId3.hxx" +#include "tag/Generic.hxx" #include "TagStream.hxx" #include "TagFile.hxx" #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" -#include "fs/FileSystem.hxx" +#include "fs/FileInfo.hxx" #include "fs/DirectoryReader.hxx" +#include "LocateUri.hxx" #include "TimePrint.hxx" -#include "ls.hxx" #include -#include #include /* for PRIu64 */ gcc_pure static bool -SkipNameFS(const char *name_fs) +SkipNameFS(PathTraitsFS::const_pointer_type name_fs) noexcept { return name_fs[0] == '.' && (name_fs[1] == 0 || @@ -55,9 +53,9 @@ gcc_pure static bool -skip_path(const char *name_fs) +skip_path(Path name_fs) noexcept { - return strchr(name_fs, '\n') != nullptr; + return name_fs.HasNewline(); } #if defined(WIN32) && GCC_CHECK_VERSION(4,6) @@ -68,28 +66,13 @@ #endif CommandResult -handle_listfiles_local(Client &client, const char *path_utf8) +handle_listfiles_local(Response &r, Path path_fs) { - const auto path_fs = AllocatedPath::FromUTF8(path_utf8); - if (path_fs.IsNull()) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported file name"); - return CommandResult::ERROR; - } - - Error error; - if (!client.AllowFile(path_fs, error)) - return print_error(client, error); - DirectoryReader reader(path_fs); - if (reader.HasFailed()) { - error.FormatErrno("Failed to open '%s'", path_utf8); - return print_error(client, error); - } while (reader.ReadEntry()) { const Path name_fs = reader.GetEntry(); - if (SkipNameFS(name_fs.c_str()) || skip_path(name_fs.c_str())) + if (SkipNameFS(name_fs.c_str()) || skip_path(name_fs)) continue; std::string name_utf8 = name_fs.ToUTF8(); @@ -98,20 +81,21 @@ const AllocatedPath full_fs = AllocatedPath::Build(path_fs, name_fs); - struct stat st; - if (!StatFile(full_fs, st, false)) + FileInfo fi; + if (!GetFileInfo(full_fs, fi, false)) continue; - if (S_ISREG(st.st_mode)) { - client_printf(client, "file: %s\n" - "size: %" PRIu64 "\n", - name_utf8.c_str(), - uint64_t(st.st_size)); - } else if (S_ISDIR(st.st_mode)) - client_printf(client, "directory: %s\n", - name_utf8.c_str()); + if (fi.IsRegular()) + r.Format("file: %s\n" + "size: %" PRIu64 "\n", + name_utf8.c_str(), + fi.GetSize()); + else if (fi.IsDirectory()) + r.Format("directory: %s\n", name_utf8.c_str()); + else + continue; - time_print(client, "Last-Modified", st.st_mtime); + time_print(r, "Last-Modified", fi.GetModificationTime()); } return CommandResult::OK; @@ -123,7 +107,7 @@ gcc_pure static bool -IsValidName(const char *p) +IsValidName(const char *p) noexcept { if (!IsAlphaASCII(*p)) return false; @@ -139,7 +123,7 @@ gcc_pure static bool -IsValidValue(const char *p) +IsValidValue(const char *p) noexcept { while (*p) { const char ch = *p++; @@ -154,106 +138,98 @@ static void print_pair(const char *key, const char *value, void *ctx) { - Client &client = *(Client *)ctx; + auto &r = *(Response *)ctx; if (IsValidName(key) && IsValidValue(value)) - client_printf(client, "%s: %s\n", key, value); + r.Format("%s: %s\n", key, value); } -static constexpr tag_handler print_comment_handler = { +static constexpr TagHandler print_comment_handler = { nullptr, nullptr, print_pair, }; static CommandResult -read_stream_comments(Client &client, const char *uri) +read_stream_comments(Response &r, const char *uri) { - if (!uri_supported_scheme(uri)) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported URI scheme"); + if (!tag_stream_scan(uri, print_comment_handler, &r)) { + r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); return CommandResult::ERROR; } - if (!tag_stream_scan(uri, print_comment_handler, &client)) { - command_error(client, ACK_ERROR_NO_EXIST, - "Failed to load file"); + return CommandResult::OK; + +} + +static CommandResult +read_file_comments(Response &r, const Path path_fs) +{ + if (!tag_file_scan(path_fs, print_comment_handler, &r)) { + r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); return CommandResult::ERROR; } + ScanGenericTags(path_fs, print_comment_handler, &r); + return CommandResult::OK; } static CommandResult -read_file_comments(Client &client, const Path path_fs) +read_db_comments(Client &client, Response &r, const char *uri) { - if (!tag_file_scan(path_fs, print_comment_handler, &client)) { - command_error(client, ACK_ERROR_NO_EXIST, - "Failed to load file"); +#ifdef ENABLE_DATABASE + const Storage *storage = client.GetStorage(); + if (storage == nullptr) { +#else + (void)client; + (void)uri; +#endif + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; +#ifdef ENABLE_DATABASE } - tag_ape_scan2(path_fs, &print_comment_handler, &client); - tag_id3_scan(path_fs, &print_comment_handler, &client); + { + AllocatedPath path_fs = storage->MapFS(uri); + if (!path_fs.IsNull()) + return read_file_comments(r, path_fs); + } - return CommandResult::OK; + { + const std::string uri2 = storage->MapUTF8(uri); + if (uri_has_scheme(uri2.c_str())) + return read_stream_comments(r, uri2.c_str()); + } + r.Error(ACK_ERROR_NO_EXIST, "No such file"); + return CommandResult::ERROR; +#endif } CommandResult -handle_read_comments(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_read_comments(Client &client, Request args, Response &r) { - assert(argc == 2); + assert(args.size == 1); - const char *const uri = argv[1]; + const char *const uri = args.front(); - if (memcmp(uri, "file:///", 8) == 0) { - /* read comments from arbitrary local file */ - const char *path_utf8 = uri + 7; - AllocatedPath path_fs = AllocatedPath::FromUTF8(path_utf8); - if (path_fs.IsNull()) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported file name"); - return CommandResult::ERROR; - } - - Error error; - if (!client.AllowFile(path_fs, error)) - return print_error(client, error); - - return read_file_comments(client, path_fs); - } else if (uri_has_scheme(uri)) { - return read_stream_comments(client, uri); - } else if (!PathTraitsUTF8::IsAbsolute(uri)) { + const auto located_uri = LocateUri(uri, &client #ifdef ENABLE_DATABASE - const Storage *storage = client.GetStorage(); - if (storage == nullptr) { + , nullptr #endif - command_error(client, ACK_ERROR_NO_EXIST, - "No database"); - return CommandResult::ERROR; -#ifdef ENABLE_DATABASE - } + ); + switch (located_uri.type) { + case LocatedUri::Type::ABSOLUTE: + return read_stream_comments(r, located_uri.canonical_uri); - { - AllocatedPath path_fs = storage->MapFS(uri); - if (!path_fs.IsNull()) - return read_file_comments(client, path_fs); - } - - { - const std::string uri2 = storage->MapUTF8(uri); - if (uri_has_scheme(uri2.c_str())) - return read_stream_comments(client, - uri2.c_str()); - } + case LocatedUri::Type::RELATIVE: + return read_db_comments(client, r, located_uri.canonical_uri); - command_error(client, ACK_ERROR_NO_EXIST, "No such file"); - return CommandResult::ERROR; -#endif - } else { - command_error(client, ACK_ERROR_NO_EXIST, "No such file"); - return CommandResult::ERROR; + case LocatedUri::Type::PATH: + return read_file_comments(r, located_uri.path); } + + gcc_unreachable(); } diff -Nru mpd-0.19.21/src/command/FileCommands.hxx mpd-0.20.9/src/command/FileCommands.hxx --- mpd-0.19.21/src/command/FileCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/FileCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,11 +23,14 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; +class Path; CommandResult -handle_listfiles_local(Client &client, const char *path_utf8); +handle_listfiles_local(Response &response, Path path_fs); CommandResult -handle_read_comments(Client &client, unsigned argc, char *argv[]); +handle_read_comments(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/MessageCommands.cxx mpd-0.20.9/src/command/MessageCommands.cxx --- mpd-0.19.21/src/command/MessageCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/MessageCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,13 @@ #include "config.h" #include "MessageCommands.hxx" +#include "Request.hxx" #include "client/Client.hxx" #include "client/ClientList.hxx" +#include "client/Response.hxx" #include "Instance.hxx" #include "Partition.hxx" -#include "protocol/Result.hxx" +#include "util/ConstBuffer.hxx" #include #include @@ -31,27 +33,25 @@ #include CommandResult -handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_subscribe(Client &client, Request args, Response &r) { - assert(argc == 2); + assert(args.size == 1); + const char *const channel_name = args[0]; - switch (client.Subscribe(argv[1])) { + switch (client.Subscribe(channel_name)) { case Client::SubscribeResult::OK: return CommandResult::OK; case Client::SubscribeResult::INVALID: - command_error(client, ACK_ERROR_ARG, - "invalid channel name"); + r.Error(ACK_ERROR_ARG, "invalid channel name"); return CommandResult::ERROR; case Client::SubscribeResult::ALREADY: - command_error(client, ACK_ERROR_EXIST, - "already subscribed to this channel"); + r.Error(ACK_ERROR_EXIST, "already subscribed to this channel"); return CommandResult::ERROR; case Client::SubscribeResult::FULL: - command_error(client, ACK_ERROR_EXIST, - "subscription list is full"); + r.Error(ACK_ERROR_EXIST, "subscription list is full"); return CommandResult::ERROR; } @@ -61,24 +61,23 @@ } CommandResult -handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_unsubscribe(Client &client, Request args, Response &r) { - assert(argc == 2); + assert(args.size == 1); + const char *const channel_name = args[0]; - if (client.Unsubscribe(argv[1])) + if (client.Unsubscribe(channel_name)) return CommandResult::OK; else { - command_error(client, ACK_ERROR_NO_EXIST, - "not subscribed to this channel"); + r.Error(ACK_ERROR_NO_EXIST, "not subscribed to this channel"); return CommandResult::ERROR; } } CommandResult -handle_channels(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_channels(Client &client, gcc_unused Request args, Response &r) { - assert(argc == 1); + assert(args.IsEmpty()); std::set channels; for (const auto &c : *client.partition.instance.client_list) @@ -86,22 +85,22 @@ c.subscriptions.end()); for (const auto &channel : channels) - client_printf(client, "channel: %s\n", channel.c_str()); + r.Format("channel: %s\n", channel.c_str()); return CommandResult::OK; } CommandResult handle_read_messages(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) + gcc_unused Request args, Response &r) { - assert(argc == 1); + assert(args.IsEmpty()); while (!client.messages.empty()) { const ClientMessage &msg = client.messages.front(); - client_printf(client, "channel: %s\nmessage: %s\n", - msg.GetChannel(), msg.GetMessage()); + r.Format("channel: %s\nmessage: %s\n", + msg.GetChannel(), msg.GetMessage()); client.messages.pop_front(); } @@ -109,19 +108,20 @@ } CommandResult -handle_send_message(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_send_message(Client &client, Request args, Response &r) { - assert(argc == 3); + assert(args.size == 2); - if (!client_message_valid_channel_name(argv[1])) { - command_error(client, ACK_ERROR_ARG, - "invalid channel name"); + const char *const channel_name = args[0]; + const char *const message_text = args[1]; + + if (!client_message_valid_channel_name(channel_name)) { + r.Error(ACK_ERROR_ARG, "invalid channel name"); return CommandResult::ERROR; } bool sent = false; - const ClientMessage msg(argv[1], argv[2]); + const ClientMessage msg(channel_name, message_text); for (auto &c : *client.partition.instance.client_list) if (c.PushMessage(msg)) sent = true; @@ -129,8 +129,8 @@ if (sent) return CommandResult::OK; else { - command_error(client, ACK_ERROR_NO_EXIST, - "nobody is subscribed to this channel"); + r.Error(ACK_ERROR_NO_EXIST, + "nobody is subscribed to this channel"); return CommandResult::ERROR; } } diff -Nru mpd-0.19.21/src/command/MessageCommands.hxx mpd-0.20.9/src/command/MessageCommands.hxx --- mpd-0.19.21/src/command/MessageCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/MessageCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,20 +23,22 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_subscribe(Client &client, unsigned argc, char *argv[]); +handle_subscribe(Client &client, Request request, Response &response); CommandResult -handle_unsubscribe(Client &client, unsigned argc, char *argv[]); +handle_unsubscribe(Client &client, Request request, Response &response); CommandResult -handle_channels(Client &client, unsigned argc, char *argv[]); +handle_channels(Client &client, Request request, Response &response); CommandResult -handle_read_messages(Client &client, unsigned argc, char *argv[]); +handle_read_messages(Client &client, Request request, Response &response); CommandResult -handle_send_message(Client &client, unsigned argc, char *argv[]); +handle_send_message(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/NeighborCommands.cxx mpd-0.20.9/src/command/NeighborCommands.cxx --- mpd-0.19.21/src/command/NeighborCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/NeighborCommands.cxx 2017-05-08 13:07:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,41 +19,36 @@ #include "config.h" #include "NeighborCommands.hxx" +#include "Request.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Instance.hxx" #include "Partition.hxx" -#include "protocol/Result.hxx" #include "neighbor/Glue.hxx" #include "neighbor/Info.hxx" -#include #include -#include - bool -neighbor_commands_available(const Instance &instance) +neighbor_commands_available(const Instance &instance) noexcept { return instance.neighbors != nullptr; } CommandResult -handle_listneighbors(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_listneighbors(Client &client, gcc_unused Request args, Response &r) { const NeighborGlue *const neighbors = client.partition.instance.neighbors; if (neighbors == nullptr) { - command_error(client, ACK_ERROR_UNKNOWN, - "No neighbor plugin configured"); + r.Error(ACK_ERROR_UNKNOWN, "No neighbor plugin configured"); return CommandResult::ERROR; } for (const auto &i : neighbors->GetList()) - client_printf(client, - "neighbor: %s\n" - "name: %s\n", - i.uri.c_str(), - i.display_name.c_str()); + r.Format("neighbor: %s\n" + "name: %s\n", + i.uri.c_str(), + i.display_name.c_str()); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/NeighborCommands.hxx mpd-0.20.9/src/command/NeighborCommands.hxx --- mpd-0.19.21/src/command/NeighborCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/NeighborCommands.hxx 2017-05-08 13:07:45.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,12 +25,14 @@ struct Instance; class Client; +class Request; +class Response; gcc_pure bool -neighbor_commands_available(const Instance &instance); +neighbor_commands_available(const Instance &instance) noexcept; CommandResult -handle_listneighbors(Client &client, unsigned argc, char *argv[]); +handle_listneighbors(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/OtherCommands.cxx mpd-0.20.9/src/command/OtherCommands.cxx --- mpd-0.19.21/src/command/OtherCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/OtherCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,13 @@ #include "config.h" #include "OtherCommands.hxx" +#include "Request.hxx" #include "FileCommands.hxx" #include "StorageCommands.hxx" #include "CommandError.hxx" #include "db/Uri.hxx" #include "storage/StorageInterface.hxx" +#include "LocateUri.hxx" #include "DetachedSong.hxx" #include "SongPrint.hxx" #include "TagPrint.hxx" @@ -31,21 +33,21 @@ #include "tag/TagHandler.hxx" #include "TimePrint.hxx" #include "decoder/DecoderPrint.hxx" -#include "protocol/ArgParser.hxx" -#include "protocol/Result.hxx" #include "ls.hxx" #include "mixer/Volume.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/StringAPI.hxx" #include "fs/AllocatedPath.hxx" #include "Stats.hxx" #include "Permission.hxx" #include "PlaylistFile.hxx" #include "db/PlaylistVector.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Partition.hxx" #include "Instance.hxx" #include "Idle.hxx" +#include "Log.hxx" #ifdef ENABLE_DATABASE #include "DatabaseCommands.hxx" @@ -57,52 +59,51 @@ #include static void -print_spl_list(Client &client, const PlaylistVector &list) +print_spl_list(Response &r, const PlaylistVector &list) { for (const auto &i : list) { - client_printf(client, "playlist: %s\n", i.name.c_str()); + r.Format("playlist: %s\n", i.name.c_str()); if (i.mtime > 0) - time_print(client, "Last-Modified", i.mtime); + time_print(r, "Last-Modified", i.mtime); } } CommandResult -handle_urlhandlers(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_urlhandlers(Client &client, gcc_unused Request args, Response &r) { if (client.IsLocal()) - client_puts(client, "handler: file://\n"); - print_supported_uri_schemes(client); + r.Format("handler: file://\n"); + print_supported_uri_schemes(r); return CommandResult::OK; } CommandResult -handle_decoders(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_decoders(gcc_unused Client &client, gcc_unused Request args, + Response &r) { - decoder_list_print(client); + decoder_list_print(r); return CommandResult::OK; } CommandResult -handle_tagtypes(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_tagtypes(gcc_unused Client &client, gcc_unused Request request, + Response &r) { - tag_print_types(client); + tag_print_types(r); return CommandResult::OK; } CommandResult -handle_kill(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_kill(gcc_unused Client &client, gcc_unused Request request, + gcc_unused Response &r) { return CommandResult::KILL; } CommandResult -handle_close(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_close(gcc_unused Client &client, gcc_unused Request args, + gcc_unused Response &r) { return CommandResult::FINISH; } @@ -110,115 +111,94 @@ static void print_tag(TagType type, const char *value, void *ctx) { - Client &client = *(Client *)ctx; + auto &r = *(Response *)ctx; - tag_print(client, type, value); + tag_print(r, type, value); } CommandResult -handle_listfiles(Client &client, unsigned argc, char *argv[]) +handle_listfiles(Client &client, Request args, Response &r) { - const char *const uri = argc == 2 - ? argv[1] - /* default is root directory */ - : ""; + /* default is root directory */ + const auto uri = args.GetOptional(0, ""); - if (memcmp(uri, "file:///", 8) == 0) - /* list local directory */ - return handle_listfiles_local(client, uri + 7); + const auto located_uri = LocateUri(uri, &client +#ifdef ENABLE_DATABASE + , nullptr +#endif + ); + switch (located_uri.type) { + case LocatedUri::Type::ABSOLUTE: #ifdef ENABLE_DATABASE - if (uri_has_scheme(uri)) /* use storage plugin to list remote directory */ - return handle_listfiles_storage(client, uri); - - /* must be a path relative to the configured - music_directory */ + return handle_listfiles_storage(r, located_uri.canonical_uri); +#else + r.Error(ACK_ERROR_NO_EXIST, "No database"); + return CommandResult::ERROR; +#endif - if (client.partition.instance.storage != nullptr) - /* if we have a storage instance, obtain a list of - files from it */ - return handle_listfiles_storage(client, - *client.partition.instance.storage, - uri); + case LocatedUri::Type::RELATIVE: +#ifdef ENABLE_DATABASE + if (client.partition.instance.storage != nullptr) + /* if we have a storage instance, obtain a list of + files from it */ + return handle_listfiles_storage(r, + *client.partition.instance.storage, + uri); - /* fall back to entries from database if we have no storage */ - return handle_listfiles_db(client, uri); + /* fall back to entries from database if we have no storage */ + return handle_listfiles_db(client, r, uri); #else - command_error(client, ACK_ERROR_NO_EXIST, "No database"); - return CommandResult::ERROR; + r.Error(ACK_ERROR_NO_EXIST, "No database"); + return CommandResult::ERROR; #endif + + case LocatedUri::Type::PATH: + /* list local directory */ + return handle_listfiles_local(r, located_uri.path); + } + + gcc_unreachable(); } -static constexpr tag_handler print_tag_handler = { +static constexpr TagHandler print_tag_handler = { nullptr, print_tag, nullptr, }; -CommandResult -handle_lsinfo(Client &client, unsigned argc, char *argv[]) +static CommandResult +handle_lsinfo_absolute(Response &r, const char *uri) { - const char *const uri = argc == 2 - ? argv[1] - /* default is root directory */ - : ""; - - if (memcmp(uri, "file:///", 8) == 0) { - /* print information about an arbitrary local file */ - const char *path_utf8 = uri + 7; - const auto path_fs = AllocatedPath::FromUTF8(path_utf8); - - if (path_fs.IsNull()) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported file name"); - return CommandResult::ERROR; - } - - Error error; - if (!client.AllowFile(path_fs, error)) - return print_error(client, error); - - DetachedSong song(path_utf8); - if (!song.Update()) { - command_error(client, ACK_ERROR_NO_EXIST, - "No such file"); - return CommandResult::ERROR; - } - - song_print_info(client, song); - return CommandResult::OK; + if (!tag_stream_scan(uri, print_tag_handler, &r)) { + r.Error(ACK_ERROR_NO_EXIST, "No such file"); + return CommandResult::ERROR; } - if (uri_has_scheme(uri)) { - if (!uri_supported_scheme(uri)) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported URI scheme"); - return CommandResult::ERROR; - } - - if (!tag_stream_scan(uri, print_tag_handler, &client)) { - command_error(client, ACK_ERROR_NO_EXIST, - "No such file"); - return CommandResult::ERROR; - } - - return CommandResult::OK; - } + return CommandResult::OK; +} +static CommandResult +handle_lsinfo_relative(Client &client, Response &r, const char *uri) +{ #ifdef ENABLE_DATABASE - CommandResult result = handle_lsinfo2(client, argc, argv); + CommandResult result = handle_lsinfo2(client, uri, r); if (result != CommandResult::OK) return result; +#else + (void)client; #endif if (isRootDirectory(uri)) { - Error error; - const auto &list = ListPlaylistFiles(error); - print_spl_list(client, list); + try { + print_spl_list(r, ListPlaylistFiles()); + } catch (const std::exception &e) { + LogError(e); + } } else { #ifndef ENABLE_DATABASE - command_error(client, ACK_ERROR_NO_EXIST, "No database"); + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; #endif } @@ -226,38 +206,84 @@ return CommandResult::OK; } +static CommandResult +handle_lsinfo_path(Client &client, Response &r, + const char *path_utf8, Path path_fs) +{ + DetachedSong song(path_utf8); + if (!song.LoadFile(path_fs)) { + r.Error(ACK_ERROR_NO_EXIST, "No such file"); + return CommandResult::ERROR; + } + + song_print_info(r, client.partition, song); + return CommandResult::OK; +} + +CommandResult +handle_lsinfo(Client &client, Request args, Response &r) +{ + /* default is root directory */ + auto uri = args.GetOptional(0, ""); + if (StringIsEqual(uri, "/")) + /* this URI is malformed, but some clients are buggy + and use "lsinfo /" to list files in the music root + directory, which was never intended to work, but + once did; in order to retain backwards + compatibility, work around this here */ + uri = ""; + + const auto located_uri = LocateUri(uri, &client +#ifdef ENABLE_DATABASE + , nullptr +#endif + ); + + switch (located_uri.type) { + case LocatedUri::Type::ABSOLUTE: + return handle_lsinfo_absolute(r, located_uri.canonical_uri); + + case LocatedUri::Type::RELATIVE: + return handle_lsinfo_relative(client, r, + located_uri.canonical_uri); + + case LocatedUri::Type::PATH: + /* print information about an arbitrary local file */ + return handle_lsinfo_path(client, r, located_uri.canonical_uri, + located_uri.path); + } + + gcc_unreachable(); +} + #ifdef ENABLE_DATABASE static CommandResult -handle_update(Client &client, UpdateService &update, +handle_update(Response &r, UpdateService &update, const char *uri_utf8, bool discard) { unsigned ret = update.Enqueue(uri_utf8, discard); if (ret > 0) { - client_printf(client, "updating_db: %i\n", ret); + r.Format("updating_db: %i\n", ret); return CommandResult::OK; } else { - command_error(client, ACK_ERROR_UPDATE_ALREADY, - "already updating"); + r.Error(ACK_ERROR_UPDATE_ALREADY, "already updating"); return CommandResult::ERROR; } } static CommandResult -handle_update(Client &client, Database &db, +handle_update(Response &r, Database &db, const char *uri_utf8, bool discard) { - Error error; - unsigned id = db.Update(uri_utf8, discard, error); + unsigned id = db.Update(uri_utf8, discard); if (id > 0) { - client_printf(client, "updating_db: %i\n", id); + r.Format("updating_db: %i\n", id); return CommandResult::OK; - } else if (error.IsDefined()) { - return print_error(client, error); } else { /* Database::Update() has returned 0 without setting the Error: the method is not implemented */ - command_error(client, ACK_ERROR_NO_EXIST, "Not implemented"); + r.Error(ACK_ERROR_NO_EXIST, "Not implemented"); return CommandResult::ERROR; } } @@ -265,72 +291,60 @@ #endif static CommandResult -handle_update(Client &client, unsigned argc, char *argv[], bool discard) +handle_update(Client &client, Request args, Response &r, bool discard) { #ifdef ENABLE_DATABASE const char *path = ""; - assert(argc <= 2); - if (argc == 2) { - path = argv[1]; + assert(args.size <= 1); + if (!args.IsEmpty()) { + path = args.front(); - if (*path == 0 || strcmp(path, "/") == 0) + if (*path == 0 || StringIsEqual(path, "/")) /* backwards compatibility with MPD 0.15 */ path = ""; else if (!uri_safe_local(path)) { - command_error(client, ACK_ERROR_ARG, - "Malformed path"); + r.Error(ACK_ERROR_ARG, "Malformed path"); return CommandResult::ERROR; } } UpdateService *update = client.partition.instance.update; if (update != nullptr) - return handle_update(client, *update, path, discard); + return handle_update(r, *update, path, discard); Database *db = client.partition.instance.database; if (db != nullptr) - return handle_update(client, *db, path, discard); + return handle_update(r, *db, path, discard); #else - (void)argc; - (void)argv; + (void)client; + (void)args; (void)discard; #endif - command_error(client, ACK_ERROR_NO_EXIST, "No database"); + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; } CommandResult -handle_update(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_update(Client &client, Request args, gcc_unused Response &r) { - return handle_update(client, argc, argv, false); + return handle_update(client, args, r, false); } CommandResult -handle_rescan(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_rescan(Client &client, Request args, Response &r) { - return handle_update(client, argc, argv, true); + return handle_update(client, args, r, true); } CommandResult -handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_setvol(Client &client, Request args, Response &r) { - unsigned level; - bool success; - - if (!check_unsigned(client, &level, argv[1])) - return CommandResult::ERROR; + unsigned level = args.ParseUnsigned(0, 100); - if (level > 100) { - command_error(client, ACK_ERROR_ARG, "Invalid volume value"); - return CommandResult::ERROR; - } - - success = volume_level_change(client.partition.outputs, level); - if (!success) { - command_error(client, ACK_ERROR_SYSTEM, - "problems setting volume"); + if (!volume_level_change(client.partition.outputs, level)) { + r.Error(ACK_ERROR_SYSTEM, "problems setting volume"); return CommandResult::ERROR; } @@ -338,20 +352,13 @@ } CommandResult -handle_volume(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_volume(Client &client, Request args, Response &r) { - int relative; - if (!check_int(client, &relative, argv[1])) - return CommandResult::ERROR; - - if (relative < -100 || relative > 100) { - command_error(client, ACK_ERROR_ARG, "Invalid volume value"); - return CommandResult::ERROR; - } + int relative = args.ParseInt(0, -100, 100); const int old_volume = volume_level_get(client.partition.outputs); if (old_volume < 0) { - command_error(client, ACK_ERROR_SYSTEM, "No mixer"); + r.Error(ACK_ERROR_SYSTEM, "No mixer"); return CommandResult::ERROR; } @@ -363,8 +370,7 @@ if (new_volume != old_volume && !volume_level_change(client.partition.outputs, new_volume)) { - command_error(client, ACK_ERROR_SYSTEM, - "problems setting volume"); + r.Error(ACK_ERROR_SYSTEM, "problems setting volume"); return CommandResult::ERROR; } @@ -372,27 +378,25 @@ } CommandResult -handle_stats(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_stats(Client &client, gcc_unused Request args, Response &r) { - stats_print(client); + stats_print(r, client.partition); return CommandResult::OK; } CommandResult -handle_ping(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_ping(gcc_unused Client &client, gcc_unused Request args, + gcc_unused Response &r) { return CommandResult::OK; } CommandResult -handle_password(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_password(Client &client, Request args, Response &r) { unsigned permission = 0; - - if (getPermissionFromPassword(argv[1], &permission) < 0) { - command_error(client, ACK_ERROR_PASSWORD, "incorrect password"); + if (getPermissionFromPassword(args.front(), &permission) < 0) { + r.Error(ACK_ERROR_PASSWORD, "incorrect password"); return CommandResult::ERROR; } @@ -402,12 +406,11 @@ } CommandResult -handle_config(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_config(Client &client, gcc_unused Request args, Response &r) { if (!client.IsLocal()) { - command_error(client, ACK_ERROR_PERMISSION, - "Command only permitted to local clients"); + r.Error(ACK_ERROR_PERMISSION, + "Command only permitted to local clients"); return CommandResult::ERROR; } @@ -415,7 +418,7 @@ const Storage *storage = client.GetStorage(); if (storage != nullptr) { const auto path = storage->MapUTF8(""); - client_printf(client, "music_directory: %s\n", path.c_str()); + r.Format("music_directory: %s\n", path.c_str()); } #endif @@ -423,17 +426,14 @@ } CommandResult -handle_idle(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_idle(Client &client, Request args, Response &r) { unsigned flags = 0; - - for (unsigned i = 1; i < argc; ++i) { - unsigned event = idle_parse_name(argv[i]); + for (const char *i : args) { + unsigned event = idle_parse_name(i); if (event == 0) { - command_error(client, ACK_ERROR_ARG, - "Unrecognized idle event: %s", - argv[i]); + r.FormatError(ACK_ERROR_ARG, + "Unrecognized idle event: %s", i); return CommandResult::ERROR; } diff -Nru mpd-0.19.21/src/command/OtherCommands.hxx mpd-0.20.9/src/command/OtherCommands.hxx --- mpd-0.19.21/src/command/OtherCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/OtherCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,53 +23,55 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_urlhandlers(Client &client, unsigned argc, char *argv[]); +handle_urlhandlers(Client &client, Request request, Response &response); CommandResult -handle_decoders(Client &client, unsigned argc, char *argv[]); +handle_decoders(Client &client, Request request, Response &response); CommandResult -handle_tagtypes(Client &client, unsigned argc, char *argv[]); +handle_tagtypes(Client &client, Request request, Response &response); CommandResult -handle_kill(Client &client, unsigned argc, char *argv[]); +handle_kill(Client &client, Request request, Response &response); CommandResult -handle_close(Client &client, unsigned argc, char *argv[]); +handle_close(Client &client, Request request, Response &response); CommandResult -handle_listfiles(Client &client, unsigned argc, char *argv[]); +handle_listfiles(Client &client, Request request, Response &response); CommandResult -handle_lsinfo(Client &client, unsigned argc, char *argv[]); +handle_lsinfo(Client &client, Request request, Response &response); CommandResult -handle_update(Client &client, unsigned argc, char *argv[]); +handle_update(Client &client, Request request, Response &response); CommandResult -handle_rescan(Client &client, unsigned argc, char *argv[]); +handle_rescan(Client &client, Request request, Response &response); CommandResult -handle_setvol(Client &client, unsigned argc, char *argv[]); +handle_setvol(Client &client, Request request, Response &response); CommandResult -handle_volume(Client &client, unsigned argc, char *argv[]); +handle_volume(Client &client, Request request, Response &response); CommandResult -handle_stats(Client &client, unsigned argc, char *argv[]); +handle_stats(Client &client, Request request, Response &response); CommandResult -handle_ping(Client &client, unsigned argc, char *argv[]); +handle_ping(Client &client, Request request, Response &response); CommandResult -handle_password(Client &client, unsigned argc, char *argv[]); +handle_password(Client &client, Request request, Response &response); CommandResult -handle_config(Client &client, unsigned argc, char *argv[]); +handle_config(Client &client, Request request, Response &response); CommandResult -handle_idle(Client &client, unsigned argc, char *argv[]); +handle_idle(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/OutputCommands.cxx mpd-0.20.9/src/command/OutputCommands.cxx --- mpd-0.19.21/src/command/OutputCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/OutputCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,23 +19,21 @@ #include "config.h" #include "OutputCommands.hxx" +#include "Request.hxx" #include "output/OutputPrint.hxx" #include "output/OutputCommand.hxx" -#include "protocol/Result.hxx" -#include "protocol/ArgParser.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Partition.hxx" CommandResult -handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_enableoutput(Client &client, Request args, Response &r) { - unsigned device; - if (!check_unsigned(client, &device, argv[1])) - return CommandResult::ERROR; + assert(args.size == 1); + unsigned device = args.ParseUnsigned(0); if (!audio_output_enable_index(client.partition.outputs, device)) { - command_error(client, ACK_ERROR_NO_EXIST, - "No such audio output"); + r.Error(ACK_ERROR_NO_EXIST, "No such audio output"); return CommandResult::ERROR; } @@ -43,15 +41,13 @@ } CommandResult -handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_disableoutput(Client &client, Request args, Response &r) { - unsigned device; - if (!check_unsigned(client, &device, argv[1])) - return CommandResult::ERROR; + assert(args.size == 1); + unsigned device = args.ParseUnsigned(0); if (!audio_output_disable_index(client.partition.outputs, device)) { - command_error(client, ACK_ERROR_NO_EXIST, - "No such audio output"); + r.Error(ACK_ERROR_NO_EXIST, "No such audio output"); return CommandResult::ERROR; } @@ -59,15 +55,13 @@ } CommandResult -handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_toggleoutput(Client &client, Request args, Response &r) { - unsigned device; - if (!check_unsigned(client, &device, argv[1])) - return CommandResult::ERROR; + assert(args.size == 1); + unsigned device = args.ParseUnsigned(0); if (!audio_output_toggle_index(client.partition.outputs, device)) { - command_error(client, ACK_ERROR_NO_EXIST, - "No such audio output"); + r.Error(ACK_ERROR_NO_EXIST, "No such audio output"); return CommandResult::ERROR; } @@ -75,10 +69,10 @@ } CommandResult -handle_devices(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_devices(Client &client, gcc_unused Request args, Response &r) { - printAudioDevices(client, client.partition.outputs); + assert(args.IsEmpty()); + printAudioDevices(r, client.partition.outputs); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/OutputCommands.hxx mpd-0.20.9/src/command/OutputCommands.hxx --- mpd-0.19.21/src/command/OutputCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/OutputCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,17 +23,19 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_enableoutput(Client &client, unsigned argc, char *argv[]); +handle_enableoutput(Client &client, Request request, Response &response); CommandResult -handle_disableoutput(Client &client, unsigned argc, char *argv[]); +handle_disableoutput(Client &client, Request request, Response &response); CommandResult -handle_toggleoutput(Client &client, unsigned argc, char *argv[]); +handle_toggleoutput(Client &client, Request request, Response &response); CommandResult -handle_devices(Client &client, unsigned argc, char *argv[]); +handle_devices(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/PlayerCommands.cxx mpd-0.20.9/src/command/PlayerCommands.cxx --- mpd-0.19.21/src/command/PlayerCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/PlayerCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,17 +19,20 @@ #include "config.h" #include "PlayerCommands.hxx" +#include "Request.hxx" #include "CommandError.hxx" #include "queue/Playlist.hxx" #include "PlaylistPrint.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "mixer/Volume.hxx" #include "Partition.hxx" #include "Instance.hxx" -#include "protocol/Result.hxx" -#include "protocol/ArgParser.hxx" +#include "Idle.hxx" #include "AudioFormat.hxx" -#include "ReplayGainConfig.hxx" +#include "util/StringBuffer.hxx" +#include "util/ScopeExit.hxx" +#include "util/Exception.hxx" #ifdef ENABLE_DATABASE #include "db/update/Service.hxx" @@ -56,68 +59,56 @@ #define COMMAND_STATUS_UPDATING_DB "updating_db" CommandResult -handle_play(Client &client, unsigned argc, char *argv[]) +handle_play(Client &client, Request args, gcc_unused Response &r) { - int song = -1; + int song = args.ParseOptional(0, -1); - if (argc == 2 && !check_int(client, &song, argv[1])) - return CommandResult::ERROR; - PlaylistResult result = client.partition.PlayPosition(song); - return print_playlist_result(client, result); + client.partition.PlayPosition(song); + return CommandResult::OK; } CommandResult -handle_playid(Client &client, unsigned argc, char *argv[]) +handle_playid(Client &client, Request args, gcc_unused Response &r) { - int id = -1; - - if (argc == 2 && !check_int(client, &id, argv[1])) - return CommandResult::ERROR; + int id = args.ParseOptional(0, -1); - PlaylistResult result = client.partition.PlayId(id); - return print_playlist_result(client, result); + client.partition.PlayId(id); + return CommandResult::OK; } CommandResult -handle_stop(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_stop(Client &client, gcc_unused Request args, gcc_unused Response &r) { client.partition.Stop(); return CommandResult::OK; } CommandResult -handle_currentsong(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_currentsong(Client &client, gcc_unused Request args, Response &r) { - playlist_print_current(client, client.playlist); + playlist_print_current(r, client.partition, client.playlist); return CommandResult::OK; } CommandResult -handle_pause(Client &client, - unsigned argc, char *argv[]) +handle_pause(Client &client, Request args, gcc_unused Response &r) { - if (argc == 2) { - bool pause_flag; - if (!check_bool(client, &pause_flag, argv[1])) - return CommandResult::ERROR; - - client.player_control.SetPause(pause_flag); + if (!args.IsEmpty()) { + bool pause_flag = args.ParseBool(0); + client.player_control.LockSetPause(pause_flag); } else - client.player_control.Pause(); + client.player_control.LockPause(); return CommandResult::OK; } CommandResult -handle_status(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_status(Client &client, gcc_unused Request args, Response &r) { const char *state = nullptr; int song; - const auto player_status = client.player_control.GetStatus(); + const auto player_status = client.player_control.LockGetStatus(); switch (player_status.state) { case PlayerState::STOP: @@ -132,64 +123,58 @@ } const playlist &playlist = client.playlist; - client_printf(client, - "volume: %i\n" - COMMAND_STATUS_REPEAT ": %i\n" - COMMAND_STATUS_RANDOM ": %i\n" - COMMAND_STATUS_SINGLE ": %i\n" - COMMAND_STATUS_CONSUME ": %i\n" - COMMAND_STATUS_PLAYLIST ": %li\n" - COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" - COMMAND_STATUS_MIXRAMPDB ": %f\n" - COMMAND_STATUS_STATE ": %s\n", - volume_level_get(client.partition.outputs), - playlist.GetRepeat(), - playlist.GetRandom(), - playlist.GetSingle(), - playlist.GetConsume(), - (unsigned long)playlist.GetVersion(), - playlist.GetLength(), - client.player_control.GetMixRampDb(), - state); + r.Format("volume: %i\n" + COMMAND_STATUS_REPEAT ": %i\n" + COMMAND_STATUS_RANDOM ": %i\n" + COMMAND_STATUS_SINGLE ": %i\n" + COMMAND_STATUS_CONSUME ": %i\n" + COMMAND_STATUS_PLAYLIST ": %li\n" + COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" + COMMAND_STATUS_MIXRAMPDB ": %f\n" + COMMAND_STATUS_STATE ": %s\n", + volume_level_get(client.partition.outputs), + playlist.GetRepeat(), + playlist.GetRandom(), + playlist.GetSingle(), + playlist.GetConsume(), + (unsigned long)playlist.GetVersion(), + playlist.GetLength(), + client.player_control.GetMixRampDb(), + state); if (client.player_control.GetCrossFade() > 0) - client_printf(client, - COMMAND_STATUS_CROSSFADE ": %i\n", - int(client.player_control.GetCrossFade() + 0.5)); + r.Format(COMMAND_STATUS_CROSSFADE ": %i\n", + int(client.player_control.GetCrossFade() + 0.5)); if (client.player_control.GetMixRampDelay() > 0) - client_printf(client, - COMMAND_STATUS_MIXRAMPDELAY ": %f\n", - client.player_control.GetMixRampDelay()); + r.Format(COMMAND_STATUS_MIXRAMPDELAY ": %f\n", + client.player_control.GetMixRampDelay()); song = playlist.GetCurrentPosition(); if (song >= 0) { - client_printf(client, - COMMAND_STATUS_SONG ": %i\n" - COMMAND_STATUS_SONGID ": %u\n", - song, playlist.PositionToId(song)); + r.Format(COMMAND_STATUS_SONG ": %i\n" + COMMAND_STATUS_SONGID ": %u\n", + song, playlist.PositionToId(song)); } if (player_status.state != PlayerState::STOP) { - client_printf(client, - COMMAND_STATUS_TIME ": %i:%i\n" - "elapsed: %1.3f\n" - COMMAND_STATUS_BITRATE ": %u\n", - player_status.elapsed_time.RoundS(), - player_status.total_time.IsNegative() - ? 0u - : unsigned(player_status.total_time.RoundS()), - player_status.elapsed_time.ToDoubleS(), - player_status.bit_rate); - - if (player_status.audio_format.IsDefined()) { - struct audio_format_string af_string; - - client_printf(client, - COMMAND_STATUS_AUDIO ": %s\n", - audio_format_to_string(player_status.audio_format, - &af_string)); - } + r.Format(COMMAND_STATUS_TIME ": %i:%i\n" + "elapsed: %1.3f\n" + COMMAND_STATUS_BITRATE ": %u\n", + player_status.elapsed_time.RoundS(), + player_status.total_time.IsNegative() + ? 0u + : unsigned(player_status.total_time.RoundS()), + player_status.elapsed_time.ToDoubleS(), + player_status.bit_rate); + + if (!player_status.total_time.IsNegative()) + r.Format("duration: %1.3f\n", + player_status.total_time.ToDoubleS()); + + if (player_status.audio_format.IsDefined()) + r.Format(COMMAND_STATUS_AUDIO ": %s\n", + ToString(player_status.audio_format).c_str()); } #ifdef ENABLE_DATABASE @@ -198,32 +183,29 @@ ? update_service->GetId() : 0; if (updateJobId != 0) { - client_printf(client, - COMMAND_STATUS_UPDATING_DB ": %i\n", - updateJobId); + r.Format(COMMAND_STATUS_UPDATING_DB ": %i\n", + updateJobId); } #endif - Error error = client.player_control.LockGetError(); - if (error.IsDefined()) - client_printf(client, - COMMAND_STATUS_ERROR ": %s\n", - error.GetMessage()); + try { + client.player_control.LockCheckRethrowError(); + } catch (...) { + r.Format(COMMAND_STATUS_ERROR ": %s\n", + FullMessage(std::current_exception()).c_str()); + } song = playlist.GetNextPosition(); - if (song >= 0) { - client_printf(client, - COMMAND_STATUS_NEXTSONG ": %i\n" - COMMAND_STATUS_NEXTSONGID ": %u\n", - song, playlist.PositionToId(song)); - } + if (song >= 0) + r.Format(COMMAND_STATUS_NEXTSONG ": %i\n" + COMMAND_STATUS_NEXTSONGID ": %u\n", + song, playlist.PositionToId(song)); return CommandResult::OK; } CommandResult -handle_next(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_next(Client &client, gcc_unused Request args, gcc_unused Response &r) { playlist &playlist = client.playlist; @@ -232,174 +214,132 @@ const bool single = playlist.queue.single; playlist.queue.single = false; - client.partition.PlayNext(); + AtScopeExit(&playlist, single) { + playlist.queue.single = single; + }; - playlist.queue.single = single; + client.partition.PlayNext(); return CommandResult::OK; } CommandResult -handle_previous(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_previous(Client &client, gcc_unused Request args, + gcc_unused Response &r) { client.partition.PlayPrevious(); return CommandResult::OK; } CommandResult -handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_repeat(Client &client, Request args, gcc_unused Response &r) { - bool status; - if (!check_bool(client, &status, argv[1])) - return CommandResult::ERROR; - + bool status = args.ParseBool(0); client.partition.SetRepeat(status); return CommandResult::OK; } CommandResult -handle_single(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_single(Client &client, Request args, gcc_unused Response &r) { - bool status; - if (!check_bool(client, &status, argv[1])) - return CommandResult::ERROR; - + bool status = args.ParseBool(0); client.partition.SetSingle(status); return CommandResult::OK; } CommandResult -handle_consume(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_consume(Client &client, Request args, gcc_unused Response &r) { - bool status; - if (!check_bool(client, &status, argv[1])) - return CommandResult::ERROR; - + bool status = args.ParseBool(0); client.partition.SetConsume(status); return CommandResult::OK; } CommandResult -handle_random(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_random(Client &client, Request args, gcc_unused Response &r) { - bool status; - if (!check_bool(client, &status, argv[1])) - return CommandResult::ERROR; - + bool status = args.ParseBool(0); client.partition.SetRandom(status); - client.partition.outputs.SetReplayGainMode(replay_gain_get_real_mode(client.partition.GetRandom())); + client.partition.UpdateEffectiveReplayGainMode(); return CommandResult::OK; } CommandResult -handle_clearerror(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_clearerror(Client &client, gcc_unused Request args, + gcc_unused Response &r) { - client.player_control.ClearError(); + client.player_control.LockClearError(); return CommandResult::OK; } CommandResult -handle_seek(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_seek(Client &client, Request args, gcc_unused Response &r) { - unsigned song; - SongTime seek_time; + unsigned song = args.ParseUnsigned(0); + SongTime seek_time = args.ParseSongTime(1); - if (!check_unsigned(client, &song, argv[1])) - return CommandResult::ERROR; - if (!ParseCommandArg(client, seek_time, argv[2])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.SeekSongPosition(song, seek_time); - return print_playlist_result(client, result); + client.partition.SeekSongPosition(song, seek_time); + return CommandResult::OK; } CommandResult -handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_seekid(Client &client, Request args, gcc_unused Response &r) { - unsigned id; - SongTime seek_time; + unsigned id = args.ParseUnsigned(0); + SongTime seek_time = args.ParseSongTime(1); - if (!check_unsigned(client, &id, argv[1])) - return CommandResult::ERROR; - if (!ParseCommandArg(client, seek_time, argv[2])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.SeekSongId(id, seek_time); - return print_playlist_result(client, result); + client.partition.SeekSongId(id, seek_time); + return CommandResult::OK; } CommandResult -handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_seekcur(Client &client, Request args, gcc_unused Response &r) { - const char *p = argv[1]; + const char *p = args.front(); bool relative = *p == '+' || *p == '-'; - SignedSongTime seek_time; - if (!ParseCommandArg(client, seek_time, p)) - return CommandResult::ERROR; + SignedSongTime seek_time = ParseCommandArgSignedSongTime(p); - PlaylistResult result = - client.partition.SeekCurrent(seek_time, relative); - return print_playlist_result(client, result); + client.partition.SeekCurrent(seek_time, relative); + return CommandResult::OK; } CommandResult -handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_crossfade(Client &client, Request args, gcc_unused Response &r) { - unsigned xfade_time; - - if (!check_unsigned(client, &xfade_time, argv[1])) - return CommandResult::ERROR; + unsigned xfade_time = args.ParseUnsigned(0); client.player_control.SetCrossFade(xfade_time); - return CommandResult::OK; } CommandResult -handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_mixrampdb(Client &client, Request args, gcc_unused Response &r) { - float db; - - if (!check_float(client, &db, argv[1])) - return CommandResult::ERROR; + float db = args.ParseFloat(0); client.player_control.SetMixRampDb(db); - return CommandResult::OK; } CommandResult -handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_mixrampdelay(Client &client, Request args, gcc_unused Response &r) { - float delay_secs; - - if (!check_float(client, &delay_secs, argv[1])) - return CommandResult::ERROR; + float delay_secs = args.ParseFloat(0); client.player_control.SetMixRampDelay(delay_secs); - return CommandResult::OK; } CommandResult -handle_replay_gain_mode(Client &client, - gcc_unused unsigned argc, char *argv[]) +handle_replay_gain_mode(Client &client, Request args, Response &) { - if (!replay_gain_set_mode_string(argv[1])) { - command_error(client, ACK_ERROR_ARG, - "Unrecognized replay gain mode"); - return CommandResult::ERROR; - } - - client.partition.outputs.SetReplayGainMode(replay_gain_get_real_mode(client.playlist.queue.random)); + auto new_mode = FromString(args.front()); + client.partition.SetReplayGainMode(new_mode); + client.partition.EmitIdle(IDLE_OPTIONS); return CommandResult::OK; } CommandResult -handle_replay_gain_status(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_replay_gain_status(Client &client, gcc_unused Request args, + Response &r) { - client_printf(client, "replay_gain_mode: %s\n", - replay_gain_get_mode_string()); + r.Format("replay_gain_mode: %s\n", + ToString(client.partition.replay_gain_mode)); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/PlayerCommands.hxx mpd-0.20.9/src/command/PlayerCommands.hxx --- mpd-0.19.21/src/command/PlayerCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/PlayerCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,68 +23,70 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_play(Client &client, unsigned argc, char *argv[]); +handle_play(Client &client, Request request, Response &response); CommandResult -handle_playid(Client &client, unsigned argc, char *argv[]); +handle_playid(Client &client, Request request, Response &response); CommandResult -handle_stop(Client &client, unsigned argc, char *argv[]); +handle_stop(Client &client, Request request, Response &response); CommandResult -handle_currentsong(Client &client, unsigned argc, char *argv[]); +handle_currentsong(Client &client, Request request, Response &response); CommandResult -handle_pause(Client &client, unsigned argc, char *argv[]); +handle_pause(Client &client, Request request, Response &response); CommandResult -handle_status(Client &client, unsigned argc, char *argv[]); +handle_status(Client &client, Request request, Response &response); CommandResult -handle_next(Client &client, unsigned argc, char *argv[]); +handle_next(Client &client, Request request, Response &response); CommandResult -handle_previous(Client &client, unsigned argc, char *avg[]); +handle_previous(Client &client, Request request, Response &response); CommandResult -handle_repeat(Client &client, unsigned argc, char *argv[]); +handle_repeat(Client &client, Request request, Response &response); CommandResult -handle_single(Client &client, unsigned argc, char *argv[]); +handle_single(Client &client, Request request, Response &response); CommandResult -handle_consume(Client &client, unsigned argc, char *argv[]); +handle_consume(Client &client, Request request, Response &response); CommandResult -handle_random(Client &client, unsigned argc, char *argv[]); +handle_random(Client &client, Request request, Response &response); CommandResult -handle_clearerror(Client &client, unsigned argc, char *argv[]); +handle_clearerror(Client &client, Request request, Response &response); CommandResult -handle_seek(Client &client, unsigned argc, char *argv[]); +handle_seek(Client &client, Request request, Response &response); CommandResult -handle_seekid(Client &client, unsigned argc, char *argv[]); +handle_seekid(Client &client, Request request, Response &response); CommandResult -handle_seekcur(Client &client, unsigned argc, char *argv[]); +handle_seekcur(Client &client, Request request, Response &response); CommandResult -handle_crossfade(Client &client, unsigned argc, char *argv[]); +handle_crossfade(Client &client, Request request, Response &response); CommandResult -handle_mixrampdb(Client &client, unsigned argc, char *argv[]); +handle_mixrampdb(Client &client, Request request, Response &response); CommandResult -handle_mixrampdelay(Client &client, unsigned argc, char *argv[]); +handle_mixrampdelay(Client &client, Request request, Response &response); CommandResult -handle_replay_gain_mode(Client &client, unsigned argc, char *argv[]); +handle_replay_gain_mode(Client &client, Request request, Response &response); CommandResult -handle_replay_gain_status(Client &client, unsigned argc, char *argv[]); +handle_replay_gain_status(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/PlaylistCommands.cxx mpd-0.20.9/src/command/PlaylistCommands.cxx --- mpd-0.19.21/src/command/PlaylistCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/PlaylistCommands.cxx 2017-05-08 13:07:39.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,194 +19,168 @@ #include "config.h" #include "PlaylistCommands.hxx" +#include "Request.hxx" #include "db/DatabasePlaylist.hxx" #include "CommandError.hxx" -#include "PlaylistPrint.hxx" #include "PlaylistSave.hxx" #include "PlaylistFile.hxx" +#include "PlaylistError.hxx" #include "db/PlaylistVector.hxx" #include "SongLoader.hxx" #include "BulkEdit.hxx" #include "playlist/PlaylistQueue.hxx" #include "playlist/Print.hxx" -#include "queue/Playlist.hxx" #include "TimePrint.hxx" #include "client/Client.hxx" -#include "protocol/ArgParser.hxx" -#include "protocol/Result.hxx" -#include "ls.hxx" +#include "client/Response.hxx" +#include "Mapper.hxx" +#include "fs/AllocatedPath.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/ConstBuffer.hxx" + +bool +playlist_commands_available() noexcept +{ + return !map_spl_path().IsNull(); +} static void -print_spl_list(Client &client, const PlaylistVector &list) +print_spl_list(Response &r, const PlaylistVector &list) { for (const auto &i : list) { - client_printf(client, "playlist: %s\n", i.name.c_str()); + r.Format("playlist: %s\n", i.name.c_str()); if (i.mtime > 0) - time_print(client, "Last-Modified", i.mtime); + time_print(r, "Last-Modified", i.mtime); } } CommandResult -handle_save(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_save(Client &client, Request args, gcc_unused Response &r) { - PlaylistResult result = spl_save_playlist(argv[1], client.playlist); - return print_playlist_result(client, result); + spl_save_playlist(args.front(), client.playlist); + return CommandResult::OK; } CommandResult -handle_load(Client &client, unsigned argc, char *argv[]) +handle_load(Client &client, Request args, gcc_unused Response &r) { - unsigned start_index, end_index; - - if (argc < 3) { - start_index = 0; - end_index = unsigned(-1); - } else if (!check_range(client, &start_index, &end_index, argv[2])) - return CommandResult::ERROR; + RangeArg range = args.ParseOptional(1, RangeArg::All()); const ScopeBulkEdit bulk_edit(client.partition); - Error error; const SongLoader loader(client); - if (!playlist_open_into_queue(argv[1], - start_index, end_index, - client.playlist, - client.player_control, loader, error)) - return print_error(client, error); - + playlist_open_into_queue(args.front(), + range.start, range.end, + client.playlist, + client.player_control, loader); return CommandResult::OK; } CommandResult -handle_listplaylist(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_listplaylist(Client &client, Request args, Response &r) { - if (playlist_file_print(client, argv[1], false)) + const char *const name = args.front(); + + if (playlist_file_print(r, client.partition, SongLoader(client), + name, false)) return CommandResult::OK; - Error error; - return spl_print(client, argv[1], false, error) - ? CommandResult::OK - : print_error(client, error); + throw PlaylistError::NoSuchList(); } CommandResult -handle_listplaylistinfo(Client &client, - gcc_unused unsigned argc, char *argv[]) +handle_listplaylistinfo(Client &client, Request args, Response &r) { - if (playlist_file_print(client, argv[1], true)) + const char *const name = args.front(); + + if (playlist_file_print(r, client.partition, SongLoader(client), + name, true)) return CommandResult::OK; - Error error; - return spl_print(client, argv[1], true, error) - ? CommandResult::OK - : print_error(client, error); + throw PlaylistError::NoSuchList(); } CommandResult -handle_rm(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_rm(gcc_unused Client &client, Request args, gcc_unused Response &r) { - Error error; - return spl_delete(argv[1], error) - ? CommandResult::OK - : print_error(client, error); + const char *const name = args.front(); + + spl_delete(name); + return CommandResult::OK; } CommandResult -handle_rename(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_rename(gcc_unused Client &client, Request args, gcc_unused Response &r) { - Error error; - return spl_rename(argv[1], argv[2], error) - ? CommandResult::OK - : print_error(client, error); + const char *const old_name = args[0]; + const char *const new_name = args[1]; + + spl_rename(old_name, new_name); + return CommandResult::OK; } CommandResult -handle_playlistdelete(Client &client, - gcc_unused unsigned argc, char *argv[]) { - char *playlist = argv[1]; - unsigned from; - - if (!check_unsigned(client, &from, argv[2])) - return CommandResult::ERROR; +handle_playlistdelete(gcc_unused Client &client, + Request args, gcc_unused Response &r) +{ + const char *const name = args[0]; + unsigned from = args.ParseUnsigned(1); - Error error; - return spl_remove_index(playlist, from, error) - ? CommandResult::OK - : print_error(client, error); + spl_remove_index(name, from); + return CommandResult::OK; } CommandResult -handle_playlistmove(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_playlistmove(gcc_unused Client &client, + Request args, gcc_unused Response &r) { - char *playlist = argv[1]; - unsigned from, to; - - if (!check_unsigned(client, &from, argv[2])) - return CommandResult::ERROR; - if (!check_unsigned(client, &to, argv[3])) - return CommandResult::ERROR; + const char *const name = args.front(); + unsigned from = args.ParseUnsigned(1); + unsigned to = args.ParseUnsigned(2); - Error error; - return spl_move_index(playlist, from, to, error) - ? CommandResult::OK - : print_error(client, error); + spl_move_index(name, from, to); + return CommandResult::OK; } CommandResult -handle_playlistclear(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_playlistclear(gcc_unused Client &client, + Request args, gcc_unused Response &r) { - Error error; - return spl_clear(argv[1], error) - ? CommandResult::OK - : print_error(client, error); + const char *const name = args.front(); + + spl_clear(name); + return CommandResult::OK; } CommandResult -handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_playlistadd(Client &client, Request args, gcc_unused Response &r) { - char *playlist = argv[1]; - char *uri = argv[2]; + const char *const playlist = args[0]; + const char *const uri = args[1]; - bool success; - Error error; if (uri_has_scheme(uri)) { const SongLoader loader(client); - success = spl_append_uri(playlist, loader, uri, error); + spl_append_uri(playlist, loader, uri); } else { #ifdef ENABLE_DATABASE - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return print_error(client, error); - - success = search_add_to_playlist(*db, *client.GetStorage(), - uri, playlist, nullptr, - error); -#else - success = false; -#endif - } + const Database &db = client.GetDatabaseOrThrow(); - if (!success && !error.IsDefined()) { - command_error(client, ACK_ERROR_NO_EXIST, - "directory or file not found"); + search_add_to_playlist(db, *client.GetStorage(), + uri, playlist, nullptr); +#else + r.Error(ACK_ERROR_NO_EXIST, "directory or file not found"); return CommandResult::ERROR; +#endif } - return success ? CommandResult::OK : print_error(client, error); + return CommandResult::OK; } CommandResult -handle_listplaylists(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_listplaylists(gcc_unused Client &client, gcc_unused Request args, + Response &r) { - Error error; - const auto list = ListPlaylistFiles(error); - if (list.empty() && error.IsDefined()) - return print_error(client, error); - - print_spl_list(client, list); + print_spl_list(r, ListPlaylistFiles()); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/PlaylistCommands.hxx mpd-0.20.9/src/command/PlaylistCommands.hxx --- mpd-0.19.21/src/command/PlaylistCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/PlaylistCommands.hxx 2017-05-08 13:07:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,40 +21,47 @@ #define MPD_PLAYLIST_COMMANDS_HXX #include "CommandResult.hxx" +#include "Compiler.h" class Client; +class Request; +class Response; + +gcc_const +bool +playlist_commands_available() noexcept; CommandResult -handle_save(Client &client, unsigned argc, char *argv[]); +handle_save(Client &client, Request request, Response &response); CommandResult -handle_load(Client &client, unsigned argc, char *argv[]); +handle_load(Client &client, Request request, Response &response); CommandResult -handle_listplaylist(Client &client, unsigned argc, char *argv[]); +handle_listplaylist(Client &client, Request request, Response &response); CommandResult -handle_listplaylistinfo(Client &client, unsigned argc, char *argv[]); +handle_listplaylistinfo(Client &client, Request request, Response &response); CommandResult -handle_rm(Client &client, unsigned argc, char *argv[]); +handle_rm(Client &client, Request request, Response &response); CommandResult -handle_rename(Client &client, unsigned argc, char *argv[]); +handle_rename(Client &client, Request request, Response &response); CommandResult -handle_playlistdelete(Client &client, unsigned argc, char *argv[]); +handle_playlistdelete(Client &client, Request request, Response &response); CommandResult -handle_playlistmove(Client &client, unsigned argc, char *argv[]); +handle_playlistmove(Client &client, Request request, Response &response); CommandResult -handle_playlistclear(Client &client, unsigned argc, char *argv[]); +handle_playlistclear(Client &client, Request request, Response &response); CommandResult -handle_playlistadd(Client &client, unsigned argc, char *argv[]); +handle_playlistadd(Client &client, Request request, Response &response); CommandResult -handle_listplaylists(Client &client, unsigned argc, char *argv[]); +handle_listplaylists(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/QueueCommands.cxx mpd-0.20.9/src/command/QueueCommands.cxx --- mpd-0.19.21/src/command/QueueCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/QueueCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,50 +19,61 @@ #include "config.h" #include "QueueCommands.hxx" +#include "Request.hxx" #include "CommandError.hxx" #include "db/DatabaseQueue.hxx" #include "db/Selection.hxx" #include "SongFilter.hxx" #include "SongLoader.hxx" +#include "DetachedSong.hxx" +#include "LocateUri.hxx" #include "queue/Playlist.hxx" #include "PlaylistPrint.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Partition.hxx" #include "BulkEdit.hxx" -#include "protocol/ArgParser.hxx" -#include "protocol/Result.hxx" -#include "ls.hxx" #include "util/ConstBuffer.hxx" -#include "util/UriUtil.hxx" +#include "util/StringAPI.hxx" #include "util/NumberParser.hxx" -#include "util/Error.hxx" -#include "fs/AllocatedPath.hxx" +#include #include -#include +static void +AddUri(Client &client, const LocatedUri &uri) +{ + std::unique_ptr song(SongLoader(client).LoadSong(uri)); + assert(song); + + auto &partition = client.partition; + partition.playlist.AppendSong(partition.pc, std::move(*song)); +} -static const char * -translate_uri(Client &client, const char *uri) +static CommandResult +AddDatabaseSelection(Client &client, const char *uri, + gcc_unused Response &r) { - if (memcmp(uri, "file:///", 8) == 0) - /* drop the "file://", leave only an absolute path - (starting with a slash) */ - return uri + 7; - - if (PathTraitsUTF8::IsAbsolute(uri)) { - command_error(client, ACK_ERROR_NO_EXIST, "Malformed URI"); - return nullptr; - } +#ifdef ENABLE_DATABASE + const ScopeBulkEdit bulk_edit(client.partition); + + const DatabaseSelection selection(uri, true); + AddFromDatabase(client.partition, selection); + return CommandResult::OK; +#else + (void)client; + (void)uri; - return uri; + r.Error(ACK_ERROR_NO_EXIST, "No database"); + return CommandResult::ERROR; +#endif } CommandResult -handle_add(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_add(Client &client, Request args, Response &r) { - const char *uri = argv[1]; - if (memcmp(uri, "/", 2) == 0) + const char *uri = args.front(); + if (StringIsEqual(uri, "/")) /* this URI is malformed, but some clients are buggy and use "add /" to add the whole database, which was never intended to work, but once did; in order @@ -70,61 +81,46 @@ here */ uri = ""; - uri = translate_uri(client, uri); - if (uri == nullptr) - return CommandResult::ERROR; - - if (uri_has_scheme(uri) || PathTraitsUTF8::IsAbsolute(uri)) { - const SongLoader loader(client); - Error error; - unsigned id = client.partition.AppendURI(loader, uri, error); - if (id == 0) - return print_error(client, error); - + const auto located_uri = LocateUri(uri, &client +#ifdef ENABLE_DATABASE + , nullptr +#endif + ); + switch (located_uri.type) { + case LocatedUri::Type::ABSOLUTE: + case LocatedUri::Type::PATH: + AddUri(client, located_uri); return CommandResult::OK; - } -#ifdef ENABLE_DATABASE - const ScopeBulkEdit bulk_edit(client.partition); + case LocatedUri::Type::RELATIVE: + return AddDatabaseSelection(client, located_uri.canonical_uri, + r); + } - const DatabaseSelection selection(uri, true); - Error error; - return AddFromDatabase(client.partition, selection, error) - ? CommandResult::OK - : print_error(client, error); -#else - command_error(client, ACK_ERROR_NO_EXIST, "No database"); - return CommandResult::ERROR; -#endif + gcc_unreachable(); } CommandResult -handle_addid(Client &client, unsigned argc, char *argv[]) +handle_addid(Client &client, Request args, Response &r) { - const char *const uri = translate_uri(client, argv[1]); - if (uri == nullptr) - return CommandResult::ERROR; + const char *const uri = args.front(); const SongLoader loader(client); - Error error; - unsigned added_id = client.partition.AppendURI(loader, uri, error); - if (added_id == 0) - return print_error(client, error); - - if (argc == 3) { - unsigned to; - if (!check_unsigned(client, &to, argv[2])) - return CommandResult::ERROR; - PlaylistResult result = client.partition.MoveId(added_id, to); - if (result != PlaylistResult::SUCCESS) { - CommandResult ret = - print_playlist_result(client, result); + unsigned added_id = client.partition.AppendURI(loader, uri); + + if (args.size == 2) { + unsigned to = args.ParseUnsigned(1); + + try { + client.partition.MoveId(added_id, to); + } catch (...) { + /* rollback */ client.partition.DeleteId(added_id); - return ret; + throw; } } - client_printf(client, "Id: %u\n", added_id); + r.Format("Id: %u\n", added_id); return CommandResult::OK; } @@ -160,134 +156,99 @@ } CommandResult -handle_rangeid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_rangeid(Client &client, Request args, Response &r) { - unsigned id; - if (!check_unsigned(client, &id, argv[1])) - return CommandResult::ERROR; + unsigned id = args.ParseUnsigned(0); SongTime start, end; - if (!parse_time_range(argv[2], start, end)) { - command_error(client, ACK_ERROR_ARG, "Bad range"); + if (!parse_time_range(args[1], start, end)) { + r.Error(ACK_ERROR_ARG, "Bad range"); return CommandResult::ERROR; } - Error error; - if (!client.partition.playlist.SetSongIdRange(client.partition.pc, - id, start, end, - error)) - return print_error(client, error); - + client.partition.playlist.SetSongIdRange(client.partition.pc, + id, start, end); return CommandResult::OK; } CommandResult -handle_delete(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_delete(Client &client, Request args, gcc_unused Response &r) { - unsigned start, end; - - if (!check_range(client, &start, &end, argv[1])) - return CommandResult::ERROR; - - PlaylistResult result = client.partition.DeleteRange(start, end); - return print_playlist_result(client, result); + RangeArg range = args.ParseRange(0); + client.partition.DeleteRange(range.start, range.end); + return CommandResult::OK; } CommandResult -handle_deleteid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_deleteid(Client &client, Request args, gcc_unused Response &r) { - unsigned id; - - if (!check_unsigned(client, &id, argv[1])) - return CommandResult::ERROR; - - PlaylistResult result = client.partition.DeleteId(id); - return print_playlist_result(client, result); + unsigned id = args.ParseUnsigned(0); + client.partition.DeleteId(id); + return CommandResult::OK; } CommandResult -handle_playlist(Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_playlist(Client &client, gcc_unused Request args, Response &r) { - playlist_print_uris(client, client.playlist); + playlist_print_uris(r, client.partition, client.playlist); return CommandResult::OK; } CommandResult -handle_shuffle(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_shuffle(gcc_unused Client &client, Request args, gcc_unused Response &r) { - unsigned start = 0, end = client.playlist.queue.GetLength(); - if (argc == 2 && !check_range(client, &start, &end, argv[1])) - return CommandResult::ERROR; - - client.partition.Shuffle(start, end); + RangeArg range = args.ParseOptional(0, RangeArg::All()); + client.partition.Shuffle(range.start, range.end); return CommandResult::OK; } CommandResult -handle_clear(gcc_unused Client &client, - gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_clear(Client &client, gcc_unused Request args, gcc_unused Response &r) { client.partition.ClearQueue(); return CommandResult::OK; } CommandResult -handle_plchanges(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_plchanges(Client &client, Request args, Response &r) { - uint32_t version; - - if (!check_uint32(client, &version, argv[1])) - return CommandResult::ERROR; - - playlist_print_changes_info(client, client.playlist, version); + uint32_t version = ParseCommandArgU32(args.front()); + RangeArg range = args.ParseOptional(1, RangeArg::All()); + playlist_print_changes_info(r, client.partition, + client.playlist, version, + range.start, range.end); return CommandResult::OK; } CommandResult -handle_plchangesposid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_plchangesposid(Client &client, Request args, Response &r) { - uint32_t version; - - if (!check_uint32(client, &version, argv[1])) - return CommandResult::ERROR; - - playlist_print_changes_position(client, client.playlist, version); + uint32_t version = ParseCommandArgU32(args.front()); + RangeArg range = args.ParseOptional(1, RangeArg::All()); + playlist_print_changes_position(r, client.playlist, version, + range.start, range.end); return CommandResult::OK; } CommandResult -handle_playlistinfo(Client &client, unsigned argc, char *argv[]) +handle_playlistinfo(Client &client, Request args, Response &r) { - unsigned start = 0, end = std::numeric_limits::max(); - bool ret; - - if (argc == 2 && !check_range(client, &start, &end, argv[1])) - return CommandResult::ERROR; - - ret = playlist_print_info(client, client.playlist, start, end); - if (!ret) - return print_playlist_result(client, - PlaylistResult::BAD_RANGE); + RangeArg range = args.ParseOptional(0, RangeArg::All()); + playlist_print_info(r, client.partition, client.playlist, + range.start, range.end); return CommandResult::OK; } CommandResult -handle_playlistid(Client &client, unsigned argc, char *argv[]) +handle_playlistid(Client &client, Request args, Response &r) { - if (argc >= 2) { - unsigned id; - if (!check_unsigned(client, &id, argv[1])) - return CommandResult::ERROR; - - bool ret = playlist_print_id(client, client.playlist, id); - if (!ret) - return print_playlist_result(client, - PlaylistResult::NO_SUCH_SONG); + if (!args.IsEmpty()) { + unsigned id = args.ParseUnsigned(0); + playlist_print_id(r, client.partition, + client.playlist, id); } else { - playlist_print_info(client, client.playlist, + playlist_print_info(r, client.partition, client.playlist, 0, std::numeric_limits::max()); } @@ -295,147 +256,92 @@ } static CommandResult -handle_playlist_match(Client &client, unsigned argc, char *argv[], +handle_playlist_match(Client &client, Request args, Response &r, bool fold_case) { - ConstBuffer args(argv + 1, argc - 1); - SongFilter filter; if (!filter.Parse(args, fold_case)) { - command_error(client, ACK_ERROR_ARG, "incorrect arguments"); + r.Error(ACK_ERROR_ARG, "incorrect arguments"); return CommandResult::ERROR; } - playlist_print_find(client, client.playlist, filter); + playlist_print_find(r, client.partition, client.playlist, filter); return CommandResult::OK; } CommandResult -handle_playlistfind(Client &client, unsigned argc, char *argv[]) +handle_playlistfind(Client &client, Request args, Response &r) { - return handle_playlist_match(client, argc, argv, false); + return handle_playlist_match(client, args, r, false); } CommandResult -handle_playlistsearch(Client &client, unsigned argc, char *argv[]) +handle_playlistsearch(Client &client, Request args, Response &r) { - return handle_playlist_match(client, argc, argv, true); + return handle_playlist_match(client, args, r, true); } CommandResult -handle_prio(Client &client, unsigned argc, char *argv[]) +handle_prio(Client &client, Request args, gcc_unused Response &r) { - unsigned priority; - - if (!check_unsigned(client, &priority, argv[1])) - return CommandResult::ERROR; - - if (priority > 0xff) { - command_error(client, ACK_ERROR_ARG, - "Priority out of range: %s", argv[1]); - return CommandResult::ERROR; - } + unsigned priority = args.ParseUnsigned(0, 0xff); + args.shift(); - for (unsigned i = 2; i < argc; ++i) { - unsigned start_position, end_position; - if (!check_range(client, &start_position, &end_position, - argv[i])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.SetPriorityRange(start_position, - end_position, - priority); - if (result != PlaylistResult::SUCCESS) - return print_playlist_result(client, result); + for (const char *i : args) { + RangeArg range = ParseCommandArgRange(i); + client.partition.SetPriorityRange(range.start, range.end, + priority); } return CommandResult::OK; } CommandResult -handle_prioid(Client &client, unsigned argc, char *argv[]) +handle_prioid(Client &client, Request args, gcc_unused Response &r) { - unsigned priority; - - if (!check_unsigned(client, &priority, argv[1])) - return CommandResult::ERROR; - - if (priority > 0xff) { - command_error(client, ACK_ERROR_ARG, - "Priority out of range: %s", argv[1]); - return CommandResult::ERROR; - } + unsigned priority = args.ParseUnsigned(0, 0xff); + args.shift(); - for (unsigned i = 2; i < argc; ++i) { - unsigned song_id; - if (!check_unsigned(client, &song_id, argv[i])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.SetPriorityId(song_id, priority); - if (result != PlaylistResult::SUCCESS) - return print_playlist_result(client, result); + for (const char *i : args) { + unsigned song_id = ParseCommandArgUnsigned(i); + client.partition.SetPriorityId(song_id, priority); } return CommandResult::OK; } CommandResult -handle_move(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_move(Client &client, Request args, gcc_unused Response &r) { - unsigned start, end; - int to; - - if (!check_range(client, &start, &end, argv[1])) - return CommandResult::ERROR; - if (!check_int(client, &to, argv[2])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.MoveRange(start, end, to); - return print_playlist_result(client, result); + RangeArg range = args.ParseRange(0); + int to = args.ParseInt(1); + client.partition.MoveRange(range.start, range.end, to); + return CommandResult::OK; } CommandResult -handle_moveid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_moveid(Client &client, Request args, gcc_unused Response &r) { - unsigned id; - int to; - - if (!check_unsigned(client, &id, argv[1])) - return CommandResult::ERROR; - if (!check_int(client, &to, argv[2])) - return CommandResult::ERROR; - PlaylistResult result = client.partition.MoveId(id, to); - return print_playlist_result(client, result); + unsigned id = args.ParseUnsigned(0); + int to = args.ParseInt(1); + client.partition.MoveId(id, to); + return CommandResult::OK; } CommandResult -handle_swap(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_swap(Client &client, Request args, gcc_unused Response &r) { - unsigned song1, song2; - - if (!check_unsigned(client, &song1, argv[1])) - return CommandResult::ERROR; - if (!check_unsigned(client, &song2, argv[2])) - return CommandResult::ERROR; - - PlaylistResult result = - client.partition.SwapPositions(song1, song2); - return print_playlist_result(client, result); + unsigned song1 = args.ParseUnsigned(0); + unsigned song2 = args.ParseUnsigned(1); + client.partition.SwapPositions(song1, song2); + return CommandResult::OK; } CommandResult -handle_swapid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_swapid(Client &client, Request args, gcc_unused Response &r) { - unsigned id1, id2; - - if (!check_unsigned(client, &id1, argv[1])) - return CommandResult::ERROR; - if (!check_unsigned(client, &id2, argv[2])) - return CommandResult::ERROR; - - PlaylistResult result = client.partition.SwapIds(id1, id2); - return print_playlist_result(client, result); + unsigned id1 = args.ParseUnsigned(0); + unsigned id2 = args.ParseUnsigned(1); + client.partition.SwapIds(id1, id2); + return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/QueueCommands.hxx mpd-0.20.9/src/command/QueueCommands.hxx --- mpd-0.19.21/src/command/QueueCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/QueueCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,65 +23,67 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_add(Client &client, unsigned argc, char *argv[]); +handle_add(Client &client, Request request, Response &response); CommandResult -handle_addid(Client &client, unsigned argc, char *argv[]); +handle_addid(Client &client, Request request, Response &response); CommandResult -handle_rangeid(Client &client, unsigned argc, char *argv[]); +handle_rangeid(Client &client, Request request, Response &response); CommandResult -handle_delete(Client &client, unsigned argc, char *argv[]); +handle_delete(Client &client, Request request, Response &response); CommandResult -handle_deleteid(Client &client, unsigned argc, char *argv[]); +handle_deleteid(Client &client, Request request, Response &response); CommandResult -handle_playlist(Client &client, unsigned argc, char *argv[]); +handle_playlist(Client &client, Request request, Response &response); CommandResult -handle_shuffle(Client &client, unsigned argc, char *argv[]); +handle_shuffle(Client &client, Request request, Response &response); CommandResult -handle_clear(Client &client, unsigned argc, char *argv[]); +handle_clear(Client &client, Request request, Response &response); CommandResult -handle_plchanges(Client &client, unsigned argc, char *argv[]); +handle_plchanges(Client &client, Request request, Response &response); CommandResult -handle_plchangesposid(Client &client, unsigned argc, char *argv[]); +handle_plchangesposid(Client &client, Request request, Response &response); CommandResult -handle_playlistinfo(Client &client, unsigned argc, char *argv[]); +handle_playlistinfo(Client &client, Request request, Response &response); CommandResult -handle_playlistid(Client &client, unsigned argc, char *argv[]); +handle_playlistid(Client &client, Request request, Response &response); CommandResult -handle_playlistfind(Client &client, unsigned argc, char *argv[]); +handle_playlistfind(Client &client, Request request, Response &response); CommandResult -handle_playlistsearch(Client &client, unsigned argc, char *argv[]); +handle_playlistsearch(Client &client, Request request, Response &response); CommandResult -handle_prio(Client &client, unsigned argc, char *argv[]); +handle_prio(Client &client, Request request, Response &response); CommandResult -handle_prioid(Client &client, unsigned argc, char *argv[]); +handle_prioid(Client &client, Request request, Response &response); CommandResult -handle_move(Client &client, unsigned argc, char *argv[]); +handle_move(Client &client, Request request, Response &response); CommandResult -handle_moveid(Client &client, unsigned argc, char *argv[]); +handle_moveid(Client &client, Request request, Response &response); CommandResult -handle_swap(Client &client, unsigned argc, char *argv[]); +handle_swap(Client &client, Request request, Response &response); CommandResult -handle_swapid(Client &client, unsigned argc, char *argv[]); +handle_swapid(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/Request.hxx mpd-0.20.9/src/command/Request.hxx --- mpd-0.19.21/src/command/Request.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/command/Request.hxx 2017-06-03 19:58:12.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_REQUEST_HXX +#define MPD_REQUEST_HXX + +#include "check.h" +#include "protocol/ArgParser.hxx" +#include "Chrono.hxx" +#include "util/ConstBuffer.hxx" + +#include + +#include + +class Response; + +class Request : public ConstBuffer { + typedef ConstBuffer Base; + +public: + constexpr Request(const char *const*argv, size_type n) + :Base(argv, n) {} + + constexpr const char *GetOptional(unsigned idx, + const char *default_value=nullptr) const { + return idx < size + ? data[idx] + : default_value; + } + + int ParseInt(unsigned idx) const { + assert(idx < size); + return ParseCommandArgInt(data[idx]); + } + + int ParseInt(unsigned idx, int min_value, int max_value) const { + assert(idx < size); + return ParseCommandArgInt(data[idx], min_value, max_value); + } + + int ParseUnsigned(unsigned idx) const { + assert(idx < size); + return ParseCommandArgUnsigned(data[idx]); + } + + int ParseUnsigned(unsigned idx, unsigned max_value) const { + assert(idx < size); + return ParseCommandArgUnsigned(data[idx], max_value); + } + + bool ParseBool(unsigned idx) const { + assert(idx < size); + return ParseCommandArgBool(data[idx]); + } + + RangeArg ParseRange(unsigned idx) const { + assert(idx < size); + return ParseCommandArgRange(data[idx]); + } + + float ParseFloat(unsigned idx) const { + assert(idx < size); + return ParseCommandArgFloat(data[idx]); + } + + SongTime ParseSongTime(unsigned idx) const { + assert(idx < size); + return ParseCommandArgSongTime(data[idx]); + } + + SignedSongTime ParseSignedSongTime(unsigned idx) const { + assert(idx < size); + return ParseCommandArgSignedSongTime(data[idx]); + } + + int ParseOptional(unsigned idx, int default_value) const { + return idx < size + ? ParseInt(idx) + : default_value; + } + + RangeArg ParseOptional(unsigned idx, RangeArg default_value) const { + return idx < size + ? ParseRange(idx) + : default_value; + } +}; + +#endif diff -Nru mpd-0.19.21/src/command/StickerCommands.cxx mpd-0.20.9/src/command/StickerCommands.cxx --- mpd-0.19.21/src/command/StickerCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/StickerCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,23 +19,21 @@ #include "config.h" #include "StickerCommands.hxx" +#include "Request.hxx" #include "SongPrint.hxx" #include "db/Interface.hxx" -#include "db/DatabaseGlue.hxx" #include "sticker/SongSticker.hxx" #include "sticker/StickerPrint.hxx" #include "sticker/StickerDatabase.hxx" -#include "CommandError.hxx" -#include "protocol/Result.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Partition.hxx" -#include "Instance.hxx" -#include "util/Error.hxx" - -#include +#include "util/StringAPI.hxx" +#include "util/ScopeExit.hxx" struct sticker_song_find_data { - Client &client; + Response &r; + Partition &partition; const char *name; }; @@ -46,125 +44,128 @@ struct sticker_song_find_data *data = (struct sticker_song_find_data *)user_data; - song_print_uri(data->client, song); - sticker_print_value(data->client, data->name, value); + song_print_uri(data->r, data->partition, song); + sticker_print_value(data->r, data->name, value); } static CommandResult -handle_sticker_song(Client &client, unsigned argc, char *argv[]) +handle_sticker_song(Response &r, Partition &partition, Request args) { - Error error; - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return print_error(client, error); + const Database &db = partition.GetDatabaseOrThrow(); + + const char *const cmd = args.front(); /* get song song_id key */ - if (argc == 5 && strcmp(argv[1], "get") == 0) { - const LightSong *song = db->GetSong(argv[3], error); - if (song == nullptr) - return print_error(client, error); + if (args.size == 4 && StringIsEqual(cmd, "get")) { + const LightSong *song = db.GetSong(args[2]); + assert(song != nullptr); + AtScopeExit(&db, song) { db.ReturnSong(song); }; - const auto value = sticker_song_get_value(*song, argv[4]); - db->ReturnSong(song); + const auto value = sticker_song_get_value(*song, args[3]); if (value.empty()) { - command_error(client, ACK_ERROR_NO_EXIST, - "no such sticker"); + r.Error(ACK_ERROR_NO_EXIST, "no such sticker"); return CommandResult::ERROR; } - sticker_print_value(client, argv[4], value.c_str()); + sticker_print_value(r, args[3], value.c_str()); return CommandResult::OK; /* list song song_id */ - } else if (argc == 4 && strcmp(argv[1], "list") == 0) { - const LightSong *song = db->GetSong(argv[3], error); - if (song == nullptr) - return print_error(client, error); + } else if (args.size == 3 && StringIsEqual(cmd, "list")) { + const LightSong *song = db.GetSong(args[2]); + assert(song != nullptr); + AtScopeExit(&db, song) { db.ReturnSong(song); }; - sticker *sticker = sticker_song_get(*song); - db->ReturnSong(song); + Sticker *sticker = sticker_song_get(*song); if (sticker) { - sticker_print(client, *sticker); + sticker_print(r, *sticker); sticker_free(sticker); } return CommandResult::OK; /* set song song_id id key */ - } else if (argc == 6 && strcmp(argv[1], "set") == 0) { - const LightSong *song = db->GetSong(argv[3], error); - if (song == nullptr) - return print_error(client, error); - - bool ret = sticker_song_set_value(*song, argv[4], argv[5]); - db->ReturnSong(song); - if (!ret) { - command_error(client, ACK_ERROR_SYSTEM, - "failed to set sticker value"); - return CommandResult::ERROR; - } + } else if (args.size == 5 && StringIsEqual(cmd, "set")) { + const LightSong *song = db.GetSong(args[2]); + assert(song != nullptr); + AtScopeExit(&db, song) { db.ReturnSong(song); }; + sticker_song_set_value(*song, args[3], args[4]); return CommandResult::OK; /* delete song song_id [key] */ - } else if ((argc == 4 || argc == 5) && - strcmp(argv[1], "delete") == 0) { - const LightSong *song = db->GetSong(argv[3], error); - if (song == nullptr) - return print_error(client, error); + } else if ((args.size == 3 || args.size == 4) && + StringIsEqual(cmd, "delete")) { + const LightSong *song = db.GetSong(args[2]); + assert(song != nullptr); + AtScopeExit(&db, song) { db.ReturnSong(song); }; - bool ret = argc == 4 + bool ret = args.size == 3 ? sticker_song_delete(*song) - : sticker_song_delete_value(*song, argv[4]); - db->ReturnSong(song); + : sticker_song_delete_value(*song, args[3]); if (!ret) { - command_error(client, ACK_ERROR_SYSTEM, - "no such sticker"); + r.Error(ACK_ERROR_SYSTEM, "no such sticker"); return CommandResult::ERROR; } return CommandResult::OK; /* find song dir key */ - } else if (argc == 5 && strcmp(argv[1], "find") == 0) { + } else if ((args.size == 4 || args.size == 6) && + StringIsEqual(cmd, "find")) { /* "sticker find song a/directory name" */ - const char *const base_uri = argv[3]; + const char *const base_uri = args[2]; + + StickerOperator op = StickerOperator::EXISTS; + const char *value = nullptr; + + if (args.size == 6) { + /* match the value */ + + const char *op_s = args[4]; + value = args[5]; + + if (StringIsEqual(op_s, "=")) + op = StickerOperator::EQUALS; + else if (StringIsEqual(op_s, "<")) + op = StickerOperator::LESS_THAN; + else if (StringIsEqual(op_s, ">")) + op = StickerOperator::GREATER_THAN; + else { + r.Error(ACK_ERROR_ARG, "bad operator"); + return CommandResult::ERROR; + } + } - bool success; struct sticker_song_find_data data = { - client, - argv[4], + r, + partition, + args[3], }; - success = sticker_song_find(*db, base_uri, data.name, - sticker_song_find_print_cb, &data); - if (!success) { - command_error(client, ACK_ERROR_SYSTEM, - "failed to set search sticker database"); - return CommandResult::ERROR; - } + sticker_song_find(db, base_uri, data.name, + op, value, + sticker_song_find_print_cb, &data); return CommandResult::OK; } else { - command_error(client, ACK_ERROR_ARG, "bad request"); + r.Error(ACK_ERROR_ARG, "bad request"); return CommandResult::ERROR; } } CommandResult -handle_sticker(Client &client, unsigned argc, char *argv[]) +handle_sticker(Client &client, Request args, Response &r) { - assert(argc >= 4); + assert(args.size >= 3); if (!sticker_enabled()) { - command_error(client, ACK_ERROR_UNKNOWN, - "sticker database is disabled"); + r.Error(ACK_ERROR_UNKNOWN, "sticker database is disabled"); return CommandResult::ERROR; } - if (strcmp(argv[2], "song") == 0) - return handle_sticker_song(client, argc, argv); + if (StringIsEqual(args[1], "song")) + return handle_sticker_song(r, client.partition, args); else { - command_error(client, ACK_ERROR_ARG, - "unknown sticker domain"); + r.Error(ACK_ERROR_ARG, "unknown sticker domain"); return CommandResult::ERROR; } } diff -Nru mpd-0.19.21/src/command/StickerCommands.hxx mpd-0.20.9/src/command/StickerCommands.hxx --- mpd-0.19.21/src/command/StickerCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/StickerCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,8 +23,10 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_sticker(Client &client, unsigned argc, char *argv[]); +handle_sticker(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/StorageCommands.cxx mpd-0.20.9/src/command/StorageCommands.cxx --- mpd-0.19.21/src/command/StorageCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/StorageCommands.cxx 2017-05-08 14:12:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,12 +21,13 @@ #include "config.h" #include "StorageCommands.hxx" +#include "Request.hxx" #include "CommandError.hxx" -#include "protocol/Result.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/ConstBuffer.hxx" #include "fs/Traits.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" #include "Partition.hxx" #include "Instance.hxx" #include "storage/Registry.hxx" @@ -38,11 +39,13 @@ #include "IOThread.hxx" #include "Idle.hxx" +#include + #include /* for PRIu64 */ gcc_pure static bool -skip_path(const char *name_utf8) +skip_path(const char *name_utf8) noexcept { return strchr(name_utf8, '\n') != nullptr; } @@ -54,100 +57,75 @@ #pragma GCC diagnostic ignored "-Wformat-extra-args" #endif -static bool -handle_listfiles_storage(Client &client, StorageDirectoryReader &reader, - Error &error) +static void +handle_listfiles_storage(Response &r, StorageDirectoryReader &reader) { const char *name_utf8; while ((name_utf8 = reader.Read()) != nullptr) { if (skip_path(name_utf8)) continue; - FileInfo info; - if (!reader.GetInfo(false, info, error)) + StorageFileInfo info; + try { + info = reader.GetInfo(false); + } catch (const std::runtime_error &) { continue; + } switch (info.type) { - case FileInfo::Type::OTHER: + case StorageFileInfo::Type::OTHER: /* ignore */ continue; - case FileInfo::Type::REGULAR: - client_printf(client, "file: %s\n" - "size: %" PRIu64 "\n", - name_utf8, - info.size); + case StorageFileInfo::Type::REGULAR: + r.Format("file: %s\n" + "size: %" PRIu64 "\n", + name_utf8, + info.size); break; - case FileInfo::Type::DIRECTORY: - client_printf(client, "directory: %s\n", name_utf8); + case StorageFileInfo::Type::DIRECTORY: + r.Format("directory: %s\n", name_utf8); break; } if (info.mtime != 0) - time_print(client, "Last-Modified", info.mtime); + time_print(r, "Last-Modified", info.mtime); } - - return true; } #if defined(WIN32) && GCC_CHECK_VERSION(4,6) #pragma GCC diagnostic pop #endif -static bool -handle_listfiles_storage(Client &client, Storage &storage, const char *uri, - Error &error) -{ - auto reader = storage.OpenDirectory(uri, error); - if (reader == nullptr) - return false; - - bool success = handle_listfiles_storage(client, *reader, error); - delete reader; - return success; -} - CommandResult -handle_listfiles_storage(Client &client, Storage &storage, const char *uri) +handle_listfiles_storage(Response &r, Storage &storage, const char *uri) { - Error error; - if (!handle_listfiles_storage(client, storage, uri, error)) - return print_error(client, error); - + std::unique_ptr reader(storage.OpenDirectory(uri)); + handle_listfiles_storage(r, *reader); return CommandResult::OK; } CommandResult -handle_listfiles_storage(Client &client, const char *uri) +handle_listfiles_storage(Response &r, const char *uri) { - Error error; - Storage *storage = CreateStorageURI(io_thread_get(), uri, error); + std::unique_ptr storage(CreateStorageURI(io_thread_get(), uri)); if (storage == nullptr) { - if (error.IsDefined()) - return print_error(client, error); - - command_error(client, ACK_ERROR_ARG, - "Unrecognized storage URI"); + r.Error(ACK_ERROR_ARG, "Unrecognized storage URI"); return CommandResult::ERROR; } - bool success = handle_listfiles_storage(client, *storage, "", error); - delete storage; - if (!success) - return print_error(client, error); - - return CommandResult::OK; + return handle_listfiles_storage(r, *storage, ""); } static void -print_storage_uri(Client &client, const Storage &storage) +print_storage_uri(Client &client, Response &r, const Storage &storage) { std::string uri = storage.MapUTF8(""); if (uri.empty()) return; - if (PathTraitsFS::IsAbsolute(uri.c_str())) { + if (PathTraitsUTF8::IsAbsolute(uri.c_str())) { /* storage points to local directory */ if (!client.IsLocal()) @@ -163,24 +141,24 @@ uri = std::move(allocated); } - client_printf(client, "storage: %s\n", uri.c_str()); + r.Format("storage: %s\n", uri.c_str()); } CommandResult -handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *argv[]) +handle_listmounts(Client &client, gcc_unused Request args, Response &r) { Storage *_composite = client.partition.instance.storage; if (_composite == nullptr) { - command_error(client, ACK_ERROR_NO_EXIST, "No database"); + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; } CompositeStorage &composite = *(CompositeStorage *)_composite; - const auto visitor = [&client](const char *mount_uri, - const Storage &storage){ - client_printf(client, "mount: %s\n", mount_uri); - print_storage_uri(client, storage); + const auto visitor = [&client, &r](const char *mount_uri, + const Storage &storage){ + r.Format("mount: %s\n", mount_uri); + print_storage_uri(client, r, storage); }; composite.VisitMounts(visitor); @@ -189,21 +167,21 @@ } CommandResult -handle_mount(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_mount(Client &client, Request args, Response &r) { Storage *_composite = client.partition.instance.storage; if (_composite == nullptr) { - command_error(client, ACK_ERROR_NO_EXIST, "No database"); + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; } CompositeStorage &composite = *(CompositeStorage *)_composite; - const char *const local_uri = argv[1]; - const char *const remote_uri = argv[2]; + const char *const local_uri = args[0]; + const char *const remote_uri = args[1]; if (*local_uri == 0) { - command_error(client, ACK_ERROR_ARG, "Bad mount point"); + r.Error(ACK_ERROR_ARG, "Bad mount point"); return CommandResult::ERROR; } @@ -213,38 +191,34 @@ UpdateQueue::Erase() really gets called for every unmount, and no Directory disappears recursively during database update */ - command_error(client, ACK_ERROR_ARG, "Bad mount point"); + r.Error(ACK_ERROR_ARG, "Bad mount point"); return CommandResult::ERROR; } - Error error; - Storage *storage = CreateStorageURI(io_thread_get(), remote_uri, - error); + Storage *storage = CreateStorageURI(io_thread_get(), remote_uri); if (storage == nullptr) { - if (error.IsDefined()) - return print_error(client, error); - - command_error(client, ACK_ERROR_ARG, - "Unrecognized storage URI"); + r.Error(ACK_ERROR_ARG, "Unrecognized storage URI"); return CommandResult::ERROR; } composite.Mount(local_uri, storage); - idle_add(IDLE_MOUNT); + client.partition.EmitIdle(IDLE_MOUNT); #ifdef ENABLE_DATABASE Database *_db = client.partition.instance.database; if (_db != nullptr && _db->IsPlugin(simple_db_plugin)) { SimpleDatabase &db = *(SimpleDatabase *)_db; - if (!db.Mount(local_uri, remote_uri, error)) { + try { + db.Mount(local_uri, remote_uri); + } catch (...) { composite.Unmount(local_uri); - return print_error(client, error); + throw; } // TODO: call Instance::OnDatabaseModified()? // TODO: trigger database update? - idle_add(IDLE_DATABASE); + client.partition.EmitIdle(IDLE_DATABASE); } #endif @@ -252,20 +226,20 @@ } CommandResult -handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_unmount(Client &client, Request args, Response &r) { Storage *_composite = client.partition.instance.storage; if (_composite == nullptr) { - command_error(client, ACK_ERROR_NO_EXIST, "No database"); + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; } CompositeStorage &composite = *(CompositeStorage *)_composite; - const char *const local_uri = argv[1]; + const char *const local_uri = args.front(); if (*local_uri == 0) { - command_error(client, ACK_ERROR_ARG, "Bad mount point"); + r.Error(ACK_ERROR_ARG, "Bad mount point"); return CommandResult::ERROR; } @@ -282,16 +256,16 @@ if (db.Unmount(local_uri)) // TODO: call Instance::OnDatabaseModified()? - idle_add(IDLE_DATABASE); + client.partition.EmitIdle(IDLE_DATABASE); } #endif if (!composite.Unmount(local_uri)) { - command_error(client, ACK_ERROR_ARG, "Not a mount point"); + r.Error(ACK_ERROR_ARG, "Not a mount point"); return CommandResult::ERROR; } - idle_add(IDLE_MOUNT); + client.partition.EmitIdle(IDLE_MOUNT); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/StorageCommands.hxx mpd-0.20.9/src/command/StorageCommands.hxx --- mpd-0.19.21/src/command/StorageCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/StorageCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,20 +24,22 @@ class Client; class Storage; +class Request; +class Response; CommandResult -handle_listfiles_storage(Client &client, Storage &storage, const char *uri); +handle_listfiles_storage(Response &r, Storage &storage, const char *uri); CommandResult -handle_listfiles_storage(Client &client, const char *uri); +handle_listfiles_storage(Response &r, const char *uri); CommandResult -handle_listmounts(Client &client, unsigned argc, char *argv[]); +handle_listmounts(Client &client, Request request, Response &response); CommandResult -handle_mount(Client &client, unsigned argc, char *argv[]); +handle_mount(Client &client, Request request, Response &response); CommandResult -handle_unmount(Client &client, unsigned argc, char *argv[]); +handle_unmount(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/command/TagCommands.cxx mpd-0.20.9/src/command/TagCommands.cxx --- mpd-0.19.21/src/command/TagCommands.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/TagCommands.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,60 +19,47 @@ #include "config.h" #include "TagCommands.hxx" -#include "CommandError.hxx" +#include "Request.hxx" #include "client/Client.hxx" -#include "protocol/ArgParser.hxx" -#include "protocol/Result.hxx" +#include "client/Response.hxx" #include "tag/Tag.hxx" #include "Partition.hxx" +#include "util/ConstBuffer.hxx" CommandResult -handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_addtagid(Client &client, Request args, Response &r) { - unsigned song_id; - if (!check_unsigned(client, &song_id, argv[1])) - return CommandResult::ERROR; + unsigned song_id = args.ParseUnsigned(0); - const char *const tag_name = argv[2]; + const char *const tag_name = args[1]; const TagType tag_type = tag_name_parse_i(tag_name); if (tag_type == TAG_NUM_OF_ITEM_TYPES) { - command_error(client, ACK_ERROR_ARG, - "Unknown tag type: %s", tag_name); + r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", tag_name); return CommandResult::ERROR; } - const char *const value = argv[3]; - - Error error; - if (!client.partition.playlist.AddSongIdTag(song_id, tag_type, value, - error)) - return print_error(client, error); + const char *const value = args[2]; + client.partition.playlist.AddSongIdTag(song_id, tag_type, value); return CommandResult::OK; } CommandResult -handle_cleartagid(Client &client, unsigned argc, char *argv[]) +handle_cleartagid(Client &client, Request args, Response &r) { - unsigned song_id; - if (!check_unsigned(client, &song_id, argv[1])) - return CommandResult::ERROR; + unsigned song_id = args.ParseUnsigned(0); TagType tag_type = TAG_NUM_OF_ITEM_TYPES; - if (argc >= 3) { - const char *const tag_name = argv[2]; + if (args.size >= 2) { + const char *const tag_name = args[1]; tag_type = tag_name_parse_i(tag_name); if (tag_type == TAG_NUM_OF_ITEM_TYPES) { - command_error(client, ACK_ERROR_ARG, + r.FormatError(ACK_ERROR_ARG, "Unknown tag type: %s", tag_name); return CommandResult::ERROR; } } - Error error; - if (!client.partition.playlist.ClearSongIdTag(song_id, tag_type, - error)) - return print_error(client, error); - + client.partition.playlist.ClearSongIdTag(song_id, tag_type); return CommandResult::OK; } diff -Nru mpd-0.19.21/src/command/TagCommands.hxx mpd-0.20.9/src/command/TagCommands.hxx --- mpd-0.19.21/src/command/TagCommands.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/command/TagCommands.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,11 +23,13 @@ #include "CommandResult.hxx" class Client; +class Request; +class Response; CommandResult -handle_addtagid(Client &client, unsigned argc, char *argv[]); +handle_addtagid(Client &client, Request request, Response &response); CommandResult -handle_cleartagid(Client &client, unsigned argc, char *argv[]); +handle_cleartagid(Client &client, Request request, Response &response); #endif diff -Nru mpd-0.19.21/src/CommandLine.cxx mpd-0.20.9/src/CommandLine.cxx --- mpd-0.19.21/src/CommandLine.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CommandLine.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -35,7 +35,9 @@ #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "fs/StandardDirectory.hxx" -#include "util/Error.hxx" +#include "system/Error.hxx" +#include "util/Macros.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/OptionDef.hxx" #include "util/OptionParser.hxx" @@ -66,12 +68,12 @@ #include #ifdef WIN32 -#define CONFIG_FILE_LOCATION "mpd\\mpd.conf" -#define APP_CONFIG_FILE_LOCATION "conf\\mpd.conf" +#define CONFIG_FILE_LOCATION PATH_LITERAL("mpd\\mpd.conf") +#define APP_CONFIG_FILE_LOCATION PATH_LITERAL("conf\\mpd.conf") #else -#define USER_CONFIG_FILE_LOCATION1 ".mpdconf" -#define USER_CONFIG_FILE_LOCATION2 ".mpd/mpd.conf" -#define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf" +#define USER_CONFIG_FILE_LOCATION1 PATH_LITERAL(".mpdconf") +#define USER_CONFIG_FILE_LOCATION2 PATH_LITERAL(".mpd/mpd.conf") +#define USER_CONFIG_FILE_LOCATION_XDG PATH_LITERAL("mpd/mpd.conf") #endif static constexpr OptionDef opt_kill( @@ -98,40 +100,44 @@ gcc_noreturn static void version(void) { - puts("Music Player Daemon " VERSION + printf("Music Player Daemon " VERSION #ifdef GIT_COMMIT - " (" GIT_COMMIT ")" + " (" GIT_COMMIT ")" #endif - "\n" - "\n" - "Copyright (C) 2003-2007 Warren Dukes \n" - "Copyright (C) 2008-2014 Max Kellermann \n" - "This is free software; see the source for copying conditions. There is NO\n" - "warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + "\n" + "\n" + "Copyright (C) 2003-2007 Warren Dukes \n" + "Copyright 2008-2017 Max Kellermann \n" + "This is free software; see the source for copying conditions. There is NO\n" + "warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" #ifdef ENABLE_DATABASE - puts("\n" - "Database plugins:"); + "\n" + "Database plugins:\n"); for (auto i = database_plugins; *i != nullptr; ++i) printf(" %s", (*i)->name); - puts("\n\n" - "Storage plugins:"); + printf("\n\n" + "Storage plugins:\n"); for (auto i = storage_plugins; *i != nullptr; ++i) printf(" %s", (*i)->name); + + printf("\n" #endif #ifdef ENABLE_NEIGHBOR_PLUGINS - puts("\n\n" - "Neighbor plugins:"); + "\n" + "Neighbor plugins:\n"); for (auto i = neighbor_plugins; *i != nullptr; ++i) printf(" %s", (*i)->name); + + printf("\n" #endif - puts("\n\n" - "Decoders plugins:"); + "\n" + "Decoders plugins:\n"); decoder_plugins_for_each([](const DecoderPlugin &plugin){ printf(" [%s]", plugin.name); @@ -141,26 +147,39 @@ for (; *suffixes != nullptr; ++suffixes) printf(" %s", *suffixes); - puts(""); + printf("\n"); }); - puts("\n" - "Output plugins:"); + printf("\n" + "Filters:\n" +#ifdef ENABLE_LIBSAMPLERATE + " libsamplerate" +#endif +#ifdef ENABLE_SOXR + " soxr" +#endif + "\n\n" + "Tag plugins:\n" +#ifdef ENABLE_ID3TAG + " id3tag" +#endif + "\n\n" + "Output plugins:\n"); audio_output_plugins_for_each(plugin) printf(" %s", plugin->name); - puts(""); + printf("\n" #ifdef ENABLE_ENCODER - puts("\n" - "Encoder plugins:"); + "\n" + "Encoder plugins:\n"); encoder_plugins_for_each(plugin) printf(" %s", plugin->name); - puts(""); + printf("\n" #endif #ifdef ENABLE_ARCHIVE - puts("\n" - "Archive plugins:"); + "\n" + "Archive plugins:\n"); archive_plugins_for_each(plugin) { printf(" [%s]", plugin->name); @@ -169,24 +188,57 @@ for (; *suffixes != nullptr; ++suffixes) printf(" %s", *suffixes); - puts(""); + printf("\n"); } + + printf("" #endif - puts("\n" - "Input plugins:"); + "\n" + "Input plugins:\n"); input_plugins_for_each(plugin) printf(" %s", plugin->name); - puts("\n\n" - "Playlist plugins:"); + printf("\n\n" + "Playlist plugins:\n"); playlist_plugins_for_each(plugin) printf(" %s", plugin->name); - puts("\n\n" - "Protocols:"); + printf("\n\n" + "Protocols:\n"); print_supported_uri_schemes_to_fp(stdout); + printf("\n" + "Other features:\n" +#ifdef HAVE_AVAHI + " avahi" +#endif +#ifdef USE_EPOLL + " epoll" +#endif +#ifdef HAVE_ICONV + " iconv" +#endif +#ifdef HAVE_ICU + " icu" +#endif +#ifdef ENABLE_INOTIFY + " inotify" +#endif +#ifdef HAVE_IPV6 + " ipv6" +#endif +#ifdef ENABLE_SYSTEMD_DAEMON + " systemd" +#endif +#ifdef HAVE_TCP + " tcp" +#endif +#ifdef HAVE_UN + " un" +#endif + "\n"); + exit(EXIT_SUCCESS); } @@ -206,12 +258,12 @@ gcc_noreturn static void help(void) { - puts("Usage:\n" - " mpd [OPTION...] [path/to/mpd.conf]\n" - "\n" - "Music Player Daemon - a daemon for playing music.\n" - "\n" - "Options:"); + printf("Usage:\n" + " mpd [OPTION...] [path/to/mpd.conf]\n" + "\n" + "Music Player Daemon - a daemon for playing music.\n" + "\n" + "Options:\n"); PrintOption(opt_help); PrintOption(opt_kill); @@ -226,29 +278,23 @@ class ConfigLoader { - Error &error; - bool result; public: - ConfigLoader(Error &_error) : error(_error), result(false) { } - - bool GetResult() const { return result; } - bool TryFile(const Path path); bool TryFile(const AllocatedPath &base_path, - PathTraitsFS::const_pointer path); + PathTraitsFS::const_pointer_type path); }; bool ConfigLoader::TryFile(Path path) { if (FileExists(path)) { - result = ReadConfigFile(path, error); + ReadConfigFile(path); return true; } return false; } bool ConfigLoader::TryFile(const AllocatedPath &base_path, - PathTraitsFS::const_pointer path) + PathTraitsFS::const_pointer_type path) { if (base_path.IsNull()) return false; @@ -256,9 +302,8 @@ return TryFile(full_path); } -bool -parse_cmdline(int argc, char **argv, struct options *options, - Error &error) +void +ParseCommandLine(int argc, char **argv, struct options *options) { bool use_config_file = true; options->kill = false; @@ -296,9 +341,8 @@ if (parser.CheckOption(opt_help, opt_help_alt)) help(); - error.Format(cmdline_domain, "invalid option: %s", - parser.GetOption()); - return false; + throw FormatRuntimeError("invalid option: %s", + parser.GetOption()); } /* initialize the logging library, so the configuration file @@ -308,7 +352,7 @@ if (!use_config_file) { LogDebug(cmdline_domain, "Ignoring config, using daemon defaults"); - return true; + return; } // Second pass: find non-option parameters (i.e. config file) @@ -320,18 +364,29 @@ config_file = argv[i]; continue; } - error.Set(cmdline_domain, "too many arguments"); - return false; + + throw std::runtime_error("too many arguments"); } if (config_file != nullptr) { /* use specified configuration file */ - return ReadConfigFile(Path::FromFS(config_file), error); +#ifdef _UNICODE + wchar_t buffer[MAX_PATH]; + auto result = MultiByteToWideChar(CP_ACP, 0, config_file, -1, + buffer, ARRAY_SIZE(buffer)); + if (result <= 0) + throw MakeLastError("MultiByteToWideChar() failed"); + + ReadConfigFile(Path::FromFS(buffer)); +#else + ReadConfigFile(Path::FromFS(config_file)); +#endif + return; } /* use default configuration file path */ - ConfigLoader loader(error); + ConfigLoader loader; bool found = #ifdef WIN32 @@ -345,10 +400,6 @@ loader.TryFile(GetHomeDir(), USER_CONFIG_FILE_LOCATION2) || loader.TryFile(Path::FromFS(SYSTEM_CONFIG_FILE_LOCATION)); #endif - if (!found) { - error.Set(cmdline_domain, "No configuration file found"); - return false; - } - - return loader.GetResult(); + if (!found) + throw std::runtime_error("No configuration file found"); } diff -Nru mpd-0.19.21/src/CommandLine.hxx mpd-0.20.9/src/CommandLine.hxx --- mpd-0.19.21/src/CommandLine.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CommandLine.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,6 @@ #ifndef MPD_COMMAND_LINE_HXX #define MPD_COMMAND_LINE_HXX -class Error; - struct options { bool kill; bool daemon; @@ -29,8 +27,7 @@ bool verbose; }; -bool -parse_cmdline(int argc, char **argv, struct options *options, - Error &error); +void +ParseCommandLine(int argc, char **argv, struct options *options); #endif diff -Nru mpd-0.19.21/src/Compiler.h mpd-0.20.9/src/Compiler.h --- mpd-0.19.21/src/Compiler.h 2016-08-23 07:56:33.000000000 +0000 +++ mpd-0.20.9/src/Compiler.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -62,8 +62,8 @@ # error Sorry, your clang version is too old. You need at least version 3.1. # endif #elif defined(__GNUC__) -# if GCC_OLDER_THAN(4,7) -# error Sorry, your gcc version is too old. You need at least version 4.6. +# if GCC_OLDER_THAN(4,9) +# error Sorry, your gcc version is too old. You need at least version 4.9. # endif #else # warning Untested compiler. Use at your own risk! @@ -97,8 +97,6 @@ #define gcc_likely(x) __builtin_expect (!!(x), 1) #define gcc_unlikely(x) __builtin_expect (!!(x), 0) -#define gcc_aligned(n) __attribute__((aligned(n))) - #define gcc_visibility_hidden __attribute__((visibility("hidden"))) #define gcc_visibility_default __attribute__((visibility("default"))) @@ -126,8 +124,6 @@ #define gcc_likely(x) (x) #define gcc_unlikely(x) (x) -#define gcc_aligned(n) - #define gcc_visibility_hidden #define gcc_visibility_default @@ -164,24 +160,6 @@ #define gcc_restrict #endif -/* C++11 features */ - -#if defined(__cplusplus) - -/* support for C++11 "override" was added in gcc 4.7 */ -#if GCC_OLDER_THAN(4,7) -#define override -#define final -#endif - -#if CLANG_OR_GCC_VERSION(4,8) -#define gcc_alignas(T, fallback) alignas(T) -#else -#define gcc_alignas(T, fallback) gcc_aligned(fallback) -#endif - -#endif - #ifndef __has_feature // define dummy macro for non-clang compilers #define __has_feature(x) 0 diff -Nru mpd-0.19.21/src/config/Block.cxx mpd-0.20.9/src/config/Block.cxx --- mpd-0.19.21/src/config/Block.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Block.cxx 2017-05-08 14:32:33.000000000 +0000 @@ -0,0 +1,140 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Block.hxx" +#include "ConfigParser.hxx" +#include "ConfigPath.hxx" +#include "system/FatalError.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/RuntimeError.hxx" + +#include +#include + +int +BlockParam::GetIntValue() const +{ + char *endptr; + long value2 = strtol(value.c_str(), &endptr, 0); + if (*endptr != 0) + FormatFatalError("Not a valid number in line %i", line); + + return value2; +} + +unsigned +BlockParam::GetUnsignedValue() const +{ + char *endptr; + unsigned long value2 = strtoul(value.c_str(), &endptr, 0); + if (*endptr != 0) + FormatFatalError("Not a valid number in line %i", line); + + return (unsigned)value2; +} + +bool +BlockParam::GetBoolValue() const +{ + bool value2; + if (!get_bool(value.c_str(), &value2)) + FormatFatalError("%s is not a boolean value (yes, true, 1) or " + "(no, false, 0) on line %i\n", + name.c_str(), line); + + return value2; +} + +ConfigBlock::~ConfigBlock() +{ + delete next; +} + +const BlockParam * +ConfigBlock::GetBlockParam(const char *name) const noexcept +{ + for (const auto &i : block_params) { + if (i.name == name) { + i.used = true; + return &i; + } + } + + return nullptr; +} + +const char * +ConfigBlock::GetBlockValue(const char *name, + const char *default_value) const noexcept +{ + const BlockParam *bp = GetBlockParam(name); + if (bp == nullptr) + return default_value; + + return bp->value.c_str(); +} + +AllocatedPath +ConfigBlock::GetPath(const char *name, const char *default_value) const +{ + const char *s; + + const BlockParam *bp = GetBlockParam(name); + if (bp != nullptr) { + s = bp->value.c_str(); + } else { + if (default_value == nullptr) + return AllocatedPath::Null(); + + s = default_value; + } + + return ParsePath(s); +} + +int +ConfigBlock::GetBlockValue(const char *name, int default_value) const +{ + const BlockParam *bp = GetBlockParam(name); + if (bp == nullptr) + return default_value; + + return bp->GetIntValue(); +} + +unsigned +ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const +{ + const BlockParam *bp = GetBlockParam(name); + if (bp == nullptr) + return default_value; + + return bp->GetUnsignedValue(); +} + +bool +ConfigBlock::GetBlockValue(const char *name, bool default_value) const +{ + const BlockParam *bp = GetBlockParam(name); + if (bp == nullptr) + return default_value; + + return bp->GetBoolValue(); +} diff -Nru mpd-0.19.21/src/config/Block.hxx mpd-0.20.9/src/config/Block.hxx --- mpd-0.19.21/src/config/Block.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Block.hxx 2017-06-03 19:34:15.000000000 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_CONFIG_BLOCK_HXX +#define MPD_CONFIG_BLOCK_HXX + +#include "check.h" +#include "Param.hxx" +#include "Compiler.h" + +#include +#include + +class AllocatedPath; + +struct BlockParam { + std::string name; + std::string value; + int line; + + /** + * This flag is false when nobody has queried the value of + * this option yet. + */ + mutable bool used; + + gcc_nonnull_all + BlockParam(const char *_name, const char *_value, int _line=-1) + :name(_name), value(_value), line(_line), used(false) {} + + int GetIntValue() const; + + unsigned GetUnsignedValue() const; + + bool GetBoolValue() const; +}; + +struct ConfigBlock { + /** + * The next #ConfigBlock with the same name. The destructor + * deletes the whole chain. + */ + ConfigBlock *next; + + int line; + + std::vector block_params; + + /** + * This flag is false when nobody has queried the value of + * this option yet. + */ + bool used; + + explicit ConfigBlock(int _line=-1) + :next(nullptr), line(_line), used(false) {} + + ConfigBlock(const ConfigBlock &) = delete; + + ~ConfigBlock(); + + ConfigBlock &operator=(const ConfigBlock &) = delete; + + /** + * Determine if this is a "null" instance, i.e. an empty + * object that was synthesized and not loaded from a + * configuration file. + */ + bool IsNull() const noexcept { + return line < 0; + } + + gcc_pure + bool IsEmpty() const noexcept { + return block_params.empty(); + } + + gcc_nonnull_all + void AddBlockParam(const char *_name, const char *_value, + int _line=-1) { + block_params.emplace_back(_name, _value, _line); + } + + gcc_nonnull_all gcc_pure + const BlockParam *GetBlockParam(const char *_name) const noexcept; + + gcc_pure + const char *GetBlockValue(const char *name, + const char *default_value=nullptr) const noexcept; + + /** + * Same as config_get_path(), but looks up the setting in the + * specified block. + * + * Throws #std::runtime_error on error. + */ + AllocatedPath GetPath(const char *name, + const char *default_value=nullptr) const; + + int GetBlockValue(const char *name, int default_value) const; + + unsigned GetBlockValue(const char *name, unsigned default_value) const; + + bool GetBlockValue(const char *name, bool default_value) const; +}; + +#endif diff -Nru mpd-0.19.21/src/config/ConfigData.cxx mpd-0.20.9/src/config/ConfigData.cxx --- mpd-0.19.21/src/config/ConfigData.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigData.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "ConfigData.hxx" -#include "ConfigParser.hxx" -#include "ConfigPath.hxx" -#include "util/Error.hxx" -#include "fs/AllocatedPath.hxx" -#include "system/FatalError.hxx" - -#include -#include - -int -block_param::GetIntValue() const -{ - char *endptr; - long value2 = strtol(value.c_str(), &endptr, 0); - if (*endptr != 0) - FormatFatalError("Not a valid number in line %i", line); - - return value2; -} - -unsigned -block_param::GetUnsignedValue() const -{ - char *endptr; - unsigned long value2 = strtoul(value.c_str(), &endptr, 0); - if (*endptr != 0) - FormatFatalError("Not a valid number in line %i", line); - - return (unsigned)value2; -} - -bool -block_param::GetBoolValue() const -{ - bool value2; - if (!get_bool(value.c_str(), &value2)) - FormatFatalError("%s is not a boolean value (yes, true, 1) or " - "(no, false, 0) on line %i\n", - name.c_str(), line); - - return value2; -} - -config_param::config_param(const char *_value, int _line) - :next(nullptr), value(_value), line(_line), used(false) {} - -config_param::~config_param() -{ - delete next; -} - -const block_param * -config_param::GetBlockParam(const char *name) const -{ - for (const auto &i : block_params) { - if (i.name == name) { - i.used = true; - return &i; - } - } - - return NULL; -} - -const char * -config_param::GetBlockValue(const char *name, const char *default_value) const -{ - const block_param *bp = GetBlockParam(name); - if (bp == nullptr) - return default_value; - - return bp->value.c_str(); -} - -AllocatedPath -config_param::GetBlockPath(const char *name, const char *default_value, - Error &error) const -{ - assert(!error.IsDefined()); - - int line2 = line; - const char *s; - - const block_param *bp = GetBlockParam(name); - if (bp != nullptr) { - line2 = bp->line; - s = bp->value.c_str(); - } else { - if (default_value == nullptr) - return AllocatedPath::Null(); - - s = default_value; - } - - AllocatedPath path = ParsePath(s, error); - if (gcc_unlikely(path.IsNull())) - error.FormatPrefix("Invalid path in \"%s\" at line %i: ", - name, line2); - - return path; -} - -AllocatedPath -config_param::GetBlockPath(const char *name, Error &error) const -{ - return GetBlockPath(name, nullptr, error); -} - -int -config_param::GetBlockValue(const char *name, int default_value) const -{ - const block_param *bp = GetBlockParam(name); - if (bp == nullptr) - return default_value; - - return bp->GetIntValue(); -} - -unsigned -config_param::GetBlockValue(const char *name, unsigned default_value) const -{ - const block_param *bp = GetBlockParam(name); - if (bp == nullptr) - return default_value; - - return bp->GetUnsignedValue(); -} - -gcc_pure -bool -config_param::GetBlockValue(const char *name, bool default_value) const -{ - const block_param *bp = GetBlockParam(name); - if (bp == NULL) - return default_value; - - return bp->GetBoolValue(); -} diff -Nru mpd-0.19.21/src/config/ConfigData.hxx mpd-0.20.9/src/config/ConfigData.hxx --- mpd-0.19.21/src/config/ConfigData.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigData.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_CONFIG_DATA_HXX -#define MPD_CONFIG_DATA_HXX - -#include "ConfigOption.hxx" -#include "Compiler.h" - -#include -#include -#include - -class AllocatedPath; -class Error; - -struct block_param { - std::string name; - std::string value; - int line; - - /** - * This flag is false when nobody has queried the value of - * this option yet. - */ - mutable bool used; - - gcc_nonnull_all - block_param(const char *_name, const char *_value, int _line=-1) - :name(_name), value(_value), line(_line), used(false) {} - - gcc_pure - int GetIntValue() const; - - gcc_pure - unsigned GetUnsignedValue() const; - - gcc_pure - bool GetBoolValue() const; -}; - -struct config_param { - /** - * The next config_param with the same name. The destructor - * deletes the whole chain. - */ - struct config_param *next; - - std::string value; - - unsigned int line; - - std::vector block_params; - - /** - * This flag is false when nobody has queried the value of - * this option yet. - */ - bool used; - - config_param(int _line=-1) - :next(nullptr), line(_line), used(false) {} - - gcc_nonnull_all - config_param(const char *_value, int _line=-1); - - config_param(const config_param &) = delete; - - ~config_param(); - - config_param &operator=(const config_param &) = delete; - - /** - * Determine if this is a "null" instance, i.e. an empty - * object that was synthesized and not loaded from a - * configuration file. - */ - bool IsNull() const { - return line == unsigned(-1); - } - - gcc_nonnull_all - void AddBlockParam(const char *_name, const char *_value, - int _line=-1) { - block_params.emplace_back(_name, _value, _line); - } - - gcc_nonnull_all gcc_pure - const block_param *GetBlockParam(const char *_name) const; - - gcc_pure - const char *GetBlockValue(const char *name, - const char *default_value=nullptr) const; - - /** - * Same as config_dup_path(), but looks up the setting in the - * specified block. - */ - AllocatedPath GetBlockPath(const char *name, const char *default_value, - Error &error) const; - - AllocatedPath GetBlockPath(const char *name, Error &error) const; - - gcc_pure - int GetBlockValue(const char *name, int default_value) const; - - gcc_pure - unsigned GetBlockValue(const char *name, unsigned default_value) const; - - gcc_pure - bool GetBlockValue(const char *name, bool default_value) const; -}; - -struct ConfigData { - std::array params; -}; - -#endif diff -Nru mpd-0.19.21/src/config/ConfigDefaults.hxx mpd-0.20.9/src/config/ConfigDefaults.hxx --- mpd-0.19.21/src/config/ConfigDefaults.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigDefaults.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/config/ConfigError.cxx mpd-0.20.9/src/config/ConfigError.cxx --- mpd-0.19.21/src/config/ConfigError.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigError.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/config/ConfigError.hxx mpd-0.20.9/src/config/ConfigError.hxx --- mpd-0.19.21/src/config/ConfigError.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/config/ConfigFile.cxx mpd-0.20.9/src/config/ConfigFile.cxx --- mpd-0.19.21/src/config/ConfigFile.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigFile.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,83 +19,60 @@ #include "config.h" #include "ConfigFile.hxx" -#include "ConfigData.hxx" +#include "Data.hxx" +#include "Param.hxx" +#include "Block.hxx" #include "ConfigTemplates.hxx" #include "util/Tokenizer.hxx" #include "util/StringUtil.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" -#include "fs/Limits.hxx" +#include "util/RuntimeError.hxx" #include "fs/Path.hxx" -#include "fs/FileSystem.hxx" +#include "fs/io/FileReader.hxx" +#include "fs/io/BufferedReader.hxx" #include "Log.hxx" -#include -#include +#include -#define MAX_STRING_SIZE MPD_PATH_MAX+80 +#include -#define CONF_COMMENT '#' +static constexpr char CONF_COMMENT = '#'; static constexpr Domain config_file_domain("config_file"); -static bool -config_read_name_value(struct config_param *param, char *input, unsigned line, - Error &error) +static void +config_read_name_value(ConfigBlock &block, char *input, unsigned line) { Tokenizer tokenizer(input); - const char *name = tokenizer.NextWord(error); - if (name == nullptr) { - assert(!tokenizer.IsEnd()); - return false; - } - - const char *value = tokenizer.NextString(error); - if (value == nullptr) { - if (tokenizer.IsEnd()) { - error.Set(config_file_domain, "Value missing"); - } else { - assert(error.IsDefined()); - } - - return false; - } - - if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) { - error.Set(config_file_domain, "Unknown tokens after value"); - return false; - } + const char *name = tokenizer.NextWord(); + assert(name != nullptr); - const struct block_param *bp = param->GetBlockParam(name); - if (bp != nullptr) { - error.Format(config_file_domain, - "\"%s\" is duplicate, first defined on line %i", - name, bp->line); - return false; - } + const char *value = tokenizer.NextString(); + if (value == nullptr) + throw std::runtime_error("Value missing"); + + if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) + throw std::runtime_error("Unknown tokens after value"); + + const BlockParam *bp = block.GetBlockParam(name); + if (bp != nullptr) + throw FormatRuntimeError("\"%s\" is duplicate, first defined on line %i", + name, bp->line); - param->AddBlockParam(name, value, line); - return true; + block.AddBlockParam(name, value, line); } -static struct config_param * -config_read_block(FILE *fp, int *count, char *string, Error &error) -{ - struct config_param *ret = new config_param(*count); +static ConfigBlock * +config_read_block(BufferedReader &reader) +try { + std::unique_ptr block(new ConfigBlock(reader.GetLineNumber())); while (true) { - char *line; - - line = fgets(string, MAX_STRING_SIZE, fp); - if (line == nullptr) { - delete ret; - error.Set(config_file_domain, - "Expected '}' before end-of-file"); - return nullptr; - } + char *line = reader.ReadLine(); + if (line == nullptr) + throw std::runtime_error("Expected '}' before end-of-file"); - (*count)++; line = StripLeft(line); if (*line == 0 || *line == CONF_COMMENT) continue; @@ -105,57 +82,121 @@ (and from this "while" loop) */ line = StripLeft(line + 1); - if (*line != 0 && *line != CONF_COMMENT) { - delete ret; - error.Format(config_file_domain, - "line %i: Unknown tokens after '}'", - *count); - return nullptr; - } + if (*line != 0 && *line != CONF_COMMENT) + throw std::runtime_error("Unknown tokens after '}'"); - return ret; + return block.release(); } /* parse name and value */ - if (!config_read_name_value(ret, line, *count, error)) { - assert(*line != 0); - delete ret; - error.FormatPrefix("line %i: ", *count); - return nullptr; - } + config_read_name_value(*block, line, + reader.GetLineNumber()); } +} catch (...) { + std::throw_with_nested(FormatRuntimeError("Error in line %u", reader.GetLineNumber())); } gcc_nonnull_all static void -Append(config_param *&head, config_param *p) +Append(ConfigBlock *&head, ConfigBlock *p) { assert(p->next == nullptr); - config_param **i = &head; + auto **i = &head; while (*i != nullptr) i = &(*i)->next; *i = p; } -static bool -ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error) +static void +ReadConfigBlock(ConfigData &config_data, BufferedReader &reader, + const char *name, ConfigBlockOption o, + Tokenizer &tokenizer) +{ + const unsigned i = unsigned(o); + const ConfigTemplate &option = config_block_templates[i]; + ConfigBlock *&head = config_data.blocks[i]; + + if (head != nullptr && !option.repeatable) { + ConfigBlock *block = head; + throw FormatRuntimeError("config parameter \"%s\" is first defined " + "on line %d and redefined on line %u\n", + name, block->line, + reader.GetLineNumber()); + } + + /* now parse the block or the value */ + + if (tokenizer.CurrentChar() != '{') + throw FormatRuntimeError("line %u: '{' expected", + reader.GetLineNumber()); + + char *line = StripLeft(tokenizer.Rest() + 1); + if (*line != 0 && *line != CONF_COMMENT) + throw FormatRuntimeError("line %u: Unknown tokens after '{'", + reader.GetLineNumber()); + + auto *param = config_read_block(reader); + assert(param != nullptr); + Append(head, param); +} + +gcc_nonnull_all +static void +Append(ConfigParam *&head, ConfigParam *p) { - assert(fp != nullptr); + assert(p->next == nullptr); + + auto **i = &head; + while (*i != nullptr) + i = &(*i)->next; + + *i = p; +} - char string[MAX_STRING_SIZE + 1]; - int count = 0; - struct config_param *param; +static void +ReadConfigParam(ConfigData &config_data, BufferedReader &reader, + const char *name, ConfigOption o, + Tokenizer &tokenizer) +{ + const unsigned i = unsigned(o); + const ConfigTemplate &option = config_param_templates[i]; + auto *&head = config_data.params[i]; + + if (head != nullptr && !option.repeatable) { + auto *param = head; + throw FormatRuntimeError("config parameter \"%s\" is first defined " + "on line %d and redefined on line %u\n", + name, param->line, + reader.GetLineNumber()); + } + + /* now parse the block or the value */ + + const char *value = tokenizer.NextString(); + if (value == nullptr) + throw FormatRuntimeError("line %u: Value missing", + reader.GetLineNumber()); + + if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) + throw FormatRuntimeError("line %u: Unknown tokens after value", + reader.GetLineNumber()); - while (fgets(string, MAX_STRING_SIZE, fp)) { - char *line; - const char *name, *value; + auto *param = new ConfigParam(value, reader.GetLineNumber()); + Append(head, param); +} - count++; +static void +ReadConfigFile(ConfigData &config_data, BufferedReader &reader) +{ + while (true) { + char *line = reader.ReadLine(); + if (line == nullptr) + return; - line = StripLeft(string); + line = StripLeft(line); if (*line == 0 || *line == CONF_COMMENT) continue; @@ -163,107 +204,38 @@ by either the value or '{' */ Tokenizer tokenizer(line); - name = tokenizer.NextWord(error); - if (name == nullptr) { - assert(!tokenizer.IsEnd()); - error.FormatPrefix("line %i: ", count); - return false; - } + const char *name = tokenizer.NextWord(); + assert(name != nullptr); /* get the definition of that option, and check the "repeatable" flag */ const ConfigOption o = ParseConfigOptionName(name); - if (o == CONF_MAX) { - error.Format(config_file_domain, - "unrecognized parameter in config file at " - "line %i: %s\n", count, name); - return false; - } - - const unsigned i = unsigned(o); - const ConfigTemplate &option = config_templates[i]; - config_param *&head = config_data.params[i]; - - if (head != nullptr && !option.repeatable) { - param = head; - error.Format(config_file_domain, - "config parameter \"%s\" is first defined " - "on line %i and redefined on line %i\n", - name, param->line, count); - return false; - } - - /* now parse the block or the value */ - - if (option.block) { - /* it's a block, call config_read_block() */ - - if (tokenizer.CurrentChar() != '{') { - error.Format(config_file_domain, - "line %i: '{' expected", count); - return false; - } - - line = StripLeft(tokenizer.Rest() + 1); - if (*line != 0 && *line != CONF_COMMENT) { - error.Format(config_file_domain, - "line %i: Unknown tokens after '{'", - count); - return false; - } - - param = config_read_block(fp, &count, string, error); - if (param == nullptr) { - return false; - } + ConfigBlockOption bo; + if (o != ConfigOption::MAX) { + ReadConfigParam(config_data, reader, name, o, + tokenizer); + } else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) { + ReadConfigBlock(config_data, reader, name, bo, + tokenizer); } else { - /* a string value */ - - value = tokenizer.NextString(error); - if (value == nullptr) { - if (tokenizer.IsEnd()) - error.Format(config_file_domain, - "line %i: Value missing", - count); - else - error.FormatPrefix("line %i: ", count); - - return false; - } - - if (!tokenizer.IsEnd() && - tokenizer.CurrentChar() != CONF_COMMENT) { - error.Format(config_file_domain, - "line %i: Unknown tokens after value", - count); - return false; - } - - param = new config_param(value, count); + throw FormatRuntimeError("unrecognized parameter in config file at " + "line %u: %s\n", + reader.GetLineNumber(), name); } - - Append(head, param); } - - return true; } -bool -ReadConfigFile(ConfigData &config_data, Path path, Error &error) +void +ReadConfigFile(ConfigData &config_data, Path path) { assert(!path.IsNull()); const std::string path_utf8 = path.ToUTF8(); FormatDebug(config_file_domain, "loading file %s", path_utf8.c_str()); - FILE *fp = FOpen(path, FOpenMode::ReadText); - if (fp == nullptr) { - error.FormatErrno("Failed to open %s", path_utf8.c_str()); - return false; - } + FileReader file(path); - bool result = ReadConfigFile(config_data, fp, error); - fclose(fp); - return result; + BufferedReader reader(file); + ReadConfigFile(config_data, reader); } diff -Nru mpd-0.19.21/src/config/ConfigFile.hxx mpd-0.20.9/src/config/ConfigFile.hxx --- mpd-0.19.21/src/config/ConfigFile.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigFile.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,10 @@ #ifndef MPD_CONFIG_FILE_HXX #define MPD_CONFIG_FILE_HXX -class Error; class Path; struct ConfigData; -bool -ReadConfigFile(ConfigData &data, Path path, Error &error); +void +ReadConfigFile(ConfigData &data, Path path); #endif diff -Nru mpd-0.19.21/src/config/ConfigGlobal.cxx mpd-0.20.9/src/config/ConfigGlobal.cxx --- mpd-0.19.21/src/config/ConfigGlobal.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigGlobal.cxx 2017-05-08 13:01:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,14 @@ #include "config.h" #include "ConfigGlobal.hxx" #include "ConfigParser.hxx" -#include "ConfigData.hxx" +#include "Data.hxx" +#include "Param.hxx" +#include "Block.hxx" #include "ConfigFile.hxx" #include "ConfigPath.hxx" #include "ConfigError.hxx" #include "fs/Path.hxx" #include "fs/AllocatedPath.hxx" -#include "util/Error.hxx" #include "system/FatalError.hxx" #include "Log.hxx" @@ -36,30 +37,29 @@ void config_global_finish(void) { - for (auto i : config_data.params) - delete i; + config_data.Clear(); } void config_global_init(void) { } -bool -ReadConfigFile(Path path, Error &error) +void +ReadConfigFile(Path path) { - return ReadConfigFile(config_data, path, error); + return ReadConfigFile(config_data, path); } static void -Check(const config_param *param) +Check(const ConfigBlock &block) { - if (!param->used) - /* this whole config_param was not queried at all - + if (!block.used) + /* this whole block was not queried at all - the feature might be disabled at compile time? Silently ignore it here. */ return; - for (const auto &i : param->block_params) { + for (const auto &i : block.block_params) { if (!i.used) FormatWarning(config_domain, "option '%s' on line %i was not recognized", @@ -69,41 +69,50 @@ void config_global_check(void) { - for (auto i : config_data.params) - for (const config_param *p = i; p != nullptr; p = p->next) - Check(p); + for (auto i : config_data.blocks) + for (const auto *p = i; p != nullptr; p = p->next) + Check(*p); } -const config_param * -config_get_param(ConfigOption option) +const ConfigParam * +config_get_param(ConfigOption option) noexcept { - config_param *param = config_data.params[unsigned(option)]; + auto *param = config_data.params[unsigned(option)]; if (param != nullptr) param->used = true; return param; } -const config_param * -config_find_block(ConfigOption option, const char *key, const char *value) +const ConfigBlock * +config_get_block(ConfigBlockOption option) noexcept { - for (const config_param *param = config_get_param(option); - param != nullptr; param = param->next) { - const char *value2 = param->GetBlockValue(key); + ConfigBlock *block = config_data.blocks[unsigned(option)]; + if (block != nullptr) + block->used = true; + return block; +} + +const ConfigBlock * +config_find_block(ConfigBlockOption option, const char *key, const char *value) +{ + for (const auto *block = config_get_block(option); + block != nullptr; block = block->next) { + const char *value2 = block->GetBlockValue(key); if (value2 == nullptr) FormatFatalError("block without '%s' name in line %d", - key, param->line); + key, block->line); if (strcmp(value2, value) == 0) - return param; + return block; } return nullptr; } const char * -config_get_string(ConfigOption option, const char *default_value) +config_get_string(ConfigOption option, const char *default_value) noexcept { - const struct config_param *param = config_get_param(option); + const auto *param = config_get_param(option); if (param == nullptr) return default_value; @@ -112,30 +121,19 @@ } AllocatedPath -config_get_path(ConfigOption option, Error &error) +config_get_path(ConfigOption option) { - const struct config_param *param = config_get_param(option); + const auto *param = config_get_param(option); if (param == nullptr) return AllocatedPath::Null(); - return config_parse_path(param, error); -} - -AllocatedPath -config_parse_path(const struct config_param *param, Error & error) -{ - AllocatedPath path = ParsePath(param->value.c_str(), error); - if (gcc_unlikely(path.IsNull())) - error.FormatPrefix("Invalid path at line %i: ", - param->line); - - return path; + return param->GetPath(); } unsigned config_get_unsigned(ConfigOption option, unsigned default_value) { - const struct config_param *param = config_get_param(option); + const auto *param = config_get_param(option); long value; char *endptr; @@ -153,7 +151,7 @@ unsigned config_get_positive(ConfigOption option, unsigned default_value) { - const struct config_param *param = config_get_param(option); + const auto *param = config_get_param(option); long value; char *endptr; @@ -174,7 +172,7 @@ bool config_get_bool(ConfigOption option, bool default_value) { - const struct config_param *param = config_get_param(option); + const auto *param = config_get_param(option); bool success, value; if (param == nullptr) diff -Nru mpd-0.19.21/src/config/ConfigGlobal.hxx mpd-0.20.9/src/config/ConfigGlobal.hxx --- mpd-0.19.21/src/config/ConfigGlobal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigGlobal.hxx 2017-05-08 12:59:00.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,26 +23,36 @@ #include "ConfigOption.hxx" #include "Compiler.h" -class Error; +#include + class Path; class AllocatedPath; -struct config_param; +struct ConfigParam; +struct ConfigBlock; + +void +config_global_init(); -void config_global_init(void); -void config_global_finish(void); +void +config_global_finish(); /** * Call this function after all configuration has been evaluated. It * checks for unused parameters, and logs warnings. */ -void config_global_check(void); +void +config_global_check(); -bool -ReadConfigFile(Path path, Error &error); +void +ReadConfigFile(Path path); gcc_pure -const config_param * -config_get_param(enum ConfigOption option); +const ConfigParam * +config_get_param(enum ConfigOption option) noexcept; + +gcc_pure +const ConfigBlock * +config_get_block(enum ConfigBlockOption option) noexcept; /** * Find a block with a matching attribute. @@ -51,47 +61,47 @@ * @param key the attribute name * @param value the expected attribute value */ -gcc_pure -const config_param * -config_find_block(ConfigOption option, const char *key, const char *value); +const ConfigBlock * +config_find_block(ConfigBlockOption option, const char *key, const char *value); -/* Note on gcc_pure: Some of the functions declared pure are not - really pure in strict sense. They have side effect such that they - validate parameter's value and signal an error if it's invalid. - However, if the argument was already validated or we don't care - about the argument at all, this may be ignored so in the end, we - should be fine with calling those functions pure. */ - -gcc_pure const char * -config_get_string(enum ConfigOption option, const char *default_value); +config_get_string(enum ConfigOption option, + const char *default_value=nullptr) noexcept; /** * Returns an optional configuration variable which contains an * absolute path. If there is a tilde prefix, it is expanded. - * Returns AllocatedPath::Null() if the value is not present. If the path - * could not be parsed, returns AllocatedPath::Null() and sets the error. - */ -AllocatedPath -config_get_path(enum ConfigOption option, Error &error); - -/** - * Parse a configuration parameter as a path. - * If there is a tilde prefix, it is expanded. If the path could - * not be parsed, returns AllocatedPath::Null() and sets the error. + * Returns AllocatedPath::Null() if the value is not present. + * + * Throws #std::runtime_error on error. */ AllocatedPath -config_parse_path(const struct config_param *param, Error & error_r); +config_get_path(enum ConfigOption option); -gcc_pure unsigned config_get_unsigned(enum ConfigOption option, unsigned default_value); -gcc_pure +static inline std::chrono::steady_clock::duration +config_get_unsigned(ConfigOption option, + std::chrono::steady_clock::duration default_value) +{ + // TODO: allow unit suffixes + auto u = config_get_unsigned(option, default_value.count()); + return std::chrono::steady_clock::duration(u); +} + unsigned config_get_positive(enum ConfigOption option, unsigned default_value); -gcc_pure +static inline std::chrono::steady_clock::duration +config_get_positive(ConfigOption option, + std::chrono::steady_clock::duration default_value) +{ + // TODO: allow unit suffixes + auto u = config_get_positive(option, default_value.count()); + return std::chrono::steady_clock::duration(u); +} + bool config_get_bool(enum ConfigOption option, bool default_value); #endif diff -Nru mpd-0.19.21/src/config/ConfigOption.hxx mpd-0.20.9/src/config/ConfigOption.hxx --- mpd-0.19.21/src/config/ConfigOption.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigOption.hxx 2017-05-08 12:55:07.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,71 +22,93 @@ #include "Compiler.h" -enum ConfigOption { - CONF_MUSIC_DIR, - CONF_PLAYLIST_DIR, - CONF_FOLLOW_INSIDE_SYMLINKS, - CONF_FOLLOW_OUTSIDE_SYMLINKS, - CONF_DB_FILE, - CONF_STICKER_FILE, - CONF_LOG_FILE, - CONF_PID_FILE, - CONF_STATE_FILE, - CONF_STATE_FILE_INTERVAL, - CONF_RESTORE_PAUSED, - CONF_USER, - CONF_GROUP, - CONF_BIND_TO_ADDRESS, - CONF_PORT, - CONF_LOG_LEVEL, - CONF_ZEROCONF_NAME, - CONF_ZEROCONF_ENABLED, - CONF_PASSWORD, - CONF_DEFAULT_PERMS, - CONF_AUDIO_OUTPUT, - CONF_AUDIO_OUTPUT_FORMAT, - CONF_MIXER_TYPE, - CONF_REPLAYGAIN, - CONF_REPLAYGAIN_PREAMP, - CONF_REPLAYGAIN_MISSING_PREAMP, - CONF_REPLAYGAIN_LIMIT, - CONF_VOLUME_NORMALIZATION, - CONF_SAMPLERATE_CONVERTER, - CONF_AUDIO_BUFFER_SIZE, - CONF_BUFFER_BEFORE_PLAY, - CONF_HTTP_PROXY_HOST, - CONF_HTTP_PROXY_PORT, - CONF_HTTP_PROXY_USER, - CONF_HTTP_PROXY_PASSWORD, - CONF_CONN_TIMEOUT, - CONF_MAX_CONN, - CONF_MAX_PLAYLIST_LENGTH, - CONF_MAX_COMMAND_LIST_SIZE, - CONF_MAX_OUTPUT_BUFFER_SIZE, - CONF_FS_CHARSET, - CONF_ID3V1_ENCODING, - CONF_METADATA_TO_USE, - CONF_SAVE_ABSOLUTE_PATHS, - CONF_DECODER, - CONF_INPUT, - CONF_GAPLESS_MP3_PLAYBACK, - CONF_PLAYLIST_PLUGIN, - CONF_AUTO_UPDATE, - CONF_AUTO_UPDATE_DEPTH, - CONF_DESPOTIFY_USER, - CONF_DESPOTIFY_PASSWORD, - CONF_DESPOTIFY_HIGH_BITRATE, - CONF_AUDIO_FILTER, - CONF_DATABASE, - CONF_NEIGHBORS, - CONF_MAX +#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7) +/* "INPUT" is declared by winuser.h */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +enum class ConfigOption { + MUSIC_DIR, + PLAYLIST_DIR, + FOLLOW_INSIDE_SYMLINKS, + FOLLOW_OUTSIDE_SYMLINKS, + DB_FILE, + STICKER_FILE, + LOG_FILE, + PID_FILE, + STATE_FILE, + STATE_FILE_INTERVAL, + RESTORE_PAUSED, + USER, + GROUP, + BIND_TO_ADDRESS, + PORT, + LOG_LEVEL, + ZEROCONF_NAME, + ZEROCONF_ENABLED, + PASSWORD, + DEFAULT_PERMS, + AUDIO_OUTPUT_FORMAT, + MIXER_TYPE, + REPLAYGAIN, + REPLAYGAIN_PREAMP, + REPLAYGAIN_MISSING_PREAMP, + REPLAYGAIN_LIMIT, + VOLUME_NORMALIZATION, + SAMPLERATE_CONVERTER, + AUDIO_BUFFER_SIZE, + BUFFER_BEFORE_PLAY, + HTTP_PROXY_HOST, + HTTP_PROXY_PORT, + HTTP_PROXY_USER, + HTTP_PROXY_PASSWORD, + CONN_TIMEOUT, + MAX_CONN, + MAX_PLAYLIST_LENGTH, + MAX_COMMAND_LIST_SIZE, + MAX_OUTPUT_BUFFER_SIZE, + FS_CHARSET, + ID3V1_ENCODING, + METADATA_TO_USE, + SAVE_ABSOLUTE_PATHS, + GAPLESS_MP3_PLAYBACK, + AUTO_UPDATE, + AUTO_UPDATE_DEPTH, + DESPOTIFY_USER, + DESPOTIFY_PASSWORD, + DESPOTIFY_HIGH_BITRATE, + MAX }; +enum class ConfigBlockOption { + AUDIO_OUTPUT, + DECODER, + INPUT, + PLAYLIST_PLUGIN, + RESAMPLER, + AUDIO_FILTER, + DATABASE, + NEIGHBORS, + MAX +}; + +#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7) +#pragma GCC diagnostic pop +#endif + /** - * @return #CONF_MAX if not found + * @return #ConfigOption::MAX if not found */ gcc_pure enum ConfigOption -ParseConfigOptionName(const char *name); +ParseConfigOptionName(const char *name) noexcept; + +/** + * @return #ConfigOption::MAX if not found + */ +gcc_pure +enum ConfigBlockOption +ParseConfigBlockOptionName(const char *name) noexcept; #endif diff -Nru mpd-0.19.21/src/config/ConfigParser.cxx mpd-0.20.9/src/config/ConfigParser.cxx --- mpd-0.19.21/src/config/ConfigParser.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigParser.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,15 +23,15 @@ bool get_bool(const char *value, bool *value_r) { - static const char *t[] = { "yes", "true", "1", nullptr }; - static const char *f[] = { "no", "false", "0", nullptr }; + static const char *const t[] = { "yes", "true", "1", nullptr }; + static const char *const f[] = { "no", "false", "0", nullptr }; - if (string_array_contains(t, value)) { + if (StringArrayContainsCase(t, value)) { *value_r = true; return true; } - if (string_array_contains(f, value)) { + if (StringArrayContainsCase(f, value)) { *value_r = false; return true; } diff -Nru mpd-0.19.21/src/config/ConfigParser.hxx mpd-0.20.9/src/config/ConfigParser.hxx --- mpd-0.19.21/src/config/ConfigParser.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigParser.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/config/ConfigPath.cxx mpd-0.20.9/src/config/ConfigPath.cxx --- mpd-0.19.21/src/config/ConfigPath.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigPath.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ #include "fs/Traits.hxx" #include "fs/Domain.hxx" #include "fs/StandardDirectory.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "ConfigGlobal.hxx" #include @@ -36,14 +36,11 @@ * Determine a given user's home directory. */ static AllocatedPath -GetHome(const char *user, Error &error) +GetHome(const char *user) { AllocatedPath result = GetHomeDir(user); - if (result.IsNull()) { - error.Format(path_domain, - "no such user: %s", user); - return AllocatedPath::Null(); - } + if (result.IsNull()) + throw FormatRuntimeError("no such user: %s", user); return result; } @@ -52,34 +49,33 @@ * Determine the current user's home directory. */ static AllocatedPath -GetHome(Error &error) +GetHome() { AllocatedPath result = GetHomeDir(); - if (result.IsNull()) { - error.Set(path_domain, - "problems getting home for current user"); - return AllocatedPath::Null(); - } + if (result.IsNull()) + throw std::runtime_error("problems getting home for current user"); return result; } /** * Determine the configured user's home directory. + * + * Throws #std::runtime_error on error. */ static AllocatedPath -GetConfiguredHome(Error &error) +GetConfiguredHome() { - const char *user = config_get_string(CONF_USER, nullptr); + const char *user = config_get_string(ConfigOption::USER); return user != nullptr - ? GetHome(user, error) - : GetHome(error); + ? GetHome(user) + : GetHome(); } #endif AllocatedPath -ParsePath(const char *path, Error &error) +ParsePath(const char *path) { assert(path != nullptr); @@ -88,12 +84,12 @@ ++path; if (*path == '\0') - return GetConfiguredHome(error); + return GetConfiguredHome(); AllocatedPath home = AllocatedPath::Null(); if (*path == '/') { - home = GetConfiguredHome(error); + home = GetConfiguredHome(); ++path; } else { @@ -102,7 +98,7 @@ ? path + strlen(path) : slash; const std::string user(path, end); - home = GetHome(user.c_str(), error); + home = GetHome(user.c_str()); if (slash == nullptr) return home; @@ -113,18 +109,16 @@ if (home.IsNull()) return AllocatedPath::Null(); - AllocatedPath path2 = AllocatedPath::FromUTF8(path, error); + AllocatedPath path2 = AllocatedPath::FromUTF8Throw(path); if (path2.IsNull()) return AllocatedPath::Null(); return AllocatedPath::Build(home, path2); } else if (!PathTraitsUTF8::IsAbsolute(path)) { - error.Format(path_domain, - "not an absolute path: %s", path); - return AllocatedPath::Null(); + throw FormatRuntimeError("not an absolute path: %s", path); } else { #endif - return AllocatedPath::FromUTF8(path, error); + return AllocatedPath::FromUTF8Throw(path); #ifndef WIN32 } #endif diff -Nru mpd-0.19.21/src/config/ConfigPath.hxx mpd-0.20.9/src/config/ConfigPath.hxx --- mpd-0.19.21/src/config/ConfigPath.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigPath.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,9 +21,11 @@ #define MPD_CONFIG_PATH_HXX class AllocatedPath; -class Error; +/** + * Throws #std::runtime_error on error. + */ AllocatedPath -ParsePath(const char *path, Error &error); +ParsePath(const char *path); #endif diff -Nru mpd-0.19.21/src/config/ConfigTemplates.cxx mpd-0.20.9/src/config/ConfigTemplates.cxx --- mpd-0.19.21/src/config/ConfigTemplates.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigTemplates.cxx 2017-05-08 12:54:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,80 +19,110 @@ #include "ConfigTemplates.hxx" #include "ConfigOption.hxx" +#include "util/Macros.hxx" #include -const ConfigTemplate config_templates[] = { - { "music_directory", false, false }, - { "playlist_directory", false, false }, - { "follow_inside_symlinks", false, false }, - { "follow_outside_symlinks", false, false }, - { "db_file", false, false }, - { "sticker_file", false, false }, - { "log_file", false, false }, - { "pid_file", false, false }, - { "state_file", false, false }, - { "state_file_interval", false, false }, - { "restore_paused", false, false }, - { "user", false, false }, - { "group", false, false }, - { "bind_to_address", true, false }, - { "port", false, false }, - { "log_level", false, false }, - { "zeroconf_name", false, false }, - { "zeroconf_enabled", false, false }, - { "password", true, false }, - { "default_permissions", false, false }, - { "audio_output", true, true }, - { "audio_output_format", false, false }, - { "mixer_type", false, false }, - { "replaygain", false, false }, - { "replaygain_preamp", false, false }, - { "replaygain_missing_preamp", false, false }, - { "replaygain_limit", false, false }, - { "volume_normalization", false, false }, - { "samplerate_converter", false, false }, - { "audio_buffer_size", false, false }, - { "buffer_before_play", false, false }, - { "http_proxy_host", false, false }, - { "http_proxy_port", false, false }, - { "http_proxy_user", false, false }, - { "http_proxy_password", false, false }, - { "connection_timeout", false, false }, - { "max_connections", false, false }, - { "max_playlist_length", false, false }, - { "max_command_list_size", false, false }, - { "max_output_buffer_size", false, false }, - { "filesystem_charset", false, false }, - { "id3v1_encoding", false, false }, - { "metadata_to_use", false, false }, - { "save_absolute_paths_in_playlists", false, false }, - { "decoder", true, true }, - { "input", true, true }, - { "gapless_mp3_playback", false, false }, - { "playlist_plugin", true, true }, - { "auto_update", false, false }, - { "auto_update_depth", false, false }, - { "despotify_user", false, false }, - { "despotify_password", false, false}, - { "despotify_high_bitrate", false, false }, - { "filter", true, true }, - { "database", false, true }, - { "neighbors", true, true }, +const ConfigTemplate config_param_templates[] = { + { "music_directory" }, + { "playlist_directory" }, + { "follow_inside_symlinks" }, + { "follow_outside_symlinks" }, + { "db_file" }, + { "sticker_file" }, + { "log_file" }, + { "pid_file" }, + { "state_file" }, + { "state_file_interval" }, + { "restore_paused" }, + { "user" }, + { "group" }, + { "bind_to_address", true }, + { "port" }, + { "log_level" }, + { "zeroconf_name" }, + { "zeroconf_enabled" }, + { "password", true }, + { "default_permissions" }, + { "audio_output_format" }, + { "mixer_type" }, + { "replaygain" }, + { "replaygain_preamp" }, + { "replaygain_missing_preamp" }, + { "replaygain_limit" }, + { "volume_normalization" }, + { "samplerate_converter" }, + { "audio_buffer_size" }, + { "buffer_before_play" }, + { "http_proxy_host", false, true }, + { "http_proxy_port", false, true }, + { "http_proxy_user", false, true }, + { "http_proxy_password", false, true }, + { "connection_timeout" }, + { "max_connections" }, + { "max_playlist_length" }, + { "max_command_list_size" }, + { "max_output_buffer_size" }, + { "filesystem_charset" }, + { "id3v1_encoding", false, true }, + { "metadata_to_use" }, + { "save_absolute_paths_in_playlists" }, + { "gapless_mp3_playback" }, + { "auto_update" }, + { "auto_update_depth" }, + { "despotify_user", false, true }, + { "despotify_password", false, true }, + { "despotify_high_bitrate", false, true }, }; -static constexpr unsigned n_config_templates = - sizeof(config_templates) / sizeof(config_templates[0]); +static constexpr unsigned n_config_param_templates = + ARRAY_SIZE(config_param_templates); -static_assert(n_config_templates == unsigned(CONF_MAX), - "Wrong number of config_templates"); +static_assert(n_config_param_templates == unsigned(ConfigOption::MAX), + "Wrong number of config_param_templates"); + +const ConfigTemplate config_block_templates[] = { + { "audio_output", true }, + { "decoder", true }, + { "input", true }, + { "playlist_plugin", true }, + { "resampler" }, + { "filter", true }, + { "database" }, + { "neighbors", true }, +}; + +static constexpr unsigned n_config_block_templates = + ARRAY_SIZE(config_block_templates); + +static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX), + "Wrong number of config_block_templates"); + +gcc_pure +static inline unsigned +ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count, + const char *name) noexcept +{ + unsigned i = 0; + for (; i < count; ++i) + if (strcmp(templates[i].name, name) == 0) + break; + + return i; +} ConfigOption -ParseConfigOptionName(const char *name) +ParseConfigOptionName(const char *name) noexcept { - for (unsigned i = 0; i < n_config_templates; ++i) - if (strcmp(config_templates[i].name, name) == 0) - return ConfigOption(i); + return ConfigOption(ParseConfigTemplateName(config_param_templates, + n_config_param_templates, + name)); +} - return CONF_MAX; +ConfigBlockOption +ParseConfigBlockOptionName(const char *name) noexcept +{ + return ConfigBlockOption(ParseConfigTemplateName(config_block_templates, + n_config_block_templates, + name)); } diff -Nru mpd-0.19.21/src/config/ConfigTemplates.hxx mpd-0.20.9/src/config/ConfigTemplates.hxx --- mpd-0.19.21/src/config/ConfigTemplates.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/config/ConfigTemplates.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,9 +23,18 @@ struct ConfigTemplate { const char *const name; const bool repeatable; - const bool block; + + // TODO: print warning when a deprecated option is used + const bool deprecated; + + constexpr ConfigTemplate(const char *_name, + bool _repeatable=false, + bool _deprecated=false) + :name(_name), repeatable(_repeatable), + deprecated(_deprecated) {} }; -extern const ConfigTemplate config_templates[]; +extern const ConfigTemplate config_param_templates[]; +extern const ConfigTemplate config_block_templates[]; #endif diff -Nru mpd-0.19.21/src/config/Data.cxx mpd-0.20.9/src/config/Data.cxx --- mpd-0.19.21/src/config/Data.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Data.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Data.hxx" +#include "Param.hxx" +#include "Block.hxx" + +void +ConfigData::Clear() +{ + for (auto &i : params) { + delete i; + i = nullptr; + } + + for (auto &i : blocks) { + delete i; + i = nullptr; + } +} diff -Nru mpd-0.19.21/src/config/Data.hxx mpd-0.20.9/src/config/Data.hxx --- mpd-0.19.21/src/config/Data.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Data.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_CONFIG_DATA_HXX +#define MPD_CONFIG_DATA_HXX + +#include "ConfigOption.hxx" + +#include + +struct ConfigParam; +struct ConfigBlock; + +struct ConfigData { + std::array params; + std::array blocks; + + void Clear(); +}; + +#endif diff -Nru mpd-0.19.21/src/config/Param.cxx mpd-0.20.9/src/config/Param.cxx --- mpd-0.19.21/src/config/Param.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Param.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Param.hxx" +#include "ConfigPath.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/RuntimeError.hxx" + +#include + +ConfigParam::ConfigParam(const char *_value, int _line) + :next(nullptr), value(_value), line(_line), used(false) {} + +ConfigParam::~ConfigParam() +{ + delete next; +} + +AllocatedPath +ConfigParam::GetPath() const +{ + try { + return ParsePath(value.c_str()); + } catch (...) { + std::throw_with_nested(FormatRuntimeError("Invalid path at line %i: ", line)); + } + +} diff -Nru mpd-0.19.21/src/config/Param.hxx mpd-0.20.9/src/config/Param.hxx --- mpd-0.19.21/src/config/Param.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/config/Param.hxx 2017-05-08 14:27:22.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_CONFIG_PARAM_HXX +#define MPD_CONFIG_PARAM_HXX + +#include "check.h" +#include "Compiler.h" + +#include + +class AllocatedPath; + +struct ConfigParam { + /** + * The next ConfigParam with the same name. The destructor + * deletes the whole chain. + */ + ConfigParam *next; + + std::string value; + + int line; + + /** + * This flag is false when nobody has queried the value of + * this option yet. + */ + bool used; + + explicit ConfigParam(int _line=-1) + :next(nullptr), line(_line), used(false) {} + + gcc_nonnull_all + ConfigParam(const char *_value, int _line=-1); + + ConfigParam(const ConfigParam &) = delete; + + ~ConfigParam(); + + ConfigParam &operator=(const ConfigParam &) = delete; + + /** + * Determine if this is a "null" instance, i.e. an empty + * object that was synthesized and not loaded from a + * configuration file. + */ + bool IsNull() const { + return line < 0; + } + + /** + * Parse the value as a path. If there is a tilde prefix, it + * is expanded. + * + * Throws #std::runtime_error on error. + */ + AllocatedPath GetPath() const; +}; + +#endif diff -Nru mpd-0.19.21/src/CrossFade.cxx mpd-0.20.9/src/CrossFade.cxx --- mpd-0.19.21/src/CrossFade.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CrossFade.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "CrossFade.hxx" -#include "Chrono.hxx" -#include "MusicChunk.hxx" -#include "AudioFormat.hxx" -#include "util/NumberParser.hxx" -#include "util/Domain.hxx" -#include "Log.hxx" - -#include - -static constexpr Domain cross_fade_domain("cross_fade"); - -gcc_pure -static float -mixramp_interpolate(const char *ramp_list, float required_db) -{ - float last_db = 0, last_secs = 0; - bool have_last = false; - - /* ramp_list is a string of pairs of dBs and seconds that describe the - * volume profile. Delimiters are semi-colons between pairs and spaces - * between the dB and seconds of a pair. - * The dB values must be monotonically increasing for this to work. */ - - while (1) { - /* Parse the dB value. */ - char *endptr; - const float db = ParseFloat(ramp_list, &endptr); - if (endptr == ramp_list || *endptr != ' ') - break; - - ramp_list = endptr + 1; - - /* Parse the time. */ - float secs = ParseFloat(ramp_list, &endptr); - if (endptr == ramp_list || (*endptr != ';' && *endptr != 0)) - break; - - ramp_list = endptr; - if (*ramp_list == ';') - ++ramp_list; - - /* Check for exact match. */ - if (db == required_db) { - return secs; - } - - /* Save if too quiet. */ - if (db < required_db) { - last_db = db; - last_secs = secs; - have_last = true; - continue; - } - - /* If required db < any stored value, use the least. */ - if (!have_last) - return secs; - - /* Finally, interpolate linearly. */ - secs = last_secs + (required_db - last_db) * (secs - last_secs) / (db - last_db); - return secs; - } - - return -1; -} - -unsigned -CrossFadeSettings::Calculate(SignedSongTime total_time, - float replay_gain_db, float replay_gain_prev_db, - const char *mixramp_start, const char *mixramp_prev_end, - const AudioFormat af, - const AudioFormat old_format, - unsigned max_chunks) const -{ - unsigned int chunks = 0; - float chunks_f; - - if (total_time.IsNegative() || - duration < 0 || duration >= total_time.ToDoubleS() || - /* we can't crossfade when the audio formats are different */ - af != old_format) - return 0; - - assert(duration >= 0); - assert(af.IsValid()); - - chunks_f = (float)af.GetTimeToSize() / (float)CHUNK_SIZE; - - if (mixramp_delay <= 0 || !mixramp_start || !mixramp_prev_end) { - chunks = (chunks_f * duration + 0.5); - } else { - /* Calculate mixramp overlap. */ - const float mixramp_overlap_current = - mixramp_interpolate(mixramp_start, - mixramp_db - replay_gain_db); - const float mixramp_overlap_prev = - mixramp_interpolate(mixramp_prev_end, - mixramp_db - replay_gain_prev_db); - const float mixramp_overlap = - mixramp_overlap_current + mixramp_overlap_prev; - - if (mixramp_overlap_current >= 0 && - mixramp_overlap_prev >= 0 && - mixramp_delay <= mixramp_overlap) { - chunks = (chunks_f * (mixramp_overlap - mixramp_delay)); - FormatDebug(cross_fade_domain, - "will overlap %d chunks, %fs", chunks, - mixramp_overlap - mixramp_delay); - } - } - - if (chunks > max_chunks) { - chunks = max_chunks; - LogWarning(cross_fade_domain, - "audio_buffer_size too small for computed MixRamp overlap"); - } - - return chunks; -} diff -Nru mpd-0.19.21/src/CrossFade.hxx mpd-0.20.9/src/CrossFade.hxx --- mpd-0.19.21/src/CrossFade.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/CrossFade.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_CROSSFADE_HXX -#define MPD_CROSSFADE_HXX - -#include "Compiler.h" - -struct AudioFormat; -class SignedSongTime; - -struct CrossFadeSettings { - /** - * The configured cross fade duration [s]. - */ - float duration; - - float mixramp_db; - - /** - * The configured MixRapm delay [s]. A non-positive value - * disables MixRamp. - */ - float mixramp_delay; - - CrossFadeSettings() - :duration(0), - mixramp_db(0), - mixramp_delay(-1) - {} - - - /** - * Calculate how many music pipe chunks should be used for crossfading. - * - * @param total_time total_time the duration of the new song - * @param replay_gain_db the ReplayGain adjustment used for this song - * @param replay_gain_prev_db the ReplayGain adjustment used on the last song - * @param mixramp_start the next songs mixramp_start tag - * @param mixramp_prev_end the last songs mixramp_end setting - * @param af the audio format of the new song - * @param old_format the audio format of the current song - * @param max_chunks the maximum number of chunks - * @return the number of chunks for crossfading, or 0 if cross fading - * should be disabled for this song change - */ - gcc_pure - unsigned Calculate(SignedSongTime total_time, - float replay_gain_db, float replay_gain_prev_db, - const char *mixramp_start, - const char *mixramp_prev_end, - AudioFormat af, AudioFormat old_format, - unsigned max_chunks) const; -}; - -#endif diff -Nru mpd-0.19.21/src/db/Configured.cxx mpd-0.20.9/src/db/Configured.cxx --- mpd-0.19.21/src/db/Configured.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Configured.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,52 +21,43 @@ #include "Configured.hxx" #include "DatabaseGlue.hxx" #include "config/ConfigGlobal.hxx" -#include "config/ConfigData.hxx" -#include "config/ConfigError.hxx" +#include "config/Param.hxx" +#include "config/Block.hxx" #include "fs/AllocatedPath.hxx" #include "fs/StandardDirectory.hxx" -#include "util/Error.hxx" -#include "Log.hxx" +#include "util/RuntimeError.hxx" Database * -CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener, - Error &error) +CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener) { - const struct config_param *param = config_get_param(CONF_DATABASE); - const struct config_param *path = config_get_param(CONF_DB_FILE); + const auto *param = config_get_block(ConfigBlockOption::DATABASE); + const auto *path = config_get_param(ConfigOption::DB_FILE); - if (param != nullptr && path != nullptr) { - error.Format(config_domain, - "Found both 'database' (line %d) and 'db_file' (line %d) setting", - param->line, path->line); - return nullptr; - } - - struct config_param *allocated = nullptr; - - if (param == nullptr && path != nullptr) { - allocated = new config_param("database", path->line); - allocated->AddBlockParam("path", path->value.c_str(), - path->line); - param = allocated; - } - - if (param == nullptr) { + if (param != nullptr && path != nullptr) + throw FormatRuntimeError("Found both 'database' (line %d) and 'db_file' (line %d) setting", + param->line, path->line); + + if (param != nullptr) + return DatabaseGlobalInit(loop, listener, *param); + else if (path != nullptr) { + ConfigBlock block(path->line); + block.AddBlockParam("path", path->value.c_str(), path->line); + return DatabaseGlobalInit(loop, listener, block); + } else { /* if there is no override, use the cache directory */ const AllocatedPath cache_dir = GetUserCacheDir(); if (cache_dir.IsNull()) return nullptr; - const auto db_file = AllocatedPath::Build(cache_dir, "mpd.db"); + const auto db_file = AllocatedPath::Build(cache_dir, + PATH_LITERAL("mpd.db")); + const auto db_file_utf8 = db_file.ToUTF8(); + if (db_file_utf8.empty()) + return nullptr; - allocated = new config_param("database"); - allocated->AddBlockParam("path", db_file.c_str(), -1); - param = allocated; + ConfigBlock block; + block.AddBlockParam("path", db_file_utf8.c_str(), -1); + return DatabaseGlobalInit(loop, listener, block); } - - Database *db = DatabaseGlobalInit(loop, listener, *param, - error); - delete allocated; - return db; } diff -Nru mpd-0.19.21/src/db/Configured.hxx mpd-0.20.9/src/db/Configured.hxx --- mpd-0.19.21/src/db/Configured.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Configured.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,15 +25,15 @@ class EventLoop; class DatabaseListener; class Database; -class Error; /** * Read database configuration settings and create a #Database - * instance from it, but do not open it. Returns nullptr on error or - * if no database is configured (no #Error set in that case). + * instance from it, but do not open it. Returns nullptr if no + * database is configured. + * + * Throws #std::runtime_error on error. */ Database * -CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener, - Error &error); +CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener); #endif diff -Nru mpd-0.19.21/src/db/Count.cxx mpd-0.20.9/src/db/Count.cxx --- mpd-0.19.21/src/db/Count.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Count.cxx 2017-01-31 20:22:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,8 @@ #include "Count.hxx" #include "Selection.hxx" #include "Interface.hxx" -#include "client/Client.hxx" +#include "Partition.hxx" +#include "client/Response.hxx" #include "LightSong.hxx" #include "tag/Tag.hxx" @@ -40,30 +41,28 @@ }; static void -PrintSearchStats(Client &client, const SearchStats &stats) +PrintSearchStats(Response &r, const SearchStats &stats) { unsigned total_duration_s = std::chrono::duration_cast(stats.total_duration).count(); - client_printf(client, - "songs: %u\n" - "playtime: %u\n", - stats.n_songs, total_duration_s); + r.Format("songs: %u\n" + "playtime: %u\n", + stats.n_songs, total_duration_s); } static void -Print(Client &client, TagType group, const TagCountMap &m) +Print(Response &r, TagType group, const TagCountMap &m) { assert(unsigned(group) < TAG_NUM_OF_ITEM_TYPES); for (const auto &i : m) { - client_printf(client, "%s: %s\n", - tag_item_names[group], i.first.c_str()); - PrintSearchStats(client, i.second); + r.Format("%s: %s\n", tag_item_names[group], i.first.c_str()); + PrintSearchStats(r, i.second); } } -static bool +static void stats_visitor_song(SearchStats &stats, const LightSong &song) { stats.n_songs++; @@ -71,8 +70,6 @@ const auto duration = song.GetDuration(); if (!duration.IsNegative()) stats.total_duration += duration; - - return true; } static bool @@ -95,7 +92,7 @@ return found; } -static bool +static void GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song) { assert(song.tag != nullptr); @@ -104,19 +101,14 @@ if (!CollectGroupCounts(map, group, tag) && group == TAG_ALBUM_ARTIST) /* fall back to "Artist" if no "AlbumArtist" was found */ CollectGroupCounts(map, TAG_ARTIST, tag); - - return true; } -bool -PrintSongCount(Client &client, const char *name, +void +PrintSongCount(Response &r, const Partition &partition, const char *name, const SongFilter *filter, - TagType group, - Error &error) + TagType group) { - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return false; + const Database &db = partition.GetDatabaseOrThrow(); const DatabaseSelection selection(name, true, filter); @@ -128,10 +120,9 @@ using namespace std::placeholders; const auto f = std::bind(stats_visitor_song, std::ref(stats), _1); - if (!db->Visit(selection, f, error)) - return false; + db.Visit(selection, f); - PrintSearchStats(client, stats); + PrintSearchStats(r, stats); } else { /* group by the specified tag: store counts in a std::map */ @@ -141,11 +132,8 @@ using namespace std::placeholders; const auto f = std::bind(GroupCountVisitor, std::ref(map), group, _1); - if (!db->Visit(selection, f, error)) - return false; + db.Visit(selection, f); - Print(client, group, map); + Print(r, group, map); } - - return true; } diff -Nru mpd-0.19.21/src/db/Count.hxx mpd-0.20.9/src/db/Count.hxx --- mpd-0.19.21/src/db/Count.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Count.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,15 +25,14 @@ #include enum TagType : uint8_t; -class Client; +struct Partition; +class Response; class SongFilter; -class Error; -gcc_nonnull(2) -bool -PrintSongCount(Client &client, const char *name, +gcc_nonnull(3) +void +PrintSongCount(Response &r, const Partition &partition, const char *name, const SongFilter *filter, - TagType group, - Error &error); + TagType group); #endif diff -Nru mpd-0.19.21/src/db/DatabaseError.cxx mpd-0.20.9/src/db/DatabaseError.cxx --- mpd-0.19.21/src/db/DatabaseError.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseError.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "DatabaseError.hxx" -#include "util/Domain.hxx" - -const Domain db_domain("db"); diff -Nru mpd-0.19.21/src/db/DatabaseError.hxx mpd-0.20.9/src/db/DatabaseError.hxx --- mpd-0.19.21/src/db/DatabaseError.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,20 +20,30 @@ #ifndef MPD_DB_ERROR_HXX #define MPD_DB_ERROR_HXX -class Domain; +#include -enum db_error { +enum class DatabaseErrorCode { /** * The database is disabled, i.e. none is configured in this * MPD instance. */ - DB_DISABLED, + DISABLED, - DB_NOT_FOUND, + NOT_FOUND, - DB_CONFLICT, + CONFLICT, }; -extern const Domain db_domain; +class DatabaseError final : public std::runtime_error { + DatabaseErrorCode code; + +public: + DatabaseError(DatabaseErrorCode _code, const char *msg) + :std::runtime_error(msg), code(_code) {} + + DatabaseErrorCode GetCode() const { + return code; + } +}; #endif diff -Nru mpd-0.19.21/src/db/DatabaseGlue.cxx mpd-0.20.9/src/db/DatabaseGlue.cxx --- mpd-0.19.21/src/db/DatabaseGlue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseGlue.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,25 +21,26 @@ #include "DatabaseGlue.hxx" #include "Registry.hxx" #include "DatabaseError.hxx" -#include "util/Error.hxx" -#include "config/ConfigData.hxx" +#include "util/RuntimeError.hxx" +#include "config/Block.hxx" #include "DatabasePlugin.hxx" -#include - Database * DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, Error &error) + const ConfigBlock &block) { const char *plugin_name = - param.GetBlockValue("plugin", "simple"); + block.GetBlockValue("plugin", "simple"); const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); - if (plugin == nullptr) { - error.Format(db_domain, - "No such database plugin: %s", plugin_name); - return nullptr; - } + if (plugin == nullptr) + throw FormatRuntimeError("No such database plugin: %s", + plugin_name); - return plugin->create(loop, listener, param, error); + try { + return plugin->create(loop, listener, block); + } catch (...) { + std::throw_with_nested(FormatRuntimeError("Failed to initialize database plugin '%s'", + plugin_name)); + } } diff -Nru mpd-0.19.21/src/db/DatabaseGlue.hxx mpd-0.20.9/src/db/DatabaseGlue.hxx --- mpd-0.19.21/src/db/DatabaseGlue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseGlue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,19 +22,20 @@ #include "Compiler.h" -struct config_param; +struct ConfigBlock; class EventLoop; class DatabaseListener; class Database; -class Error; /** * Initialize the database library. * - * @param param the database configuration block + * Throws #std::runtime_error on error. + * + * @param block the database configuration block */ Database * DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, Error &error); + const ConfigBlock &block); #endif diff -Nru mpd-0.19.21/src/db/DatabaseListener.hxx mpd-0.20.9/src/db/DatabaseListener.hxx --- mpd-0.19.21/src/db/DatabaseListener.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseListener.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -40,7 +40,7 @@ * During database update, a song is about to be removed from * the database because the file has disappeared. */ - virtual void OnDatabaseSongRemoved(const LightSong &song) = 0; + virtual void OnDatabaseSongRemoved(const char *uri) = 0; }; #endif diff -Nru mpd-0.19.21/src/db/DatabaseLock.cxx mpd-0.20.9/src/db/DatabaseLock.cxx --- mpd-0.19.21/src/db/DatabaseLock.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseLock.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/DatabaseLock.hxx mpd-0.20.9/src/db/DatabaseLock.hxx --- mpd-0.19.21/src/db/DatabaseLock.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseLock.hxx 2017-05-08 13:29:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -45,7 +45,7 @@ */ gcc_pure static inline bool -holding_db_lock(void) +holding_db_lock() noexcept { return db_mutex_holder.IsInside(); } @@ -84,14 +84,41 @@ } class ScopeDatabaseLock { + bool locked = true; + public: ScopeDatabaseLock() { db_lock(); } ~ScopeDatabaseLock() { + if (locked) + db_unlock(); + } + + /** + * Unlock the mutex now, making the destructor a no-op. + */ + void unlock() { + assert(locked); + + db_unlock(); + locked = false; + } +}; + +/** + * Unlock the database while in the current scope. + */ +class ScopeDatabaseUnlock { +public: + ScopeDatabaseUnlock() { db_unlock(); } + + ~ScopeDatabaseUnlock() { + db_lock(); + } }; #endif diff -Nru mpd-0.19.21/src/db/DatabasePlaylist.cxx mpd-0.20.9/src/db/DatabasePlaylist.cxx --- mpd-0.19.21/src/db/DatabasePlaylist.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabasePlaylist.cxx 2017-01-31 20:22:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,29 +24,26 @@ #include "PlaylistFile.hxx" #include "Interface.hxx" #include "DetachedSong.hxx" -#include "storage/StorageInterface.hxx" #include -static bool +static void AddSong(const Storage &storage, const char *playlist_path_utf8, - const LightSong &song, Error &error) + const LightSong &song) { - return spl_append_song(playlist_path_utf8, - DatabaseDetachSong(storage, song), - error); + spl_append_song(playlist_path_utf8, + DatabaseDetachSong(storage, song)); } -bool +void search_add_to_playlist(const Database &db, const Storage &storage, const char *uri, const char *playlist_path_utf8, - const SongFilter *filter, - Error &error) + const SongFilter *filter) { const DatabaseSelection selection(uri, true, filter); using namespace std::placeholders; const auto f = std::bind(AddSong, std::ref(storage), - playlist_path_utf8, _1, _2); - return db.Visit(selection, f, error); + playlist_path_utf8, _1); + db.Visit(selection, f); } diff -Nru mpd-0.19.21/src/db/DatabasePlaylist.hxx mpd-0.20.9/src/db/DatabasePlaylist.hxx --- mpd-0.19.21/src/db/DatabasePlaylist.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabasePlaylist.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,13 +25,11 @@ class Database; class Storage; class SongFilter; -class Error; gcc_nonnull(3,4) -bool +void search_add_to_playlist(const Database &db, const Storage &storage, const char *uri, const char *path_utf8, - const SongFilter *filter, - Error &error); + const SongFilter *filter); #endif diff -Nru mpd-0.19.21/src/db/DatabasePlugin.hxx mpd-0.20.9/src/db/DatabasePlugin.hxx --- mpd-0.19.21/src/db/DatabasePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabasePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,8 +26,7 @@ #ifndef MPD_DATABASE_PLUGIN_HXX #define MPD_DATABASE_PLUGIN_HXX -struct config_param; -class Error; +struct ConfigBlock; class EventLoop; class DatabaseListener; class Database; @@ -45,10 +44,11 @@ /** * Allocates and configures a database. + * + * Throws #std::runtime_error on error. */ Database *(*create)(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); constexpr bool RequireStorage() const { return flags & FLAG_REQUIRE_STORAGE; diff -Nru mpd-0.19.21/src/db/DatabasePrint.cxx mpd-0.20.9/src/db/DatabasePrint.cxx --- mpd-0.19.21/src/db/DatabasePrint.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabasePrint.cxx 2017-01-31 20:22:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,8 @@ #include "SongFilter.hxx" #include "SongPrint.hxx" #include "TimePrint.hxx" -#include "client/Client.hxx" +#include "client/Response.hxx" +#include "Partition.hxx" #include "tag/Tag.hxx" #include "LightSong.hxx" #include "LightDirectory.hxx" @@ -42,180 +43,184 @@ } static void -PrintDirectoryURI(Client &client, bool base, const LightDirectory &directory) +PrintDirectoryURI(Response &r, bool base, const LightDirectory &directory) { - client_printf(client, "directory: %s\n", - ApplyBaseFlag(directory.GetPath(), base)); + r.Format("directory: %s\n", + ApplyBaseFlag(directory.GetPath(), base)); } -static bool -PrintDirectoryBrief(Client &client, bool base, const LightDirectory &directory) +static void +PrintDirectoryBrief(Response &r, bool base, const LightDirectory &directory) { if (!directory.IsRoot()) - PrintDirectoryURI(client, base, directory); - - return true; + PrintDirectoryURI(r, base, directory); } -static bool -PrintDirectoryFull(Client &client, bool base, const LightDirectory &directory) +static void +PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory) { if (!directory.IsRoot()) { - PrintDirectoryURI(client, base, directory); + PrintDirectoryURI(r, base, directory); if (directory.mtime > 0) - time_print(client, "Last-Modified", directory.mtime); + time_print(r, "Last-Modified", directory.mtime); } - - return true; } static void -print_playlist_in_directory(Client &client, bool base, +print_playlist_in_directory(Response &r, bool base, const char *directory, const char *name_utf8) { if (base || directory == nullptr) - client_printf(client, "playlist: %s\n", - ApplyBaseFlag(name_utf8, base)); + r.Format("playlist: %s\n", + ApplyBaseFlag(name_utf8, base)); else - client_printf(client, "playlist: %s/%s\n", - directory, name_utf8); + r.Format("playlist: %s/%s\n", + directory, name_utf8); } static void -print_playlist_in_directory(Client &client, bool base, +print_playlist_in_directory(Response &r, bool base, const LightDirectory *directory, const char *name_utf8) { if (base || directory == nullptr || directory->IsRoot()) - client_printf(client, "playlist: %s\n", name_utf8); + r.Format("playlist: %s\n", name_utf8); else - client_printf(client, "playlist: %s/%s\n", - directory->GetPath(), name_utf8); + r.Format("playlist: %s/%s\n", + directory->GetPath(), name_utf8); } -static bool -PrintSongBrief(Client &client, bool base, const LightSong &song) +static void +PrintSongBrief(Response &r, Partition &partition, + bool base, const LightSong &song) { - song_print_uri(client, song, base); + song_print_uri(r, partition, song, base); if (song.tag->has_playlist) /* this song file has an embedded CUE sheet */ - print_playlist_in_directory(client, base, + print_playlist_in_directory(r, base, song.directory, song.uri); - - return true; } -static bool -PrintSongFull(Client &client, bool base, const LightSong &song) +static void +PrintSongFull(Response &r, Partition &partition, + bool base, const LightSong &song) { - song_print_info(client, song, base); + song_print_info(r, partition, song, base); if (song.tag->has_playlist) /* this song file has an embedded CUE sheet */ - print_playlist_in_directory(client, base, + print_playlist_in_directory(r, base, song.directory, song.uri); - - return true; } -static bool -PrintPlaylistBrief(Client &client, bool base, +static void +PrintPlaylistBrief(Response &r, bool base, const PlaylistInfo &playlist, const LightDirectory &directory) { - print_playlist_in_directory(client, base, + print_playlist_in_directory(r, base, &directory, playlist.name.c_str()); - return true; } -static bool -PrintPlaylistFull(Client &client, bool base, +static void +PrintPlaylistFull(Response &r, bool base, const PlaylistInfo &playlist, const LightDirectory &directory) { - print_playlist_in_directory(client, base, + print_playlist_in_directory(r, base, &directory, playlist.name.c_str()); if (playlist.mtime > 0) - time_print(client, "Last-Modified", playlist.mtime); - - return true; + time_print(r, "Last-Modified", playlist.mtime); } -bool -db_selection_print(Client &client, const DatabaseSelection &selection, - bool full, bool base, Error &error) +void +db_selection_print(Response &r, Partition &partition, + const DatabaseSelection &selection, + bool full, bool base, + unsigned window_start, unsigned window_end) { - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return false; + const Database &db = partition.GetDatabaseOrThrow(); + + unsigned i = 0; using namespace std::placeholders; const auto d = selection.filter == nullptr ? std::bind(full ? PrintDirectoryFull : PrintDirectoryBrief, - std::ref(client), base, _1) + std::ref(r), base, _1) : VisitDirectory(); - const auto s = std::bind(full ? PrintSongFull : PrintSongBrief, - std::ref(client), base, _1); + VisitSong s = std::bind(full ? PrintSongFull : PrintSongBrief, + std::ref(r), std::ref(partition), base, _1); const auto p = selection.filter == nullptr ? std::bind(full ? PrintPlaylistFull : PrintPlaylistBrief, - std::ref(client), base, _1, _2) + std::ref(r), base, _1, _2) : VisitPlaylist(); - return db->Visit(selection, d, s, p, error); + if (window_start > 0 || + window_end < (unsigned)std::numeric_limits::max()) + s = [s, window_start, window_end, &i](const LightSong &song){ + const bool in_window = i >= window_start && i < window_end; + ++i; + if (in_window) + s(song); + }; + + db.Visit(selection, d, s, p); +} + +void +db_selection_print(Response &r, Partition &partition, + const DatabaseSelection &selection, + bool full, bool base) +{ + db_selection_print(r, partition, selection, full, base, + 0, std::numeric_limits::max()); } -static bool -PrintSongURIVisitor(Client &client, const LightSong &song) +static void +PrintSongURIVisitor(Response &r, Partition &partition, const LightSong &song) { - song_print_uri(client, song); - - return true; + song_print_uri(r, partition, song); } -static bool -PrintUniqueTag(Client &client, TagType tag_type, +static void +PrintUniqueTag(Response &r, TagType tag_type, const Tag &tag) { const char *value = tag.GetValue(tag_type); assert(value != nullptr); - client_printf(client, "%s: %s\n", tag_item_names[tag_type], value); + r.Format("%s: %s\n", tag_item_names[tag_type], value); for (const auto &item : tag) if (item.type != tag_type) - client_printf(client, "%s: %s\n", - tag_item_names[item.type], item.value); - - return true; + r.Format("%s: %s\n", + tag_item_names[item.type], item.value); } -bool -PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask, - const SongFilter *filter, - Error &error) +void +PrintUniqueTags(Response &r, Partition &partition, + unsigned type, tag_mask_t group_mask, + const SongFilter *filter) { - const Database *db = client.GetDatabase(error); - if (db == nullptr) - return false; + const Database &db = partition.GetDatabaseOrThrow(); const DatabaseSelection selection("", true, filter); if (type == LOCATE_TAG_FILE_TYPE) { using namespace std::placeholders; const auto f = std::bind(PrintSongURIVisitor, - std::ref(client), _1); - return db->Visit(selection, f, error); + std::ref(r), std::ref(partition), _1); + db.Visit(selection, f); } else { assert(type < TAG_NUM_OF_ITEM_TYPES); using namespace std::placeholders; - const auto f = std::bind(PrintUniqueTag, std::ref(client), + const auto f = std::bind(PrintUniqueTag, std::ref(r), (TagType)type, _1); - return db->VisitUniqueTags(selection, (TagType)type, - group_mask, - f, error); + db.VisitUniqueTags(selection, (TagType)type, + group_mask, f); } } diff -Nru mpd-0.19.21/src/db/DatabasePrint.hxx mpd-0.20.9/src/db/DatabasePrint.hxx --- mpd-0.19.21/src/db/DatabasePrint.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabasePrint.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,26 +20,31 @@ #ifndef MPD_DB_PRINT_H #define MPD_DB_PRINT_H -#include "Compiler.h" - -#include +#include "tag/Mask.hxx" class SongFilter; struct DatabaseSelection; -class Client; -class Error; +struct Partition; +class Response; /** * @param full print attributes/tags * @param base print only base name of songs/directories? */ -bool -db_selection_print(Client &client, const DatabaseSelection &selection, - bool full, bool base, Error &error); - -bool -PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask, - const SongFilter *filter, - Error &error); +void +db_selection_print(Response &r, Partition &partition, + const DatabaseSelection &selection, + bool full, bool base); + +void +db_selection_print(Response &r, Partition &partition, + const DatabaseSelection &selection, + bool full, bool base, + unsigned window_start, unsigned window_end); + +void +PrintUniqueTags(Response &r, Partition &partition, + unsigned type, tag_mask_t group_mask, + const SongFilter *filter); #endif diff -Nru mpd-0.19.21/src/db/DatabaseQueue.cxx mpd-0.20.9/src/db/DatabaseQueue.cxx --- mpd-0.19.21/src/db/DatabaseQueue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseQueue.cxx 2017-01-31 20:22:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,27 +27,21 @@ #include -static bool -AddToQueue(Partition &partition, const LightSong &song, Error &error) +static void +AddToQueue(Partition &partition, const LightSong &song) { const Storage &storage = *partition.instance.storage; - unsigned id = - partition.playlist.AppendSong(partition.pc, - DatabaseDetachSong(storage, - song), - error); - return id != 0; + partition.playlist.AppendSong(partition.pc, + DatabaseDetachSong(storage, + song)); } -bool -AddFromDatabase(Partition &partition, const DatabaseSelection &selection, - Error &error) +void +AddFromDatabase(Partition &partition, const DatabaseSelection &selection) { - const Database *db = partition.instance.GetDatabase(error); - if (db == nullptr) - return false; + const Database &db = partition.instance.GetDatabaseOrThrow(); using namespace std::placeholders; - const auto f = std::bind(AddToQueue, std::ref(partition), _1, _2); - return db->Visit(selection, f, error); + const auto f = std::bind(AddToQueue, std::ref(partition), _1); + db.Visit(selection, f); } diff -Nru mpd-0.19.21/src/db/DatabaseQueue.hxx mpd-0.20.9/src/db/DatabaseQueue.hxx --- mpd-0.19.21/src/db/DatabaseQueue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseQueue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,10 +22,8 @@ struct Partition; struct DatabaseSelection; -class Error; -bool -AddFromDatabase(Partition &partition, const DatabaseSelection &selection, - Error &error); +void +AddFromDatabase(Partition &partition, const DatabaseSelection &selection); #endif diff -Nru mpd-0.19.21/src/db/DatabaseSong.cxx mpd-0.20.9/src/db/DatabaseSong.cxx --- mpd-0.19.21/src/db/DatabaseSong.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseSong.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -41,12 +41,10 @@ } DetachedSong * -DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri, - Error &error) +DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri) { - const LightSong *tmp = db.GetSong(uri, error); - if (tmp == nullptr) - return nullptr; + const LightSong *tmp = db.GetSong(uri); + assert(tmp != nullptr); DetachedSong *song = new DetachedSong(DatabaseDetachSong(storage, *tmp)); diff -Nru mpd-0.19.21/src/db/DatabaseSong.hxx mpd-0.20.9/src/db/DatabaseSong.hxx --- mpd-0.19.21/src/db/DatabaseSong.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/DatabaseSong.hxx 2017-05-08 13:32:16.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,13 +26,11 @@ class Database; class Storage; class DetachedSong; -class Error; /** * "Detach" the #Song object, i.e. convert it to a #DetachedSong * instance. */ -gcc_pure DetachedSong DatabaseDetachSong(const Storage &storage, const LightSong &song); @@ -44,7 +42,7 @@ */ gcc_malloc gcc_nonnull_all DetachedSong * -DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri, - Error &error); +DatabaseDetachSong(const Database &db, const Storage &storage, + const char *uri); #endif diff -Nru mpd-0.19.21/src/db/Helpers.cxx mpd-0.20.9/src/db/Helpers.cxx --- mpd-0.19.21/src/db/Helpers.cxx 2016-08-23 07:47:48.000000000 +0000 +++ mpd-0.20.9/src/db/Helpers.cxx 2017-06-04 10:40:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ struct StringLess { gcc_pure - bool operator()(const char *a, const char *b) const { + bool operator()(const char *a, const char *b) const noexcept { return strcmp(a, b) < 0; } }; @@ -67,21 +67,19 @@ } } -static bool +static void StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums, const LightSong &song) { ++stats.song_count; StatsVisitTag(stats, artists, albums, *song.tag); - - return true; } -bool -GetStats(const Database &db, const DatabaseSelection &selection, - DatabaseStats &stats, Error &error) +DatabaseStats +GetStats(const Database &db, const DatabaseSelection &selection) { + DatabaseStats stats; stats.Clear(); StringSet artists, albums; @@ -89,10 +87,9 @@ const auto f = std::bind(StatsVisitSong, std::ref(stats), std::ref(artists), std::ref(albums), _1); - if (!db.Visit(selection, f, error)) - return false; + db.Visit(selection, f); stats.artist_count = artists.size(); stats.album_count = albums.size(); - return true; + return stats; } diff -Nru mpd-0.19.21/src/db/Helpers.hxx mpd-0.20.9/src/db/Helpers.hxx --- mpd-0.19.21/src/db/Helpers.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Helpers.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,11 @@ #ifndef MPD_MEMORY_DATABASE_PLUGIN_HXX #define MPD_MEMORY_DATABASE_PLUGIN_HXX -class Error; class Database; struct DatabaseSelection; struct DatabaseStats; -bool -GetStats(const Database &db, const DatabaseSelection &selection, - DatabaseStats &stats, Error &error); +DatabaseStats +GetStats(const Database &db, const DatabaseSelection &selection); #endif diff -Nru mpd-0.19.21/src/db/Interface.hxx mpd-0.20.9/src/db/Interface.hxx --- mpd-0.19.21/src/db/Interface.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Interface.hxx 2017-06-03 19:56:46.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,16 +22,15 @@ #include "Visitor.hxx" #include "tag/TagType.h" +#include "tag/Mask.hxx" #include "Compiler.h" #include -#include struct DatabasePlugin; struct DatabaseStats; struct DatabaseSelection; struct LightSong; -class Error; class Database { const DatabasePlugin &plugin; @@ -55,9 +54,10 @@ /** * Open the database. Read it into memory if applicable. + * + * Throws #DatabaseError or std::runtime_error on error. */ - virtual bool Open(gcc_unused Error &error) { - return true; + virtual void Open() { } /** @@ -72,8 +72,7 @@ * @param uri_utf8 the URI of the song within the music * directory (UTF-8) */ - virtual const LightSong *GetSong(const char *uri_utf8, - Error &error) const = 0; + virtual const LightSong *GetSong(const char *uri_utf8) const = 0; /** * Mark the song object as "unused". Call this on objects @@ -84,46 +83,41 @@ /** * Visit the selected entities. */ - virtual bool Visit(const DatabaseSelection &selection, + virtual void Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const = 0; + VisitPlaylist visit_playlist) const = 0; - bool Visit(const DatabaseSelection &selection, + void Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, - VisitSong visit_song, - Error &error) const { - return Visit(selection, visit_directory, visit_song, - VisitPlaylist(), error); + VisitSong visit_song) const { + Visit(selection, visit_directory, visit_song, VisitPlaylist()); } - bool Visit(const DatabaseSelection &selection, VisitSong visit_song, - Error &error) const { - return Visit(selection, VisitDirectory(), visit_song, error); + void Visit(const DatabaseSelection &selection, + VisitSong visit_song) const { + return Visit(selection, VisitDirectory(), visit_song); } /** * Visit all unique tag values. */ - virtual bool VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const = 0; - - virtual bool GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, - Error &error) const = 0; + virtual void VisitUniqueTags(const DatabaseSelection &selection, + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) const = 0; + + virtual DatabaseStats GetStats(const DatabaseSelection &selection) const = 0; /** - * Update the database. Returns the job id on success, 0 on - * error (with #Error set) and 0 if not implemented (#Error - * not set). + * Update the database. + * + * Throws #std::runtime_error on error. + * + * @return the job id or 0 if not implemented */ virtual unsigned Update(gcc_unused const char *uri_utf8, - gcc_unused bool discard, - gcc_unused Error &error) { - /* not implemented: return 0 and don't set an Error */ + gcc_unused bool discard) { + /* not implemented: return 0 */ return 0; } @@ -132,7 +126,7 @@ * Returns 0 if that is not not known/available. */ gcc_pure - virtual time_t GetUpdateStamp() const = 0; + virtual time_t GetUpdateStamp() const noexcept = 0; }; #endif diff -Nru mpd-0.19.21/src/db/LightDirectory.hxx mpd-0.20.9/src/db/LightDirectory.hxx --- mpd-0.19.21/src/db/LightDirectory.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/LightDirectory.hxx 2017-06-04 10:24:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -44,16 +44,16 @@ constexpr LightDirectory(const char *_uri, time_t _mtime) :uri(_uri), mtime(_mtime) {} - static constexpr LightDirectory Root() { + static constexpr LightDirectory Root() noexcept { return LightDirectory("", 0); } - bool IsRoot() const { + bool IsRoot() const noexcept { return *uri == 0; } gcc_pure - const char *GetPath() const { + const char *GetPath() const noexcept { return uri; } }; diff -Nru mpd-0.19.21/src/db/LightSong.cxx mpd-0.20.9/src/db/LightSong.cxx --- mpd-0.19.21/src/db/LightSong.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/LightSong.cxx 2017-05-08 13:40:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "tag/Tag.hxx" SignedSongTime -LightSong::GetDuration() const +LightSong::GetDuration() const noexcept { SongTime a = start_time, b = end_time; if (!b.IsPositive()) { diff -Nru mpd-0.19.21/src/db/LightSong.hxx mpd-0.20.9/src/db/LightSong.hxx --- mpd-0.19.21/src/db/LightSong.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/LightSong.hxx 2017-05-08 13:40:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -76,7 +76,7 @@ SongTime end_time; gcc_pure - std::string GetURI() const { + std::string GetURI() const noexcept { if (directory == nullptr) return std::string(uri); @@ -87,7 +87,7 @@ } gcc_pure - SignedSongTime GetDuration() const; + SignedSongTime GetDuration() const noexcept; }; #endif diff -Nru mpd-0.19.21/src/db/PlaylistInfo.hxx mpd-0.20.9/src/db/PlaylistInfo.hxx --- mpd-0.19.21/src/db/PlaylistInfo.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/PlaylistInfo.hxx 2017-06-03 19:56:19.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -45,7 +45,7 @@ constexpr CompareName(const char *_name):name(_name) {} gcc_pure - bool operator()(const PlaylistInfo &pi) const { + bool operator()(const PlaylistInfo &pi) const noexcept { return pi.name.compare(name) == 0; } }; diff -Nru mpd-0.19.21/src/db/PlaylistVector.cxx mpd-0.20.9/src/db/PlaylistVector.cxx --- mpd-0.19.21/src/db/PlaylistVector.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/PlaylistVector.cxx 2017-05-08 13:30:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ #include PlaylistVector::iterator -PlaylistVector::find(const char *name) +PlaylistVector::find(const char *name) noexcept { assert(holding_db_lock()); assert(name != nullptr); diff -Nru mpd-0.19.21/src/db/PlaylistVector.hxx mpd-0.20.9/src/db/PlaylistVector.hxx --- mpd-0.19.21/src/db/PlaylistVector.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/PlaylistVector.hxx 2017-05-08 13:30:13.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ * Caller must lock the #db_mutex. */ gcc_pure - iterator find(const char *name); + iterator find(const char *name) noexcept; public: using std::list::empty; diff -Nru mpd-0.19.21/src/db/plugins/LazyDatabase.cxx mpd-0.20.9/src/db/plugins/LazyDatabase.cxx --- mpd-0.19.21/src/db/plugins/LazyDatabase.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/LazyDatabase.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "LazyDatabase.hxx" -#include "db/Interface.hxx" - -#include - -LazyDatabase::LazyDatabase(Database *_db) - :Database(_db->GetPlugin()), db(_db), open(false) {} - -LazyDatabase::~LazyDatabase() -{ - assert(!open); - - delete db; -} - -bool -LazyDatabase::EnsureOpen(Error &error) const -{ - if (open) - return true; - - if (!db->Open(error)) - return false; - - open = true; - return true; -} - -void -LazyDatabase::Close() -{ - if (open) { - open = false; - db->Close(); - } -} - -const LightSong * -LazyDatabase::GetSong(const char *uri, Error &error) const -{ - return EnsureOpen(error) - ? db->GetSong(uri, error) - : nullptr; -} - -void -LazyDatabase::ReturnSong(const LightSong *song) const -{ - assert(open); - - db->ReturnSong(song); -} - -bool -LazyDatabase::Visit(const DatabaseSelection &selection, - VisitDirectory visit_directory, - VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const -{ - return EnsureOpen(error) && - db->Visit(selection, visit_directory, visit_song, - visit_playlist, error); -} - -bool -LazyDatabase::VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const -{ - return EnsureOpen(error) && - db->VisitUniqueTags(selection, tag_type, group_mask, visit_tag, - error); -} - -bool -LazyDatabase::GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, Error &error) const -{ - return EnsureOpen(error) && db->GetStats(selection, stats, error); -} - -time_t -LazyDatabase::GetUpdateStamp() const -{ - return open ? db->GetUpdateStamp() : 0; -} diff -Nru mpd-0.19.21/src/db/plugins/LazyDatabase.hxx mpd-0.20.9/src/db/plugins/LazyDatabase.hxx --- mpd-0.19.21/src/db/plugins/LazyDatabase.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/LazyDatabase.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_LAZY_DATABASE_PLUGIN_HXX -#define MPD_LAZY_DATABASE_PLUGIN_HXX - -#include "db/Interface.hxx" -#include "Compiler.h" - -/** - * A wrapper for a #Database object that gets opened on the first - * database access. This works around daemonization problems with - * some plugins. - */ -class LazyDatabase final : public Database { - Database *const db; - - mutable bool open; - -public: - gcc_nonnull_all - LazyDatabase(Database *_db); - - virtual ~LazyDatabase(); - - virtual void Close() override; - - virtual const LightSong *GetSong(const char *uri_utf8, - Error &error) const override; - void ReturnSong(const LightSong *song) const override; - - virtual bool Visit(const DatabaseSelection &selection, - VisitDirectory visit_directory, - VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const override; - - virtual bool VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const override; - - virtual bool GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, - Error &error) const override; - - virtual time_t GetUpdateStamp() const override; - -private: - bool EnsureOpen(Error &error) const; -}; - -#endif diff -Nru mpd-0.19.21/src/db/plugins/ProxyDatabasePlugin.cxx mpd-0.20.9/src/db/plugins/ProxyDatabasePlugin.cxx --- mpd-0.19.21/src/db/plugins/ProxyDatabasePlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/ProxyDatabasePlugin.cxx 2017-06-03 19:56:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -30,11 +30,11 @@ #include "db/Stats.hxx" #include "SongFilter.hxx" #include "Compiler.h" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "tag/TagBuilder.hxx" #include "tag/Tag.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/ScopeExit.hxx" +#include "util/RuntimeError.hxx" #include "protocol/Ack.hxx" #include "event/SocketMonitor.hxx" #include "event/IdleMonitor.hxx" @@ -47,6 +47,18 @@ #include #include +class LibmpdclientError final : public std::runtime_error { + enum mpd_error code; + +public: + LibmpdclientError(enum mpd_error _code, const char *_msg) + :std::runtime_error(_msg), code(_code) {} + + enum mpd_error GetCode() const { + return code; + } +}; + class ProxySong : public LightSong { Tag tag2; @@ -69,8 +81,9 @@ class ProxyDatabase final : public Database, SocketMonitor, IdleMonitor { DatabaseListener &listener; - std::string host; - unsigned port; + const std::string host; + const unsigned port; + const bool keepalive; struct mpd_connection *connection; @@ -90,61 +103,48 @@ bool is_idle; public: - ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener) - :Database(proxy_db_plugin), - SocketMonitor(_loop), IdleMonitor(_loop), - listener(_listener) {} + ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener, + const ConfigBlock &block); static Database *Create(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual const LightSong *GetSong(const char *uri_utf8, - Error &error) const override; + void Open() override; + void Close() override; + const LightSong *GetSong(const char *uri_utf8) const override; void ReturnSong(const LightSong *song) const override; - virtual bool Visit(const DatabaseSelection &selection, - VisitDirectory visit_directory, - VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const override; - - virtual bool VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const override; - - virtual bool GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, - Error &error) const override; + void Visit(const DatabaseSelection &selection, + VisitDirectory visit_directory, + VisitSong visit_song, + VisitPlaylist visit_playlist) const override; - virtual unsigned Update(const char *uri_utf8, bool discard, - Error &error) override; + void VisitUniqueTags(const DatabaseSelection &selection, + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) const override; - virtual time_t GetUpdateStamp() const override { + DatabaseStats GetStats(const DatabaseSelection &selection) const override; + + unsigned Update(const char *uri_utf8, bool discard) override; + + time_t GetUpdateStamp() const noexcept override { return update_stamp; } private: - bool Configure(const config_param ¶m, Error &error); - - bool Connect(Error &error); - bool CheckConnection(Error &error); - bool EnsureConnected(Error &error); + void Connect(); + void CheckConnection(); + void EnsureConnected(); void Disconnect(); /* virtual methods from SocketMonitor */ - virtual bool OnSocketReady(unsigned flags) override; + bool OnSocketReady(unsigned flags) override; /* virtual methods from IdleMonitor */ - virtual void OnIdle() override; + void OnIdle() override; }; -static constexpr Domain libmpdclient_domain("libmpdclient"); - static constexpr struct { TagType d; enum mpd_tag_type s; @@ -216,7 +216,7 @@ gcc_const static enum mpd_tag_type -Convert(TagType tag_type) +Convert(TagType tag_type) noexcept { for (auto i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i) if (i->d == tag_type) @@ -225,27 +225,34 @@ return MPD_TAG_COUNT; } -static bool -CheckError(struct mpd_connection *connection, Error &error) +static void +ThrowError(struct mpd_connection *connection) { const auto code = mpd_connection_get_error(connection); - if (code == MPD_ERROR_SUCCESS) - return true; + + AtScopeExit(connection) { + mpd_connection_clear_error(connection); + }; if (code == MPD_ERROR_SERVER) { /* libmpdclient's "enum mpd_server_error" is the same as our "enum ack" */ const auto server_error = mpd_connection_get_server_error(connection); - error.Set(ack_domain, (int)server_error, - mpd_connection_get_error_message(connection)); + throw ProtocolError((enum ack)server_error, + mpd_connection_get_error_message(connection)); } else { - error.Set(libmpdclient_domain, (int)code, - mpd_connection_get_error_message(connection)); + throw LibmpdclientError(code, + mpd_connection_get_error_message(connection)); } +} - mpd_connection_clear_error(connection); - return false; +static void +CheckError(struct mpd_connection *connection) +{ + const auto code = mpd_connection_get_error(connection); + if (code != MPD_ERROR_SUCCESS) + ThrowError(connection); } static bool @@ -262,18 +269,18 @@ return mpd_search_add_base_constraint(connection, MPD_OPERATOR_DEFAULT, - item.GetValue().c_str()); + item.GetValue()); #endif case LOCATE_TAG_FILE_TYPE: return mpd_search_add_uri_constraint(connection, MPD_OPERATOR_DEFAULT, - item.GetValue().c_str()); + item.GetValue()); case LOCATE_TAG_ANY_TYPE: return mpd_search_add_any_tag_constraint(connection, MPD_OPERATOR_DEFAULT, - item.GetValue().c_str()); + item.GetValue()); default: tag = Convert(TagType(item.GetTag())); @@ -283,7 +290,7 @@ return mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT, tag, - item.GetValue().c_str()); + item.GetValue()); } } @@ -318,37 +325,36 @@ return true; } -Database * -ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, Error &error) +ProxyDatabase::ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener, + const ConfigBlock &block) + :Database(proxy_db_plugin), + SocketMonitor(_loop), IdleMonitor(_loop), + listener(_listener), + host(block.GetBlockValue("host", "")), + port(block.GetBlockValue("port", 0u)), + keepalive(block.GetBlockValue("keepalive", false)) { - ProxyDatabase *db = new ProxyDatabase(loop, listener); - if (!db->Configure(param, error)) { - delete db; - db = nullptr; - } - - return db; } -bool -ProxyDatabase::Configure(const config_param ¶m, gcc_unused Error &error) +Database * +ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener, + const ConfigBlock &block) { - host = param.GetBlockValue("host", ""); - port = param.GetBlockValue("port", 0u); - - return true; + return new ProxyDatabase(loop, listener, block); } -bool -ProxyDatabase::Open(Error &error) +void +ProxyDatabase::Open() { - if (!Connect(error)) - return false; - update_stamp = 0; - return true; + try { + Connect(); + } catch (const std::runtime_error &error) { + /* this error is non-fatal, because this plugin will + attempt to reconnect again automatically */ + LogError(error); + } } void @@ -358,64 +364,75 @@ Disconnect(); } -bool -ProxyDatabase::Connect(Error &error) +void +ProxyDatabase::Connect() { const char *_host = host.empty() ? nullptr : host.c_str(); connection = mpd_connection_new(_host, port, 0); - if (connection == nullptr) { - error.Set(libmpdclient_domain, (int)MPD_ERROR_OOM, - "Out of memory"); - return false; - } + if (connection == nullptr) + throw LibmpdclientError(MPD_ERROR_OOM, "Out of memory"); - if (!CheckError(connection, error)) { + try { + CheckError(connection); + } catch (...) { mpd_connection_free(connection); connection = nullptr; - return false; + std::throw_with_nested(host.empty() + ? std::runtime_error("Failed to connect to remote MPD") + : FormatRuntimeError("Failed to connect to remote MPD '%s'", + host.c_str())); } +#if LIBMPDCLIENT_CHECK_VERSION(2, 10, 0) + mpd_connection_set_keepalive(connection, keepalive); +#else + // suppress -Wunused-private-field + (void)keepalive; +#endif + idle_received = unsigned(-1); is_idle = false; SocketMonitor::Open(mpd_async_get_fd(mpd_connection_get_async(connection))); IdleMonitor::Schedule(); - - return true; } -bool -ProxyDatabase::CheckConnection(Error &error) +void +ProxyDatabase::CheckConnection() { assert(connection != nullptr); if (!mpd_connection_clear_error(connection)) { Disconnect(); - return Connect(error); + Connect(); + return; } if (is_idle) { unsigned idle = mpd_run_noidle(connection); - if (idle == 0 && !CheckError(connection, error)) { - Disconnect(); - return false; + if (idle == 0) { + try { + CheckError(connection); + } catch (...) { + Disconnect(); + throw; + } } idle_received |= idle; is_idle = false; IdleMonitor::Schedule(); } - - return true; } -bool -ProxyDatabase::EnsureConnected(Error &error) +void +ProxyDatabase::EnsureConnected() { - return connection != nullptr - ? CheckConnection(error) - : Connect(error); + if (connection != nullptr) + CheckConnection(); + else + Connect(); } void @@ -443,8 +460,9 @@ unsigned idle = (unsigned)mpd_recv_idle(connection, false); if (idle == 0) { - Error error; - if (!CheckError(connection, error)) { + try { + CheckError(connection); + } catch (const std::runtime_error &error) { LogError(error); Disconnect(); return false; @@ -477,9 +495,11 @@ return; if (!mpd_send_idle_mask(connection, MPD_IDLE_DATABASE)) { - Error error; - if (!CheckError(connection, error)) + try { + ThrowError(connection); + } catch (const std::runtime_error &error) { LogError(error); + } SocketMonitor::Steal(); mpd_connection_free(connection); @@ -492,29 +512,24 @@ } const LightSong * -ProxyDatabase::GetSong(const char *uri, Error &error) const +ProxyDatabase::GetSong(const char *uri) const { // TODO: eliminate the const_cast - if (!const_cast(this)->EnsureConnected(error)) - return nullptr; + const_cast(this)->EnsureConnected(); - if (!mpd_send_list_meta(connection, uri)) { - CheckError(connection, error); - return nullptr; - } + if (!mpd_send_list_meta(connection, uri)) + ThrowError(connection); struct mpd_song *song = mpd_recv_song(connection); - if (!mpd_response_finish(connection) && - !CheckError(connection, error)) { + if (!mpd_response_finish(connection)) { if (song != nullptr) mpd_song_free(song); - return nullptr; + ThrowError(connection); } - if (song == nullptr) { - error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri); - return nullptr; - } + if (song == nullptr) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such song"); return new AllocatedProxySong(song); } @@ -529,18 +544,18 @@ delete song; } -static bool +static void Visit(struct mpd_connection *connection, const char *uri, bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, Error &error); + VisitPlaylist visit_playlist); -static bool +static void Visit(struct mpd_connection *connection, bool recursive, const SongFilter *filter, const struct mpd_directory *directory, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, Error &error) + VisitPlaylist visit_playlist) { const char *path = mpd_directory_get_path(directory); #if LIBMPDCLIENT_CHECK_VERSION(2,9,0) @@ -549,48 +564,45 @@ time_t mtime = 0; #endif - if (visit_directory && - !visit_directory(LightDirectory(path, mtime), error)) - return false; - - if (recursive && - !Visit(connection, path, recursive, filter, - visit_directory, visit_song, visit_playlist, error)) - return false; + if (visit_directory) + visit_directory(LightDirectory(path, mtime)); - return true; + if (recursive) + Visit(connection, path, recursive, filter, + visit_directory, visit_song, visit_playlist); } gcc_pure static bool -Match(const SongFilter *filter, const LightSong &song) +Match(const SongFilter *filter, const LightSong &song) noexcept { return filter == nullptr || filter->Match(song); } -static bool +static void Visit(const SongFilter *filter, const mpd_song *_song, - VisitSong visit_song, Error &error) + VisitSong visit_song) { if (!visit_song) - return true; + return; const ProxySong song(_song); - return !Match(filter, song) || visit_song(song, error); + if (Match(filter, song)) + visit_song(song); } -static bool +static void Visit(const struct mpd_playlist *playlist, - VisitPlaylist visit_playlist, Error &error) + VisitPlaylist visit_playlist) { if (!visit_playlist) - return true; + return; PlaylistInfo p(mpd_playlist_get_path(playlist), mpd_playlist_get_last_modified(playlist)); - return visit_playlist(p, LightDirectory::Root(), error); + visit_playlist(p, LightDirectory::Root()); } class ProxyEntity { @@ -631,18 +643,17 @@ return entities; } -static bool +static void Visit(struct mpd_connection *connection, const char *uri, bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, Error &error) + VisitPlaylist visit_playlist) { if (!mpd_send_list_meta(connection, uri)) - return CheckError(connection, error); + ThrowError(connection); std::list entities(ReceiveEntities(connection)); - if (!CheckError(connection, error)) - return false; + CheckError(connection); for (const auto &entity : entities) { switch (mpd_entity_get_type(entity)) { @@ -650,36 +661,27 @@ break; case MPD_ENTITY_TYPE_DIRECTORY: - if (!Visit(connection, recursive, filter, - mpd_entity_get_directory(entity), - visit_directory, visit_song, visit_playlist, - error)) - return false; + Visit(connection, recursive, filter, + mpd_entity_get_directory(entity), + visit_directory, visit_song, visit_playlist); break; case MPD_ENTITY_TYPE_SONG: - if (!Visit(filter, - mpd_entity_get_song(entity), visit_song, - error)) - return false; + Visit(filter, mpd_entity_get_song(entity), visit_song); break; case MPD_ENTITY_TYPE_PLAYLIST: - if (!Visit(mpd_entity_get_playlist(entity), - visit_playlist, error)) - return false; + Visit(mpd_entity_get_playlist(entity), + visit_playlist); break; } } - - return CheckError(connection, error); } -static bool +static void SearchSongs(struct mpd_connection *connection, const DatabaseSelection &selection, - VisitSong visit_song, - Error &error) + VisitSong visit_song) { assert(selection.recursive); assert(visit_song); @@ -690,19 +692,23 @@ if (!mpd_search_db_songs(connection, exact) || !SendConstraints(connection, selection) || !mpd_search_commit(connection)) - return CheckError(connection, error); + ThrowError(connection); - bool result = true; - struct mpd_song *song; - while (result && (song = mpd_recv_song(connection)) != nullptr) { + while (auto *song = mpd_recv_song(connection)) { AllocatedProxySong song2(song); - result = !Match(selection.filter, song2) || - visit_song(song2, error); + if (Match(selection.filter, song2)) { + try { + visit_song(song2); + } catch (...) { + mpd_response_finish(connection); + throw; + } + } } - mpd_response_finish(connection); - return result && CheckError(connection, error); + if (!mpd_response_finish(connection)) + ThrowError(connection); } /** @@ -711,7 +717,7 @@ */ gcc_pure static bool -ServerSupportsSearchBase(const struct mpd_connection *connection) +ServerSupportsSearchBase(const struct mpd_connection *connection) noexcept { #if LIBMPDCLIENT_CHECK_VERSION(2,9,0) return mpd_connection_cmp_server_version(connection, 0, 18, 0) >= 0; @@ -722,65 +728,58 @@ #endif } -bool +void ProxyDatabase::Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const + VisitPlaylist visit_playlist) const { // TODO: eliminate the const_cast - if (!const_cast(this)->EnsureConnected(error)) - return false; + const_cast(this)->EnsureConnected(); if (!visit_directory && !visit_playlist && selection.recursive && (ServerSupportsSearchBase(connection) ? !selection.IsEmpty() - : selection.HasOtherThanBase())) + : selection.HasOtherThanBase())) { /* this optimized code path can only be used under certain conditions */ - return ::SearchSongs(connection, selection, visit_song, error); + ::SearchSongs(connection, selection, visit_song); + return; + } /* fall back to recursive walk (slow!) */ - return ::Visit(connection, selection.uri.c_str(), - selection.recursive, selection.filter, - visit_directory, visit_song, visit_playlist, - error); + ::Visit(connection, selection.uri.c_str(), + selection.recursive, selection.filter, + visit_directory, visit_song, visit_playlist); } -bool +void ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection, TagType tag_type, - gcc_unused uint32_t group_mask, - VisitTag visit_tag, - Error &error) const + gcc_unused tag_mask_t group_mask, + VisitTag visit_tag) const { // TODO: eliminate the const_cast - if (!const_cast(this)->EnsureConnected(error)) - return false; + const_cast(this)->EnsureConnected(); enum mpd_tag_type tag_type2 = Convert(tag_type); - if (tag_type2 == MPD_TAG_COUNT) { - error.Set(libmpdclient_domain, "Unsupported tag"); - return false; - } - - if (!mpd_search_db_tags(connection, tag_type2)) - return CheckError(connection, error); + if (tag_type2 == MPD_TAG_COUNT) + throw std::runtime_error("Unsupported tag"); - if (!SendConstraints(connection, selection)) - return CheckError(connection, error); + if (!mpd_search_db_tags(connection, tag_type2) || + !SendConstraints(connection, selection)) + ThrowError(connection); // TODO: use group_mask if (!mpd_search_commit(connection)) - return CheckError(connection, error); + ThrowError(connection); - bool result = true; + while (auto *pair = mpd_recv_pair_tag(connection, tag_type2)) { + AtScopeExit(this, pair) { + mpd_return_pair(connection, pair); + }; - struct mpd_pair *pair; - while (result && - (pair = mpd_recv_pair_tag(connection, tag_type2)) != nullptr) { TagBuilder tag; tag.AddItem(tag_type, pair->value); @@ -792,54 +791,53 @@ given tag type to be present */ tag.AddEmptyItem(tag_type); - result = visit_tag(tag.Commit(), error); - mpd_return_pair(connection, pair); + try { + visit_tag(tag.Commit()); + } catch (...) { + mpd_response_finish(connection); + throw; + } } - return mpd_response_finish(connection) && - CheckError(connection, error) && - result; + if (!mpd_response_finish(connection)) + ThrowError(connection); } -bool -ProxyDatabase::GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, Error &error) const +DatabaseStats +ProxyDatabase::GetStats(const DatabaseSelection &selection) const { // TODO: match (void)selection; // TODO: eliminate the const_cast - if (!const_cast(this)->EnsureConnected(error)) - return false; + const_cast(this)->EnsureConnected(); struct mpd_stats *stats2 = mpd_run_stats(connection); if (stats2 == nullptr) - return CheckError(connection, error); + ThrowError(connection); update_stamp = (time_t)mpd_stats_get_db_update_time(stats2); + DatabaseStats stats; stats.song_count = mpd_stats_get_number_of_songs(stats2); stats.total_duration = std::chrono::seconds(mpd_stats_get_db_play_time(stats2)); stats.artist_count = mpd_stats_get_number_of_artists(stats2); stats.album_count = mpd_stats_get_number_of_albums(stats2); mpd_stats_free(stats2); - - return true; + return stats; } unsigned -ProxyDatabase::Update(const char *uri_utf8, bool discard, - Error &error) +ProxyDatabase::Update(const char *uri_utf8, bool discard) { - if (!EnsureConnected(error)) - return 0; + EnsureConnected(); unsigned id = discard ? mpd_run_rescan(connection, uri_utf8) : mpd_run_update(connection, uri_utf8); if (id == 0) - CheckError(connection, error); + CheckError(connection); return id; } diff -Nru mpd-0.19.21/src/db/plugins/ProxyDatabasePlugin.hxx mpd-0.20.9/src/db/plugins/ProxyDatabasePlugin.hxx --- mpd-0.19.21/src/db/plugins/ProxyDatabasePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/ProxyDatabasePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/plugins/simple/DatabaseSave.cxx mpd-0.20.9/src/db/plugins/simple/DatabaseSave.cxx --- mpd-0.19.21/src/db/plugins/simple/DatabaseSave.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/DatabaseSave.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,17 +20,15 @@ #include "config.h" #include "DatabaseSave.hxx" #include "db/DatabaseLock.hxx" -#include "db/DatabaseError.hxx" #include "Directory.hxx" #include "DirectorySave.hxx" #include "fs/io/BufferedOutputStream.hxx" #include "fs/io/TextFile.hxx" #include "tag/Tag.hxx" -#include "tag/TagSettings.h" +#include "tag/Settings.hxx" #include "fs/Charset.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" -#include "Log.hxx" +#include "util/StringCompare.hxx" +#include "util/RuntimeError.hxx" #include #include @@ -58,7 +56,7 @@ os.Format("%s%s\n", DIRECTORY_FS_CHARSET, GetFSCharset()); for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) - if (!ignore_tag_items[i]) + if (IsTagEnabled(i)) os.Format(DB_TAG_PREFIX "%s\n", tag_item_names[i]); os.Format("%s\n", DIRECTORY_INFO_END); @@ -66,95 +64,69 @@ directory_save(os, music_root); } -bool -db_load_internal(TextFile &file, Directory &music_root, Error &error) +void +db_load_internal(TextFile &file, Directory &music_root) { char *line; unsigned format = 0; bool found_charset = false, found_version = false; - bool success; bool tags[TAG_NUM_OF_ITEM_TYPES]; /* get initial info */ line = file.ReadLine(); - if (line == nullptr || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) { - error.Set(db_domain, "Database corrupted"); - return false; - } + if (line == nullptr || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) + throw std::runtime_error("Database corrupted"); memset(tags, false, sizeof(tags)); while ((line = file.ReadLine()) != nullptr && strcmp(line, DIRECTORY_INFO_END) != 0) { - if (StringStartsWith(line, DB_FORMAT_PREFIX)) { - format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1); + const char *p; + + if ((p = StringAfterPrefix(line, DB_FORMAT_PREFIX))) { + format = atoi(p); } else if (StringStartsWith(line, DIRECTORY_MPD_VERSION)) { - if (found_version) { - error.Set(db_domain, "Duplicate version line"); - return false; - } + if (found_version) + throw std::runtime_error("Duplicate version line"); found_version = true; - } else if (StringStartsWith(line, DIRECTORY_FS_CHARSET)) { - const char *new_charset; - - if (found_charset) { - error.Set(db_domain, "Duplicate charset line"); - return false; - } + } else if ((p = StringAfterPrefix(line, DIRECTORY_FS_CHARSET))) { + if (found_charset) + throw std::runtime_error("Duplicate charset line"); found_charset = true; - new_charset = line + sizeof(DIRECTORY_FS_CHARSET) - 1; + const char *new_charset = p; const char *const old_charset = GetFSCharset(); if (*old_charset != 0 - && strcmp(new_charset, old_charset) != 0) { - error.Format(db_domain, - "Existing database has charset " - "\"%s\" instead of \"%s\"; " - "discarding database file", - new_charset, old_charset); - return false; - } - } else if (StringStartsWith(line, DB_TAG_PREFIX)) { - const char *name = line + sizeof(DB_TAG_PREFIX) - 1; + && strcmp(new_charset, old_charset) != 0) + throw FormatRuntimeError("Existing database has charset " + "\"%s\" instead of \"%s\"; " + "discarding database file", + new_charset, old_charset); + } else if ((p = StringAfterPrefix(line, DB_TAG_PREFIX))) { + const char *name = p; TagType tag = tag_name_parse(name); - if (tag == TAG_NUM_OF_ITEM_TYPES) { - error.Format(db_domain, - "Unrecognized tag '%s', " - "discarding database file", - name); - return false; - } + if (tag == TAG_NUM_OF_ITEM_TYPES) + throw FormatRuntimeError("Unrecognized tag '%s', " + "discarding database file", + name); tags[tag] = true; } else { - error.Format(db_domain, "Malformed line: %s", line); - return false; - } - } - - if (format < OLDEST_DB_FORMAT || format > DB_FORMAT) { - error.Set(db_domain, - "Database format mismatch, " - "discarding database file"); - return false; - } - - for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { - if (!ignore_tag_items[i] && !tags[i]) { - error.Set(db_domain, - "Tag list mismatch, " - "discarding database file"); - return false; + throw FormatRuntimeError("Malformed line: %s", line); } } - LogDebug(db_domain, "reading DB"); + if (format < OLDEST_DB_FORMAT || format > DB_FORMAT) + throw std::runtime_error("Database format mismatch, " + "discarding database file"); - db_lock(); - success = directory_load(file, music_root, error); - db_unlock(); + for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) + if (IsTagEnabled(i) && !tags[i]) + throw std::runtime_error("Tag list mismatch, " + "discarding database file"); - return success; + const ScopeDatabaseLock protect; + directory_load(file, music_root); } diff -Nru mpd-0.19.21/src/db/plugins/simple/DatabaseSave.hxx mpd-0.20.9/src/db/plugins/simple/DatabaseSave.hxx --- mpd-0.19.21/src/db/plugins/simple/DatabaseSave.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/DatabaseSave.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,12 +23,14 @@ struct Directory; class BufferedOutputStream; class TextFile; -class Error; void db_save_internal(BufferedOutputStream &os, const Directory &root); -bool -db_load_internal(TextFile &file, Directory &root, Error &error); +/** + * Throws #std::runtime_error on error. + */ +void +db_load_internal(TextFile &file, Directory &root); #endif diff -Nru mpd-0.19.21/src/db/plugins/simple/Directory.cxx mpd-0.20.9/src/db/plugins/simple/Directory.cxx --- mpd-0.19.21/src/db/plugins/simple/Directory.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Directory.cxx 2017-05-08 15:16:57.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ #include "lib/icu/Collate.hxx" #include "fs/Traits.hxx" #include "util/Alloc.hxx" -#include "util/Error.hxx" +#include "util/DeleteDisposer.hxx" #include #include @@ -51,7 +51,7 @@ delete mounted_database; songs.clear_and_dispose(Song::Disposer()); - children.clear_and_dispose(Disposer()); + children.clear_and_dispose(DeleteDisposer()); } void @@ -61,11 +61,11 @@ assert(parent != nullptr); parent->children.erase_and_dispose(parent->children.iterator_to(*this), - Disposer()); + DeleteDisposer()); } const char * -Directory::GetName() const +Directory::GetName() const noexcept { assert(!IsRoot()); @@ -89,7 +89,7 @@ } const Directory * -Directory::FindChild(const char *name) const +Directory::FindChild(const char *name) const noexcept { assert(holding_db_lock()); @@ -101,7 +101,7 @@ } void -Directory::PruneEmpty() +Directory::PruneEmpty() noexcept { assert(holding_db_lock()); @@ -110,14 +110,15 @@ child->PruneEmpty(); if (child->IsEmpty()) - child = children.erase_and_dispose(child, Disposer()); + child = children.erase_and_dispose(child, + DeleteDisposer()); else ++child; } } Directory::LookupResult -Directory::LookupDirectory(const char *uri) +Directory::LookupDirectory(const char *uri) noexcept { assert(holding_db_lock()); assert(uri != nullptr); @@ -172,7 +173,7 @@ } void -Directory::RemoveSong(Song *song) +Directory::RemoveSong(Song *song) noexcept { assert(holding_db_lock()); assert(song != nullptr); @@ -182,7 +183,7 @@ } const Song * -Directory::FindSong(const char *name_utf8) const +Directory::FindSong(const char *name_utf8) const noexcept { assert(holding_db_lock()); assert(name_utf8 != nullptr); @@ -199,13 +200,13 @@ gcc_pure static bool -directory_cmp(const Directory &a, const Directory &b) +directory_cmp(const Directory &a, const Directory &b) noexcept { return IcuCollate(a.path.c_str(), b.path.c_str()) < 0; } void -Directory::Sort() +Directory::Sort() noexcept { assert(holding_db_lock()); @@ -216,62 +217,51 @@ child.Sort(); } -bool +void Directory::Walk(bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const + VisitPlaylist visit_playlist) const { - assert(!error.IsDefined()); - if (IsMount()) { assert(IsEmpty()); /* TODO: eliminate this unlock/lock; it is necessary because the child's SimpleDatabasePlugin::Visit() call will lock it again */ - db_unlock(); - bool result = WalkMount(GetPath(), *mounted_database, - recursive, filter, - visit_directory, visit_song, - visit_playlist, - error); - db_lock(); - return result; + const ScopeDatabaseUnlock unlock; + WalkMount(GetPath(), *mounted_database, + recursive, filter, + visit_directory, visit_song, + visit_playlist); + return; } if (visit_song) { for (auto &song : songs){ const LightSong song2 = song.Export(); - if ((filter == nullptr || filter->Match(song2)) && - !visit_song(song2, error)) - return false; + if (filter == nullptr || filter->Match(song2)) + visit_song(song2); } } if (visit_playlist) { for (const PlaylistInfo &p : playlists) - if (!visit_playlist(p, Export(), error)) - return false; + visit_playlist(p, Export()); } for (auto &child : children) { - if (visit_directory && - !visit_directory(child.Export(), error)) - return false; - - if (recursive && - !child.Walk(recursive, filter, - visit_directory, visit_song, visit_playlist, - error)) - return false; - } + if (visit_directory) + visit_directory(child.Export()); - return true; + if (recursive) + child.Walk(recursive, filter, + visit_directory, visit_song, + visit_playlist); + } } LightDirectory -Directory::Export() const +Directory::Export() const noexcept { return LightDirectory(GetPath(), mtime); } diff -Nru mpd-0.19.21/src/db/plugins/simple/Directory.hxx mpd-0.20.9/src/db/plugins/simple/Directory.hxx --- mpd-0.19.21/src/db/plugins/simple/Directory.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Directory.hxx 2017-06-03 19:57:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -43,9 +43,7 @@ */ static constexpr unsigned DEVICE_CONTAINER = -2; -struct db_visitor; class SongFilter; -class Error; class Database; struct Directory { @@ -53,12 +51,6 @@ typedef boost::intrusive::link_mode LinkMode; typedef boost::intrusive::list_member_hook Hook; - struct Disposer { - void operator()(Directory *directory) const { - delete directory; - } - }; - /** * Pointers to the siblings of this directory within the * parent directory. It is unused (undefined) in the root @@ -94,7 +86,7 @@ Directory *parent; time_t mtime; - unsigned inode, device; + uint64_t inode, device; std::string path; @@ -142,10 +134,10 @@ * Caller must lock the #db_mutex. */ gcc_pure - const Directory *FindChild(const char *name) const; + const Directory *FindChild(const char *name) const noexcept; gcc_pure - Directory *FindChild(const char *name) { + Directory *FindChild(const char *name) noexcept { const Directory *cthis = this; return const_cast(cthis->FindChild(name)); } @@ -185,17 +177,17 @@ * @return the Directory, or nullptr if none was found */ gcc_pure - LookupResult LookupDirectory(const char *uri); + LookupResult LookupDirectory(const char *uri) noexcept; gcc_pure - bool IsEmpty() const { + bool IsEmpty() const noexcept { return children.empty() && songs.empty() && playlists.empty(); } gcc_pure - const char *GetPath() const { + const char *GetPath() const noexcept { return path.c_str(); } @@ -203,13 +195,13 @@ * Returns the base name of the directory. */ gcc_pure - const char *GetName() const; + const char *GetName() const noexcept; /** * Is this the root directory of the music database? */ gcc_pure - bool IsRoot() const { + bool IsRoot() const noexcept { return parent == nullptr; } @@ -237,10 +229,10 @@ * Caller must lock the #db_mutex. */ gcc_pure - const Song *FindSong(const char *name_utf8) const; + const Song *FindSong(const char *name_utf8) const noexcept; gcc_pure - Song *FindSong(const char *name_utf8) { + Song *FindSong(const char *name_utf8) noexcept { const Directory *cthis = this; return const_cast(cthis->FindSong(name_utf8)); } @@ -256,30 +248,29 @@ * invalidates the song object, because the "parent" attribute becomes * stale), but does not free it. */ - void RemoveSong(Song *song); + void RemoveSong(Song *song) noexcept; /** * Caller must lock the #db_mutex. */ - void PruneEmpty(); + void PruneEmpty() noexcept; /** * Sort all directory entries recursively. * * Caller must lock the #db_mutex. */ - void Sort(); + void Sort() noexcept; /** * Caller must lock #db_mutex. */ - bool Walk(bool recursive, const SongFilter *match, + void Walk(bool recursive, const SongFilter *match, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const; + VisitPlaylist visit_playlist) const; gcc_pure - LightDirectory Export() const; + LightDirectory Export() const noexcept; }; #endif diff -Nru mpd-0.19.21/src/db/plugins/simple/DirectorySave.cxx mpd-0.20.9/src/db/plugins/simple/DirectorySave.cxx --- mpd-0.19.21/src/db/plugins/simple/DirectorySave.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/DirectorySave.cxx 2017-05-08 15:15:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,12 +26,10 @@ #include "PlaylistDatabase.hxx" #include "fs/io/TextFile.hxx" #include "fs/io/BufferedOutputStream.hxx" -#include "util/StringUtil.hxx" +#include "util/StringCompare.hxx" #include "util/NumberParser.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" -#include #include #define DIRECTORY_DIR "directory: " @@ -40,11 +38,9 @@ #define DIRECTORY_BEGIN "begin: " #define DIRECTORY_END "end: " -static constexpr Domain directory_domain("directory"); - gcc_const static const char * -DeviceToTypeString(unsigned device) +DeviceToTypeString(unsigned device) noexcept { switch (device) { case DEVICE_INARCHIVE: @@ -60,7 +56,7 @@ gcc_pure static unsigned -ParseTypeString(const char *type) +ParseTypeString(const char *type) noexcept { if (strcmp(type, "archive") == 0) return DEVICE_INARCHIVE; @@ -90,9 +86,6 @@ if (!child.IsMount()) directory_save(os, child); - - if (!os.Check()) - return; } for (const auto &song : directory.songs) @@ -107,12 +100,11 @@ static bool ParseLine(Directory &directory, const char *line) { - if (StringStartsWith(line, DIRECTORY_MTIME)) { - directory.mtime = - ParseUint64(line + sizeof(DIRECTORY_MTIME) - 1); - } else if (StringStartsWith(line, DIRECTORY_TYPE)) { - directory.device = - ParseTypeString(line + sizeof(DIRECTORY_TYPE) - 1); + const char *p; + if ((p = StringAfterPrefix(line, DIRECTORY_MTIME))) { + directory.mtime = ParseUint64(p); + } else if ((p = StringAfterPrefix(line, DIRECTORY_TYPE))) { + directory.device = ParseTypeString(p); } else return false; @@ -120,88 +112,61 @@ } static Directory * -directory_load_subdir(TextFile &file, Directory &parent, const char *name, - Error &error) +directory_load_subdir(TextFile &file, Directory &parent, const char *name) { - bool success; - - if (parent.FindChild(name) != nullptr) { - error.Format(directory_domain, - "Duplicate subdirectory '%s'", name); - return nullptr; - } + if (parent.FindChild(name) != nullptr) + throw FormatRuntimeError("Duplicate subdirectory '%s'", name); Directory *directory = parent.CreateChild(name); - while (true) { - const char *line = file.ReadLine(); - if (line == nullptr) { - error.Set(directory_domain, "Unexpected end of file"); - directory->Delete(); - return nullptr; - } + try { + while (true) { + const char *line = file.ReadLine(); + if (line == nullptr) + throw std::runtime_error("Unexpected end of file"); - if (StringStartsWith(line, DIRECTORY_BEGIN)) - break; + if (StringStartsWith(line, DIRECTORY_BEGIN)) + break; - if (!ParseLine(*directory, line)) { - error.Format(directory_domain, - "Malformed line: %s", line); - directory->Delete(); - return nullptr; + if (!ParseLine(*directory, line)) + throw FormatRuntimeError("Malformed line: %s", line); } - } - success = directory_load(file, *directory, error); - if (!success) { + directory_load(file, *directory); + } catch (...) { directory->Delete(); - return nullptr; + throw; } return directory; } -bool -directory_load(TextFile &file, Directory &directory, Error &error) +void +directory_load(TextFile &file, Directory &directory) { const char *line; while ((line = file.ReadLine()) != nullptr && !StringStartsWith(line, DIRECTORY_END)) { - if (StringStartsWith(line, DIRECTORY_DIR)) { - Directory *subdir = - directory_load_subdir(file, directory, - line + sizeof(DIRECTORY_DIR) - 1, - error); - if (subdir == nullptr) - return false; - } else if (StringStartsWith(line, SONG_BEGIN)) { - const char *name = line + sizeof(SONG_BEGIN) - 1; - - if (directory.FindSong(name) != nullptr) { - error.Format(directory_domain, - "Duplicate song '%s'", name); - return false; - } - - DetachedSong *song = song_load(file, name, error); - if (song == nullptr) - return false; + const char *p; + if ((p = StringAfterPrefix(line, DIRECTORY_DIR))) { + directory_load_subdir(file, directory, p); + } else if ((p = StringAfterPrefix(line, SONG_BEGIN))) { + const char *name = p; + + if (directory.FindSong(name) != nullptr) + throw FormatRuntimeError("Duplicate song '%s'", name); + + DetachedSong *song = song_load(file, name); directory.AddSong(Song::NewFrom(std::move(*song), directory)); delete song; - } else if (StringStartsWith(line, PLAYLIST_META_BEGIN)) { - const char *name = line + sizeof(PLAYLIST_META_BEGIN) - 1; - if (!playlist_metadata_load(file, directory.playlists, - name, error)) - return false; + } else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) { + const char *name = p; + playlist_metadata_load(file, directory.playlists, name); } else { - error.Format(directory_domain, - "Malformed line: %s", line); - return false; + throw FormatRuntimeError("Malformed line: %s", line); } } - - return true; } diff -Nru mpd-0.19.21/src/db/plugins/simple/DirectorySave.hxx mpd-0.20.9/src/db/plugins/simple/DirectorySave.hxx --- mpd-0.19.21/src/db/plugins/simple/DirectorySave.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/DirectorySave.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,12 +23,14 @@ struct Directory; class TextFile; class BufferedOutputStream; -class Error; void directory_save(BufferedOutputStream &os, const Directory &directory); -bool -directory_load(TextFile &file, Directory &directory, Error &error); +/** + * Throws #std::runtime_error on error. + */ +void +directory_load(TextFile &file, Directory &directory); #endif diff -Nru mpd-0.19.21/src/db/plugins/simple/Mount.cxx mpd-0.20.9/src/db/plugins/simple/Mount.cxx --- mpd-0.19.21/src/db/plugins/simple/Mount.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Mount.cxx 2017-03-01 16:30:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,10 +22,15 @@ #include "PrefixedLightSong.hxx" #include "db/Selection.hxx" #include "db/LightDirectory.hxx" -#include "db/LightSong.hxx" #include "db/Interface.hxx" #include "fs/Traits.hxx" -#include "util/Error.hxx" + +#ifdef _LIBCPP_VERSION +/* workaround for "error: incomplete type 'PlaylistInfo' used in type + trait expression" with libc++ version 3900 (from Android NDK + r13b) */ +#include "db/PlaylistInfo.hxx" +#endif #include @@ -42,55 +47,51 @@ } }; -static bool +static void PrefixVisitDirectory(const char *base, const VisitDirectory &visit_directory, - const LightDirectory &directory, Error &error) + const LightDirectory &directory) { - return visit_directory(PrefixedLightDirectory(directory, base), error); + visit_directory(PrefixedLightDirectory(directory, base)); } -static bool +static void PrefixVisitSong(const char *base, const VisitSong &visit_song, - const LightSong &song, Error &error) + const LightSong &song) { - return visit_song(PrefixedLightSong(song, base), error); + visit_song(PrefixedLightSong(song, base)); } -static bool +static void PrefixVisitPlaylist(const char *base, const VisitPlaylist &visit_playlist, const PlaylistInfo &playlist, - const LightDirectory &directory, - Error &error) + const LightDirectory &directory) { - return visit_playlist(playlist, - PrefixedLightDirectory(directory, base), - error); + visit_playlist(playlist, + PrefixedLightDirectory(directory, base)); } -bool +void WalkMount(const char *base, const Database &db, bool recursive, const SongFilter *filter, const VisitDirectory &visit_directory, const VisitSong &visit_song, - const VisitPlaylist &visit_playlist, - Error &error) + const VisitPlaylist &visit_playlist) { using namespace std::placeholders; VisitDirectory vd; if (visit_directory) vd = std::bind(PrefixVisitDirectory, - base, std::ref(visit_directory), _1, _2); + base, std::ref(visit_directory), _1); VisitSong vs; if (visit_song) vs = std::bind(PrefixVisitSong, - base, std::ref(visit_song), _1, _2); + base, std::ref(visit_song), _1); VisitPlaylist vp; if (visit_playlist) vp = std::bind(PrefixVisitPlaylist, - base, std::ref(visit_playlist), _1, _2, _3); + base, std::ref(visit_playlist), _1, _2); - return db.Visit(DatabaseSelection("", recursive, filter), - vd, vs, vp, error); + db.Visit(DatabaseSelection("", recursive, filter), vd, vs, vp); } diff -Nru mpd-0.19.21/src/db/plugins/simple/Mount.hxx mpd-0.20.9/src/db/plugins/simple/Mount.hxx --- mpd-0.19.21/src/db/plugins/simple/Mount.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Mount.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,13 +24,11 @@ class Database; class SongFilter; -class Error; -bool +void WalkMount(const char *base, const Database &db, bool recursive, const SongFilter *filter, const VisitDirectory &visit_directory, const VisitSong &visit_song, - const VisitPlaylist &visit_playlist, - Error &error); + const VisitPlaylist &visit_playlist); #endif diff -Nru mpd-0.19.21/src/db/plugins/simple/PrefixedLightSong.hxx mpd-0.20.9/src/db/plugins/simple/PrefixedLightSong.hxx --- mpd-0.19.21/src/db/plugins/simple/PrefixedLightSong.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/PrefixedLightSong.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/plugins/simple/SimpleDatabasePlugin.cxx mpd-0.20.9/src/db/plugins/simple/SimpleDatabasePlugin.cxx --- mpd-0.19.21/src/db/plugins/simple/SimpleDatabasePlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/SimpleDatabasePlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,50 +23,58 @@ #include "db/DatabasePlugin.hxx" #include "db/Selection.hxx" #include "db/Helpers.hxx" +#include "db/Stats.hxx" #include "db/UniqueTags.hxx" #include "db/LightDirectory.hxx" #include "Directory.hxx" #include "Song.hxx" -#include "SongFilter.hxx" #include "DatabaseSave.hxx" #include "db/DatabaseLock.hxx" #include "db/DatabaseError.hxx" #include "fs/io/TextFile.hxx" #include "fs/io/BufferedOutputStream.hxx" #include "fs/io/FileOutputStream.hxx" -#include "config/ConfigData.hxx" +#include "fs/FileInfo.hxx" +#include "config/Block.hxx" #include "fs/FileSystem.hxx" #include "util/CharUtil.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB #include "fs/io/GzipOutputStream.hxx" #endif +#include + #include static constexpr Domain simple_db_domain("simple_db"); -inline SimpleDatabase::SimpleDatabase() +inline SimpleDatabase::SimpleDatabase(const ConfigBlock &block) :Database(simple_db_plugin), - path(AllocatedPath::Null()), -#ifdef HAVE_ZLIB - compress(true), + path(block.GetPath("path")), +#ifdef ENABLE_ZLIB + compress(block.GetBlockValue("compress", true)), #endif - cache_path(AllocatedPath::Null()), - prefixed_light_song(nullptr) {} + cache_path(block.GetPath("cache_directory")), + prefixed_light_song(nullptr) +{ + if (path.IsNull()) + throw std::runtime_error("No \"path\" parameter specified"); + + path_utf8 = path.ToUTF8(); +} inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path, -#ifndef HAVE_ZLIB +#ifndef ENABLE_ZLIB gcc_unused #endif bool _compress) :Database(simple_db_plugin), path(std::move(_path)), path_utf8(path.ToUTF8()), -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB compress(_compress), #endif cache_path(AllocatedPath::Null()), @@ -76,132 +84,83 @@ Database * SimpleDatabase::Create(gcc_unused EventLoop &loop, gcc_unused DatabaseListener &listener, - const config_param ¶m, Error &error) + const ConfigBlock &block) { - SimpleDatabase *db = new SimpleDatabase(); - if (!db->Configure(param, error)) { - delete db; - db = nullptr; - } - - return db; -} - -bool -SimpleDatabase::Configure(const config_param ¶m, Error &error) -{ - path = param.GetBlockPath("path", error); - if (path.IsNull()) { - if (!error.IsDefined()) - error.Set(simple_db_domain, - "No \"path\" parameter specified"); - return false; - } - - path_utf8 = path.ToUTF8(); - - cache_path = param.GetBlockPath("cache_directory", error); - if (path.IsNull() && error.IsDefined()) - return false; - -#ifdef HAVE_ZLIB - compress = param.GetBlockValue("compress", compress); -#endif - - return true; + return new SimpleDatabase(block); } -bool -SimpleDatabase::Check(Error &error) const +void +SimpleDatabase::Check() const { assert(!path.IsNull()); /* Check if the file exists */ - if (!CheckAccess(path)) { + if (!PathExists(path)) { /* If the file doesn't exist, we can't check if we can write * it, so we are going to try to get the directory path, and * see if we can write a file in that */ const auto dirPath = path.GetDirectoryName(); /* Check that the parent part of the path is a directory */ - struct stat st; - if (!StatFile(dirPath, st)) { - error.FormatErrno("Couldn't stat parent directory of db file " - "\"%s\"", - path_utf8.c_str()); - return false; - } + FileInfo fi; - if (!S_ISDIR(st.st_mode)) { - error.Format(simple_db_domain, - "Couldn't create db file \"%s\" because the " - "parent path is not a directory", - path_utf8.c_str()); - return false; + try { + fi = FileInfo(dirPath); + } catch (...) { + std::throw_with_nested(std::runtime_error("On parent directory of db file")); } + if (!fi.IsDirectory()) + throw std::runtime_error("Couldn't create db file \"" + + path_utf8 + "\" because the " + "parent path is not a directory"); + #ifndef WIN32 /* Check if we can write to the directory */ if (!CheckAccess(dirPath, X_OK | W_OK)) { const int e = errno; const std::string dirPath_utf8 = dirPath.ToUTF8(); - error.FormatErrno(e, "Can't create db file in \"%s\"", + throw FormatErrno(e, "Can't create db file in \"%s\"", dirPath_utf8.c_str()); - return false; } #endif - return true; + + return; } /* Path exists, now check if it's a regular file */ - struct stat st; - if (!StatFile(path, st)) { - error.FormatErrno("Couldn't stat db file \"%s\"", - path_utf8.c_str()); - return false; - } + const FileInfo fi(path); - if (!S_ISREG(st.st_mode)) { - error.Format(simple_db_domain, - "db file \"%s\" is not a regular file", - path_utf8.c_str()); - return false; - } + if (!fi.IsRegular()) + throw std::runtime_error("db file \"" + path_utf8 + "\" is not a regular file"); #ifndef WIN32 /* And check that we can write to it */ - if (!CheckAccess(path, R_OK | W_OK)) { - error.FormatErrno("Can't open db file \"%s\" for reading/writing", + if (!CheckAccess(path, R_OK | W_OK)) + throw FormatErrno("Can't open db file \"%s\" for reading/writing", path_utf8.c_str()); - return false; - } #endif - - return true; } -bool -SimpleDatabase::Load(Error &error) +void +SimpleDatabase::Load() { assert(!path.IsNull()); assert(root != nullptr); - TextFile file(path, error); - if (file.HasFailed()) - return false; + TextFile file(path); - if (!db_load_internal(file, *root, error) || !file.Check(error)) - return false; + LogDebug(simple_db_domain, "reading DB"); - struct stat st; - if (StatFile(path, st)) - mtime = st.st_mtime; + db_load_internal(file, *root); - return true; + FileInfo fi; + if (GetFileInfo(path, fi)) + mtime = fi.GetModificationTime(); } -bool -SimpleDatabase::Open(Error &error) +void +SimpleDatabase::Open() { assert(prefixed_light_song == nullptr); @@ -212,19 +171,17 @@ borrowed_song_count = 0; #endif - if (!Load(error)) { - delete root; + try { + Load(); + } catch (const std::exception &e) { + LogError(e); - LogError(error); - error.Clear(); + delete root; - if (!Check(error)) - return false; + Check(); root = Directory::NewRoot(); } - - return true; } void @@ -238,22 +195,22 @@ } const LightSong * -SimpleDatabase::GetSong(const char *uri, Error &error) const +SimpleDatabase::GetSong(const char *uri) const { assert(root != nullptr); assert(prefixed_light_song == nullptr); assert(borrowed_song_count == 0); - db_lock(); + ScopeDatabaseLock protect; auto r = root->LookupDirectory(uri); if (r.directory->IsMount()) { /* pass the request to the mounted database */ - db_unlock(); + protect.unlock(); const LightSong *song = - r.directory->mounted_database->GetSong(r.uri, error); + r.directory->mounted_database->GetSong(r.uri); if (song == nullptr) return nullptr; @@ -262,29 +219,21 @@ return prefixed_light_song; } - if (r.uri == nullptr) { + if (r.uri == nullptr) /* it's a directory */ - db_unlock(); - error.Format(db_domain, DB_NOT_FOUND, - "No such song: %s", uri); - return nullptr; - } + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such song"); - if (strchr(r.uri, '/') != nullptr) { + if (strchr(r.uri, '/') != nullptr) /* refers to a URI "below" the actual song */ - db_unlock(); - error.Format(db_domain, DB_NOT_FOUND, - "No such song: %s", uri); - return nullptr; - } + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such song"); const Song *song = r.directory->FindSong(r.uri); - db_unlock(); - if (song == nullptr) { - error.Format(db_domain, DB_NOT_FOUND, - "No such song: %s", uri); - return nullptr; - } + protect.unlock(); + if (song == nullptr) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such song"); light_song = song->Export(); @@ -312,12 +261,11 @@ #endif } -bool +void SimpleDatabase::Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const + VisitPlaylist visit_playlist) const { ScopeDatabaseLock protect; @@ -325,14 +273,13 @@ if (r.uri == nullptr) { /* it's a directory */ - if (selection.recursive && visit_directory && - !visit_directory(r.directory->Export(), error)) - return false; - - return r.directory->Walk(selection.recursive, selection.filter, - visit_directory, visit_song, - visit_playlist, - error); + if (selection.recursive && visit_directory) + visit_directory(r.directory->Export()); + + r.directory->Walk(selection.recursive, selection.filter, + visit_directory, visit_song, + visit_playlist); + return; } if (strchr(r.uri, '/') == nullptr) { @@ -340,65 +287,56 @@ Song *song = r.directory->FindSong(r.uri); if (song != nullptr) { const LightSong song2 = song->Export(); - return !selection.Match(song2) || - visit_song(song2, error); + if (selection.Match(song2)) + visit_song(song2); + + return; } } } - error.Set(db_domain, DB_NOT_FOUND, "No such directory"); - return false; + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such directory"); } -bool +void SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) const { - return ::VisitUniqueTags(*this, selection, tag_type, group_mask, - visit_tag, - error); + ::VisitUniqueTags(*this, selection, tag_type, group_mask, visit_tag); } -bool -SimpleDatabase::GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, Error &error) const +DatabaseStats +SimpleDatabase::GetStats(const DatabaseSelection &selection) const { - return ::GetStats(*this, selection, stats, error); + return ::GetStats(*this, selection); } -bool -SimpleDatabase::Save(Error &error) +void +SimpleDatabase::Save() { - db_lock(); - - LogDebug(simple_db_domain, "removing empty directories from DB"); - root->PruneEmpty(); + { + const ScopeDatabaseLock protect; - LogDebug(simple_db_domain, "sorting DB"); - root->Sort(); + LogDebug(simple_db_domain, "removing empty directories from DB"); + root->PruneEmpty(); - db_unlock(); + LogDebug(simple_db_domain, "sorting DB"); + root->Sort(); + } LogDebug(simple_db_domain, "writing DB"); - FileOutputStream fos(path, error); - if (!fos.IsDefined()) - return false; + FileOutputStream fos(path); OutputStream *os = &fos; -#ifdef HAVE_ZLIB - GzipOutputStream *gzip = nullptr; +#ifdef ENABLE_ZLIB + std::unique_ptr gzip; if (compress) { - gzip = new GzipOutputStream(*os, error); - if (!gzip->IsDefined()) { - delete gzip; - return false; - } - - os = gzip; + gzip.reset(new GzipOutputStream(*os)); + os = gzip.get(); } #endif @@ -406,34 +344,24 @@ db_save_internal(bos, *root); - if (!bos.Flush(error)) { -#ifdef HAVE_ZLIB - delete gzip; -#endif - return false; - } + bos.Flush(); -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB if (gzip != nullptr) { - bool success = gzip->Flush(error); - delete gzip; - if (!success) - return false; + gzip->Flush(); + gzip.reset(); } #endif - if (!fos.Commit(error)) - return false; + fos.Commit(); - struct stat st; - if (StatFile(path, st)) - mtime = st.st_mtime; - - return true; + FileInfo fi; + if (GetFileInfo(path, fi)) + mtime = fi.GetModificationTime(); } -bool -SimpleDatabase::Mount(const char *uri, Database *db, Error &error) +void +SimpleDatabase::Mount(const char *uri, Database *db) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ @@ -445,21 +373,16 @@ ScopeDatabaseLock protect; auto r = root->LookupDirectory(uri); - if (r.uri == nullptr) { - error.Format(db_domain, DB_CONFLICT, - "Already exists: %s", uri); - return false; - } - - if (strchr(r.uri, '/') != nullptr) { - error.Format(db_domain, DB_NOT_FOUND, - "Parent not found: %s", uri); - return false; - } + if (r.uri == nullptr) + throw DatabaseError(DatabaseErrorCode::CONFLICT, + "Already exists"); + + if (strchr(r.uri, '/') != nullptr) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "Parent not found"); Directory *mnt = r.directory->CreateChild(r.uri); mnt->mounted_database = db; - return true; } static constexpr bool @@ -474,39 +397,40 @@ return !IsSafeChar(ch); } -bool -SimpleDatabase::Mount(const char *local_uri, const char *storage_uri, - Error &error) -{ - if (cache_path.IsNull()) { - error.Format(db_domain, DB_NOT_FOUND, - "No 'cache_directory' configured"); - return false; - } +void +SimpleDatabase::Mount(const char *local_uri, const char *storage_uri) +{ + if (cache_path.IsNull()) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No 'cache_directory' configured"); std::string name(storage_uri); std::replace_if(name.begin(), name.end(), IsUnsafeChar, '_'); -#ifndef HAVE_ZLIB + const auto name_fs = AllocatedPath::FromUTF8Throw(name.c_str()); + +#ifndef ENABLE_ZLIB constexpr bool compress = false; #endif auto db = new SimpleDatabase(AllocatedPath::Build(cache_path, - name.c_str()), + name_fs.c_str()), compress); - if (!db->Open(error)) { + try { + db->Open(); + } catch (...) { delete db; - return false; + throw; } // TODO: update the new database instance? - if (!Mount(local_uri, db, error)) { + try { + Mount(local_uri, db); + } catch (...) { db->Close(); delete db; - return false; + throw; } - - return true; } Database * diff -Nru mpd-0.19.21/src/db/plugins/simple/SimpleDatabasePlugin.hxx mpd-0.20.9/src/db/plugins/simple/SimpleDatabasePlugin.hxx --- mpd-0.19.21/src/db/plugins/simple/SimpleDatabasePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/SimpleDatabasePlugin.hxx 2017-06-03 20:00:39.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ #include -struct config_param; +struct ConfigBlock; struct Directory; struct DatabasePlugin; class EventLoop; @@ -39,7 +39,7 @@ AllocatedPath path; std::string path_utf8; -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB bool compress; #endif @@ -67,23 +67,22 @@ mutable unsigned borrowed_song_count; #endif - SimpleDatabase(); + SimpleDatabase(const ConfigBlock &block); SimpleDatabase(AllocatedPath &&_path, bool _compress); public: static Database *Create(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); gcc_pure - Directory &GetRoot() { + Directory &GetRoot() noexcept { assert(root != NULL); return *root; } - bool Save(Error &error); + void Save(); /** * Returns true if there is a valid database file on the disk. @@ -97,49 +96,48 @@ * success, this object gains ownership of the given #Database */ gcc_nonnull_all - bool Mount(const char *uri, Database *db, Error &error); + void Mount(const char *uri, Database *db); + /** + * Throws #std::runtime_error on error. + */ gcc_nonnull_all - bool Mount(const char *local_uri, const char *storage_uri, - Error &error); + void Mount(const char *local_uri, const char *storage_uri); gcc_nonnull_all bool Unmount(const char *uri); /* virtual methods from class Database */ - virtual bool Open(Error &error) override; - virtual void Close() override; + void Open() override; + void Close() override; - const LightSong *GetSong(const char *uri_utf8, - Error &error) const override; + const LightSong *GetSong(const char *uri_utf8) const override; void ReturnSong(const LightSong *song) const override; - virtual bool Visit(const DatabaseSelection &selection, - VisitDirectory visit_directory, - VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const override; - - virtual bool VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const override; - - virtual bool GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, - Error &error) const override; + void Visit(const DatabaseSelection &selection, + VisitDirectory visit_directory, + VisitSong visit_song, + VisitPlaylist visit_playlist) const override; + + void VisitUniqueTags(const DatabaseSelection &selection, + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) const override; + + DatabaseStats GetStats(const DatabaseSelection &selection) const override; - virtual time_t GetUpdateStamp() const override { + time_t GetUpdateStamp() const noexcept override { return mtime; } private: - bool Configure(const config_param ¶m, Error &error); + void Configure(const ConfigBlock &block); - gcc_pure - bool Check(Error &error) const; + void Check() const; - bool Load(Error &error); + /** + * Throws #std::runtime_error on error. + */ + void Load(); Database *LockUmountSteal(const char *uri); }; diff -Nru mpd-0.19.21/src/db/plugins/simple/Song.cxx mpd-0.20.9/src/db/plugins/simple/Song.cxx --- mpd-0.19.21/src/db/plugins/simple/Song.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Song.cxx 2017-05-08 15:15:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,6 @@ #include #include -#include inline Song::Song(const char *_uri, size_t uri_length, Directory &_parent) :parent(&_parent), mtime(0), @@ -78,7 +77,7 @@ } std::string -Song::GetURI() const +Song::GetURI() const noexcept { assert(*uri); @@ -97,7 +96,7 @@ } LightSong -Song::Export() const +Song::Export() const noexcept { LightSong dest; dest.directory = parent->IsRoot() diff -Nru mpd-0.19.21/src/db/plugins/simple/Song.hxx mpd-0.20.9/src/db/plugins/simple/Song.hxx --- mpd-0.19.21/src/db/plugins/simple/Song.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/Song.hxx 2017-05-08 15:15:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,7 @@ #ifndef MPD_SONG_HXX #define MPD_SONG_HXX +#include "check.h" #include "Chrono.hxx" #include "tag/Tag.hxx" #include "Compiler.h" @@ -28,13 +29,13 @@ #include -#include #include struct LightSong; struct Directory; class DetachedSong; class Storage; +class ArchiveFile; /** * A song file inside the configured music directory. Internal @@ -109,17 +110,23 @@ void Free(); bool UpdateFile(Storage &storage); - bool UpdateFileInArchive(const Storage &storage); + +#ifdef ENABLE_ARCHIVE + static Song *LoadFromArchive(ArchiveFile &archive, + const char *name_utf8, + Directory &parent); + bool UpdateFileInArchive(ArchiveFile &archive); +#endif /** * Returns the URI of the song in UTF-8 encoding, including its * location within the music directory. */ gcc_pure - std::string GetURI() const; + std::string GetURI() const noexcept; gcc_pure - LightSong Export() const; + LightSong Export() const noexcept; }; typedef boost::intrusive::list static int -compare_utf8_string(const char *a, const char *b) +compare_utf8_string(const char *a, const char *b) noexcept { if (a == nullptr) return b == nullptr ? 0 : -1; @@ -42,8 +42,7 @@ * nullptr. */ static int -compare_string_tag_item(const Tag &a, const Tag &b, - TagType type) +compare_string_tag_item(const Tag &a, const Tag &b, TagType type) noexcept { return compare_utf8_string(a.GetValue(type), b.GetValue(type)); @@ -54,7 +53,7 @@ * (e.g. disc or track number). Either one may be nullptr. */ static int -compare_number_string(const char *a, const char *b) +compare_number_string(const char *a, const char *b) noexcept { long ai = a == nullptr ? 0 : strtol(a, nullptr, 10); long bi = b == nullptr ? 0 : strtol(b, nullptr, 10); @@ -69,7 +68,7 @@ } static int -compare_tag_item(const Tag &a, const Tag &b, TagType type) +compare_tag_item(const Tag &a, const Tag &b, TagType type) noexcept { return compare_number_string(a.GetValue(type), b.GetValue(type)); @@ -78,7 +77,7 @@ /* Only used for sorting/searchin a songvec, not general purpose compares */ gcc_pure static bool -song_cmp(const Song &a, const Song &b) +song_cmp(const Song &a, const Song &b) noexcept { int ret; @@ -102,7 +101,7 @@ } void -song_list_sort(SongList &songs) +song_list_sort(SongList &songs) noexcept { songs.sort(song_cmp); } diff -Nru mpd-0.19.21/src/db/plugins/simple/SongSort.hxx mpd-0.20.9/src/db/plugins/simple/SongSort.hxx --- mpd-0.19.21/src/db/plugins/simple/SongSort.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/simple/SongSort.hxx 2017-05-08 15:14:56.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,9 +22,7 @@ #include "Song.hxx" -struct list_head; - void -song_list_sort(SongList &songs); +song_list_sort(SongList &songs) noexcept; #endif diff -Nru mpd-0.19.21/src/db/plugins/upnp/ContentDirectoryService.cxx mpd-0.20.9/src/db/plugins/upnp/ContentDirectoryService.cxx --- mpd-0.19.21/src/db/plugins/upnp/ContentDirectoryService.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/ContentDirectoryService.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,32 +19,33 @@ #include "config.h" #include "lib/upnp/ContentDirectoryService.hxx" -#include "lib/upnp/Domain.hxx" #include "lib/upnp/ixmlwrap.hxx" +#include "lib/upnp/UniqueIxml.hxx" #include "lib/upnp/Action.hxx" #include "Directory.hxx" #include "util/NumberParser.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" +#include "util/ScopeExit.hxx" #include -static bool -ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response, Error &error) +static void +ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response) { const char *p = ixmlwrap::getFirstElementValue(response, "Result"); if (p == nullptr) p = ""; - return dirbuf.parse(p, error); + dirbuf.Parse(p); } -inline bool +inline void ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl, const char *objectId, unsigned offset, unsigned count, UPnPDirContent &dirbuf, - unsigned &didreadp, unsigned &totalp, - Error &error) const + unsigned &didreadp, + unsigned &totalp) const { // Create request char ofbuf[100], cntbuf[100]; @@ -59,21 +60,19 @@ "SortCriteria", "", "StartingIndex", ofbuf, "RequestedCount", cntbuf); - if (request == nullptr) { - error.Set(upnp_domain, "UpnpMakeAction() failed"); - return false; - } + if (request == nullptr) + throw std::runtime_error("UpnpMakeAction() failed"); + + AtScopeExit(request) { ixmlDocument_free(request); }; IXML_Document *response; int code = UpnpSendAction(hdl, m_actionURL.c_str(), m_serviceType.c_str(), 0 /*devUDN*/, request, &response); - ixmlDocument_free(request); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSendAction() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSendAction() failed: %s", + UpnpGetErrorMessage(code)); + + AtScopeExit(response) { ixmlDocument_free(response); }; const char *value = ixmlwrap::getFirstElementValue(response, "NumberReturned"); didreadp = value != nullptr @@ -84,122 +83,104 @@ if (value != nullptr) totalp = ParseUnsigned(value); - bool success = ReadResultTag(dirbuf, response, error); - ixmlDocument_free(response); - return success; + ReadResultTag(dirbuf, response); } -bool +UPnPDirContent ContentDirectoryService::readDir(UpnpClient_Handle handle, - const char *objectId, - UPnPDirContent &dirbuf, - Error &error) const + const char *objectId) const { + UPnPDirContent dirbuf; unsigned offset = 0, total = -1, count; do { - if (!readDirSlice(handle, objectId, offset, m_rdreqcnt, dirbuf, - count, total, error)) - return false; + readDirSlice(handle, objectId, offset, m_rdreqcnt, dirbuf, + count, total); offset += count; } while (count > 0 && offset < total); - return true; + return dirbuf; } -bool +UPnPDirContent ContentDirectoryService::search(UpnpClient_Handle hdl, const char *objectId, - const char *ss, - UPnPDirContent &dirbuf, - Error &error) const + const char *ss) const { + UPnPDirContent dirbuf; unsigned offset = 0, total = -1, count; do { char ofbuf[100]; sprintf(ofbuf, "%d", offset); - IXML_Document *request = - MakeActionHelper("Search", m_serviceType.c_str(), - "ContainerID", objectId, - "SearchCriteria", ss, - "Filter", "*", - "SortCriteria", "", - "StartingIndex", ofbuf, - "RequestedCount", "0"); // Setting a value here gets twonky into fits - if (request == 0) { - error.Set(upnp_domain, "UpnpMakeAction() failed"); - return false; - } + UniqueIxmlDocument request(MakeActionHelper("Search", m_serviceType.c_str(), + "ContainerID", objectId, + "SearchCriteria", ss, + "Filter", "*", + "SortCriteria", "", + "StartingIndex", ofbuf, + "RequestedCount", "0")); // Setting a value here gets twonky into fits + if (!request) + throw std::runtime_error("UpnpMakeAction() failed"); - IXML_Document *response; + IXML_Document *_response; auto code = UpnpSendAction(hdl, m_actionURL.c_str(), m_serviceType.c_str(), - 0 /*devUDN*/, request, &response); - ixmlDocument_free(request); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSendAction() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } + 0 /*devUDN*/, + request.get(), &_response); + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSendAction() failed: %s", + UpnpGetErrorMessage(code)); + + UniqueIxmlDocument response(_response); const char *value = - ixmlwrap::getFirstElementValue(response, "NumberReturned"); + ixmlwrap::getFirstElementValue(response.get(), + "NumberReturned"); count = value != nullptr ? ParseUnsigned(value) : 0; offset += count; - value = ixmlwrap::getFirstElementValue(response, "TotalMatches"); + value = ixmlwrap::getFirstElementValue(response.get(), + "TotalMatches"); if (value != nullptr) total = ParseUnsigned(value); - bool success = ReadResultTag(dirbuf, response, error); - ixmlDocument_free(response); - if (!success) - return false; + ReadResultTag(dirbuf, response.get()); } while (count > 0 && offset < total); - return true; + return dirbuf; } -bool +UPnPDirContent ContentDirectoryService::getMetadata(UpnpClient_Handle hdl, - const char *objectId, - UPnPDirContent &dirbuf, - Error &error) const + const char *objectId) const { // Create request - IXML_Document *request = - MakeActionHelper("Browse", m_serviceType.c_str(), - "ObjectID", objectId, - "BrowseFlag", "BrowseMetadata", - "Filter", "*", - "SortCriteria", "", - "StartingIndex", "0", - "RequestedCount", "1"); - if (request == nullptr) { - error.Set(upnp_domain, "UpnpMakeAction() failed"); - return false; - } + UniqueIxmlDocument request(MakeActionHelper("Browse", m_serviceType.c_str(), + "ObjectID", objectId, + "BrowseFlag", "BrowseMetadata", + "Filter", "*", + "SortCriteria", "", + "StartingIndex", "0", + "RequestedCount", "1")); + if (request == nullptr) + throw std::runtime_error("UpnpMakeAction() failed"); - IXML_Document *response; + IXML_Document *_response; auto code = UpnpSendAction(hdl, m_actionURL.c_str(), m_serviceType.c_str(), - 0 /*devUDN*/, request, &response); - ixmlDocument_free(request); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSendAction() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } - - bool success = ReadResultTag(dirbuf, response, error); - ixmlDocument_free(response); - return success; + 0 /*devUDN*/, request.get(), &_response); + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSendAction() failed: %s", + UpnpGetErrorMessage(code)); + + UniqueIxmlDocument response(_response); + UPnPDirContent dirbuf; + ReadResultTag(dirbuf, response.get()); + return dirbuf; } diff -Nru mpd-0.19.21/src/db/plugins/upnp/Directory.cxx mpd-0.20.9/src/db/plugins/upnp/Directory.cxx --- mpd-0.19.21/src/db/plugins/upnp/Directory.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Directory.cxx 2017-05-08 15:17:57.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include "tag/TagBuilder.hxx" #include "tag/TagTable.hxx" #include "util/NumberParser.hxx" +#include "util/StringView.hxx" #include #include @@ -36,23 +37,13 @@ /* this destructor exists here just so it won't get inlined */ } -gcc_pure gcc_nonnull_all -static bool -CompareStringLiteral(const char *literal, const char *value, size_t length) -{ - return length == strlen(literal) && - memcmp(literal, value, length) == 0; -} - gcc_pure static UPnPDirObject::ItemClass -ParseItemClass(const char *name, size_t length) +ParseItemClass(StringView name) noexcept { - if (CompareStringLiteral("object.item.audioItem.musicTrack", - name, length)) + if (name.EqualsLiteral("object.item.audioItem.musicTrack")) return UPnPDirObject::ItemClass::MUSIC; - else if (CompareStringLiteral("object.item.playlistItem", - name, length)) + else if (name.EqualsLiteral("object.item.playlistItem")) return UPnPDirObject::ItemClass::PLAYLIST; else return UPnPDirObject::ItemClass::UNKNOWN; @@ -60,7 +51,7 @@ gcc_pure static SignedSongTime -ParseDuration(const char *duration) +ParseDuration(const char *duration) noexcept { char *endptr; @@ -89,18 +80,18 @@ * this. Twonky returns directory names (titles) like 'Artist/Album'. */ gcc_pure -static std::string -titleToPathElt(std::string &&s) +static std::string && +TitleToPathSegment(std::string &&s) noexcept { std::replace(s.begin(), s.end(), '/', '_'); - return s; + return std::move(s); } /** * An XML parser which builds directory contents from DIDL lite input. */ class UPnPDirParser final : public CommonExpatParser { - UPnPDirContent &m_dir; + UPnPDirContent &directory; enum { NONE, @@ -120,22 +111,22 @@ */ std::string value; - UPnPDirObject m_tobj; + UPnPDirObject object; TagBuilder tag; public: - UPnPDirParser(UPnPDirContent& dir) - :m_dir(dir), + UPnPDirParser(UPnPDirContent &_directory) + :directory(_directory), state(NONE), tag_type(TAG_NUM_OF_ITEM_TYPES) { - m_tobj.clear(); + object.Clear(); } protected: - virtual void StartElement(const XML_Char *name, const XML_Char **attrs) + void StartElement(const XML_Char *name, const XML_Char **attrs) override { - if (m_tobj.type != UPnPDirObject::Type::UNKNOWN && + if (object.type != UPnPDirObject::Type::UNKNOWN && tag_type == TAG_NUM_OF_ITEM_TYPES) { tag_type = tag_table_lookup(upnp_tags, name); if (tag_type != TAG_NUM_OF_ITEM_TYPES) @@ -147,31 +138,31 @@ switch (name[0]) { case 'c': if (!strcmp(name, "container")) { - m_tobj.clear(); - m_tobj.type = UPnPDirObject::Type::CONTAINER; + object.Clear(); + object.type = UPnPDirObject::Type::CONTAINER; const char *id = GetAttribute(attrs, "id"); if (id != nullptr) - m_tobj.m_id = id; + object.id = id; const char *pid = GetAttribute(attrs, "parentID"); if (pid != nullptr) - m_tobj.m_pid = pid; + object.parent_id = pid; } break; case 'i': if (!strcmp(name, "item")) { - m_tobj.clear(); - m_tobj.type = UPnPDirObject::Type::ITEM; + object.Clear(); + object.type = UPnPDirObject::Type::ITEM; const char *id = GetAttribute(attrs, "id"); if (id != nullptr) - m_tobj.m_id = id; + object.id = id; const char *pid = GetAttribute(attrs, "parentID"); if (pid != nullptr) - m_tobj.m_pid = pid; + object.parent_id = pid; } break; @@ -197,25 +188,15 @@ } } - bool checkobjok() { - if (m_tobj.m_id.empty() || m_tobj.m_pid.empty() || - m_tobj.name.empty() || - (m_tobj.type == UPnPDirObject::Type::ITEM && - m_tobj.item_class == UPnPDirObject::ItemClass::UNKNOWN)) - return false; - - return true; - } - - virtual void EndElement(const XML_Char *name) + void EndElement(const XML_Char *name) override { if (tag_type != TAG_NUM_OF_ITEM_TYPES) { - assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN); + assert(object.type != UPnPDirObject::Type::UNKNOWN); tag.AddItem(tag_type, value.c_str()); if (tag_type == TAG_TITLE) - m_tobj.name = titleToPathElt(std::move(value)); + object.name = TitleToPathSegment(std::move(value)); value.clear(); tag_type = TAG_NUM_OF_ITEM_TYPES; @@ -223,18 +204,18 @@ } if ((!strcmp(name, "container") || !strcmp(name, "item")) && - checkobjok()) { - tag.Commit(m_tobj.tag); - m_dir.objects.emplace_back(std::move(m_tobj)); + object.Check()) { + tag.Commit(object.tag); + directory.objects.emplace_back(std::move(object)); } state = NONE; } - virtual void CharacterData(const XML_Char *s, int len) + void CharacterData(const XML_Char *s, int len) override { if (tag_type != TAG_NUM_OF_ITEM_TYPES) { - assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN); + assert(object.type != UPnPDirObject::Type::UNKNOWN); value.append(s, len); return; @@ -245,19 +226,19 @@ break; case RES: - m_tobj.url.assign(s, len); + object.url.assign(s, len); break; case CLASS: - m_tobj.item_class = ParseItemClass(s, len); + object.item_class = ParseItemClass(StringView(s, len)); break; } } }; -bool -UPnPDirContent::parse(const char *input, Error &error) +void +UPnPDirContent::Parse(const char *input) { UPnPDirParser parser(*this); - return parser.Parse(input, strlen(input), true, error); + parser.Parse(input, strlen(input), true); } diff -Nru mpd-0.19.21/src/db/plugins/upnp/Directory.hxx mpd-0.20.9/src/db/plugins/upnp/Directory.hxx --- mpd-0.19.21/src/db/plugins/upnp/Directory.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Directory.hxx 2017-05-08 15:17:42.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,8 +26,6 @@ #include #include -class Error; - /** * Image of a MediaServer Directory Service container (directory), * possibly containing items and subordinate containers. @@ -36,10 +34,13 @@ public: std::vector objects; + UPnPDirContent() = default; + UPnPDirContent(UPnPDirContent &&) = default; + ~UPnPDirContent(); gcc_pure - UPnPDirObject *FindObject(const char *name) { + UPnPDirObject *FindObject(const char *name) noexcept { for (auto &o : objects) if (o.name == name) return &o; @@ -60,7 +61,7 @@ * actually global, nothing really bad will happen if you mix * up... */ - bool parse(const char *didltext, Error &error); + void Parse(const char *didltext); }; #endif /* _UPNPDIRCONTENT_H_X_INCLUDED_ */ diff -Nru mpd-0.19.21/src/db/plugins/upnp/Object.cxx mpd-0.20.9/src/db/plugins/upnp/Object.cxx --- mpd-0.19.21/src/db/plugins/upnp/Object.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Object.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/plugins/upnp/Object.hxx mpd-0.20.9/src/db/plugins/upnp/Object.hxx --- mpd-0.19.21/src/db/plugins/upnp/Object.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Object.hxx 2017-06-04 10:41:14.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #define MPD_UPNP_OBJECT_HXX #include "tag/Tag.hxx" +#include "Compiler.h" #include @@ -50,8 +51,16 @@ PLAYLIST, }; - std::string m_id; // ObjectId - std::string m_pid; // Parent ObjectId + /** + * ObjectId + */ + std::string id; + + /** + * Parent's ObjectId + */ + std::string parent_id; + std::string url; /** @@ -71,15 +80,21 @@ UPnPDirObject &operator=(UPnPDirObject &&) = default; - void clear() - { - m_id.clear(); - m_pid.clear(); + void Clear() noexcept { + id.clear(); + parent_id.clear(); url.clear(); type = Type::UNKNOWN; item_class = ItemClass::UNKNOWN; tag.Clear(); } + + gcc_pure + bool Check() const noexcept { + return !id.empty() && !parent_id.empty() && !name.empty() && + (type != UPnPDirObject::Type::ITEM || + item_class != UPnPDirObject::ItemClass::UNKNOWN); + } }; #endif /* _UPNPDIRCONTENT_H_X_INCLUDED_ */ diff -Nru mpd-0.19.21/src/db/plugins/upnp/Tags.cxx mpd-0.20.9/src/db/plugins/upnp/Tags.cxx --- mpd-0.19.21/src/db/plugins/upnp/Tags.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Tags.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/plugins/upnp/Tags.hxx mpd-0.20.9/src/db/plugins/upnp/Tags.hxx --- mpd-0.19.21/src/db/plugins/upnp/Tags.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/Tags.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/plugins/upnp/UpnpDatabasePlugin.cxx mpd-0.20.9/src/db/plugins/upnp/UpnpDatabasePlugin.cxx --- mpd-0.19.21/src/db/plugins/upnp/UpnpDatabasePlugin.cxx 2016-08-23 07:47:48.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/UpnpDatabasePlugin.cxx 2017-06-03 19:57:03.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,6 @@ #include "UpnpDatabasePlugin.hxx" #include "Directory.hxx" #include "Tags.hxx" -#include "lib/upnp/Domain.hxx" #include "lib/upnp/ClientInit.hxx" #include "lib/upnp/Discovery.hxx" #include "lib/upnp/ContentDirectoryService.hxx" @@ -33,11 +32,9 @@ #include "db/LightDirectory.hxx" #include "db/LightSong.hxx" #include "db/Stats.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "tag/TagBuilder.hxx" #include "tag/TagTable.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include "fs/Traits.hxx" #include "Log.hxx" #include "SongFilter.hxx" @@ -78,120 +75,88 @@ UpnpDatabase():Database(upnp_db_plugin) {} static Database *Create(EventLoop &loop, DatabaseListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual const LightSong *GetSong(const char *uri_utf8, - Error &error) const override; + void Open() override; + void Close() override; + const LightSong *GetSong(const char *uri_utf8) const override; void ReturnSong(const LightSong *song) const override; - virtual bool Visit(const DatabaseSelection &selection, - VisitDirectory visit_directory, - VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const override; - - virtual bool VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) const override; - - virtual bool GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, - Error &error) const override; - time_t GetUpdateStamp() const override { + void Visit(const DatabaseSelection &selection, + VisitDirectory visit_directory, + VisitSong visit_song, + VisitPlaylist visit_playlist) const override; + + void VisitUniqueTags(const DatabaseSelection &selection, + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) const override; + + DatabaseStats GetStats(const DatabaseSelection &selection) const override; + + time_t GetUpdateStamp() const noexcept override { return 0; } -protected: - bool Configure(const config_param ¶m, Error &error); - private: - bool VisitServer(const ContentDirectoryService &server, + void VisitServer(const ContentDirectoryService &server, const std::list &vpath, const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const; + VisitPlaylist visit_playlist) const; /** * Run an UPnP search according to MPD parameters, and * visit_song the results. */ - bool SearchSongs(const ContentDirectoryService &server, + void SearchSongs(const ContentDirectoryService &server, const char *objid, const DatabaseSelection &selection, - VisitSong visit_song, - Error &error) const; + VisitSong visit_song) const; - bool SearchSongs(const ContentDirectoryService &server, - const char *objid, - const DatabaseSelection &selection, - UPnPDirContent& dirbuf, - Error &error) const; + UPnPDirContent SearchSongs(const ContentDirectoryService &server, + const char *objid, + const DatabaseSelection &selection) const; - bool Namei(const ContentDirectoryService &server, - const std::list &vpath, - UPnPDirObject &dirent, - Error &error) const; + UPnPDirObject Namei(const ContentDirectoryService &server, + const std::list &vpath) const; /** * Take server and objid, return metadata. */ - bool ReadNode(const ContentDirectoryService &server, - const char *objid, UPnPDirObject& dirent, - Error &error) const; + UPnPDirObject ReadNode(const ContentDirectoryService &server, + const char *objid) const; /** * Get the path for an object Id. This works much like pwd, * except easier cause our inodes have a parent id. Not used * any more actually (see comments in SearchSongs). */ - bool BuildPath(const ContentDirectoryService &server, - const UPnPDirObject& dirent, std::string &idpath, - Error &error) const; + std::string BuildPath(const ContentDirectoryService &server, + const UPnPDirObject& dirent) const; }; Database * UpnpDatabase::Create(gcc_unused EventLoop &loop, gcc_unused DatabaseListener &listener, - const config_param ¶m, Error &error) + const ConfigBlock &) { - UpnpDatabase *db = new UpnpDatabase(); - if (!db->Configure(param, error)) { - delete db; - return nullptr; - } - - /* libupnp loses its ability to receive multicast messages - apparently due to daemonization; using the LazyDatabase - wrapper works around this problem */ - return db; -} - -inline bool -UpnpDatabase::Configure(const config_param &, Error &) -{ - return true; + return new UpnpDatabase(); } -bool -UpnpDatabase::Open(Error &error) +void +UpnpDatabase::Open() { - if (!UpnpClientGlobalInit(handle, error)) - return false; + UpnpClientGlobalInit(handle); discovery = new UPnPDeviceDirectory(handle); - if (!discovery->Start(error)) { + try { + discovery->Start(); + } catch (...) { delete discovery; UpnpClientGlobalFinish(); - return false; + throw; } - - return true; } void @@ -213,28 +178,22 @@ // Get song info by path. We can receive either the id path, or the titles // one const LightSong * -UpnpDatabase::GetSong(const char *uri, Error &error) const +UpnpDatabase::GetSong(const char *uri) const { - auto vpath = stringToTokens(uri, "/", true); - if (vpath.size() < 2) { - error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri); - return nullptr; - } + auto vpath = stringToTokens(uri, '/'); + if (vpath.size() < 2) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such song"); - ContentDirectoryService server; - if (!discovery->getServer(vpath.front().c_str(), server, error)) - return nullptr; + auto server = discovery->GetServer(vpath.front().c_str()); vpath.pop_front(); UPnPDirObject dirent; if (vpath.front() != rootid) { - if (!Namei(server, vpath, dirent, error)) - return nullptr; + dirent = Namei(server, vpath); } else { - if (!ReadNode(server, vpath.back().c_str(), dirent, - error)) - return nullptr; + dirent = ReadNode(server, vpath.back().c_str()); } return new UpnpSong(std::move(dirent), uri); @@ -264,23 +223,18 @@ // Run an UPnP search, according to MPD parameters. Return results as // UPnP items -bool +UPnPDirContent UpnpDatabase::SearchSongs(const ContentDirectoryService &server, const char *objid, - const DatabaseSelection &selection, - UPnPDirContent &dirbuf, - Error &error) const + const DatabaseSelection &selection) const { const SongFilter *filter = selection.filter; if (selection.filter == nullptr) - return true; - - std::list searchcaps; - if (!server.getSearchCapabilities(handle, searchcaps, error)) - return false; + return UPnPDirContent(); + const auto searchcaps = server.getSearchCapabilities(handle); if (searchcaps.empty()) - return true; + return UPnPDirContent(); std::string cond; for (const auto &item : filter->GetItems()) { @@ -303,7 +257,7 @@ } else { cond += " = "; } - dquote(cond, item.GetValue().c_str()); + dquote(cond, item.GetValue()); } cond += ')'; } @@ -339,22 +293,20 @@ } else { cond += " = "; } - dquote(cond, item.GetValue().c_str()); + dquote(cond, item.GetValue()); } } - return server.search(handle, - objid, cond.c_str(), dirbuf, - error); + return server.search(handle, objid, cond.c_str()); } -static bool +static void visitSong(const UPnPDirObject &meta, const char *path, const DatabaseSelection &selection, - VisitSong visit_song, Error& error) + VisitSong visit_song) { if (!visit_song) - return true; + return; LightSong song; song.directory = nullptr; @@ -364,7 +316,8 @@ song.mtime = 0; song.start_time = song.end_time = SongTime::zero(); - return !selection.Match(song) || visit_song(song, error); + if (selection.Match(song)) + visit_song(song); } /** @@ -379,20 +332,16 @@ return servername + "/" + rootid + "/" + objid; } -bool +void UpnpDatabase::SearchSongs(const ContentDirectoryService &server, const char *objid, const DatabaseSelection &selection, - VisitSong visit_song, - Error &error) const + VisitSong visit_song) const { - UPnPDirContent dirbuf; if (!visit_song) - return true; - if (!SearchSongs(server, objid, selection, dirbuf, error)) - return false; + return; - for (auto &dirent : dirbuf.objects) { + for (auto &dirent : SearchSongs(server, objid, selection).objects) { if (dirent.type != UPnPDirObject::Type::ITEM || dirent.item_class != UPnPDirObject::ItemClass::MUSIC) continue; @@ -414,48 +363,32 @@ // So we return synthetic and ugly paths based on the object id, // which we later have to detect. const std::string path = songPath(server.getFriendlyName(), - dirent.m_id); - if (!visitSong(std::move(dirent), path.c_str(), - selection, visit_song, - error)) - return false; + dirent.id); + visitSong(std::move(dirent), path.c_str(), + selection, visit_song); } - - return true; } -bool +UPnPDirObject UpnpDatabase::ReadNode(const ContentDirectoryService &server, - const char *objid, UPnPDirObject &dirent, - Error &error) const + const char *objid) const { - UPnPDirContent dirbuf; - if (!server.getMetadata(handle, objid, dirbuf, error)) - return false; - - if (dirbuf.objects.size() == 1) { - dirent = std::move(dirbuf.objects.front()); - } else { - error.Format(upnp_domain, "Bad resource"); - return false; - } + auto dirbuf = server.getMetadata(handle, objid); + if (dirbuf.objects.size() != 1) + throw std::runtime_error("Bad resource"); - return true; + return std::move(dirbuf.objects.front()); } -bool +std::string UpnpDatabase::BuildPath(const ContentDirectoryService &server, - const UPnPDirObject& idirent, - std::string &path, - Error &error) const + const UPnPDirObject& idirent) const { - const char *pid = idirent.m_id.c_str(); - path.clear(); - UPnPDirObject dirent; + const char *pid = idirent.id.c_str(); + std::string path; while (strcmp(pid, rootid) != 0) { - if (!ReadNode(server, pid, dirent, error)) - return false; - pid = dirent.m_pid.c_str(); + auto dirent = ReadNode(server, pid); + pid = dirent.parent_id.c_str(); if (path.empty()) path = dirent.name; @@ -464,70 +397,53 @@ path.c_str()); } - path = PathTraitsUTF8::Build(server.getFriendlyName(), + return PathTraitsUTF8::Build(server.getFriendlyName(), path.c_str()); - return true; } // Take server and internal title pathname and return objid and metadata. -bool +UPnPDirObject UpnpDatabase::Namei(const ContentDirectoryService &server, - const std::list &vpath, - UPnPDirObject &odirent, - Error &error) const + const std::list &vpath) const { - if (vpath.empty()) { + if (vpath.empty()) // looking for root info - if (!ReadNode(server, rootid, odirent, error)) - return false; - - return true; - } + return ReadNode(server, rootid); std::string objid(rootid); // Walk the path elements, read each directory and try to find the next one for (auto i = vpath.begin(), last = std::prev(vpath.end());; ++i) { - UPnPDirContent dirbuf; - if (!server.readDir(handle, objid.c_str(), dirbuf, error)) - return false; + auto dirbuf = server.readDir(handle, objid.c_str()); // Look for the name in the sub-container list UPnPDirObject *child = dirbuf.FindObject(i->c_str()); - if (child == nullptr) { - error.Format(db_domain, DB_NOT_FOUND, - "No such object"); - return false; - } - - if (i == last) { - odirent = std::move(*child); - return true; - } - - if (child->type != UPnPDirObject::Type::CONTAINER) { - error.Format(db_domain, DB_NOT_FOUND, - "Not a container"); - return false; - } + if (child == nullptr) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "No such object"); + + if (i == last) + return std::move(*child); + + if (child->type != UPnPDirObject::Type::CONTAINER) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "Not a container"); - objid = std::move(child->m_id); + objid = std::move(child->id); } } -static bool +static void VisitItem(const UPnPDirObject &object, const char *uri, const DatabaseSelection &selection, - VisitSong visit_song, VisitPlaylist visit_playlist, - Error &error) + VisitSong visit_song, VisitPlaylist visit_playlist) { assert(object.type == UPnPDirObject::Type::ITEM); switch (object.item_class) { case UPnPDirObject::ItemClass::MUSIC: - return !visit_song || - visitSong(object, uri, - selection, visit_song, error); + visitSong(object, uri, selection, visit_song); + break; case UPnPDirObject::ItemClass::PLAYLIST: if (visit_playlist) { @@ -539,23 +455,19 @@ see one... */ } - return true; + break; case UPnPDirObject::ItemClass::UNKNOWN: - return true; + break; } - - assert(false); - gcc_unreachable(); } -static bool +static void VisitObject(const UPnPDirObject &object, const char *uri, const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) + VisitPlaylist visit_playlist) { switch (object.type) { case UPnPDirObject::Type::UNKNOWN: @@ -563,29 +475,26 @@ gcc_unreachable(); case UPnPDirObject::Type::CONTAINER: - return !visit_directory || - visit_directory(LightDirectory(uri, 0), error); + if (visit_directory) + visit_directory(LightDirectory(uri, 0)); + break; case UPnPDirObject::Type::ITEM: - return VisitItem(object, uri, selection, - visit_song, visit_playlist, - error); + VisitItem(object, uri, selection, + visit_song, visit_playlist); + break; } - - assert(false); - gcc_unreachable(); } // vpath is a parsed and writeable version of selection.uri. There is // really just one path parameter. -bool +void UpnpDatabase::VisitServer(const ContentDirectoryService &server, const std::list &vpath, const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const + VisitPlaylist visit_playlist) const { /* If the path begins with rootid, we know that this is a song, not a directory (because that's how we set things @@ -598,149 +507,115 @@ if (!vpath.empty() && vpath.front() == rootid) { switch (vpath.size()) { case 1: - return true; + return; case 2: break; default: - error.Format(db_domain, DB_NOT_FOUND, - "Not found"); - return false; + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "Not found"); } if (visit_song) { - UPnPDirObject dirent; - if (!ReadNode(server, vpath.back().c_str(), dirent, - error)) - return false; + auto dirent = ReadNode(server, vpath.back().c_str()); if (dirent.type != UPnPDirObject::Type::ITEM || - dirent.item_class != UPnPDirObject::ItemClass::MUSIC) { - error.Format(db_domain, DB_NOT_FOUND, - "Not found"); - return false; - } + dirent.item_class != UPnPDirObject::ItemClass::MUSIC) + throw DatabaseError(DatabaseErrorCode::NOT_FOUND, + "Not found"); std::string path = songPath(server.getFriendlyName(), - dirent.m_id); - if (!visitSong(std::move(dirent), path.c_str(), - selection, - visit_song, error)) - return false; + dirent.id); + visitSong(std::move(dirent), path.c_str(), + selection, visit_song); } - return true; + + return; } // Translate the target path into an object id and the associated metadata. - UPnPDirObject tdirent; - if (!Namei(server, vpath, tdirent, error)) - return false; + const auto tdirent = Namei(server, vpath); /* If recursive is set, this is a search... No use sending it if the filter is empty. In this case, we implement limited recursion (1-deep) here, which will handle the "add dir" case. */ - if (selection.recursive && selection.filter) - return SearchSongs(server, tdirent.m_id.c_str(), selection, - visit_song, error); + if (selection.recursive && selection.filter) { + SearchSongs(server, tdirent.id.c_str(), selection, visit_song); + return; + } const char *const base_uri = selection.uri.empty() ? server.getFriendlyName() : selection.uri.c_str(); if (tdirent.type == UPnPDirObject::Type::ITEM) { - return VisitItem(tdirent, base_uri, - selection, - visit_song, visit_playlist, - error); + VisitItem(tdirent, base_uri, + selection, + visit_song, visit_playlist); + return; } /* Target was a a container. Visit it. We could read slices and loop here, but it's not useful as mpd will only return data to the client when we're done anyway. */ - UPnPDirContent dirbuf; - if (!server.readDir(handle, tdirent.m_id.c_str(), dirbuf, - error)) - return false; - - for (auto &dirent : dirbuf.objects) { + for (const auto &dirent : server.readDir(handle, tdirent.id.c_str()).objects) { const std::string uri = PathTraitsUTF8::Build(base_uri, dirent.name.c_str()); - if (!VisitObject(dirent, uri.c_str(), - selection, - visit_directory, - visit_song, visit_playlist, - error)) - return false; + VisitObject(dirent, uri.c_str(), + selection, + visit_directory, + visit_song, visit_playlist); } - - return true; } // Deal with the possibly multiple servers, call VisitServer if needed. -bool +void UpnpDatabase::Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - Error &error) const + VisitPlaylist visit_playlist) const { - auto vpath = stringToTokens(selection.uri, "/", true); + auto vpath = stringToTokens(selection.uri, '/'); if (vpath.empty()) { - std::vector servers; - if (!discovery->getDirServices(servers, error)) - return false; - - for (const auto &server : servers) { + for (const auto &server : discovery->GetDirectories()) { if (visit_directory) { const LightDirectory d(server.getFriendlyName(), 0); - if (!visit_directory(d, error)) - return false; + visit_directory(d); } - if (selection.recursive && - !VisitServer(server, vpath, selection, - visit_directory, visit_song, visit_playlist, - error)) - return false; + if (selection.recursive) + VisitServer(server, vpath, selection, + visit_directory, visit_song, + visit_playlist); } - return true; + return; } // We do have a path: the first element selects the server std::string servername(std::move(vpath.front())); vpath.pop_front(); - ContentDirectoryService server; - if (!discovery->getServer(servername.c_str(), server, error)) - return false; - - return VisitServer(server, vpath, selection, - visit_directory, visit_song, visit_playlist, error); + auto server = discovery->GetServer(servername.c_str()); + VisitServer(server, vpath, selection, + visit_directory, visit_song, visit_playlist); } -bool +void UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection, - TagType tag, gcc_unused uint32_t group_mask, - VisitTag visit_tag, - Error &error) const + TagType tag, gcc_unused tag_mask_t group_mask, + VisitTag visit_tag) const { // TODO: use group_mask if (!visit_tag) - return true; - - std::vector servers; - if (!discovery->getDirServices(servers, error)) - return false; + return; std::set values; - for (auto& server : servers) { - UPnPDirContent dirbuf; - if (!SearchSongs(server, rootid, selection, dirbuf, error)) - return false; + for (auto& server : discovery->GetDirectories()) { + const auto dirbuf = SearchSongs(server, rootid, selection); for (const auto &dirent : dirbuf.objects) { if (dirent.type != UPnPDirObject::Type::ITEM || @@ -761,21 +636,18 @@ for (const auto& value : values) { TagBuilder builder; builder.AddItem(tag, value.c_str()); - if (!visit_tag(builder.Commit(), error)) - return false; + visit_tag(builder.Commit()); } - - return true; } -bool -UpnpDatabase::GetStats(const DatabaseSelection &, - DatabaseStats &stats, Error &) const +DatabaseStats +UpnpDatabase::GetStats(const DatabaseSelection &) const { /* Note: this gets called before the daemonizing so we can't reallyopen this would be a problem if we had real stats */ + DatabaseStats stats; stats.Clear(); - return true; + return stats; } const DatabasePlugin upnp_db_plugin = { diff -Nru mpd-0.19.21/src/db/plugins/upnp/UpnpDatabasePlugin.hxx mpd-0.20.9/src/db/plugins/upnp/UpnpDatabasePlugin.hxx --- mpd-0.19.21/src/db/plugins/upnp/UpnpDatabasePlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/plugins/upnp/UpnpDatabasePlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/Registry.cxx mpd-0.20.9/src/db/Registry.cxx --- mpd-0.19.21/src/db/Registry.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Registry.cxx 2017-05-08 13:39:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,17 +28,17 @@ const DatabasePlugin *const database_plugins[] = { &simple_db_plugin, -#ifdef HAVE_LIBMPDCLIENT +#ifdef ENABLE_LIBMPDCLIENT &proxy_db_plugin, #endif -#ifdef HAVE_LIBUPNP +#ifdef ENABLE_UPNP &upnp_db_plugin, #endif nullptr }; const DatabasePlugin * -GetDatabasePluginByName(const char *name) +GetDatabasePluginByName(const char *name) noexcept { for (auto i = database_plugins; *i != nullptr; ++i) if (strcmp((*i)->name, name) == 0) diff -Nru mpd-0.19.21/src/db/Registry.hxx mpd-0.20.9/src/db/Registry.hxx --- mpd-0.19.21/src/db/Registry.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Registry.hxx 2017-05-08 13:39:52.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,6 +32,6 @@ gcc_pure const DatabasePlugin * -GetDatabasePluginByName(const char *name); +GetDatabasePluginByName(const char *name) noexcept; #endif diff -Nru mpd-0.19.21/src/db/Selection.cxx mpd-0.20.9/src/db/Selection.cxx --- mpd-0.19.21/src/db/Selection.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Selection.cxx 2017-05-08 14:12:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,24 +26,27 @@ { /* optimization: if the caller didn't specify a base URI, pick the one from SongFilter */ - if (uri.empty() && filter != nullptr) - uri = filter->GetBase(); + if (uri.empty() && filter != nullptr) { + auto base = filter->GetBase(); + if (base != nullptr) + uri = base; + } } bool -DatabaseSelection::IsEmpty() const +DatabaseSelection::IsEmpty() const noexcept { return uri.empty() && (filter == nullptr || filter->IsEmpty()); } bool -DatabaseSelection::HasOtherThanBase() const +DatabaseSelection::HasOtherThanBase() const noexcept { return filter != nullptr && filter->HasOtherThanBase(); } bool -DatabaseSelection::Match(const LightSong &song) const +DatabaseSelection::Match(const LightSong &song) const noexcept { return filter == nullptr || filter->Match(song); } diff -Nru mpd-0.19.21/src/db/Selection.hxx mpd-0.20.9/src/db/Selection.hxx --- mpd-0.19.21/src/db/Selection.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Selection.hxx 2017-05-08 14:12:14.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -45,16 +45,16 @@ const SongFilter *_filter=nullptr); gcc_pure - bool IsEmpty() const; + bool IsEmpty() const noexcept; /** * Does this selection contain constraints other than "base"? */ gcc_pure - bool HasOtherThanBase() const; + bool HasOtherThanBase() const noexcept; gcc_pure - bool Match(const LightSong &song) const; + bool Match(const LightSong &song) const noexcept; }; #endif diff -Nru mpd-0.19.21/src/db/Stats.hxx mpd-0.20.9/src/db/Stats.hxx --- mpd-0.19.21/src/db/Stats.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Stats.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/UniqueTags.cxx mpd-0.20.9/src/db/UniqueTags.cxx --- mpd-0.19.21/src/db/UniqueTags.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/UniqueTags.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,34 +26,28 @@ #include -static bool -CollectTags(TagSet &set, TagType tag_type, uint32_t group_mask, +static void +CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask, const LightSong &song) { assert(song.tag != nullptr); const Tag &tag = *song.tag; set.InsertUnique(tag, tag_type, group_mask); - return true; } -bool +void VisitUniqueTags(const Database &db, const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error) + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag) { TagSet set; using namespace std::placeholders; const auto f = std::bind(CollectTags, std::ref(set), tag_type, group_mask, _1); - if (!db.Visit(selection, f, error)) - return false; + db.Visit(selection, f); for (const auto &value : set) - if (!visit_tag(value, error)) - return false; - - return true; + visit_tag(value); } diff -Nru mpd-0.19.21/src/db/UniqueTags.hxx mpd-0.20.9/src/db/UniqueTags.hxx --- mpd-0.19.21/src/db/UniqueTags.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/UniqueTags.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,17 +22,14 @@ #include "Visitor.hxx" #include "tag/TagType.h" +#include "tag/Mask.hxx" -#include - -class Error; class Database; struct DatabaseSelection; -bool +void VisitUniqueTags(const Database &db, const DatabaseSelection &selection, - TagType tag_type, uint32_t group_mask, - VisitTag visit_tag, - Error &error); + TagType tag_type, tag_mask_t group_mask, + VisitTag visit_tag); #endif diff -Nru mpd-0.19.21/src/db/update/Archive.cxx mpd-0.20.9/src/db/update/Archive.cxx --- mpd-0.19.21/src/db/update/Archive.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Archive.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -30,67 +30,95 @@ #include "archive/ArchivePlugin.hxx" #include "archive/ArchiveFile.hxx" #include "archive/ArchiveVisitor.hxx" -#include "util/Error.hxx" +#include "util/StringCompare.hxx" #include "Log.hxx" #include +#include -#include #include +static Directory * +LockFindChild(Directory &directory, const char *name) +{ + const ScopeDatabaseLock protect; + return directory.FindChild(name); +} + +static Directory * +LockMakeChild(Directory &directory, const char *name) +{ + const ScopeDatabaseLock protect; + return directory.MakeChild(name); +} + +static Song * +LockFindSong(Directory &directory, const char *name) +{ + const ScopeDatabaseLock protect; + return directory.FindSong(name); +} + void -UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name) +UpdateWalk::UpdateArchiveTree(ArchiveFile &archive, Directory &directory, + const char *name) { const char *tmp = strchr(name, '/'); if (tmp) { const std::string child_name(name, tmp); //add dir is not there already - db_lock(); - Directory *subdir = - directory.MakeChild(child_name.c_str()); + Directory *subdir = LockMakeChild(directory, + child_name.c_str()); subdir->device = DEVICE_INARCHIVE; - db_unlock(); //create directories first - UpdateArchiveTree(*subdir, tmp + 1); + UpdateArchiveTree(archive, *subdir, tmp + 1); } else { - if (strlen(name) == 0) { + if (StringIsEmpty(name)) { LogWarning(update_domain, "archive returned directory only"); return; } //add file - db_lock(); - Song *song = directory.FindSong(name); - db_unlock(); + Song *song = LockFindSong(directory, name); if (song == nullptr) { - song = Song::LoadFile(storage, name, directory); + song = Song::LoadFromArchive(archive, name, directory); if (song != nullptr) { - db_lock(); - directory.AddSong(song); - db_unlock(); + { + const ScopeDatabaseLock protect; + directory.AddSong(song); + } modified = true; FormatDefault(update_domain, "added %s/%s", directory.GetPath(), name); } + } else { + if (!song->UpdateFileInArchive(archive)) { + FormatDebug(update_domain, + "deleting unrecognized file %s/%s", + directory.GetPath(), name); + editor.LockDeleteSong(directory, song); + } } } } class UpdateArchiveVisitor final : public ArchiveVisitor { UpdateWalk &walk; + ArchiveFile &archive; Directory *directory; public: - UpdateArchiveVisitor(UpdateWalk &_walk, Directory *_directory) - :walk(_walk), directory(_directory) {} + UpdateArchiveVisitor(UpdateWalk &_walk, ArchiveFile &_archive, + Directory *_directory) + :walk(_walk), archive(_archive), directory(_directory) {} virtual void VisitArchiveEntry(const char *path_utf8) override { FormatDebug(update_domain, "adding archive file: %s", path_utf8); - walk.UpdateArchiveTree(*directory, path_utf8); + walk.UpdateArchiveTree(archive, *directory, path_utf8); } }; @@ -104,12 +132,10 @@ */ void UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name, - const FileInfo &info, + const StorageFileInfo &info, const ArchivePlugin &plugin) { - db_lock(); - Directory *directory = parent.FindChild(name); - db_unlock(); + Directory *directory = LockFindChild(parent, name); if (directory != nullptr && directory->mtime == info.mtime && !walk_discard) @@ -124,10 +150,11 @@ return; /* open archive */ - Error error; - ArchiveFile *file = archive_file_open(&plugin, path_fs, error); - if (file == nullptr) { - LogError(error); + ArchiveFile *file; + try { + file = archive_file_open(&plugin, path_fs); + } catch (const std::runtime_error &e) { + LogError(e); if (directory != nullptr) editor.LockDeleteDirectory(directory); return; @@ -138,17 +165,17 @@ if (directory == nullptr) { FormatDebug(update_domain, "creating archive directory: %s", name); - db_lock(); + + const ScopeDatabaseLock protect; directory = parent.CreateChild(name); /* mark this directory as archive (we use device for this) */ directory->device = DEVICE_INARCHIVE; - db_unlock(); } directory->mtime = info.mtime; - UpdateArchiveVisitor visitor(*this, directory); + UpdateArchiveVisitor visitor(*this, *file, directory); file->Visit(visitor); file->Close(); } @@ -156,7 +183,7 @@ bool UpdateWalk::UpdateArchiveFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info) + const StorageFileInfo &info) { const ArchivePlugin *plugin = archive_plugin_from_suffix(suffix); if (plugin == nullptr) diff -Nru mpd-0.19.21/src/db/update/Container.cxx mpd-0.20.9/src/db/update/Container.cxx --- mpd-0.19.21/src/db/update/Container.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Container.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include "config.h" /* must be first for large file support */ #include "Walk.hxx" #include "UpdateDomain.hxx" +#include "DetachedSong.hxx" #include "db/DatabaseLock.hxx" #include "db/plugins/simple/Directory.hxx" #include "db/plugins/simple/Song.hxx" @@ -28,15 +29,12 @@ #include "decoder/DecoderList.hxx" #include "fs/AllocatedPath.hxx" #include "storage/FileInfo.hxx" -#include "tag/TagHandler.hxx" -#include "tag/TagBuilder.hxx" #include "Log.hxx" - -#include +#include "util/AllocatedString.hxx" Directory * UpdateWalk::MakeDirectoryIfModified(Directory &parent, const char *name, - const FileInfo &info) + const StorageFileInfo &info) { Directory *directory = parent.FindChild(name); @@ -69,7 +67,7 @@ bool UpdateWalk::UpdateContainerFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info) + const StorageFileInfo &info) { const DecoderPlugin *_plugin = decoder_plugins_find([suffix](const DecoderPlugin &plugin){ return SupportsContainerSuffix(plugin, suffix); @@ -78,16 +76,16 @@ return false; const DecoderPlugin &plugin = *_plugin; - db_lock(); - Directory *contdir = MakeDirectoryIfModified(directory, name, info); - if (contdir == nullptr) { - /* not modified */ - db_unlock(); - return true; - } + Directory *contdir; + { + const ScopeDatabaseLock protect; + contdir = MakeDirectoryIfModified(directory, name, info); + if (contdir == nullptr) + /* not modified */ + return true; - contdir->device = DEVICE_CONTAINER; - db_unlock(); + contdir->device = DEVICE_CONTAINER; + } const auto pathname = storage.MapFS(contdir->GetPath()); if (pathname.IsNull()) { @@ -97,36 +95,35 @@ return false; } - char *vtrack; - unsigned int tnum = 0; - TagBuilder tag_builder; - while ((vtrack = plugin.container_scan(pathname, ++tnum)) != nullptr) { - Song *song = Song::NewFile(vtrack, *contdir); - - // shouldn't be necessary but it's there.. - song->mtime = info.mtime; - - const auto child_path_fs = AllocatedPath::Build(pathname, - vtrack); - plugin.ScanFile(child_path_fs, - add_tag_handler, &tag_builder); - - tag_builder.Commit(song->tag); - - db_lock(); - contdir->AddSong(song); - db_unlock(); - - modified = true; + try { + auto v = plugin.container_scan(pathname); + if (v.empty()) { + editor.LockDeleteDirectory(contdir); + return false; + } - FormatDefault(update_domain, "added %s/%s", - directory.GetPath(), vtrack); - delete[] vtrack; - } + for (auto &vtrack : v) { + Song *song = Song::NewFrom(std::move(vtrack), + *contdir); + + // shouldn't be necessary but it's there.. + song->mtime = info.mtime; + + FormatDefault(update_domain, "added %s/%s", + contdir->GetPath(), song->uri); + + { + const ScopeDatabaseLock protect; + contdir->AddSong(song); + } - if (tnum == 1) { + modified = true; + } + } catch (const std::runtime_error &e) { editor.LockDeleteDirectory(contdir); + LogError(e); return false; - } else - return true; + } + + return true; } diff -Nru mpd-0.19.21/src/db/update/Editor.cxx mpd-0.20.9/src/db/update/Editor.cxx --- mpd-0.19.21/src/db/update/Editor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Editor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,6 @@ #include "db/plugins/simple/Song.hxx" #include -#include void DatabaseEditor::DeleteSong(Directory &dir, Song *del) @@ -36,23 +35,21 @@ /* first, prevent traversers in main task from getting this */ dir.RemoveSong(del); - db_unlock(); /* temporary unlock, because update_remove_song() blocks */ + /* temporary unlock, because update_remove_song() blocks */ + const ScopeDatabaseUnlock unlock; /* now take it out of the playlist (in the main_task) */ - remove.Remove(del); + remove.Remove(del->GetURI()); /* finally, all possible references gone, free it */ del->Free(); - - db_lock(); } void DatabaseEditor::LockDeleteSong(Directory &parent, Song *song) { - db_lock(); + const ScopeDatabaseLock protect; DeleteSong(parent, song); - db_unlock(); } /** @@ -87,17 +84,17 @@ void DatabaseEditor::LockDeleteDirectory(Directory *directory) { - db_lock(); + const ScopeDatabaseLock protect; DeleteDirectory(directory); - db_unlock(); } bool DatabaseEditor::DeleteNameIn(Directory &parent, const char *name) { + const ScopeDatabaseLock protect; + bool modified = false; - db_lock(); Directory *directory = parent.FindChild(name); if (directory != nullptr) { @@ -113,7 +110,5 @@ parent.playlists.erase(name); - db_unlock(); - return modified; } diff -Nru mpd-0.19.21/src/db/update/Editor.hxx mpd-0.20.9/src/db/update/Editor.hxx --- mpd-0.19.21/src/db/update/Editor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Editor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,6 @@ struct Directory; struct Song; -class UpdateRemoveService; class DatabaseEditor final { UpdateRemoveService remove; diff -Nru mpd-0.19.21/src/db/update/ExcludeList.cxx mpd-0.20.9/src/db/update/ExcludeList.cxx --- mpd-0.19.21/src/db/update/ExcludeList.cxx 2016-07-29 12:55:05.000000000 +0000 +++ mpd-0.20.9/src/db/update/ExcludeList.cxx 2017-06-03 20:01:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,38 +25,24 @@ #include "config.h" #include "ExcludeList.hxx" #include "fs/Path.hxx" -#include "fs/FileSystem.hxx" -#include "util/StringUtil.hxx" -#include "util/Domain.hxx" +#include "fs/NarrowPath.hxx" +#include "fs/io/TextFile.hxx" +#include "system/Error.hxx" #include "Log.hxx" +#include + #include #include -#include - -#ifdef HAVE_GLIB -static constexpr Domain exclude_list_domain("exclude_list"); -#endif bool -ExcludeList::LoadFile(Path path_fs) -{ -#ifdef HAVE_GLIB - FILE *file = FOpen(path_fs, FOpenMode::ReadText); - if (file == nullptr) { - const int e = errno; - if (e != ENOENT) { - const auto path_utf8 = path_fs.ToUTF8(); - FormatErrno(exclude_list_domain, - "Failed to open %s", - path_utf8.c_str()); - } - - return false; - } +ExcludeList::LoadFile(Path path_fs) noexcept +try { +#ifdef HAVE_CLASS_GLOB + TextFile file(path_fs); - char line[1024]; - while (fgets(line, sizeof(line), file) != nullptr) { + char *line; + while ((line = file.ReadLine()) != nullptr) { char *p = strchr(line, '#'); if (p != nullptr) *p = 0; @@ -65,29 +51,44 @@ if (*p != 0) patterns.emplace_front(p); } - - fclose(file); #else - // TODO: implement + /* not implemented */ (void)path_fs; #endif return true; +} catch (const std::system_error &e) { + if (!IsFileNotFound(e)) + LogError(e); + return false; +} catch (const std::exception &e) { + LogError(e); + return false; } bool -ExcludeList::Check(Path name_fs) const +ExcludeList::Check(Path name_fs) const noexcept { assert(!name_fs.IsNull()); /* XXX include full path name in check */ -#ifdef HAVE_GLIB - for (const auto &i : patterns) - if (i.Check(name_fs.c_str())) +#ifdef HAVE_CLASS_GLOB + if (parent != nullptr) { + if (parent->Check(name_fs)) { return true; + } + } + + for (const auto &i : patterns) { + try { + if (i.Check(NarrowPath(name_fs).c_str())) + return true; + } catch (const std::runtime_error &) { + } + } #else - // TODO: implement + /* not implemented */ (void)name_fs; #endif diff -Nru mpd-0.19.21/src/db/update/ExcludeList.hxx mpd-0.20.9/src/db/update/ExcludeList.hxx --- mpd-0.19.21/src/db/update/ExcludeList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/ExcludeList.hxx 2017-06-03 20:01:19.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,51 +27,34 @@ #include "check.h" #include "Compiler.h" +#include "fs/Glob.hxx" +#ifdef HAVE_CLASS_GLOB #include - -#ifdef HAVE_GLIB -#include #endif class Path; class ExcludeList { -#ifdef HAVE_GLIB - class Pattern { - GPatternSpec *pattern; - - public: - Pattern(const char *_pattern) - :pattern(g_pattern_spec_new(_pattern)) {} - - Pattern(Pattern &&other) - :pattern(other.pattern) { - other.pattern = nullptr; - } - - ~Pattern() { - g_pattern_spec_free(pattern); - } - - gcc_pure - bool Check(const char *name_fs) const { - return g_pattern_match_string(pattern, name_fs); - } - }; + const ExcludeList *const parent; - std::forward_list patterns; -#else - // TODO: implement +#ifdef HAVE_CLASS_GLOB + std::forward_list patterns; #endif public: + ExcludeList() + :parent(nullptr) {} + + ExcludeList(const ExcludeList &_parent) + :parent(&_parent) {} + gcc_pure - bool IsEmpty() const { -#ifdef HAVE_GLIB - return patterns.empty(); + bool IsEmpty() const noexcept { +#ifdef HAVE_CLASS_GLOB + return ((parent == nullptr) || parent->IsEmpty()) && patterns.empty(); #else - // TODO: implement + /* not implemented */ return true; #endif } @@ -79,13 +62,13 @@ /** * Loads and parses a .mpdignore file. */ - bool LoadFile(Path path_fs); + bool LoadFile(Path path_fs) noexcept; /** * Checks whether one of the patterns in the .mpdignore file matches * the specified file name. */ - bool Check(Path name_fs) const; + bool Check(Path name_fs) const noexcept; }; diff -Nru mpd-0.19.21/src/db/update/InotifyDomain.cxx mpd-0.20.9/src/db/update/InotifyDomain.cxx --- mpd-0.19.21/src/db/update/InotifyDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/InotifyDomain.hxx mpd-0.20.9/src/db/update/InotifyDomain.hxx --- mpd-0.19.21/src/db/update/InotifyDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/InotifyQueue.cxx mpd-0.20.9/src/db/update/InotifyQueue.cxx --- mpd-0.19.21/src/db/update/InotifyQueue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyQueue.cxx 2017-05-08 14:13:19.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,15 +22,15 @@ #include "InotifyDomain.hxx" #include "Service.hxx" #include "Log.hxx" - -#include +#include "util/StringCompare.hxx" /** * Wait this long after the last change before calling * update_enqueue(). This increases the probability that updates can * be bundled. */ -static constexpr unsigned INOTIFY_UPDATE_DELAY_S = 5; +static constexpr std::chrono::steady_clock::duration INOTIFY_UPDATE_DELAY = + std::chrono::seconds(5); void InotifyQueue::OnTimeout() @@ -43,7 +43,7 @@ id = update.Enqueue(uri_utf8, false); if (id == 0) { /* retry later */ - ScheduleSeconds(INOTIFY_UPDATE_DELAY_S); + Schedule(INOTIFY_UPDATE_DELAY); return; } @@ -54,20 +54,22 @@ } } +gcc_pure static bool -path_in(const char *path, const char *possible_parent) +path_in(const char *path, const char *possible_parent) noexcept { - size_t length = strlen(possible_parent); + if (StringIsEmpty(path)) + return true; - return path[0] == 0 || - (memcmp(possible_parent, path, length) == 0 && - (path[length] == 0 || path[length] == '/')); + auto rest = StringAfterPrefix(path, possible_parent); + return rest != nullptr && + (StringIsEmpty(rest) || rest[0] == '/'); } void InotifyQueue::Enqueue(const char *uri_utf8) { - ScheduleSeconds(INOTIFY_UPDATE_DELAY_S); + Schedule(INOTIFY_UPDATE_DELAY); for (auto i = queue.begin(), end = queue.end(); i != end;) { const char *current_uri = i->c_str(); diff -Nru mpd-0.19.21/src/db/update/InotifyQueue.hxx mpd-0.20.9/src/db/update/InotifyQueue.hxx --- mpd-0.19.21/src/db/update/InotifyQueue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyQueue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/InotifySource.cxx mpd-0.20.9/src/db/update/InotifySource.cxx --- mpd-0.19.21/src/db/update/InotifySource.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifySource.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,11 @@ #include "config.h" #include "InotifySource.hxx" #include "InotifyDomain.hxx" -#include "util/Error.hxx" -#include "system/fd_util.h" +#include "system/FileDescriptor.hxx" #include "system/FatalError.hxx" +#include "system/Error.hxx" #include "Log.hxx" -#include - #include #include #include @@ -69,37 +67,30 @@ return true; } -inline -InotifySource::InotifySource(EventLoop &_loop, - mpd_inotify_callback_t _callback, void *_ctx, - int _fd) - :SocketMonitor(_fd, _loop), - callback(_callback), callback_ctx(_ctx) +static int +InotifyInit() { - ScheduleRead(); + FileDescriptor fd; + if (!fd.CreateInotify()) + throw MakeErrno("inotify_init() has failed"); + return fd.Get(); } -InotifySource * -InotifySource::Create(EventLoop &loop, - mpd_inotify_callback_t callback, void *callback_ctx, - Error &error) +InotifySource::InotifySource(EventLoop &_loop, + mpd_inotify_callback_t _callback, void *_ctx) + :SocketMonitor(InotifyInit(), _loop), + callback(_callback), callback_ctx(_ctx) { - int fd = inotify_init_cloexec(); - if (fd < 0) { - error.SetErrno("inotify_init() has failed"); - return nullptr; - } - - return new InotifySource(loop, callback, callback_ctx, fd); + ScheduleRead(); } int -InotifySource::Add(const char *path_fs, unsigned mask, Error &error) +InotifySource::Add(const char *path_fs, unsigned mask) { int wd = inotify_add_watch(Get(), path_fs, mask); if (wd < 0) - error.SetErrno("inotify_add_watch() has failed"); + throw MakeErrno("inotify_add_watch() has failed"); return wd; } diff -Nru mpd-0.19.21/src/db/update/InotifySource.hxx mpd-0.20.9/src/db/update/InotifySource.hxx --- mpd-0.19.21/src/db/update/InotifySource.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifySource.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ #include "event/SocketMonitor.hxx" #include "Compiler.h" -class Error; +class FileDescriptor; typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask, const char *name, void *ctx); @@ -32,31 +32,31 @@ mpd_inotify_callback_t callback; void *callback_ctx; +public: + /** + * Creates a new inotify source and registers it in the + * #EventLoop. + * + * Throws #std::system_error on error. + * + * @param callback a callback invoked for events received from + * the kernel + */ InotifySource(EventLoop &_loop, - mpd_inotify_callback_t callback, void *ctx, int fd); + mpd_inotify_callback_t callback, void *ctx); -public: ~InotifySource() { Close(); } /** - * Creates a new inotify source and registers it in the GLib main - * loop. - * - * @param a callback invoked for events received from the kernel - */ - static InotifySource *Create(EventLoop &_loop, - mpd_inotify_callback_t callback, - void *ctx, - Error &error); - - /** * Adds a path to the notify list. * - * @return a watch descriptor or -1 on error + * Throws #std::system_error on error. + * + * @return a watch descriptor */ - int Add(const char *path_fs, unsigned mask, Error &error); + int Add(const char *path_fs, unsigned mask); /** * Removes a path from the notify list. diff -Nru mpd-0.19.21/src/db/update/InotifyUpdate.cxx mpd-0.20.9/src/db/update/InotifyUpdate.cxx --- mpd-0.19.21/src/db/update/InotifyUpdate.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyUpdate.cxx 2017-05-08 14:12:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,8 +24,7 @@ #include "InotifyDomain.hxx" #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" -#include "fs/FileSystem.hxx" -#include "util/Error.hxx" +#include "fs/FileInfo.hxx" #include "Log.hxx" #include @@ -34,7 +33,6 @@ #include #include -#include #include #include @@ -64,10 +62,10 @@ WatchDirectory &operator=(const WatchDirectory &) = delete; gcc_pure - unsigned GetDepth() const; + unsigned GetDepth() const noexcept; gcc_pure - AllocatedPath GetUriFS() const; + AllocatedPath GetUriFS() const noexcept; }; static InotifySource *inotify_source; @@ -134,7 +132,7 @@ } AllocatedPath -WatchDirectory::GetUriFS() const +WatchDirectory::GetUriFS() const noexcept { if (parent == nullptr) return AllocatedPath::Null(); @@ -158,7 +156,6 @@ recursive_watch_subdirectories(WatchDirectory *directory, const AllocatedPath &path_fs, unsigned depth) { - Error error; DIR *dir; struct dirent *ent; @@ -179,7 +176,6 @@ } while ((ent = readdir(dir))) { - struct stat st; int ret; if (skip_path(ent->d_name)) @@ -187,24 +183,25 @@ const auto child_path_fs = AllocatedPath::Build(path_fs, ent->d_name); - ret = StatFile(child_path_fs, st); - if (ret < 0) { - FormatErrno(inotify_domain, - "Failed to stat %s", - child_path_fs.c_str()); + + FileInfo fi; + try { + fi = FileInfo(child_path_fs); + } catch (const std::runtime_error &e) { + LogError(e); continue; } - if (!S_ISDIR(st.st_mode)) + if (!fi.IsDirectory()) continue; - ret = inotify_source->Add(child_path_fs.c_str(), IN_MASK, - error); - if (ret < 0) { - FormatError(error, + try { + ret = inotify_source->Add(child_path_fs.c_str(), + IN_MASK); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to register %s", child_path_fs.c_str()); - error.Clear(); continue; } @@ -228,7 +225,7 @@ gcc_pure unsigned -WatchDirectory::GetDepth() const +WatchDirectory::GetDepth() const noexcept { const WatchDirectory *d = this; unsigned depth = 0; @@ -301,20 +298,22 @@ return; } - Error error; - inotify_source = InotifySource::Create(loop, - mpd_inotify_callback, nullptr, - error); - if (inotify_source == nullptr) { - LogError(error); + try { + inotify_source = new InotifySource(loop, + mpd_inotify_callback, + nullptr); + } catch (const std::runtime_error &e) { + LogError(e); return; } inotify_max_depth = max_depth; - int descriptor = inotify_source->Add(path.c_str(), IN_MASK, error); - if (descriptor < 0) { - LogError(error); + int descriptor; + try { + descriptor = inotify_source->Add(path.c_str(), IN_MASK); + } catch (const std::runtime_error &e) { + LogError(e); delete inotify_source; inotify_source = nullptr; return; @@ -332,7 +331,7 @@ } void -mpd_inotify_finish(void) +mpd_inotify_finish(void) noexcept { if (inotify_source == nullptr) return; diff -Nru mpd-0.19.21/src/db/update/InotifyUpdate.hxx mpd-0.20.9/src/db/update/InotifyUpdate.hxx --- mpd-0.19.21/src/db/update/InotifyUpdate.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/InotifyUpdate.hxx 2017-05-08 14:12:36.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,6 +32,6 @@ unsigned max_depth); void -mpd_inotify_finish(void); +mpd_inotify_finish() noexcept; #endif diff -Nru mpd-0.19.21/src/db/update/Queue.cxx mpd-0.20.9/src/db/update/Queue.cxx --- mpd-0.19.21/src/db/update/Queue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Queue.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/Queue.hxx mpd-0.20.9/src/db/update/Queue.hxx --- mpd-0.19.21/src/db/update/Queue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Queue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/Remove.cxx mpd-0.20.9/src/db/update/Remove.cxx --- mpd-0.19.21/src/db/update/Remove.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Remove.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,49 +20,50 @@ #include "config.h" /* must be first for large file support */ #include "Remove.hxx" #include "UpdateDomain.hxx" -#include "db/plugins/simple/Song.hxx" -#include "db/LightSong.hxx" #include "db/DatabaseListener.hxx" #include "Log.hxx" -#include - /** - * Safely remove a song from the database. This must be done in the - * main task, to be sure that there is no pointer left to it. + * Safely remove songs from the database. This must be done in the + * main task, because some (thread-unsafe) data structures are + * available only there. */ void UpdateRemoveService::RunDeferred() { - assert(removed_song != nullptr); + /* copy the list and unlock the mutex before invoking + callbacks */ + + std::forward_list copy; { - const auto uri = removed_song->GetURI(); - FormatDefault(update_domain, "removing %s", uri.c_str()); + const std::lock_guard protect(mutex); + std::swap(uris, copy); } - listener.OnDatabaseSongRemoved(removed_song->Export()); + for (const auto &uri : copy) { + FormatDefault(update_domain, "removing %s", uri.c_str()); + listener.OnDatabaseSongRemoved(uri.c_str()); + } - /* clear "removed_song" and send signal to update thread */ - remove_mutex.lock(); - removed_song = nullptr; - remove_cond.signal(); - remove_mutex.unlock(); + /* note: if Remove() was called in the meantime, it saw an + empty list, and scheduled another event */ } void -UpdateRemoveService::Remove(const Song *song) +UpdateRemoveService::Remove(std::string &&uri) { - assert(removed_song == nullptr); + bool was_empty; - removed_song = song; - - DeferredMonitor::Schedule(); - - remove_mutex.lock(); - - while (removed_song != nullptr) - remove_cond.wait(remove_mutex); + { + const std::lock_guard protect(mutex); + was_empty = uris.empty(); + uris.emplace_front(std::move(uri)); + } - remove_mutex.unlock(); + /* inject an event into the main thread, but only if the list + was empty; if it was not, then that even was already + pending */ + if (was_empty) + DeferredMonitor::Schedule(); } diff -Nru mpd-0.19.21/src/db/update/Remove.hxx mpd-0.20.9/src/db/update/Remove.hxx --- mpd-0.19.21/src/db/update/Remove.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Remove.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,9 +23,11 @@ #include "check.h" #include "event/DeferredMonitor.hxx" #include "thread/Mutex.hxx" -#include "thread/Cond.hxx" #include "Compiler.h" +#include +#include + struct Song; class DatabaseListener; @@ -36,15 +38,13 @@ class UpdateRemoveService final : DeferredMonitor { DatabaseListener &listener; - Mutex remove_mutex; - Cond remove_cond; + Mutex mutex; - const Song *removed_song; + std::forward_list uris; public: UpdateRemoveService(EventLoop &_loop, DatabaseListener &_listener) - :DeferredMonitor(_loop), listener(_listener), - removed_song(nullptr){} + :DeferredMonitor(_loop), listener(_listener) {} /** * Sends a signal to the main thread which will in turn remove @@ -52,7 +52,7 @@ * This serialized access is implemented to avoid excessive * locking. */ - void Remove(const Song *song); + void Remove(std::string &&uri); private: /* virtual methods from class DeferredMonitor */ diff -Nru mpd-0.19.21/src/db/update/Service.cxx mpd-0.20.9/src/db/update/Service.cxx --- mpd-0.19.21/src/db/update/Service.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Service.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,11 +27,7 @@ #include "db/plugins/simple/Directory.hxx" #include "storage/CompositeStorage.hxx" #include "Idle.hxx" -#include "util/Error.hxx" #include "Log.hxx" -#include "Instance.hxx" -#include "system/FatalError.hxx" -#include "thread/Id.hxx" #include "thread/Thread.hxx" #include "thread/Util.hxx" @@ -47,7 +43,6 @@ :DeferredMonitor(_loop), db(_db), storage(_storage), listener(_listener), - progress(UPDATE_PROGRESS_IDLE), update_task_id(0), walk(nullptr) { @@ -80,9 +75,11 @@ /* determine which (mounted) database will be updated and what storage will be scanned */ - db_lock(); - const auto lr = db.GetRoot().LookupDirectory(uri); - db_unlock(); + Directory::LookupResult lr; + { + const ScopeDatabaseLock protect; + lr = db.GetRoot().LookupDirectory(uri); + } if (!lr.directory->IsMount()) return; @@ -127,9 +124,11 @@ next.discard); if (modified || !next.db->FileExists()) { - Error error; - if (!next.db->Save(error)) - LogError(error, "Failed to save database"); + try { + next.db->Save(); + } catch (const std::exception &e) { + LogError(e, "Failed to save database"); + } } if (!next.path_utf8.empty()) @@ -138,7 +137,6 @@ else LogDebug(update_domain, "finished"); - progress = UPDATE_PROGRESS_DONE; DeferredMonitor::Schedule(); } @@ -155,15 +153,12 @@ assert(GetEventLoop().IsInsideOrNull()); assert(walk == nullptr); - progress = UPDATE_PROGRESS_RUNNING; modified = false; next = std::move(i); walk = new UpdateWalk(GetEventLoop(), listener, *next.storage); - Error error; - if (!update_thread.Start(Task, this, error)) - FatalError(error); + update_thread.Start(Task, this); FormatDebug(update_domain, "spawned thread for update job id %i", next.id); @@ -188,9 +183,12 @@ SimpleDatabase *db2; Storage *storage2; - db_lock(); - const auto lr = db.GetRoot().LookupDirectory(path); - db_unlock(); + Directory::LookupResult lr; + { + const ScopeDatabaseLock protect; + lr = db.GetRoot().LookupDirectory(path); + } + if (lr.directory->IsMount()) { /* follow the mountpoint, update the mounted database */ @@ -226,7 +224,7 @@ happen */ return 0; - if (progress != UPDATE_PROGRESS_IDLE) { + if (walk != nullptr) { const unsigned id = GenerateId(); if (!queue.Push(*db2, *storage2, path, discard, id)) return 0; @@ -249,7 +247,6 @@ void UpdateService::RunDeferred() { - assert(progress == UPDATE_PROGRESS_DONE); assert(next.IsDefined()); assert(walk != nullptr); @@ -273,7 +270,5 @@ if (i.IsDefined()) { /* schedule the next path */ StartThread(std::move(i)); - } else { - progress = UPDATE_PROGRESS_IDLE; } } diff -Nru mpd-0.19.21/src/db/update/Service.hxx mpd-0.20.9/src/db/update/Service.hxx --- mpd-0.19.21/src/db/update/Service.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Service.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -35,24 +35,16 @@ * This class manages the update queue and runs the update thread. */ class UpdateService final : DeferredMonitor { - enum Progress { - UPDATE_PROGRESS_IDLE = 0, - UPDATE_PROGRESS_RUNNING = 1, - UPDATE_PROGRESS_DONE = 2 - }; - SimpleDatabase &db; CompositeStorage &storage; DatabaseListener &listener; - Progress progress; - bool modified; Thread update_thread; - static const unsigned update_task_id_max = 1 << 15; + static constexpr unsigned update_task_id_max = 1 << 15; unsigned update_task_id; diff -Nru mpd-0.19.21/src/db/update/UpdateDomain.cxx mpd-0.20.9/src/db/update/UpdateDomain.cxx --- mpd-0.19.21/src/db/update/UpdateDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/UpdateDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/UpdateDomain.hxx mpd-0.20.9/src/db/update/UpdateDomain.hxx --- mpd-0.19.21/src/db/update/UpdateDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/UpdateDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/update/UpdateIO.cxx mpd-0.20.9/src/db/update/UpdateIO.cxx --- mpd-0.19.21/src/db/update/UpdateIO.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/UpdateIO.cxx 2017-05-08 13:39:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,45 +19,48 @@ #include "config.h" /* must be first for large file support */ #include "UpdateIO.hxx" -#include "UpdateDomain.hxx" #include "db/plugins/simple/Directory.hxx" #include "storage/FileInfo.hxx" #include "storage/StorageInterface.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "fs/AllocatedPath.hxx" -#include "util/Error.hxx" #include "Log.hxx" +#include + #include -#include bool -GetInfo(Storage &storage, const char *uri_utf8, FileInfo &info) -{ - Error error; - bool success = storage.GetInfo(uri_utf8, true, info, error); - if (!success) - LogError(error); - return success; +GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info) noexcept +try { + info = storage.GetInfo(uri_utf8, true); + return true; +} catch (const std::runtime_error &e) { + LogError(e); + return false; } bool -GetInfo(StorageDirectoryReader &reader, FileInfo &info) -{ - Error error; - bool success = reader.GetInfo(true, info, error); - if (!success) - LogError(error); - return success; +GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info) noexcept +try { + info = reader.GetInfo(true); + return true; +} catch (const std::runtime_error &e) { + LogError(e); + return false; } bool -DirectoryExists(Storage &storage, const Directory &directory) +DirectoryExists(Storage &storage, const Directory &directory) noexcept { - FileInfo info; - if (!storage.GetInfo(directory.GetPath(), true, info, IgnoreError())) + StorageFileInfo info; + + try { + info = storage.GetInfo(directory.GetPath(), true); + } catch (const std::runtime_error &) { return false; + } return directory.device == DEVICE_INARCHIVE || directory.device == DEVICE_CONTAINER @@ -65,28 +68,28 @@ : info.IsDirectory(); } -static bool +static StorageFileInfo GetDirectoryChildInfo(Storage &storage, const Directory &directory, - const char *name_utf8, FileInfo &info, Error &error) + const char *name_utf8) { const auto uri_utf8 = PathTraitsUTF8::Build(directory.GetPath(), name_utf8); - return storage.GetInfo(uri_utf8.c_str(), true, info, error); + return storage.GetInfo(uri_utf8.c_str(), true); } bool directory_child_is_regular(Storage &storage, const Directory &directory, - const char *name_utf8) -{ - FileInfo info; - return GetDirectoryChildInfo(storage, directory, name_utf8, info, - IgnoreError()) && - info.IsRegular(); + const char *name_utf8) noexcept +try { + return GetDirectoryChildInfo(storage, directory, name_utf8) + .IsRegular(); +} catch (const std::runtime_error &) { + return false; } bool directory_child_access(Storage &storage, const Directory &directory, - const char *name, int mode) + const char *name, int mode) noexcept { #ifdef WIN32 /* CheckAccess() is useless on WIN32 */ diff -Nru mpd-0.19.21/src/db/update/UpdateIO.hxx mpd-0.20.9/src/db/update/UpdateIO.hxx --- mpd-0.19.21/src/db/update/UpdateIO.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/UpdateIO.hxx 2017-05-08 13:39:31.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,7 @@ #include "Compiler.h" struct Directory; -struct FileInfo; +struct StorageFileInfo; class Storage; class StorageDirectoryReader; @@ -33,23 +33,23 @@ * returning them. */ bool -GetInfo(Storage &storage, const char *uri_utf8, FileInfo &info); +GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info) noexcept; /** * Wrapper for LocalDirectoryReader::GetInfo() that logs errors * instead of returning them. */ bool -GetInfo(StorageDirectoryReader &reader, FileInfo &info); +GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info) noexcept; gcc_pure bool -DirectoryExists(Storage &storage, const Directory &directory); +DirectoryExists(Storage &storage, const Directory &directory) noexcept; gcc_pure bool directory_child_is_regular(Storage &storage, const Directory &directory, - const char *name_utf8); + const char *name_utf8) noexcept; /** * Checks if the given permissions on the mapped file are given. @@ -57,6 +57,6 @@ gcc_pure bool directory_child_access(Storage &storage, const Directory &directory, - const char *name, int mode); + const char *name, int mode) noexcept; #endif diff -Nru mpd-0.19.21/src/db/update/UpdateSong.cxx mpd-0.20.9/src/db/update/UpdateSong.cxx --- mpd-0.19.21/src/db/update/UpdateSong.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/UpdateSong.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -33,11 +33,13 @@ inline void UpdateWalk::UpdateSongFile2(Directory &directory, const char *name, const char *suffix, - const FileInfo &info) + const StorageFileInfo &info) { - db_lock(); - Song *song = directory.FindSong(name); - db_unlock(); + Song *song; + { + const ScopeDatabaseLock protect; + song = directory.FindSong(name); + } if (!directory_child_access(storage, directory, name, R_OK)) { FormatError(update_domain, @@ -69,9 +71,10 @@ return; } - db_lock(); - directory.AddSong(song); - db_unlock(); + { + const ScopeDatabaseLock protect; + directory.AddSong(song); + } modified = true; FormatDefault(update_domain, "added %s/%s", @@ -93,7 +96,7 @@ bool UpdateWalk::UpdateSongFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info) + const StorageFileInfo &info) { if (!decoder_plugins_supports_suffix(suffix)) return false; diff -Nru mpd-0.19.21/src/db/update/Walk.cxx mpd-0.20.9/src/db/update/Walk.cxx --- mpd-0.19.21/src/db/update/Walk.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Walk.cxx 2017-05-08 13:40:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -35,19 +35,19 @@ #include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" -#include "fs/Charset.hxx" #include "storage/FileInfo.hxx" #include "util/Alloc.hxx" +#include "util/StringCompare.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" #include "Log.hxx" +#include +#include + #include -#include #include #include #include -#include UpdateWalk::UpdateWalk(EventLoop &_loop, DatabaseListener &_listener, Storage &_storage) @@ -57,17 +57,17 @@ { #ifndef WIN32 follow_inside_symlinks = - config_get_bool(CONF_FOLLOW_INSIDE_SYMLINKS, + config_get_bool(ConfigOption::FOLLOW_INSIDE_SYMLINKS, DEFAULT_FOLLOW_INSIDE_SYMLINKS); follow_outside_symlinks = - config_get_bool(CONF_FOLLOW_OUTSIDE_SYMLINKS, + config_get_bool(ConfigOption::FOLLOW_OUTSIDE_SYMLINKS, DEFAULT_FOLLOW_OUTSIDE_SYMLINKS); #endif } static void -directory_set_stat(Directory &dir, const FileInfo &info) +directory_set_stat(Directory &dir, const StorageFileInfo &info) { dir.inode = info.inode; dir.device = info.device; @@ -77,7 +77,7 @@ UpdateWalk::RemoveExcludedFromDirectory(Directory &directory, const ExcludeList &exclude_list) { - db_lock(); + const ScopeDatabaseLock protect; directory.ForEachChildSafe([&](Directory &child){ const auto name_fs = @@ -98,8 +98,6 @@ modified = true; } }); - - db_unlock(); } inline void @@ -128,9 +126,8 @@ i != end;) { if (!directory_child_is_regular(storage, directory, i->name.c_str())) { - db_lock(); + const ScopeDatabaseLock protect; i = directory.playlists.erase(i); - db_unlock(); } else ++i; } @@ -140,7 +137,7 @@ static bool update_directory_stat(Storage &storage, Directory &directory) { - FileInfo info; + StorageFileInfo info; if (!GetInfo(storage, directory.GetPath(), info)) return false; @@ -190,23 +187,22 @@ inline bool UpdateWalk::UpdatePlaylistFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info) + const StorageFileInfo &info) { if (!playlist_suffix_supported(suffix)) return false; PlaylistInfo pi(name, info.mtime); - db_lock(); + const ScopeDatabaseLock protect; if (directory.playlists.UpdateOrInsert(std::move(pi))) modified = true; - db_unlock(); return true; } inline bool UpdateWalk::UpdateRegularFile(Directory &directory, - const char *name, const FileInfo &info) + const char *name, const StorageFileInfo &info) { const char *suffix = uri_get_suffix(name); if (suffix == nullptr) @@ -219,8 +215,9 @@ void UpdateWalk::UpdateDirectoryChild(Directory &directory, - const char *name, const FileInfo &info) -{ + const ExcludeList &exclude_list, + const char *name, const StorageFileInfo &info) +try { assert(strchr(name, '/') == nullptr); if (info.IsRegular()) { @@ -230,24 +227,28 @@ info.inode, info.device)) return; - db_lock(); - Directory *subdir = directory.MakeChild(name); - db_unlock(); + Directory *subdir; + { + const ScopeDatabaseLock protect; + subdir = directory.MakeChild(name); + } assert(&directory == subdir->parent); - if (!UpdateDirectory(*subdir, info)) + if (!UpdateDirectory(*subdir, exclude_list, info)) editor.LockDeleteDirectory(subdir); } else { FormatDebug(update_domain, "%s is not a directory, archive or music", name); } +} catch (const std::exception &e) { + LogError(e); } /* we don't look at "." / ".." nor files with newlines in their name */ gcc_pure static bool -skip_path(const char *name_utf8) +skip_path(const char *name_utf8) noexcept { return strchr(name_utf8, '\n') != nullptr; } @@ -255,7 +256,7 @@ gcc_pure bool UpdateWalk::SkipSymlink(const Directory *directory, - const char *utf8_name) const + const char *utf8_name) const noexcept { #ifndef WIN32 const auto path_fs = storage.MapChildFS(directory->GetPath(), @@ -277,12 +278,10 @@ return false; } - const char *target_str = target.c_str(); - - if (PathTraitsFS::IsAbsolute(target_str)) { + if (target.IsAbsolute()) { /* if the symlink points to an absolute path, see if that path is inside the music directory */ - const auto target_utf8 = PathToUTF8(target_str); + const auto target_utf8 = target.ToUTF8(); if (target_utf8.empty()) return true; @@ -293,7 +292,7 @@ : !follow_outside_symlinks; } - const char *p = target_str; + const char *p = target.c_str(); while (*p == '.') { if (p[1] == '.' && PathTraitsFS::IsSeparator(p[2])) { /* "../" moves to parent directory */ @@ -327,30 +326,34 @@ } bool -UpdateWalk::UpdateDirectory(Directory &directory, const FileInfo &info) +UpdateWalk::UpdateDirectory(Directory &directory, + const ExcludeList &exclude_list, + const StorageFileInfo &info) { assert(info.IsDirectory()); directory_set_stat(directory, info); - Error error; - const std::unique_ptr reader(storage.OpenDirectory(directory.GetPath(), error)); - if (reader.get() == nullptr) { - LogError(error); + std::unique_ptr reader; + + try { + reader.reset(storage.OpenDirectory(directory.GetPath())); + } catch (const std::runtime_error &e) { + LogError(e); return false; } - ExcludeList exclude_list; + ExcludeList child_exclude_list(exclude_list); { const auto exclude_path_fs = storage.MapChildFS(directory.GetPath(), ".mpdignore"); if (!exclude_path_fs.IsNull()) - exclude_list.LoadFile(exclude_path_fs); + child_exclude_list.LoadFile(exclude_path_fs); } - if (!exclude_list.IsEmpty()) - RemoveExcludedFromDirectory(directory, exclude_list); + if (!child_exclude_list.IsEmpty()) + RemoveExcludedFromDirectory(directory, child_exclude_list); PurgeDeletedFromDirectory(directory); @@ -361,7 +364,7 @@ { const auto name_fs = AllocatedPath::FromUTF8(name_utf8); - if (name_fs.IsNull() || exclude_list.Check(name_fs)) + if (name_fs.IsNull() || child_exclude_list.Check(name_fs)) continue; } @@ -370,13 +373,13 @@ continue; } - FileInfo info2; + StorageFileInfo info2; if (!GetInfo(*reader, info2)) { modified |= editor.DeleteNameIn(directory, name_utf8); continue; } - UpdateDirectoryChild(directory, name_utf8, info2); + UpdateDirectoryChild(directory, child_exclude_list, name_utf8, info2); } directory.mtime = info.mtime; @@ -389,9 +392,11 @@ const char *uri_utf8, const char *name_utf8) { - db_lock(); - Directory *directory = parent.FindChild(name_utf8); - db_unlock(); + Directory *directory; + { + const ScopeDatabaseLock protect; + directory = parent.FindChild(name_utf8); + } if (directory != nullptr) { if (directory->IsMount()) @@ -400,7 +405,7 @@ return directory; } - FileInfo info; + StorageFileInfo info; if (!GetInfo(storage, uri_utf8, info) || FindAncestorLoop(storage, &parent, info.inode, info.device)) return nullptr; @@ -410,13 +415,14 @@ /* if we're adding directory paths, make sure to delete filenames with potentially the same name */ - db_lock(); - Song *conflicting = parent.FindSong(name_utf8); - if (conflicting) - editor.DeleteSong(parent, conflicting); + { + const ScopeDatabaseLock protect; + Song *conflicting = parent.FindSong(name_utf8); + if (conflicting) + editor.DeleteSong(parent, conflicting); - directory = parent.CreateChild(name_utf8); - db_unlock(); + directory = parent.CreateChild(name_utf8); + } directory_set_stat(*directory, info); return directory; @@ -432,7 +438,7 @@ while ((slash = strchr(name_utf8, '/')) != nullptr) { *slash = 0; - if (*name_utf8 == 0) + if (StringIsEmpty(name_utf8)) continue; directory = DirectoryMakeChildChecked(*directory, @@ -450,7 +456,7 @@ inline void UpdateWalk::UpdateUri(Directory &root, const char *uri) -{ +try { Directory *parent = DirectoryMakeUriParentChecked(root, uri); if (parent == nullptr) return; @@ -462,13 +468,17 @@ return; } - FileInfo info; + StorageFileInfo info; if (!GetInfo(storage, uri, info)) { modified |= editor.DeleteNameIn(*parent, name); return; } - UpdateDirectoryChild(*parent, name, info); + ExcludeList exclude_list; + + UpdateDirectoryChild(*parent, exclude_list, name, info); +} catch (const std::exception &e) { + LogError(e); } bool @@ -480,11 +490,13 @@ if (path != nullptr && !isRootDirectory(path)) { UpdateUri(root, path); } else { - FileInfo info; + StorageFileInfo info; if (!GetInfo(storage, "", info)) return false; - UpdateDirectory(root, info); + ExcludeList exclude_list; + + UpdateDirectory(root, exclude_list, info); } return modified; diff -Nru mpd-0.19.21/src/db/update/Walk.hxx mpd-0.20.9/src/db/update/Walk.hxx --- mpd-0.19.21/src/db/update/Walk.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/update/Walk.hxx 2017-05-08 13:40:30.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,12 +24,10 @@ #include "Editor.hxx" #include "Compiler.h" -#include - -struct stat; -struct FileInfo; +struct StorageFileInfo; struct Directory; struct ArchivePlugin; +class ArchiveFile; class Storage; class ExcludeList; @@ -80,7 +78,7 @@ private: gcc_pure bool SkipSymlink(const Directory *directory, - const char *utf8_name) const; + const char *utf8_name) const noexcept; void RemoveExcludedFromDirectory(Directory &directory, const ExcludeList &exclude_list); @@ -89,26 +87,27 @@ void UpdateSongFile2(Directory &directory, const char *name, const char *suffix, - const FileInfo &info); + const StorageFileInfo &info); bool UpdateSongFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info); + const StorageFileInfo &info); bool UpdateContainerFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info); + const StorageFileInfo &info); #ifdef ENABLE_ARCHIVE - void UpdateArchiveTree(Directory &parent, const char *name); + void UpdateArchiveTree(ArchiveFile &archive, Directory &parent, + const char *name); bool UpdateArchiveFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info); + const StorageFileInfo &info); void UpdateArchiveFile(Directory &directory, const char *name, - const FileInfo &info, + const StorageFileInfo &info, const ArchivePlugin &plugin); @@ -116,33 +115,37 @@ bool UpdateArchiveFile(gcc_unused Directory &directory, gcc_unused const char *name, gcc_unused const char *suffix, - gcc_unused const FileInfo &info) { + gcc_unused const StorageFileInfo &info) { return false; } #endif bool UpdatePlaylistFile(Directory &directory, const char *name, const char *suffix, - const FileInfo &info); + const StorageFileInfo &info); bool UpdateRegularFile(Directory &directory, - const char *name, const FileInfo &info); + const char *name, const StorageFileInfo &info); void UpdateDirectoryChild(Directory &directory, - const char *name, const FileInfo &info); - - bool UpdateDirectory(Directory &directory, const FileInfo &info); + const ExcludeList &exclude_list, + const char *name, + const StorageFileInfo &info); + + bool UpdateDirectory(Directory &directory, + const ExcludeList &exclude_list, + const StorageFileInfo &info); /** * Create the specified directory object if it does not exist - * already or if the #stat object indicates that it has been + * already or if the #StorageFileInfo object indicates that it has been * modified since the last update. Returns nullptr when it * exists already and is unmodified. * * The caller must lock the database. */ Directory *MakeDirectoryIfModified(Directory &parent, const char *name, - const FileInfo &info); + const StorageFileInfo &info); Directory *DirectoryMakeChildChecked(Directory &parent, const char *uri_utf8, diff -Nru mpd-0.19.21/src/db/Uri.hxx mpd-0.20.9/src/db/Uri.hxx --- mpd-0.19.21/src/db/Uri.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Uri.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/db/Visitor.hxx mpd-0.20.9/src/db/Visitor.hxx --- mpd-0.19.21/src/db/Visitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/db/Visitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,13 +26,12 @@ struct LightSong; struct PlaylistInfo; struct Tag; -class Error; -typedef std::function VisitDirectory; -typedef std::function VisitSong; -typedef std::function VisitPlaylist; +typedef std::function VisitDirectory; +typedef std::function VisitSong; +typedef std::function VisitPlaylist; -typedef std::function VisitTag; +typedef std::function VisitTag; #endif diff -Nru mpd-0.19.21/src/decoder/Bridge.cxx mpd-0.20.9/src/decoder/Bridge.cxx --- mpd-0.19.21/src/decoder/Bridge.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/Bridge.cxx 2017-06-03 19:50:35.000000000 +0000 @@ -0,0 +1,612 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Bridge.hxx" +#include "DecoderAPI.hxx" +#include "DecoderError.hxx" +#include "DecoderControl.hxx" +#include "DetachedSong.hxx" +#include "pcm/PcmConvert.hxx" +#include "MusicPipe.hxx" +#include "MusicBuffer.hxx" +#include "MusicChunk.hxx" +#include "pcm/PcmConvert.hxx" +#include "tag/Tag.hxx" +#include "Log.hxx" +#include "input/InputStream.hxx" +#include "util/ConstBuffer.hxx" +#include "util/StringBuffer.hxx" + +#include +#include +#include + +DecoderBridge::~DecoderBridge() +{ + /* caller must flush the chunk */ + assert(current_chunk == nullptr); + + if (convert != nullptr) { + convert->Close(); + delete convert; + } + + delete song_tag; + delete stream_tag; + delete decoder_tag; +} + +bool +DecoderBridge::CheckCancelRead() const noexcept +{ + if (error) + /* this translates to DecoderCommand::STOP */ + return true; + + if (dc.command == DecoderCommand::NONE) + return false; + + /* ignore the SEEK command during initialization, the plugin + should handle that after it has initialized successfully */ + if (dc.command == DecoderCommand::SEEK && + (dc.state == DecoderState::START || seeking || + initial_seek_running)) + return false; + + return true; +} + +/** + * All chunks are full of decoded data; wait for the player to free + * one. + */ +static DecoderCommand +need_chunks(DecoderControl &dc) noexcept +{ + if (dc.command == DecoderCommand::NONE) + dc.Wait(); + + return dc.command; +} + +static DecoderCommand +LockNeedChunks(DecoderControl &dc) noexcept +{ + const std::lock_guard protect(dc.mutex); + return need_chunks(dc); +} + +MusicChunk * +DecoderBridge::GetChunk() noexcept +{ + DecoderCommand cmd; + + if (current_chunk != nullptr) + return current_chunk; + + do { + current_chunk = dc.buffer->Allocate(); + if (current_chunk != nullptr) { + current_chunk->replay_gain_serial = replay_gain_serial; + if (replay_gain_serial != 0) + current_chunk->replay_gain_info = replay_gain_info; + + return current_chunk; + } + + cmd = LockNeedChunks(dc); + } while (cmd == DecoderCommand::NONE); + + return nullptr; +} + +void +DecoderBridge::FlushChunk() +{ + assert(!seeking); + assert(!initial_seek_running); + assert(!initial_seek_pending); + assert(current_chunk != nullptr); + + auto *chunk = std::exchange(current_chunk, nullptr); + if (chunk->IsEmpty()) + dc.buffer->Return(chunk); + else + dc.pipe->Push(chunk); + + const std::lock_guard protect(dc.mutex); + if (dc.client_is_waiting) + dc.client_cond.signal(); +} + +bool +DecoderBridge::PrepareInitialSeek() +{ + assert(dc.pipe != nullptr); + + if (dc.state != DecoderState::DECODE) + /* wait until the decoder has finished initialisation + (reading file headers etc.) before emitting the + virtual "SEEK" command */ + return false; + + if (initial_seek_running) + /* initial seek has already begun - override any other + command */ + return true; + + if (initial_seek_pending) { + if (!dc.seekable) { + /* seeking is not possible */ + initial_seek_pending = false; + return false; + } + + if (dc.command == DecoderCommand::NONE) { + /* begin initial seek */ + + initial_seek_pending = false; + initial_seek_running = true; + return true; + } + + /* skip initial seek when there's another command + (e.g. STOP) */ + + initial_seek_pending = false; + } + + return false; +} + +DecoderCommand +DecoderBridge::GetVirtualCommand() noexcept +{ + if (error) + /* an error has occurred: stop the decoder plugin */ + return DecoderCommand::STOP; + + assert(dc.pipe != nullptr); + + if (PrepareInitialSeek()) + return DecoderCommand::SEEK; + + return dc.command; +} + +DecoderCommand +DecoderBridge::LockGetVirtualCommand() noexcept +{ + const std::lock_guard protect(dc.mutex); + return GetVirtualCommand(); +} + +DecoderCommand +DecoderBridge::DoSendTag(const Tag &tag) +{ + if (current_chunk != nullptr) { + /* there is a partial chunk - flush it, we want the + tag in a new chunk */ + FlushChunk(); + } + + assert(current_chunk == nullptr); + + auto *chunk = GetChunk(); + if (chunk == nullptr) { + assert(dc.command != DecoderCommand::NONE); + return dc.command; + } + + chunk->tag = new Tag(tag); + return DecoderCommand::NONE; +} + +bool +DecoderBridge::UpdateStreamTag(InputStream *is) +{ + auto *tag = is != nullptr + ? is->LockReadTag() + : nullptr; + if (tag == nullptr) { + tag = song_tag; + if (tag == nullptr) + return false; + + /* no stream tag present - submit the song tag + instead */ + } else + /* discard the song tag; we don't need it */ + delete song_tag; + + song_tag = nullptr; + + delete stream_tag; + stream_tag = tag; + return true; +} + +void +DecoderBridge::Ready(const AudioFormat audio_format, + bool seekable, SignedSongTime duration) +{ + assert(convert == nullptr); + assert(stream_tag == nullptr); + assert(decoder_tag == nullptr); + assert(!seeking); + + FormatDebug(decoder_domain, "audio_format=%s, seekable=%s", + ToString(audio_format).c_str(), + seekable ? "true" : "false"); + + { + const std::lock_guard protect(dc.mutex); + dc.SetReady(audio_format, seekable, duration); + } + + if (dc.in_audio_format != dc.out_audio_format) { + FormatDebug(decoder_domain, "converting to %s", + ToString(dc.out_audio_format).c_str()); + + convert = new PcmConvert(); + + try { + convert->Open(dc.in_audio_format, + dc.out_audio_format); + } catch (...) { + error = std::current_exception(); + } + } +} + +DecoderCommand +DecoderBridge::GetCommand() noexcept +{ + return LockGetVirtualCommand(); +} + +void +DecoderBridge::CommandFinished() +{ + const std::lock_guard protect(dc.mutex); + + assert(dc.command != DecoderCommand::NONE || initial_seek_running); + assert(dc.command != DecoderCommand::SEEK || + initial_seek_running || + dc.seek_error || seeking); + assert(dc.pipe != nullptr); + + if (initial_seek_running) { + assert(!seeking); + assert(current_chunk == nullptr); + assert(dc.pipe->IsEmpty()); + + initial_seek_running = false; + timestamp = dc.start_time.ToDoubleS(); + return; + } + + if (seeking) { + seeking = false; + + /* delete frames from the old song position */ + + if (current_chunk != nullptr) { + dc.buffer->Return(current_chunk); + current_chunk = nullptr; + } + + dc.pipe->Clear(*dc.buffer); + + if (convert != nullptr) + convert->Reset(); + + timestamp = dc.seek_time.ToDoubleS(); + } + + dc.command = DecoderCommand::NONE; + dc.client_cond.signal(); +} + +SongTime +DecoderBridge::GetSeekTime() noexcept +{ + assert(dc.pipe != nullptr); + + if (initial_seek_running) + return dc.start_time; + + assert(dc.command == DecoderCommand::SEEK); + + seeking = true; + + return dc.seek_time; +} + +uint64_t +DecoderBridge::GetSeekFrame() noexcept +{ + return GetSeekTime().ToScale(dc.in_audio_format.sample_rate); +} + +void +DecoderBridge::SeekError() +{ + assert(dc.pipe != nullptr); + + if (initial_seek_running) { + /* d'oh, we can't seek to the sub-song start position, + what now? - no idea, ignoring the problem for now. */ + initial_seek_running = false; + return; + } + + assert(dc.command == DecoderCommand::SEEK); + + dc.seek_error = true; + seeking = false; + + CommandFinished(); +} + +InputStreamPtr +DecoderBridge::OpenUri(const char *uri) +{ + assert(dc.state == DecoderState::START || + dc.state == DecoderState::DECODE); + + Mutex &mutex = dc.mutex; + Cond &cond = dc.cond; + + auto is = InputStream::Open(uri, mutex, cond); + + const std::lock_guard lock(mutex); + while (true) { + is->Update(); + if (is->IsReady()) + return is; + + if (dc.command == DecoderCommand::STOP) + throw StopDecoder(); + + cond.wait(mutex); + } +} + +size_t +DecoderBridge::Read(InputStream &is, void *buffer, size_t length) +try { + assert(buffer != nullptr); + assert(dc.state == DecoderState::START || + dc.state == DecoderState::DECODE); + + if (length == 0) + return 0; + + std::lock_guard lock(is.mutex); + + while (true) { + if (CheckCancelRead()) + return 0; + + if (is.IsAvailable()) + break; + + is.cond.wait(is.mutex); + } + + size_t nbytes = is.Read(buffer, length); + assert(nbytes > 0 || is.IsEOF()); + + return nbytes; +} catch (const std::runtime_error &e) { + error = std::current_exception(); + return 0; +} + +void +DecoderBridge::SubmitTimestamp(double t) +{ + assert(t >= 0); + + timestamp = t; +} + +DecoderCommand +DecoderBridge::SubmitData(InputStream *is, + const void *data, size_t length, + uint16_t kbit_rate) +{ + assert(dc.state == DecoderState::DECODE); + assert(dc.pipe != nullptr); + assert(length % dc.in_audio_format.GetFrameSize() == 0); + + DecoderCommand cmd = LockGetVirtualCommand(); + + if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK || + length == 0) + return cmd; + + assert(!initial_seek_pending); + assert(!initial_seek_running); + + /* send stream tags */ + + if (UpdateStreamTag(is)) { + if (decoder_tag != nullptr) { + /* merge with tag from decoder plugin */ + Tag *tag = Tag::Merge(*decoder_tag, + *stream_tag); + cmd = DoSendTag(*tag); + delete tag; + } else + /* send only the stream tag */ + cmd = DoSendTag(*stream_tag); + + if (cmd != DecoderCommand::NONE) + return cmd; + } + + if (convert != nullptr) { + assert(dc.in_audio_format != dc.out_audio_format); + + try { + auto result = convert->Convert({data, length}); + data = result.data; + length = result.size; + } catch (const std::runtime_error &e) { + /* the PCM conversion has failed - stop + playback, since we have no better way to + bail out */ + error = std::current_exception(); + return DecoderCommand::STOP; + } + } else { + assert(dc.in_audio_format == dc.out_audio_format); + } + + while (length > 0) { + bool full; + + auto *chunk = GetChunk(); + if (chunk == nullptr) { + assert(dc.command != DecoderCommand::NONE); + return dc.command; + } + + const auto dest = + chunk->Write(dc.out_audio_format, + SongTime::FromS(timestamp) - + dc.song->GetStartTime(), + kbit_rate); + if (dest.IsEmpty()) { + /* the chunk is full, flush it */ + FlushChunk(); + continue; + } + + const size_t nbytes = std::min(dest.size, length); + + /* copy the buffer */ + + memcpy(dest.data, data, nbytes); + + /* expand the music pipe chunk */ + + full = chunk->Expand(dc.out_audio_format, nbytes); + if (full) { + /* the chunk is full, flush it */ + FlushChunk(); + } + + data = (const uint8_t *)data + nbytes; + length -= nbytes; + + timestamp += (double)nbytes / + dc.out_audio_format.GetTimeToSize(); + + if (dc.end_time.IsPositive() && + timestamp >= dc.end_time.ToDoubleS()) + /* the end of this range has been reached: + stop decoding */ + return DecoderCommand::STOP; + } + + return DecoderCommand::NONE; +} + +DecoderCommand +DecoderBridge::SubmitTag(InputStream *is, Tag &&tag) +{ + DecoderCommand cmd; + + assert(dc.state == DecoderState::DECODE); + assert(dc.pipe != nullptr); + + /* save the tag */ + + delete decoder_tag; + decoder_tag = new Tag(std::move(tag)); + + /* check for a new stream tag */ + + UpdateStreamTag(is); + + /* check if we're seeking */ + + if (PrepareInitialSeek()) + /* during initial seek, no music chunk must be created + until seeking is finished; skip the rest of the + function here */ + return DecoderCommand::SEEK; + + /* send tag to music pipe */ + + if (stream_tag != nullptr) { + /* merge with tag from input stream */ + Tag *merged; + + merged = Tag::Merge(*stream_tag, *decoder_tag); + cmd = DoSendTag(*merged); + delete merged; + } else + /* send only the decoder tag */ + cmd = DoSendTag(*decoder_tag); + + return cmd; +} + +void +DecoderBridge::SubmitReplayGain(const ReplayGainInfo *new_replay_gain_info) +{ + if (new_replay_gain_info != nullptr) { + static unsigned serial; + if (++serial == 0) + serial = 1; + + if (ReplayGainMode::OFF != dc.replay_gain_mode) { + ReplayGainMode rgm = dc.replay_gain_mode; + if (rgm != ReplayGainMode::ALBUM) + rgm = ReplayGainMode::TRACK; + + const auto &tuple = new_replay_gain_info->Get(rgm); + const auto scale = + tuple.CalculateScale(dc.replay_gain_config); + dc.replay_gain_db = 20.0 * log10f(scale); + } + + replay_gain_info = *new_replay_gain_info; + replay_gain_serial = serial; + + if (current_chunk != nullptr) { + /* flush the current chunk because the new + replay gain values affect the following + samples */ + FlushChunk(); + } + } else + replay_gain_serial = 0; +} + +void +DecoderBridge::SubmitMixRamp(MixRampInfo &&mix_ramp) +{ + dc.SetMixRamp(std::move(mix_ramp)); +} diff -Nru mpd-0.19.21/src/decoder/Bridge.hxx mpd-0.20.9/src/decoder/Bridge.hxx --- mpd-0.19.21/src/decoder/Bridge.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/Bridge.hxx 2017-06-03 19:45:49.000000000 +0000 @@ -0,0 +1,176 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DECODER_BRIDGE_HXX +#define MPD_DECODER_BRIDGE_HXX + +#include "Client.hxx" +#include "ReplayGainInfo.hxx" + +#include + +class PcmConvert; +struct MusicChunk; +struct DecoderControl; +struct Tag; + +/** + * A bridge between the #DecoderClient interface and the MPD core + * (#DecoderControl, #MusicPipe etc.). + */ +class DecoderBridge final : public DecoderClient { +public: + DecoderControl &dc; + + /** + * For converting input data to the configured audio format. + * nullptr means no conversion necessary. + */ + PcmConvert *convert = nullptr; + + /** + * The time stamp of the next data chunk, in seconds. + */ + double timestamp = 0; + + /** + * Is the initial seek (to the start position of the sub-song) + * pending, or has it been performed already? + */ + bool initial_seek_pending; + + /** + * Is the initial seek currently running? During this time, + * the decoder command is SEEK. This flag is set by + * decoder_get_virtual_command(), when the virtual SEEK + * command is generated for the first time. + */ + bool initial_seek_running = false; + + /** + * This flag is set by GetSeekTime(), and checked by + * CommandFinished(). It is used to clean up after seeking. + */ + bool seeking = false; + + /** + * The tag from the song object. This is only used for local + * files, because we expect the stream server to send us a new + * tag each time we play it. + */ + Tag *song_tag; + + /** the last tag received from the stream */ + Tag *stream_tag = nullptr; + + /** the last tag received from the decoder plugin */ + Tag *decoder_tag = nullptr; + + /** the chunk currently being written to */ + MusicChunk *current_chunk = nullptr; + + ReplayGainInfo replay_gain_info; + + /** + * A positive serial number for checking if replay gain info + * has changed since the last check. + */ + unsigned replay_gain_serial = 0; + + /** + * An error has occurred (in DecoderAPI.cxx), and the plugin + * will be asked to stop. + */ + std::exception_ptr error; + + DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending, + Tag *_tag) + :dc(_dc), + initial_seek_pending(_initial_seek_pending), + song_tag(_tag) {} + + ~DecoderBridge(); + + /** + * Should be read operation be cancelled? That is the case when the + * player thread has sent a command such as "STOP". + * + * Caller must lock the #DecoderControl object. + */ + gcc_pure + bool CheckCancelRead() const noexcept; + + /** + * Returns the current chunk the decoder writes to, or allocates a new + * chunk if there is none. + * + * @return the chunk, or NULL if we have received a decoder command + */ + MusicChunk *GetChunk() noexcept; + + /** + * Flushes the current chunk. + * + * Caller must not lock the #DecoderControl object. + */ + void FlushChunk(); + + /* virtual methods from DecoderClient */ + void Ready(AudioFormat audio_format, + bool seekable, SignedSongTime duration) override; + DecoderCommand GetCommand() noexcept override; + void CommandFinished() override; + SongTime GetSeekTime() noexcept override; + uint64_t GetSeekFrame() noexcept override; + void SeekError() override; + InputStreamPtr OpenUri(const char *uri) override; + size_t Read(InputStream &is, void *buffer, size_t length) override; + void SubmitTimestamp(double t) override; + DecoderCommand SubmitData(InputStream *is, + const void *data, size_t length, + uint16_t kbit_rate) override; + DecoderCommand SubmitTag(InputStream *is, Tag &&tag) override ; + void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) override; + void SubmitMixRamp(MixRampInfo &&mix_ramp) override; + +private: + /** + * Checks if we need an "initial seek". If so, then the + * initial seek is prepared, and the function returns true. + */ + bool PrepareInitialSeek(); + + /** + * Returns the current decoder command. May return a + * "virtual" synthesized command, e.g. to seek to the + * beginning of the CUE track. + */ + DecoderCommand GetVirtualCommand() noexcept; + DecoderCommand LockGetVirtualCommand() noexcept; + + /** + * Sends a #Tag as-is to the #MusicPipe. Flushes the current + * chunk (DecoderBridge::chunk) if there is one. + */ + DecoderCommand DoSendTag(const Tag &tag); + + bool UpdateStreamTag(InputStream *is); +}; + +#endif diff -Nru mpd-0.19.21/src/decoder/Client.hxx mpd-0.20.9/src/decoder/Client.hxx --- mpd-0.19.21/src/decoder/Client.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/Client.hxx 2017-06-03 19:45:36.000000000 +0000 @@ -0,0 +1,171 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DECODER_CLIENT_HXX +#define MPD_DECODER_CLIENT_HXX + +#include "check.h" +#include "DecoderCommand.hxx" +#include "Chrono.hxx" +#include "input/Ptr.hxx" +#include "Compiler.h" + +#include + +struct AudioFormat; +struct Tag; +struct ReplayGainInfo; +class MixRampInfo; + +/** + * An interface between the decoder plugin and the MPD core. + */ +class DecoderClient { +public: + /** + * Notify the client that it has finished initialization and + * that it has read the song's meta data. + * + * @param audio_format the audio format which is going to be + * sent to SubmitData() + * @param seekable true if the song is seekable + * @param duration the total duration of this song; negative if + * unknown + */ + virtual void Ready(AudioFormat audio_format, + bool seekable, SignedSongTime duration) = 0; + + /** + * Determines the pending decoder command. + * + * @return the current command, or DecoderCommand::NONE if there is no + * command pending + */ + gcc_pure + virtual DecoderCommand GetCommand() noexcept = 0; + + /** + * Called by the decoder when it has performed the requested command + * (dc->command). This function resets dc->command and wakes up the + * player thread. + */ + virtual void CommandFinished() = 0; + + /** + * Call this when you have received the DecoderCommand::SEEK command. + * + * @return the destination position for the seek in milliseconds + */ + gcc_pure + virtual SongTime GetSeekTime() noexcept = 0; + + /** + * Call this when you have received the DecoderCommand::SEEK command. + * + * @return the destination position for the seek in frames + */ + gcc_pure + virtual uint64_t GetSeekFrame() noexcept = 0; + + /** + * Call this instead of CommandFinished() when seeking has + * failed. + */ + virtual void SeekError() = 0; + + /** + * Open a new #InputStream and wait until it's ready. + * + * Throws #StopDecoder if DecoderCommand::STOP was received. + * + * Throws std::runtime_error on error. + */ + virtual InputStreamPtr OpenUri(const char *uri) = 0; + + /** + * Blocking read from the input stream. + * + * @param is the input stream to read from + * @param buffer the destination buffer + * @param length the maximum number of bytes to read + * @return the number of bytes read, or 0 if one of the following + * occurs: end of file; error; command (like SEEK or STOP). + */ + virtual size_t Read(InputStream &is, void *buffer, size_t length) = 0; + + /** + * Sets the time stamp for the next data chunk [seconds]. The MPD + * core automatically counts it up, and a decoder plugin only needs to + * use this function if it thinks that adding to the time stamp based + * on the buffer size won't work. + */ + virtual void SubmitTimestamp(double t) = 0; + + /** + * This function is called by the decoder plugin when it has + * successfully decoded block of input data. + * + * @param is an input stream which is buffering while we are waiting + * for the player + * @param data the source buffer + * @param length the number of bytes in the buffer + * @return the current command, or DecoderCommand::NONE if there is no + * command pending + */ + virtual DecoderCommand SubmitData(InputStream *is, + const void *data, size_t length, + uint16_t kbit_rate) = 0; + + DecoderCommand SubmitData(InputStream &is, + const void *data, size_t length, + uint16_t kbit_rate) { + return SubmitData(&is, data, length, kbit_rate); + } + + /** + * This function is called by the decoder plugin when it has + * successfully decoded a tag. + * + * @param is an input stream which is buffering while we are waiting + * for the player + * @param tag the tag to send + * @return the current command, or DecoderCommand::NONE if there is no + * command pending + */ + virtual DecoderCommand SubmitTag(InputStream *is, Tag &&tag) = 0 ; + + DecoderCommand SubmitTag(InputStream &is, Tag &&tag) { + return SubmitTag(&is, std::move(tag)); + } + + /** + * Set replay gain values for the following chunks. + * + * @param replay_gain_info the replay_gain_info object; may be nullptr + * to invalidate the previous replay gain values + */ + virtual void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) = 0; + + /** + * Store MixRamp tags. + */ + virtual void SubmitMixRamp(MixRampInfo &&mix_ramp) = 0; +}; + +#endif diff -Nru mpd-0.19.21/src/decoder/DecoderAPI.cxx mpd-0.20.9/src/decoder/DecoderAPI.cxx --- mpd-0.19.21/src/decoder/DecoderAPI.cxx 2016-11-17 21:15:59.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderAPI.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,345 +19,38 @@ #include "config.h" #include "DecoderAPI.hxx" -#include "DecoderError.hxx" -#include "pcm/PcmConvert.hxx" -#include "AudioConfig.hxx" -#include "ReplayGainConfig.hxx" -#include "MusicChunk.hxx" -#include "MusicBuffer.hxx" -#include "MusicPipe.hxx" -#include "DecoderControl.hxx" -#include "DecoderInternal.hxx" -#include "DetachedSong.hxx" #include "input/InputStream.hxx" -#include "util/Error.hxx" -#include "util/ConstBuffer.hxx" #include "Log.hxx" #include -#include -#include - -void -decoder_initialized(Decoder &decoder, - const AudioFormat audio_format, - bool seekable, SignedSongTime duration) -{ - DecoderControl &dc = decoder.dc; - struct audio_format_string af_string; - - assert(dc.state == DecoderState::START); - assert(dc.pipe != nullptr); - assert(dc.pipe->IsEmpty()); - assert(decoder.convert == nullptr); - assert(decoder.stream_tag == nullptr); - assert(decoder.decoder_tag == nullptr); - assert(!decoder.seeking); - assert(audio_format.IsDefined()); - assert(audio_format.IsValid()); - - dc.in_audio_format = audio_format; - dc.out_audio_format = getOutputAudioFormat(audio_format); - - dc.seekable = seekable; - dc.total_time = duration; - - FormatDebug(decoder_domain, "audio_format=%s, seekable=%s", - audio_format_to_string(dc.in_audio_format, &af_string), - seekable ? "true" : "false"); - - if (dc.in_audio_format != dc.out_audio_format) { - FormatDebug(decoder_domain, "converting to %s", - audio_format_to_string(dc.out_audio_format, - &af_string)); - - decoder.convert = new PcmConvert(); - - Error error; - if (!decoder.convert->Open(dc.in_audio_format, - dc.out_audio_format, - error)) - decoder.error = std::move(error); - } - - dc.Lock(); - dc.state = DecoderState::DECODE; - dc.client_cond.signal(); - dc.Unlock(); -} - -/** - * Checks if we need an "initial seek". If so, then the initial seek - * is prepared, and the function returns true. - */ -gcc_pure -static bool -decoder_prepare_initial_seek(Decoder &decoder) -{ - const DecoderControl &dc = decoder.dc; - assert(dc.pipe != nullptr); - - if (dc.state != DecoderState::DECODE) - /* wait until the decoder has finished initialisation - (reading file headers etc.) before emitting the - virtual "SEEK" command */ - return false; - - if (decoder.initial_seek_running) - /* initial seek has already begun - override any other - command */ - return true; - - if (decoder.initial_seek_pending) { - if (!dc.seekable) { - /* seeking is not possible */ - decoder.initial_seek_pending = false; - return false; - } - - if (dc.command == DecoderCommand::NONE) { - /* begin initial seek */ - - decoder.initial_seek_pending = false; - decoder.initial_seek_running = true; - return true; - } - - /* skip initial seek when there's another command - (e.g. STOP) */ - - decoder.initial_seek_pending = false; - } - - return false; -} - -/** - * Returns the current decoder command. May return a "virtual" - * synthesized command, e.g. to seek to the beginning of the CUE - * track. - */ -gcc_pure -static DecoderCommand -decoder_get_virtual_command(Decoder &decoder) -{ - if (decoder.error.IsDefined()) - /* an error has occurred: stop the decoder plugin */ - return DecoderCommand::STOP; - - const DecoderControl &dc = decoder.dc; - assert(dc.pipe != nullptr); - - if (decoder_prepare_initial_seek(decoder)) - return DecoderCommand::SEEK; - - return dc.command; -} - -DecoderCommand -decoder_get_command(Decoder &decoder) -{ - return decoder_get_virtual_command(decoder); -} - -void -decoder_command_finished(Decoder &decoder) -{ - DecoderControl &dc = decoder.dc; - - dc.Lock(); - - assert(dc.command != DecoderCommand::NONE || - decoder.initial_seek_running); - assert(dc.command != DecoderCommand::SEEK || - decoder.initial_seek_running || - dc.seek_error || decoder.seeking); - assert(dc.pipe != nullptr); - - if (decoder.initial_seek_running) { - assert(!decoder.seeking); - assert(decoder.chunk == nullptr); - assert(dc.pipe->IsEmpty()); - - decoder.initial_seek_running = false; - decoder.timestamp = dc.start_time.ToDoubleS(); - dc.Unlock(); - return; - } - - if (decoder.seeking) { - decoder.seeking = false; - - /* delete frames from the old song position */ - - if (decoder.chunk != nullptr) { - dc.buffer->Return(decoder.chunk); - decoder.chunk = nullptr; - } - - dc.pipe->Clear(*dc.buffer); - - decoder.timestamp = dc.seek_time.ToDoubleS(); - } - - dc.command = DecoderCommand::NONE; - dc.client_cond.signal(); - dc.Unlock(); -} - -SongTime -decoder_seek_time(Decoder &decoder) -{ - const DecoderControl &dc = decoder.dc; - - assert(dc.pipe != nullptr); - - if (decoder.initial_seek_running) - return dc.start_time; - - assert(dc.command == DecoderCommand::SEEK); - - decoder.seeking = true; - - return dc.seek_time; -} - -uint64_t -decoder_seek_where_frame(Decoder &decoder) -{ - const DecoderControl &dc = decoder.dc; - - return decoder_seek_time(decoder).ToScale(dc.in_audio_format.sample_rate); -} - -void decoder_seek_error(Decoder & decoder) -{ - DecoderControl &dc = decoder.dc; - - assert(dc.pipe != nullptr); - - if (decoder.initial_seek_running) { - /* d'oh, we can't seek to the sub-song start position, - what now? - no idea, ignoring the problem for now. */ - decoder.initial_seek_running = false; - return; - } - - assert(dc.command == DecoderCommand::SEEK); - - dc.seek_error = true; - decoder.seeking = false; - - decoder_command_finished(decoder); -} - -InputStream * -decoder_open_uri(Decoder &decoder, const char *uri, Error &error) -{ - assert(decoder.dc.state == DecoderState::START || - decoder.dc.state == DecoderState::DECODE); - - DecoderControl &dc = decoder.dc; - Mutex &mutex = dc.mutex; - Cond &cond = dc.cond; - - InputStream *is = InputStream::Open(uri, mutex, cond, error); - if (is == nullptr) - return nullptr; - - mutex.lock(); - while (true) { - is->Update(); - if (is->IsReady()) { - mutex.unlock(); - return is; - } - - if (dc.command == DecoderCommand::STOP) { - mutex.unlock(); - delete is; - return nullptr; - } - - cond.wait(mutex); - } -} - -/** - * Should be read operation be cancelled? That is the case when the - * player thread has sent a command such as "STOP". - */ -gcc_pure -static inline bool -decoder_check_cancel_read(const Decoder *decoder) -{ - if (decoder == nullptr) - return false; - - const DecoderControl &dc = decoder->dc; - if (dc.command == DecoderCommand::NONE) - return false; - - /* ignore the SEEK command during initialization, the plugin - should handle that after it has initialized successfully */ - if (dc.command == DecoderCommand::SEEK && - (dc.state == DecoderState::START || decoder->seeking || - decoder->initial_seek_running)) - return false; - - return true; -} size_t -decoder_read(Decoder *decoder, +decoder_read(DecoderClient *client, InputStream &is, void *buffer, size_t length) { - /* XXX don't allow decoder==nullptr */ - - assert(decoder == nullptr || - decoder->dc.state == DecoderState::START || - decoder->dc.state == DecoderState::DECODE); assert(buffer != nullptr); - if (length == 0) + /* XXX don't allow client==nullptr */ + if (client != nullptr) + return client->Read(is, buffer, length); + + try { + return is.LockRead(buffer, length); + } catch (const std::runtime_error &e) { + LogError(e); return 0; - - is.Lock(); - - while (true) { - if (decoder_check_cancel_read(decoder)) { - is.Unlock(); - return 0; - } - - if (is.IsAvailable()) - break; - - is.cond.wait(is.mutex); } - - Error error; - size_t nbytes = is.Read(buffer, length, error); - assert(nbytes == 0 || !error.IsDefined()); - assert(nbytes > 0 || error.IsDefined() || is.IsEOF()); - - is.Unlock(); - - if (gcc_unlikely(nbytes == 0 && error.IsDefined())) - LogError(error); - - return nbytes; } bool -decoder_read_full(Decoder *decoder, InputStream &is, +decoder_read_full(DecoderClient *client, InputStream &is, void *_buffer, size_t size) { uint8_t *buffer = (uint8_t *)_buffer; while (size > 0) { - size_t nbytes = decoder_read(decoder, is, buffer, size); + size_t nbytes = decoder_read(client, is, buffer, size); if (nbytes == 0) return false; @@ -369,11 +62,11 @@ } bool -decoder_skip(Decoder *decoder, InputStream &is, size_t size) +decoder_skip(DecoderClient *client, InputStream &is, size_t size) { while (size > 0) { char buffer[1024]; - size_t nbytes = decoder_read(decoder, is, buffer, + size_t nbytes = decoder_read(client, is, buffer, std::min(sizeof(buffer), size)); if (nbytes == 0) return false; @@ -383,263 +76,3 @@ return true; } - -void -decoder_timestamp(Decoder &decoder, double t) -{ - assert(t >= 0); - - decoder.timestamp = t; -} - -/** - * Sends a #tag as-is to the music pipe. Flushes the current chunk - * (decoder.chunk) if there is one. - */ -static DecoderCommand -do_send_tag(Decoder &decoder, const Tag &tag) -{ - MusicChunk *chunk; - - if (decoder.chunk != nullptr) { - /* there is a partial chunk - flush it, we want the - tag in a new chunk */ - decoder.FlushChunk(); - } - - assert(decoder.chunk == nullptr); - - chunk = decoder.GetChunk(); - if (chunk == nullptr) { - assert(decoder.dc.command != DecoderCommand::NONE); - return decoder.dc.command; - } - - chunk->tag = new Tag(tag); - return DecoderCommand::NONE; -} - -static bool -update_stream_tag(Decoder &decoder, InputStream *is) -{ - Tag *tag; - - tag = is != nullptr - ? is->LockReadTag() - : nullptr; - if (tag == nullptr) { - tag = decoder.song_tag; - if (tag == nullptr) - return false; - - /* no stream tag present - submit the song tag - instead */ - } else - /* discard the song tag; we don't need it */ - delete decoder.song_tag; - - decoder.song_tag = nullptr; - - delete decoder.stream_tag; - decoder.stream_tag = tag; - return true; -} - -DecoderCommand -decoder_data(Decoder &decoder, - InputStream *is, - const void *data, size_t length, - uint16_t kbit_rate) -{ - DecoderControl &dc = decoder.dc; - DecoderCommand cmd; - - assert(dc.state == DecoderState::DECODE); - assert(dc.pipe != nullptr); - assert(length % dc.in_audio_format.GetFrameSize() == 0); - - dc.Lock(); - cmd = decoder_get_virtual_command(decoder); - dc.Unlock(); - - if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK || - length == 0) - return cmd; - - assert(!decoder.initial_seek_pending); - assert(!decoder.initial_seek_running); - - /* send stream tags */ - - if (update_stream_tag(decoder, is)) { - if (decoder.decoder_tag != nullptr) { - /* merge with tag from decoder plugin */ - Tag *tag = Tag::Merge(*decoder.decoder_tag, - *decoder.stream_tag); - cmd = do_send_tag(decoder, *tag); - delete tag; - } else - /* send only the stream tag */ - cmd = do_send_tag(decoder, *decoder.stream_tag); - - if (cmd != DecoderCommand::NONE) - return cmd; - } - - if (decoder.convert != nullptr) { - assert(dc.in_audio_format != dc.out_audio_format); - - Error error; - auto result = decoder.convert->Convert({data, length}, - error); - if (data == nullptr) { - /* the PCM conversion has failed - stop - playback, since we have no better way to - bail out */ - LogError(error); - return DecoderCommand::STOP; - } - - data = result.data; - length = result.size; - } else { - assert(dc.in_audio_format == dc.out_audio_format); - } - - while (length > 0) { - MusicChunk *chunk; - bool full; - - chunk = decoder.GetChunk(); - if (chunk == nullptr) { - assert(dc.command != DecoderCommand::NONE); - return dc.command; - } - - const auto dest = - chunk->Write(dc.out_audio_format, - SongTime::FromS(decoder.timestamp) - - dc.song->GetStartTime(), - kbit_rate); - if (dest.IsEmpty()) { - /* the chunk is full, flush it */ - decoder.FlushChunk(); - continue; - } - - const size_t nbytes = std::min(dest.size, length); - - /* copy the buffer */ - - memcpy(dest.data, data, nbytes); - - /* expand the music pipe chunk */ - - full = chunk->Expand(dc.out_audio_format, nbytes); - if (full) { - /* the chunk is full, flush it */ - decoder.FlushChunk(); - } - - data = (const uint8_t *)data + nbytes; - length -= nbytes; - - decoder.timestamp += (double)nbytes / - dc.out_audio_format.GetTimeToSize(); - - if (dc.end_time.IsPositive() && - decoder.timestamp >= dc.end_time.ToDoubleS()) - /* the end of this range has been reached: - stop decoding */ - return DecoderCommand::STOP; - } - - return DecoderCommand::NONE; -} - -DecoderCommand -decoder_tag(Decoder &decoder, InputStream *is, - Tag &&tag) -{ - gcc_unused const DecoderControl &dc = decoder.dc; - DecoderCommand cmd; - - assert(dc.state == DecoderState::DECODE); - assert(dc.pipe != nullptr); - - /* save the tag */ - - delete decoder.decoder_tag; - decoder.decoder_tag = new Tag(std::move(tag)); - - /* check for a new stream tag */ - - update_stream_tag(decoder, is); - - /* check if we're seeking */ - - if (decoder_prepare_initial_seek(decoder)) - /* during initial seek, no music chunk must be created - until seeking is finished; skip the rest of the - function here */ - return DecoderCommand::SEEK; - - /* send tag to music pipe */ - - if (decoder.stream_tag != nullptr) { - /* merge with tag from input stream */ - Tag *merged; - - merged = Tag::Merge(*decoder.stream_tag, - *decoder.decoder_tag); - cmd = do_send_tag(decoder, *merged); - delete merged; - } else - /* send only the decoder tag */ - cmd = do_send_tag(decoder, *decoder.decoder_tag); - - return cmd; -} - -void -decoder_replay_gain(Decoder &decoder, - const ReplayGainInfo *replay_gain_info) -{ - if (replay_gain_info != nullptr) { - static unsigned serial; - if (++serial == 0) - serial = 1; - - if (REPLAY_GAIN_OFF != replay_gain_mode) { - ReplayGainMode rgm = replay_gain_mode; - if (rgm != REPLAY_GAIN_ALBUM) - rgm = REPLAY_GAIN_TRACK; - - const auto &tuple = replay_gain_info->tuples[rgm]; - const auto scale = - tuple.CalculateScale(replay_gain_preamp, - replay_gain_missing_preamp, - replay_gain_limit); - decoder.dc.replay_gain_db = 20.0 * log10f(scale); - } - - decoder.replay_gain_info = *replay_gain_info; - decoder.replay_gain_serial = serial; - - if (decoder.chunk != nullptr) { - /* flush the current chunk because the new - replay gain values affect the following - samples */ - decoder.FlushChunk(); - } - } else - decoder.replay_gain_serial = 0; -} - -void -decoder_mixramp(Decoder &decoder, MixRampInfo &&mix_ramp) -{ - DecoderControl &dc = decoder.dc; - - dc.SetMixRamp(std::move(mix_ramp)); -} diff -Nru mpd-0.19.21/src/decoder/DecoderAPI.hxx mpd-0.20.9/src/decoder/DecoderAPI.hxx --- mpd-0.19.21/src/decoder/DecoderAPI.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderAPI.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -30,94 +30,29 @@ // IWYU pragma: begin_exports #include "check.h" +#include "Client.hxx" +#include "input/Ptr.hxx" #include "DecoderCommand.hxx" #include "DecoderPlugin.hxx" #include "ReplayGainInfo.hxx" #include "tag/Tag.hxx" #include "AudioFormat.hxx" #include "MixRampInfo.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "Chrono.hxx" // IWYU pragma: end_exports #include -class Error; +class DecoderClient; /** - * Notify the player thread that it has finished initialization and - * that it has read the song's meta data. - * - * @param decoder the decoder object - * @param audio_format the audio format which is going to be sent to - * decoder_data() - * @param seekable true if the song is seekable - * @param duration the total duration of this song; negative if - * unknown - */ -void -decoder_initialized(Decoder &decoder, - AudioFormat audio_format, - bool seekable, SignedSongTime duration); - -/** - * Determines the pending decoder command. - * - * @param decoder the decoder object - * @return the current command, or DecoderCommand::NONE if there is no - * command pending - */ -gcc_pure -DecoderCommand -decoder_get_command(Decoder &decoder); - -/** - * Called by the decoder when it has performed the requested command - * (dc->command). This function resets dc->command and wakes up the - * player thread. - * - * @param decoder the decoder object - */ -void -decoder_command_finished(Decoder &decoder); - -/** - * Call this when you have received the DecoderCommand::SEEK command. - * - * @param decoder the decoder object - * @return the destination position for the seek in milliseconds - */ -gcc_pure -SongTime -decoder_seek_time(Decoder &decoder); - -/** - * Call this when you have received the DecoderCommand::SEEK command. - * - * @param decoder the decoder object - * @return the destination position for the seek in frames - */ -gcc_pure -uint64_t -decoder_seek_where_frame(Decoder &decoder); - -/** - * Call this instead of decoder_command_finished() when seeking has - * failed. - * - * @param decoder the decoder object - */ -void -decoder_seek_error(Decoder &decoder); - -/** - * Open a new #InputStream and wait until it's ready. Can get - * cancelled by DecoderCommand::STOP (returns nullptr without setting - * #Error). + * Throw an instance of this class to stop decoding the current song + * (successfully). It can be used to jump out of all of a decoder's + * stack frames. */ -InputStream * -decoder_open_uri(Decoder &decoder, const char *uri, Error &error); +class StopDecoder {}; /** * Blocking read from the input stream. @@ -130,11 +65,11 @@ * occurs: end of file; error; command (like SEEK or STOP). */ size_t -decoder_read(Decoder *decoder, InputStream &is, +decoder_read(DecoderClient *decoder, InputStream &is, void *buffer, size_t length); static inline size_t -decoder_read(Decoder &decoder, InputStream &is, +decoder_read(DecoderClient &decoder, InputStream &is, void *buffer, size_t length) { return decoder_read(&decoder, is, buffer, length); @@ -148,7 +83,7 @@ * data */ bool -decoder_read_full(Decoder *decoder, InputStream &is, +decoder_read_full(DecoderClient *decoder, InputStream &is, void *buffer, size_t size); /** @@ -157,81 +92,6 @@ * @return true on success, false on error or command */ bool -decoder_skip(Decoder *decoder, InputStream &is, size_t size); - -/** - * Sets the time stamp for the next data chunk [seconds]. The MPD - * core automatically counts it up, and a decoder plugin only needs to - * use this function if it thinks that adding to the time stamp based - * on the buffer size won't work. - */ -void -decoder_timestamp(Decoder &decoder, double t); - -/** - * This function is called by the decoder plugin when it has - * successfully decoded block of input data. - * - * @param decoder the decoder object - * @param is an input stream which is buffering while we are waiting - * for the player - * @param data the source buffer - * @param length the number of bytes in the buffer - * @return the current command, or DecoderCommand::NONE if there is no - * command pending - */ -DecoderCommand -decoder_data(Decoder &decoder, InputStream *is, - const void *data, size_t length, - uint16_t kbit_rate); - -static inline DecoderCommand -decoder_data(Decoder &decoder, InputStream &is, - const void *data, size_t length, - uint16_t kbit_rate) -{ - return decoder_data(decoder, &is, data, length, kbit_rate); -} - -/** - * This function is called by the decoder plugin when it has - * successfully decoded a tag. - * - * @param decoder the decoder object - * @param is an input stream which is buffering while we are waiting - * for the player - * @param tag the tag to send - * @return the current command, or DecoderCommand::NONE if there is no - * command pending - */ -DecoderCommand -decoder_tag(Decoder &decoder, InputStream *is, Tag &&tag); - -static inline DecoderCommand -decoder_tag(Decoder &decoder, InputStream &is, Tag &&tag) -{ - return decoder_tag(decoder, &is, std::move(tag)); -} - -/** - * Set replay gain values for the following chunks. - * - * @param decoder the decoder object - * @param rgi the replay_gain_info object; may be nullptr to invalidate - * the previous replay gain values - */ -void -decoder_replay_gain(Decoder &decoder, - const ReplayGainInfo *replay_gain_info); - -/** - * Store MixRamp tags. - * - * @param decoder the decoder object - * @param mixramp_start the mixramp_start tag; may be nullptr to invalidate - * @param mixramp_end the mixramp_end tag; may be nullptr to invalidate - */ -void -decoder_mixramp(Decoder &decoder, MixRampInfo &&mix_ramp); +decoder_skip(DecoderClient *decoder, InputStream &is, size_t size); #endif diff -Nru mpd-0.19.21/src/decoder/DecoderBuffer.cxx mpd-0.20.9/src/decoder/DecoderBuffer.cxx --- mpd-0.19.21/src/decoder/DecoderBuffer.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderBuffer.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,8 +21,6 @@ #include "DecoderBuffer.hxx" #include "DecoderAPI.hxx" -#include - bool DecoderBuffer::Fill() { @@ -31,7 +29,7 @@ /* buffer is full */ return false; - size_t nbytes = decoder_read(decoder, is, + size_t nbytes = decoder_read(client, is, w.data, w.size); if (nbytes == 0) /* end of file, I/O error or decoder command @@ -67,5 +65,5 @@ buffer.Clear(); nbytes -= r.size; - return decoder_skip(decoder, is, nbytes); + return decoder_skip(client, is, nbytes); } diff -Nru mpd-0.19.21/src/decoder/DecoderBuffer.hxx mpd-0.20.9/src/decoder/DecoderBuffer.hxx --- mpd-0.19.21/src/decoder/DecoderBuffer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderBuffer.hxx 2017-06-04 10:35:27.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ #include #include -struct Decoder; +class DecoderClient; class InputStream; /** @@ -36,7 +36,7 @@ * read it. It will automatically handle shifting the buffer. */ class DecoderBuffer { - Decoder *const decoder; + DecoderClient *const client; InputStream &is; DynamicFifoBuffer buffer; @@ -45,20 +45,20 @@ /** * Creates a new buffer. * - * @param _decoder the decoder object, used for decoder_read(), + * @param _client the decoder client, used for decoder_read(), * may be nullptr * @param _is the input stream object where we should read from * @param _size the maximum size of the buffer */ - DecoderBuffer(Decoder *_decoder, InputStream &_is, + DecoderBuffer(DecoderClient *_client, InputStream &_is, size_t _size) - :decoder(_decoder), is(_is), buffer(_size) {} + :client(_client), is(_is), buffer(_size) {} - const InputStream &GetStream() const { + const InputStream &GetStream() const noexcept { return is; } - void Clear() { + void Clear() noexcept { buffer.Clear(); } @@ -75,7 +75,7 @@ * How many bytes are stored in the buffer? */ gcc_pure - size_t GetAvailable() const { + size_t GetAvailable() const noexcept { return buffer.GetAvailable(); } @@ -84,7 +84,7 @@ * you have to call Consume() to do that. The returned buffer * becomes invalid after a Fill() or a Consume() call. */ - ConstBuffer Read() const { + ConstBuffer Read() const noexcept { auto r = buffer.Read(); return { r.data, r.size }; } @@ -102,7 +102,7 @@ * * @param nbytes the number of bytes to consume */ - void Consume(size_t nbytes) { + void Consume(size_t nbytes) noexcept { buffer.Consume(nbytes); } diff -Nru mpd-0.19.21/src/decoder/DecoderCommand.hxx mpd-0.20.9/src/decoder/DecoderCommand.hxx --- mpd-0.19.21/src/decoder/DecoderCommand.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderCommand.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/DecoderControl.cxx mpd-0.20.9/src/decoder/DecoderControl.cxx --- mpd-0.19.21/src/decoder/DecoderControl.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderControl.cxx 2017-05-08 13:16:38.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,18 +19,20 @@ #include "config.h" #include "DecoderControl.hxx" +#include "DecoderError.hxx" #include "MusicPipe.hxx" #include "DetachedSong.hxx" +#include + #include -DecoderControl::DecoderControl(Mutex &_mutex, Cond &_client_cond) +DecoderControl::DecoderControl(Mutex &_mutex, Cond &_client_cond, + const AudioFormat _configured_audio_format, + const ReplayGainConfig &_replay_gain_config) :mutex(_mutex), client_cond(_client_cond), - state(DecoderState::STOP), - command(DecoderCommand::NONE), - client_is_waiting(false), - song(nullptr), - replay_gain_db(0), replay_gain_prev_db(0) {} + configured_audio_format(_configured_audio_format), + replay_gain_config(_replay_gain_config) {} DecoderControl::~DecoderControl() { @@ -51,8 +53,28 @@ client_is_waiting = false; } +void +DecoderControl::SetReady(const AudioFormat audio_format, + bool _seekable, SignedSongTime _duration) +{ + assert(state == DecoderState::START); + assert(pipe != nullptr); + assert(pipe->IsEmpty()); + assert(audio_format.IsDefined()); + assert(audio_format.IsValid()); + + in_audio_format = audio_format; + out_audio_format = audio_format.WithMask(configured_audio_format); + + seekable = _seekable; + total_time = _duration; + + state = DecoderState::DECODE; + client_cond.signal(); +} + bool -DecoderControl::IsCurrentSong(const DetachedSong &_song) const +DecoderControl::IsCurrentSong(const DetachedSong &_song) const noexcept { switch (state) { case DecoderState::STOP: @@ -89,7 +111,7 @@ void DecoderControl::Stop() { - Lock(); + const std::lock_guard protect(mutex); if (command != DecoderCommand::NONE) /* Attempt to cancel the current command. If it's too @@ -100,24 +122,37 @@ if (state != DecoderState::STOP && state != DecoderState::ERROR) SynchronousCommandLocked(DecoderCommand::STOP); - - Unlock(); } -bool +void DecoderControl::Seek(SongTime t) { assert(state != DecoderState::START); + assert(state != DecoderState::ERROR); - if (state == DecoderState::STOP || - state == DecoderState::ERROR || !seekable) - return false; + switch (state) { + case DecoderState::START: + case DecoderState::ERROR: + gcc_unreachable(); + + case DecoderState::STOP: + /* TODO: if this happens, the caller should be given a + chance to restart the decoder */ + throw std::runtime_error("Decoder is dead"); + + case DecoderState::DECODE: + break; + } + + if (!seekable) + throw std::runtime_error("Not seekable"); seek_time = t; seek_error = false; LockSynchronousCommand(DecoderCommand::SEEK); - return !seek_error; + if (seek_error) + throw std::runtime_error("Decoder failed to seek"); } void diff -Nru mpd-0.19.21/src/decoder/DecoderControl.hxx mpd-0.20.9/src/decoder/DecoderControl.hxx --- mpd-0.19.21/src/decoder/DecoderControl.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderControl.hxx 2017-06-03 19:43:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,12 @@ #include "thread/Cond.hxx" #include "thread/Thread.hxx" #include "Chrono.hxx" -#include "util/Error.hxx" +#include "ReplayGainConfig.hxx" +#include "ReplayGainMode.hxx" + +#include + +#include #include #include @@ -86,8 +91,8 @@ */ Cond &client_cond; - DecoderState state; - DecoderCommand command; + DecoderState state = DecoderState::STOP; + DecoderCommand command = DecoderCommand::NONE; /** * The error that occurred in the decoder thread. This @@ -95,7 +100,7 @@ * The object must be freed when this object transitions to * any other state (usually #DecoderState::START). */ - Error error; + std::exception_ptr error; bool quit; @@ -104,12 +109,17 @@ * false, the DecoderThread may omit invoking Cond::signal(), * reducing the number of system calls. */ - bool client_is_waiting; + bool client_is_waiting = false; bool seek_error; bool seekable; SongTime seek_time; + /** + * The "audio_output_format" setting. + */ + const AudioFormat configured_audio_format; + /** the format of the song file */ AudioFormat in_audio_format; @@ -124,7 +134,7 @@ * This is a duplicate, and must be freed when this attribute * is cleared. */ - DetachedSong *song; + DetachedSong *song = nullptr; /** * The initial seek position, e.g. to the start of a sub-track @@ -153,8 +163,11 @@ */ MusicPipe *pipe; - float replay_gain_db; - float replay_gain_prev_db; + const ReplayGainConfig replay_gain_config; + ReplayGainMode replay_gain_mode = ReplayGainMode::OFF; + + float replay_gain_db = 0; + float replay_gain_prev_db = 0; MixRampInfo mix_ramp, previous_mix_ramp; @@ -162,7 +175,9 @@ * @param _mutex see #mutex * @param _client_cond see #client_cond */ - DecoderControl(Mutex &_mutex, Cond &_client_cond); + DecoderControl(Mutex &_mutex, Cond &_client_cond, + const AudioFormat _configured_audio_format, + const ReplayGainConfig &_replay_gain_config); ~DecoderControl(); /** @@ -212,65 +227,62 @@ } gcc_pure - bool LockIsIdle() const { - Lock(); - bool result = IsIdle(); - Unlock(); - return result; + bool LockIsIdle() const noexcept { + const std::lock_guard protect(mutex); + return IsIdle(); } - bool IsStarting() const { + bool IsStarting() const noexcept { return state == DecoderState::START; } gcc_pure - bool LockIsStarting() const { - Lock(); - bool result = IsStarting(); - Unlock(); - return result; + bool LockIsStarting() const noexcept { + const std::lock_guard protect(mutex); + return IsStarting(); } - bool HasFailed() const { + bool HasFailed() const noexcept { assert(command == DecoderCommand::NONE); return state == DecoderState::ERROR; } gcc_pure - bool LockHasFailed() const { - Lock(); - bool result = HasFailed(); - Unlock(); - return result; + bool LockHasFailed() const noexcept { + const std::lock_guard protect(mutex); + return HasFailed(); } /** - * Checks whether an error has occurred, and if so, returns a - * copy of the #Error object. + * Transition this obejct from DecoderState::START to + * DecoderState::DECODE. * * Caller must lock the object. */ - gcc_pure - Error GetError() const { + void SetReady(const AudioFormat audio_format, + bool _seekable, SignedSongTime _duration); + + /** + * Checks whether an error has occurred, and if so, rethrows + * it. + * + * Caller must lock the object. + */ + void CheckRethrowError() const { assert(command == DecoderCommand::NONE); - assert(state != DecoderState::ERROR || error.IsDefined()); + assert(state != DecoderState::ERROR || error); - Error result; if (state == DecoderState::ERROR) - result.Set(error); - return result; + std::rethrow_exception(error); } /** - * Like GetError(), but locks and unlocks the object. + * Like CheckRethrowError(), but locks and unlocks the object. */ - gcc_pure - Error LockGetError() const { - Lock(); - Error result = GetError(); - Unlock(); - return result; + void LockCheckRethrowError() const { + const std::lock_guard protect(mutex); + CheckRethrowError(); } /** @@ -280,7 +292,7 @@ */ void ClearError() { if (state == DecoderState::ERROR) { - error.Clear(); + error = std::exception_ptr(); state = DecoderState::STOP; } } @@ -293,14 +305,12 @@ * Caller must lock the object. */ gcc_pure - bool IsCurrentSong(const DetachedSong &_song) const; + bool IsCurrentSong(const DetachedSong &_song) const noexcept; gcc_pure - bool LockIsCurrentSong(const DetachedSong &_song) const { - Lock(); - const bool result = IsCurrentSong(_song); - Unlock(); - return result; + bool LockIsCurrentSong(const DetachedSong &_song) const noexcept { + const std::lock_guard protect(mutex); + return IsCurrentSong(_song); } private: @@ -336,21 +346,33 @@ * object. */ void LockSynchronousCommand(DecoderCommand cmd) { - Lock(); + const std::lock_guard protect(mutex); ClearError(); SynchronousCommandLocked(cmd); - Unlock(); } void LockAsynchronousCommand(DecoderCommand cmd) { - Lock(); + const std::lock_guard protect(mutex); command = cmd; Signal(); - Unlock(); } public: /** + * Marks the current command as "finished" and notifies the + * client (= player thread). + * + * To be called from the decoder thread. Caller must lock the + * mutex. + */ + void CommandFinishedLocked() { + assert(command != DecoderCommand::NONE); + + command = DecoderCommand::NONE; + client_cond.signal(); + } + + /** * Start the decoder. * * @param song the song to be decoded; the given instance will be @@ -365,7 +387,10 @@ void Stop(); - bool Seek(SongTime t); + /** + * Throws #std::runtime_error on error. + */ + void Seek(SongTime t); void Quit(); diff -Nru mpd-0.19.21/src/decoder/DecoderError.cxx mpd-0.20.9/src/decoder/DecoderError.cxx --- mpd-0.19.21/src/decoder/DecoderError.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderError.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/DecoderError.hxx mpd-0.20.9/src/decoder/DecoderError.hxx --- mpd-0.19.21/src/decoder/DecoderError.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/DecoderInternal.cxx mpd-0.20.9/src/decoder/DecoderInternal.cxx --- mpd-0.19.21/src/decoder/DecoderInternal.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderInternal.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "DecoderInternal.hxx" -#include "DecoderControl.hxx" -#include "pcm/PcmConvert.hxx" -#include "MusicPipe.hxx" -#include "MusicBuffer.hxx" -#include "MusicChunk.hxx" -#include "tag/Tag.hxx" - -#include - -Decoder::~Decoder() -{ - /* caller must flush the chunk */ - assert(chunk == nullptr); - - if (convert != nullptr) { - convert->Close(); - delete convert; - } - - delete song_tag; - delete stream_tag; - delete decoder_tag; -} - -/** - * All chunks are full of decoded data; wait for the player to free - * one. - */ -static DecoderCommand -need_chunks(DecoderControl &dc) -{ - if (dc.command == DecoderCommand::NONE) - dc.Wait(); - - return dc.command; -} - -MusicChunk * -Decoder::GetChunk() -{ - DecoderCommand cmd; - - if (chunk != nullptr) - return chunk; - - do { - chunk = dc.buffer->Allocate(); - if (chunk != nullptr) { - chunk->replay_gain_serial = replay_gain_serial; - if (replay_gain_serial != 0) - chunk->replay_gain_info = replay_gain_info; - - return chunk; - } - - dc.Lock(); - cmd = need_chunks(dc); - dc.Unlock(); - } while (cmd == DecoderCommand::NONE); - - return nullptr; -} - -void -Decoder::FlushChunk() -{ - assert(!seeking); - assert(!initial_seek_running); - assert(!initial_seek_pending); - assert(chunk != nullptr); - - if (chunk->IsEmpty()) - dc.buffer->Return(chunk); - else - dc.pipe->Push(chunk); - - chunk = nullptr; - - dc.Lock(); - if (dc.client_is_waiting) - dc.client_cond.signal(); - dc.Unlock(); -} diff -Nru mpd-0.19.21/src/decoder/DecoderInternal.hxx mpd-0.20.9/src/decoder/DecoderInternal.hxx --- mpd-0.19.21/src/decoder/DecoderInternal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderInternal.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_DECODER_INTERNAL_HXX -#define MPD_DECODER_INTERNAL_HXX - -#include "ReplayGainInfo.hxx" -#include "util/Error.hxx" - -class PcmConvert; -struct MusicChunk; -struct DecoderControl; -struct Tag; - -struct Decoder { - DecoderControl &dc; - - /** - * For converting input data to the configured audio format. - * nullptr means no conversion necessary. - */ - PcmConvert *convert; - - /** - * The time stamp of the next data chunk, in seconds. - */ - double timestamp; - - /** - * Is the initial seek (to the start position of the sub-song) - * pending, or has it been performed already? - */ - bool initial_seek_pending; - - /** - * Is the initial seek currently running? During this time, - * the decoder command is SEEK. This flag is set by - * decoder_get_virtual_command(), when the virtual SEEK - * command is generated for the first time. - */ - bool initial_seek_running; - - /** - * This flag is set by decoder_seek_time(), and checked by - * decoder_command_finished(). It is used to clean up after - * seeking. - */ - bool seeking; - - /** - * The tag from the song object. This is only used for local - * files, because we expect the stream server to send us a new - * tag each time we play it. - */ - Tag *song_tag; - - /** the last tag received from the stream */ - Tag *stream_tag; - - /** the last tag received from the decoder plugin */ - Tag *decoder_tag; - - /** the chunk currently being written to */ - MusicChunk *chunk; - - ReplayGainInfo replay_gain_info; - - /** - * A positive serial number for checking if replay gain info - * has changed since the last check. - */ - unsigned replay_gain_serial; - - /** - * An error has occurred (in DecoderAPI.cxx), and the plugin - * will be asked to stop. - */ - Error error; - - Decoder(DecoderControl &_dc, bool _initial_seek_pending, Tag *_tag) - :dc(_dc), - convert(nullptr), - timestamp(0), - initial_seek_pending(_initial_seek_pending), - initial_seek_running(false), - seeking(false), - song_tag(_tag), stream_tag(nullptr), decoder_tag(nullptr), - chunk(nullptr), - replay_gain_serial(0) { - } - - ~Decoder(); - - /** - * Returns the current chunk the decoder writes to, or allocates a new - * chunk if there is none. - * - * @return the chunk, or NULL if we have received a decoder command - */ - MusicChunk *GetChunk(); - - /** - * Flushes the current chunk. - * - * Caller must not lock the #DecoderControl object. - */ - void FlushChunk(); -}; - -#endif diff -Nru mpd-0.19.21/src/decoder/DecoderList.cxx mpd-0.20.9/src/decoder/DecoderList.cxx --- mpd-0.19.21/src/decoder/DecoderList.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderList.cxx 2017-05-08 13:16:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "DecoderList.hxx" #include "DecoderPlugin.hxx" #include "config/ConfigGlobal.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "plugins/AudiofileDecoderPlugin.hxx" #include "plugins/PcmDecoderPlugin.hxx" #include "plugins/DsdiffDecoderPlugin.hxx" @@ -48,44 +48,42 @@ #include const struct DecoderPlugin *const decoder_plugins[] = { -#ifdef HAVE_MAD +#ifdef ENABLE_MAD &mad_decoder_plugin, #endif -#ifdef HAVE_MPG123 +#ifdef ENABLE_MPG123 &mpg123_decoder_plugin, #endif #ifdef ENABLE_VORBIS_DECODER &vorbis_decoder_plugin, #endif -#if defined(HAVE_FLAC) +#ifdef ENABLE_FLAC &oggflac_decoder_plugin, -#endif -#ifdef HAVE_FLAC &flac_decoder_plugin, #endif -#ifdef HAVE_OPUS +#ifdef ENABLE_OPUS &opus_decoder_plugin, #endif #ifdef ENABLE_SNDFILE &sndfile_decoder_plugin, #endif -#ifdef HAVE_AUDIOFILE +#ifdef ENABLE_AUDIOFILE &audiofile_decoder_plugin, #endif #ifdef ENABLE_DSD &dsdiff_decoder_plugin, &dsf_decoder_plugin, #endif -#ifdef HAVE_FAAD +#ifdef ENABLE_FAAD &faad_decoder_plugin, #endif -#ifdef HAVE_MPCDEC +#ifdef ENABLE_MPCDEC &mpcdec_decoder_plugin, #endif -#ifdef HAVE_WAVPACK +#ifdef ENABLE_WAVPACK &wavpack_decoder_plugin, #endif -#ifdef HAVE_MODPLUG +#ifdef ENABLE_MODPLUG &modplug_decoder_plugin, #endif #ifdef ENABLE_MIKMOD_DECODER @@ -100,13 +98,13 @@ #ifdef ENABLE_FLUIDSYNTH &fluidsynth_decoder_plugin, #endif -#ifdef HAVE_ADPLUG +#ifdef ENABLE_ADPLUG &adplug_decoder_plugin, #endif -#ifdef HAVE_FFMPEG +#ifdef ENABLE_FFMPEG &ffmpeg_decoder_plugin, #endif -#ifdef HAVE_GME +#ifdef ENABLE_GME &gme_decoder_plugin, #endif &pcm_decoder_plugin, @@ -120,7 +118,7 @@ bool decoder_plugins_enabled[num_decoder_plugins]; const struct DecoderPlugin * -decoder_plugin_from_name(const char *name) +decoder_plugin_from_name(const char *name) noexcept { return decoder_plugins_find([=](const DecoderPlugin &plugin){ return strcmp(plugin.name, name) == 0; @@ -129,12 +127,13 @@ void decoder_plugin_init_all(void) { - struct config_param empty; + ConfigBlock empty; for (unsigned i = 0; decoder_plugins[i] != nullptr; ++i) { const DecoderPlugin &plugin = *decoder_plugins[i]; - const struct config_param *param = - config_find_block(CONF_DECODER, "plugin", plugin.name); + const auto *param = + config_find_block(ConfigBlockOption::DECODER, "plugin", + plugin.name); if (param == nullptr) param = ∅ @@ -155,7 +154,7 @@ } bool -decoder_plugins_supports_suffix(const char *suffix) +decoder_plugins_supports_suffix(const char *suffix) noexcept { return decoder_plugins_try([suffix](const DecoderPlugin &plugin){ return plugin.SupportsSuffix(suffix); diff -Nru mpd-0.19.21/src/decoder/DecoderList.hxx mpd-0.20.9/src/decoder/DecoderList.hxx --- mpd-0.19.21/src/decoder/DecoderList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderList.hxx 2017-05-08 13:16:13.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,13 +31,15 @@ gcc_pure const struct DecoderPlugin * -decoder_plugin_from_name(const char *name); +decoder_plugin_from_name(const char *name) noexcept; /* this is where we "load" all the "plugins" ;-) */ -void decoder_plugin_init_all(void); +void +decoder_plugin_init_all(); /* this is where we "unload" all the "plugins" */ -void decoder_plugin_deinit_all(void); +void +decoder_plugin_deinit_all(); template static inline const DecoderPlugin * @@ -84,6 +86,6 @@ */ gcc_pure gcc_nonnull_all bool -decoder_plugins_supports_suffix(const char *suffix); +decoder_plugins_supports_suffix(const char *suffix) noexcept; #endif diff -Nru mpd-0.19.21/src/decoder/DecoderPlugin.cxx mpd-0.20.9/src/decoder/DecoderPlugin.cxx --- mpd-0.19.21/src/decoder/DecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderPlugin.cxx 2017-05-08 14:55:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,19 +24,19 @@ #include bool -DecoderPlugin::SupportsSuffix(const char *suffix) const +DecoderPlugin::SupportsSuffix(const char *suffix) const noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(suffix != nullptr); #endif - return suffixes != nullptr && string_array_contains(suffixes, suffix); - + return suffixes != nullptr && + StringArrayContainsCase(suffixes, suffix); } bool -DecoderPlugin::SupportsMimeType(const char *mime_type) const +DecoderPlugin::SupportsMimeType(const char *mime_type) const noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ @@ -44,5 +44,5 @@ #endif return mime_types != nullptr && - string_array_contains(mime_types, mime_type); + StringArrayContainsCase(mime_types, mime_type); } diff -Nru mpd-0.19.21/src/decoder/DecoderPlugin.hxx mpd-0.20.9/src/decoder/DecoderPlugin.hxx --- mpd-0.19.21/src/decoder/DecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderPlugin.hxx 2017-05-08 14:55:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,16 +22,14 @@ #include "Compiler.h" -struct config_param; +#include + +struct ConfigBlock; class InputStream; -struct tag_handler; +struct TagHandler; class Path; - -/** - * Opaque handle which the decoder plugin passes to the functions in - * this header. - */ -struct Decoder; +class DecoderClient; +class DetachedSong; struct DecoderPlugin { const char *name; @@ -44,29 +42,29 @@ * @return true if the plugin was initialized successfully, * false if the plugin is not available */ - bool (*init)(const config_param ¶m); + bool (*init)(const ConfigBlock &block); /** * Deinitialize a decoder plugin which was initialized * successfully. Optional method. */ - void (*finish)(void); + void (*finish)(); /** - * Decode a stream (data read from an #input_stream object). + * Decode a stream (data read from an #InputStream object). * * Either implement this method or file_decode(). If * possible, it is recommended to implement this method, * because it is more versatile. */ - void (*stream_decode)(Decoder &decoder, InputStream &is); + void (*stream_decode)(DecoderClient &client, InputStream &is); /** * Decode a local file. * * Either implement this method or stream_decode(). */ - void (*file_decode)(Decoder &decoder, Path path_fs); + void (*file_decode)(DecoderClient &client, Path path_fs); /** * Scan metadata of a file. @@ -74,7 +72,7 @@ * @return false if the operation has failed */ bool (*scan_file)(Path path_fs, - const struct tag_handler *handler, + const TagHandler &handler, void *handler_ctx); /** @@ -83,22 +81,19 @@ * @return false if the operation has failed */ bool (*scan_stream)(InputStream &is, - const struct tag_handler *handler, + const TagHandler &handler, void *handler_ctx); /** * @brief Return a "virtual" filename for subtracks in * container formats like flac - * @param const char* pathname full pathname for the file on fs - * @param const unsigned int tnum track number + * @param path_fs full pathname for the file on fs * - * @return nullptr if there are no multiple files - * a filename for every single track according to tnum (param 2) + * @return an empty list if there are no multiple files + * a filename for every single track; * do not include full pathname here, just the "virtual" file - * - * Free the return value with delete[]. */ - char* (*container_scan)(Path path_fs, const unsigned int tnum); + std::forward_list (*container_scan)(Path path_fs); /* last element in these arrays must always be a nullptr: */ const char *const*suffixes; @@ -107,14 +102,13 @@ /** * Initialize a decoder plugin. * - * @param param a configuration block for this plugin, or nullptr if none - * is configured + * @param block a configuration block for this plugin * @return true if the plugin was initialized successfully, false if * the plugin is not available */ - bool Init(const config_param ¶m) const { + bool Init(const ConfigBlock &block) const { return init != nullptr - ? init(param) + ? init(block) : true; } @@ -129,16 +123,16 @@ /** * Decode a stream. */ - void StreamDecode(Decoder &decoder, InputStream &is) const { - stream_decode(decoder, is); + void StreamDecode(DecoderClient &client, InputStream &is) const { + stream_decode(client, is); } /** * Decode a file. */ template - void FileDecode(Decoder &decoder, P path_fs) const { - file_decode(decoder, path_fs); + void FileDecode(DecoderClient &client, P path_fs) const { + file_decode(client, path_fs); } /** @@ -146,9 +140,9 @@ */ template bool ScanFile(P path_fs, - const tag_handler &handler, void *handler_ctx) const { + const TagHandler &handler, void *handler_ctx) const { return scan_file != nullptr - ? scan_file(path_fs, &handler, handler_ctx) + ? scan_file(path_fs, handler, handler_ctx) : false; } @@ -156,9 +150,9 @@ * Read the tag of a stream. */ bool ScanStream(InputStream &is, - const tag_handler &handler, void *handler_ctx) const { + const TagHandler &handler, void *handler_ctx) const { return scan_stream != nullptr - ? scan_stream(is, &handler, handler_ctx) + ? scan_stream(is, handler, handler_ctx) : false; } @@ -174,13 +168,13 @@ * Does the plugin announce the specified file name suffix? */ gcc_pure gcc_nonnull_all - bool SupportsSuffix(const char *suffix) const; + bool SupportsSuffix(const char *suffix) const noexcept; /** * Does the plugin announce the specified MIME type? */ gcc_pure gcc_nonnull_all - bool SupportsMimeType(const char *mime_type) const; + bool SupportsMimeType(const char *mime_type) const noexcept; }; #endif diff -Nru mpd-0.19.21/src/decoder/DecoderPrint.cxx mpd-0.20.9/src/decoder/DecoderPrint.cxx --- mpd-0.19.21/src/decoder/DecoderPrint.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderPrint.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,35 +21,35 @@ #include "DecoderPrint.hxx" #include "DecoderList.hxx" #include "DecoderPlugin.hxx" -#include "client/Client.hxx" +#include "client/Response.hxx" #include #include static void -decoder_plugin_print(Client &client, +decoder_plugin_print(Response &r, const DecoderPlugin &plugin) { const char *const*p; assert(plugin.name != nullptr); - client_printf(client, "plugin: %s\n", plugin.name); + r.Format("plugin: %s\n", plugin.name); if (plugin.suffixes != nullptr) for (p = plugin.suffixes; *p != nullptr; ++p) - client_printf(client, "suffix: %s\n", *p); + r.Format("suffix: %s\n", *p); if (plugin.mime_types != nullptr) for (p = plugin.mime_types; *p != nullptr; ++p) - client_printf(client, "mime_type: %s\n", *p); + r.Format("mime_type: %s\n", *p); } void -decoder_list_print(Client &client) +decoder_list_print(Response &r) { using namespace std::placeholders; - const auto f = std::bind(decoder_plugin_print, std::ref(client), _1); + const auto f = std::bind(decoder_plugin_print, std::ref(r), _1); decoder_plugins_for_each_enabled(f); } diff -Nru mpd-0.19.21/src/decoder/DecoderPrint.hxx mpd-0.20.9/src/decoder/DecoderPrint.hxx --- mpd-0.19.21/src/decoder/DecoderPrint.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderPrint.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,9 +20,9 @@ #ifndef MPD_DECODER_PRINT_HXX #define MPD_DECODER_PRINT_HXX -class Client; +class Response; void -decoder_list_print(Client &client); +decoder_list_print(Response &r); #endif diff -Nru mpd-0.19.21/src/decoder/DecoderThread.cxx mpd-0.20.9/src/decoder/DecoderThread.cxx --- mpd-0.19.21/src/decoder/DecoderThread.cxx 2016-08-05 16:14:28.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderThread.cxx 2017-05-08 13:16:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,10 @@ #include "config.h" #include "DecoderThread.hxx" #include "DecoderControl.hxx" -#include "DecoderInternal.hxx" +#include "Bridge.hxx" #include "DecoderError.hxx" #include "DecoderPlugin.hxx" #include "DetachedSong.hxx" -#include "system/FatalError.hxx" #include "MusicPipe.hxx" #include "fs/Traits.hxx" #include "fs/AllocatedPath.hxx" @@ -32,179 +31,159 @@ #include "input/InputStream.hxx" #include "input/LocalOpen.hxx" #include "DecoderList.hxx" +#include "system/Error.hxx" +#include "util/MimeType.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" +#include "util/ScopeExit.hxx" #include "thread/Name.hxx" #include "tag/ApeReplayGain.hxx" #include "Log.hxx" +#include #include +#include static constexpr Domain decoder_thread_domain("decoder_thread"); /** - * Marks the current decoder command as "finished" and notifies the - * player thread. - * - * @param dc the #DecoderControl object; must be locked - */ -static void -decoder_command_finished_locked(DecoderControl &dc) -{ - assert(dc.command != DecoderCommand::NONE); - - dc.command = DecoderCommand::NONE; - - dc.client_cond.signal(); -} - -/** - * Opens the input stream with input_stream::Open(), and waits until - * the stream gets ready. If a decoder STOP command is received - * during that, it cancels the operation (but does not close the - * stream). + * Opens the input stream with InputStream::Open(), and waits until + * the stream gets ready. * * Unlock the decoder before calling this function. - * - * @return an input_stream on success or if #DecoderCommand::STOP is - * received, nullptr on error */ -static InputStream * +static InputStreamPtr decoder_input_stream_open(DecoderControl &dc, const char *uri) { - Error error; - - InputStream *is = InputStream::Open(uri, dc.mutex, dc.cond, error); - if (is == nullptr) { - if (error.IsDefined()) - LogError(error); - - return nullptr; - } + auto is = InputStream::Open(uri, dc.mutex, dc.cond); /* wait for the input stream to become ready; its metadata will be available then */ - dc.Lock(); + const std::lock_guard protect(dc.mutex); is->Update(); - while (!is->IsReady() && - dc.command != DecoderCommand::STOP) { + while (!is->IsReady()) { + if (dc.command == DecoderCommand::STOP) + throw StopDecoder(); + dc.Wait(); is->Update(); } - if (!is->Check(error)) { - dc.Unlock(); - delete is; - - LogError(error); - return nullptr; - } - - dc.Unlock(); + is->Check(); return is; } -static InputStream * +static InputStreamPtr decoder_input_stream_open(DecoderControl &dc, Path path) { - Error error; - - InputStream *is = OpenLocalInputStream(path, dc.mutex, dc.cond, error); - if (is == nullptr) { - LogError(error); - return nullptr; - } + auto is = OpenLocalInputStream(path, dc.mutex, dc.cond); assert(is->IsReady()); return is; } +/** + * Decode a stream with the given decoder plugin. + * + * Caller holds DecoderControl::mutex. + */ static bool decoder_stream_decode(const DecoderPlugin &plugin, - Decoder &decoder, + DecoderBridge &bridge, InputStream &input_stream) { assert(plugin.stream_decode != nullptr); - assert(decoder.stream_tag == nullptr); - assert(decoder.decoder_tag == nullptr); + assert(bridge.stream_tag == nullptr); + assert(bridge.decoder_tag == nullptr); assert(input_stream.IsReady()); - assert(decoder.dc.state == DecoderState::START); + assert(bridge.dc.state == DecoderState::START); FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name); - if (decoder.dc.command == DecoderCommand::STOP) - return true; + if (bridge.dc.command == DecoderCommand::STOP) + throw StopDecoder(); /* rewind the stream, so each plugin gets a fresh start */ - input_stream.Rewind(IgnoreError()); - - decoder.dc.Unlock(); + try { + input_stream.Rewind(); + } catch (const std::runtime_error &) { + } - FormatThreadName("decoder:%s", plugin.name); + { + const ScopeUnlock unlock(bridge.dc.mutex); - plugin.StreamDecode(decoder, input_stream); + FormatThreadName("decoder:%s", plugin.name); - SetThreadName("decoder"); + plugin.StreamDecode(bridge, input_stream); - decoder.dc.Lock(); + SetThreadName("decoder"); + } - assert(decoder.dc.state == DecoderState::START || - decoder.dc.state == DecoderState::DECODE); + assert(bridge.dc.state == DecoderState::START || + bridge.dc.state == DecoderState::DECODE); - return decoder.dc.state != DecoderState::START; + return bridge.dc.state != DecoderState::START; } +/** + * Decode a file with the given decoder plugin. + * + * Caller holds DecoderControl::mutex. + */ static bool decoder_file_decode(const DecoderPlugin &plugin, - Decoder &decoder, Path path) + DecoderBridge &bridge, Path path) { assert(plugin.file_decode != nullptr); - assert(decoder.stream_tag == nullptr); - assert(decoder.decoder_tag == nullptr); + assert(bridge.stream_tag == nullptr); + assert(bridge.decoder_tag == nullptr); assert(!path.IsNull()); assert(path.IsAbsolute()); - assert(decoder.dc.state == DecoderState::START); + assert(bridge.dc.state == DecoderState::START); FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name); - if (decoder.dc.command == DecoderCommand::STOP) - return true; + if (bridge.dc.command == DecoderCommand::STOP) + throw StopDecoder(); - decoder.dc.Unlock(); + { + const ScopeUnlock unlock(bridge.dc.mutex); - FormatThreadName("decoder:%s", plugin.name); + FormatThreadName("decoder:%s", plugin.name); - plugin.FileDecode(decoder, path); + plugin.FileDecode(bridge, path); - SetThreadName("decoder"); - - decoder.dc.Lock(); + SetThreadName("decoder"); + } - assert(decoder.dc.state == DecoderState::START || - decoder.dc.state == DecoderState::DECODE); + assert(bridge.dc.state == DecoderState::START || + bridge.dc.state == DecoderState::DECODE); - return decoder.dc.state != DecoderState::START; + return bridge.dc.state != DecoderState::START; } gcc_pure static bool -decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is) +decoder_check_plugin_mime(const DecoderPlugin &plugin, + const InputStream &is) noexcept { assert(plugin.stream_decode != nullptr); const char *mime_type = is.GetMimeType(); - return mime_type != nullptr && plugin.SupportsMimeType(mime_type); + return mime_type != nullptr && + plugin.SupportsMimeType(GetMimeTypeBase(mime_type).c_str()); } gcc_pure static bool -decoder_check_plugin_suffix(const DecoderPlugin &plugin, const char *suffix) +decoder_check_plugin_suffix(const DecoderPlugin &plugin, + const char *suffix) noexcept { assert(plugin.stream_decode != nullptr); @@ -214,7 +193,7 @@ gcc_pure static bool decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is, - const char *suffix) + const char *suffix) noexcept { return plugin.stream_decode != nullptr && (decoder_check_plugin_mime(plugin, is) || @@ -222,7 +201,7 @@ } static bool -decoder_run_stream_plugin(Decoder &decoder, InputStream &is, +decoder_run_stream_plugin(DecoderBridge &bridge, InputStream &is, const char *suffix, const DecoderPlugin &plugin, bool &tried_r) @@ -230,12 +209,14 @@ if (!decoder_check_plugin(plugin, is, suffix)) return false; + bridge.error = std::exception_ptr(); + tried_r = true; - return decoder_stream_decode(plugin, decoder, is); + return decoder_stream_decode(plugin, bridge, is); } static bool -decoder_run_stream_locked(Decoder &decoder, InputStream &is, +decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is, const char *uri, bool &tried_r) { UriSuffixBuffer suffix_buffer; @@ -243,7 +224,7 @@ using namespace std::placeholders; const auto f = std::bind(decoder_run_stream_plugin, - std::ref(decoder), std::ref(is), suffix, + std::ref(bridge), std::ref(is), suffix, _1, std::ref(tried_r)); return decoder_plugins_try(f); } @@ -252,188 +233,264 @@ * Try decoding a stream, using the fallback plugin. */ static bool -decoder_run_stream_fallback(Decoder &decoder, InputStream &is) +decoder_run_stream_fallback(DecoderBridge &bridge, InputStream &is) { const struct DecoderPlugin *plugin; -#ifdef HAVE_FFMPEG +#ifdef ENABLE_FFMPEG plugin = decoder_plugin_from_name("ffmpeg"); #else plugin = decoder_plugin_from_name("mad"); #endif return plugin != nullptr && plugin->stream_decode != nullptr && - decoder_stream_decode(*plugin, decoder, is); + decoder_stream_decode(*plugin, bridge, is); +} + +/** + * Attempt to load replay gain data, and pass it to + * DecoderClient::SubmitReplayGain(). + */ +static void +LoadReplayGain(DecoderClient &client, InputStream &is) +{ + ReplayGainInfo info; + if (replay_gain_ape_read(is, info)) + client.SubmitReplayGain(&info); +} + +/** + * Call LoadReplayGain() unless ReplayGain is disabled. This saves + * the I/O overhead when the user is not interested in the feature. + */ +static void +MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is) +{ + { + const std::lock_guard protect(bridge.dc.mutex); + if (bridge.dc.replay_gain_mode == ReplayGainMode::OFF) + /* ReplayGain is disabled */ + return; + } + + LoadReplayGain(bridge, is); } /** * Try decoding a stream. + * + * DecoderControl::mutex is not locked by caller. */ static bool -decoder_run_stream(Decoder &decoder, const char *uri) +decoder_run_stream(DecoderBridge &bridge, const char *uri) { - DecoderControl &dc = decoder.dc; - InputStream *input_stream; - bool success; + DecoderControl &dc = bridge.dc; - dc.Unlock(); + auto input_stream = decoder_input_stream_open(dc, uri); + assert(input_stream); - input_stream = decoder_input_stream_open(dc, uri); - if (input_stream == nullptr) { - dc.Lock(); - return false; - } + MaybeLoadReplayGain(bridge, *input_stream); - dc.Lock(); + const std::lock_guard protect(dc.mutex); bool tried = false; - success = dc.command == DecoderCommand::STOP || - decoder_run_stream_locked(decoder, *input_stream, uri, + return dc.command == DecoderCommand::STOP || + decoder_run_stream_locked(bridge, *input_stream, uri, tried) || /* fallback to mp3: this is needed for bastard streams that don't have a suffix or set the mimeType */ (!tried && - decoder_run_stream_fallback(decoder, *input_stream)); - - dc.Unlock(); - delete input_stream; - dc.Lock(); - - return success; + decoder_run_stream_fallback(bridge, *input_stream)); } /** - * Attempt to load replay gain data, and pass it to - * decoder_replay_gain(). + * Decode a file with the given decoder plugin. + * + * DecoderControl::mutex is not locked by caller. */ -static void -decoder_load_replay_gain(Decoder &decoder, Path path_fs) -{ - ReplayGainInfo info; - if (replay_gain_ape_read(path_fs, info)) - decoder_replay_gain(decoder, &info); -} - static bool -TryDecoderFile(Decoder &decoder, Path path_fs, const char *suffix, +TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix, + InputStream &input_stream, const DecoderPlugin &plugin) { if (!plugin.SupportsSuffix(suffix)) return false; - DecoderControl &dc = decoder.dc; + bridge.error = std::exception_ptr(); - if (plugin.file_decode != nullptr) { - dc.Lock(); - - if (decoder_file_decode(plugin, decoder, path_fs)) - return true; + DecoderControl &dc = bridge.dc; - dc.Unlock(); + if (plugin.file_decode != nullptr) { + const std::lock_guard protect(dc.mutex); + return decoder_file_decode(plugin, bridge, path_fs); } else if (plugin.stream_decode != nullptr) { - InputStream *input_stream = - decoder_input_stream_open(dc, path_fs); - if (input_stream == nullptr) - return false; - - dc.Lock(); - - bool success = decoder_stream_decode(plugin, decoder, - *input_stream); + const std::lock_guard protect(dc.mutex); + return decoder_stream_decode(plugin, bridge, input_stream); + } else + return false; +} - dc.Unlock(); +/** + * Decode a container file with the given decoder plugin. + * + * DecoderControl::mutex is not locked by caller. + */ +static bool +TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix, + const DecoderPlugin &plugin) +{ + if (plugin.container_scan == nullptr || + plugin.file_decode == nullptr || + !plugin.SupportsSuffix(suffix)) + return false; - delete input_stream; + bridge.error = nullptr; - if (success) { - dc.Lock(); - return true; - } - } + DecoderControl &dc = bridge.dc; + const std::lock_guard protect(dc.mutex); + return decoder_file_decode(plugin, bridge, path_fs); +} - return false; +/** + * Decode a container file. + * + * DecoderControl::mutex is not locked by caller. + */ +static bool +TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix) +{ + return decoder_plugins_try([&bridge, path_fs, + suffix](const DecoderPlugin &plugin){ + return TryContainerDecoder(bridge, + path_fs, + suffix, + plugin); + }); } /** * Try decoding a file. + * + * DecoderControl::mutex is not locked by caller. */ static bool -decoder_run_file(Decoder &decoder, const char *uri_utf8, Path path_fs) +decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs) { const char *suffix = uri_get_suffix(uri_utf8); if (suffix == nullptr) return false; - DecoderControl &dc = decoder.dc; - dc.Unlock(); + InputStreamPtr input_stream; + + try { + input_stream = decoder_input_stream_open(bridge.dc, path_fs); + } catch (const std::system_error &e) { + if (IsPathNotFound(e) && + /* ENOTDIR means this may be a path inside a + "container" file */ + TryContainerDecoder(bridge, path_fs, suffix)) + return true; + + throw; + } - decoder_load_replay_gain(decoder, path_fs); + assert(input_stream); - if (decoder_plugins_try([&decoder, path_fs, - suffix](const DecoderPlugin &plugin){ - return TryDecoderFile(decoder, - path_fs, suffix, - plugin); - })) - return true; + MaybeLoadReplayGain(bridge, *input_stream); - dc.Lock(); - return false; + auto &is = *input_stream; + return decoder_plugins_try([&bridge, path_fs, suffix, + &is](const DecoderPlugin &plugin){ + return TryDecoderFile(bridge, + path_fs, + suffix, + is, + plugin); + }); } +/** + * Decode a song. + * + * DecoderControl::mutex is not locked. + */ +static bool +DecoderUnlockedRunUri(DecoderBridge &bridge, + const char *real_uri, Path path_fs) +try { + return !path_fs.IsNull() + ? decoder_run_file(bridge, real_uri, path_fs) + : decoder_run_stream(bridge, real_uri); +} catch (StopDecoder) { + return true; +} catch (...) { + const char *error_uri = real_uri; + const std::string allocated = uri_remove_auth(error_uri); + if (!allocated.empty()) + error_uri = allocated.c_str(); + + std::throw_with_nested(FormatRuntimeError("Failed to decode %s", + error_uri)); +} + +/** + * Decode a song addressed by a #DetachedSong. + * + * Caller holds DecoderControl::mutex. + */ static void decoder_run_song(DecoderControl &dc, const DetachedSong &song, const char *uri, Path path_fs) { - Decoder decoder(dc, dc.start_time.IsPositive(), - /* pass the song tag only if it's - authoritative, i.e. if it's a local file - - tags on "stream" songs are just remembered - from the last time we played it*/ - song.IsFile() ? new Tag(song.GetTag()) : nullptr); - int ret; + DecoderBridge bridge(dc, dc.start_time.IsPositive(), + /* pass the song tag only if it's + authoritative, i.e. if it's a local + file - tags on "stream" songs are just + remembered from the last time we + played it*/ + song.IsFile() ? new Tag(song.GetTag()) : nullptr); dc.state = DecoderState::START; + dc.CommandFinishedLocked(); - decoder_command_finished_locked(dc); - - ret = !path_fs.IsNull() - ? decoder_run_file(decoder, uri, path_fs) - : decoder_run_stream(decoder, uri); - - dc.Unlock(); + bool success; + { + const ScopeUnlock unlock(dc.mutex); - /* flush the last chunk */ + AtScopeExit(&bridge) { + /* flush the last chunk */ + if (bridge.current_chunk != nullptr) + bridge.FlushChunk(); + }; - if (decoder.chunk != nullptr) - decoder.FlushChunk(); + success = DecoderUnlockedRunUri(bridge, uri, path_fs); - dc.Lock(); + } - if (decoder.error.IsDefined()) { - /* copy the Error from sruct Decoder to + if (bridge.error) { + /* copy the Error from struct Decoder to DecoderControl */ - dc.state = DecoderState::ERROR; - dc.error = std::move(decoder.error); - } else if (ret) + std::rethrow_exception(bridge.error); + } else if (success) dc.state = DecoderState::STOP; else { - dc.state = DecoderState::ERROR; - const char *error_uri = song.GetURI(); const std::string allocated = uri_remove_auth(error_uri); if (!allocated.empty()) error_uri = allocated.c_str(); - dc.error.Format(decoder_domain, - "Failed to decode %s", error_uri); + throw FormatRuntimeError("Failed to decode %s", error_uri); } dc.client_cond.signal(); } +/** + * + * Caller holds DecoderControl::mutex. + */ static void decoder_run(DecoderControl &dc) -{ +try { dc.ClearError(); assert(dc.song != nullptr); @@ -444,18 +501,15 @@ Path path_fs = Path::Null(); AllocatedPath path_buffer = AllocatedPath::Null(); if (PathTraitsUTF8::IsAbsolute(uri_utf8)) { - path_buffer = AllocatedPath::FromUTF8(uri_utf8, dc.error); - if (path_buffer.IsNull()) { - dc.state = DecoderState::ERROR; - decoder_command_finished_locked(dc); - return; - } - + path_buffer = AllocatedPath::FromUTF8Throw(uri_utf8); path_fs = path_buffer; } decoder_run_song(dc, song, uri_utf8, path_fs); - +} catch (...) { + dc.state = DecoderState::ERROR; + dc.error = std::current_exception(); + dc.client_cond.signal(); } static void @@ -465,7 +519,7 @@ SetThreadName("decoder"); - dc.Lock(); + const std::lock_guard protect(dc.mutex); do { assert(dc.state == DecoderState::STOP || @@ -478,6 +532,16 @@ dc.replay_gain_db = 0; decoder_run(dc); + + if (dc.state == DecoderState::ERROR) { + try { + std::rethrow_exception(dc.error); + } catch (const std::exception &e) { + LogError(e); + } catch (...) { + } + } + break; case DecoderCommand::SEEK: @@ -493,7 +557,7 @@ break; case DecoderCommand::STOP: - decoder_command_finished_locked(dc); + dc.CommandFinishedLocked(); break; case DecoderCommand::NONE: @@ -501,8 +565,6 @@ break; } } while (dc.command != DecoderCommand::NONE || !dc.quit); - - dc.Unlock(); } void @@ -511,8 +573,5 @@ assert(!dc.thread.IsDefined()); dc.quit = false; - - Error error; - if (!dc.thread.Start(decoder_task, &dc, error)) - FatalError(error); + dc.thread.Start(decoder_task, &dc); } diff -Nru mpd-0.19.21/src/decoder/DecoderThread.hxx mpd-0.20.9/src/decoder/DecoderThread.hxx --- mpd-0.19.21/src/decoder/DecoderThread.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/DecoderThread.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/AdPlugDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/AdPlugDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/AdPlugDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/AdPlugDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,6 @@ #include "../DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "util/Macros.hxx" #include "Log.hxx" @@ -38,24 +37,19 @@ static unsigned sample_rate; static bool -adplug_init(const config_param ¶m) +adplug_init(const ConfigBlock &block) { FormatDebug(adplug_domain, "adplug %s", CAdPlug::get_version().c_str()); - Error error; - - sample_rate = param.GetBlockValue("sample_rate", 48000u); - if (!audio_check_sample_rate(sample_rate, error)) { - LogError(error); - return false; - } + sample_rate = block.GetBlockValue("sample_rate", 48000u); + CheckSampleRate(sample_rate); return true; } static void -adplug_file_decode(Decoder &decoder, Path path_fs) +adplug_file_decode(DecoderClient &client, Path path_fs) { CEmuopl opl(sample_rate, true, true); opl.init(); @@ -67,8 +61,8 @@ const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2); assert(audio_format.IsValid()); - decoder_initialized(decoder, audio_format, false, - SongTime::FromMS(player->songlength())); + client.Ready(audio_format, false, + SongTime::FromMS(player->songlength())); DecoderCommand cmd; @@ -79,9 +73,9 @@ int16_t buffer[2048]; constexpr unsigned frames_per_buffer = ARRAY_SIZE(buffer) / 2; opl.update(buffer, frames_per_buffer); - cmd = decoder_data(decoder, nullptr, - buffer, sizeof(buffer), - 0); + cmd = client.SubmitData(nullptr, + buffer, sizeof(buffer), + 0); } while (cmd == DecoderCommand::NONE); delete player; @@ -89,7 +83,7 @@ static void adplug_scan_tag(TagType type, const std::string &value, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { if (!value.empty()) tag_handler_invoke_tag(handler, handler_ctx, @@ -98,7 +92,7 @@ static bool adplug_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { CEmuopl opl(sample_rate, true, true); opl.init(); @@ -110,7 +104,7 @@ tag_handler_invoke_duration(handler, handler_ctx, SongTime::FromMS(player->songlength())); - if (handler->tag != nullptr) { + if (handler.tag != nullptr) { adplug_scan_tag(TAG_TITLE, player->gettitle(), handler, handler_ctx); adplug_scan_tag(TAG_ARTIST, player->getauthor(), diff -Nru mpd-0.19.21/src/decoder/plugins/AdPlugDecoderPlugin.h mpd-0.20.9/src/decoder/plugins/AdPlugDecoderPlugin.h --- mpd-0.19.21/src/decoder/plugins/AdPlugDecoderPlugin.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/AdPlugDecoderPlugin.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/AudiofileDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/AudiofileDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/AudiofileDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/AudiofileDecoderPlugin.cxx 2017-05-08 15:09:17.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,14 +23,15 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "tag/TagHandler.hxx" -#include "fs/Path.hxx" -#include "util/Error.hxx" +#include "util/ScopeExit.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include #include +#include + #include #include @@ -43,21 +44,21 @@ } static bool -audiofile_init(const config_param &) +audiofile_init(const ConfigBlock &) { afSetErrorHandler(audiofile_error_func); return true; } struct AudioFileInputStream { - Decoder *const decoder; + DecoderClient *const client; InputStream &is; size_t Read(void *buffer, size_t size) { /* libaudiofile does not like partial reads at all, and will abort playback; therefore always force full reads */ - return decoder_read_full(decoder, is, buffer, size) + return decoder_read_full(client, is, buffer, size) ? size : 0; } @@ -65,7 +66,7 @@ gcc_pure static SongTime -audiofile_get_duration(AFfilehandle fh) +audiofile_get_duration(AFfilehandle fh) noexcept { return SongTime::FromScale(afGetFrameCount(fh, AF_DEFAULT_TRACK), afGetRate(fh, AF_DEFAULT_TRACK)); @@ -116,11 +117,11 @@ if (is_relative) offset += is.GetOffset(); - Error error; - if (is.LockSeek(offset, error)) { + try { + is.LockSeek(offset); return is.GetOffset(); - } else { - LogError(error, "Seek failed"); + } catch (const std::runtime_error &e) { + LogError(e, "Seek failed"); return -1; } } @@ -180,31 +181,26 @@ } static void -audiofile_stream_decode(Decoder &decoder, InputStream &is) +audiofile_stream_decode(DecoderClient &client, InputStream &is) { if (!is.IsSeekable() || !is.KnownSize()) { LogWarning(audiofile_domain, "not seekable"); return; } - AudioFileInputStream afis{&decoder, is}; + AudioFileInputStream afis{&client, is}; AFvirtualfile *const vf = setup_virtual_fops(afis); const AFfilehandle fh = afOpenVirtualFile(vf, "r", nullptr); if (fh == AF_NULL_FILEHANDLE) return; - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, - afGetRate(fh, AF_DEFAULT_TRACK), - audiofile_setup_sample_format(fh), - afGetVirtualChannels(fh, AF_DEFAULT_TRACK), - error)) { - LogError(error); - afCloseFile(fh); - return; - } + AtScopeExit(fh) { afCloseFile(fh); }; + + const auto audio_format = + CheckAudioFormat(afGetRate(fh, AF_DEFAULT_TRACK), + audiofile_setup_sample_format(fh), + afGetVirtualChannels(fh, AF_DEFAULT_TRACK)); const auto total_time = audiofile_get_duration(fh); @@ -214,7 +210,7 @@ const unsigned frame_size = (unsigned) afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true); - decoder_initialized(decoder, audio_format, true, total_time); + client.Ready(audio_format, true, total_time); DecoderCommand cmd; do { @@ -227,25 +223,23 @@ if (nframes <= 0) break; - cmd = decoder_data(decoder, nullptr, - chunk, nframes * frame_size, - kbit_rate); + cmd = client.SubmitData(nullptr, + chunk, nframes * frame_size, + kbit_rate); if (cmd == DecoderCommand::SEEK) { - AFframecount frame = decoder_seek_where_frame(decoder); + AFframecount frame = client.GetSeekFrame(); afSeekFrame(fh, AF_DEFAULT_TRACK, frame); - decoder_command_finished(decoder); + client.CommandFinished(); cmd = DecoderCommand::NONE; } } while (cmd == DecoderCommand::NONE); - - afCloseFile(fh); } gcc_pure static SignedSongTime -audiofile_get_duration(InputStream &is) +audiofile_get_duration(InputStream &is) noexcept { if (!is.IsSeekable() || !is.KnownSize()) return SignedSongTime::Negative(); @@ -263,7 +257,7 @@ static bool audiofile_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const auto duration = audiofile_get_duration(is); if (duration.IsNegative()) diff -Nru mpd-0.19.21/src/decoder/plugins/AudiofileDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/AudiofileDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/AudiofileDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/AudiofileDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/DsdiffDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/DsdiffDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/DsdiffDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsdiffDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,7 +32,6 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "util/bit_reverse.h" -#include "util/Error.hxx" #include "system/ByteOrder.hxx" #include "tag/TagHandler.hxx" #include "DsdLib.hxx" @@ -72,28 +71,28 @@ static bool lsbitfirst; static bool -dsdiff_init(const config_param ¶m) +dsdiff_init(const ConfigBlock &block) { - lsbitfirst = param.GetBlockValue("lsbitfirst", false); + lsbitfirst = block.GetBlockValue("lsbitfirst", false); return true; } static bool -dsdiff_read_id(Decoder *decoder, InputStream &is, +dsdiff_read_id(DecoderClient *client, InputStream &is, DsdId *id) { - return decoder_read_full(decoder, is, id, sizeof(*id)); + return decoder_read_full(client, is, id, sizeof(*id)); } static bool -dsdiff_read_chunk_header(Decoder *decoder, InputStream &is, +dsdiff_read_chunk_header(DecoderClient *client, InputStream &is, DsdiffChunkHeader *header) { - return decoder_read_full(decoder, is, header, sizeof(*header)); + return decoder_read_full(client, is, header, sizeof(*header)); } static bool -dsdiff_read_payload(Decoder *decoder, InputStream &is, +dsdiff_read_payload(DecoderClient *client, InputStream &is, const DsdiffChunkHeader *header, void *data, size_t length) { @@ -101,20 +100,20 @@ if (size != (uint64_t)length) return false; - return decoder_read_full(decoder, is, data, length); + return decoder_read_full(client, is, data, length); } /** * Read and parse a "SND" chunk inside "PROP". */ static bool -dsdiff_read_prop_snd(Decoder *decoder, InputStream &is, +dsdiff_read_prop_snd(DecoderClient *client, InputStream &is, DsdiffMetaData *metadata, offset_type end_offset) { DsdiffChunkHeader header; while (is.GetOffset() + sizeof(header) <= end_offset) { - if (!dsdiff_read_chunk_header(decoder, is, &header)) + if (!dsdiff_read_chunk_header(client, is, &header)) return false; offset_type chunk_end_offset = is.GetOffset() @@ -124,7 +123,7 @@ if (header.id.Equals("FS ")) { uint32_t sample_rate; - if (!dsdiff_read_payload(decoder, is, &header, + if (!dsdiff_read_payload(client, is, &header, &sample_rate, sizeof(sample_rate))) return false; @@ -133,18 +132,18 @@ } else if (header.id.Equals("CHNL")) { uint16_t channels; if (header.GetSize() < sizeof(channels) || - !decoder_read_full(decoder, is, + !decoder_read_full(client, is, &channels, sizeof(channels)) || - !dsdlib_skip_to(decoder, is, chunk_end_offset)) + !dsdlib_skip_to(client, is, chunk_end_offset)) return false; metadata->channels = FromBE16(channels); } else if (header.id.Equals("CMPR")) { DsdId type; if (header.GetSize() < sizeof(type) || - !decoder_read_full(decoder, is, + !decoder_read_full(client, is, &type, sizeof(type)) || - !dsdlib_skip_to(decoder, is, chunk_end_offset)) + !dsdlib_skip_to(client, is, chunk_end_offset)) return false; if (!type.Equals("DSD ")) @@ -154,7 +153,7 @@ } else { /* ignore unknown chunk */ - if (!dsdlib_skip_to(decoder, is, chunk_end_offset)) + if (!dsdlib_skip_to(client, is, chunk_end_offset)) return false; } } @@ -166,7 +165,7 @@ * Read and parse a "PROP" chunk. */ static bool -dsdiff_read_prop(Decoder *decoder, InputStream &is, +dsdiff_read_prop(DecoderClient *client, InputStream &is, DsdiffMetaData *metadata, const DsdiffChunkHeader *prop_header) { @@ -175,19 +174,19 @@ DsdId prop_id; if (prop_size < sizeof(prop_id) || - !dsdiff_read_id(decoder, is, &prop_id)) + !dsdiff_read_id(client, is, &prop_id)) return false; if (prop_id.Equals("SND ")) - return dsdiff_read_prop_snd(decoder, is, metadata, end_offset); + return dsdiff_read_prop_snd(client, is, metadata, end_offset); else /* ignore unknown PROP chunk */ - return dsdlib_skip_to(decoder, is, end_offset); + return dsdlib_skip_to(client, is, end_offset); } static void dsdiff_handle_native_tag(InputStream &is, - const struct tag_handler *handler, + const TagHandler &handler, void *handler_ctx, offset_type tagoffset, TagType type) { @@ -226,17 +225,17 @@ */ static bool -dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is, +dsdiff_read_metadata_extra(DecoderClient *client, InputStream &is, DsdiffMetaData *metadata, DsdiffChunkHeader *chunk_header, - const struct tag_handler *handler, + const TagHandler &handler, void *handler_ctx) { /* skip from DSD data to next chunk header */ - if (!dsdlib_skip(decoder, is, metadata->chunk_size)) + if (!dsdlib_skip(client, is, metadata->chunk_size)) return false; - if (!dsdiff_read_chunk_header(decoder, is, chunk_header)) + if (!dsdiff_read_chunk_header(client, is, chunk_header)) return false; /** offset for artist tag */ @@ -244,7 +243,7 @@ /** offset for title tag */ offset_type title_offset = 0; -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG offset_type id3_offset = 0; #endif @@ -269,7 +268,7 @@ chunk_size = chunk_header->GetSize(); title_offset = is.GetOffset(); } -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG /* 'ID3 ' chunk, offspec. Used by sacdextract */ if (chunk_header->id.Equals("ID3 ")) { chunk_size = chunk_header->GetSize(); @@ -277,13 +276,13 @@ } #endif - if (!dsdlib_skip(decoder, is, chunk_size)) + if (!dsdlib_skip(client, is, chunk_size)) break; - } while (dsdiff_read_chunk_header(decoder, is, chunk_header)); + } while (dsdiff_read_chunk_header(client, is, chunk_header)); /* done processing chunk headers, process tags if any */ -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG if (id3_offset != 0) { /* a ID3 tag has preference over the other tags, do not process other tags if we have one */ @@ -308,23 +307,23 @@ * "chunk_header" parameter. */ static bool -dsdiff_read_metadata(Decoder *decoder, InputStream &is, +dsdiff_read_metadata(DecoderClient *client, InputStream &is, DsdiffMetaData *metadata, DsdiffChunkHeader *chunk_header) { DsdiffHeader header; - if (!decoder_read_full(decoder, is, &header, sizeof(header)) || + if (!decoder_read_full(client, is, &header, sizeof(header)) || !header.id.Equals("FRM8") || !header.format.Equals("DSD ")) return false; while (true) { - if (!dsdiff_read_chunk_header(decoder, is, + if (!dsdiff_read_chunk_header(client, is, chunk_header)) return false; if (chunk_header->id.Equals("PROP")) { - if (!dsdiff_read_prop(decoder, is, metadata, + if (!dsdiff_read_prop(client, is, metadata, chunk_header)) return false; } else if (chunk_header->id.Equals("DSD ")) { @@ -337,7 +336,7 @@ const offset_type chunk_end_offset = is.GetOffset() + chunk_size; - if (!dsdlib_skip_to(decoder, is, chunk_end_offset)) + if (!dsdlib_skip_to(client, is, chunk_end_offset)) return false; } } @@ -360,7 +359,7 @@ * Decode one "DSD" chunk. */ static bool -dsdiff_decode_chunk(Decoder &decoder, InputStream &is, +dsdiff_decode_chunk(DecoderClient &client, InputStream &is, unsigned channels, unsigned sample_rate, const offset_type total_bytes) { @@ -373,23 +372,23 @@ const unsigned buffer_frames = sizeof(buffer) / frame_size; const size_t buffer_size = buffer_frames * frame_size; - auto cmd = decoder_get_command(decoder); + auto cmd = client.GetCommand(); for (offset_type remaining_bytes = total_bytes; remaining_bytes >= frame_size && cmd != DecoderCommand::STOP;) { if (cmd == DecoderCommand::SEEK) { - uint64_t frame = decoder_seek_where_frame(decoder); + uint64_t frame = client.GetSeekFrame(); offset_type offset = FrameToOffset(frame, channels); if (offset >= total_bytes) { - decoder_command_finished(decoder); + client.CommandFinished(); break; } - if (dsdlib_skip_to(&decoder, is, + if (dsdlib_skip_to(&client, is, start_offset + offset)) { - decoder_command_finished(decoder); + client.CommandFinished(); remaining_bytes = total_bytes - offset; } else - decoder_seek_error(decoder); + client.SeekError(); } /* see how much aligned data from the remaining chunk @@ -400,7 +399,7 @@ now_size = now_frames * frame_size; } - if (!decoder_read_full(&decoder, is, buffer, now_size)) + if (!decoder_read_full(&client, is, buffer, now_size)) return false; const size_t nbytes = now_size; @@ -409,31 +408,26 @@ if (lsbitfirst) bit_reverse_buffer(buffer, buffer + nbytes); - cmd = decoder_data(decoder, is, buffer, nbytes, - sample_rate / 1000); + cmd = client.SubmitData(is, buffer, nbytes, + sample_rate / 1000); } return true; } static void -dsdiff_stream_decode(Decoder &decoder, InputStream &is) +dsdiff_stream_decode(DecoderClient &client, InputStream &is) { DsdiffMetaData metadata; DsdiffChunkHeader chunk_header; /* check if it is is a proper DFF file */ - if (!dsdiff_read_metadata(&decoder, is, &metadata, &chunk_header)) + if (!dsdiff_read_metadata(&client, is, &metadata, &chunk_header)) return; - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, - SampleFormat::DSD, - metadata.channels, error)) { - LogError(error); - return; - } + auto audio_format = CheckAudioFormat(metadata.sample_rate / 8, + SampleFormat::DSD, + metadata.channels); /* calculate song time from DSD chunk size and sample frequency */ offset_type chunk_size = metadata.chunk_size; @@ -443,12 +437,12 @@ audio_format.sample_rate); /* success: file was recognized */ - decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime); + client.Ready(audio_format, is.IsSeekable(), songtime); /* every iteration of the following loop decodes one "DSD" chunk from a DFF file */ - dsdiff_decode_chunk(decoder, is, + dsdiff_decode_chunk(client, is, metadata.channels, metadata.sample_rate, chunk_size); @@ -456,7 +450,7 @@ static bool dsdiff_scan_stream(InputStream &is, - gcc_unused const struct tag_handler *handler, + gcc_unused const TagHandler &handler, gcc_unused void *handler_ctx) { DsdiffMetaData metadata; @@ -466,12 +460,9 @@ if (!dsdiff_read_metadata(nullptr, is, &metadata, &chunk_header)) return false; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, - SampleFormat::DSD, - metadata.channels, IgnoreError())) - /* refuse to parse files which we cannot play anyway */ - return false; + auto audio_format = CheckAudioFormat(metadata.sample_rate / 8, + SampleFormat::DSD, + metadata.channels); /* calculate song time and add as tag */ uint64_t n_frames = metadata.chunk_size / audio_format.channels; diff -Nru mpd-0.19.21/src/decoder/plugins/DsdiffDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/DsdiffDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/DsdiffDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsdiffDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/DsdLib.cxx mpd-0.20.9/src/decoder/plugins/DsdLib.cxx --- mpd-0.19.21/src/decoder/plugins/DsdLib.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsdLib.cxx 2017-05-08 14:56:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,18 +28,18 @@ #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" #include "tag/TagId3.hxx" -#include "util/Error.hxx" -#include "util/Alloc.hxx" -#include -#include - -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG #include #endif +#include + +#include +#include + bool -DsdId::Equals(const char *s) const +DsdId::Equals(const char *s) const noexcept { assert(s != nullptr); assert(strlen(s) == sizeof(value)); @@ -48,44 +48,54 @@ } /** - * Skip the #input_stream to the specified offset. + * Skip the #InputStream to the specified offset. */ bool -dsdlib_skip_to(Decoder *decoder, InputStream &is, +dsdlib_skip_to(DecoderClient *client, InputStream &is, offset_type offset) { - if (is.IsSeekable()) - return is.LockSeek(offset, IgnoreError()); + if (is.IsSeekable()) { + try { + is.LockSeek(offset); + } catch (const std::runtime_error &) { + return false; + } + } if (is.GetOffset() > offset) return false; - return dsdlib_skip(decoder, is, offset - is.GetOffset()); + return dsdlib_skip(client, is, offset - is.GetOffset()); } /** - * Skip some bytes from the #input_stream. + * Skip some bytes from the #InputStream. */ bool -dsdlib_skip(Decoder *decoder, InputStream &is, +dsdlib_skip(DecoderClient *client, InputStream &is, offset_type delta) { if (delta == 0) return true; - if (is.IsSeekable()) - return is.LockSeek(is.GetOffset() + delta, IgnoreError()); + if (is.IsSeekable()) { + try { + is.LockSeek(is.GetOffset() + delta); + } catch (const std::runtime_error &) { + return false; + } + } if (delta > 1024 * 1024) /* don't skip more than one megabyte; it would be too expensive */ return false; - return decoder_skip(decoder, is, delta); + return decoder_skip(client, is, delta); } bool -dsdlib_valid_freq(uint32_t samplefreq) +dsdlib_valid_freq(uint32_t samplefreq) noexcept { switch (samplefreq) { case 2822400: /* DSD64, 64xFs, Fs = 44.100kHz */ @@ -103,31 +113,29 @@ } } -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG void dsdlib_tag_id3(InputStream &is, - const struct tag_handler *handler, - void *handler_ctx, int64_t tagoffset) + const TagHandler &handler, + void *handler_ctx, offset_type tagoffset) { - assert(tagoffset >= 0); - if (tagoffset == 0 || !is.KnownSize()) return; - if (!dsdlib_skip_to(nullptr, is, tagoffset)) - return; - /* Prevent broken files causing problems */ const auto size = is.GetSize(); - const auto offset = is.GetOffset(); - if (offset >= size) + if (tagoffset >= size) return; - const id3_length_t count = size - offset; + const auto count64 = size - tagoffset; + if (count64 < 10 || count64 > 1024 * 1024) + return; - if (count < 10 || count > 1024 * 1024) + if (!dsdlib_skip_to(nullptr, is, tagoffset)) return; + const id3_length_t count = count64; + id3_byte_t *const id3_buf = new id3_byte_t[count]; if (id3_buf == nullptr) return; diff -Nru mpd-0.19.21/src/decoder/plugins/DsdLib.hxx mpd-0.20.9/src/decoder/plugins/DsdLib.hxx --- mpd-0.19.21/src/decoder/plugins/DsdLib.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsdLib.hxx 2017-05-08 14:56:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,17 +24,17 @@ #include "input/Offset.hxx" #include "Compiler.h" -#include #include -struct Decoder; +struct TagHandler; +class DecoderClient; class InputStream; struct DsdId { char value[4]; gcc_pure - bool Equals(const char *s) const; + bool Equals(const char *s) const noexcept; }; class DsdUint64 { @@ -60,11 +60,11 @@ }; bool -dsdlib_skip_to(Decoder *decoder, InputStream &is, +dsdlib_skip_to(DecoderClient *client, InputStream &is, offset_type offset); bool -dsdlib_skip(Decoder *decoder, InputStream &is, +dsdlib_skip(DecoderClient *client, InputStream &is, offset_type delta); /** @@ -72,7 +72,7 @@ **/ gcc_const bool -dsdlib_valid_freq(uint32_t samplefreq); +dsdlib_valid_freq(uint32_t samplefreq) noexcept; /** * Add tags from ID3 tag. All tags commonly found in the ID3 tags of @@ -80,7 +80,7 @@ */ void dsdlib_tag_id3(InputStream &is, - const struct tag_handler *handler, - void *handler_ctx, int64_t tagoffset); + const TagHandler &handler, + void *handler_ctx, offset_type tagoffset); #endif diff -Nru mpd-0.19.21/src/decoder/plugins/DsfDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/DsfDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/DsfDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsfDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -33,7 +33,6 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "util/bit_reverse.h" -#include "util/Error.hxx" #include "system/ByteOrder.hxx" #include "DsdLib.hxx" #include "tag/TagHandler.hxx" @@ -47,7 +46,7 @@ unsigned sample_rate, channels; bool bitreverse; offset_type n_blocks; -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG offset_type id3_offset; #endif }; @@ -99,11 +98,11 @@ * Read and parse all needed metadata chunks for DSF files. */ static bool -dsf_read_metadata(Decoder *decoder, InputStream &is, +dsf_read_metadata(DecoderClient *client, InputStream &is, DsfMetaData *metadata) { DsfHeader dsf_header; - if (!decoder_read_full(decoder, is, &dsf_header, sizeof(dsf_header)) || + if (!decoder_read_full(client, is, &dsf_header, sizeof(dsf_header)) || !dsf_header.id.Equals("DSD ")) return false; @@ -111,13 +110,13 @@ if (sizeof(dsf_header) != chunk_size) return false; -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG const offset_type metadata_offset = dsf_header.pmeta.Read(); #endif /* read the 'fmt ' chunk of the DSF file */ DsfFmtChunk dsf_fmt_chunk; - if (!decoder_read_full(decoder, is, + if (!decoder_read_full(client, is, &dsf_fmt_chunk, sizeof(dsf_fmt_chunk)) || !dsf_fmt_chunk.id.Equals("fmt ")) return false; @@ -145,7 +144,7 @@ /* read the 'data' chunk of the DSF file */ DsfDataChunk data_chunk; - if (!decoder_read_full(decoder, is, &data_chunk, sizeof(data_chunk)) || + if (!decoder_read_full(client, is, &data_chunk, sizeof(data_chunk)) || !data_chunk.id.Equals("data")) return false; @@ -174,7 +173,7 @@ metadata->n_blocks = data_size / block_size; metadata->channels = channels; metadata->sample_rate = samplefreq; -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG metadata->id3_offset = metadata_offset; #endif /* check bits per sample format, determine if bitreverse is needed */ @@ -252,7 +251,7 @@ * Decode one complete DSF 'data' chunk i.e. a complete song */ static bool -dsf_decode_chunk(Decoder &decoder, InputStream &is, +dsf_decode_chunk(DecoderClient &client, InputStream &is, unsigned channels, unsigned sample_rate, offset_type n_blocks, bool bitreverse) @@ -260,28 +259,28 @@ const size_t block_size = channels * DSF_BLOCK_SIZE; const offset_type start_offset = is.GetOffset(); - auto cmd = decoder_get_command(decoder); + auto cmd = client.GetCommand(); for (offset_type i = 0; i < n_blocks && cmd != DecoderCommand::STOP;) { if (cmd == DecoderCommand::SEEK) { - uint64_t frame = decoder_seek_where_frame(decoder); + uint64_t frame = client.GetSeekFrame(); offset_type block = FrameToBlock(frame); if (block >= n_blocks) { - decoder_command_finished(decoder); + client.CommandFinished(); break; } offset_type offset = start_offset + block * block_size; - if (dsdlib_skip_to(&decoder, is, offset)) { - decoder_command_finished(decoder); + if (dsdlib_skip_to(&client, is, offset)) { + client.CommandFinished(); i = block; } else - decoder_seek_error(decoder); + client.SeekError(); } /* worst-case buffer size */ uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE]; - if (!decoder_read_full(&decoder, is, buffer, block_size)) + if (!decoder_read_full(&client, is, buffer, block_size)) return false; if (bitreverse) @@ -290,9 +289,9 @@ uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE]; InterleaveDsfBlock(interleaved_buffer, buffer, channels); - cmd = decoder_data(decoder, is, - interleaved_buffer, block_size, - sample_rate / 1000); + cmd = client.SubmitData(is, + interleaved_buffer, block_size, + sample_rate / 1000); ++i; } @@ -300,30 +299,26 @@ } static void -dsf_stream_decode(Decoder &decoder, InputStream &is) +dsf_stream_decode(DecoderClient &client, InputStream &is) { /* check if it is a proper DSF file */ DsfMetaData metadata; - if (!dsf_read_metadata(&decoder, is, &metadata)) + if (!dsf_read_metadata(&client, is, &metadata)) return; - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, - SampleFormat::DSD, - metadata.channels, error)) { - LogError(error); - return; - } + auto audio_format = CheckAudioFormat(metadata.sample_rate / 8, + SampleFormat::DSD, + metadata.channels); + /* Calculate song time from DSD chunk size and sample frequency */ const auto n_blocks = metadata.n_blocks; auto songtime = SongTime::FromScale(n_blocks * DSF_BLOCK_SIZE, audio_format.sample_rate); /* success: file was recognized */ - decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime); + client.Ready(audio_format, is.IsSeekable(), songtime); - dsf_decode_chunk(decoder, is, metadata.channels, + dsf_decode_chunk(client, is, metadata.channels, metadata.sample_rate, n_blocks, metadata.bitreverse); @@ -331,7 +326,7 @@ static bool dsf_scan_stream(InputStream &is, - gcc_unused const struct tag_handler *handler, + gcc_unused const TagHandler &handler, gcc_unused void *handler_ctx) { /* check DSF metadata */ @@ -339,12 +334,9 @@ if (!dsf_read_metadata(nullptr, is, &metadata)) return false; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, - SampleFormat::DSD, - metadata.channels, IgnoreError())) - /* refuse to parse files which we cannot play anyway */ - return false; + auto audio_format = CheckAudioFormat(metadata.sample_rate / 8, + SampleFormat::DSD, + metadata.channels); /* calculate song time and add as tag */ const auto n_blocks = metadata.n_blocks; @@ -352,7 +344,7 @@ audio_format.sample_rate); tag_handler_invoke_duration(handler, handler_ctx, songtime); -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG /* Add available tags from the ID3 tag */ dsdlib_tag_id3(is, handler, handler_ctx, metadata.id3_offset); #endif diff -Nru mpd-0.19.21/src/decoder/plugins/DsfDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/DsfDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/DsfDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/DsfDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FaadDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/FaadDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/FaadDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FaadDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,16 +24,17 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "tag/TagHandler.hxx" +#include "util/ScopeExit.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include +#include + #include #include -#include static const unsigned adts_sample_rates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, @@ -193,7 +194,10 @@ auto song_length = adts_song_duration(buffer); - is.LockSeek(tagsize, IgnoreError()); + try { + is.LockSeek(tagsize); + } catch (const std::runtime_error &) { + } buffer.Clear(); @@ -243,16 +247,16 @@ /** * Wrapper for NeAACDecInit() which works around some API * inconsistencies in libfaad. + * + * Throws #std::runtime_error on error. */ -static bool +static void faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer &buffer, - AudioFormat &audio_format, Error &error) + AudioFormat &audio_format) { auto data = ConstBuffer::FromVoid(buffer.Read()); - if (data.IsEmpty()) { - error.Set(faad_decoder_domain, "Empty file"); - return false; - } + if (data.IsEmpty()) + throw std::runtime_error("Empty file"); uint8_t channels; unsigned long sample_rate; @@ -261,15 +265,13 @@ const_cast(data.data), data.size, &sample_rate, &channels); - if (nbytes < 0) { - error.Set(faad_decoder_domain, "Not an AAC stream"); - return false; - } + if (nbytes < 0) + throw std::runtime_error("Not an AAC stream"); buffer.Consume(nbytes); - return audio_format_init_checked(audio_format, sample_rate, - SampleFormat::S16, channels, error); + audio_format = CheckAudioFormat(sample_rate, SampleFormat::S16, + channels); } /** @@ -306,22 +308,23 @@ if (!recognized) { NeAACDecHandle decoder = faad_decoder_new(); + AtScopeExit(decoder) { NeAACDecClose(decoder); }; buffer.Fill(); AudioFormat audio_format; - if (faad_decoder_init(decoder, buffer, audio_format, - IgnoreError())) + try { + faad_decoder_init(decoder, buffer, audio_format); recognized = true; - - NeAACDecClose(decoder); + } catch (const std::runtime_error &e) { + } } return std::make_pair(recognized, duration); } static void -faad_stream_decode(Decoder &mpd_decoder, InputStream &is, +faad_stream_decode(DecoderClient &client, InputStream &is, DecoderBuffer &buffer, const NeAACDecHandle decoder) { const auto total_time = faad_song_duration(buffer, is); @@ -331,16 +334,12 @@ /* initialize it */ - Error error; AudioFormat audio_format; - if (!faad_decoder_init(decoder, buffer, audio_format, error)) { - LogError(error); - return; - } + faad_decoder_init(decoder, buffer, audio_format); /* initialize the MPD core */ - decoder_initialized(mpd_decoder, audio_format, false, total_time); + client.Ready(audio_format, false, total_time); /* the decoder loop */ @@ -394,32 +393,29 @@ /* send PCM samples to MPD */ - cmd = decoder_data(mpd_decoder, is, decoded, - (size_t)frame_info.samples * 2, - bit_rate); + cmd = client.SubmitData(is, decoded, + (size_t)frame_info.samples * 2, + bit_rate); } while (cmd != DecoderCommand::STOP); } static void -faad_stream_decode(Decoder &mpd_decoder, InputStream &is) +faad_stream_decode(DecoderClient &client, InputStream &is) { - DecoderBuffer buffer(&mpd_decoder, is, + DecoderBuffer buffer(&client, is, FAAD_MIN_STREAMSIZE * MAX_CHANNELS); /* create the libfaad decoder */ const NeAACDecHandle decoder = faad_decoder_new(); + AtScopeExit(decoder) { NeAACDecClose(decoder); }; - faad_stream_decode(mpd_decoder, is, buffer, decoder); - - /* cleanup */ - - NeAACDecClose(decoder); + faad_stream_decode(client, is, buffer, decoder); } static bool faad_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { auto result = faad_get_file_time(is); if (!result.first) diff -Nru mpd-0.19.21/src/decoder/plugins/FaadDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/FaadDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/FaadDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FaadDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/FfmpegDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/FfmpegDecoderPlugin.cxx 2016-12-13 07:32:47.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegDecoderPlugin.cxx 2017-06-03 18:57:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,12 +32,14 @@ #include "FfmpegMetaData.hxx" #include "FfmpegIo.hxx" #include "pcm/Interleave.hxx" +#include "tag/TagBuilder.hxx" #include "tag/TagHandler.hxx" +#include "tag/ReplayGain.hxx" +#include "tag/MixRamp.hxx" #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "util/ScopeExit.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "LogV.hxx" extern "C" { @@ -45,7 +47,6 @@ #include #include #include -#include #if LIBAVUTIL_VERSION_MAJOR >= 53 #include @@ -55,48 +56,70 @@ #include #include +/** + * Muxer options to be passed to avformat_open_input(). + */ +static AVDictionary *avformat_options = nullptr; + static AVFormatContext * FfmpegOpenInput(AVIOContext *pb, const char *filename, - AVInputFormat *fmt, - Error &error) + AVInputFormat *fmt) { AVFormatContext *context = avformat_alloc_context(); - if (context == nullptr) { - error.Set(ffmpeg_domain, "Out of memory"); - return nullptr; - } + if (context == nullptr) + throw std::runtime_error("avformat_alloc_context() failed"); context->pb = pb; - int err = avformat_open_input(&context, filename, fmt, nullptr); - if (err < 0) { - SetFfmpegError(error, err, "avformat_open_input() failed"); - return nullptr; - } + AVDictionary *options = nullptr; + AtScopeExit(&options) { av_dict_free(&options); }; + av_dict_copy(&options, avformat_options, 0); + + int err = avformat_open_input(&context, filename, fmt, &options); + if (err < 0) + throw MakeFfmpegError(err, "avformat_open_input() failed"); return context; } static bool -ffmpeg_init(gcc_unused const config_param ¶m) +ffmpeg_init(const ConfigBlock &block) { FfmpegInit(); + + static constexpr const char *option_names[] = { + "probesize", + "analyzeduration", + }; + + for (const char *name : option_names) { + const char *value = block.GetBlockValue(name); + if (value != nullptr) + av_dict_set(&avformat_options, name, value, 0); + } + return true; } +static void +ffmpeg_finish() +{ + av_dict_free(&avformat_options); +} + #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 25, 0) /* FFmpeg 3.1 */ gcc_pure static const AVCodecParameters & -GetCodecParameters(const AVStream &stream) +GetCodecParameters(const AVStream &stream) noexcept { return *stream.codecpar; } gcc_pure static AVSampleFormat -GetSampleFormat(const AVCodecParameters &codec_params) +GetSampleFormat(const AVCodecParameters &codec_params) noexcept { return AVSampleFormat(codec_params.format); } @@ -105,14 +128,14 @@ gcc_pure static const AVCodecContext & -GetCodecParameters(const AVStream &stream) +GetCodecParameters(const AVStream &stream) noexcept { return *stream.codec; } gcc_pure static AVSampleFormat -GetSampleFormat(const AVCodecContext &codec_context) +GetSampleFormat(const AVCodecContext &codec_context) noexcept { return codec_context.sample_fmt; } @@ -121,14 +144,14 @@ gcc_pure static bool -IsAudio(const AVStream &stream) +IsAudio(const AVStream &stream) noexcept { return GetCodecParameters(stream).codec_type == AVMEDIA_TYPE_AUDIO; } gcc_pure static int -ffmpeg_find_audio_stream(const AVFormatContext &format_context) +ffmpeg_find_audio_stream(const AVFormatContext &format_context) noexcept { for (unsigned i = 0; i < format_context.nb_streams; ++i) if (IsAudio(*format_context.streams[i])) @@ -151,12 +174,13 @@ /** * Copy PCM data from a non-empty AVFrame to an interleaved buffer. + * + * Throws #std::exception on error. */ static ConstBuffer copy_interleave_frame(const AVCodecContext &codec_context, const AVFrame &frame, - FfmpegBuffer &global_buffer, - Error &error) + FfmpegBuffer &global_buffer) { assert(frame.nb_samples > 0); @@ -167,20 +191,16 @@ frame.nb_samples, codec_context.sample_fmt, 1); assert(data_size != 0); - if (data_size < 0) { - SetFfmpegError(error, data_size); - return 0; - } + if (data_size < 0) + throw MakeFfmpegError(data_size); void *output_buffer; if (av_sample_fmt_is_planar(codec_context.sample_fmt) && codec_context.channels > 1) { output_buffer = global_buffer.GetT(data_size); - if (output_buffer == nullptr) { + if (output_buffer == nullptr) /* Not enough memory - shouldn't happen */ - error.SetErrno(ENOMEM); - return 0; - } + throw std::bad_alloc(); PcmInterleave(output_buffer, ConstBuffer((const void *const*)frame.extended_data, @@ -200,7 +220,7 @@ */ gcc_pure static int64_t -StreamRelativePts(const AVPacket &packet, const AVStream &stream) +StreamRelativePts(const AVPacket &packet, const AVStream &stream) noexcept { auto pts = packet.pts; if (pts < 0 || pts == int64_t(AV_NOPTS_VALUE)) @@ -217,28 +237,30 @@ gcc_pure static uint64_t PtsToPcmFrame(uint64_t pts, const AVStream &stream, - const AVCodecContext &codec_context) + const AVCodecContext &codec_context) noexcept { return av_rescale_q(pts, stream.time_base, codec_context.time_base); } /** - * Invoke decoder_data() with the contents of an #AVFrame. + * Invoke DecoderClient::SubmitData() with the contents of an + * #AVFrame. */ static DecoderCommand -FfmpegSendFrame(Decoder &decoder, InputStream &is, +FfmpegSendFrame(DecoderClient &client, InputStream &is, AVCodecContext &codec_context, const AVFrame &frame, size_t &skip_bytes, FfmpegBuffer &buffer) { - Error error; - auto output_buffer = - copy_interleave_frame(codec_context, frame, - buffer, error); - if (output_buffer.IsNull()) { + ConstBuffer output_buffer; + + try { + output_buffer = copy_interleave_frame(codec_context, frame, + buffer); + } catch (const std::exception e) { /* this must be a serious error, e.g. OOM */ - LogError(error); + LogError(e); return DecoderCommand::STOP; } @@ -254,15 +276,15 @@ skip_bytes = 0; } - return decoder_data(decoder, is, - output_buffer.data, output_buffer.size, - codec_context.bit_rate / 1000); + return client.SubmitData(is, + output_buffer.data, output_buffer.size, + codec_context.bit_rate / 1000); } #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0) static DecoderCommand -FfmpegReceiveFrames(Decoder &decoder, InputStream &is, +FfmpegReceiveFrames(DecoderClient &client, InputStream &is, AVCodecContext &codec_context, AVFrame &frame, size_t &skip_bytes, @@ -275,7 +297,7 @@ int err = avcodec_receive_frame(&codec_context, &frame); switch (err) { case 0: - cmd = FfmpegSendFrame(decoder, is, codec_context, + cmd = FfmpegSendFrame(client, is, codec_context, frame, skip_bytes, buffer); if (cmd != DecoderCommand::NONE) @@ -316,7 +338,7 @@ * desired time stamp has been reached */ static DecoderCommand -ffmpeg_send_packet(Decoder &decoder, InputStream &is, +ffmpeg_send_packet(DecoderClient &client, InputStream &is, AVPacket &&packet, AVCodecContext &codec_context, const AVStream &stream, @@ -334,9 +356,8 @@ if (cur_frame < min_frame) skip_bytes = pcm_frame_size * (min_frame - cur_frame); } else - decoder_timestamp(decoder, - FfmpegTimeToDouble(pts, - stream.time_base)); + client.SubmitTimestamp(FfmpegTimeToDouble(pts, + stream.time_base)); } #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0) @@ -362,7 +383,7 @@ return DecoderCommand::NONE; } - auto cmd = FfmpegReceiveFrames(decoder, is, codec_context, + auto cmd = FfmpegReceiveFrames(client, is, codec_context, frame, skip_bytes, buffer, eof); @@ -387,7 +408,7 @@ if (!got_frame || frame.nb_samples <= 0) continue; - cmd = FfmpegSendFrame(decoder, is, codec_context, + cmd = FfmpegSendFrame(client, is, codec_context, frame, skip_bytes, buffer); } @@ -397,7 +418,7 @@ } static DecoderCommand -ffmpeg_send_packet(Decoder &decoder, InputStream &is, +ffmpeg_send_packet(DecoderClient &client, InputStream &is, const AVPacket &packet, AVCodecContext &codec_context, const AVStream &stream, @@ -405,7 +426,7 @@ uint64_t min_frame, size_t pcm_frame_size, FfmpegBuffer &buffer) { - return ffmpeg_send_packet(decoder, is, + return ffmpeg_send_packet(client, is, /* copy the AVPacket, because FFmpeg < 3.0 requires this */ AVPacket(packet), @@ -416,7 +437,7 @@ gcc_const static SampleFormat -ffmpeg_sample_format(enum AVSampleFormat sample_fmt) +ffmpeg_sample_format(enum AVSampleFormat sample_fmt) noexcept { switch (sample_fmt) { case AV_SAMPLE_FMT_S16: @@ -450,16 +471,22 @@ } static AVInputFormat * -ffmpeg_probe(Decoder *decoder, InputStream &is) +ffmpeg_probe(DecoderClient *client, InputStream &is) { constexpr size_t BUFFER_SIZE = 16384; constexpr size_t PADDING = 16; unsigned char buffer[BUFFER_SIZE]; - size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE); - if (nbytes <= PADDING || !is.LockRewind(IgnoreError())) + size_t nbytes = decoder_read(client, is, buffer, BUFFER_SIZE); + if (nbytes <= PADDING) return nullptr; + try { + is.LockRewind(); + } catch (const std::runtime_error &) { + return nullptr; + } + /* some ffmpeg parsers (e.g. ac3_parser.c) read a few bytes beyond the declared buffer limit, which makes valgrind angry; this workaround removes some padding from the buffer @@ -493,7 +520,111 @@ } static void -FfmpegDecode(Decoder &decoder, InputStream &input, +FfmpegParseMetaData(AVDictionary &dict, ReplayGainInfo &rg, MixRampInfo &mr) +{ + AVDictionaryEntry *i = nullptr; + + while ((i = av_dict_get(&dict, "", i, + AV_DICT_IGNORE_SUFFIX)) != nullptr) { + const char *name = i->key; + const char *value = i->value; + + if (!ParseReplayGainTag(rg, name, value)) + ParseMixRampTag(mr, name, value); + } +} + +static void +FfmpegParseMetaData(const AVStream &stream, + ReplayGainInfo &rg, MixRampInfo &mr) +{ + FfmpegParseMetaData(*stream.metadata, rg, mr); +} + +static void +FfmpegParseMetaData(const AVFormatContext &format_context, int audio_stream, + ReplayGainInfo &rg, MixRampInfo &mr) +{ + assert(audio_stream >= 0); + + FfmpegParseMetaData(*format_context.metadata, rg, mr); + FfmpegParseMetaData(*format_context.streams[audio_stream], + rg, mr); +} + +static void +FfmpegParseMetaData(DecoderClient &client, + const AVFormatContext &format_context, int audio_stream) +{ + ReplayGainInfo rg; + rg.Clear(); + + MixRampInfo mr; + mr.Clear(); + + FfmpegParseMetaData(format_context, audio_stream, rg, mr); + + if (rg.IsDefined()) + client.SubmitReplayGain(&rg); + + if (mr.IsDefined()) + client.SubmitMixRamp(std::move(mr)); +} + +static void +FfmpegScanMetadata(const AVStream &stream, + const TagHandler &handler, void *handler_ctx) +{ + FfmpegScanDictionary(stream.metadata, handler, handler_ctx); +} + +static void +FfmpegScanMetadata(const AVFormatContext &format_context, int audio_stream, + const TagHandler &handler, void *handler_ctx) +{ + assert(audio_stream >= 0); + + FfmpegScanDictionary(format_context.metadata, handler, handler_ctx); + FfmpegScanMetadata(*format_context.streams[audio_stream], + handler, handler_ctx); +} + +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0) + +static void +FfmpegScanTag(const AVFormatContext &format_context, int audio_stream, + TagBuilder &tag) +{ + FfmpegScanMetadata(format_context, audio_stream, + full_tag_handler, &tag); +} + +/** + * Check if a new stream tag was received and pass it to + * DecoderClient::SubmitTag(). + */ +static void +FfmpegCheckTag(DecoderClient &client, InputStream &is, + AVFormatContext &format_context, int audio_stream) +{ + AVStream &stream = *format_context.streams[audio_stream]; + if ((stream.event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) == 0) + /* no new metadata */ + return; + + /* clear the flag */ + stream.event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED; + + TagBuilder tag; + FfmpegScanTag(format_context, audio_stream, tag); + if (!tag.IsEmpty()) + client.SubmitTag(is, tag.Commit()); +} + +#endif + +static void +FfmpegDecode(DecoderClient &client, InputStream &input, AVFormatContext &format_context) { const int find_result = @@ -559,15 +690,9 @@ return; } - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, - codec_params.sample_rate, - sample_format, - codec_params.channels, error)) { - LogError(error); - return; - } + const auto audio_format = CheckAudioFormat(codec_params.sample_rate, + sample_format, + codec_params.channels); /* the audio format must be read from AVCodecContext by now, because avcodec_open() has been demonstrated to fill bogus @@ -589,8 +714,9 @@ const SignedSongTime total_time = FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base); - decoder_initialized(decoder, audio_format, - input.IsSeekable(), total_time); + client.Ready(audio_format, input.IsSeekable(), total_time); + + FfmpegParseMetaData(client, format_context, audio_stream); #if LIBAVUTIL_VERSION_MAJOR >= 53 AVFrame *frame = av_frame_alloc(); @@ -616,11 +742,11 @@ uint64_t min_frame = 0; - DecoderCommand cmd = decoder_get_command(decoder); + DecoderCommand cmd = client.GetCommand(); while (cmd != DecoderCommand::STOP) { if (cmd == DecoderCommand::SEEK) { int64_t where = - ToFfmpegTime(decoder_seek_time(decoder), + ToFfmpegTime(client.GetSeekTime(), av_stream.time_base) + start_time_fallback(av_stream); @@ -629,11 +755,11 @@ stamp, not after */ if (av_seek_frame(&format_context, audio_stream, where, AVSEEK_FLAG_ANY|AVSEEK_FLAG_BACKWARD) < 0) - decoder_seek_error(decoder); + client.SeekError(); else { avcodec_flush_buffers(codec_context); - min_frame = decoder_seek_where_frame(decoder); - decoder_command_finished(decoder); + min_frame = client.GetSeekFrame(); + client.CommandFinished(); } } @@ -642,8 +768,12 @@ /* end of file */ break; +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0) + FfmpegCheckTag(client, input, format_context, audio_stream); +#endif + if (packet.size > 0 && packet.stream_index == audio_stream) { - cmd = ffmpeg_send_packet(decoder, input, + cmd = ffmpeg_send_packet(client, input, packet, *codec_context, av_stream, @@ -652,7 +782,7 @@ interleaved_buffer); min_frame = 0; } else - cmd = decoder_get_command(decoder); + cmd = client.GetCommand(); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 25, 100) av_packet_unref(&packet); @@ -663,26 +793,27 @@ } static void -ffmpeg_decode(Decoder &decoder, InputStream &input) +ffmpeg_decode(DecoderClient &client, InputStream &input) { - AVInputFormat *input_format = ffmpeg_probe(&decoder, input); + AVInputFormat *input_format = ffmpeg_probe(&client, input); if (input_format == nullptr) return; FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)", input_format->name, input_format->long_name); - AvioStream stream(&decoder, input); + AvioStream stream(&client, input); if (!stream.Open()) { LogError(ffmpeg_domain, "Failed to open stream"); return; } - Error error; - AVFormatContext *format_context = - FfmpegOpenInput(stream.io, input.GetURI(), input_format, error); - if (format_context == nullptr) { - LogError(error); + AVFormatContext *format_context; + try { + format_context =FfmpegOpenInput(stream.io, input.GetURI(), + input_format); + } catch (const std::runtime_error &e) { + LogError(e); return; } @@ -690,37 +821,36 @@ avformat_close_input(&format_context); }; - FfmpegDecode(decoder, input, *format_context); + FfmpegDecode(client, input, *format_context); } static bool FfmpegScanStream(AVFormatContext &format_context, - const struct tag_handler &handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const int find_result = avformat_find_stream_info(&format_context, nullptr); if (find_result < 0) return false; - if (format_context.duration != (int64_t)AV_NOPTS_VALUE) { - const auto duration = - SongTime::FromScale(format_context.duration, - AV_TIME_BASE); - tag_handler_invoke_duration(&handler, handler_ctx, duration); - } + const int audio_stream = ffmpeg_find_audio_stream(format_context); + if (audio_stream < 0) + return false; + + const AVStream &stream = *format_context.streams[audio_stream]; + if (stream.duration != (int64_t)AV_NOPTS_VALUE) + tag_handler_invoke_duration(handler, handler_ctx, + FromFfmpegTime(stream.duration, + stream.time_base)); - FfmpegScanDictionary(format_context.metadata, &handler, handler_ctx); - int idx = ffmpeg_find_audio_stream(format_context); - if (idx >= 0) - FfmpegScanDictionary(format_context.streams[idx]->metadata, - &handler, handler_ctx); + FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx); return true; } static bool ffmpeg_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { AVInputFormat *input_format = ffmpeg_probe(nullptr, is); if (input_format == nullptr) @@ -730,17 +860,18 @@ if (!stream.Open()) return false; - AVFormatContext *f = - FfmpegOpenInput(stream.io, is.GetURI(), input_format, - IgnoreError()); - if (f == nullptr) + AVFormatContext *f; + try { + f = FfmpegOpenInput(stream.io, is.GetURI(), input_format); + } catch (const std::runtime_error &) { return false; + } AtScopeExit(&f) { avformat_close_input(&f); }; - return FfmpegScanStream(*f, *handler, handler_ctx); + return FfmpegScanStream(*f, handler, handler_ctx); } /** @@ -750,7 +881,8 @@ * more formats. */ static const char *const ffmpeg_suffixes[] = { - "16sv", "3g2", "3gp", "4xm", "8svx", "aa3", "aac", "ac3", "afc", "aif", + "16sv", "3g2", "3gp", "4xm", "8svx", + "aa3", "aac", "ac3", "adx", "afc", "aif", "aifc", "aiff", "al", "alaw", "amr", "anim", "apc", "ape", "asf", "atrac", "au", "aud", "avi", "avm2", "avs", "bap", "bfi", "c93", "cak", "cin", "cmv", "cpk", "daud", "dct", "divx", "dts", "dv", "dvd", "dxa", @@ -803,6 +935,7 @@ "audio/x-16sv", "audio/x-aac", "audio/x-ac3", + "audio/x-adx", "audio/x-aiff" "audio/x-alaw", "audio/x-au", @@ -863,7 +996,7 @@ const struct DecoderPlugin ffmpeg_decoder_plugin = { "ffmpeg", ffmpeg_init, - nullptr, + ffmpeg_finish, ffmpeg_decode, nullptr, nullptr, diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/FfmpegDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/FfmpegDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegIo.cxx mpd-0.20.9/src/decoder/plugins/FfmpegIo.cxx --- mpd-0.19.21/src/decoder/plugins/FfmpegIo.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegIo.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2016 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,8 @@ #include "FfmpegIo.hxx" #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" -#include "util/Error.hxx" + +#include AvioStream::~AvioStream() { @@ -34,49 +35,62 @@ } } -static int -mpd_ffmpeg_stream_read(void *opaque, uint8_t *buf, int size) +inline int +AvioStream::Read(void *dest, int size) { - AvioStream *stream = (AvioStream *)opaque; - - return decoder_read(stream->decoder, stream->input, - (void *)buf, size); + return decoder_read(client, input, dest, size); } -static int64_t -mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence) +inline int64_t +AvioStream::Seek(int64_t pos, int whence) { - AvioStream *stream = (AvioStream *)opaque; - switch (whence) { case SEEK_SET: break; case SEEK_CUR: - pos += stream->input.GetOffset(); + pos += input.GetOffset(); break; case SEEK_END: - if (!stream->input.KnownSize()) + if (!input.KnownSize()) return -1; - pos += stream->input.GetSize(); + pos += input.GetSize(); break; case AVSEEK_SIZE: - if (!stream->input.KnownSize()) + if (!input.KnownSize()) return -1; - return stream->input.GetSize(); + return input.GetSize(); default: return -1; } - if (!stream->input.LockSeek(pos, IgnoreError())) + try { + input.LockSeek(pos); + return input.GetOffset(); + } catch (const std::runtime_error &) { return -1; + } +} + +int +AvioStream::_Read(void *opaque, uint8_t *buf, int size) +{ + AvioStream &stream = *(AvioStream *)opaque; + + return stream.Read(buf, size); +} + +int64_t +AvioStream::_Seek(void *opaque, int64_t pos, int whence) +{ + AvioStream &stream = *(AvioStream *)opaque; - return stream->input.GetOffset(); + return stream.Seek(pos, whence); } bool @@ -89,9 +103,8 @@ io = avio_alloc_context(buffer, BUFFER_SIZE, false, this, - mpd_ffmpeg_stream_read, nullptr, - input.IsSeekable() - ? mpd_ffmpeg_stream_seek : nullptr); + _Read, nullptr, + input.IsSeekable() ? _Seek : nullptr); /* If avio_alloc_context() fails, who frees the buffer? The libavformat API documentation does not specify this, it only says that AVIOContext.buffer must be freed in the end, diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegIo.hxx mpd-0.20.9/src/decoder/plugins/FfmpegIo.hxx --- mpd-0.19.21/src/decoder/plugins/FfmpegIo.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegIo.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2016 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,21 +28,28 @@ #include +class DecoderClient; class InputStream; -struct Decoder; struct AvioStream { - Decoder *const decoder; + DecoderClient *const client; InputStream &input; AVIOContext *io; - AvioStream(Decoder *_decoder, InputStream &_input) - :decoder(_decoder), input(_input), io(nullptr) {} + AvioStream(DecoderClient *_client, InputStream &_input) + :client(_client), input(_input), io(nullptr) {} ~AvioStream(); bool Open(); + +private: + int Read(void *buffer, int size); + int64_t Seek(int64_t pos, int whence); + + static int _Read(void *opaque, uint8_t *buf, int size); + static int64_t _Seek(void *opaque, int64_t pos, int whence); }; #endif diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegMetaData.cxx mpd-0.20.9/src/decoder/plugins/FfmpegMetaData.cxx --- mpd-0.19.21/src/decoder/plugins/FfmpegMetaData.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegMetaData.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,11 @@ #include "tag/TagTable.hxx" #include "tag/TagHandler.hxx" -static const struct tag_table ffmpeg_tags[] = { +extern "C" { +#include +} + +static constexpr struct tag_table ffmpeg_tags[] = { { "year", TAG_DATE }, { "author-sort", TAG_ARTIST_SORT }, { "album_artist", TAG_ALBUM_ARTIST }, @@ -38,7 +42,7 @@ static void FfmpegScanTag(TagType type, AVDictionary *m, const char *name, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { AVDictionaryEntry *mt = nullptr; @@ -49,7 +53,7 @@ static void FfmpegScanPairs(AVDictionary *dict, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { AVDictionaryEntry *i = nullptr; @@ -60,9 +64,9 @@ void FfmpegScanDictionary(AVDictionary *dict, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { - if (handler->tag != nullptr) { + if (handler.tag != nullptr) { for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) FfmpegScanTag(TagType(i), dict, tag_item_names[i], handler, handler_ctx); @@ -73,6 +77,6 @@ handler, handler_ctx); } - if (handler->pair != nullptr) + if (handler.pair != nullptr) FfmpegScanPairs(dict, handler, handler_ctx); } diff -Nru mpd-0.19.21/src/decoder/plugins/FfmpegMetaData.hxx mpd-0.20.9/src/decoder/plugins/FfmpegMetaData.hxx --- mpd-0.19.21/src/decoder/plugins/FfmpegMetaData.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FfmpegMetaData.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,19 +20,11 @@ #ifndef MPD_FFMPEG_METADATA_HXX #define MPD_FFMPEG_METADATA_HXX -extern "C" { -#include -} - -/* suppress the ffmpeg compatibility macro */ -#ifdef SampleFormat -#undef SampleFormat -#endif - -struct tag_handler; +struct AVDictionary; +struct TagHandler; void FfmpegScanDictionary(AVDictionary *dict, - const tag_handler *handler, void *handler_ctx); + const TagHandler &handler, void *handler_ctx); #endif diff -Nru mpd-0.19.21/src/decoder/plugins/FlacCommon.cxx mpd-0.20.9/src/decoder/plugins/FlacCommon.cxx --- mpd-0.19.21/src/decoder/plugins/FlacCommon.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacCommon.cxx 2017-03-29 19:22:00.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,107 +24,79 @@ #include "config.h" #include "FlacCommon.hxx" #include "FlacMetadata.hxx" -#include "FlacPcm.hxx" -#include "CheckAudioFormat.hxx" -#include "util/Error.hxx" +#include "util/ConstBuffer.hxx" #include "Log.hxx" -flac_data::flac_data(Decoder &_decoder, - InputStream &_input_stream) - :FlacInput(_input_stream, &_decoder), - initialized(false), unsupported(false), - position(0), - decoder(_decoder), input_stream(_input_stream) -{ -} - -static SampleFormat -flac_sample_format(unsigned bits_per_sample) -{ - switch (bits_per_sample) { - case 8: - return SampleFormat::S8; - - case 16: - return SampleFormat::S16; - - case 24: - return SampleFormat::S24_P32; - - case 32: - return SampleFormat::S32; - - default: - return SampleFormat::UNDEFINED; - } -} +#include bool -flac_data::Initialize(unsigned sample_rate, unsigned bits_per_sample, - unsigned channels, FLAC__uint64 total_frames) +FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample, + unsigned channels, FLAC__uint64 total_frames) { assert(!initialized); assert(!unsupported); - ::Error error; - if (!audio_format_init_checked(audio_format, - sample_rate, - flac_sample_format(bits_per_sample), - channels, error)) { - LogError(error); + try { + pcm_import.Open(sample_rate, bits_per_sample, + channels); + } catch (const std::runtime_error &e) { + LogError(e); unsupported = true; return false; } - frame_size = audio_format.GetFrameSize(); + const auto audio_format = pcm_import.GetAudioFormat(); const auto duration = total_frames > 0 ? SignedSongTime::FromScale(total_frames, audio_format.sample_rate) : SignedSongTime::Negative(); - decoder_initialized(decoder, audio_format, - input_stream.IsSeekable(), - duration); + GetClient()->Ready(audio_format, + GetInputStream().IsSeekable(), + duration); initialized = true; return true; } -static void -flac_got_stream_info(struct flac_data *data, - const FLAC__StreamMetadata_StreamInfo *stream_info) +inline void +FlacDecoder::OnStreamInfo(const FLAC__StreamMetadata_StreamInfo &stream_info) { - if (data->initialized || data->unsupported) + if (initialized) return; - data->Initialize(stream_info->sample_rate, - stream_info->bits_per_sample, - stream_info->channels, - stream_info->total_samples); + Initialize(stream_info.sample_rate, + stream_info.bits_per_sample, + stream_info.channels, + stream_info.total_samples); } -void flac_metadata_common_cb(const FLAC__StreamMetadata * block, - struct flac_data *data) +inline void +FlacDecoder::OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc) { - if (data->unsupported) - return; - ReplayGainInfo rgi; + if (flac_parse_replay_gain(rgi, vc)) + GetClient()->SubmitReplayGain(&rgi); - switch (block->type) { + GetClient()->SubmitMixRamp(flac_parse_mixramp(vc)); + + tag = flac_vorbis_comments_to_tag(&vc); +} + +void +FlacDecoder::OnMetadata(const FLAC__StreamMetadata &metadata) +{ + if (unsupported) + return; + + switch (metadata.type) { case FLAC__METADATA_TYPE_STREAMINFO: - flac_got_stream_info(data, &block->data.stream_info); + OnStreamInfo(metadata.data.stream_info); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: - if (flac_parse_replay_gain(rgi, block->data.vorbis_comment)) - decoder_replay_gain(data->decoder, &rgi); - - decoder_mixramp(data->decoder, - flac_parse_mixramp(block->data.vorbis_comment)); - - data->tag = flac_vorbis_comments_to_tag(&block->data.vorbis_comment); + OnVorbisComment(metadata.data.vorbis_comment); break; default: @@ -132,49 +104,53 @@ } } -/** - * This function attempts to call decoder_initialized() in case there - * was no STREAMINFO block. This is allowed for nonseekable streams, - * where the server sends us only a part of the file, without - * providing the STREAMINFO block from the beginning of the file - * (e.g. when seeking with SqueezeBox Server). - */ -static bool -flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header) +inline bool +FlacDecoder::OnFirstFrame(const FLAC__FrameHeader &header) { - if (data->unsupported) + if (unsupported) return false; - return data->Initialize(header->sample_rate, - header->bits_per_sample, - header->channels, - /* unknown duration */ - 0); + return Initialize(header.sample_rate, + header.bits_per_sample, + header.channels, + /* unknown duration */ + 0); +} + +FLAC__uint64 +FlacDecoder::GetDeltaPosition(const FLAC__StreamDecoder &sd) +{ + FLAC__uint64 nbytes; + if (!FLAC__stream_decoder_get_decode_position(&sd, &nbytes)) + return 0; + + if (position > 0 && nbytes > position) { + nbytes -= position; + position += nbytes; + } else { + position = nbytes; + nbytes = 0; + } + + return nbytes; } FLAC__StreamDecoderWriteStatus -flac_common_write(struct flac_data *data, const FLAC__Frame * frame, - const FLAC__int32 *const buf[], - FLAC__uint64 nbytes) +FlacDecoder::OnWrite(const FLAC__Frame &frame, + const FLAC__int32 *const buf[], + FLAC__uint64 nbytes) { - void *buffer; - - if (!data->initialized && !flac_got_first_frame(data, &frame->header)) + if (!initialized && !OnFirstFrame(frame.header)) return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - size_t buffer_size = frame->header.blocksize * data->frame_size; - buffer = data->buffer.Get(buffer_size); + const auto data = pcm_import.Import(buf, frame.header.blocksize); + + unsigned bit_rate = nbytes * 8 * frame.header.sample_rate / + (1000 * frame.header.blocksize); - flac_convert(buffer, frame->header.channels, - data->audio_format.format, buf, - 0, frame->header.blocksize); - - unsigned bit_rate = nbytes * 8 * frame->header.sample_rate / - (1000 * frame->header.blocksize); - - auto cmd = decoder_data(data->decoder, data->input_stream, - buffer, buffer_size, - bit_rate); + auto cmd = GetClient()->SubmitData(GetInputStream(), + data.data, data.size, + bit_rate); switch (cmd) { case DecoderCommand::NONE: case DecoderCommand::START: diff -Nru mpd-0.19.21/src/decoder/plugins/FlacCommon.hxx mpd-0.20.9/src/decoder/plugins/FlacCommon.hxx --- mpd-0.19.21/src/decoder/plugins/FlacCommon.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacCommon.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,61 +25,65 @@ #define MPD_FLAC_COMMON_HXX #include "FlacInput.hxx" +#include "FlacPcm.hxx" #include "../DecoderAPI.hxx" -#include "pcm/PcmBuffer.hxx" #include -struct flac_data : public FlacInput { - PcmBuffer buffer; - - /** - * The size of one frame in the output buffer. - */ - unsigned frame_size; - +struct FlacDecoder : public FlacInput { /** - * Has decoder_initialized() been called yet? + * Has DecoderClient::Ready() been called yet? */ - bool initialized; + bool initialized = false; /** * Does the FLAC file contain an unsupported audio format? */ - bool unsupported; + bool unsupported = false; - /** - * The validated audio format of the FLAC file. This - * attribute is defined if "initialized" is true. - */ - AudioFormat audio_format; + FlacPcmImport pcm_import; /** * End of last frame's position within the stream. This is * used for bit rate calculations. */ - FLAC__uint64 position; - - Decoder &decoder; - InputStream &input_stream; + FLAC__uint64 position = 0; Tag tag; - flac_data(Decoder &decoder, InputStream &input_stream); + FlacDecoder(DecoderClient &_client, InputStream &_input_stream) + :FlacInput(_input_stream, &_client) {} /** - * Wrapper for decoder_initialized(). + * Wrapper for DecoderClient::Ready(). */ bool Initialize(unsigned sample_rate, unsigned bits_per_sample, unsigned channels, FLAC__uint64 total_frames); -}; -void flac_metadata_common_cb(const FLAC__StreamMetadata * block, - struct flac_data *data); + void OnMetadata(const FLAC__StreamMetadata &metadata); -FLAC__StreamDecoderWriteStatus -flac_common_write(struct flac_data *data, const FLAC__Frame * frame, - const FLAC__int32 *const buf[], - FLAC__uint64 nbytes); + FLAC__StreamDecoderWriteStatus OnWrite(const FLAC__Frame &frame, + const FLAC__int32 *const buf[], + FLAC__uint64 nbytes); + + /** + * Calculate the delta (in bytes) between the last frame and + * the current frame. + */ + FLAC__uint64 GetDeltaPosition(const FLAC__StreamDecoder &sd); + +private: + void OnStreamInfo(const FLAC__StreamMetadata_StreamInfo &stream_info); + void OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc); + + /** + * This function attempts to call DecoderClient::Ready() in case there + * was no STREAMINFO block. This is allowed for nonseekable streams, + * where the server sends us only a part of the file, without + * providing the STREAMINFO block from the beginning of the file + * (e.g. when seeking with SqueezeBox Server). + */ + bool OnFirstFrame(const FLAC__FrameHeader &header); +}; #endif /* _FLAC_COMMON_H */ diff -Nru mpd-0.19.21/src/decoder/plugins/FlacDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/FlacDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/FlacDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacDecoderPlugin.cxx 2017-03-29 19:22:00.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,12 +19,13 @@ #include "config.h" /* must be first for large file support */ #include "FlacDecoderPlugin.h" +#include "FlacStreamDecoder.hxx" #include "FlacDomain.hxx" #include "FlacCommon.hxx" #include "FlacMetadata.hxx" #include "OggCodec.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" +#include "fs/NarrowPath.hxx" #include "Log.hxx" #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 @@ -55,36 +56,24 @@ static void flacMetadata(gcc_unused const FLAC__StreamDecoder * dec, const FLAC__StreamMetadata * block, void *vdata) { - flac_metadata_common_cb(block, (struct flac_data *) vdata); + auto &fd = *(FlacDecoder *)vdata; + fd.OnMetadata(*block); } static FLAC__StreamDecoderWriteStatus flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame, const FLAC__int32 *const buf[], void *vdata) { - struct flac_data *data = (struct flac_data *) vdata; - FLAC__uint64 nbytes = 0; - - if (FLAC__stream_decoder_get_decode_position(dec, &nbytes)) { - if (data->position > 0 && nbytes > data->position) { - nbytes -= data->position; - data->position += nbytes; - } else { - data->position = nbytes; - nbytes = 0; - } - } else - nbytes = 0; - - return flac_common_write(data, frame, buf, nbytes); + auto &fd = *(FlacDecoder *)vdata; + return fd.OnWrite(*frame, buf, fd.GetDeltaPosition(*dec)); } static bool flac_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { FlacMetadataChain chain; - if (!chain.Read(path_fs.c_str())) { + if (!chain.Read(NarrowPath(path_fs))) { FormatDebug(flac_domain, "Failed to read FLAC tags: %s", chain.GetStatusString()); @@ -97,7 +86,7 @@ static bool flac_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { FlacMetadataChain chain; if (!chain.Read(is)) { @@ -114,17 +103,11 @@ /** * Some glue code around FLAC__stream_decoder_new(). */ -static FLAC__StreamDecoder * +static FlacStreamDecoder flac_decoder_new(void) { - FLAC__StreamDecoder *sd = FLAC__stream_decoder_new(); - if (sd == nullptr) { - LogError(flac_domain, - "FLAC__stream_decoder_new() failed"); - return nullptr; - } - - if(!FLAC__stream_decoder_set_metadata_respond(sd, FLAC__METADATA_TYPE_VORBIS_COMMENT)) + FlacStreamDecoder sd; + if(!FLAC__stream_decoder_set_metadata_respond(sd.get(), FLAC__METADATA_TYPE_VORBIS_COMMENT)) LogDebug(flac_domain, "FLAC__stream_decoder_set_metadata_respond() has failed"); @@ -132,7 +115,7 @@ } static bool -flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd) +flac_decoder_initialize(FlacDecoder *data, FLAC__StreamDecoder *sd) { if (!FLAC__stream_decoder_process_until_end_of_metadata(sd)) { if (FLAC__stream_decoder_get_state(sd) != FLAC__STREAM_DECODER_END_OF_STREAM) @@ -145,7 +128,7 @@ return true; } - if (data->input_stream.IsSeekable()) + if (data->GetInputStream().IsSeekable()) /* allow the workaround below only for nonseekable streams*/ return false; @@ -157,27 +140,26 @@ } static void -flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec) +flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec) { - Decoder &decoder = data->decoder; + DecoderClient &client = *data->GetClient(); while (true) { DecoderCommand cmd; if (!data->tag.IsEmpty()) { - cmd = decoder_tag(data->decoder, data->input_stream, - std::move(data->tag)); + cmd = client.SubmitTag(data->GetInputStream(), + std::move(data->tag)); data->tag.Clear(); } else - cmd = decoder_get_command(decoder); + cmd = client.GetCommand(); if (cmd == DecoderCommand::SEEK) { - FLAC__uint64 seek_sample = - decoder_seek_where_frame(decoder); + FLAC__uint64 seek_sample = client.GetSeekFrame(); if (FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) { data->position = 0; - decoder_command_finished(decoder); + client.CommandFinished(); } else - decoder_seek_error(decoder); + client.SeekError(); } else if (cmd == DecoderCommand::STOP) break; @@ -215,7 +197,7 @@ } if (!FLAC__stream_decoder_process_single(flac_dec) && - decoder_get_command(decoder) == DecoderCommand::NONE) { + client.GetCommand() == DecoderCommand::NONE) { /* a failure that was not triggered by a decoder command */ flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec)); @@ -225,7 +207,7 @@ } static FLAC__StreamDecoderInitStatus -stream_init_oggflac(FLAC__StreamDecoder *flac_dec, struct flac_data *data) +stream_init_oggflac(FLAC__StreamDecoder *flac_dec, FlacDecoder *data) { return FLAC__stream_decoder_init_ogg_stream(flac_dec, FlacInput::Read, @@ -240,7 +222,7 @@ } static FLAC__StreamDecoderInitStatus -stream_init_flac(FLAC__StreamDecoder *flac_dec, struct flac_data *data) +stream_init_flac(FLAC__StreamDecoder *flac_dec, FlacDecoder *data) { return FLAC__stream_decoder_init_stream(flac_dec, FlacInput::Read, @@ -255,7 +237,7 @@ } static FLAC__StreamDecoderInitStatus -stream_init(FLAC__StreamDecoder *flac_dec, struct flac_data *data, bool is_ogg) +stream_init(FLAC__StreamDecoder *flac_dec, FlacDecoder *data, bool is_ogg) { return is_ogg ? stream_init_oggflac(flac_dec, data) @@ -263,7 +245,7 @@ } static bool -FlacInitAndDecode(struct flac_data &data, FLAC__StreamDecoder *sd, bool is_ogg) +FlacInitAndDecode(FlacDecoder &data, FLAC__StreamDecoder *sd, bool is_ogg) { auto init_status = stream_init(sd, &data, is_ogg); if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { @@ -281,41 +263,37 @@ } static void -flac_decode_internal(Decoder &decoder, +flac_decode_internal(DecoderClient &client, InputStream &input_stream, bool is_ogg) { - FLAC__StreamDecoder *flac_dec; - - flac_dec = flac_decoder_new(); - if (flac_dec == nullptr) + auto flac_dec = flac_decoder_new(); + if (!flac_dec) return; - struct flac_data data(decoder, input_stream); + FlacDecoder data(client, input_stream); - FlacInitAndDecode(data, flac_dec, is_ogg); - - FLAC__stream_decoder_delete(flac_dec); + FlacInitAndDecode(data, flac_dec.get(), is_ogg); } static void -flac_decode(Decoder &decoder, InputStream &input_stream) +flac_decode(DecoderClient &client, InputStream &input_stream) { - flac_decode_internal(decoder, input_stream, false); + flac_decode_internal(client, input_stream, false); } static bool -oggflac_init(gcc_unused const config_param ¶m) +oggflac_init(gcc_unused const ConfigBlock &block) { return !!FLAC_API_SUPPORTS_OGG_FLAC; } static bool oggflac_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { FlacMetadataChain chain; - if (!chain.ReadOgg(path_fs.c_str())) { + if (!chain.ReadOgg(NarrowPath(path_fs))) { FormatDebug(flac_domain, "Failed to read OggFLAC tags: %s", chain.GetStatusString()); @@ -328,7 +306,7 @@ static bool oggflac_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { FlacMetadataChain chain; if (!chain.ReadOgg(is)) { @@ -343,16 +321,19 @@ } static void -oggflac_decode(Decoder &decoder, InputStream &input_stream) +oggflac_decode(DecoderClient &client, InputStream &input_stream) { - if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_FLAC) + if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_FLAC) return; /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream.LockRewind(IgnoreError()); + try { + input_stream.LockRewind(); + } catch (const std::runtime_error &) { + } - flac_decode_internal(decoder, input_stream, true); + flac_decode_internal(client, input_stream, true); } static const char *const oggflac_suffixes[] = { "ogg", "oga", nullptr }; diff -Nru mpd-0.19.21/src/decoder/plugins/FlacDecoderPlugin.h mpd-0.20.9/src/decoder/plugins/FlacDecoderPlugin.h --- mpd-0.19.21/src/decoder/plugins/FlacDecoderPlugin.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacDecoderPlugin.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FlacDomain.cxx mpd-0.20.9/src/decoder/plugins/FlacDomain.cxx --- mpd-0.19.21/src/decoder/plugins/FlacDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FlacDomain.hxx mpd-0.20.9/src/decoder/plugins/FlacDomain.hxx --- mpd-0.19.21/src/decoder/plugins/FlacDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FlacInput.cxx mpd-0.20.9/src/decoder/plugins/FlacInput.cxx --- mpd-0.19.21/src/decoder/plugins/FlacInput.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacInput.cxx 2017-03-29 19:22:00.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,20 +22,21 @@ #include "FlacDomain.hxx" #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" -#include "util/Error.hxx" #include "Log.hxx" #include "Compiler.h" +#include + FLAC__StreamDecoderReadStatus FlacInput::Read(FLAC__byte buffer[], size_t *bytes) { - size_t r = decoder_read(decoder, input_stream, (void *)buffer, *bytes); + size_t r = decoder_read(client, input_stream, (void *)buffer, *bytes); *bytes = r; if (r == 0) { if (input_stream.LockIsEOF() || - (decoder != nullptr && - decoder_get_command(*decoder) != DecoderCommand::NONE)) + (client != nullptr && + client->GetCommand() != DecoderCommand::NONE)) return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; else return FLAC__STREAM_DECODER_READ_STATUS_ABORT; @@ -50,13 +51,13 @@ if (!input_stream.IsSeekable()) return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - ::Error error; - if (!input_stream.LockSeek(absolute_byte_offset, error)) { - LogError(error); + try { + input_stream.LockSeek(absolute_byte_offset); + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; + } catch (const std::runtime_error &e) { + LogError(e); return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; } - - return FLAC__STREAM_DECODER_SEEK_STATUS_OK; } FLAC__StreamDecoderTellStatus @@ -82,17 +83,17 @@ FLAC__bool FlacInput::Eof() { - return (decoder != nullptr && - decoder_get_command(*decoder) != DecoderCommand::NONE && - decoder_get_command(*decoder) != DecoderCommand::SEEK) || + return (client != nullptr && + client->GetCommand() != DecoderCommand::NONE && + client->GetCommand() != DecoderCommand::SEEK) || input_stream.LockIsEOF(); } void FlacInput::Error(FLAC__StreamDecoderErrorStatus status) { - if (decoder == nullptr || - decoder_get_command(*decoder) != DecoderCommand::STOP) + if (client == nullptr || + client->GetCommand() != DecoderCommand::STOP) LogWarning(flac_domain, FLAC__StreamDecoderErrorStatusString[status]); } diff -Nru mpd-0.19.21/src/decoder/plugins/FlacInput.hxx mpd-0.20.9/src/decoder/plugins/FlacInput.hxx --- mpd-0.19.21/src/decoder/plugins/FlacInput.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacInput.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ #include -struct Decoder; +class DecoderClient; class InputStream; /** @@ -30,14 +30,22 @@ * callbacks. */ class FlacInput { - Decoder *const decoder; + DecoderClient *const client; InputStream &input_stream; public: FlacInput(InputStream &_input_stream, - Decoder *_decoder=nullptr) - :decoder(_decoder), input_stream(_input_stream) {} + DecoderClient *_client=nullptr) + :client(_client), input_stream(_input_stream) {} + + DecoderClient *GetClient() { + return client; + } + + InputStream &GetInputStream() { + return input_stream; + } protected: FLAC__StreamDecoderReadStatus Read(FLAC__byte buffer[], size_t *bytes); diff -Nru mpd-0.19.21/src/decoder/plugins/FlacIOHandle.cxx mpd-0.20.9/src/decoder/plugins/FlacIOHandle.cxx --- mpd-0.19.21/src/decoder/plugins/FlacIOHandle.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacIOHandle.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,9 +19,9 @@ #include "config.h" #include "FlacIOHandle.hxx" -#include "util/Error.hxx" #include "Log.hxx" #include "Compiler.h" +#include "system/Error.hxx" #include #include @@ -37,24 +37,29 @@ /* libFLAC is very picky about short reads, and expects the IO callback to fill the whole buffer (undocumented!) */ - Error error; while (p < end) { - size_t nbytes = is->LockRead(p, end - p, error); - if (nbytes == 0) { - if (!error.IsDefined()) + try { + size_t nbytes = is->LockRead(p, end - p); + if (nbytes == 0) /* end of file */ break; - if (error.IsDomain(errno_domain)) - errno = error.GetCode(); - else - /* just some random non-zero - errno value */ - errno = EINVAL; + p += nbytes; + +#ifndef WIN32 + } catch (const std::system_error &e) { + errno = e.code().category() == ErrnoCategory() + ? e.code().value() + /* just some random non-zero errno + value */ + : EINVAL; + return 0; +#endif + } catch (const std::runtime_error &) { + /* just some random non-zero errno value */ + errno = EINVAL; return 0; } - - p += nbytes; } /* libFLAC expects a clean errno after returning from the IO @@ -88,13 +93,13 @@ return -1; } - Error error; - if (!is->LockSeek(offset, error)) { - LogError(error); + try { + is->LockSeek(offset); + return 0; + } catch (const std::runtime_error &e) { + LogError(e); return -1; } - - return 0; } static FLAC__int64 diff -Nru mpd-0.19.21/src/decoder/plugins/FlacIOHandle.hxx mpd-0.20.9/src/decoder/plugins/FlacIOHandle.hxx --- mpd-0.19.21/src/decoder/plugins/FlacIOHandle.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacIOHandle.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/FlacMetadata.cxx mpd-0.20.9/src/decoder/plugins/FlacMetadata.cxx --- mpd-0.19.21/src/decoder/plugins/FlacMetadata.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacMetadata.cxx 2017-06-04 10:37:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "config.h" #include "FlacMetadata.hxx" -#include "XiphTags.hxx" +#include "lib/xiph/XiphTags.hxx" #include "MixRampInfo.hxx" #include "tag/TagHandler.hxx" #include "tag/TagTable.hxx" @@ -29,8 +29,7 @@ #include "tag/ReplayGain.hxx" #include "tag/MixRamp.hxx" #include "ReplayGainInfo.hxx" -#include "util/ASCII.hxx" -#include "util/SplitString.hxx" +#include "util/DivideString.hxx" bool flac_parse_replay_gain(ReplayGainInfo &rgi, @@ -68,7 +67,7 @@ */ static const char * flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry, - const char *name) + const char *name) noexcept { return vorbis_comment_value((const char *)entry->entry, name); } @@ -80,7 +79,7 @@ static bool flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *name, TagType tag_type, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const char *value = flac_comment_value(entry, name); if (value != nullptr) { @@ -93,11 +92,11 @@ static void flac_scan_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { - if (handler->pair != nullptr) { + if (handler.pair != nullptr) { const char *comment = (const char *)entry->entry; - const SplitString split(comment, '='); + const DivideString split(comment, '='); if (split.IsDefined() && !split.IsEmpty()) tag_handler_invoke_pair(handler, handler_ctx, split.GetFirst(), @@ -118,7 +117,7 @@ static void flac_scan_comments(const FLAC__StreamMetadata_VorbisComment *comment, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { for (unsigned i = 0; i < comment->num_comments; ++i) flac_scan_comment(&comment->comments[i], @@ -127,7 +126,7 @@ gcc_pure static inline SongTime -flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) +flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) noexcept { assert(stream_info->sample_rate > 0); @@ -137,7 +136,7 @@ void flac_scan_metadata(const FLAC__StreamMetadata *block, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { switch (block->type) { case FLAC__METADATA_TYPE_VORBIS_COMMENT: @@ -160,12 +159,12 @@ flac_vorbis_comments_to_tag(const FLAC__StreamMetadata_VorbisComment *comment) { TagBuilder tag_builder; - flac_scan_comments(comment, &add_tag_handler, &tag_builder); + flac_scan_comments(comment, add_tag_handler, &tag_builder); return tag_builder.Commit(); } void -FlacMetadataChain::Scan(const struct tag_handler *handler, void *handler_ctx) +FlacMetadataChain::Scan(const TagHandler &handler, void *handler_ctx) { FLACMetadataIterator iterator(*this); diff -Nru mpd-0.19.21/src/decoder/plugins/FlacMetadata.hxx mpd-0.20.9/src/decoder/plugins/FlacMetadata.hxx --- mpd-0.19.21/src/decoder/plugins/FlacMetadata.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacMetadata.hxx 2017-06-04 10:37:08.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,9 +25,7 @@ #include -#include - -struct tag_handler; +struct TagHandler; class MixRampInfo; class FlacMetadataChain { @@ -44,25 +42,27 @@ return chain; } - bool Read(const char *path) { + bool Read(const char *path) noexcept { return ::FLAC__metadata_chain_read(chain, path); } - bool Read(FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) { + bool Read(FLAC__IOHandle handle, + FLAC__IOCallbacks callbacks) noexcept { return ::FLAC__metadata_chain_read_with_callbacks(chain, handle, callbacks); } - bool Read(InputStream &is) { + bool Read(InputStream &is) noexcept { return Read(::ToFlacIOHandle(is), ::GetFlacIOCallbacks(is)); } - bool ReadOgg(const char *path) { + bool ReadOgg(const char *path) noexcept { return ::FLAC__metadata_chain_read_ogg(chain, path); } - bool ReadOgg(FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) { + bool ReadOgg(FLAC__IOHandle handle, + FLAC__IOCallbacks callbacks) noexcept { return ::FLAC__metadata_chain_read_ogg_with_callbacks(chain, handle, callbacks); @@ -73,16 +73,16 @@ } gcc_pure - FLAC__Metadata_ChainStatus GetStatus() const { + FLAC__Metadata_ChainStatus GetStatus() const noexcept { return ::FLAC__metadata_chain_status(chain); } gcc_pure - const char *GetStatusString() const { + const char *GetStatusString() const noexcept { return FLAC__Metadata_ChainStatusString[GetStatus()]; } - void Scan(const tag_handler *handler, void *handler_ctx); + void Scan(const TagHandler &handler, void *handler_ctx); }; class FLACMetadataIterator { @@ -101,12 +101,12 @@ ::FLAC__metadata_iterator_delete(iterator); } - bool Next() { + bool Next() noexcept { return ::FLAC__metadata_iterator_next(iterator); } gcc_pure - FLAC__StreamMetadata *GetBlock() { + FLAC__StreamMetadata *GetBlock() noexcept { return ::FLAC__metadata_iterator_get_block(iterator); } }; @@ -126,6 +126,6 @@ void flac_scan_metadata(const FLAC__StreamMetadata *block, - const tag_handler *handler, void *handler_ctx); + const TagHandler &handler, void *handler_ctx); #endif diff -Nru mpd-0.19.21/src/decoder/plugins/FlacPcm.cxx mpd-0.20.9/src/decoder/plugins/FlacPcm.cxx --- mpd-0.19.21/src/decoder/plugins/FlacPcm.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacPcm.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,92 +19,111 @@ #include "config.h" #include "FlacPcm.hxx" +#include "CheckAudioFormat.hxx" +#include "util/RuntimeError.hxx" +#include "util/ConstBuffer.hxx" #include -static void flac_convert_stereo16(int16_t *dest, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) -{ - for (; position < end; ++position) { - *dest++ = buf[0][position]; - *dest++ = buf[1][position]; +static SampleFormat +flac_sample_format(unsigned bits_per_sample) +{ + switch (bits_per_sample) { + case 8: + return SampleFormat::S8; + + case 16: + return SampleFormat::S16; + + case 24: + return SampleFormat::S24_P32; + + case 32: + return SampleFormat::S32; + + default: + return SampleFormat::UNDEFINED; } } -static void -flac_convert_16(int16_t *dest, - unsigned int num_channels, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) +void +FlacPcmImport::Open(unsigned sample_rate, unsigned bits_per_sample, + unsigned channels) { - unsigned int c_chan; + auto sample_format = flac_sample_format(bits_per_sample); + if (sample_format == SampleFormat::UNDEFINED) + throw FormatRuntimeError("Unsupported FLAC bit depth: %u", + bits_per_sample); - for (; position < end; ++position) - for (c_chan = 0; c_chan < num_channels; c_chan++) - *dest++ = buf[c_chan][position]; + audio_format = CheckAudioFormat(sample_rate, sample_format, channels); } -/** - * Note: this function also handles 24 bit files! - */ +template static void -flac_convert_32(int32_t *dest, - unsigned int num_channels, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) -{ - unsigned int c_chan; - - for (; position < end; ++position) - for (c_chan = 0; c_chan < num_channels; c_chan++) - *dest++ = buf[c_chan][position]; +FlacImportStereo(T *dest, const FLAC__int32 *const src[], size_t n_frames) +{ + for (size_t i = 0; i != n_frames; ++i) { + *dest++ = (T)src[0][i]; + *dest++ = (T)src[1][i]; + } } +template static void -flac_convert_8(int8_t *dest, - unsigned int num_channels, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) -{ - unsigned int c_chan; - - for (; position < end; ++position) - for (c_chan = 0; c_chan < num_channels; c_chan++) - *dest++ = buf[c_chan][position]; +FlacImportAny(T *dest, const FLAC__int32 *const src[], size_t n_frames, + unsigned n_channels) +{ + for (size_t i = 0; i != n_frames; ++i) + for (unsigned c = 0; c != n_channels; ++c) + *dest++ = src[c][i]; } -void -flac_convert(void *dest, - unsigned int num_channels, SampleFormat sample_format, - const FLAC__int32 *const buf[], - unsigned int position, unsigned int end) +template +static void +FlacImport(T *dest, const FLAC__int32 *const src[], size_t n_frames, + unsigned n_channels) +{ + if (n_channels == 2) + FlacImportStereo(dest, src, n_frames); + else + FlacImportAny(dest, src, n_frames, n_channels); +} + +template +static ConstBuffer +FlacImport(PcmBuffer &buffer, const FLAC__int32 *const src[], size_t n_frames, + unsigned n_channels) +{ + size_t n_samples = n_frames * n_channels; + size_t dest_size = n_samples * sizeof(T); + T *dest = (T *)buffer.Get(dest_size); + FlacImport(dest, src, n_frames, n_channels); + return {dest, dest_size}; +} + +ConstBuffer +FlacPcmImport::Import(const FLAC__int32 *const src[], size_t n_frames) { - switch (sample_format) { + switch (audio_format.format) { case SampleFormat::S16: - if (num_channels == 2) - flac_convert_stereo16((int16_t*)dest, buf, - position, end); - else - flac_convert_16((int16_t*)dest, num_channels, buf, - position, end); - break; + return FlacImport(buffer, src, n_frames, + audio_format.channels); case SampleFormat::S24_P32: case SampleFormat::S32: - flac_convert_32((int32_t*)dest, num_channels, buf, - position, end); - break; + return FlacImport(buffer, src, n_frames, + audio_format.channels); case SampleFormat::S8: - flac_convert_8((int8_t*)dest, num_channels, buf, - position, end); - break; + return FlacImport(buffer, src, n_frames, + audio_format.channels); case SampleFormat::FLOAT: case SampleFormat::DSD: case SampleFormat::UNDEFINED: - assert(false); - gcc_unreachable(); + break; } + + assert(false); + gcc_unreachable(); } diff -Nru mpd-0.19.21/src/decoder/plugins/FlacPcm.hxx mpd-0.20.9/src/decoder/plugins/FlacPcm.hxx --- mpd-0.19.21/src/decoder/plugins/FlacPcm.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacPcm.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,14 +20,36 @@ #ifndef MPD_FLAC_PCM_HXX #define MPD_FLAC_PCM_HXX +#include "check.h" +#include "pcm/PcmBuffer.hxx" #include "AudioFormat.hxx" #include -void -flac_convert(void *dest, - unsigned int num_channels, SampleFormat sample_format, - const FLAC__int32 *const buf[], - unsigned int position, unsigned int end); +template struct ConstBuffer; + +/** + * This class imports libFLAC PCM data into a PCM format supported by + * MPD. + */ +class FlacPcmImport { + PcmBuffer buffer; + + AudioFormat audio_format; + +public: + /** + * Throws #std::runtime_error on error. + */ + void Open(unsigned sample_rate, unsigned bits_per_sample, + unsigned channels); + + const AudioFormat &GetAudioFormat() const { + return audio_format; + } + + ConstBuffer Import(const FLAC__int32 *const src[], + size_t n_frames); +}; #endif diff -Nru mpd-0.19.21/src/decoder/plugins/FlacStreamDecoder.hxx mpd-0.20.9/src/decoder/plugins/FlacStreamDecoder.hxx --- mpd-0.19.21/src/decoder/plugins/FlacStreamDecoder.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FlacStreamDecoder.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FLAC_STREAM_DECODER +#define MPD_FLAC_STREAM_DECODER + +#include "check.h" + +#include + +#include +#include + +#include + +/** + * OO wrapper for a FLAC__StreamDecoder. + */ +class FlacStreamDecoder { + FLAC__StreamDecoder *decoder; + +public: + FlacStreamDecoder() + :decoder(FLAC__stream_decoder_new()) { + if (decoder == nullptr) + throw std::runtime_error("FLAC__stream_decoder_new() failed"); + } + + FlacStreamDecoder(FlacStreamDecoder &&src) + :decoder(src.decoder) { + src.decoder = nullptr; + } + + ~FlacStreamDecoder() { + if (decoder != nullptr) + FLAC__stream_decoder_delete(decoder); + } + + FlacStreamDecoder &operator=(FlacStreamDecoder &&src) { + std::swap(decoder, src.decoder); + return *this; + } + + operator bool() const { + return decoder != nullptr; + } + + FLAC__StreamDecoder *get() { + assert(decoder != nullptr); + + return decoder; + } +}; + +#endif diff -Nru mpd-0.19.21/src/decoder/plugins/FluidsynthDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/FluidsynthDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/FluidsynthDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FluidsynthDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ #include "../DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "util/Macros.hxx" #include "Log.hxx" @@ -35,7 +34,7 @@ static const char *soundfont_path; /** - * Convert a fluidsynth log level to a GLib log level. + * Convert a fluidsynth log level to a MPD log level. */ static LogLevel fluidsynth_level_to_mpd(enum fluid_log_level level) @@ -61,7 +60,7 @@ } /** - * The fluidsynth logging callback. It forwards messages to the GLib + * The fluidsynth logging callback. It forwards messages to the MPD * logging library. */ static void @@ -73,17 +72,12 @@ } static bool -fluidsynth_init(const config_param ¶m) +fluidsynth_init(const ConfigBlock &block) { - Error error; + sample_rate = block.GetBlockValue("sample_rate", 48000u); + CheckSampleRate(sample_rate); - sample_rate = param.GetBlockValue("sample_rate", 48000u); - if (!audio_check_sample_rate(sample_rate, error)) { - LogError(error); - return false; - } - - soundfont_path = param.GetBlockValue("soundfont", + soundfont_path = block.GetBlockValue("soundfont", "/usr/share/sounds/sf2/FluidR3_GM.sf2"); fluid_set_log_function(LAST_LOG_LEVEL, @@ -93,7 +87,7 @@ } static void -fluidsynth_file_decode(Decoder &decoder, Path path_fs) +fluidsynth_file_decode(DecoderClient &client, Path path_fs) { char setting_sample_rate[] = "synth.sample-rate"; /* @@ -166,8 +160,7 @@ MPD core */ const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2); - decoder_initialized(decoder, audio_format, false, - SignedSongTime::Negative()); + client.Ready(audio_format, false, SignedSongTime::Negative()); DecoderCommand cmd; while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { @@ -183,8 +176,7 @@ if (ret != 0) break; - cmd = decoder_data(decoder, nullptr, buffer, sizeof(buffer), - 0); + cmd = client.SubmitData(nullptr, buffer, sizeof(buffer), 0); if (cmd != DecoderCommand::NONE) break; } @@ -201,7 +193,7 @@ static bool fluidsynth_scan_file(Path path_fs, - gcc_unused const struct tag_handler *handler, + gcc_unused const TagHandler &handler, gcc_unused void *handler_ctx) { return fluid_is_midifile(path_fs.c_str()); diff -Nru mpd-0.19.21/src/decoder/plugins/FluidsynthDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/FluidsynthDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/FluidsynthDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/FluidsynthDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/GmeDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/GmeDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/GmeDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/GmeDecoderPlugin.cxx 2017-05-08 15:10:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,22 +20,25 @@ #include "config.h" #include "GmeDecoderPlugin.hxx" #include "../DecoderAPI.hxx" +#include "config/Block.cxx" #include "CheckAudioFormat.hxx" +#include "DetachedSong.hxx" #include "tag/TagHandler.hxx" +#include "tag/TagBuilder.hxx" #include "fs/Path.hxx" -#include "util/Alloc.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/ScopeExit.hxx" #include "util/FormatString.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" -#include +#include + #include #include #include - -#include +#include #define SUBTUNE_PREFIX "tune_" @@ -47,112 +50,88 @@ static constexpr unsigned GME_BUFFER_SAMPLES = GME_BUFFER_FRAMES * GME_CHANNELS; -/** - * returns the file path stripped of any /tune_xxx.* subtune - * suffix - */ -static char * -get_container_name(Path path_fs) -{ - const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); - char *path_container = xstrdup(path_fs.c_str()); +struct GmeContainerPath { + AllocatedPath path; + unsigned track; +}; - char pat[64]; - snprintf(pat, sizeof(pat), "%s%s", - "*/" SUBTUNE_PREFIX "???.", - subtune_suffix); - GPatternSpec *path_with_subtune = g_pattern_spec_new(pat); - if (!g_pattern_match(path_with_subtune, - strlen(path_container), path_container, nullptr)) { - g_pattern_spec_free(path_with_subtune); - return path_container; - } +#if GME_VERSION >= 0x000600 +static int gme_accuracy; +#endif - char *ptr = g_strrstr(path_container, "/" SUBTUNE_PREFIX); - if (ptr != nullptr) - *ptr='\0'; +static bool +gme_plugin_init(gcc_unused const ConfigBlock &block) +{ +#if GME_VERSION >= 0x000600 + auto accuracy = block.GetBlockParam("accuracy"); + gme_accuracy = accuracy != nullptr + ? (int)accuracy->GetBoolValue() + : -1; +#endif - g_pattern_spec_free(path_with_subtune); - return path_container; + return true; } -/** - * returns tune number from file.nsf/tune_xxx.* style path or 0 if no subtune - * is appended. - */ -static int -get_song_num(Path path_fs) +gcc_pure +static unsigned +ParseSubtuneName(const char *base) noexcept { - const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); + if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0) + return 0; + + base += sizeof(SUBTUNE_PREFIX) - 1; - char pat[64]; - snprintf(pat, sizeof(pat), "%s%s", - "*/" SUBTUNE_PREFIX "???.", - subtune_suffix); - GPatternSpec *path_with_subtune = g_pattern_spec_new(pat); - - if (g_pattern_match(path_with_subtune, - path_fs.length(), path_fs.data(), nullptr)) { - char *sub = g_strrstr(path_fs.c_str(), "/" SUBTUNE_PREFIX); - g_pattern_spec_free(path_with_subtune); - if (!sub) - return 0; - - sub += strlen("/" SUBTUNE_PREFIX); - int song_num = strtol(sub, nullptr, 10); - - return song_num - 1; - } else { - g_pattern_spec_free(path_with_subtune); + char *endptr; + auto track = strtoul(base, &endptr, 10); + if (endptr == base || *endptr != '.') return 0; - } + + return track; } -static char * -gme_container_scan(Path path_fs, const unsigned int tnum) +/** + * returns the file path stripped of any /tune_xxx.* subtune suffix + * and the track number (or 0 if no "tune_xxx" suffix is present). + */ +static GmeContainerPath +ParseContainerPath(Path path_fs) { - Music_Emu *emu; - const char *gme_err = gme_open_file(path_fs.c_str(), &emu, - GME_SAMPLE_RATE); - if (gme_err != nullptr) { - LogWarning(gme_domain, gme_err); - return nullptr; - } + const Path base = path_fs.GetBase(); + unsigned track; + if (base.IsNull() || + (track = ParseSubtuneName(base.c_str())) < 1) + return { AllocatedPath(path_fs), 0 }; - const unsigned num_songs = gme_track_count(emu); - gme_delete(emu); - /* if it only contains a single tune, don't treat as container */ - if (num_songs < 2) - return nullptr; - - const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); - if (tnum <= num_songs){ - return FormatNew(SUBTUNE_PREFIX "%03u.%s", - tnum, subtune_suffix); - } else - return nullptr; + return { path_fs.GetDirectoryName(), track - 1 }; } static void -gme_file_decode(Decoder &decoder, Path path_fs) +gme_file_decode(DecoderClient &client, Path path_fs) { - char *path_container = get_container_name(path_fs); + const auto container = ParseContainerPath(path_fs); Music_Emu *emu; const char *gme_err = - gme_open_file(path_container, &emu, GME_SAMPLE_RATE); - free(path_container); + gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE); if (gme_err != nullptr) { LogWarning(gme_domain, gme_err); return; } + AtScopeExit(emu) { gme_delete(emu); }; + + FormatDebug(gme_domain, "emulator type '%s'\n", + gme_type_system(gme_type(emu))); + +#if GME_VERSION >= 0x000600 + if (gme_accuracy >= 0) + gme_enable_accuracy(emu, gme_accuracy); +#endif + gme_info_t *ti; - const int song_num = get_song_num(path_fs); - gme_err = gme_track_info(emu, &ti, song_num); + gme_err = gme_track_info(emu, &ti, container.track); if (gme_err != nullptr) { LogWarning(gme_domain, gme_err); - gme_delete(emu); return; } @@ -165,19 +144,13 @@ /* initialize the MPD decoder */ - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, GME_SAMPLE_RATE, - SampleFormat::S16, GME_CHANNELS, - error)) { - LogError(error); - gme_delete(emu); - return; - } + const auto audio_format = CheckAudioFormat(GME_SAMPLE_RATE, + SampleFormat::S16, + GME_CHANNELS); - decoder_initialized(decoder, audio_format, true, song_len); + client.Ready(audio_format, true, song_len); - gme_err = gme_start_track(emu, song_num); + gme_err = gme_start_track(emu, container.track); if (gme_err != nullptr) LogWarning(gme_domain, gme_err); @@ -194,102 +167,155 @@ return; } - cmd = decoder_data(decoder, nullptr, buf, sizeof(buf), 0); + cmd = client.SubmitData(nullptr, buf, sizeof(buf), 0); if (cmd == DecoderCommand::SEEK) { - unsigned where = decoder_seek_time(decoder).ToMS(); + unsigned where = client.GetSeekTime().ToMS(); gme_err = gme_seek(emu, where); if (gme_err != nullptr) { LogWarning(gme_domain, gme_err); - decoder_seek_error(decoder); + client.SeekError(); } else - decoder_command_finished(decoder); + client.CommandFinished(); } if (gme_track_ended(emu)) break; } while (cmd != DecoderCommand::STOP); - - gme_delete(emu); } -static bool -gme_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) +static void +ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count, + const TagHandler &handler, void *handler_ctx) { - char *path_container = get_container_name(path_fs); + if (info.play_length > 0) + tag_handler_invoke_duration(handler, handler_ctx, + SongTime::FromMS(info.play_length)); - Music_Emu *emu; - const char *gme_err = - gme_open_file(path_container, &emu, GME_SAMPLE_RATE); - free(path_container); - if (gme_err != nullptr) { - LogWarning(gme_domain, gme_err); - return false; + if (track_count > 1) { + char track[16]; + sprintf(track, "%u", song_num + 1); + tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track); } - const int song_num = get_song_num(path_fs); - - gme_info_t *ti; - gme_err = gme_track_info(emu, &ti, song_num); - if (gme_err != nullptr) { - LogWarning(gme_domain, gme_err); - gme_delete(emu); - return false; - } - - assert(ti != nullptr); - - if (ti->play_length > 0) - tag_handler_invoke_duration(handler, handler_ctx, - SongTime::FromMS(ti->play_length)); - - if (ti->song != nullptr) { - if (gme_track_count(emu) > 1) { + if (info.song != nullptr) { + if (track_count > 1) { /* start numbering subtunes from 1 */ char tag_title[1024]; snprintf(tag_title, sizeof(tag_title), - "%s (%d/%d)", - ti->song, song_num + 1, - gme_track_count(emu)); + "%s (%u/%d)", + info.song, song_num + 1, + track_count); tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, tag_title); } else tag_handler_invoke_tag(handler, handler_ctx, - TAG_TITLE, ti->song); + TAG_TITLE, info.song); } - if (ti->author != nullptr) + if (info.author != nullptr) tag_handler_invoke_tag(handler, handler_ctx, - TAG_ARTIST, ti->author); + TAG_ARTIST, info.author); - if (ti->game != nullptr) + if (info.game != nullptr) tag_handler_invoke_tag(handler, handler_ctx, - TAG_ALBUM, ti->game); + TAG_ALBUM, info.game); - if (ti->comment != nullptr) + if (info.comment != nullptr) tag_handler_invoke_tag(handler, handler_ctx, - TAG_COMMENT, ti->comment); + TAG_COMMENT, info.comment); - if (ti->copyright != nullptr) + if (info.copyright != nullptr) tag_handler_invoke_tag(handler, handler_ctx, - TAG_DATE, ti->copyright); + TAG_DATE, info.copyright); +} - gme_free_info(ti); - gme_delete(emu); +static bool +ScanMusicEmu(Music_Emu *emu, unsigned song_num, + const TagHandler &handler, void *handler_ctx) +{ + gme_info_t *ti; + const char *gme_err = gme_track_info(emu, &ti, song_num); + if (gme_err != nullptr) { + LogWarning(gme_domain, gme_err); + return false; + } + assert(ti != nullptr); + + AtScopeExit(ti) { gme_free_info(ti); }; + + ScanGmeInfo(*ti, song_num, gme_track_count(emu), + handler, handler_ctx); return true; } +static bool +gme_scan_file(Path path_fs, + const TagHandler &handler, void *handler_ctx) +{ + const auto container = ParseContainerPath(path_fs); + + Music_Emu *emu; + const char *gme_err = + gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE); + if (gme_err != nullptr) { + LogWarning(gme_domain, gme_err); + return false; + } + + AtScopeExit(emu) { gme_delete(emu); }; + + return ScanMusicEmu(emu, container.track, handler, handler_ctx); +} + +static std::forward_list +gme_container_scan(Path path_fs) +{ + std::forward_list list; + + Music_Emu *emu; + const char *gme_err = gme_open_file(path_fs.c_str(), &emu, + GME_SAMPLE_RATE); + if (gme_err != nullptr) { + LogWarning(gme_domain, gme_err); + return list; + } + + AtScopeExit(emu) { gme_delete(emu); }; + + const unsigned num_songs = gme_track_count(emu); + /* if it only contains a single tune, don't treat as container */ + if (num_songs < 2) + return list; + + const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); + + TagBuilder tag_builder; + + auto tail = list.before_begin(); + for (unsigned i = 1; i <= num_songs; ++i) { + ScanMusicEmu(emu, i, + add_tag_handler, &tag_builder); + + char track_name[64]; + snprintf(track_name, sizeof(track_name), + SUBTUNE_PREFIX "%03u.%s", i, subtune_suffix); + tail = list.emplace_after(tail, track_name, + tag_builder.Commit()); + } + + return list; +} + static const char *const gme_suffixes[] = { "ay", "gbs", "gym", "hes", "kss", "nsf", "nsfe", "sap", "spc", "vgm", "vgz", nullptr }; -extern const struct DecoderPlugin gme_decoder_plugin; const struct DecoderPlugin gme_decoder_plugin = { "gme", - nullptr, + gme_plugin_init, nullptr, nullptr, gme_file_decode, diff -Nru mpd-0.19.21/src/decoder/plugins/GmeDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/GmeDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/GmeDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/GmeDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/MadDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/MadDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/MadDecoderPlugin.cxx 2016-10-27 19:24:24.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MadDecoderPlugin.cxx 2017-05-08 14:57:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,18 +28,18 @@ #include "tag/ReplayGain.hxx" #include "tag/MixRamp.hxx" #include "CheckAudioFormat.hxx" -#include "util/StringUtil.hxx" -#include "util/ASCII.hxx" -#include "util/Error.hxx" +#include "util/StringCompare.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG #include #endif +#include + #include #include #include @@ -71,7 +71,7 @@ gcc_const static SongTime -ToSongTime(mad_timer_t t) +ToSongTime(mad_timer_t t) noexcept { return SongTime::FromMS(mad_timer_count(t, MAD_UNITS_MILLISECONDS)); } @@ -107,9 +107,9 @@ } static bool -mp3_plugin_init(gcc_unused const config_param ¶m) +mp3_plugin_init(gcc_unused const ConfigBlock &block) { - gapless_playback = config_get_bool(CONF_GAPLESS_MP3_PLAYBACK, + gapless_playback = config_get_bool(ConfigOption::GAPLESS_MP3_PLAYBACK, DEFAULT_GAPLESS_MP3_PLAYBACK); return true; } @@ -127,25 +127,25 @@ SignedSongTime total_time; SongTime elapsed_time; SongTime seek_time; - enum muteframe mute_frame; - long *frame_offsets; - mad_timer_t *times; - unsigned long highest_frame; - unsigned long max_frames; - unsigned long current_frame; - unsigned int drop_start_frames; - unsigned int drop_end_frames; - unsigned int drop_start_samples; - unsigned int drop_end_samples; - bool found_replay_gain; - bool found_first_frame; - bool decoded_first_frame; + enum muteframe mute_frame = MUTEFRAME_NONE; + long *frame_offsets = nullptr; + mad_timer_t *times = nullptr; + unsigned long highest_frame = 0; + unsigned long max_frames = 0; + unsigned long current_frame = 0; + unsigned int drop_start_frames = 0; + unsigned int drop_end_frames = 0; + unsigned int drop_start_samples = 0; + unsigned int drop_end_samples = 0; + bool found_replay_gain = false; + bool found_first_frame = false; + bool decoded_first_frame = false; unsigned long bit_rate; - Decoder *const decoder; + DecoderClient *const client; InputStream &input_stream; - enum mad_layer layer; + enum mad_layer layer = mad_layer(0); - MadDecoder(Decoder *decoder, InputStream &input_stream); + MadDecoder(DecoderClient *client, InputStream &input_stream); ~MadDecoder(); bool Seek(long offset); @@ -155,10 +155,10 @@ enum mp3_action DecodeNextFrame(); gcc_pure - offset_type ThisFrameOffset() const; + offset_type ThisFrameOffset() const noexcept; gcc_pure - offset_type RestIncludingThisFrame() const; + offset_type RestIncludingThisFrame() const noexcept; /** * Attempt to calulcate the length of the song from filesize @@ -167,37 +167,38 @@ bool DecodeFirstFrame(Tag **tag); + void AllocateBuffers() { + assert(max_frames > 0); + assert(frame_offsets == nullptr); + assert(times == nullptr); + + frame_offsets = new long[max_frames]; + times = new mad_timer_t[max_frames]; + } + gcc_pure - long TimeToFrame(SongTime t) const; + long TimeToFrame(SongTime t) const noexcept; void UpdateTimerNextFrame(); /** - * Sends the synthesized current frame via decoder_data(). + * Sends the synthesized current frame via + * DecoderClient::SubmitData(). */ DecoderCommand SendPCM(unsigned i, unsigned pcm_length); /** * Synthesize the current frame and send it via - * decoder_data(). + * DecoderClient::SubmitData(). */ DecoderCommand SyncAndSend(); bool Read(); }; -MadDecoder::MadDecoder(Decoder *_decoder, +MadDecoder::MadDecoder(DecoderClient *_client, InputStream &_input_stream) - :mute_frame(MUTEFRAME_NONE), - frame_offsets(nullptr), - times(nullptr), - highest_frame(0), max_frames(0), current_frame(0), - drop_start_frames(0), drop_end_frames(0), - drop_start_samples(0), drop_end_samples(0), - found_replay_gain(false), - found_first_frame(false), decoded_first_frame(false), - decoder(_decoder), input_stream(_input_stream), - layer(mad_layer(0)) + :client(_client), input_stream(_input_stream) { mad_stream_init(&stream); mad_stream_options(&stream, MAD_OPTION_IGNORECRC); @@ -209,9 +210,11 @@ inline bool MadDecoder::Seek(long offset) { - Error error; - if (!input_stream.LockSeek(offset, error)) + try { + input_stream.LockSeek(offset); + } catch (const std::runtime_error &) { return false; + } mad_stream_buffer(&stream, input_buffer, 0); stream.error = MAD_ERROR_NONE; @@ -241,7 +244,7 @@ if (length == 0) return false; - length = decoder_read(decoder, input_stream, dest, length); + length = decoder_read(client, input_stream, dest, length); if (length == 0) return false; @@ -251,7 +254,7 @@ return true; } -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG static bool parse_id3_replay_gain_info(ReplayGainInfo &rgi, struct id3_tag *tag) @@ -285,10 +288,10 @@ } #endif -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG gcc_pure static MixRampInfo -parse_id3_mixramp(struct id3_tag *tag) +parse_id3_mixramp(struct id3_tag *tag) noexcept { MixRampInfo result; @@ -317,7 +320,7 @@ inline void MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag) { -#ifdef HAVE_ID3TAG +#ifdef ENABLE_ID3TAG id3_byte_t *allocated = nullptr; const id3_length_t count = stream.bufend - stream.this_frame; @@ -331,7 +334,7 @@ memcpy(allocated, stream.this_frame, count); mad_stream_skip(&(stream), count); - if (!decoder_read_full(decoder, input_stream, + if (!decoder_read_full(client, input_stream, allocated + count, tagsize - count)) { LogDebug(mad_domain, "error parsing ID3 tag"); delete[] allocated; @@ -355,21 +358,21 @@ } } - if (decoder != nullptr) { + if (client != nullptr) { ReplayGainInfo rgi; if (parse_id3_replay_gain_info(rgi, id3_tag)) { - decoder_replay_gain(*decoder, &rgi); + client->SubmitReplayGain(&rgi); found_replay_gain = true; } - decoder_mixramp(*decoder, parse_id3_mixramp(id3_tag)); + client->SubmitMixRamp(parse_id3_mixramp(id3_tag)); } id3_tag_delete(id3_tag); delete[] allocated; -#else /* !HAVE_ID3TAG */ +#else /* !ENABLE_ID3TAG */ (void)mpd_tag; /* This code is enabled when libid3tag is disabled. Instead @@ -381,12 +384,12 @@ mad_stream_skip(&stream, tagsize); } else { mad_stream_skip(&stream, count); - decoder_skip(decoder, input_stream, tagsize - count); + decoder_skip(client, input_stream, tagsize - count); } #endif } -#ifndef HAVE_ID3TAG +#ifndef ENABLE_ID3TAG /** * This function emulates libid3tag when it is disabled. Instead of * doing a real analyzation of the frame, it just checks whether the @@ -402,7 +405,7 @@ ? (p[8] << 7) + p[9] + 10 : 0; } -#endif /* !HAVE_ID3TAG */ +#endif /* !ENABLE_ID3TAG */ static enum mp3_action RecoverFrameError(struct mad_stream &stream) @@ -504,10 +507,10 @@ enum xing_magic magic; /* header magic */ }; -static const unsigned XING_FRAMES = 1; -static const unsigned XING_BYTES = 2; -static const unsigned XING_TOC = 4; -static const unsigned XING_SCALE = 8; +static constexpr unsigned XING_FRAMES = 1; +static constexpr unsigned XING_BYTES = 2; +static constexpr unsigned XING_TOC = 4; +static constexpr unsigned XING_SCALE = 8; struct lame_version { unsigned major; @@ -707,7 +710,7 @@ } inline offset_type -MadDecoder::ThisFrameOffset() const +MadDecoder::ThisFrameOffset() const noexcept { auto offset = input_stream.GetOffset(); @@ -720,7 +723,7 @@ } inline offset_type -MadDecoder::RestIncludingThisFrame() const +MadDecoder::RestIncludingThisFrame() const noexcept { return input_stream.GetSize() - ThisFrameOffset(); } @@ -798,13 +801,13 @@ /* Album gain isn't currently used. See comment in * parse_lame() for details. -- jat */ - if (decoder != nullptr && !found_replay_gain && + if (client != nullptr && !found_replay_gain && lame.track_gain) { ReplayGainInfo rgi; rgi.Clear(); - rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain; - rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak; - decoder_replay_gain(*decoder, &rgi); + rgi.track.gain = lame.track_gain; + rgi.track.peak = lame.peak; + client->SubmitReplayGain(&rgi); } } } @@ -819,9 +822,6 @@ return false; } - frame_offsets = new long[max_frames]; - times = new mad_timer_t[max_frames]; - return true; } @@ -846,7 +846,7 @@ } long -MadDecoder::TimeToFrame(SongTime t) const +MadDecoder::TimeToFrame(SongTime t) const noexcept { unsigned long i; @@ -904,9 +904,9 @@ MAD_NCHANNELS(&frame.header)); num_samples *= MAD_NCHANNELS(&frame.header); - auto cmd = decoder_data(*decoder, input_stream, output_buffer, - sizeof(output_buffer[0]) * num_samples, - bit_rate / 1000); + auto cmd = client->SubmitData(input_stream, output_buffer, + sizeof(output_buffer[0]) * num_samples, + bit_rate / 1000); if (cmd != DecoderCommand::NONE) return cmd; } @@ -986,18 +986,18 @@ if (cmd == DecoderCommand::SEEK) { assert(input_stream.IsSeekable()); - unsigned long j = - TimeToFrame(decoder_seek_time(*decoder)); + const auto t = client->GetSeekTime(); + unsigned long j = TimeToFrame(t); if (j < highest_frame) { if (Seek(frame_offsets[j])) { current_frame = j; - decoder_command_finished(*decoder); + client->CommandFinished(); } else - decoder_seek_error(*decoder); + client->SeekError(); } else { - seek_time = decoder_seek_time(*decoder); + seek_time = t; mute_frame = MUTEFRAME_SEEK; - decoder_command_finished(*decoder); + client->CommandFinished(); } } else if (cmd != DecoderCommand::NONE) return false; @@ -1011,8 +1011,8 @@ ret = DecodeNextFrameHeader(&tag); if (tag != nullptr) { - decoder_tag(*decoder, input_stream, - std::move(*tag)); + client->SubmitTag(input_stream, + std::move(*tag)); delete tag; } } while (ret == DECODE_CONT); @@ -1035,38 +1035,30 @@ } static void -mp3_decode(Decoder &decoder, InputStream &input_stream) +mp3_decode(DecoderClient &client, InputStream &input_stream) { - MadDecoder data(&decoder, input_stream); + MadDecoder data(&client, input_stream); Tag *tag = nullptr; if (!data.DecodeFirstFrame(&tag)) { delete tag; - if (decoder_get_command(decoder) == DecoderCommand::NONE) + if (client.GetCommand() == DecoderCommand::NONE) LogError(mad_domain, "input/Input does not appear to be a mp3 bit stream"); return; } - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, - data.frame.header.samplerate, - SampleFormat::S24_P32, - MAD_NCHANNELS(&data.frame.header), - error)) { - LogError(error); - delete tag; - return; - } + data.AllocateBuffers(); - decoder_initialized(decoder, audio_format, - input_stream.IsSeekable(), - data.total_time); + client.Ready(CheckAudioFormat(data.frame.header.samplerate, + SampleFormat::S24_P32, + MAD_NCHANNELS(&data.frame.header)), + input_stream.IsSeekable(), + data.total_time); if (tag != nullptr) { - decoder_tag(decoder, input_stream, std::move(*tag)); + client.SubmitTag(input_stream, std::move(*tag)); delete tag; } @@ -1075,7 +1067,7 @@ static bool mad_decoder_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const auto result = mad_decoder_total_file_time(is); if (!result.first) diff -Nru mpd-0.19.21/src/decoder/plugins/MadDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/MadDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/MadDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MadDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/MikmodDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/MikmodDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/MikmodDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MikmodDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,9 +21,9 @@ #include "MikmodDecoderPlugin.hxx" #include "../DecoderAPI.hxx" #include "tag/TagHandler.hxx" -#include "system/FatalError.hxx" #include "fs/Path.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -109,15 +109,15 @@ static unsigned mikmod_sample_rate; static bool -mikmod_decoder_init(const config_param ¶m) +mikmod_decoder_init(const ConfigBlock &block) { static char params[] = ""; - mikmod_loop = param.GetBlockValue("loop", false); - mikmod_sample_rate = param.GetBlockValue("sample_rate", 44100u); + mikmod_loop = block.GetBlockValue("loop", false); + mikmod_sample_rate = block.GetBlockValue("sample_rate", 44100u); if (!audio_valid_sample_rate(mikmod_sample_rate)) - FormatFatalError("Invalid sample rate in line %d: %u", - param.line, mikmod_sample_rate); + throw FormatRuntimeError("Invalid sample rate in line %d: %u", + block.line, mikmod_sample_rate); md_device = 0; md_reverb = 0; @@ -147,7 +147,7 @@ } static void -mikmod_decoder_file_decode(Decoder &decoder, Path path_fs) +mikmod_decoder_file_decode(DecoderClient &client, Path path_fs) { /* deconstify the path because libmikmod wants a non-const string pointer */ @@ -170,15 +170,14 @@ const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2); assert(audio_format.IsValid()); - decoder_initialized(decoder, audio_format, false, - SignedSongTime::Negative()); + client.Ready(audio_format, false, SignedSongTime::Negative()); Player_Start(handle); DecoderCommand cmd = DecoderCommand::NONE; while (cmd == DecoderCommand::NONE && Player_Active()) { ret = VC_WriteBytes(buffer, sizeof(buffer)); - cmd = decoder_data(decoder, nullptr, buffer, ret, 0); + cmd = client.SubmitData(nullptr, buffer, ret, 0); } Player_Stop(); @@ -187,7 +186,7 @@ static bool mikmod_decoder_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { /* deconstify the path because libmikmod wants a non-const string pointer */ diff -Nru mpd-0.19.21/src/decoder/plugins/MikmodDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/MikmodDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/MikmodDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MikmodDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/ModplugDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/ModplugDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/ModplugDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/ModplugDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,9 +22,9 @@ #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" #include "tag/TagHandler.hxx" -#include "system/FatalError.hxx" #include "util/WritableBuffer.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -41,18 +41,18 @@ static int modplug_loop_count; static bool -modplug_decoder_init(const config_param ¶m) +modplug_decoder_init(const ConfigBlock &block) { - modplug_loop_count = param.GetBlockValue("loop_count", 0); + modplug_loop_count = block.GetBlockValue("loop_count", 0); if (modplug_loop_count < -1) - FormatFatalError("Invalid loop count in line %d: %i", - param.line, modplug_loop_count); + throw FormatRuntimeError("Invalid loop count in line %d: %i", + block.line, modplug_loop_count); return true; } static WritableBuffer -mod_loadfile(Decoder *decoder, InputStream &is) +mod_loadfile(DecoderClient *client, InputStream &is) { //known/unknown size, preallocate array, lets read in chunks @@ -83,7 +83,7 @@ uint8_t *p = buffer.begin(); while (true) { - size_t ret = decoder_read(decoder, is, p, end - p); + size_t ret = decoder_read(client, is, p, end - p); if (ret == 0) { if (is.LockIsEOF()) /* end of file */ @@ -112,9 +112,9 @@ } static ModPlugFile * -LoadModPlugFile(Decoder *decoder, InputStream &is) +LoadModPlugFile(DecoderClient *client, InputStream &is) { - const auto buffer = mod_loadfile(decoder, is); + const auto buffer = mod_loadfile(client, is); if (buffer.IsNull()) { LogWarning(modplug_domain, "could not load stream"); return nullptr; @@ -126,7 +126,7 @@ } static void -mod_decode(Decoder &decoder, InputStream &is) +mod_decode(DecoderClient &client, InputStream &is) { ModPlug_Settings settings; int ret; @@ -142,7 +142,7 @@ /* insert more setting changes here */ ModPlug_SetSettings(&settings); - ModPlugFile *f = LoadModPlugFile(&decoder, is); + ModPlugFile *f = LoadModPlugFile(&client, is); if (f == nullptr) { LogWarning(modplug_domain, "could not decode stream"); return; @@ -151,9 +151,8 @@ static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2); assert(audio_format.IsValid()); - decoder_initialized(decoder, audio_format, - is.IsSeekable(), - SongTime::FromMS(ModPlug_GetLength(f))); + client.Ready(audio_format, is.IsSeekable(), + SongTime::FromMS(ModPlug_GetLength(f))); DecoderCommand cmd; do { @@ -161,13 +160,13 @@ if (ret <= 0) break; - cmd = decoder_data(decoder, nullptr, - audio_buffer, ret, - 0); + cmd = client.SubmitData(nullptr, + audio_buffer, ret, + 0); if (cmd == DecoderCommand::SEEK) { - ModPlug_Seek(f, decoder_seek_time(decoder).ToMS()); - decoder_command_finished(decoder); + ModPlug_Seek(f, client.GetSeekTime().ToMS()); + client.CommandFinished(); } } while (cmd != DecoderCommand::STOP); @@ -177,7 +176,7 @@ static bool modplug_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { ModPlugFile *f = LoadModPlugFile(nullptr, is); if (f == nullptr) diff -Nru mpd-0.19.21/src/decoder/plugins/ModplugDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/ModplugDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/ModplugDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/ModplugDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/MpcdecDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/MpcdecDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/MpcdecDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MpcdecDecoderPlugin.cxx 2017-03-01 15:15:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,22 +24,24 @@ #include "CheckAudioFormat.hxx" #include "pcm/Traits.hxx" #include "tag/TagHandler.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "util/Macros.hxx" #include "util/Clamp.hxx" +#include "util/ScopeExit.hxx" #include "Log.hxx" #include +#include + #include struct mpc_decoder_data { InputStream &is; - Decoder *decoder; + DecoderClient *client; - mpc_decoder_data(InputStream &_is, Decoder *_decoder) - :is(_is), decoder(_decoder) {} + mpc_decoder_data(InputStream &_is, DecoderClient *_client) + :is(_is), client(_client) {} }; static constexpr Domain mpcdec_domain("mpcdec"); @@ -53,7 +55,7 @@ struct mpc_decoder_data *data = (struct mpc_decoder_data *)reader->data; - return decoder_read(data->decoder, data->is, ptr, size); + return decoder_read(data->client, data->is, ptr, size); } static mpc_bool_t @@ -62,7 +64,12 @@ struct mpc_decoder_data *data = (struct mpc_decoder_data *)reader->data; - return data->is.LockSeek(offset, IgnoreError()); + try { + data->is.LockSeek(offset); + return true; + } catch (const std::runtime_error &) { + return false; + } } static mpc_int32_t @@ -132,11 +139,9 @@ } static void -mpcdec_decode(Decoder &mpd_decoder, InputStream &is) +mpcdec_decode(DecoderClient &client, InputStream &is) { - MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; - - mpc_decoder_data data(is, &mpd_decoder); + mpc_decoder_data data(is, &client); mpc_reader reader; reader.read = mpc_read_cb; @@ -148,55 +153,48 @@ mpc_demux *demux = mpc_demux_init(&reader); if (demux == nullptr) { - if (decoder_get_command(mpd_decoder) != DecoderCommand::STOP) + if (client.GetCommand() != DecoderCommand::STOP) LogWarning(mpcdec_domain, "Not a valid musepack stream"); return; } + AtScopeExit(demux) { mpc_demux_exit(demux); }; + mpc_streaminfo info; mpc_demux_get_info(demux, &info); - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, info.sample_freq, - mpcdec_sample_format, - info.channels, error)) { - LogError(error); - mpc_demux_exit(demux); - return; - } + auto audio_format = CheckAudioFormat(info.sample_freq, + mpcdec_sample_format, + info.channels); ReplayGainInfo rgi; rgi.Clear(); - rgi.tuples[REPLAY_GAIN_ALBUM].gain = MPC_OLD_GAIN_REF - (info.gain_album / 256.); - rgi.tuples[REPLAY_GAIN_ALBUM].peak = pow(10, info.peak_album / 256. / 20) / 32767; - rgi.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.); - rgi.tuples[REPLAY_GAIN_TRACK].peak = pow(10, info.peak_title / 256. / 20) / 32767; - - decoder_replay_gain(mpd_decoder, &rgi); - - decoder_initialized(mpd_decoder, audio_format, - is.IsSeekable(), - SongTime::FromS(mpc_streaminfo_get_length(&info))); + rgi.album.gain = MPC_OLD_GAIN_REF - (info.gain_album / 256.); + rgi.album.peak = pow(10, info.peak_album / 256. / 20) / 32767; + rgi.track.gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.); + rgi.track.peak = pow(10, info.peak_title / 256. / 20) / 32767; + + client.SubmitReplayGain(&rgi); + + client.Ready(audio_format, is.IsSeekable(), + SongTime::FromS(mpc_streaminfo_get_length(&info))); DecoderCommand cmd = DecoderCommand::NONE; do { if (cmd == DecoderCommand::SEEK) { - mpc_int64_t where = - decoder_seek_where_frame(mpd_decoder); + mpc_int64_t where = client.GetSeekFrame(); bool success; success = mpc_demux_seek_sample(demux, where) == MPC_STATUS_OK; if (success) - decoder_command_finished(mpd_decoder); + client.CommandFinished(); else - decoder_seek_error(mpd_decoder); + client.SeekError(); } - mpc_uint32_t vbr_update_bits = 0; - + MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; mpc_frame_info frame; frame.buffer = (MPC_SAMPLE_FORMAT *)sample_buffer; mpc_status status = mpc_demux_decode(demux, &frame); @@ -209,21 +207,28 @@ if (frame.bits == -1) break; + if (frame.samples <= 0) { + /* empty frame - this has been observed to + happen spuriously after seeking; skip this + obscure frame, and hope libmpcdec + recovers */ + cmd = client.GetCommand(); + continue; + } + mpc_uint32_t ret = frame.samples; ret *= info.channels; MpcdecSampleTraits::value_type chunk[ARRAY_SIZE(sample_buffer)]; mpc_to_mpd_buffer(chunk, sample_buffer, ret); - long bit_rate = vbr_update_bits * audio_format.sample_rate - / 1152 / 1000; + long bit_rate = unsigned(frame.bits) * audio_format.sample_rate + / (1000 * frame.samples); - cmd = decoder_data(mpd_decoder, is, - chunk, ret * sizeof(chunk[0]), - bit_rate); + cmd = client.SubmitData(is, + chunk, ret * sizeof(chunk[0]), + bit_rate); } while (cmd != DecoderCommand::STOP); - - mpc_demux_exit(demux); } static SignedSongTime @@ -243,16 +248,17 @@ if (demux == nullptr) return SignedSongTime::Negative(); + AtScopeExit(demux) { mpc_demux_exit(demux); }; + mpc_streaminfo info; mpc_demux_get_info(demux, &info); - mpc_demux_exit(demux); return SongTime::FromS(mpc_streaminfo_get_length(&info)); } static bool mpcdec_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const auto duration = mpcdec_get_file_duration(is); if (duration.IsNegative()) diff -Nru mpd-0.19.21/src/decoder/plugins/MpcdecDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/MpcdecDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/MpcdecDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/MpcdecDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/Mpg123DecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/Mpg123DecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/Mpg123DecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/Mpg123DecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,8 +26,8 @@ #include "tag/ReplayGain.hxx" #include "tag/MixRamp.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" +#include "util/StringView.hxx" #include "Log.hxx" #include @@ -37,7 +37,7 @@ static constexpr Domain mpg123_domain("mpg123"); static bool -mpd_mpg123_init(gcc_unused const config_param ¶m) +mpd_mpg123_init(gcc_unused const ConfigBlock &block) { mpg123_init(); @@ -94,13 +94,7 @@ return false; } - Error error2; - if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16, - channels, error2)) { - LogError(error2); - return false; - } - + audio_format = CheckAudioFormat(rate, SampleFormat::S16, channels); return true; } @@ -111,7 +105,7 @@ assert(s.size >= s.fill); assert(s.fill > 0); - tag.AddItem(type, s.p, s.fill - 1); + tag.AddItem(type, {s.p, s.fill - 1}); } static void @@ -122,7 +116,7 @@ } static void -mpd_mpg123_id3v2_tag(Decoder &decoder, const mpg123_id3v2 &id3v2) +mpd_mpg123_id3v2_tag(DecoderClient &client, const mpg123_id3v2 &id3v2) { TagBuilder tag; @@ -135,11 +129,11 @@ for (size_t i = 0, n = id3v2.comments; i < n; ++i) AddTagItem(tag, TAG_COMMENT, id3v2.comment_list[i].text); - decoder_tag(decoder, nullptr, tag.Commit()); + client.SubmitTag(nullptr, tag.Commit()); } static void -mpd_mpg123_id3v2_extras(Decoder &decoder, const mpg123_id3v2 &id3v2) +mpd_mpg123_id3v2_extras(DecoderClient &client, const mpg123_id3v2 &id3v2) { ReplayGainInfo replay_gain; replay_gain.Clear(); @@ -160,21 +154,21 @@ } if (found_replay_gain) - decoder_replay_gain(decoder, &replay_gain); + client.SubmitReplayGain(&replay_gain); if (found_mixramp) - decoder_mixramp(decoder, std::move(mix_ramp)); + client.SubmitMixRamp(std::move(mix_ramp)); } static void -mpd_mpg123_id3v2(Decoder &decoder, const mpg123_id3v2 &id3v2) +mpd_mpg123_id3v2(DecoderClient &client, const mpg123_id3v2 &id3v2) { - mpd_mpg123_id3v2_tag(decoder, id3v2); - mpd_mpg123_id3v2_extras(decoder, id3v2); + mpd_mpg123_id3v2_tag(client, id3v2); + mpd_mpg123_id3v2_extras(client, id3v2); } static void -mpd_mpg123_meta(Decoder &decoder, mpg123_handle *const handle) +mpd_mpg123_meta(DecoderClient &client, mpg123_handle *const handle) { if ((mpg123_meta_check(handle) & MPG123_NEW_ID3) == 0) return; @@ -185,11 +179,11 @@ return; if (v2 != nullptr) - mpd_mpg123_id3v2(decoder, *v2); + mpd_mpg123_id3v2(client, *v2); } static void -mpd_mpg123_file_decode(Decoder &decoder, Path path_fs) +mpd_mpg123_file_decode(DecoderClient &client, Path path_fs) { /* open the file */ @@ -216,7 +210,7 @@ SongTime::FromScale(num_samples, audio_format.sample_rate); - decoder_initialized(decoder, audio_format, true, duration); + client.Ready(audio_format, true, duration); struct mpg123_frameinfo info; if (mpg123_info(handle, &info) != MPG123_OK) { @@ -238,7 +232,7 @@ DecoderCommand cmd; do { /* read metadata */ - mpd_mpg123_meta(decoder, handle); + mpd_mpg123_meta(client, handle); /* decode */ @@ -263,16 +257,16 @@ /* send to MPD */ - cmd = decoder_data(decoder, nullptr, buffer, nbytes, info.bitrate); + cmd = client.SubmitData(nullptr, buffer, nbytes, info.bitrate); if (cmd == DecoderCommand::SEEK) { - off_t c = decoder_seek_where_frame(decoder); + off_t c = client.GetSeekFrame(); c = mpg123_seek(handle, c, SEEK_SET); if (c < 0) - decoder_seek_error(decoder); + client.SeekError(); else { - decoder_command_finished(decoder); - decoder_timestamp(decoder, c/(double)audio_format.sample_rate); + client.CommandFinished(); + client.SubmitTimestamp(c / (double)audio_format.sample_rate); } cmd = DecoderCommand::NONE; @@ -286,7 +280,7 @@ static bool mpd_mpg123_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { int error; mpg123_handle *const handle = mpg123_new(nullptr, &error); diff -Nru mpd-0.19.21/src/decoder/plugins/Mpg123DecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/Mpg123DecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/Mpg123DecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/Mpg123DecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OggCodec.cxx mpd-0.20.9/src/decoder/plugins/OggCodec.cxx --- mpd-0.19.21/src/decoder/plugins/OggCodec.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggCodec.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,13 +28,13 @@ #include enum ogg_codec -ogg_codec_detect(Decoder *decoder, InputStream &is) +ogg_codec_detect(DecoderClient *client, InputStream &is) { /* oggflac detection based on code in ogg123 and this post * http://lists.xiph.org/pipermail/flac/2004-December/000393.html * ogg123 trunk still doesn't have this patch as of June 2005 */ unsigned char buf[41]; - size_t r = decoder_read(decoder, is, buf, sizeof(buf)); + size_t r = decoder_read(client, is, buf, sizeof(buf)); if (r < sizeof(buf) || memcmp(buf, "OggS", 4) != 0) return OGG_CODEC_UNKNOWN; diff -Nru mpd-0.19.21/src/decoder/plugins/OggCodec.hxx mpd-0.20.9/src/decoder/plugins/OggCodec.hxx --- mpd-0.19.21/src/decoder/plugins/OggCodec.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggCodec.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,7 @@ #ifndef MPD_OGG_CODEC_HXX #define MPD_OGG_CODEC_HXX -struct Decoder; +class DecoderClient; class InputStream; enum ogg_codec { @@ -35,6 +35,6 @@ }; enum ogg_codec -ogg_codec_detect(Decoder *decoder, InputStream &is); +ogg_codec_detect(DecoderClient *client, InputStream &is); #endif /* _OGG_COMMON_H */ diff -Nru mpd-0.19.21/src/decoder/plugins/OggDecoder.cxx mpd-0.20.9/src/decoder/plugins/OggDecoder.cxx --- mpd-0.19.21/src/decoder/plugins/OggDecoder.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggDecoder.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" /* must be first for large file support */ +#include "OggDecoder.hxx" +#include "lib/xiph/OggFind.hxx" +#include "input/InputStream.hxx" + +#include + +/** + * Load the end-of-stream packet and restore the previous file + * position. + */ +bool +OggDecoder::LoadEndPacket(ogg_packet &packet) const +{ + if (!input_stream.CheapSeeking()) + /* we do this for local files only, because seeking + around remote files is expensive and not worth the + trouble */ + return false; + + const auto old_offset = input_stream.GetOffset(); + + /* create temporary Ogg objects for seeking and parsing the + EOS packet */ + + bool result; + + { + DecoderReader reader(client, input_stream); + OggSyncState sync2(reader); + OggStreamState stream2(GetSerialNo()); + result = OggSeekFindEOS(sync2, stream2, packet, + input_stream); + } + + /* restore the previous file position */ + try { + input_stream.LockSeek(old_offset); + } catch (const std::runtime_error &) { + } + + return result; +} + +ogg_int64_t +OggDecoder::LoadEndGranulePos() const +{ + ogg_packet packet; + if (!LoadEndPacket(packet)) + return -1; + + return packet.granulepos; +} + +void +OggDecoder::SeekGranulePos(ogg_int64_t where_granulepos) +{ + assert(IsSeekable()); + + /* interpolate the file offset where we expect to find the + given granule position */ + /* TODO: implement binary search */ + offset_type offset(where_granulepos * input_stream.GetSize() + / end_granulepos); + + input_stream.LockSeek(offset); + PostSeek(); +} + diff -Nru mpd-0.19.21/src/decoder/plugins/OggDecoder.hxx mpd-0.20.9/src/decoder/plugins/OggDecoder.hxx --- mpd-0.19.21/src/decoder/plugins/OggDecoder.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggDecoder.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_DECODER_HXX +#define MPD_OGG_DECODER_HXX + +#include "config.h" /* must be first for large file support */ +#include "lib/xiph/OggVisitor.hxx" +#include "decoder/Reader.hxx" + +class OggDecoder : public OggVisitor { + ogg_int64_t end_granulepos; + +protected: + DecoderClient &client; + InputStream &input_stream; + +public: + explicit OggDecoder(DecoderReader &reader) + :OggVisitor(reader), + client(reader.GetClient()), + input_stream(reader.GetInputStream()) {} + + bool Seek(OggSyncState &oy, uint64_t where_frame); + +private: + /** + * Load the end-of-stream packet and restore the previous file + * position. + */ + bool LoadEndPacket(ogg_packet &packet) const; + ogg_int64_t LoadEndGranulePos() const; + +protected: + ogg_int64_t UpdateEndGranulePos() { + return end_granulepos = LoadEndGranulePos(); + } + + bool IsSeekable() const { + return end_granulepos > 0; + } + + void SeekGranulePos(ogg_int64_t where_granulepos); +}; + +#endif diff -Nru mpd-0.19.21/src/decoder/plugins/OggFind.cxx mpd-0.20.9/src/decoder/plugins/OggFind.cxx --- mpd-0.19.21/src/decoder/plugins/OggFind.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggFind.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "OggFind.hxx" -#include "OggSyncState.hxx" -#include "input/InputStream.hxx" -#include "util/Error.hxx" - -bool -OggFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet) -{ - while (true) { - int r = ogg_stream_packetout(&os, &packet); - if (r == 0) { - if (!oy.ExpectPageIn(os)) - return false; - - continue; - } else if (r > 0 && packet.e_o_s) - return true; - } -} - -bool -OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is, - offset_type offset) -{ - oy.Reset(); - - /* reset the stream to clear any previous partial packet - data */ - ogg_stream_reset(&os); - - return is.LockSeek(offset, IgnoreError()) && - oy.ExpectPageSeekIn(os); -} - -bool -OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, - InputStream &is) -{ - if (!is.KnownSize()) - return false; - - if (is.GetRest() < 65536) - return OggFindEOS(oy, os, packet); - - if (!is.CheapSeeking()) - return false; - - return OggSeekPageAtOffset(oy, os, is, is.GetSize() - 65536) && - OggFindEOS(oy, os, packet); -} diff -Nru mpd-0.19.21/src/decoder/plugins/OggFind.hxx mpd-0.20.9/src/decoder/plugins/OggFind.hxx --- mpd-0.19.21/src/decoder/plugins/OggFind.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggFind.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OGG_FIND_HXX -#define MPD_OGG_FIND_HXX - -#include "check.h" -#include "input/Offset.hxx" - -#include - -class OggSyncState; -class InputStream; - -/** - * Skip all pages/packets until an end-of-stream (EOS) packet for the - * specified stream is found. - * - * @return true if the EOS packet was found - */ -bool -OggFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet); - -/** - * Seek the #InputStream and find the next Ogg page. - */ -bool -OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is, - offset_type offset); - -/** - * Try to find the end-of-stream (EOS) packet. Seek to the end of the - * file if necessary. - * - * @return true if the EOS packet was found - */ -bool -OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, - InputStream &is); - -#endif diff -Nru mpd-0.19.21/src/decoder/plugins/OggSyncState.hxx mpd-0.20.9/src/decoder/plugins/OggSyncState.hxx --- mpd-0.19.21/src/decoder/plugins/OggSyncState.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggSyncState.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OGG_SYNC_STATE_HXX -#define MPD_OGG_SYNC_STATE_HXX - -#include "check.h" -#include "OggUtil.hxx" - -#include - -#include - -/** - * Wrapper for an ogg_sync_state. - */ -class OggSyncState { - ogg_sync_state oy; - - InputStream &is; - Decoder *const decoder; - -public: - OggSyncState(InputStream &_is, Decoder *const _decoder=nullptr) - :is(_is), decoder(_decoder) { - ogg_sync_init(&oy); - } - - ~OggSyncState() { - ogg_sync_clear(&oy); - } - - void Reset() { - ogg_sync_reset(&oy); - } - - bool Feed(size_t size) { - return OggFeed(oy, decoder, is, size); - } - - bool ExpectPage(ogg_page &page) { - return OggExpectPage(oy, page, decoder, is); - } - - bool ExpectFirstPage(ogg_stream_state &os) { - return OggExpectFirstPage(oy, os, decoder, is); - } - - bool ExpectPageIn(ogg_stream_state &os) { - return OggExpectPageIn(oy, os, decoder, is); - } - - bool ExpectPageSeek(ogg_page &page) { - return OggExpectPageSeek(oy, page, decoder, is); - } - - bool ExpectPageSeekIn(ogg_stream_state &os) { - return OggExpectPageSeekIn(oy, os, decoder, is); - } -}; - -#endif diff -Nru mpd-0.19.21/src/decoder/plugins/OggUtil.cxx mpd-0.20.9/src/decoder/plugins/OggUtil.cxx --- mpd-0.19.21/src/decoder/plugins/OggUtil.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggUtil.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "OggUtil.hxx" -#include "../DecoderAPI.hxx" - -bool -OggFeed(ogg_sync_state &oy, Decoder *decoder, - InputStream &input_stream, size_t size) -{ - char *buffer = ogg_sync_buffer(&oy, size); - if (buffer == nullptr) - return false; - - size_t nbytes = decoder_read(decoder, input_stream, - buffer, size); - if (nbytes == 0) - return false; - - ogg_sync_wrote(&oy, nbytes); - return true; -} - -bool -OggExpectPage(ogg_sync_state &oy, ogg_page &page, - Decoder *decoder, InputStream &input_stream) -{ - while (true) { - int r = ogg_sync_pageout(&oy, &page); - if (r != 0) - return r > 0; - - if (!OggFeed(oy, decoder, input_stream, 1024)) - return false; - } -} - -bool -OggExpectFirstPage(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is) -{ - ogg_page page; - if (!OggExpectPage(oy, page, decoder, is)) - return false; - - ogg_stream_init(&os, ogg_page_serialno(&page)); - ogg_stream_pagein(&os, &page); - return true; -} - -bool -OggExpectPageIn(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is) -{ - ogg_page page; - if (!OggExpectPage(oy, page, decoder, is)) - return false; - - ogg_stream_pagein(&os, &page); - return true; -} - -bool -OggExpectPageSeek(ogg_sync_state &oy, ogg_page &page, - Decoder *decoder, InputStream &input_stream) -{ - size_t remaining_skipped = 32768; - - while (true) { - int r = ogg_sync_pageseek(&oy, &page); - if (r > 0) - return true; - - if (r < 0) { - /* skipped -r bytes */ - size_t nbytes = -r; - if (nbytes > remaining_skipped) - /* still no ogg page - we lost our - patience, abort */ - return false; - - remaining_skipped -= nbytes; - continue; - } - - if (!OggFeed(oy, decoder, input_stream, 1024)) - return false; - } -} - -bool -OggExpectPageSeekIn(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is) -{ - ogg_page page; - if (!OggExpectPageSeek(oy, page, decoder, is)) - return false; - - ogg_stream_pagein(&os, &page); - return true; -} diff -Nru mpd-0.19.21/src/decoder/plugins/OggUtil.hxx mpd-0.20.9/src/decoder/plugins/OggUtil.hxx --- mpd-0.19.21/src/decoder/plugins/OggUtil.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OggUtil.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OGG_UTIL_HXX -#define MPD_OGG_UTIL_HXX - -#include "check.h" - -#include - -#include - -class InputStream; -struct Decoder; - -/** - * Feed data from the #InputStream into the #ogg_sync_state. - * - * @return false on error or end-of-file - */ -bool -OggFeed(ogg_sync_state &oy, Decoder *decoder, InputStream &is, - size_t size); - -/** - * Feed into the #ogg_sync_state until a page gets available. Garbage - * data at the beginning is considered a fatal error. - * - * @return true if a page is available - */ -bool -OggExpectPage(ogg_sync_state &oy, ogg_page &page, - Decoder *decoder, InputStream &is); - -/** - * Combines OggExpectPage(), ogg_stream_init() and - * ogg_stream_pagein(). - * - * @return true if the stream was initialized and the first page was - * delivered to it - */ -bool -OggExpectFirstPage(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is); - -/** - * Combines OggExpectPage() and ogg_stream_pagein(). - * - * @return true if a page was delivered to the stream - */ -bool -OggExpectPageIn(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is); - -/** - * Like OggExpectPage(), but allow skipping garbage (after seeking). - */ -bool -OggExpectPageSeek(ogg_sync_state &oy, ogg_page &page, - Decoder *decoder, InputStream &is); - -/** - * Combines OggExpectPageSeek() and ogg_stream_pagein(). - * - * @return true if a page was delivered to the stream - */ -bool -OggExpectPageSeekIn(ogg_sync_state &oy, ogg_stream_state &os, - Decoder *decoder, InputStream &is); - -#endif diff -Nru mpd-0.19.21/src/decoder/plugins/OpusDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/OpusDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/OpusDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusDecoderPlugin.cxx 2017-06-04 10:35:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,24 +19,28 @@ #include "config.h" /* must be first for large file support */ #include "OpusDecoderPlugin.h" +#include "OggDecoder.hxx" #include "OpusDomain.hxx" #include "OpusHead.hxx" #include "OpusTags.hxx" -#include "OggFind.hxx" -#include "OggSyncState.hxx" +#include "lib/xiph/OggPacket.hxx" +#include "lib/xiph/OggFind.hxx" #include "../DecoderAPI.hxx" +#include "decoder/Reader.hxx" +#include "input/Reader.hxx" #include "OggCodec.hxx" #include "tag/TagHandler.hxx" #include "tag/TagBuilder.hxx" #include "input/InputStream.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include #include #include -#include + +namespace { static constexpr opus_int32 opus_sample_rate = 48000; @@ -48,34 +52,29 @@ gcc_pure static bool -IsOpusHead(const ogg_packet &packet) +IsOpusHead(const ogg_packet &packet) noexcept { return packet.bytes >= 8 && memcmp(packet.packet, "OpusHead", 8) == 0; } gcc_pure static bool -IsOpusTags(const ogg_packet &packet) +IsOpusTags(const ogg_packet &packet) noexcept { return packet.bytes >= 8 && memcmp(packet.packet, "OpusTags", 8) == 0; } static bool -mpd_opus_init(gcc_unused const config_param ¶m) +mpd_opus_init(gcc_unused const ConfigBlock &block) { LogDebug(opus_domain, opus_get_version_string()); return true; } -class MPDOpusDecoder { - Decoder &decoder; - InputStream &input_stream; - - ogg_stream_state os; - - OpusDecoder *opus_decoder; - opus_int16 *output_buffer; +class MPDOpusDecoder final : public OggDecoder { + OpusDecoder *opus_decoder = nullptr; + opus_int16 *output_buffer = nullptr; /** * If non-zero, then a previous Opus stream has been found @@ -83,37 +82,34 @@ * nullptr, then its end-of-stream packet has been found * already. */ - unsigned previous_channels; - - bool os_initialized; - - int opus_serialno; - - ogg_int64_t eos_granulepos; + unsigned previous_channels = 0; size_t frame_size; public: - MPDOpusDecoder(Decoder &_decoder, - InputStream &_input_stream) - :decoder(_decoder), input_stream(_input_stream), - opus_decoder(nullptr), - output_buffer(nullptr), - previous_channels(0), - os_initialized(false) {} + explicit MPDOpusDecoder(DecoderReader &reader) + :OggDecoder(reader) {} + ~MPDOpusDecoder(); - bool ReadFirstPage(OggSyncState &oy); - bool ReadNextPage(OggSyncState &oy); + /** + * Has DecoderClient::Ready() been called yet? + */ + bool IsInitialized() const { + return previous_channels != 0; + } + + bool Seek(uint64_t where_frame); - DecoderCommand HandlePackets(); - DecoderCommand HandlePacket(const ogg_packet &packet); - DecoderCommand HandleBOS(const ogg_packet &packet); - DecoderCommand HandleEOS(); - DecoderCommand HandleTags(const ogg_packet &packet); - DecoderCommand HandleAudio(const ogg_packet &packet); +private: + void HandleTags(const ogg_packet &packet); + void HandleAudio(const ogg_packet &packet); - bool Seek(OggSyncState &oy, uint64_t where_frame); +protected: + /* virtual methods from class OggVisitor */ + void OnOggBeginning(const ogg_packet &packet) override; + void OnOggPacket(const ogg_packet &packet) override; + void OnOggEnd() override; }; MPDOpusDecoder::~MPDOpusDecoder() @@ -122,148 +118,36 @@ if (opus_decoder != nullptr) opus_decoder_destroy(opus_decoder); - - if (os_initialized) - ogg_stream_clear(&os); } -inline bool -MPDOpusDecoder::ReadFirstPage(OggSyncState &oy) +void +MPDOpusDecoder::OnOggPacket(const ogg_packet &packet) { - assert(!os_initialized); - - if (!oy.ExpectFirstPage(os)) - return false; - - os_initialized = true; - return true; -} - -inline bool -MPDOpusDecoder::ReadNextPage(OggSyncState &oy) -{ - assert(os_initialized); - - ogg_page page; - if (!oy.ExpectPage(page)) - return false; - - const auto page_serialno = ogg_page_serialno(&page); - if (page_serialno != os.serialno) - ogg_stream_reset_serialno(&os, page_serialno); - - ogg_stream_pagein(&os, &page); - return true; -} - -inline DecoderCommand -MPDOpusDecoder::HandlePackets() -{ - ogg_packet packet; - while (ogg_stream_packetout(&os, &packet) == 1) { - auto cmd = HandlePacket(packet); - if (cmd != DecoderCommand::NONE) - return cmd; - } - - return DecoderCommand::NONE; -} - -inline DecoderCommand -MPDOpusDecoder::HandlePacket(const ogg_packet &packet) -{ - if (packet.e_o_s) - return HandleEOS(); - - if (packet.b_o_s) - return HandleBOS(packet); - else if (opus_decoder == nullptr) { - LogDebug(opus_domain, "BOS packet expected"); - return DecoderCommand::STOP; - } - if (IsOpusTags(packet)) - return HandleTags(packet); - - return HandleAudio(packet); -} - -/** - * Load the end-of-stream packet and restore the previous file - * position. - */ -static bool -LoadEOSPacket(InputStream &is, Decoder *decoder, int serialno, - ogg_packet &packet) -{ - if (!is.CheapSeeking()) - /* we do this for local files only, because seeking - around remote files is expensive and not worth the - troubl */ - return false; - - const auto old_offset = is.GetOffset(); - - /* create temporary Ogg objects for seeking and parsing the - EOS packet */ - OggSyncState oy(is, decoder); - ogg_stream_state os; - ogg_stream_init(&os, serialno); - - bool result = OggSeekFindEOS(oy, os, packet, is); - ogg_stream_clear(&os); - - /* restore the previous file position */ - is.LockSeek(old_offset, IgnoreError()); - - return result; -} - -/** - * Load the end-of-stream granulepos and restore the previous file - * position. - * - * @return -1 on error - */ -gcc_pure -static ogg_int64_t -LoadEOSGranulePos(InputStream &is, Decoder *decoder, int serialno) -{ - ogg_packet packet; - if (!LoadEOSPacket(is, decoder, serialno, packet)) - return -1; - - return packet.granulepos; + HandleTags(packet); + else + HandleAudio(packet); } -inline DecoderCommand -MPDOpusDecoder::HandleBOS(const ogg_packet &packet) +void +MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet) { assert(packet.b_o_s); - if (opus_decoder != nullptr || !IsOpusHead(packet)) { - LogDebug(opus_domain, "BOS packet must be OpusHead"); - return DecoderCommand::STOP; - } + if (opus_decoder != nullptr || !IsOpusHead(packet)) + throw std::runtime_error("BOS packet must be OpusHead"); unsigned channels; if (!ScanOpusHeader(packet.packet, packet.bytes, channels) || - !audio_valid_channel_count(channels)) { - LogDebug(opus_domain, "Malformed BOS packet"); - return DecoderCommand::STOP; - } + !audio_valid_channel_count(channels)) + throw std::runtime_error("Malformed BOS packet"); assert(opus_decoder == nullptr); - assert((previous_channels == 0) == (output_buffer == nullptr)); + assert(IsInitialized() == (output_buffer != nullptr)); - if (previous_channels != 0 && channels != previous_channels) { - FormatWarning(opus_domain, - "Next stream has different channels (%u -> %u)", - previous_channels, channels); - return DecoderCommand::STOP; - } - - opus_serialno = os.serialno; + if (IsInitialized() && channels != previous_channels) + throw FormatRuntimeError("Next stream has different channels (%u -> %u)", + previous_channels, channels); /* TODO: parse attributes from the OpusHead (sample rate, channels, ...) */ @@ -271,21 +155,18 @@ int opus_error; opus_decoder = opus_decoder_create(opus_sample_rate, channels, &opus_error); - if (opus_decoder == nullptr) { - FormatError(opus_domain, "libopus error: %s", - opus_strerror(opus_error)); - return DecoderCommand::STOP; - } + if (opus_decoder == nullptr) + throw FormatRuntimeError("libopus error: %s", + opus_strerror(opus_error)); - if (previous_channels != 0) { + if (IsInitialized()) { /* decoder was already initialized by the previous stream; skip the rest of this method */ LogDebug(opus_domain, "Found another stream"); - return decoder_get_command(decoder); + return; } - eos_granulepos = LoadEOSGranulePos(input_stream, &decoder, - opus_serialno); + const auto eos_granulepos = UpdateEndGranulePos(); const auto duration = eos_granulepos >= 0 ? SignedSongTime::FromScale(eos_granulepos, opus_sample_rate) @@ -294,34 +175,32 @@ previous_channels = channels; const AudioFormat audio_format(opus_sample_rate, SampleFormat::S16, channels); - decoder_initialized(decoder, audio_format, - eos_granulepos > 0, duration); + client.Ready(audio_format, eos_granulepos > 0, duration); frame_size = audio_format.GetFrameSize(); output_buffer = new opus_int16[opus_output_buffer_frames * audio_format.channels]; - return decoder_get_command(decoder); + auto cmd = client.GetCommand(); + if (cmd != DecoderCommand::NONE) + throw cmd; } -inline DecoderCommand -MPDOpusDecoder::HandleEOS() +void +MPDOpusDecoder::OnOggEnd() { - if (eos_granulepos < 0 && previous_channels != 0) { + if (!IsSeekable() && IsInitialized()) { /* allow chaining of (unseekable) streams */ assert(opus_decoder != nullptr); assert(output_buffer != nullptr); opus_decoder_destroy(opus_decoder); opus_decoder = nullptr; - - return decoder_get_command(decoder); - } - - return DecoderCommand::STOP; + } else + throw StopDecoder(); } -inline DecoderCommand +inline void MPDOpusDecoder::HandleTags(const ogg_packet &packet) { ReplayGainInfo rgi; @@ -329,22 +208,20 @@ TagBuilder tag_builder; - DecoderCommand cmd; if (ScanOpusTags(packet.packet, packet.bytes, &rgi, - &add_tag_handler, &tag_builder) && + add_tag_handler, &tag_builder) && !tag_builder.IsEmpty()) { - decoder_replay_gain(decoder, &rgi); + client.SubmitReplayGain(&rgi); Tag tag = tag_builder.Commit(); - cmd = decoder_tag(decoder, input_stream, std::move(tag)); - } else - cmd = decoder_get_command(decoder); - - return cmd; + auto cmd = client.SubmitTag(input_stream, std::move(tag)); + if (cmd != DecoderCommand::NONE) + throw cmd; + } } -inline DecoderCommand +inline void MPDOpusDecoder::HandleAudio(const ogg_packet &packet) { assert(opus_decoder != nullptr); @@ -354,156 +231,134 @@ packet.bytes, output_buffer, opus_output_buffer_frames, 0); - if (nframes < 0) { - FormatError(opus_domain, "libopus error: %s", - opus_strerror(nframes)); - return DecoderCommand::STOP; - } + if (nframes < 0) + throw FormatRuntimeError("libopus error: %s", + opus_strerror(nframes)); if (nframes > 0) { const size_t nbytes = nframes * frame_size; - auto cmd = decoder_data(decoder, input_stream, - output_buffer, nbytes, - 0); + auto cmd = client.SubmitData(input_stream, + output_buffer, nbytes, + 0); if (cmd != DecoderCommand::NONE) - return cmd; + throw cmd; if (packet.granulepos > 0) - decoder_timestamp(decoder, - double(packet.granulepos) - / opus_sample_rate); + client.SubmitTimestamp(double(packet.granulepos) + / opus_sample_rate); } - - return DecoderCommand::NONE; } bool -MPDOpusDecoder::Seek(OggSyncState &oy, uint64_t where_frame) +MPDOpusDecoder::Seek(uint64_t where_frame) { - assert(eos_granulepos > 0); + assert(IsSeekable()); assert(input_stream.IsSeekable()); assert(input_stream.KnownSize()); const ogg_int64_t where_granulepos(where_frame); - /* interpolate the file offset where we expect to find the - given granule position */ - /* TODO: implement binary search */ - offset_type offset(where_granulepos * input_stream.GetSize() - / eos_granulepos); - - return OggSeekPageAtOffset(oy, os, input_stream, offset); + try { + SeekGranulePos(where_granulepos); + return true; + } catch (const std::runtime_error &) { + return false; + } } static void -mpd_opus_stream_decode(Decoder &decoder, +mpd_opus_stream_decode(DecoderClient &client, InputStream &input_stream) { - if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_OPUS) + if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_OPUS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream.LockRewind(IgnoreError()); + try { + input_stream.LockRewind(); + } catch (const std::runtime_error &) { + } - MPDOpusDecoder d(decoder, input_stream); - OggSyncState oy(input_stream, &decoder); + DecoderReader reader(client, input_stream); - if (!d.ReadFirstPage(oy)) - return; + MPDOpusDecoder d(reader); while (true) { - auto cmd = d.HandlePackets(); - if (cmd == DecoderCommand::SEEK) { - if (d.Seek(oy, decoder_seek_where_frame(decoder))) - decoder_command_finished(decoder); - else - decoder_seek_error(decoder); - - continue; - } - - if (cmd != DecoderCommand::NONE) - break; - - if (!d.ReadNextPage(oy)) + try { + d.Visit(); break; + } catch (DecoderCommand cmd) { + if (cmd == DecoderCommand::SEEK) { + if (d.Seek(client.GetSeekFrame())) + client.CommandFinished(); + else + client.SeekError(); + } else if (cmd != DecoderCommand::NONE) + break; + } } } static bool -mpd_opus_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) +ReadAndParseOpusHead(OggSyncState &sync, OggStreamState &stream, + unsigned &channels) { - OggSyncState oy(is); - - ogg_stream_state os; - if (!oy.ExpectFirstPage(os)) - return false; - - /* read at most 64 more pages */ - unsigned remaining_pages = 64; - - unsigned remaining_packets = 4; - - bool result = false; - ogg_packet packet; - while (remaining_packets > 0) { - int r = ogg_stream_packetout(&os, &packet); - if (r < 0) { - result = false; - break; - } - if (r == 0) { - if (remaining_pages-- == 0) - break; - - if (!oy.ExpectPageIn(os)) { - result = false; - break; - } - - continue; - } - - --remaining_packets; - - if (packet.b_o_s) { - if (!IsOpusHead(packet)) - break; + return OggReadPacket(sync, stream, packet) && packet.b_o_s && + IsOpusHead(packet) && + ScanOpusHeader(packet.packet, packet.bytes, channels) && + audio_valid_channel_count(channels); +} - unsigned channels; - if (!ScanOpusHeader(packet.packet, packet.bytes, channels) || - !audio_valid_channel_count(channels)) { - result = false; - break; - } +static bool +ReadAndVisitOpusTags(OggSyncState &sync, OggStreamState &stream, + const TagHandler &handler, void *handler_ctx) +{ + ogg_packet packet; - result = true; - } else if (!result) - break; - else if (IsOpusTags(packet)) { - if (!ScanOpusTags(packet.packet, packet.bytes, - nullptr, - handler, handler_ctx)) - result = false; + return OggReadPacket(sync, stream, packet) && + IsOpusTags(packet) && + ScanOpusTags(packet.packet, packet.bytes, + nullptr, + handler, handler_ctx); +} - break; - } - } +static void +VisitOpusDuration(InputStream &is, OggSyncState &sync, OggStreamState &stream, + const TagHandler &handler, void *handler_ctx) +{ + ogg_packet packet; - if (packet.e_o_s || OggSeekFindEOS(oy, os, packet, is)) { + if (OggSeekFindEOS(sync, stream, packet, is)) { const auto duration = SongTime::FromScale(packet.granulepos, opus_sample_rate); tag_handler_invoke_duration(handler, handler_ctx, duration); } +} + +static bool +mpd_opus_scan_stream(InputStream &is, + const TagHandler &handler, void *handler_ctx) +{ + InputStreamReader reader(is); + OggSyncState oy(reader); + + ogg_page first_page; + if (!oy.ExpectPage(first_page)) + return false; + + OggStreamState os(first_page); - ogg_stream_clear(&os); + unsigned channels; + if (!ReadAndParseOpusHead(oy, os, channels) || + !ReadAndVisitOpusTags(oy, os, handler, handler_ctx)) + return false; - return result; + VisitOpusDuration(is, oy, os, handler, handler_ctx); + return true; } static const char *const opus_suffixes[] = { @@ -525,6 +380,8 @@ nullptr }; +} /* anonymous namespace */ + const struct DecoderPlugin opus_decoder_plugin = { "opus", mpd_opus_init, diff -Nru mpd-0.19.21/src/decoder/plugins/OpusDecoderPlugin.h mpd-0.20.9/src/decoder/plugins/OpusDecoderPlugin.h --- mpd-0.19.21/src/decoder/plugins/OpusDecoderPlugin.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusDecoderPlugin.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusDomain.cxx mpd-0.20.9/src/decoder/plugins/OpusDomain.cxx --- mpd-0.19.21/src/decoder/plugins/OpusDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusDomain.hxx mpd-0.20.9/src/decoder/plugins/OpusDomain.hxx --- mpd-0.19.21/src/decoder/plugins/OpusDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusHead.cxx mpd-0.20.9/src/decoder/plugins/OpusHead.cxx --- mpd-0.19.21/src/decoder/plugins/OpusHead.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusHead.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusHead.hxx mpd-0.20.9/src/decoder/plugins/OpusHead.hxx --- mpd-0.19.21/src/decoder/plugins/OpusHead.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusHead.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusReader.hxx mpd-0.20.9/src/decoder/plugins/OpusReader.hxx --- mpd-0.19.21/src/decoder/plugins/OpusReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/OpusTags.cxx mpd-0.20.9/src/decoder/plugins/OpusTags.cxx --- mpd-0.19.21/src/decoder/plugins/OpusTags.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusTags.cxx 2017-05-08 14:58:17.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ #include "config.h" #include "OpusTags.hxx" #include "OpusReader.hxx" -#include "XiphTags.hxx" +#include "lib/xiph/XiphTags.hxx" #include "tag/TagHandler.hxx" #include "tag/Tag.hxx" #include "ReplayGainInfo.hxx" @@ -31,7 +31,7 @@ gcc_pure static TagType -ParseOpusTagName(const char *name) +ParseOpusTagName(const char *name) noexcept { TagType type = tag_name_parse_i(name); if (type != TAG_NUM_OF_ITEM_TYPES) @@ -43,7 +43,7 @@ static void ScanOneOpusTag(const char *name, const char *value, ReplayGainInfo *rgi, - const struct tag_handler *handler, void *ctx) + const TagHandler &handler, void *ctx) { if (rgi != nullptr && strcmp(name, "R128_TRACK_GAIN") == 0) { /* R128_TRACK_GAIN is a Q7.8 fixed point number in @@ -52,12 +52,12 @@ char *endptr; long l = strtol(value, &endptr, 10); if (endptr > value && *endptr == 0) - rgi->tuples[REPLAY_GAIN_TRACK].gain = double(l) / 256.; + rgi->track.gain = double(l) / 256.; } tag_handler_invoke_pair(handler, ctx, name, value); - if (handler->tag != nullptr) { + if (handler.tag != nullptr) { TagType t = ParseOpusTagName(name); if (t != TAG_NUM_OF_ITEM_TYPES) tag_handler_invoke_tag(handler, ctx, t, value); @@ -67,13 +67,13 @@ bool ScanOpusTags(const void *data, size_t size, ReplayGainInfo *rgi, - const struct tag_handler *handler, void *ctx) + const TagHandler &handler, void *ctx) { OpusReader r(data, size); if (!r.Expect("OpusTags", 8)) return false; - if (handler->pair == nullptr && handler->tag == nullptr) + if (handler.pair == nullptr && handler.tag == nullptr) return true; if (!r.SkipString()) diff -Nru mpd-0.19.21/src/decoder/plugins/OpusTags.hxx mpd-0.20.9/src/decoder/plugins/OpusTags.hxx --- mpd-0.19.21/src/decoder/plugins/OpusTags.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/OpusTags.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,10 +25,11 @@ #include struct ReplayGainInfo; +struct TagHandler; bool ScanOpusTags(const void *data, size_t size, ReplayGainInfo *rgi, - const struct tag_handler *handler, void *ctx); + const TagHandler &handler, void *ctx); #endif diff -Nru mpd-0.19.21/src/decoder/plugins/PcmDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/PcmDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/PcmDecoderPlugin.cxx 2016-11-17 21:20:17.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/PcmDecoderPlugin.cxx 2017-04-24 18:36:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,24 +20,33 @@ #include "config.h" #include "PcmDecoderPlugin.hxx" #include "../DecoderAPI.hxx" +#include "CheckAudioFormat.hxx" #include "input/InputStream.hxx" -#include "util/Error.hxx" +#include "system/ByteOrder.hxx" +#include "util/Domain.hxx" #include "util/ByteReverse.hxx" #include "util/StaticFifoBuffer.hxx" +#include "util/NumberParser.hxx" +#include "util/MimeType.hxx" #include "Log.hxx" +#include + #include #include +static constexpr Domain pcm_decoder_domain("pcm_decoder"); + template static bool -FillBuffer(Decoder &decoder, InputStream &is, B &buffer) +FillBuffer(DecoderClient &client, InputStream &is, B &buffer) { buffer.Shift(); auto w = buffer.Write(); - assert(!w.IsEmpty()); + if (w.IsEmpty()) + return true; - size_t nbytes = decoder_read(decoder, is, w.data, w.size); + size_t nbytes = decoder_read(client, is, w.data, w.size); if (nbytes == 0 && is.LockIsEOF()) return false; @@ -46,17 +55,87 @@ } static void -pcm_stream_decode(Decoder &decoder, InputStream &is) +pcm_stream_decode(DecoderClient &client, InputStream &is) { - static constexpr AudioFormat audio_format = { + AudioFormat audio_format = { 44100, SampleFormat::S16, 2, }; const char *const mime = is.GetMimeType(); - const bool reverse_endian = mime != nullptr && - strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0; + + const bool l16 = mime != nullptr && + GetMimeTypeBase(mime) == "audio/L16"; + const bool is_float = mime != nullptr && + GetMimeTypeBase(mime) == "audio/x-mpd-float"; + if (l16 || is_float) { + audio_format.sample_rate = 0; + audio_format.channels = 1; + } + + const bool reverse_endian = (l16 && IsLittleEndian()) || + (mime != nullptr && + strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0); + + if (is_float) + audio_format.format = SampleFormat::FLOAT; + + if (mime != nullptr) { + const auto mime_parameters = ParseMimeTypeParameters(mime); + + /* MIME type parameters according to RFC 2586 */ + auto i = mime_parameters.find("rate"); + if (i != mime_parameters.end()) { + const char *s = i->second.c_str(); + char *endptr; + unsigned value = ParseUnsigned(s, &endptr); + if (endptr == s || *endptr != 0) { + FormatWarning(pcm_decoder_domain, + "Failed to parse sample rate: %s", + s); + return; + } + + try { + CheckSampleRate(value); + } catch (const std::runtime_error &e) { + LogError(e); + return; + } + + audio_format.sample_rate = value; + } + + i = mime_parameters.find("channels"); + if (i != mime_parameters.end()) { + const char *s = i->second.c_str(); + char *endptr; + unsigned value = ParseUnsigned(s, &endptr); + if (endptr == s || *endptr != 0) { + FormatWarning(pcm_decoder_domain, + "Failed to parse sample rate: %s", + s); + return; + } + + try { + CheckChannelCount(value); + } catch (const std::runtime_error &e) { + LogError(e); + return; + } + + audio_format.channels = value; + } + } + + if (audio_format.sample_rate == 0) { + FormatWarning(pcm_decoder_domain, + "Missing 'rate' parameter: %s", + mime); + return; + } const auto frame_size = audio_format.GetFrameSize(); @@ -65,19 +144,19 @@ audio_format.sample_rate) : SignedSongTime::Negative(); - decoder_initialized(decoder, audio_format, - is.IsSeekable(), total_time); + client.Ready(audio_format, is.IsSeekable(), total_time); StaticFifoBuffer buffer; DecoderCommand cmd; do { - if (!FillBuffer(decoder, is, buffer)) + if (!FillBuffer(client, is, buffer)) break; auto r = buffer.Read(); /* round down to the nearest frame size, because we - must not pass partial frames to decoder_data() */ + must not pass partial frames to + DecoderClient::SubmitData() */ r.size -= r.size % frame_size; buffer.Consume(r.size); @@ -88,19 +167,19 @@ (uint16_t *)(r.data + r.size)); cmd = !r.IsEmpty() - ? decoder_data(decoder, is, r.data, r.size, 0) - : decoder_get_command(decoder); + ? client.SubmitData(is, r.data, r.size, 0) + : client.GetCommand(); if (cmd == DecoderCommand::SEEK) { - uint64_t frame = decoder_seek_where_frame(decoder); + uint64_t frame = client.GetSeekFrame(); offset_type offset = frame * frame_size; - Error error; - if (is.LockSeek(offset, error)) { + try { + is.LockSeek(offset); buffer.Clear(); - decoder_command_finished(decoder); - } else { - LogError(error); - decoder_seek_error(decoder); + client.CommandFinished(); + } catch (const std::runtime_error &e) { + LogError(e); + client.SeekError(); } cmd = DecoderCommand::NONE; @@ -109,6 +188,12 @@ } static const char *const pcm_mime_types[] = { + /* RFC 2586 */ + "audio/L16", + + /* MPD-specific: float32 native-endian */ + "audio/x-mpd-float", + /* for streams obtained by the cdio_paranoia input plugin */ "audio/x-mpd-cdda-pcm", diff -Nru mpd-0.19.21/src/decoder/plugins/PcmDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/PcmDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/PcmDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/PcmDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/SidplayDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/SidplayDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/SidplayDecoderPlugin.cxx 2016-10-27 18:40:26.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/SidplayDecoderPlugin.cxx 2017-05-08 15:09:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,18 +21,16 @@ #include "SidplayDecoderPlugin.hxx" #include "../DecoderAPI.hxx" #include "tag/TagHandler.hxx" +#include "tag/TagBuilder.hxx" +#include "DetachedSong.hxx" #include "fs/Path.hxx" #include "fs/AllocatedPath.hxx" #include "util/Macros.hxx" #include "util/FormatString.hxx" #include "util/Domain.hxx" -#include "util/Error.hxx" #include "system/ByteOrder.hxx" -#include "system/FatalError.hxx" #include "Log.hxx" -#include - #ifdef HAVE_SIDPLAYFP #include #include @@ -49,6 +47,13 @@ #include #endif +#include +#include + +#ifdef HAVE_SIDPLAYFP +#define LIBSIDPLAYFP_VERSION GCC_MAKE_VERSION(LIBSIDPLAYFP_VERSION_MAJ, LIBSIDPLAYFP_VERSION_MIN, LIBSIDPLAYFP_VERSION_LEV) +#endif + #define SUBTUNE_PREFIX "tune_" static constexpr Domain sidplay_domain("sidplay"); @@ -81,22 +86,19 @@ } static bool -sidplay_init(const config_param ¶m) +sidplay_init(const ConfigBlock &block) { /* read the songlengths database file */ - Error error; - const auto database_path = param.GetBlockPath("songlength_database", error); + const auto database_path = block.GetPath("songlength_database"); if (!database_path.IsNull()) songlength_database = sidplay_load_songlength_db(database_path); - else if (error.IsDefined()) - FatalError(error); - default_songlength = param.GetBlockValue("default_songlength", 0u); + default_songlength = block.GetBlockValue("default_songlength", 0u); all_files_are_containers = - param.GetBlockValue("all_files_are_containers", true); + block.GetBlockValue("all_files_are_containers", true); - filter_setting = param.GetBlockValue("filter", true); + filter_setting = block.GetBlockValue("filter", true); return true; } @@ -114,7 +116,7 @@ gcc_pure static unsigned -ParseSubtuneName(const char *base) +ParseSubtuneName(const char *base) noexcept { if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0) return 0; @@ -145,27 +147,15 @@ return { path_fs.GetDirectoryName(), track }; } -#ifdef HAVE_SIDPLAYFP - -static SignedSongTime -get_song_length(SidTune &tune) -{ - if (songlength_database == nullptr) - return SignedSongTime::Negative(); - - const auto length = songlength_database->length(tune); - if (length < 0) - return SignedSongTime::Negative(); - - return SignedSongTime::FromS(length); -} - -#else - +/** + * This is a template, because libsidplay requires SidTuneMod while + * libsidplayfp requires just a plain Sidtune. + */ +template static SignedSongTime -get_song_length(SidTuneMod &tune) +get_song_length(T &tune) { - assert(tune); + assert(tune.getStatus()); if (songlength_database == nullptr) return SignedSongTime::Negative(); @@ -177,10 +167,8 @@ return SignedSongTime::FromS(length); } -#endif - static void -sidplay_file_decode(Decoder &decoder, Path path_fs) +sidplay_file_decode(DecoderClient &client, Path path_fs) { int channels; @@ -301,8 +289,12 @@ #endif #ifdef HAVE_SIDPLAYFP +#if LIBSIDPLAYFP_VERSION >= GCC_MAKE_VERSION(1,8,0) const bool stereo = tune.getInfo()->sidChips() >= 2; #else + const bool stereo = tune.getInfo()->isStereo(); +#endif +#else const bool stereo = tune.isStereo(); #endif @@ -338,7 +330,7 @@ const AudioFormat audio_format(48000, SampleFormat::S16, channels); assert(audio_format.IsValid()); - decoder_initialized(decoder, audio_format, true, duration); + client.Ready(audio_format, true, duration); /* .. and play */ @@ -367,14 +359,14 @@ const size_t nbytes = result; #endif - decoder_timestamp(decoder, (double)player.time() / timebase); + client.SubmitTimestamp((double)player.time() / timebase); - cmd = decoder_data(decoder, nullptr, buffer, nbytes, 0); + cmd = client.SubmitData(nullptr, buffer, nbytes, 0); if (cmd == DecoderCommand::SEEK) { unsigned data_time = player.time(); unsigned target_time = - decoder_seek_time(decoder).ToScale(timebase); + client.GetSeekTime().ToScale(timebase); /* can't rewind so return to zero and seek forward */ if(target_time 0) data_time = player.time(); - decoder_command_finished(decoder); + client.CommandFinished(); } if (end > 0 && player.time() >= end) @@ -398,7 +390,7 @@ gcc_pure static const char * -GetInfoString(const SidTuneInfo &info, unsigned i) +GetInfoString(const SidTuneInfo &info, unsigned i) noexcept { #ifdef HAVE_SIDPLAYFP return info.numberOfInfoStrings() > i @@ -411,31 +403,10 @@ #endif } -static bool -sidplay_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) +static void +ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks, + const TagHandler &handler, void *handler_ctx) { - const auto container = ParseContainerPath(path_fs); - const unsigned song_num = container.track; - -#ifdef HAVE_SIDPLAYFP - SidTune tune(container.path.c_str()); -#else - SidTuneMod tune(container.path.c_str()); -#endif - if (!tune.getStatus()) - return false; - - tune.selectSong(song_num); - -#ifdef HAVE_SIDPLAYFP - const SidTuneInfo &info = *tune.getInfo(); - const unsigned n_tracks = info.songs(); -#else - const SidTuneInfo &info = tune.getInfo(); - const unsigned n_tracks = info.songs; -#endif - /* title */ const char *title = GetInfoString(info, 0); if (title == nullptr) @@ -444,8 +415,8 @@ if (n_tracks > 1) { char tag_title[1024]; snprintf(tag_title, sizeof(tag_title), - "%s (%d/%u)", - title, song_num, n_tracks); + "%s (%u/%u)", + title, track, n_tracks); tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, tag_title); } else @@ -464,9 +435,37 @@ date); /* track */ - char track[16]; - sprintf(track, "%d", song_num); - tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track); + char track_buffer[16]; + sprintf(track_buffer, "%d", track); + tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track_buffer); +} + +static bool +sidplay_scan_file(Path path_fs, + const TagHandler &handler, void *handler_ctx) +{ + const auto container = ParseContainerPath(path_fs); + const unsigned song_num = container.track; + +#ifdef HAVE_SIDPLAYFP + SidTune tune(container.path.c_str()); +#else + SidTuneMod tune(container.path.c_str()); +#endif + if (!tune.getStatus()) + return false; + + tune.selectSong(song_num); + +#ifdef HAVE_SIDPLAYFP + const SidTuneInfo &info = *tune.getInfo(); + const unsigned n_tracks = info.songs(); +#else + const SidTuneInfo &info = tune.getInfo(); + const unsigned n_tracks = info.songs; +#endif + + ScanSidTuneInfo(info, song_num, n_tracks, handler, handler_ctx); /* time */ const auto duration = get_song_length(tune); @@ -477,12 +476,18 @@ return true; } -static char * -sidplay_container_scan(Path path_fs, const unsigned int tnum) +static std::forward_list +sidplay_container_scan(Path path_fs) { - SidTune tune(path_fs.c_str(), nullptr, true); + std::forward_list list; + +#ifdef HAVE_SIDPLAYFP + SidTune tune(path_fs.c_str()); +#else + SidTuneMod tune(path_fs.c_str()); +#endif if (!tune.getStatus()) - return nullptr; + return list; #ifdef HAVE_SIDPLAYFP const SidTuneInfo &info = *tune.getInfo(); @@ -495,14 +500,26 @@ /* Don't treat sids containing a single tune as containers */ if(!all_files_are_containers && n_tracks < 2) - return nullptr; + return list; - /* Construct container/tune path names, eg. - Delta.sid/tune_001.sid */ - if (tnum <= n_tracks) { - return FormatNew(SUBTUNE_PREFIX "%03u.sid", tnum); - } else - return nullptr; + TagBuilder tag_builder; + + auto tail = list.before_begin(); + for (unsigned i = 1; i <= n_tracks; ++i) { + tune.selectSong(i); + + ScanSidTuneInfo(info, i, n_tracks, + add_tag_handler, &tag_builder); + + char track_name[32]; + /* Construct container/tune path names, eg. + Delta.sid/tune_001.sid */ + sprintf(track_name, SUBTUNE_PREFIX "%03u.sid", i); + tail = list.emplace_after(tail, track_name, + tag_builder.Commit()); + } + + return list; } static const char *const sidplay_suffixes[] = { diff -Nru mpd-0.19.21/src/decoder/plugins/SidplayDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/SidplayDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/SidplayDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/SidplayDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/SndfileDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/SndfileDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/SndfileDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/SndfileDecoderPlugin.cxx 2017-05-08 15:09:33.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,29 +23,30 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "tag/TagHandler.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" +#include + #include static constexpr Domain sndfile_domain("sndfile"); static bool -sndfile_init(gcc_unused const config_param ¶m) +sndfile_init(gcc_unused const ConfigBlock &block) { LogDebug(sndfile_domain, sf_version_string()); return true; } struct SndfileInputStream { - Decoder *const decoder; + DecoderClient *const client; InputStream &is; size_t Read(void *buffer, size_t size) { /* libsndfile chokes on partial reads; therefore always force full reads */ - return decoder_read_full(decoder, is, buffer, size) + return decoder_read_full(client, is, buffer, size) ? size : 0; } @@ -89,13 +90,13 @@ return -1; } - Error error; - if (!is.LockSeek(offset, error)) { - LogError(error, "Seek failed"); + try { + is.LockSeek(offset); + return is.GetOffset(); + } catch (const std::runtime_error &e) { + LogError(e, "Seek failed"); return -1; } - - return is.GetOffset(); } static sf_count_t @@ -125,7 +126,7 @@ } /** - * This SF_VIRTUAL_IO implementation wraps MPD's #input_stream to a + * This SF_VIRTUAL_IO implementation wraps MPD's #InputStream to a * libsndfile stream. */ static SF_VIRTUAL_IO vio = { @@ -147,7 +148,7 @@ gcc_pure static SampleFormat -sndfile_sample_format(const SF_INFO &info) +sndfile_sample_format(const SF_INFO &info) noexcept { switch (info.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8: @@ -185,13 +186,13 @@ } static void -sndfile_stream_decode(Decoder &decoder, InputStream &is) +sndfile_stream_decode(DecoderClient &client, InputStream &is) { SF_INFO info; info.format = 0; - SndfileInputStream sis{&decoder, is}; + SndfileInputStream sis{&client, is}; SNDFILE *const sf = sf_open_virtual(&vio, SFM_READ, &info, &sis); if (sf == nullptr) { FormatWarning(sndfile_domain, "sf_open_virtual() failed: %s", @@ -199,17 +200,12 @@ return; } - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, info.samplerate, - sndfile_sample_format(info), - info.channels, error)) { - LogError(error); - return; - } + const auto audio_format = + CheckAudioFormat(info.samplerate, + sndfile_sample_format(info), + info.channels); - decoder_initialized(decoder, audio_format, info.seekable, - sndfile_duration(info)); + client.Ready(audio_format, info.seekable, sndfile_duration(info)); char buffer[16384]; @@ -225,16 +221,16 @@ if (num_frames <= 0) break; - cmd = decoder_data(decoder, is, - buffer, num_frames * frame_size, - 0); + cmd = client.SubmitData(is, + buffer, num_frames * frame_size, + 0); if (cmd == DecoderCommand::SEEK) { - sf_count_t c = decoder_seek_where_frame(decoder); + sf_count_t c = client.GetSeekFrame(); c = sf_seek(sf, c, SEEK_SET); if (c < 0) - decoder_seek_error(decoder); + client.SeekError(); else - decoder_command_finished(decoder); + client.CommandFinished(); cmd = DecoderCommand::NONE; } } while (cmd == DecoderCommand::NONE); @@ -244,7 +240,7 @@ static void sndfile_handle_tag(SNDFILE *sf, int str, TagType tag, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { const char *value = sf_get_string(sf, str); if (value != nullptr) @@ -266,7 +262,7 @@ static bool sndfile_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { SF_INFO info; diff -Nru mpd-0.19.21/src/decoder/plugins/SndfileDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/SndfileDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/SndfileDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/SndfileDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisComments.cxx mpd-0.20.9/src/decoder/plugins/VorbisComments.cxx --- mpd-0.19.21/src/decoder/plugins/VorbisComments.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisComments.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "VorbisComments.hxx" -#include "XiphTags.hxx" -#include "tag/TagTable.hxx" -#include "tag/TagHandler.hxx" -#include "tag/TagBuilder.hxx" -#include "tag/VorbisComment.hxx" -#include "tag/ReplayGain.hxx" -#include "ReplayGainInfo.hxx" -#include "util/ASCII.hxx" -#include "util/SplitString.hxx" - -#include -#include - -bool -vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments) -{ - rgi.Clear(); - - bool found = false; - - while (*comments) { - if (ParseReplayGainVorbis(rgi, *comments)) - found = true; - - comments++; - } - - return found; -} - -/** - * Check if the comment's name equals the passed name, and if so, copy - * the comment value into the tag. - */ -static bool -vorbis_copy_comment(const char *comment, - const char *name, TagType tag_type, - const struct tag_handler *handler, void *handler_ctx) -{ - const char *value; - - value = vorbis_comment_value(comment, name); - if (value != nullptr) { - tag_handler_invoke_tag(handler, handler_ctx, tag_type, value); - return true; - } - - return false; -} - -static void -vorbis_scan_comment(const char *comment, - const struct tag_handler *handler, void *handler_ctx) -{ - if (handler->pair != nullptr) { - const SplitString split(comment, '='); - if (split.IsDefined() && !split.IsEmpty()) - tag_handler_invoke_pair(handler, handler_ctx, - split.GetFirst(), - split.GetSecond()); - } - - for (const struct tag_table *i = xiph_tags; i->name != nullptr; ++i) - if (vorbis_copy_comment(comment, i->name, i->type, - handler, handler_ctx)) - return; - - for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) - if (vorbis_copy_comment(comment, - tag_item_names[i], TagType(i), - handler, handler_ctx)) - return; -} - -void -vorbis_comments_scan(char **comments, - const struct tag_handler *handler, void *handler_ctx) -{ - while (*comments) - vorbis_scan_comment(*comments++, - handler, handler_ctx); - -} - -Tag * -vorbis_comments_to_tag(char **comments) -{ - TagBuilder tag_builder; - vorbis_comments_scan(comments, &add_tag_handler, &tag_builder); - return tag_builder.IsEmpty() - ? nullptr - : tag_builder.CommitNew(); -} diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisComments.hxx mpd-0.20.9/src/decoder/plugins/VorbisComments.hxx --- mpd-0.19.21/src/decoder/plugins/VorbisComments.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisComments.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_VORBIS_COMMENTS_HXX -#define MPD_VORBIS_COMMENTS_HXX - -#include "check.h" - -struct ReplayGainInfo; -struct tag_handler; -struct Tag; - -bool -vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments); - -void -vorbis_comments_scan(char **comments, - const tag_handler *handler, void *handler_ctx); - -Tag * -vorbis_comments_to_tag(char **comments); - -#endif diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/VorbisDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/VorbisDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,182 +19,278 @@ #include "config.h" #include "VorbisDecoderPlugin.h" -#include "VorbisComments.hxx" +#include "OggDecoder.hxx" +#include "lib/xiph/VorbisComments.hxx" +#include "lib/xiph/OggPacket.hxx" +#include "lib/xiph/OggFind.hxx" #include "VorbisDomain.hxx" #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" +#include "input/Reader.hxx" #include "OggCodec.hxx" -#include "util/Error.hxx" +#include "pcm/Interleave.hxx" #include "util/Macros.hxx" +#include "util/ScopeExit.hxx" #include "CheckAudioFormat.hxx" #include "tag/TagHandler.hxx" #include "Log.hxx" #ifndef HAVE_TREMOR -#define OV_EXCLUDE_STATIC_CALLBACKS -#include +#include #else -#include -/* Macros to make Tremor's API look like libogg. Tremor always - returns host-byte-order 16-bit signed data, and uses integer - milliseconds where libogg uses double seconds. -*/ -#define ov_read(VF, BUFFER, LENGTH, BIGENDIANP, WORD, SGNED, BITSTREAM) \ - ov_read(VF, BUFFER, LENGTH, BITSTREAM) -#define ov_time_total(VF, I) ((double)ov_time_total(VF, I)/1000) -#define ov_time_tell(VF) ((double)ov_time_tell(VF)/1000) -#define ov_time_seek_page(VF, S) (ov_time_seek_page(VF, (S)*1000)) +#include #endif /* HAVE_TREMOR */ -#include +#include -struct VorbisInputStream { - Decoder *const decoder; +class VorbisDecoder final : public OggDecoder { +#ifdef HAVE_TREMOR + static constexpr SampleFormat sample_format = SampleFormat::S16; + typedef ogg_int32_t in_sample_t; + typedef int16_t out_sample_t; +#else + static constexpr SampleFormat sample_format = SampleFormat::FLOAT; + typedef float in_sample_t; + typedef float out_sample_t; +#endif - InputStream &input_stream; - bool seekable; + unsigned remaining_header_packets; - VorbisInputStream(Decoder *_decoder, InputStream &_is) - :decoder(_decoder), input_stream(_is), - seekable(input_stream.CheapSeeking()) {} -}; + vorbis_info vi; + vorbis_comment vc; + vorbis_dsp_state dsp; + vorbis_block block; + + /** + * If non-zero, then a previous Vorbis stream has been found + * already with this number of channels. + */ + AudioFormat audio_format = AudioFormat::Undefined(); + size_t frame_size; + + bool dsp_initialized = false; + +public: + explicit VorbisDecoder(DecoderReader &reader) + :OggDecoder(reader) { + InitVorbis(); + } -static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *data) -{ - VorbisInputStream *vis = (VorbisInputStream *)data; - size_t ret = decoder_read(vis->decoder, vis->input_stream, - ptr, size * nmemb); + ~VorbisDecoder() { + DeinitVorbis(); + } - errno = 0; + bool Seek(uint64_t where_frame); - return ret / size; -} - -static int ogg_seek_cb(void *data, ogg_int64_t _offset, int whence) -{ - VorbisInputStream *vis = (VorbisInputStream *)data; - InputStream &is = vis->input_stream; +private: + void InitVorbis() { + vorbis_info_init(&vi); + vorbis_comment_init(&vc); + } - if (!vis->seekable || - (vis->decoder != nullptr && - decoder_get_command(*vis->decoder) == DecoderCommand::STOP)) - return -1; + void DeinitVorbis() { + if (dsp_initialized) { + dsp_initialized = false; - offset_type offset = _offset; - switch (whence) { - case SEEK_SET: - break; + vorbis_block_clear(&block); + vorbis_dsp_clear(&dsp); + } - case SEEK_CUR: - offset += is.GetOffset(); - break; + vorbis_comment_clear(&vc); + vorbis_info_clear(&vi); + } - case SEEK_END: - if (!is.KnownSize()) - return -1; + void ReinitVorbis() { + DeinitVorbis(); + InitVorbis(); + } - offset += is.GetSize(); - break; + void SubmitInit(); + bool SubmitSomePcm(); + void SubmitPcm(); + +protected: + /* virtual methods from class OggVisitor */ + void OnOggBeginning(const ogg_packet &packet) override; + void OnOggPacket(const ogg_packet &packet) override; + void OnOggEnd() override; +}; - default: - return -1; +bool +VorbisDecoder::Seek(uint64_t where_frame) +{ + assert(IsSeekable()); + assert(input_stream.IsSeekable()); + assert(input_stream.KnownSize()); + + const ogg_int64_t where_granulepos(where_frame); + + try { + SeekGranulePos(where_granulepos); + vorbis_synthesis_restart(&dsp); + return true; + } catch (const std::runtime_error &) { + return false; } - - return is.LockSeek(offset, IgnoreError()) - ? 0 : -1; } -/* TODO: check Ogg libraries API and see if we can just not have this func */ -static int ogg_close_cb(gcc_unused void *data) +void +VorbisDecoder::OnOggBeginning(const ogg_packet &_packet) { - return 0; + /* libvorbis wants non-const packets */ + ogg_packet &packet = const_cast(_packet); + + ReinitVorbis(); + + if (vorbis_synthesis_headerin(&vi, &vc, &packet) != 0) + throw std::runtime_error("Unrecognized Vorbis BOS packet"); + + remaining_header_packets = 2; } -static long ogg_tell_cb(void *data) +static void +vorbis_send_comments(DecoderClient &client, InputStream &is, + char **comments) { - VorbisInputStream *vis = (VorbisInputStream *)data; + Tag *tag = vorbis_comments_to_tag(comments); + if (!tag) + return; - return (long)vis->input_stream.GetOffset(); + client.SubmitTag(is, std::move(*tag)); + delete tag; } -static const ov_callbacks vorbis_is_callbacks = { - ogg_read_cb, - ogg_seek_cb, - ogg_close_cb, - ogg_tell_cb, -}; - -static const char * -vorbis_strerror(int code) +void +VorbisDecoder::SubmitInit() { - switch (code) { - case OV_EREAD: - return "read error"; + assert(!dsp_initialized); - case OV_ENOTVORBIS: - return "not vorbis stream"; + audio_format = CheckAudioFormat(vi.rate, sample_format, vi.channels); - case OV_EVERSION: - return "vorbis version mismatch"; + frame_size = audio_format.GetFrameSize(); - case OV_EBADHEADER: - return "invalid vorbis header"; - - case OV_EFAULT: - return "internal logic error"; + const auto eos_granulepos = UpdateEndGranulePos(); + const auto duration = eos_granulepos >= 0 + ? SignedSongTime::FromScale(eos_granulepos, + audio_format.sample_rate) + : SignedSongTime::Negative(); - default: - return "unknown error"; - } + client.Ready(audio_format, eos_granulepos > 0, duration); } -static bool -vorbis_is_open(VorbisInputStream *vis, OggVorbis_File *vf) +bool +VorbisDecoder::SubmitSomePcm() { - int ret = ov_open_callbacks(vis, vf, nullptr, 0, vorbis_is_callbacks); - if (ret < 0) { - if (vis->decoder == nullptr || - decoder_get_command(*vis->decoder) == DecoderCommand::NONE) - FormatWarning(vorbis_domain, - "Failed to open Ogg Vorbis stream: %s", - vorbis_strerror(ret)); + in_sample_t **pcm; + int result = vorbis_synthesis_pcmout(&dsp, &pcm); + if (result <= 0) return false; + + out_sample_t buffer[4096]; + const unsigned channels = audio_format.channels; + size_t max_frames = ARRAY_SIZE(buffer) / channels; + size_t n_frames = std::min(size_t(result), max_frames); + +#ifdef HAVE_TREMOR + for (unsigned c = 0; c < channels; ++c) { + const auto *src = pcm[c]; + auto *dest = &buffer[c]; + + for (size_t i = 0; i < n_frames; ++i) { + *dest = *src++; + dest += channels; + } } +#else + PcmInterleaveFloat(buffer, + ConstBuffer(pcm, + channels), + n_frames); +#endif + + vorbis_synthesis_read(&dsp, n_frames); + + const size_t nbytes = n_frames * frame_size; + auto cmd = client.SubmitData(input_stream, + buffer, nbytes, + 0); + if (cmd != DecoderCommand::NONE) + throw cmd; return true; } -static void -vorbis_send_comments(Decoder &decoder, InputStream &is, - char **comments) +void +VorbisDecoder::SubmitPcm() { - Tag *tag = vorbis_comments_to_tag(comments); - if (!tag) - return; - - decoder_tag(decoder, is, std::move(*tag)); - delete tag; + while (SubmitSomePcm()) {} } -#ifndef HAVE_TREMOR -static void -vorbis_interleave(float *dest, const float *const*src, - unsigned nframes, unsigned channels) +void +VorbisDecoder::OnOggPacket(const ogg_packet &_packet) { - for (const float *const*src_end = src + channels; - src != src_end; ++src, ++dest) { - float *gcc_restrict d = dest; - for (const float *gcc_restrict s = *src, *s_end = s + nframes; - s != s_end; ++s, d += channels) - *d = *s; + /* libvorbis wants non-const packets */ + ogg_packet &packet = const_cast(_packet); + + if (remaining_header_packets > 0) { + if (vorbis_synthesis_headerin(&vi, &vc, &packet) != 0) + throw std::runtime_error("Unrecognized Vorbis header packet"); + + if (--remaining_header_packets > 0) + return; + + if (audio_format.IsDefined()) { + /* TODO: change the MPD decoder plugin API to + allow mid-song AudioFormat changes */ + if ((unsigned)vi.rate != audio_format.sample_rate || + (unsigned)vi.channels != audio_format.channels) + throw std::runtime_error("Next stream has different audio format"); + } else + SubmitInit(); + + vorbis_send_comments(client, input_stream, vc.user_comments); + + ReplayGainInfo rgi; + if (vorbis_comments_to_replay_gain(rgi, vc.user_comments)) + client.SubmitReplayGain(&rgi); + } else { + if (!dsp_initialized) { + dsp_initialized = true; + + vorbis_synthesis_init(&dsp, &vi); + vorbis_block_init(&dsp, &block); + } + + if (vorbis_synthesis(&block, &packet) != 0) { + /* ignore bad packets, but give the MPD core a + chance to stop us */ + auto cmd = client.GetCommand(); + if (cmd != DecoderCommand::NONE) + throw cmd; + return; + } + + if (vorbis_synthesis_blockin(&dsp, &block) != 0) + throw std::runtime_error("vorbis_synthesis_blockin() failed"); + + SubmitPcm(); + +#ifndef HAVE_TREMOR + if (packet.granulepos > 0) + client.SubmitTimestamp(vorbis_granule_time(&dsp, packet.granulepos)); +#endif } } -#endif + +void +VorbisDecoder::OnOggEnd() +{ +} /* public */ static bool -vorbis_init(gcc_unused const config_param ¶m) +vorbis_init(gcc_unused const ConfigBlock &block) { #ifndef HAVE_TREMOR LogDebug(vorbis_domain, vorbis_version_string()); @@ -202,160 +298,99 @@ return true; } -gcc_pure -static SignedSongTime -vorbis_duration(OggVorbis_File &vf) -{ - auto total = ov_time_total(&vf, -1); - return total >= 0 - ? SignedSongTime::FromS(total) - : SignedSongTime::Negative(); -} - static void -vorbis_stream_decode(Decoder &decoder, +vorbis_stream_decode(DecoderClient &client, InputStream &input_stream) { - if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_VORBIS) + if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_VORBIS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream.LockRewind(IgnoreError()); - - VorbisInputStream vis(&decoder, input_stream); - OggVorbis_File vf; - if (!vorbis_is_open(&vis, &vf)) - return; - - const vorbis_info *vi = ov_info(&vf, -1); - if (vi == nullptr) { - LogWarning(vorbis_domain, "ov_info() has failed"); - return; - } - - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, vi->rate, -#ifdef HAVE_TREMOR - SampleFormat::S16, -#else - SampleFormat::FLOAT, -#endif - vi->channels, error)) { - LogError(error); - return; + try { + input_stream.LockRewind(); + } catch (const std::runtime_error &) { } - decoder_initialized(decoder, audio_format, vis.seekable, - vorbis_duration(vf)); - -#ifdef HAVE_TREMOR - char buffer[4096]; -#else - float buffer[2048]; - const int frames_per_buffer = - ARRAY_SIZE(buffer) / audio_format.channels; - const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels; -#endif - - int prev_section = -1; - unsigned kbit_rate = 0; + DecoderReader reader(client, input_stream); + VorbisDecoder d(reader); - DecoderCommand cmd = decoder_get_command(decoder); - do { - if (cmd == DecoderCommand::SEEK) { - auto seek_where = decoder_seek_where_frame(decoder); - if (0 == ov_pcm_seek_page(&vf, seek_where)) { - decoder_command_finished(decoder); - } else - decoder_seek_error(decoder); + while (true) { + try { + d.Visit(); + break; + } catch (DecoderCommand cmd) { + if (cmd == DecoderCommand::SEEK) { + if (d.Seek(client.GetSeekFrame())) + client.CommandFinished(); + else + client.SeekError(); + } else if (cmd != DecoderCommand::NONE) + break; } + } +} - int current_section; +static void +VisitVorbisDuration(InputStream &is, + OggSyncState &sync, OggStreamState &stream, + unsigned sample_rate, + const TagHandler &handler, void *handler_ctx) +{ + ogg_packet packet; -#ifdef HAVE_TREMOR - long nbytes = ov_read(&vf, buffer, sizeof(buffer), - IsBigEndian(), 2, 1, - ¤t_section); -#else - float **per_channel; - long nframes = ov_read_float(&vf, &per_channel, - frames_per_buffer, - ¤t_section); - long nbytes = nframes; - if (nframes > 0) { - vorbis_interleave(buffer, - (const float*const*)per_channel, - nframes, audio_format.channels); - nbytes *= frame_size; - } -#endif + if (!OggSeekFindEOS(sync, stream, packet, is)) + return; - if (nbytes == OV_HOLE) /* bad packet */ - nbytes = 0; - else if (nbytes <= 0) - /* break on EOF or other error */ - break; + const auto duration = + SongTime::FromScale(packet.granulepos, + sample_rate); + tag_handler_invoke_duration(handler, handler_ctx, duration); +} - if (current_section != prev_section) { - vi = ov_info(&vf, -1); - if (vi == nullptr) { - LogWarning(vorbis_domain, - "ov_info() has failed"); - break; - } +static bool +vorbis_scan_stream(InputStream &is, + const TagHandler &handler, void *handler_ctx) +{ + /* initialize libogg */ - if (vi->rate != (long)audio_format.sample_rate || - vi->channels != (int)audio_format.channels) { - /* we don't support audio format - change yet */ - LogWarning(vorbis_domain, - "audio format change, stopping here"); - break; - } + InputStreamReader reader(is); + OggSyncState sync(reader); - char **comments = ov_comment(&vf, -1)->user_comments; - vorbis_send_comments(decoder, input_stream, comments); + ogg_page first_page; + if (!sync.ExpectPage(first_page)) + return false; - ReplayGainInfo rgi; - if (vorbis_comments_to_replay_gain(rgi, comments)) - decoder_replay_gain(decoder, &rgi); + OggStreamState stream(first_page); - prev_section = current_section; - } + /* initialize libvorbis */ - long test = ov_bitrate_instant(&vf); - if (test > 0) - kbit_rate = test / 1000; - - cmd = decoder_data(decoder, input_stream, - buffer, nbytes, - kbit_rate); - } while (cmd != DecoderCommand::STOP); + vorbis_info vi; + vorbis_info_init(&vi); + AtScopeExit(&) { vorbis_info_clear(&vi); }; - ov_clear(&vf); -} + vorbis_comment vc; + vorbis_comment_init(&vc); + AtScopeExit(&) { vorbis_comment_clear(&vc); }; -static bool -vorbis_scan_stream(InputStream &is, - const struct tag_handler *handler, void *handler_ctx) -{ - VorbisInputStream vis(nullptr, is); - OggVorbis_File vf; + /* feed the first 3 packets to libvorbis */ - if (!vorbis_is_open(&vis, &vf)) - return false; + for (unsigned i = 0; i < 3; ++i) { + ogg_packet packet; + if (!OggReadPacket(sync, stream, packet) || + vorbis_synthesis_headerin(&vi, &vc, &packet) != 0) + return false; + } - const auto total = ov_time_total(&vf, -1); - if (total >= 0) - tag_handler_invoke_duration(handler, handler_ctx, - SongTime::FromS(total)); + /* visit the Vorbis comments we just read */ - vorbis_comments_scan(ov_comment(&vf, -1)->user_comments, + vorbis_comments_scan(vc.user_comments, handler, handler_ctx); - ov_clear(&vf); + /* check the song duration by locating the e_o_s packet */ + + VisitVorbisDuration(is, sync, stream, vi.rate, handler, handler_ctx); + return true; } diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisDecoderPlugin.h mpd-0.20.9/src/decoder/plugins/VorbisDecoderPlugin.h --- mpd-0.19.21/src/decoder/plugins/VorbisDecoderPlugin.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisDecoderPlugin.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisDomain.cxx mpd-0.20.9/src/decoder/plugins/VorbisDomain.cxx --- mpd-0.19.21/src/decoder/plugins/VorbisDomain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisDomain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/VorbisDomain.hxx mpd-0.20.9/src/decoder/plugins/VorbisDomain.hxx --- mpd-0.19.21/src/decoder/plugins/VorbisDomain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/VorbisDomain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/WavpackDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/WavpackDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/WavpackDecoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/WavpackDecoderPlugin.cxx 2017-05-08 14:58:29.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,99 +23,151 @@ #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" #include "tag/TagHandler.hxx" -#include "tag/ApeTag.hxx" #include "fs/Path.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include "util/Macros.hxx" -#include "Log.hxx" +#include "util/Alloc.hxx" +#include "util/ScopeExit.hxx" +#include "util/RuntimeError.hxx" #include -#include + +#include +#include + +#include #include -#include -#include #define ERRORLEN 80 -static constexpr Domain wavpack_domain("wavpack"); +#ifdef OPEN_DSD_AS_PCM +/* libWavPack supports DSD since version 5 */ + #ifdef ENABLE_DSD +static constexpr int OPEN_DSD_FLAG = OPEN_DSD_NATIVE; + #else +static constexpr int OPEN_DSD_FLAG = OPEN_DSD_AS_PCM; + #endif +#else +/* no DSD support in this libWavPack version */ +static constexpr int OPEN_DSD_FLAG = 0; +#endif + +static WavpackContext * +WavpackOpenInput(Path path, int flags, int norm_offset) +{ + char error[ERRORLEN]; + auto *wpc = WavpackOpenFileInput(path.c_str(), error, + flags, norm_offset); + if (wpc == nullptr) + throw FormatRuntimeError("failed to open WavPack file \"%s\": %s", + path.c_str(), error); + + return wpc; +} + +#ifdef OPEN_DSD_AS_PCM + +static WavpackContext * +WavpackOpenInput(WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, + int flags, int norm_offset) +{ + char error[ERRORLEN]; + auto *wpc = WavpackOpenFileInputEx64(reader, wv_id, wvc_id, error, + flags, norm_offset); + if (wpc == nullptr) + throw FormatRuntimeError("failed to open WavPack stream: %s", + error); + + return wpc; +} + +#else -/** A pointer type for format converter function. */ -typedef void (*format_samples_t)( - int bytes_per_sample, - void *buffer, uint32_t count -); +static WavpackContext * +WavpackOpenInput(WavpackStreamReader *reader, void *wv_id, void *wvc_id, + int flags, int norm_offset) +{ + char error[ERRORLEN]; + auto *wpc = WavpackOpenFileInputEx(reader, wv_id, wvc_id, error, + flags, norm_offset); + if (wpc == nullptr) + throw FormatRuntimeError("failed to open WavPack stream: %s", + error); + + return wpc; +} + +#endif + +gcc_pure +static SignedSongTime +GetDuration(WavpackContext *wpc) noexcept +{ +#ifdef OPEN_DSD_AS_PCM + /* libWavPack 5 */ + const auto n_samples = WavpackGetNumSamples64(wpc); + if (n_samples == -1) + /* unknown */ + return SignedSongTime::Negative(); +#else + const uint32_t n_samples = WavpackGetNumSamples(wpc); + if (n_samples == uint32_t(-1)) + /* unknown */ + return SignedSongTime::Negative(); +#endif + + return SongTime::FromScale(n_samples, + WavpackGetSampleRate(wpc)); +} /* - * This function has been borrowed from the tiny player found on - * wavpack.com. Modifications were required because mpd only handles - * max 24-bit samples. + * Convert integer samples. */ +template static void -format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) +format_samples_int(void *buffer, uint32_t count) { int32_t *src = (int32_t *)buffer; + T *dst = (T *)buffer; + /* + * The asserts like the following one are because we do the + * formatting of samples within a single buffer. The size of + * the output samples never can be greater than the size of + * the input ones. Otherwise we would have an overflow. + */ + static_assert(sizeof(*dst) <= sizeof(*src), "Wrong size"); - switch (bytes_per_sample) { - case 1: { - int8_t *dst = (int8_t *)buffer; - /* - * The asserts like the following one are because we do the - * formatting of samples within a single buffer. The size - * of the output samples never can be greater than the size - * of the input ones. Otherwise we would have an overflow. - */ - static_assert(sizeof(*dst) <= sizeof(*src), "Wrong size"); - - /* pass through and align 8-bit samples */ - while (count--) { - *dst++ = *src++; - } - break; - } - case 2: { - uint16_t *dst = (uint16_t *)buffer; - static_assert(sizeof(*dst) <= sizeof(*src), "Wrong size"); - - /* pass through and align 16-bit samples */ - while (count--) { - *dst++ = *src++; - } - break; - } - - case 3: - case 4: - /* do nothing */ - break; - } + /* pass through and align samples */ + std::copy_n(src, count, dst); } /* - * This function converts floating point sample data to 24-bit integer. + * No conversion necessary. */ static void -format_samples_float(gcc_unused int bytes_per_sample, void *buffer, - uint32_t count) +format_samples_nop(gcc_unused void *buffer, gcc_unused uint32_t count) { - float *p = (float *)buffer; - - while (count--) { - *p /= (1 << 23); - ++p; - } + /* do nothing */ } /** * Choose a MPD sample format from libwavpacks' number of bits. */ static SampleFormat -wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) +wavpack_bits_to_sample_format(bool is_float, +#if defined(OPEN_DSD_AS_PCM) && defined(ENABLE_DSD) + bool is_dsd, +#endif + int bytes_per_sample) { if (is_float) return SampleFormat::FLOAT; +#if defined(OPEN_DSD_AS_PCM) && defined(ENABLE_DSD) + if (is_dsd) + return SampleFormat::DSD; +#endif + switch (bytes_per_sample) { case 1: return SampleFormat::S8; @@ -139,32 +191,42 @@ * Requires an already opened WavpackContext. */ static void -wavpack_decode(Decoder &decoder, WavpackContext *wpc, bool can_seek) +wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek) { - bool is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0; + const bool is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0; +#if defined(OPEN_DSD_AS_PCM) && defined(ENABLE_DSD) + const bool is_dsd = (WavpackGetQualifyMode(wpc) & QMODE_DSD_AUDIO) != 0; +#else + constexpr bool is_dsd = false; +#endif SampleFormat sample_format = wavpack_bits_to_sample_format(is_float, +#if defined(OPEN_DSD_AS_PCM) && defined(ENABLE_DSD) + is_dsd, +#endif WavpackGetBytesPerSample(wpc)); - Error error; - AudioFormat audio_format; - if (!audio_format_init_checked(audio_format, - WavpackGetSampleRate(wpc), - sample_format, - WavpackGetNumChannels(wpc), error)) { - LogError(error); - return; - } - - const format_samples_t format_samples = is_float - ? format_samples_float - : format_samples_int; - - const auto total_time = - SongTime::FromScale(WavpackGetNumSamples(wpc), - audio_format.sample_rate); + auto audio_format = CheckAudioFormat(WavpackGetSampleRate(wpc), + sample_format, + WavpackGetReducedChannels(wpc)); + + auto *format_samples = format_samples_nop; + if (is_dsd) + format_samples = format_samples_int; + else if (!is_float) { + switch (WavpackGetBytesPerSample(wpc)) { + case 1: + format_samples = format_samples_int; + break; + + case 2: + format_samples = format_samples_int; + break; + } + } + + client.Ready(audio_format, can_seek, GetDuration(wpc)); - const int bytes_per_sample = WavpackGetBytesPerSample(wpc); const int output_sample_size = audio_format.GetFrameSize(); /* wavpack gives us all kind of samples in a 32-bit space */ @@ -172,21 +234,25 @@ const uint32_t samples_requested = ARRAY_SIZE(chunk) / audio_format.channels; - decoder_initialized(decoder, audio_format, can_seek, total_time); - - DecoderCommand cmd = decoder_get_command(decoder); + DecoderCommand cmd = client.GetCommand(); while (cmd != DecoderCommand::STOP) { if (cmd == DecoderCommand::SEEK) { if (can_seek) { - auto where = decoder_seek_where_frame(decoder); - - if (WavpackSeekSample(wpc, where)) { - decoder_command_finished(decoder); - } else { - decoder_seek_error(decoder); + auto where = client.GetSeekFrame(); +#ifdef OPEN_DSD_AS_PCM + bool success = WavpackSeekSample64(wpc, where); +#else + bool success = WavpackSeekSample(wpc, where); +#endif + if (!success) { + /* seek errors are fatal */ + client.SeekError(); + break; } + + client.CommandFinished(); } else { - decoder_seek_error(decoder); + client.SeekError(); } } @@ -197,145 +263,86 @@ int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 + 0.5); - format_samples(bytes_per_sample, chunk, - samples_got * audio_format.channels); + format_samples(chunk, samples_got * audio_format.channels); - cmd = decoder_data(decoder, nullptr, chunk, - samples_got * output_sample_size, - bitrate); + cmd = client.SubmitData(nullptr, chunk, + samples_got * output_sample_size, + bitrate); } } -/** - * Locate and parse a floating point tag. Returns true if it was - * found. +/* + * #InputStream <=> WavpackStreamReader wrapper callbacks */ -static bool -wavpack_tag_float(WavpackContext *wpc, const char *key, float *value_r) -{ - char buffer[64]; - if (WavpackGetTagItem(wpc, key, buffer, sizeof(buffer)) <= 0) - return false; - - *value_r = atof(buffer); - return true; -} -static bool -wavpack_replaygain(ReplayGainInfo &rgi, - WavpackContext *wpc) -{ - rgi.Clear(); +/* This struct is needed for per-stream last_byte storage. */ +struct WavpackInput { + DecoderClient *const client; + InputStream &is; + /* Needed for push_back_byte() */ + int last_byte; - bool found = false; - found |= wavpack_tag_float(wpc, "replaygain_track_gain", - &rgi.tuples[REPLAY_GAIN_TRACK].gain); - found |= wavpack_tag_float(wpc, "replaygain_track_peak", - &rgi.tuples[REPLAY_GAIN_TRACK].peak); - found |= wavpack_tag_float(wpc, "replaygain_album_gain", - &rgi.tuples[REPLAY_GAIN_ALBUM].gain); - found |= wavpack_tag_float(wpc, "replaygain_album_peak", - &rgi.tuples[REPLAY_GAIN_ALBUM].peak); + constexpr WavpackInput(DecoderClient *_client, InputStream &_is) + :client(_client), is(_is), last_byte(EOF) {} - return found; -} + int32_t ReadBytes(void *data, size_t bcount); -static void -wavpack_scan_tag_item(WavpackContext *wpc, const char *name, - TagType type, - const struct tag_handler *handler, void *handler_ctx) -{ - char buffer[1024]; - int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer)); - if (len <= 0 || (unsigned)len >= sizeof(buffer)) - return; + InputStream::offset_type GetPos() const { + return is.GetOffset(); + } - tag_handler_invoke_tag(handler, handler_ctx, type, buffer); + int SetPosAbs(InputStream::offset_type pos) { + try { + is.LockSeek(pos); + return 0; + } catch (const std::runtime_error &) { + return -1; + } + } -} + int SetPosRel(InputStream::offset_type delta, int mode) { + offset_type offset = delta; + switch (mode) { + case SEEK_SET: + break; -static void -wavpack_scan_pair(WavpackContext *wpc, const char *name, - const struct tag_handler *handler, void *handler_ctx) -{ - char buffer[8192]; - int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer)); - if (len <= 0 || (unsigned)len >= sizeof(buffer)) - return; + case SEEK_CUR: + offset += is.GetOffset(); + break; - tag_handler_invoke_pair(handler, handler_ctx, name, buffer); -} + case SEEK_END: + if (!is.KnownSize()) + return -1; -/* - * Reads metainfo from the specified file. - */ -static bool -wavpack_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) -{ - char error[ERRORLEN]; - WavpackContext *wpc = WavpackOpenFileInput(path_fs.c_str(), error, - OPEN_TAGS, 0); - if (wpc == nullptr) { - FormatError(wavpack_domain, - "failed to open WavPack file \"%s\": %s", - path_fs.c_str(), error); - return false; - } - - const auto duration = - SongTime::FromScale(WavpackGetNumSamples(wpc), - WavpackGetSampleRate(wpc)); - tag_handler_invoke_duration(handler, handler_ctx, duration); - - /* the WavPack format implies APEv2 tags, which means we can - reuse the mapping from tag_ape.c */ - - for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { - const char *name = tag_item_names[i]; - if (name != nullptr) - wavpack_scan_tag_item(wpc, name, (TagType)i, - handler, handler_ctx); - } - - for (const struct tag_table *i = ape_tags; i->name != nullptr; ++i) - wavpack_scan_tag_item(wpc, i->name, i->type, - handler, handler_ctx); - - if (handler->pair != nullptr) { - char name[64]; - - for (int i = 0, n = WavpackGetNumTagItems(wpc); - i < n; ++i) { - int len = WavpackGetTagItemIndexed(wpc, i, name, - sizeof(name)); - if (len <= 0 || (unsigned)len >= sizeof(name)) - continue; + offset += is.GetSize(); + break; - wavpack_scan_pair(wpc, name, handler, handler_ctx); + default: + return -1; } - } - - WavpackCloseFile(wpc); - return true; -} + return SetPosAbs(offset); + } -/* - * mpd input_stream <=> WavpackStreamReader wrapper callbacks - */ + int PushBackByte(int c) { + if (last_byte == EOF) { + last_byte = c; + return c; + } else { + return EOF; + } + } -/* This struct is needed for per-stream last_byte storage. */ -struct WavpackInput { - Decoder &decoder; - InputStream &is; - /* Needed for push_back_byte() */ - int last_byte; + InputStream::offset_type GetLength() const { + if (!is.KnownSize()) + return 0; - constexpr WavpackInput(Decoder &_decoder, InputStream &_is) - :decoder(_decoder), is(_is), last_byte(EOF) {} + return is.GetSize(); + } - int32_t ReadBytes(void *data, size_t bcount); + bool CanSeek() const { + return is.IsSeekable(); + } }; /** @@ -370,7 +377,7 @@ /* wavpack fails if we return a partial read, so we just wait until the buffer is full */ while (bcount > 0) { - size_t nbytes = decoder_read(&decoder, is, buf, bcount); + size_t nbytes = decoder_read(client, is, buf, bcount); if (nbytes == 0) { /* EOF, error or a decoder command */ break; @@ -384,85 +391,105 @@ return i; } -static uint32_t +#ifdef OPEN_DSD_AS_PCM + +static int64_t wavpack_input_get_pos(void *id) { WavpackInput &wpi = *wpin(id); - - return wpi.is.GetOffset(); + return wpi.GetPos(); } static int -wavpack_input_set_pos_abs(void *id, uint32_t pos) +wavpack_input_set_pos_abs(void *id, int64_t pos) { WavpackInput &wpi = *wpin(id); - - return wpi.is.LockSeek(pos, IgnoreError()) ? 0 : -1; + return wpi.SetPosAbs(pos); } static int -wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) +wavpack_input_set_pos_rel(void *id, int64_t delta, int mode) { WavpackInput &wpi = *wpin(id); - InputStream &is = wpi.is; + return wpi.SetPosRel(delta, mode); +} - offset_type offset = delta; - switch (mode) { - case SEEK_SET: - break; - - case SEEK_CUR: - offset += is.GetOffset(); - break; +#else - case SEEK_END: - if (!is.KnownSize()) - return -1; - - offset += is.GetSize(); - break; +static uint32_t +wavpack_input_get_pos(void *id) +{ + WavpackInput &wpi = *wpin(id); + return wpi.GetPos(); +} - default: - return -1; - } +static int +wavpack_input_set_pos_abs(void *id, uint32_t pos) +{ + WavpackInput &wpi = *wpin(id); + return wpi.SetPosAbs(pos); +} - return is.LockSeek(offset, IgnoreError()) ? 0 : -1; +static int +wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) +{ + WavpackInput &wpi = *wpin(id); + return wpi.SetPosRel(delta, mode); } +#endif + static int wavpack_input_push_back_byte(void *id, int c) { WavpackInput &wpi = *wpin(id); - - if (wpi.last_byte == EOF) { - wpi.last_byte = c; - return c; - } else { - return EOF; - } + return wpi.PushBackByte(c); } -static uint32_t +#ifdef OPEN_DSD_AS_PCM + +static int64_t wavpack_input_get_length(void *id) { WavpackInput &wpi = *wpin(id); - InputStream &is = wpi.is; + return wpi.GetLength(); +} - if (!is.KnownSize()) - return 0; +#else - return is.GetSize(); +static uint32_t +wavpack_input_get_length(void *id) +{ + WavpackInput &wpi = *wpin(id); + return wpi.GetLength(); } +#endif + static int wavpack_input_can_seek(void *id) { WavpackInput &wpi = *wpin(id); - InputStream &is = wpi.is; - - return is.IsSeekable(); + return wpi.CanSeek(); } +#ifdef OPEN_DSD_AS_PCM + +static WavpackStreamReader64 mpd_is_reader = { + wavpack_input_read_bytes, + nullptr, /* write_bytes */ + wavpack_input_get_pos, + wavpack_input_set_pos_abs, + wavpack_input_set_pos_rel, + wavpack_input_push_back_byte, + wavpack_input_get_length, + wavpack_input_can_seek, + nullptr, /* truncate_here */ + nullptr, /* close */ +}; + +#else + static WavpackStreamReader mpd_is_reader = { wavpack_input_read_bytes, wavpack_input_get_pos, @@ -474,8 +501,10 @@ nullptr /* no need to write edited tags */ }; -static WavpackInput * -wavpack_open_wvc(Decoder &decoder, const char *uri) +#endif + +static InputStreamPtr +wavpack_open_wvc(DecoderClient &client, const char *uri) { /* * As we use dc->utf8url, this function will be bad for @@ -484,83 +513,102 @@ if (uri == nullptr) return nullptr; - char *wvc_url = g_strconcat(uri, "c", nullptr); - - InputStream *is_wvc = decoder_open_uri(decoder, uri, IgnoreError()); - g_free(wvc_url); - - if (is_wvc == nullptr) + char *wvc_url = xstrcatdup(uri, "c"); + AtScopeExit(wvc_url) { + free(wvc_url); + }; + + try { + return client.OpenUri(uri); + } catch (const std::runtime_error &) { return nullptr; - - return new WavpackInput(decoder, *is_wvc); + } } /* * Decodes a stream. */ static void -wavpack_streamdecode(Decoder &decoder, InputStream &is) +wavpack_streamdecode(DecoderClient &client, InputStream &is) { - int open_flags = OPEN_NORMALIZE; + int open_flags = OPEN_DSD_FLAG | OPEN_NORMALIZE; bool can_seek = is.IsSeekable(); - WavpackInput *wvc = wavpack_open_wvc(decoder, is.GetURI()); - if (wvc != nullptr) { + std::unique_ptr wvc; + auto is_wvc = wavpack_open_wvc(client, is.GetURI()); + if (is_wvc) { open_flags |= OPEN_WVC; - can_seek &= wvc->is.IsSeekable(); + can_seek &= is_wvc->IsSeekable(); + + wvc.reset(new WavpackInput(&client, *is_wvc)); } if (!can_seek) { open_flags |= OPEN_STREAMING; } - WavpackInput isp(decoder, is); + WavpackInput isp(&client, is); - char error[ERRORLEN]; - WavpackContext *wpc = - WavpackOpenFileInputEx(&mpd_is_reader, &isp, wvc, - error, open_flags, 23); + auto *wpc = WavpackOpenInput(&mpd_is_reader, &isp, wvc.get(), + open_flags, 0); + AtScopeExit(wpc) { + WavpackCloseFile(wpc); + }; - if (wpc == nullptr) { - FormatError(wavpack_domain, - "failed to open WavPack stream: %s", error); - return; - } - - wavpack_decode(decoder, wpc, can_seek); - - WavpackCloseFile(wpc); - - if (wvc != nullptr) { - delete &wvc->is; - delete wvc; - } + wavpack_decode(client, wpc, can_seek); } /* * Decodes a file. */ static void -wavpack_filedecode(Decoder &decoder, Path path_fs) +wavpack_filedecode(DecoderClient &client, Path path_fs) { - char error[ERRORLEN]; - WavpackContext *wpc = WavpackOpenFileInput(path_fs.c_str(), error, - OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, - 23); - if (wpc == nullptr) { - FormatWarning(wavpack_domain, - "failed to open WavPack file \"%s\": %s", - path_fs.c_str(), error); - return; - } - - ReplayGainInfo rgi; - if (wavpack_replaygain(rgi, wpc)) - decoder_replay_gain(decoder, &rgi); + auto *wpc = WavpackOpenInput(path_fs, + OPEN_DSD_FLAG | OPEN_NORMALIZE | OPEN_WVC, + 0); + AtScopeExit(wpc) { + WavpackCloseFile(wpc); + }; - wavpack_decode(decoder, wpc, true); + wavpack_decode(client, wpc, true); +} - WavpackCloseFile(wpc); +/* + * Reads metainfo from the specified file. + */ +static bool +wavpack_scan_file(Path path_fs, + const TagHandler &handler, void *handler_ctx) +{ + auto *wpc = WavpackOpenInput(path_fs, OPEN_DSD_FLAG, 0); + AtScopeExit(wpc) { + WavpackCloseFile(wpc); + }; + + const auto duration = GetDuration(wpc); + if (!duration.IsNegative()) + tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration)); + + return true; +} + +static bool +wavpack_scan_stream(InputStream &is, + const TagHandler &handler, void *handler_ctx) +{ + WavpackInput isp(nullptr, is); + auto *wpc = WavpackOpenInput(&mpd_is_reader, &isp, nullptr, + OPEN_DSD_FLAG, 0); + AtScopeExit(wpc) { + WavpackCloseFile(wpc); + }; + + const auto duration = GetDuration(wpc); + if (!duration.IsNegative()) + tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration)); + + return true; } static char const *const wavpack_suffixes[] = { @@ -580,7 +628,7 @@ wavpack_streamdecode, wavpack_filedecode, wavpack_scan_file, - nullptr, + wavpack_scan_stream, nullptr, wavpack_suffixes, wavpack_mime_types diff -Nru mpd-0.19.21/src/decoder/plugins/WavpackDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/WavpackDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/WavpackDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/WavpackDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/WildmidiDecoderPlugin.cxx mpd-0.20.9/src/decoder/plugins/WildmidiDecoderPlugin.cxx --- mpd-0.19.21/src/decoder/plugins/WildmidiDecoderPlugin.cxx 2016-08-15 08:08:26.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/WildmidiDecoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,12 +21,10 @@ #include "WildmidiDecoderPlugin.hxx" #include "../DecoderAPI.hxx" #include "tag/TagHandler.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "fs/Path.hxx" -#include "system/FatalError.hxx" #include "Log.hxx" extern "C" { @@ -38,15 +36,11 @@ static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000; static bool -wildmidi_init(const config_param ¶m) +wildmidi_init(const ConfigBlock &block) { - Error error; const AllocatedPath path = - param.GetBlockPath("config_file", - "/etc/timidity/timidity.cfg", - error); - if (path.IsNull()) - FatalError(error); + block.GetPath("config_file", + "/etc/timidity/timidity.cfg"); if (!FileExists(path)) { const auto utf8 = path.ToUTF8(); @@ -66,7 +60,7 @@ } static DecoderCommand -wildmidi_output(Decoder &decoder, midi *wm) +wildmidi_output(DecoderClient &client, midi *wm) { #ifdef LIBWILDMIDI_VER_MAJOR /* WildMidi 0.4 has switched from "char*" to "int8_t*" */ @@ -80,11 +74,11 @@ if (length <= 0) return DecoderCommand::STOP; - return decoder_data(decoder, nullptr, buffer, length, 0); + return client.SubmitData(nullptr, buffer, length, 0); } static void -wildmidi_file_decode(Decoder &decoder, Path path_fs) +wildmidi_file_decode(DecoderClient &client, Path path_fs) { static constexpr AudioFormat audio_format = { WILDMIDI_SAMPLE_RATE, @@ -108,7 +102,7 @@ SongTime::FromScale(info->approx_total_samples, WILDMIDI_SAMPLE_RATE); - decoder_initialized(decoder, audio_format, true, duration); + client.Ready(audio_format, true, duration); DecoderCommand cmd; do { @@ -116,14 +110,13 @@ if (info == nullptr) break; - cmd = wildmidi_output(decoder, wm); + cmd = wildmidi_output(client, wm); if (cmd == DecoderCommand::SEEK) { - unsigned long seek_where = - decoder_seek_where_frame(decoder); + unsigned long seek_where = client.GetSeekFrame(); WildMidi_FastSeek(wm, &seek_where); - decoder_command_finished(decoder); + client.CommandFinished(); cmd = DecoderCommand::NONE; } @@ -134,7 +127,7 @@ static bool wildmidi_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) + const TagHandler &handler, void *handler_ctx) { midi *wm = WildMidi_Open(path_fs.c_str()); if (wm == nullptr) diff -Nru mpd-0.19.21/src/decoder/plugins/WildmidiDecoderPlugin.hxx mpd-0.20.9/src/decoder/plugins/WildmidiDecoderPlugin.hxx --- mpd-0.19.21/src/decoder/plugins/WildmidiDecoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/WildmidiDecoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/decoder/plugins/XiphTags.cxx mpd-0.20.9/src/decoder/plugins/XiphTags.cxx --- mpd-0.19.21/src/decoder/plugins/XiphTags.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/XiphTags.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* This File contains additional Tags for Xiph-Based Formats like Ogg-Vorbis, - * Flac and Opus which will be used in addition to the Tags in tag/TagNames.c - * see https://www.xiph.org/vorbis/doc/v-comment.html for further Info - */ -#include "config.h" -#include "XiphTags.hxx" - -const struct tag_table xiph_tags[] = { - { "tracknumber", TAG_TRACK }, - { "discnumber", TAG_DISC }, - { "album artist", TAG_ALBUM_ARTIST }, - { "description", TAG_COMMENT }, - { nullptr, TAG_NUM_OF_ITEM_TYPES } -}; diff -Nru mpd-0.19.21/src/decoder/plugins/XiphTags.hxx mpd-0.20.9/src/decoder/plugins/XiphTags.hxx --- mpd-0.19.21/src/decoder/plugins/XiphTags.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/decoder/plugins/XiphTags.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_XIPH_TAGS_HXX -#define MPD_XIPH_TAGS_HXX - -#include "check.h" -#include "tag/TagTable.hxx" - -extern const struct tag_table xiph_tags[]; - -#endif diff -Nru mpd-0.19.21/src/decoder/Reader.cxx mpd-0.20.9/src/decoder/Reader.cxx --- mpd-0.19.21/src/decoder/Reader.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/Reader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Reader.hxx" +#include "DecoderAPI.hxx" + +size_t +DecoderReader::Read(void *data, size_t size) +{ + return decoder_read(client, is, data, size); +} diff -Nru mpd-0.19.21/src/decoder/Reader.hxx mpd-0.20.9/src/decoder/Reader.hxx --- mpd-0.19.21/src/decoder/Reader.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/decoder/Reader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DECODER_READER_HXX +#define MPD_DECODER_READER_HXX + +#include "check.h" +#include "fs/io/Reader.hxx" +#include "Compiler.h" + +class DecoderClient; +class InputStream; + +/** + * A wrapper for decoder_read() which implements the #Reader + * interface. + */ +class DecoderReader final : public Reader { + DecoderClient &client; + InputStream &is; + +public: + DecoderReader(DecoderClient &_client, InputStream &_is) + :client(_client), is(_is) {} + + DecoderClient &GetClient() { + return client; + } + + InputStream &GetInputStream() { + return is; + } + + /* virtual methods from class Reader */ + size_t Read(void *data, size_t size) override; +}; + +#endif diff -Nru mpd-0.19.21/src/DetachedSong.cxx mpd-0.20.9/src/DetachedSong.cxx --- mpd-0.19.21/src/DetachedSong.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/DetachedSong.cxx 2017-05-08 13:31:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -37,19 +37,19 @@ } bool -DetachedSong::IsRemote() const +DetachedSong::IsRemote() const noexcept { return uri_has_scheme(GetRealURI()); } bool -DetachedSong::IsAbsoluteFile() const +DetachedSong::IsAbsoluteFile() const noexcept { return PathTraitsUTF8::IsAbsolute(GetRealURI()); } bool -DetachedSong::IsInDatabase() const +DetachedSong::IsInDatabase() const noexcept { /* here, we use GetURI() and not GetRealURI() because GetRealURI() is never relative */ @@ -59,7 +59,7 @@ } SignedSongTime -DetachedSong::GetDuration() const +DetachedSong::GetDuration() const noexcept { SongTime a = start_time, b = end_time; if (!b.IsPositive()) { diff -Nru mpd-0.19.21/src/DetachedSong.hxx mpd-0.20.9/src/DetachedSong.hxx --- mpd-0.19.21/src/DetachedSong.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/DetachedSong.hxx 2017-06-03 19:44:53.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,9 +32,9 @@ struct LightSong; class Storage; +class Path; class DetachedSong { - friend DetachedSong map_song_detach(const LightSong &song); friend DetachedSong DatabaseDetachSong(const Storage &db, const LightSong &song); @@ -63,18 +63,18 @@ Tag tag; - time_t mtime; + time_t mtime = 0; /** * Start of this sub-song within the file. */ - SongTime start_time; + SongTime start_time = SongTime::zero(); /** * End of this sub-song within the file. * Unused if zero. */ - SongTime end_time; + SongTime end_time = SongTime::zero(); explicit DetachedSong(const LightSong &other); @@ -82,33 +82,25 @@ explicit DetachedSong(const DetachedSong &) = default; explicit DetachedSong(const char *_uri) - :uri(_uri), - mtime(0), - start_time(SongTime::zero()), end_time(SongTime::zero()) {} + :uri(_uri) {} explicit DetachedSong(const std::string &_uri) - :uri(_uri), - mtime(0), - start_time(SongTime::zero()), end_time(SongTime::zero()) {} + :uri(_uri) {} explicit DetachedSong(std::string &&_uri) - :uri(std::move(_uri)), - mtime(0), - start_time(SongTime::zero()), end_time(SongTime::zero()) {} + :uri(std::move(_uri)) {} template DetachedSong(U &&_uri, Tag &&_tag) :uri(std::forward(_uri)), - tag(std::move(_tag)), - mtime(0), - start_time(SongTime::zero()), end_time(SongTime::zero()) {} + tag(std::move(_tag)) {} DetachedSong(DetachedSong &&) = default; ~DetachedSong(); gcc_pure - const char *GetURI() const { + const char *GetURI() const noexcept { return uri.c_str(); } @@ -122,7 +114,7 @@ * displayed URI? */ gcc_pure - bool HasRealURI() const { + bool HasRealURI() const noexcept { return !real_uri.empty(); } @@ -131,7 +123,7 @@ * GetURI(). */ gcc_pure - const char *GetRealURI() const { + const char *GetRealURI() const noexcept { return (HasRealURI() ? real_uri : uri).c_str(); } @@ -145,34 +137,36 @@ * song. */ gcc_pure - bool IsSame(const DetachedSong &other) const { - return uri == other.uri; + bool IsSame(const DetachedSong &other) const noexcept { + return uri == other.uri && + start_time == other.start_time && + end_time == other.end_time; } gcc_pure gcc_nonnull_all - bool IsURI(const char *other_uri) const { + bool IsURI(const char *other_uri) const noexcept { return uri == other_uri; } gcc_pure - bool IsRemote() const; + bool IsRemote() const noexcept; gcc_pure - bool IsFile() const { + bool IsFile() const noexcept { return !IsRemote(); } gcc_pure - bool IsAbsoluteFile() const; + bool IsAbsoluteFile() const noexcept; gcc_pure - bool IsInDatabase() const; + bool IsInDatabase() const noexcept; - const Tag &GetTag() const { + const Tag &GetTag() const noexcept { return tag; } - Tag &WritableTag() { + Tag &WritableTag() noexcept { return tag; } @@ -221,7 +215,7 @@ } gcc_pure - SignedSongTime GetDuration() const; + SignedSongTime GetDuration() const noexcept; /** * Update the #tag and #mtime. @@ -229,6 +223,11 @@ * @return true on success */ bool Update(); + + /** + * Load #tag and #mtime from a local file. + */ + bool LoadFile(Path path); }; #endif diff -Nru mpd-0.19.21/src/encoder/EncoderAPI.hxx mpd-0.20.9/src/encoder/EncoderAPI.hxx --- mpd-0.19.21/src/encoder/EncoderAPI.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/EncoderAPI.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,10 +27,11 @@ // IWYU pragma: begin_exports +#include "EncoderInterface.hxx" #include "EncoderPlugin.hxx" #include "AudioFormat.hxx" #include "tag/Tag.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" // IWYU pragma: end_exports diff -Nru mpd-0.19.21/src/encoder/EncoderInterface.hxx mpd-0.20.9/src/encoder/EncoderInterface.hxx --- mpd-0.19.21/src/encoder/EncoderInterface.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/encoder/EncoderInterface.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ENCODER_INTERFACE_HXX +#define MPD_ENCODER_INTERFACE_HXX + +#include "EncoderPlugin.hxx" +#include "Compiler.h" + +#include +#include + +struct AudioFormat; +struct Tag; + +class Encoder { + const bool implements_tag; + +public: + explicit Encoder(bool _implements_tag) + :implements_tag(_implements_tag) {} + virtual ~Encoder() {} + + bool ImplementsTag() const { + return implements_tag; + } + + /** + * Ends the stream: flushes the encoder object, generate an + * end-of-stream marker (if applicable), make everything which + * might currently be buffered available by encoder_read(). + * + * After this function has been called, the encoder may not be + * usable for more data, and only Read() and Close() can be + * called. + * + * Throws #std::runtime_error on error. + */ + virtual void End() { + } + + /** + * Flushes an encoder object, make everything which might + * currently be buffered available by Read(). + * + * Throws #std::runtime_error on error. + */ + virtual void Flush() { + } + + /** + * Prepare for sending a tag to the encoder. This is used by + * some encoders to flush the previous sub-stream, in + * preparation to begin a new one. + * + * Throws #std::runtime_error on error. + */ + virtual void PreTag() { + } + + /** + * Sends a tag to the encoder. + * + * Instructions: call PreTag(); then obtain flushed data with + * Read(); finally call Tag(). + * + * Throws #std::runtime_error on error. + * + * @param tag the tag object + */ + virtual void SendTag(gcc_unused const Tag &tag) { + } + + /** + * Writes raw PCM data to the encoder. + * + * Throws #std::runtime_error on error. + * + * @param data the buffer containing PCM samples + * @param length the length of the buffer in bytes + */ + virtual void Write(const void *data, size_t length) = 0; + + /** + * Reads encoded data from the encoder. + * + * Call this repeatedly until no more data is returned. + * + * @param dest the destination buffer to copy to + * @param length the maximum length of the destination buffer + * @return the number of bytes written to #dest + */ + virtual size_t Read(void *dest, size_t length) = 0; +}; + +class PreparedEncoder { +public: + virtual ~PreparedEncoder() {} + + /** + * Opens the object. You must call this prior to using it. + * Before you free it, you must call Close(). You may open + * and close (reuse) one encoder any number of times. + * + * After this function returns successfully and before the + * first encoder_write() call, you should invoke + * encoder_read() to obtain the file header. + * + * Throws #std::runtime_error on error. + * + * @param audio_format the encoder's input audio format; the plugin + * may modify the struct to adapt it to its abilities + */ + virtual Encoder *Open(AudioFormat &audio_format) = 0; + + /** + * Get mime type of encoded content. + * + * @return an constant string, nullptr on failure + */ + virtual const char *GetMimeType() const { + return nullptr; + } +}; + +#endif diff -Nru mpd-0.19.21/src/encoder/EncoderList.cxx mpd-0.20.9/src/encoder/EncoderList.cxx --- mpd-0.19.21/src/encoder/EncoderList.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/EncoderList.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -33,16 +33,16 @@ const EncoderPlugin *const encoder_plugins[] = { &null_encoder_plugin, -#ifdef ENABLE_VORBIS_ENCODER +#ifdef ENABLE_VORBISENC &vorbis_encoder_plugin, #endif -#ifdef HAVE_OPUS +#ifdef ENABLE_OPUS &opus_encoder_plugin, #endif -#ifdef ENABLE_LAME_ENCODER +#ifdef ENABLE_LAME &lame_encoder_plugin, #endif -#ifdef ENABLE_TWOLAME_ENCODER +#ifdef ENABLE_TWOLAME &twolame_encoder_plugin, #endif #ifdef ENABLE_WAVE_ENCODER @@ -51,7 +51,7 @@ #ifdef ENABLE_FLAC_ENCODER &flac_encoder_plugin, #endif -#ifdef ENABLE_SHINE_ENCODER +#ifdef ENABLE_SHINE &shine_encoder_plugin, #endif nullptr diff -Nru mpd-0.19.21/src/encoder/EncoderList.hxx mpd-0.20.9/src/encoder/EncoderList.hxx --- mpd-0.19.21/src/encoder/EncoderList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/EncoderList.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/EncoderPlugin.hxx mpd-0.20.9/src/encoder/EncoderPlugin.hxx --- mpd-0.19.21/src/encoder/EncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/EncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,302 +20,29 @@ #ifndef MPD_ENCODER_PLUGIN_HXX #define MPD_ENCODER_PLUGIN_HXX -#include -#include -#include - -struct EncoderPlugin; -struct AudioFormat; -struct config_param; -struct Tag; -class Error; - -struct Encoder { - const EncoderPlugin &plugin; - -#ifndef NDEBUG - bool open, pre_tag, tag, end; -#endif - - explicit Encoder(const EncoderPlugin &_plugin) - :plugin(_plugin) -#ifndef NDEBUG - , open(false) -#endif - {} -}; +class PreparedEncoder; +struct ConfigBlock; struct EncoderPlugin { const char *name; - Encoder *(*init)(const config_param ¶m, - Error &error); - - void (*finish)(Encoder *encoder); - - bool (*open)(Encoder *encoder, - AudioFormat &audio_format, - Error &error); - - void (*close)(Encoder *encoder); - - bool (*end)(Encoder *encoder, Error &error); - - bool (*flush)(Encoder *encoder, Error &error); - - bool (*pre_tag)(Encoder *encoder, Error &error); - - bool (*tag)(Encoder *encoder, const Tag *tag, - Error &error); - - bool (*write)(Encoder *encoder, - const void *data, size_t length, - Error &error); - - size_t (*read)(Encoder *encoder, void *dest, size_t length); - - const char *(*get_mime_type)(Encoder *encoder); + /** + * Throws #std::runtime_error on error. + */ + PreparedEncoder *(*init)(const ConfigBlock &block); }; /** * Creates a new encoder object. * - * @param plugin the encoder plugin - * @param param optional configuration - * @param error location to store the error occurring, or nullptr to ignore errors. - * @return an encoder object on success, nullptr on failure - */ -static inline Encoder * -encoder_init(const EncoderPlugin &plugin, const config_param ¶m, - Error &error_r) -{ - return plugin.init(param, error_r); -} - -/** - * Frees an encoder object. - * - * @param encoder the encoder - */ -static inline void -encoder_finish(Encoder *encoder) -{ - assert(!encoder->open); - - encoder->plugin.finish(encoder); -} - -/** - * Opens an encoder object. You must call this prior to using it. - * Before you free it, you must call encoder_close(). You may open - * and close (reuse) one encoder any number of times. - * - * After this function returns successfully and before the first - * encoder_write() call, you should invoke encoder_read() to obtain - * the file header. - * - * @param encoder the encoder - * @param audio_format the encoder's input audio format; the plugin - * may modify the struct to adapt it to its abilities - * @return true on success - */ -static inline bool -encoder_open(Encoder *encoder, AudioFormat &audio_format, - Error &error) -{ - assert(!encoder->open); - - bool success = encoder->plugin.open(encoder, audio_format, error); -#ifndef NDEBUG - encoder->open = success; - encoder->pre_tag = encoder->tag = encoder->end = false; -#endif - return success; -} - -/** - * Closes an encoder object. This disables the encoder, and readies - * it for reusal by calling encoder_open() again. - * - * @param encoder the encoder - */ -static inline void -encoder_close(Encoder *encoder) -{ - assert(encoder->open); - - if (encoder->plugin.close != nullptr) - encoder->plugin.close(encoder); - -#ifndef NDEBUG - encoder->open = false; -#endif -} - -/** - * Ends the stream: flushes the encoder object, generate an - * end-of-stream marker (if applicable), make everything which might - * currently be buffered available by encoder_read(). - * - * After this function has been called, the encoder may not be usable - * for more data, and only encoder_read() and encoder_close() can be - * called. - * - * @param encoder the encoder - * @return true on success - */ -static inline bool -encoder_end(Encoder *encoder, Error &error) -{ - assert(encoder->open); - assert(!encoder->end); - -#ifndef NDEBUG - encoder->end = true; -#endif - - /* this method is optional */ - return encoder->plugin.end != nullptr - ? encoder->plugin.end(encoder, error) - : true; -} - -/** - * Flushes an encoder object, make everything which might currently be - * buffered available by encoder_read(). - * - * @param encoder the encoder - * @return true on success - */ -static inline bool -encoder_flush(Encoder *encoder, Error &error) -{ - assert(encoder->open); - assert(!encoder->pre_tag); - assert(!encoder->tag); - assert(!encoder->end); - - /* this method is optional */ - return encoder->plugin.flush != nullptr - ? encoder->plugin.flush(encoder, error) - : true; -} - -/** - * Prepare for sending a tag to the encoder. This is used by some - * encoders to flush the previous sub-stream, in preparation to begin - * a new one. - * - * @param encoder the encoder - * @param tag the tag object - * @return true on success - */ -static inline bool -encoder_pre_tag(Encoder *encoder, Error &error) -{ - assert(encoder->open); - assert(!encoder->pre_tag); - assert(!encoder->tag); - assert(!encoder->end); - - /* this method is optional */ - bool success = encoder->plugin.pre_tag != nullptr - ? encoder->plugin.pre_tag(encoder, error) - : true; - -#ifndef NDEBUG - encoder->pre_tag = success; -#endif - return success; -} - -/** - * Sends a tag to the encoder. - * - * Instructions: call encoder_pre_tag(); then obtain flushed data with - * encoder_read(); finally call encoder_tag(). - * - * @param encoder the encoder - * @param tag the tag object - * @return true on success - */ -static inline bool -encoder_tag(Encoder *encoder, const Tag *tag, Error &error) -{ - assert(encoder->open); - assert(!encoder->pre_tag); - assert(encoder->tag); - assert(!encoder->end); - -#ifndef NDEBUG - encoder->tag = false; -#endif - - /* this method is optional */ - return encoder->plugin.tag != nullptr - ? encoder->plugin.tag(encoder, tag, error) - : true; -} - -/** - * Writes raw PCM data to the encoder. - * - * @param encoder the encoder - * @param data the buffer containing PCM samples - * @param length the length of the buffer in bytes - * @return true on success - */ -static inline bool -encoder_write(Encoder *encoder, const void *data, size_t length, - Error &error) -{ - assert(encoder->open); - assert(!encoder->pre_tag); - assert(!encoder->tag); - assert(!encoder->end); - - return encoder->plugin.write(encoder, data, length, error); -} - -/** - * Reads encoded data from the encoder. - * - * Call this repeatedly until no more data is returned. - * - * @param encoder the encoder - * @param dest the destination buffer to copy to - * @param length the maximum length of the destination buffer - * @return the number of bytes written to #dest - */ -static inline size_t -encoder_read(Encoder *encoder, void *dest, size_t length) -{ - assert(encoder->open); - assert(!encoder->pre_tag || !encoder->tag); - -#ifndef NDEBUG - if (encoder->pre_tag) { - encoder->pre_tag = false; - encoder->tag = true; - } -#endif - - return encoder->plugin.read(encoder, dest, length); -} - -/** - * Get mime type of encoded content. + * Throws #std::runtime_error on error. * * @param plugin the encoder plugin - * @return an constant string, nullptr on failure */ -static inline const char * -encoder_get_mime_type(Encoder *encoder) +static inline PreparedEncoder * +encoder_init(const EncoderPlugin &plugin, const ConfigBlock &block) { - /* this method is optional */ - return encoder->plugin.get_mime_type != nullptr - ? encoder->plugin.get_mime_type(encoder) - : nullptr; + return plugin.init(block); } #endif diff -Nru mpd-0.19.21/src/encoder/plugins/FlacEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/FlacEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/FlacEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/FlacEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,8 @@ #include "AudioFormat.hxx" #include "pcm/PcmBuffer.hxx" #include "config/ConfigError.hxx" -#include "util/Manual.hxx" #include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include @@ -34,13 +32,10 @@ #error libFLAC is too old #endif -struct flac_encoder { - Encoder encoder; +class FlacEncoder final : public Encoder { + const AudioFormat audio_format; - AudioFormat audio_format; - unsigned compression; - - FLAC__StreamEncoder *fse; + FLAC__StreamEncoder *const fse; PcmBuffer expand_buffer; @@ -48,113 +43,111 @@ * This buffer will hold encoded data from libFLAC until it is * picked up with flac_encoder_read(). */ - Manual> output_buffer; + DynamicFifoBuffer output_buffer; - flac_encoder():encoder(flac_encoder_plugin) {} -}; +public: + FlacEncoder(AudioFormat _audio_format, FLAC__StreamEncoder *_fse); -static constexpr Domain flac_encoder_domain("vorbis_encoder"); + ~FlacEncoder() override { + FLAC__stream_encoder_delete(fse); + } -static bool -flac_encoder_configure(struct flac_encoder *encoder, const config_param ¶m, - gcc_unused Error &error) -{ - encoder->compression = param.GetBlockValue("compression", 5u); + /* virtual methods from class Encoder */ + void End() override { + (void) FLAC__stream_encoder_finish(fse); + } - return true; -} + void Flush() override { + (void) FLAC__stream_encoder_finish(fse); + } -static Encoder * -flac_encoder_init(const config_param ¶m, Error &error) -{ - flac_encoder *encoder = new flac_encoder(); + void Write(const void *data, size_t length) override; - /* load configuration from "param" */ - if (!flac_encoder_configure(encoder, param, error)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; + size_t Read(void *dest, size_t length) override { + return output_buffer.Read((uint8_t *)dest, length); } - return &encoder->encoder; -} +private: + static FLAC__StreamEncoderWriteStatus WriteCallback(const FLAC__StreamEncoder *, + const FLAC__byte data[], + size_t bytes, + gcc_unused unsigned samples, + gcc_unused unsigned current_frame, + void *client_data) { + auto &encoder = *(FlacEncoder *)client_data; + encoder.output_buffer.Append((const uint8_t *)data, bytes); + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + } +}; -static void -flac_encoder_finish(Encoder *_encoder) -{ - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; +class PreparedFlacEncoder final : public PreparedEncoder { + const unsigned compression; - /* the real libFLAC cleanup was already performed by - flac_encoder_close(), so no real work here */ - delete encoder; -} +public: + PreparedFlacEncoder(const ConfigBlock &block); -static bool -flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, - Error &error) -{ - if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, - encoder->compression)) { - error.Format(config_domain, - "error setting flac compression to %d", - encoder->compression); - return false; - } - - if ( !FLAC__stream_encoder_set_channels(encoder->fse, - encoder->audio_format.channels)) { - error.Format(config_domain, - "error setting flac channels num to %d", - encoder->audio_format.channels); - return false; - } - if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, - bits_per_sample)) { - error.Format(config_domain, - "error setting flac bit format to %d", - bits_per_sample); - return false; - } - if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, - encoder->audio_format.sample_rate)) { - error.Format(config_domain, - "error setting flac sample rate to %d", - encoder->audio_format.sample_rate); - return false; + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; + + const char *GetMimeType() const override { + return "audio/flac"; } - return true; -} +}; -static FLAC__StreamEncoderWriteStatus -flac_write_callback(gcc_unused const FLAC__StreamEncoder *fse, - const FLAC__byte data[], - size_t bytes, - gcc_unused unsigned samples, - gcc_unused unsigned current_frame, void *client_data) +PreparedFlacEncoder::PreparedFlacEncoder(const ConfigBlock &block) + :compression(block.GetBlockValue("compression", 5u)) { - struct flac_encoder *encoder = (struct flac_encoder *) client_data; - - //transfer data to buffer - encoder->output_buffer->Append((const uint8_t *)data, bytes); +} - return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; +static PreparedEncoder * +flac_encoder_init(const ConfigBlock &block) +{ + return new PreparedFlacEncoder(block); } static void -flac_encoder_close(Encoder *_encoder) +flac_encoder_setup(FLAC__StreamEncoder *fse, unsigned compression, + const AudioFormat &audio_format, unsigned bits_per_sample) { - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; - - FLAC__stream_encoder_delete(encoder->fse); + if (!FLAC__stream_encoder_set_compression_level(fse, compression)) + throw FormatRuntimeError("error setting flac compression to %d", + compression); + + if (!FLAC__stream_encoder_set_channels(fse, audio_format.channels)) + throw FormatRuntimeError("error setting flac channels num to %d", + audio_format.channels); + + if (!FLAC__stream_encoder_set_bits_per_sample(fse, bits_per_sample)) + throw FormatRuntimeError("error setting flac bit format to %d", + bits_per_sample); + + if (!FLAC__stream_encoder_set_sample_rate(fse, + audio_format.sample_rate)) + throw FormatRuntimeError("error setting flac sample rate to %d", + audio_format.sample_rate); +} + +FlacEncoder::FlacEncoder(AudioFormat _audio_format, FLAC__StreamEncoder *_fse) + :Encoder(false), + audio_format(_audio_format), fse(_fse), + output_buffer(8192) +{ + /* this immediately outputs data through callback */ - encoder->expand_buffer.Clear(); - encoder->output_buffer.Destruct(); + auto init_status = + FLAC__stream_encoder_init_stream(fse, + WriteCallback, + nullptr, nullptr, nullptr, + this); + + if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) + throw FormatRuntimeError("failed to initialize encoder: %s\n", + FLAC__StreamEncoderInitStatusString[init_status]); } -static bool -flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) +Encoder * +PreparedFlacEncoder::Open(AudioFormat &audio_format) { - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned bits_per_sample; /* FIXME: flac should support 32bit as well */ @@ -176,51 +169,20 @@ audio_format.format = SampleFormat::S24_P32; } - encoder->audio_format = audio_format; - /* allocate the encoder */ - encoder->fse = FLAC__stream_encoder_new(); - if (encoder->fse == nullptr) { - error.Set(flac_encoder_domain, "flac_new() failed"); - return false; - } - - if (!flac_encoder_setup(encoder, bits_per_sample, error)) { - FLAC__stream_encoder_delete(encoder->fse); - return false; - } - - encoder->output_buffer.Construct(8192); - - /* this immediately outputs data through callback */ - - { - FLAC__StreamEncoderInitStatus init_status; - - init_status = FLAC__stream_encoder_init_stream(encoder->fse, - flac_write_callback, - nullptr, nullptr, nullptr, encoder); - - if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { - error.Format(flac_encoder_domain, - "failed to initialize encoder: %s\n", - FLAC__StreamEncoderInitStatusString[init_status]); - flac_encoder_close(_encoder); - return false; - } + auto fse = FLAC__stream_encoder_new(); + if (fse == nullptr) + throw std::runtime_error("FLAC__stream_encoder_new() failed"); + + try { + flac_encoder_setup(fse, compression, + audio_format, bits_per_sample); + } catch (...) { + FLAC__stream_encoder_delete(fse); + throw; } - return true; -} - - -static bool -flac_encoder_flush(Encoder *_encoder, gcc_unused Error &error) -{ - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; - - (void) FLAC__stream_encoder_finish(encoder->fse); - return true; + return new FlacEncoder(audio_format, fse); } static inline void @@ -241,31 +203,27 @@ } } -static bool -flac_encoder_write(Encoder *_encoder, - const void *data, size_t length, - gcc_unused Error &error) +void +FlacEncoder::Write(const void *data, size_t length) { - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; - unsigned num_frames, num_samples; void *exbuffer; const void *buffer = nullptr; /* format conversion */ - num_frames = length / encoder->audio_format.GetFrameSize(); - num_samples = num_frames * encoder->audio_format.channels; + const unsigned num_frames = length / audio_format.GetFrameSize(); + const unsigned num_samples = num_frames * audio_format.channels; - switch (encoder->audio_format.format) { + switch (audio_format.format) { case SampleFormat::S8: - exbuffer = encoder->expand_buffer.Get(length * 4); + exbuffer = expand_buffer.Get(length * 4); pcm8_to_flac((int32_t *)exbuffer, (const int8_t *)data, num_samples); buffer = exbuffer; break; case SampleFormat::S16: - exbuffer = encoder->expand_buffer.Get(length * 2); + exbuffer = expand_buffer.Get(length * 2); pcm16_to_flac((int32_t *)exbuffer, (const int16_t *)data, num_samples); buffer = exbuffer; @@ -284,42 +242,14 @@ /* feed samples to encoder */ - if (!FLAC__stream_encoder_process_interleaved(encoder->fse, + if (!FLAC__stream_encoder_process_interleaved(fse, (const FLAC__int32 *)buffer, - num_frames)) { - error.Set(flac_encoder_domain, "flac encoder process failed"); - return false; - } - - return true; -} - -static size_t -flac_encoder_read(Encoder *_encoder, void *dest, size_t length) -{ - struct flac_encoder *encoder = (struct flac_encoder *)_encoder; - - return encoder->output_buffer->Read((uint8_t *)dest, length); -} - -static const char * -flac_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/flac"; + num_frames)) + throw std::runtime_error("flac encoder process failed"); } const EncoderPlugin flac_encoder_plugin = { "flac", flac_encoder_init, - flac_encoder_finish, - flac_encoder_open, - flac_encoder_close, - flac_encoder_flush, - flac_encoder_flush, - nullptr, - nullptr, - flac_encoder_write, - flac_encoder_read, - flac_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/FlacEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/FlacEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/FlacEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/FlacEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/LameEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/LameEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/LameEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/LameEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,270 +24,191 @@ #include "config/ConfigError.hxx" #include "util/NumberParser.hxx" #include "util/ReusableArray.hxx" -#include "util/Manual.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include +#include + #include #include -struct LameEncoder final { - Encoder encoder; +class LameEncoder final : public Encoder { + const AudioFormat audio_format; - AudioFormat audio_format; - float quality; - int bitrate; + lame_global_flags *const gfp; - lame_global_flags *gfp; + ReusableArray output_buffer; + unsigned char *output_begin = nullptr, *output_end = nullptr; - Manual> output_buffer; - unsigned char *output_begin, *output_end; +public: + LameEncoder(const AudioFormat _audio_format, + lame_global_flags *_gfp) + :Encoder(false), + audio_format(_audio_format), gfp(_gfp) {} - LameEncoder():encoder(lame_encoder_plugin) {} + ~LameEncoder() override; - bool Configure(const config_param ¶m, Error &error); + /* virtual methods from class Encoder */ + void Write(const void *data, size_t length) override; + size_t Read(void *dest, size_t length) override; }; -static constexpr Domain lame_encoder_domain("lame_encoder"); +class PreparedLameEncoder final : public PreparedEncoder { + float quality; + int bitrate; + +public: + PreparedLameEncoder(const ConfigBlock &block); + + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; + + const char *GetMimeType() const override { + return "audio/mpeg"; + } +}; -bool -LameEncoder::Configure(const config_param ¶m, Error &error) +PreparedLameEncoder::PreparedLameEncoder(const ConfigBlock &block) { const char *value; char *endptr; - value = param.GetBlockValue("quality"); + value = block.GetBlockValue("quality"); if (value != nullptr) { /* a quality was configured (VBR) */ quality = ParseDouble(value, &endptr); - if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { - error.Format(config_domain, - "quality \"%s\" is not a number in the " - "range -1 to 10", - value); - return false; - } - - if (param.GetBlockValue("bitrate") != nullptr) { - error.Set(config_domain, - "quality and bitrate are both defined"); - return false; - } + if (*endptr != '\0' || quality < -1.0 || quality > 10.0) + throw FormatRuntimeError("quality \"%s\" is not a number in the " + "range -1 to 10", + value); + + if (block.GetBlockValue("bitrate") != nullptr) + throw std::runtime_error("quality and bitrate are both defined"); } else { /* a bit rate was configured */ - value = param.GetBlockValue("bitrate"); - if (value == nullptr) { - error.Set(config_domain, - "neither bitrate nor quality defined"); - return false; - } + value = block.GetBlockValue("bitrate"); + if (value == nullptr) + throw std::runtime_error("neither bitrate nor quality defined"); quality = -2.0; bitrate = ParseInt(value, &endptr); - if (*endptr != '\0' || bitrate <= 0) { - error.Set(config_domain, - "bitrate should be a positive integer"); - return false; - } + if (*endptr != '\0' || bitrate <= 0) + throw std::runtime_error("bitrate should be a positive integer"); } - - return true; } -static Encoder * -lame_encoder_init(const config_param ¶m, Error &error) +static PreparedEncoder * +lame_encoder_init(const ConfigBlock &block) { - LameEncoder *encoder = new LameEncoder(); - - /* load configuration from "param" */ - if (!encoder->Configure(param, error)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; - } - - return &encoder->encoder; + return new PreparedLameEncoder(block); } static void -lame_encoder_finish(Encoder *_encoder) -{ - LameEncoder *encoder = (LameEncoder *)_encoder; - - /* the real liblame cleanup was already performed by - lame_encoder_close(), so no real work here */ - delete encoder; -} - -static bool -lame_encoder_setup(LameEncoder *encoder, Error &error) +lame_encoder_setup(lame_global_flags *gfp, float quality, int bitrate, + const AudioFormat &audio_format) { - if (encoder->quality >= -1.0) { + if (quality >= -1.0) { /* a quality was configured (VBR) */ - if (0 != lame_set_VBR(encoder->gfp, vbr_rh)) { - error.Set(lame_encoder_domain, - "error setting lame VBR mode"); - return false; - } - if (0 != lame_set_VBR_q(encoder->gfp, encoder->quality)) { - error.Set(lame_encoder_domain, - "error setting lame VBR quality"); - return false; - } + if (0 != lame_set_VBR(gfp, vbr_rh)) + throw std::runtime_error("error setting lame VBR mode"); + + if (0 != lame_set_VBR_q(gfp, quality)) + throw std::runtime_error("error setting lame VBR quality"); } else { /* a bit rate was configured */ - if (0 != lame_set_brate(encoder->gfp, encoder->bitrate)) { - error.Set(lame_encoder_domain, - "error setting lame bitrate"); - return false; - } + if (0 != lame_set_brate(gfp, bitrate)) + throw std::runtime_error("error setting lame bitrate"); } - if (0 != lame_set_num_channels(encoder->gfp, - encoder->audio_format.channels)) { - error.Set(lame_encoder_domain, - "error setting lame num channels"); - return false; - } + if (0 != lame_set_num_channels(gfp, audio_format.channels)) + throw std::runtime_error("error setting lame num channels"); - if (0 != lame_set_in_samplerate(encoder->gfp, - encoder->audio_format.sample_rate)) { - error.Set(lame_encoder_domain, - "error setting lame sample rate"); - return false; - } + if (0 != lame_set_in_samplerate(gfp, audio_format.sample_rate)) + throw std::runtime_error("error setting lame sample rate"); - if (0 != lame_set_out_samplerate(encoder->gfp, - encoder->audio_format.sample_rate)) { - error.Set(lame_encoder_domain, - "error setting lame out sample rate"); - return false; - } + if (0 != lame_set_out_samplerate(gfp, audio_format.sample_rate)) + throw std::runtime_error("error setting lame out sample rate"); - if (0 > lame_init_params(encoder->gfp)) { - error.Set(lame_encoder_domain, - "error initializing lame params"); - return false; - } - - return true; + if (0 > lame_init_params(gfp)) + throw std::runtime_error("error initializing lame params"); } -static bool -lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) +Encoder * +PreparedLameEncoder::Open(AudioFormat &audio_format) { - LameEncoder *encoder = (LameEncoder *)_encoder; - audio_format.format = SampleFormat::S16; audio_format.channels = 2; - encoder->audio_format = audio_format; - - encoder->gfp = lame_init(); - if (encoder->gfp == nullptr) { - error.Set(lame_encoder_domain, "lame_init() failed"); - return false; - } + auto gfp = lame_init(); + if (gfp == nullptr) + throw std::runtime_error("lame_init() failed"); - if (!lame_encoder_setup(encoder, error)) { - lame_close(encoder->gfp); - return false; + try { + lame_encoder_setup(gfp, quality, bitrate, audio_format); + } catch (...) { + lame_close(gfp); + throw; } - encoder->output_buffer.Construct(); - encoder->output_begin = encoder->output_end = nullptr; - - return true; + return new LameEncoder(audio_format, gfp); } -static void -lame_encoder_close(Encoder *_encoder) +LameEncoder::~LameEncoder() { - LameEncoder *encoder = (LameEncoder *)_encoder; - - lame_close(encoder->gfp); - encoder->output_buffer.Destruct(); + lame_close(gfp); } -static bool -lame_encoder_write(Encoder *_encoder, - const void *data, size_t length, - gcc_unused Error &error) +void +LameEncoder::Write(const void *data, size_t length) { - LameEncoder *encoder = (LameEncoder *)_encoder; const int16_t *src = (const int16_t*)data; - assert(encoder->output_begin == encoder->output_end); + assert(output_begin == output_end); - const unsigned num_frames = - length / encoder->audio_format.GetFrameSize(); - const unsigned num_samples = - length / encoder->audio_format.GetSampleSize(); + const unsigned num_frames = length / audio_format.GetFrameSize(); + const unsigned num_samples = length / audio_format.GetSampleSize(); /* worst-case formula according to LAME documentation */ const size_t output_buffer_size = 5 * num_samples / 4 + 7200; - const auto output_buffer = encoder->output_buffer->Get(output_buffer_size); + const auto dest = output_buffer.Get(output_buffer_size); /* this is for only 16-bit audio */ - int bytes_out = lame_encode_buffer_interleaved(encoder->gfp, + int bytes_out = lame_encode_buffer_interleaved(gfp, const_cast(src), num_frames, - output_buffer, - output_buffer_size); + dest, output_buffer_size); - if (bytes_out < 0) { - error.Set(lame_encoder_domain, "lame encoder failed"); - return false; - } + if (bytes_out < 0) + throw std::runtime_error("lame encoder failed"); - encoder->output_begin = output_buffer; - encoder->output_end = output_buffer + bytes_out; - return true; + output_begin = dest; + output_end = dest + bytes_out; } -static size_t -lame_encoder_read(Encoder *_encoder, void *dest, size_t length) +size_t +LameEncoder::Read(void *dest, size_t length) { - LameEncoder *encoder = (LameEncoder *)_encoder; - - const auto begin = encoder->output_begin; - assert(begin <= encoder->output_end); - const size_t remainning = encoder->output_end - begin; + const auto begin = output_begin; + assert(begin <= output_end); + const size_t remainning = output_end - begin; if (length > remainning) length = remainning; memcpy(dest, begin, length); - encoder->output_begin = begin + length; + output_begin = begin + length; return length; } -static const char * -lame_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/mpeg"; -} - const EncoderPlugin lame_encoder_plugin = { "lame", lame_encoder_init, - lame_encoder_finish, - lame_encoder_open, - lame_encoder_close, - nullptr, - nullptr, - nullptr, - nullptr, - lame_encoder_write, - lame_encoder_read, - lame_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/LameEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/LameEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/LameEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/LameEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/NullEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/NullEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/NullEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/NullEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,86 +20,42 @@ #include "config.h" #include "NullEncoderPlugin.hxx" #include "../EncoderAPI.hxx" -#include "util/Manual.hxx" #include "util/DynamicFifoBuffer.hxx" #include "Compiler.h" -#include - -struct NullEncoder final { - Encoder encoder; - - Manual> buffer; +class NullEncoder final : public Encoder { + DynamicFifoBuffer buffer; +public: NullEncoder() - :encoder(null_encoder_plugin) {} -}; - -static Encoder * -null_encoder_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) -{ - NullEncoder *encoder = new NullEncoder(); - return &encoder->encoder; -} - -static void -null_encoder_finish(Encoder *_encoder) -{ - NullEncoder *encoder = (NullEncoder *)_encoder; - - delete encoder; -} - -static void -null_encoder_close(Encoder *_encoder) -{ - NullEncoder *encoder = (NullEncoder *)_encoder; + :Encoder(false), + buffer(8192) {} - encoder->buffer.Destruct(); -} - - -static bool -null_encoder_open(Encoder *_encoder, - gcc_unused AudioFormat &audio_format, - gcc_unused Error &error) -{ - NullEncoder *encoder = (NullEncoder *)_encoder; - encoder->buffer.Construct(8192); - return true; -} - -static bool -null_encoder_write(Encoder *_encoder, - const void *data, size_t length, - gcc_unused Error &error) -{ - NullEncoder *encoder = (NullEncoder *)_encoder; + /* virtual methods from class Encoder */ + void Write(const void *data, size_t length) override { + buffer.Append((const uint8_t *)data, length); + } + + size_t Read(void *dest, size_t length) override { + return buffer.Read((uint8_t *)dest, length); + } +}; - encoder->buffer->Append((const uint8_t *)data, length); - return length; -} +class PreparedNullEncoder final : public PreparedEncoder { +public: + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &) override { + return new NullEncoder(); + } +}; -static size_t -null_encoder_read(Encoder *_encoder, void *dest, size_t length) +static PreparedEncoder * +null_encoder_init(gcc_unused const ConfigBlock &block) { - NullEncoder *encoder = (NullEncoder *)_encoder; - - return encoder->buffer->Read((uint8_t *)dest, length); + return new PreparedNullEncoder(); } const EncoderPlugin null_encoder_plugin = { "null", null_encoder_init, - null_encoder_finish, - null_encoder_open, - null_encoder_close, - nullptr, - nullptr, - nullptr, - nullptr, - null_encoder_write, - null_encoder_read, - nullptr, }; diff -Nru mpd-0.19.21/src/encoder/plugins/NullEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/NullEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/NullEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/NullEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/OggEncoder.hxx mpd-0.20.9/src/encoder/plugins/OggEncoder.hxx --- mpd-0.19.21/src/encoder/plugins/OggEncoder.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OggEncoder.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_ENCODER_HXX +#define MPD_OGG_ENCODER_HXX + +#include "config.h" +#include "../EncoderAPI.hxx" +#include "lib/xiph/OggStreamState.hxx" +#include "lib/xiph/OggPage.hxx" +#include "lib/xiph/OggSerial.hxx" + +#include + +/** + * An abstract base class which contains code common to all encoders + * with Ogg container output. + */ +class OggEncoder : public Encoder { + /* initialize "flush" to true, so the caller gets the full + headers on the first read */ + bool flush = true; + +protected: + OggStreamState stream; + +public: + OggEncoder(bool _implements_tag) + :Encoder(_implements_tag), + stream(GenerateOggSerial()) { + } + + /* virtual methods from class Encoder */ + void Flush() final { + flush = true; + } + + size_t Read(void *dest, size_t length) override { + ogg_page page; + bool success = stream.PageOut(page); + if (!success) { + if (flush) { + flush = false; + success = stream.Flush(page); + } + + if (!success) + return 0; + } + + return ReadPage(page, dest, length); + } +}; + +#endif diff -Nru mpd-0.19.21/src/encoder/plugins/OggSerial.cxx mpd-0.20.9/src/encoder/plugins/OggSerial.cxx --- mpd-0.19.21/src/encoder/plugins/OggSerial.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OggSerial.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "OggSerial.hxx" -#include "system/Clock.hxx" -#include "Compiler.h" - -#include - -static std::atomic_uint next_ogg_serial; - -int -GenerateOggSerial() -{ - unsigned serial = ++next_ogg_serial; - if (gcc_unlikely(serial < 16)) { - /* first-time initialization: seed with a clock value, - which is random enough for our use */ - - /* this code is not race-free, but good enough */ - const unsigned seed = MonotonicClockMS(); - next_ogg_serial = serial = seed; - } - - return serial; -} - diff -Nru mpd-0.19.21/src/encoder/plugins/OggSerial.hxx mpd-0.20.9/src/encoder/plugins/OggSerial.hxx --- mpd-0.19.21/src/encoder/plugins/OggSerial.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OggSerial.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OGG_SERIAL_HXX -#define MPD_OGG_SERIAL_HXX - -/** - * Generate the next pseudo-random Ogg serial. - */ -int -GenerateOggSerial(); - -#endif diff -Nru mpd-0.19.21/src/encoder/plugins/OggStream.hxx mpd-0.20.9/src/encoder/plugins/OggStream.hxx --- mpd-0.19.21/src/encoder/plugins/OggStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OggStream.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OGG_STREAM_HXX -#define MPD_OGG_STREAM_HXX - -#include "check.h" - -#include - -#include -#include -#include - -class OggStream { - ogg_stream_state state; - - bool flush; - -#ifndef NDEBUG - bool initialized; -#endif - -public: -#ifndef NDEBUG - OggStream():initialized(false) {} - ~OggStream() { - assert(!initialized); - } -#endif - - void Initialize(int serialno) { - assert(!initialized); - - ogg_stream_init(&state, serialno); - - /* set "flush" to true, so the caller gets the full - headers on the first read() */ - flush = true; - -#ifndef NDEBUG - initialized = true; -#endif - } - - void Reinitialize(int serialno) { - assert(initialized); - - ogg_stream_reset_serialno(&state, serialno); - - /* set "flush" to true, so the caller gets the full - headers on the first read() */ - flush = true; - } - - void Deinitialize() { - assert(initialized); - - ogg_stream_clear(&state); - -#ifndef NDEBUG - initialized = false; -#endif - } - - void Flush() { - assert(initialized); - - flush = true; - } - - void PacketIn(const ogg_packet &packet) { - assert(initialized); - - ogg_stream_packetin(&state, - const_cast(&packet)); - } - - bool PageOut(ogg_page &page) { - int result = ogg_stream_pageout(&state, &page); - if (result == 0 && flush) { - flush = false; - result = ogg_stream_flush(&state, &page); - } - - return result != 0; - } - - size_t PageOut(void *_buffer, size_t size) { - ogg_page page; - if (!PageOut(page)) - return 0; - - assert(page.header_len > 0 || page.body_len > 0); - - size_t header_len = (size_t)page.header_len; - size_t body_len = (size_t)page.body_len; - assert(header_len <= size); - - if (header_len + body_len > size) - /* TODO: better overflow handling */ - body_len = size - header_len; - - uint8_t *buffer = (uint8_t *)_buffer; - memcpy(buffer, page.header, header_len); - memcpy(buffer + header_len, page.body, body_len); - - return header_len + body_len; - } -}; - -#endif diff -Nru mpd-0.19.21/src/encoder/plugins/OpusEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/OpusEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/OpusEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OpusEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,130 +19,126 @@ #include "config.h" #include "OpusEncoderPlugin.hxx" -#include "OggStream.hxx" -#include "OggSerial.hxx" -#include "../EncoderAPI.hxx" +#include "OggEncoder.hxx" #include "AudioFormat.hxx" #include "config/ConfigError.hxx" #include "util/Alloc.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include "system/ByteOrder.hxx" #include #include +#include + #include #include -struct opus_encoder { - /** the base class */ - Encoder encoder; - - /* configuration */ - - opus_int32 bitrate; - int complexity; - int signal; +namespace { - /* runtime information */ +class OpusEncoder final : public OggEncoder { + const AudioFormat audio_format; - AudioFormat audio_format; + const size_t frame_size; - size_t frame_size; + const size_t buffer_frames, buffer_size; + size_t buffer_position = 0; + uint8_t *const buffer; - size_t buffer_frames, buffer_size, buffer_position; - uint8_t *buffer; - - OpusEncoder *enc; + ::OpusEncoder *const enc; unsigned char buffer2[1275 * 3 + 7]; - OggStream stream; - int lookahead; - ogg_int64_t packetno; + ogg_int64_t packetno = 0; ogg_int64_t granulepos; - opus_encoder():encoder(opus_encoder_plugin), granulepos(0) {} +public: + OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc); + ~OpusEncoder() override; + + /* virtual methods from class Encoder */ + void End() override; + void Write(const void *data, size_t length) override; + + size_t Read(void *dest, size_t length) override; + +private: + void DoEncode(bool eos); + void WriteSilence(unsigned fill_frames); + + void GenerateHead(); + void GenerateTags(); }; -static constexpr Domain opus_encoder_domain("opus_encoder"); +class PreparedOpusEncoder final : public PreparedEncoder { + opus_int32 bitrate; + int complexity; + int signal; + +public: + PreparedOpusEncoder(const ConfigBlock &block); + + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; + + const char *GetMimeType() const override { + return "audio/ogg"; + } +}; -static bool -opus_encoder_configure(struct opus_encoder *encoder, - const config_param ¶m, Error &error) +PreparedOpusEncoder::PreparedOpusEncoder(const ConfigBlock &block) { - const char *value = param.GetBlockValue("bitrate", "auto"); + const char *value = block.GetBlockValue("bitrate", "auto"); if (strcmp(value, "auto") == 0) - encoder->bitrate = OPUS_AUTO; + bitrate = OPUS_AUTO; else if (strcmp(value, "max") == 0) - encoder->bitrate = OPUS_BITRATE_MAX; + bitrate = OPUS_BITRATE_MAX; else { char *endptr; - encoder->bitrate = strtoul(value, &endptr, 10); + bitrate = strtoul(value, &endptr, 10); if (endptr == value || *endptr != 0 || - encoder->bitrate < 500 || encoder->bitrate > 512000) { - error.Set(config_domain, "Invalid bit rate"); - return false; - } + bitrate < 500 || bitrate > 512000) + throw std::runtime_error("Invalid bit rate"); } - encoder->complexity = param.GetBlockValue("complexity", 10u); - if (encoder->complexity > 10) { - error.Format(config_domain, "Invalid complexity"); - return false; - } + complexity = block.GetBlockValue("complexity", 10u); + if (complexity > 10) + throw std::runtime_error("Invalid complexity"); - value = param.GetBlockValue("signal", "auto"); + value = block.GetBlockValue("signal", "auto"); if (strcmp(value, "auto") == 0) - encoder->signal = OPUS_AUTO; + signal = OPUS_AUTO; else if (strcmp(value, "voice") == 0) - encoder->signal = OPUS_SIGNAL_VOICE; + signal = OPUS_SIGNAL_VOICE; else if (strcmp(value, "music") == 0) - encoder->signal = OPUS_SIGNAL_MUSIC; - else { - error.Format(config_domain, "Invalid signal"); - return false; - } - - return true; + signal = OPUS_SIGNAL_MUSIC; + else + throw std::runtime_error("Invalid signal"); } -static Encoder * -opus_encoder_init(const config_param ¶m, Error &error) +static PreparedEncoder * +opus_encoder_init(const ConfigBlock &block) { - opus_encoder *encoder = new opus_encoder(); - - /* load configuration from "param" */ - if (!opus_encoder_configure(encoder, param, error)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; - } - - return &encoder->encoder; + return new PreparedOpusEncoder(block); } -static void -opus_encoder_finish(Encoder *_encoder) +OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc) + :OggEncoder(false), + audio_format(_audio_format), + frame_size(_audio_format.GetFrameSize()), + buffer_frames(_audio_format.sample_rate / 50), + buffer_size(frame_size * buffer_frames), + buffer((unsigned char *)xalloc(buffer_size)), + enc(_enc) { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; - - /* the real libopus cleanup was already performed by - opus_encoder_close(), so no real work here */ - delete encoder; + opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&lookahead)); } -static bool -opus_encoder_open(Encoder *_encoder, - AudioFormat &audio_format, - Error &error) +Encoder * +PreparedOpusEncoder::Open(AudioFormat &audio_format) { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; - /* libopus supports only 48 kHz */ audio_format.sample_rate = 48000; @@ -163,186 +159,131 @@ break; } - encoder->audio_format = audio_format; - encoder->frame_size = audio_format.GetFrameSize(); - int error_code; - encoder->enc = opus_encoder_create(audio_format.sample_rate, - audio_format.channels, - OPUS_APPLICATION_AUDIO, - &error_code); - if (encoder->enc == nullptr) { - error.Set(opus_encoder_domain, error_code, - opus_strerror(error_code)); - return false; - } + auto *enc = opus_encoder_create(audio_format.sample_rate, + audio_format.channels, + OPUS_APPLICATION_AUDIO, + &error_code); + if (enc == nullptr) + throw std::runtime_error(opus_strerror(error_code)); - opus_encoder_ctl(encoder->enc, OPUS_SET_BITRATE(encoder->bitrate)); - opus_encoder_ctl(encoder->enc, - OPUS_SET_COMPLEXITY(encoder->complexity)); - opus_encoder_ctl(encoder->enc, OPUS_SET_SIGNAL(encoder->signal)); + opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); + opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); + opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal)); - opus_encoder_ctl(encoder->enc, OPUS_GET_LOOKAHEAD(&encoder->lookahead)); - - encoder->buffer_frames = audio_format.sample_rate / 50; - encoder->buffer_size = encoder->frame_size * encoder->buffer_frames; - encoder->buffer_position = 0; - encoder->buffer = (unsigned char *)xalloc(encoder->buffer_size); - - encoder->stream.Initialize(GenerateOggSerial()); - encoder->packetno = 0; - - return true; + return new OpusEncoder(audio_format, enc); } -static void -opus_encoder_close(Encoder *_encoder) +OpusEncoder::~OpusEncoder() { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; - - encoder->stream.Deinitialize(); - free(encoder->buffer); - opus_encoder_destroy(encoder->enc); + free(buffer); + opus_encoder_destroy(enc); } -static bool -opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, - Error &error) +void +OpusEncoder::DoEncode(bool eos) { - assert(encoder->buffer_position == encoder->buffer_size); + assert(buffer_position == buffer_size); opus_int32 result = - encoder->audio_format.format == SampleFormat::S16 - ? opus_encode(encoder->enc, - (const opus_int16 *)encoder->buffer, - encoder->buffer_frames, - encoder->buffer2, - sizeof(encoder->buffer2)) - : opus_encode_float(encoder->enc, - (const float *)encoder->buffer, - encoder->buffer_frames, - encoder->buffer2, - sizeof(encoder->buffer2)); - if (result < 0) { - error.Set(opus_encoder_domain, "Opus encoder error"); - return false; - } + audio_format.format == SampleFormat::S16 + ? opus_encode(enc, + (const opus_int16 *)buffer, + buffer_frames, + buffer2, + sizeof(buffer2)) + : opus_encode_float(enc, + (const float *)buffer, + buffer_frames, + buffer2, + sizeof(buffer2)); + if (result < 0) + throw std::runtime_error("Opus encoder error"); - encoder->granulepos += encoder->buffer_frames; + granulepos += buffer_frames; ogg_packet packet; - packet.packet = encoder->buffer2; + packet.packet = buffer2; packet.bytes = result; packet.b_o_s = false; packet.e_o_s = eos; - packet.granulepos = encoder->granulepos; - packet.packetno = encoder->packetno++; - encoder->stream.PacketIn(packet); + packet.granulepos = granulepos; + packet.packetno = packetno++; + stream.PacketIn(packet); - encoder->buffer_position = 0; - - return true; + buffer_position = 0; } -static bool -opus_encoder_end(Encoder *_encoder, Error &error) +void +OpusEncoder::End() { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; - - encoder->stream.Flush(); - - memset(encoder->buffer + encoder->buffer_position, 0, - encoder->buffer_size - encoder->buffer_position); - encoder->buffer_position = encoder->buffer_size; + Flush(); - return opus_encoder_do_encode(encoder, true, error); -} - -static bool -opus_encoder_flush(Encoder *_encoder, gcc_unused Error &error) -{ - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; + memset(buffer + buffer_position, 0, + buffer_size - buffer_position); + buffer_position = buffer_size; - encoder->stream.Flush(); - return true; + DoEncode(true); } -static bool -opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, - Error &error) +void +OpusEncoder::WriteSilence(unsigned fill_frames) { - size_t fill_bytes = fill_frames * encoder->frame_size; + size_t fill_bytes = fill_frames * frame_size; while (fill_bytes > 0) { - size_t nbytes = - encoder->buffer_size - encoder->buffer_position; + size_t nbytes = buffer_size - buffer_position; if (nbytes > fill_bytes) nbytes = fill_bytes; - memset(encoder->buffer + encoder->buffer_position, - 0, nbytes); - encoder->buffer_position += nbytes; + memset(buffer + buffer_position, 0, nbytes); + buffer_position += nbytes; fill_bytes -= nbytes; - if (encoder->buffer_position == encoder->buffer_size && - !opus_encoder_do_encode(encoder, false, error)) - return false; + if (buffer_position == buffer_size) + DoEncode(false); } - - return true; } -static bool -opus_encoder_write(Encoder *_encoder, - const void *_data, size_t length, - Error &error) +void +OpusEncoder::Write(const void *_data, size_t length) { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; const uint8_t *data = (const uint8_t *)_data; - if (encoder->lookahead > 0) { + if (lookahead > 0) { /* generate some silence at the beginning of the stream */ - assert(encoder->buffer_position == 0); - - if (!opus_encoder_write_silence(encoder, encoder->lookahead, - error)) - return false; + assert(buffer_position == 0); - encoder->lookahead = 0; + WriteSilence(lookahead); + lookahead = 0; } while (length > 0) { - size_t nbytes = - encoder->buffer_size - encoder->buffer_position; + size_t nbytes = buffer_size - buffer_position; if (nbytes > length) nbytes = length; - memcpy(encoder->buffer + encoder->buffer_position, - data, nbytes); + memcpy(buffer + buffer_position, data, nbytes); data += nbytes; length -= nbytes; - encoder->buffer_position += nbytes; + buffer_position += nbytes; - if (encoder->buffer_position == encoder->buffer_size && - !opus_encoder_do_encode(encoder, false, error)) - return false; + if (buffer_position == buffer_size) + DoEncode(false); } - - return true; } -static void -opus_encoder_generate_head(struct opus_encoder *encoder) +void +OpusEncoder::GenerateHead() { unsigned char header[19]; memcpy(header, "OpusHead", 8); header[8] = 1; - header[9] = encoder->audio_format.channels; - *(uint16_t *)(header + 10) = ToLE16(encoder->lookahead); - *(uint32_t *)(header + 12) = - ToLE32(encoder->audio_format.sample_rate); + header[9] = audio_format.channels; + *(uint16_t *)(header + 10) = ToLE16(lookahead); + *(uint32_t *)(header + 12) = ToLE32(audio_format.sample_rate); header[16] = 0; header[17] = 0; header[18] = 0; @@ -353,13 +294,13 @@ packet.b_o_s = true; packet.e_o_s = false; packet.granulepos = 0; - packet.packetno = encoder->packetno++; - encoder->stream.PacketIn(packet); - encoder->stream.Flush(); + packet.packetno = packetno++; + stream.PacketIn(packet); + Flush(); } -static void -opus_encoder_generate_tags(struct opus_encoder *encoder) +void +OpusEncoder::GenerateTags() { const char *version = opus_get_version_string(); size_t version_length = strlen(version); @@ -377,43 +318,27 @@ packet.b_o_s = false; packet.e_o_s = false; packet.granulepos = 0; - packet.packetno = encoder->packetno++; - encoder->stream.PacketIn(packet); - encoder->stream.Flush(); + packet.packetno = packetno++; + stream.PacketIn(packet); + Flush(); free(comments); } -static size_t -opus_encoder_read(Encoder *_encoder, void *dest, size_t length) +size_t +OpusEncoder::Read(void *dest, size_t length) { - struct opus_encoder *encoder = (struct opus_encoder *)_encoder; + if (packetno == 0) + GenerateHead(); + else if (packetno == 1) + GenerateTags(); - if (encoder->packetno == 0) - opus_encoder_generate_head(encoder); - else if (encoder->packetno == 1) - opus_encoder_generate_tags(encoder); - - return encoder->stream.PageOut(dest, length); + return OggEncoder::Read(dest, length); } -static const char * -opus_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/ogg"; } const EncoderPlugin opus_encoder_plugin = { "opus", opus_encoder_init, - opus_encoder_finish, - opus_encoder_open, - opus_encoder_close, - opus_encoder_end, - opus_encoder_flush, - nullptr, - nullptr, - opus_encoder_write, - opus_encoder_read, - opus_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/OpusEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/OpusEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/OpusEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/OpusEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/ShineEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/ShineEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/ShineEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/ShineEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,10 +22,8 @@ #include "../EncoderAPI.hxx" #include "AudioFormat.hxx" #include "config/ConfigError.hxx" -#include "util/Manual.hxx" -#include "util/NumberParser.hxx" #include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" extern "C" { @@ -35,134 +33,113 @@ static constexpr size_t BUFFER_INIT_SIZE = 8192; static constexpr unsigned CHANNELS = 2; -struct ShineEncoder { - Encoder encoder; +class ShineEncoder final : public Encoder { + const AudioFormat audio_format; - AudioFormat audio_format; + const shine_t shine; - shine_t shine; + const size_t frame_size; - shine_config_t config; + /* workaround for bug: + https://github.com/savonet/shine/issues/11 */ + size_t input_pos = SHINE_MAX_SAMPLES + 1; - size_t frame_size; - size_t input_pos; int16_t *stereo[CHANNELS]; - Manual> output_buffer; - - ShineEncoder():encoder(shine_encoder_plugin){} + DynamicFifoBuffer output_buffer; - bool Configure(const config_param ¶m, Error &error); +public: + ShineEncoder(AudioFormat _audio_format, shine_t _shine) + :Encoder(false), + audio_format(_audio_format), shine(_shine), + frame_size(shine_samples_per_pass(shine)), + stereo{new int16_t[frame_size], new int16_t[frame_size]}, + output_buffer(BUFFER_INIT_SIZE) {} + + ~ShineEncoder() override { + if (input_pos > SHINE_MAX_SAMPLES) { + /* write zero chunk */ + input_pos = 0; + WriteChunk(true); + } - bool Setup(Error &error); + shine_close(shine); + delete[] stereo[0]; + delete[] stereo[1]; + } bool WriteChunk(bool flush); -}; - -inline bool -ShineEncoder::Configure(const config_param ¶m, - gcc_unused Error &error) -{ - shine_set_config_mpeg_defaults(&config.mpeg); - config.mpeg.bitr = param.GetBlockValue("bitrate", 128); - - return true; -} - -static Encoder * -shine_encoder_init(const config_param ¶m, Error &error) -{ - ShineEncoder *encoder = new ShineEncoder(); - /* load configuration from "param" */ - if (!encoder->Configure(param, error)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; + /* virtual methods from class Encoder */ + void End() override { + return Flush(); } - return &encoder->encoder; -} - -static void -shine_encoder_finish(Encoder *_encoder) -{ - ShineEncoder *encoder = (ShineEncoder *)_encoder; + void Flush() override; - delete encoder; -} + void Write(const void *data, size_t length) override; -inline bool -ShineEncoder::Setup(Error &error) -{ - config.mpeg.mode = audio_format.channels == 2 ? STEREO : MONO; - config.wave.samplerate = audio_format.sample_rate; - config.wave.channels = - audio_format.channels == 2 ? PCM_STEREO : PCM_MONO; - - if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) { - error.Format(config_domain, - "error configuring shine. " - "samplerate %d and bitrate %d configuration" - " not supported.", - config.wave.samplerate, - config.mpeg.bitr); - - return false; + size_t Read(void *dest, size_t length) override { + return output_buffer.Read((uint8_t *)dest, length); } +}; - shine = shine_initialise(&config); +class PreparedShineEncoder final : public PreparedEncoder { + shine_config_t config; - if (!shine) { - error.Format(config_domain, - "error initializing shine."); +public: + PreparedShineEncoder(const ConfigBlock &block); - return false; - } + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; - frame_size = shine_samples_per_pass(shine); + const char *GetMimeType() const override { + return "audio/mpeg"; + } +}; - return true; +PreparedShineEncoder::PreparedShineEncoder(const ConfigBlock &block) +{ + shine_set_config_mpeg_defaults(&config.mpeg); + config.mpeg.bitr = block.GetBlockValue("bitrate", 128); } -static bool -shine_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) +static PreparedEncoder * +shine_encoder_init(const ConfigBlock &block) { - ShineEncoder *encoder = (ShineEncoder *)_encoder; + return new PreparedShineEncoder(block); +} +static shine_t +SetupShine(shine_config_t config, AudioFormat &audio_format) +{ audio_format.format = SampleFormat::S16; audio_format.channels = CHANNELS; - encoder->audio_format = audio_format; - if (!encoder->Setup(error)) - return false; + config.mpeg.mode = audio_format.channels == 2 ? STEREO : MONO; + config.wave.samplerate = audio_format.sample_rate; + config.wave.channels = + audio_format.channels == 2 ? PCM_STEREO : PCM_MONO; - encoder->stereo[0] = new int16_t[encoder->frame_size]; - encoder->stereo[1] = new int16_t[encoder->frame_size]; - /* workaround for bug: - https://github.com/savonet/shine/issues/11 */ - encoder->input_pos = SHINE_MAX_SAMPLES + 1; + if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) + throw FormatRuntimeError("error configuring shine. " + "samplerate %d and bitrate %d configuration" + " not supported.", + config.wave.samplerate, + config.mpeg.bitr); - encoder->output_buffer.Construct(BUFFER_INIT_SIZE); + auto shine = shine_initialise(&config); + if (!shine) + throw std::runtime_error("error initializing shine"); - return true; + return shine; } -static void -shine_encoder_close(Encoder *_encoder) +Encoder * +PreparedShineEncoder::Open(AudioFormat &audio_format) { - ShineEncoder *encoder = (ShineEncoder *)_encoder; - - if (encoder->input_pos > SHINE_MAX_SAMPLES) { - /* write zero chunk */ - encoder->input_pos = 0; - encoder->WriteChunk(true); - } - - shine_close(encoder->shine); - delete[] encoder->stereo[0]; - delete[] encoder->stereo[1]; - encoder->output_buffer.Destruct(); + auto shine = SetupShine(config, audio_format); + return new ShineEncoder(audio_format, shine); } bool @@ -181,7 +158,7 @@ shine_encode_buffer(shine, stereo, &written); if (written > 0) - output_buffer->Append(out, written); + output_buffer.Append(out, written); input_pos = 0; } @@ -189,80 +166,45 @@ return true; } -static bool -shine_encoder_write(Encoder *_encoder, - const void *_data, size_t length, - gcc_unused Error &error) +void +ShineEncoder::Write(const void *_data, size_t length) { - ShineEncoder *encoder = (ShineEncoder *)_encoder; const int16_t *data = (const int16_t*)_data; - length /= sizeof(*data) * encoder->audio_format.channels; + length /= sizeof(*data) * audio_format.channels; size_t written = 0; - if (encoder->input_pos > SHINE_MAX_SAMPLES) { - encoder->input_pos = 0; - } + if (input_pos > SHINE_MAX_SAMPLES) + input_pos = 0; /* write all data to de-interleaved buffers */ while (written < length) { for (; - written < length - && encoder->input_pos < encoder->frame_size; - written++, encoder->input_pos++) { + written < length && input_pos < frame_size; + written++, input_pos++) { const size_t base = - written * encoder->audio_format.channels; - encoder->stereo[0][encoder->input_pos] = data[base]; - encoder->stereo[1][encoder->input_pos] = data[base + 1]; + written * audio_format.channels; + stereo[0][input_pos] = data[base]; + stereo[1][input_pos] = data[base + 1]; } /* write if chunk is filled */ - encoder->WriteChunk(false); + WriteChunk(false); } - - return true; } -static bool -shine_encoder_flush(Encoder *_encoder, gcc_unused Error &error) +void +ShineEncoder::Flush() { - ShineEncoder *encoder = (ShineEncoder *)_encoder; - /* flush buffers and flush shine */ - encoder->WriteChunk(true); + WriteChunk(true); int written; - const uint8_t *data = shine_flush(encoder->shine, &written); + const uint8_t *data = shine_flush(shine, &written); if (written > 0) - encoder->output_buffer->Append(data, written); - - return true; -} - -static size_t -shine_encoder_read(Encoder *_encoder, void *dest, size_t length) -{ - ShineEncoder *encoder = (ShineEncoder *)_encoder; - - return encoder->output_buffer->Read((uint8_t *)dest, length); -} - -static const char * -shine_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/mpeg"; + output_buffer.Append(data, written); } const EncoderPlugin shine_encoder_plugin = { "shine", shine_encoder_init, - shine_encoder_finish, - shine_encoder_open, - shine_encoder_close, - shine_encoder_flush, - shine_encoder_flush, - nullptr, - nullptr, - shine_encoder_write, - shine_encoder_read, - shine_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/ShineEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/ShineEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/ShineEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/ShineEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/TwolameEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/TwolameEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/TwolameEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/TwolameEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,292 +23,217 @@ #include "AudioFormat.hxx" #include "config/ConfigError.hxx" #include "util/NumberParser.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include +#include + #include #include -struct TwolameEncoder final { - Encoder encoder; - - AudioFormat audio_format; - float quality; - int bitrate; +class TwolameEncoder final : public Encoder { + const AudioFormat audio_format; twolame_options *options; unsigned char output_buffer[32768]; - size_t output_buffer_length; - size_t output_buffer_position; + size_t output_buffer_length = 0; + size_t output_buffer_position = 0; /** * Call libtwolame's flush function when the output_buffer is * empty? */ - bool flush; + bool flush = false; + +public: + TwolameEncoder(const AudioFormat _audio_format, + twolame_options *_options) + :Encoder(false), + audio_format(_audio_format), options(_options) {} + ~TwolameEncoder() override; + + /* virtual methods from class Encoder */ + + void End() override { + flush = true; + } + + void Flush() override { + flush = true; + } + + void Write(const void *data, size_t length) override; + size_t Read(void *dest, size_t length) override; +}; + +class PreparedTwolameEncoder final : public PreparedEncoder { + float quality; + int bitrate; - TwolameEncoder():encoder(twolame_encoder_plugin) {} +public: + PreparedTwolameEncoder(const ConfigBlock &block); - bool Configure(const config_param ¶m, Error &error); + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; + + const char *GetMimeType() const override { + return "audio/mpeg"; + } }; static constexpr Domain twolame_encoder_domain("twolame_encoder"); -bool -TwolameEncoder::Configure(const config_param ¶m, Error &error) +PreparedTwolameEncoder::PreparedTwolameEncoder(const ConfigBlock &block) { const char *value; char *endptr; - value = param.GetBlockValue("quality"); + value = block.GetBlockValue("quality"); if (value != nullptr) { /* a quality was configured (VBR) */ quality = ParseDouble(value, &endptr); - if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { - error.Format(config_domain, - "quality \"%s\" is not a number in the " - "range -1 to 10", - value); - return false; - } + if (*endptr != '\0' || quality < -1.0 || quality > 10.0) + throw FormatRuntimeError("quality \"%s\" is not a number in the " + "range -1 to 10", + value); - if (param.GetBlockValue("bitrate") != nullptr) { - error.Set(config_domain, - "quality and bitrate are both defined"); - return false; - } + if (block.GetBlockValue("bitrate") != nullptr) + throw std::runtime_error("quality and bitrate are both defined"); } else { /* a bit rate was configured */ - value = param.GetBlockValue("bitrate"); - if (value == nullptr) { - error.Set(config_domain, - "neither bitrate nor quality defined"); - return false; - } + value = block.GetBlockValue("bitrate"); + if (value == nullptr) + throw std::runtime_error("neither bitrate nor quality defined"); quality = -2.0; bitrate = ParseInt(value, &endptr); - if (*endptr != '\0' || bitrate <= 0) { - error.Set(config_domain, - "bitrate should be a positive integer"); - return false; - } + if (*endptr != '\0' || bitrate <= 0) + throw std::runtime_error("bitrate should be a positive integer"); } - - return true; } -static Encoder * -twolame_encoder_init(const config_param ¶m, Error &error_r) +static PreparedEncoder * +twolame_encoder_init(const ConfigBlock &block) { FormatDebug(twolame_encoder_domain, "libtwolame version %s", get_twolame_version()); - TwolameEncoder *encoder = new TwolameEncoder(); - - /* load configuration from "param" */ - if (!encoder->Configure(param, error_r)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; - } - - return &encoder->encoder; + return new PreparedTwolameEncoder(block); } static void -twolame_encoder_finish(Encoder *_encoder) -{ - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; - - /* the real libtwolame cleanup was already performed by - twolame_encoder_close(), so no real work here */ - delete encoder; -} - -static bool -twolame_encoder_setup(TwolameEncoder *encoder, Error &error) +twolame_encoder_setup(twolame_options *options, float quality, int bitrate, + const AudioFormat &audio_format) { - if (encoder->quality >= -1.0) { + if (quality >= -1.0) { /* a quality was configured (VBR) */ - if (0 != twolame_set_VBR(encoder->options, true)) { - error.Set(twolame_encoder_domain, - "error setting twolame VBR mode"); - return false; - } - if (0 != twolame_set_VBR_q(encoder->options, encoder->quality)) { - error.Set(twolame_encoder_domain, - "error setting twolame VBR quality"); - return false; - } + if (0 != twolame_set_VBR(options, true)) + throw std::runtime_error("error setting twolame VBR mode"); + + if (0 != twolame_set_VBR_q(options, quality)) + throw std::runtime_error("error setting twolame VBR quality"); } else { /* a bit rate was configured */ - if (0 != twolame_set_brate(encoder->options, encoder->bitrate)) { - error.Set(twolame_encoder_domain, - "error setting twolame bitrate"); - return false; - } + if (0 != twolame_set_brate(options, bitrate)) + throw std::runtime_error("error setting twolame bitrate"); } - if (0 != twolame_set_num_channels(encoder->options, - encoder->audio_format.channels)) { - error.Set(twolame_encoder_domain, - "error setting twolame num channels"); - return false; - } - - if (0 != twolame_set_in_samplerate(encoder->options, - encoder->audio_format.sample_rate)) { - error.Set(twolame_encoder_domain, - "error setting twolame sample rate"); - return false; - } + if (0 != twolame_set_num_channels(options, audio_format.channels)) + throw std::runtime_error("error setting twolame num channels"); - if (0 > twolame_init_params(encoder->options)) { - error.Set(twolame_encoder_domain, - "error initializing twolame params"); - return false; - } + if (0 != twolame_set_in_samplerate(options, + audio_format.sample_rate)) + throw std::runtime_error("error setting twolame sample rate"); - return true; + if (0 > twolame_init_params(options)) + throw std::runtime_error("error initializing twolame params"); } -static bool -twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - Error &error) +Encoder * +PreparedTwolameEncoder::Open(AudioFormat &audio_format) { - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; - audio_format.format = SampleFormat::S16; audio_format.channels = 2; - encoder->audio_format = audio_format; - - encoder->options = twolame_init(); - if (encoder->options == nullptr) { - error.Set(twolame_encoder_domain, "twolame_init() failed"); - return false; - } + auto options = twolame_init(); + if (options == nullptr) + throw std::runtime_error("twolame_init() failed"); - if (!twolame_encoder_setup(encoder, error)) { - twolame_close(&encoder->options); - return false; + try { + twolame_encoder_setup(options, quality, bitrate, + audio_format); + } catch (...) { + twolame_close(&options); + throw; } - encoder->output_buffer_length = 0; - encoder->output_buffer_position = 0; - encoder->flush = false; - - return true; + return new TwolameEncoder(audio_format, options); } -static void -twolame_encoder_close(Encoder *_encoder) +TwolameEncoder::~TwolameEncoder() { - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; - - twolame_close(&encoder->options); + twolame_close(&options); } -static bool -twolame_encoder_flush(Encoder *_encoder, gcc_unused Error &error) +void +TwolameEncoder::Write(const void *data, size_t length) { - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; - - encoder->flush = true; - return true; -} - -static bool -twolame_encoder_write(Encoder *_encoder, - const void *data, size_t length, - gcc_unused Error &error) -{ - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; const int16_t *src = (const int16_t*)data; - assert(encoder->output_buffer_position == - encoder->output_buffer_length); + assert(output_buffer_position == output_buffer_length); - const unsigned num_frames = - length / encoder->audio_format.GetFrameSize(); + const unsigned num_frames = length / audio_format.GetFrameSize(); - int bytes_out = twolame_encode_buffer_interleaved(encoder->options, + int bytes_out = twolame_encode_buffer_interleaved(options, src, num_frames, - encoder->output_buffer, - sizeof(encoder->output_buffer)); - if (bytes_out < 0) { - error.Set(twolame_encoder_domain, "twolame encoder failed"); - return false; - } + output_buffer, + sizeof(output_buffer)); + if (bytes_out < 0) + throw std::runtime_error("twolame encoder failed"); - encoder->output_buffer_length = (size_t)bytes_out; - encoder->output_buffer_position = 0; - return true; + output_buffer_length = (size_t)bytes_out; + output_buffer_position = 0; } -static size_t -twolame_encoder_read(Encoder *_encoder, void *dest, size_t length) +size_t +TwolameEncoder::Read(void *dest, size_t length) { - TwolameEncoder *encoder = (TwolameEncoder *)_encoder; - - assert(encoder->output_buffer_position <= - encoder->output_buffer_length); + assert(output_buffer_position <= output_buffer_length); - if (encoder->output_buffer_position == encoder->output_buffer_length && - encoder->flush) { - int ret = twolame_encode_flush(encoder->options, - encoder->output_buffer, - sizeof(encoder->output_buffer)); + if (output_buffer_position == output_buffer_length && flush) { + int ret = twolame_encode_flush(options, output_buffer, + sizeof(output_buffer)); if (ret > 0) { - encoder->output_buffer_length = (size_t)ret; - encoder->output_buffer_position = 0; + output_buffer_length = (size_t)ret; + output_buffer_position = 0; } - encoder->flush = false; + flush = false; } - const size_t remainning = encoder->output_buffer_length - - encoder->output_buffer_position; + const size_t remainning = output_buffer_length - output_buffer_position; if (length > remainning) length = remainning; - memcpy(dest, encoder->output_buffer + encoder->output_buffer_position, - length); + memcpy(dest, output_buffer + output_buffer_position, length); - encoder->output_buffer_position += length; + output_buffer_position += length; return length; } -static const char * -twolame_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/mpeg"; -} - const EncoderPlugin twolame_encoder_plugin = { "twolame", twolame_encoder_init, - twolame_encoder_finish, - twolame_encoder_open, - twolame_encoder_close, - twolame_encoder_flush, - twolame_encoder_flush, - nullptr, - nullptr, - twolame_encoder_write, - twolame_encoder_read, - twolame_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/TwolameEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/TwolameEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/TwolameEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/TwolameEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/VorbisEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/VorbisEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/VorbisEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/VorbisEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,288 +19,218 @@ #include "config.h" #include "VorbisEncoderPlugin.hxx" -#include "OggStream.hxx" -#include "OggSerial.hxx" -#include "../EncoderAPI.hxx" -#include "tag/Tag.hxx" +#include "OggEncoder.hxx" +#include "lib/xiph/VorbisComment.hxx" #include "AudioFormat.hxx" #include "config/ConfigError.hxx" +#include "util/StringUtil.hxx" #include "util/NumberParser.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include -#include - -struct vorbis_encoder { - /** the base class */ - Encoder encoder; - - /* configuration */ - - float quality; - int bitrate; - - /* runtime information */ - +class VorbisEncoder final : public OggEncoder { AudioFormat audio_format; vorbis_dsp_state vd; vorbis_block vb; vorbis_info vi; - OggStream stream; +public: + VorbisEncoder(float quality, int bitrate, AudioFormat &_audio_format); + + virtual ~VorbisEncoder() { + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_info_clear(&vi); + } - vorbis_encoder():encoder(vorbis_encoder_plugin) {} + /* virtual methods from class Encoder */ + void End() override { + PreTag(); + } + + void PreTag() override; + void SendTag(const Tag &tag) override; + + void Write(const void *data, size_t length) override; + +private: + void HeaderOut(vorbis_comment &vc); + void SendHeader(); + void BlockOut(); }; -static constexpr Domain vorbis_encoder_domain("vorbis_encoder"); +class PreparedVorbisEncoder final : public PreparedEncoder { + float quality; + int bitrate; + +public: + PreparedVorbisEncoder(const ConfigBlock &block); + + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override; -static bool -vorbis_encoder_configure(struct vorbis_encoder *encoder, - const config_param ¶m, Error &error) + const char *GetMimeType() const override { + return "audio/ogg"; + } +}; + +PreparedVorbisEncoder::PreparedVorbisEncoder(const ConfigBlock &block) { - const char *value = param.GetBlockValue("quality"); + const char *value = block.GetBlockValue("quality"); if (value != nullptr) { /* a quality was configured (VBR) */ char *endptr; - encoder->quality = ParseDouble(value, &endptr); + quality = ParseDouble(value, &endptr); - if (*endptr != '\0' || encoder->quality < -1.0 || - encoder->quality > 10.0) { - error.Format(config_domain, - "quality \"%s\" is not a number in the " - "range -1 to 10", - value); - return false; - } + if (*endptr != '\0' || quality < -1.0 || quality > 10.0) + throw FormatRuntimeError("quality \"%s\" is not a number in the " + "range -1 to 10", + value); - if (param.GetBlockValue("bitrate") != nullptr) { - error.Set(config_domain, - "quality and bitrate are both defined"); - return false; - } + if (block.GetBlockValue("bitrate") != nullptr) + throw std::runtime_error("quality and bitrate are both defined"); } else { /* a bit rate was configured */ - value = param.GetBlockValue("bitrate"); - if (value == nullptr) { - error.Set(config_domain, - "neither bitrate nor quality defined"); - return false; - } + value = block.GetBlockValue("bitrate"); + if (value == nullptr) + throw std::runtime_error("neither bitrate nor quality defined"); - encoder->quality = -2.0; + quality = -2.0; char *endptr; - encoder->bitrate = ParseInt(value, &endptr); - if (*endptr != '\0' || encoder->bitrate <= 0) { - error.Set(config_domain, - "bitrate should be a positive integer"); - return false; - } + bitrate = ParseInt(value, &endptr); + if (*endptr != '\0' || bitrate <= 0) + throw std::runtime_error("bitrate should be a positive integer"); } - - return true; } -static Encoder * -vorbis_encoder_init(const config_param ¶m, Error &error) +static PreparedEncoder * +vorbis_encoder_init(const ConfigBlock &block) { - vorbis_encoder *encoder = new vorbis_encoder(); - - /* load configuration from "param" */ - if (!vorbis_encoder_configure(encoder, param, error)) { - /* configuration has failed, roll back and return error */ - delete encoder; - return nullptr; - } - - return &encoder->encoder; + return new PreparedVorbisEncoder(block); } -static void -vorbis_encoder_finish(Encoder *_encoder) +VorbisEncoder::VorbisEncoder(float quality, int bitrate, + AudioFormat &_audio_format) + :OggEncoder(true) { - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; + vorbis_info_init(&vi); - /* the real libvorbis/libogg cleanup was already performed by - vorbis_encoder_close(), so no real work here */ - delete encoder; -} - -static bool -vorbis_encoder_reinit(struct vorbis_encoder *encoder, Error &error) -{ - vorbis_info_init(&encoder->vi); + _audio_format.format = SampleFormat::FLOAT; + audio_format = _audio_format; - if (encoder->quality >= -1.0) { + if (quality >= -1.0) { /* a quality was configured (VBR) */ - if (0 != vorbis_encode_init_vbr(&encoder->vi, - encoder->audio_format.channels, - encoder->audio_format.sample_rate, - encoder->quality * 0.1)) { - error.Set(vorbis_encoder_domain, - "error initializing vorbis vbr"); - vorbis_info_clear(&encoder->vi); - return false; + if (0 != vorbis_encode_init_vbr(&vi, + audio_format.channels, + audio_format.sample_rate, + quality * 0.1)) { + vorbis_info_clear(&vi); + throw std::runtime_error("error initializing vorbis vbr"); } } else { /* a bit rate was configured */ - if (0 != vorbis_encode_init(&encoder->vi, - encoder->audio_format.channels, - encoder->audio_format.sample_rate, -1.0, - encoder->bitrate * 1000, -1.0)) { - error.Set(vorbis_encoder_domain, - "error initializing vorbis encoder"); - vorbis_info_clear(&encoder->vi); - return false; + if (0 != vorbis_encode_init(&vi, + audio_format.channels, + audio_format.sample_rate, -1.0, + bitrate * 1000, -1.0)) { + vorbis_info_clear(&vi); + throw std::runtime_error("error initializing vorbis encoder"); } } - vorbis_analysis_init(&encoder->vd, &encoder->vi); - vorbis_block_init(&encoder->vd, &encoder->vb); - encoder->stream.Initialize(GenerateOggSerial()); + vorbis_analysis_init(&vd, &vi); + vorbis_block_init(&vd, &vb); - return true; + SendHeader(); } -static void -vorbis_encoder_headerout(struct vorbis_encoder *encoder, vorbis_comment *vc) +void +VorbisEncoder::HeaderOut(vorbis_comment &vc) { ogg_packet packet, comments, codebooks; - vorbis_analysis_headerout(&encoder->vd, vc, + vorbis_analysis_headerout(&vd, &vc, &packet, &comments, &codebooks); - encoder->stream.PacketIn(packet); - encoder->stream.PacketIn(comments); - encoder->stream.PacketIn(codebooks); + stream.PacketIn(packet); + stream.PacketIn(comments); + stream.PacketIn(codebooks); } -static void -vorbis_encoder_send_header(struct vorbis_encoder *encoder) -{ - vorbis_comment vc; - - vorbis_comment_init(&vc); - vorbis_encoder_headerout(encoder, &vc); - vorbis_comment_clear(&vc); -} - -static bool -vorbis_encoder_open(Encoder *_encoder, - AudioFormat &audio_format, - Error &error) -{ - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - audio_format.format = SampleFormat::FLOAT; - - encoder->audio_format = audio_format; - - if (!vorbis_encoder_reinit(encoder, error)) - return false; - - vorbis_encoder_send_header(encoder); - - return true; -} - -static void -vorbis_encoder_clear(struct vorbis_encoder *encoder) +void +VorbisEncoder::SendHeader() { - encoder->stream.Deinitialize(); - vorbis_block_clear(&encoder->vb); - vorbis_dsp_clear(&encoder->vd); - vorbis_info_clear(&encoder->vi); + VorbisComment vc; + HeaderOut(vc); } -static void -vorbis_encoder_close(Encoder *_encoder) +Encoder * +PreparedVorbisEncoder::Open(AudioFormat &audio_format) { - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - vorbis_encoder_clear(encoder); + return new VorbisEncoder(quality, bitrate, audio_format); } -static void -vorbis_encoder_blockout(struct vorbis_encoder *encoder) +void +VorbisEncoder::BlockOut() { - while (vorbis_analysis_blockout(&encoder->vd, &encoder->vb) == 1) { - vorbis_analysis(&encoder->vb, nullptr); - vorbis_bitrate_addblock(&encoder->vb); + while (vorbis_analysis_blockout(&vd, &vb) == 1) { + vorbis_analysis(&vb, nullptr); + vorbis_bitrate_addblock(&vb); ogg_packet packet; - while (vorbis_bitrate_flushpacket(&encoder->vd, &packet)) - encoder->stream.PacketIn(packet); + while (vorbis_bitrate_flushpacket(&vd, &packet)) + stream.PacketIn(packet); } } -static bool -vorbis_encoder_flush(Encoder *_encoder, gcc_unused Error &error) -{ - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - encoder->stream.Flush(); - return true; -} - -static bool -vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error) +void +VorbisEncoder::PreTag() { - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - vorbis_analysis_wrote(&encoder->vd, 0); - vorbis_encoder_blockout(encoder); + vorbis_analysis_wrote(&vd, 0); + BlockOut(); /* reinitialize vorbis_dsp_state and vorbis_block to reset the end-of-stream marker */ - vorbis_block_clear(&encoder->vb); - vorbis_dsp_clear(&encoder->vd); - vorbis_analysis_init(&encoder->vd, &encoder->vi); - vorbis_block_init(&encoder->vd, &encoder->vb); + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_analysis_init(&vd, &vi); + vorbis_block_init(&vd, &vb); - encoder->stream.Flush(); - return true; + Flush(); } static void -copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag) +copy_tag_to_vorbis_comment(VorbisComment &vc, const Tag &tag) { - for (const auto &item : *tag) { - char *name = g_ascii_strup(tag_item_names[item.type], -1); - vorbis_comment_add_tag(vc, name, item.value); - g_free(name); + for (const auto &item : tag) { + char name[64]; + ToUpperASCII(name, tag_item_names[item.type], sizeof(name)); + vc.AddTag(name, item.value); } } -static bool -vorbis_encoder_tag(Encoder *_encoder, const Tag *tag, - gcc_unused Error &error) +void +VorbisEncoder::SendTag(const Tag &tag) { - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - vorbis_comment comment; - /* write the vorbis_comment object */ - vorbis_comment_init(&comment); - copy_tag_to_vorbis_comment(&comment, tag); + VorbisComment comment; + copy_tag_to_vorbis_comment(comment, tag); /* reset ogg_stream_state and begin a new stream */ - encoder->stream.Reinitialize(GenerateOggSerial()); + stream.Reinitialize(GenerateOggSerial()); /* send that vorbis_comment to the ogg_stream_state */ - vorbis_encoder_headerout(encoder, &comment); - vorbis_comment_clear(&comment); - - return true; + HeaderOut(comment); } static void @@ -312,53 +242,23 @@ dest[j][i] = *src++; } -static bool -vorbis_encoder_write(Encoder *_encoder, - const void *data, size_t length, - gcc_unused Error &error) +void +VorbisEncoder::Write(const void *data, size_t length) { - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - unsigned num_frames = length / encoder->audio_format.GetFrameSize(); + unsigned num_frames = length / audio_format.GetFrameSize(); /* this is for only 16-bit audio */ - interleaved_to_vorbis_buffer(vorbis_analysis_buffer(&encoder->vd, - num_frames), + interleaved_to_vorbis_buffer(vorbis_analysis_buffer(&vd, num_frames), (const float *)data, num_frames, - encoder->audio_format.channels); - - vorbis_analysis_wrote(&encoder->vd, num_frames); - vorbis_encoder_blockout(encoder); - return true; -} - -static size_t -vorbis_encoder_read(Encoder *_encoder, void *dest, size_t length) -{ - struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; - - return encoder->stream.PageOut(dest, length); -} + audio_format.channels); -static const char * -vorbis_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/ogg"; + vorbis_analysis_wrote(&vd, num_frames); + BlockOut(); } const EncoderPlugin vorbis_encoder_plugin = { "vorbis", vorbis_encoder_init, - vorbis_encoder_finish, - vorbis_encoder_open, - vorbis_encoder_close, - vorbis_encoder_pre_tag, - vorbis_encoder_flush, - vorbis_encoder_pre_tag, - vorbis_encoder_tag, - vorbis_encoder_write, - vorbis_encoder_read, - vorbis_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/VorbisEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/VorbisEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/VorbisEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/VorbisEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/plugins/WaveEncoderPlugin.cxx mpd-0.20.9/src/encoder/plugins/WaveEncoderPlugin.cxx --- mpd-0.19.21/src/encoder/plugins/WaveEncoderPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/WaveEncoderPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,6 @@ #include "WaveEncoderPlugin.hxx" #include "../EncoderAPI.hxx" #include "system/ByteOrder.hxx" -#include "util/Manual.hxx" #include "util/DynamicFifoBuffer.hxx" #include @@ -29,16 +28,34 @@ static constexpr uint16_t WAVE_FORMAT_PCM = 1; -struct WaveEncoder { - Encoder encoder; +class WaveEncoder final : public Encoder { unsigned bits; - Manual> buffer; + DynamicFifoBuffer buffer; - WaveEncoder():encoder(wave_encoder_plugin) {} +public: + WaveEncoder(AudioFormat &audio_format); + + /* virtual methods from class Encoder */ + void Write(const void *data, size_t length) override; + + size_t Read(void *dest, size_t length) override { + return buffer.Read((uint8_t *)dest, length); + } +}; + +class PreparedWaveEncoder final : public PreparedEncoder { + /* virtual methods from class PreparedEncoder */ + Encoder *Open(AudioFormat &audio_format) override { + return new WaveEncoder(audio_format); + } + + const char *GetMimeType() const override { + return "audio/wav"; + } }; -struct wave_header { +struct WaveHeader { uint32_t id_riff; uint32_t riff_size; uint32_t id_wave; @@ -55,7 +72,7 @@ }; static void -fill_wave_header(struct wave_header *header, int channels, int bits, +fill_wave_header(WaveHeader *header, int channels, int bits, int freq, int block_size) { int data_size = 0x0FFFFFFF; @@ -80,78 +97,53 @@ header->riff_size = ToLE32(4 + (8 + 16) + (8 + data_size)); } -static Encoder * -wave_encoder_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) +static PreparedEncoder * +wave_encoder_init(gcc_unused const ConfigBlock &block) { - WaveEncoder *encoder = new WaveEncoder(); - return &encoder->encoder; + return new PreparedWaveEncoder(); } -static void -wave_encoder_finish(Encoder *_encoder) +WaveEncoder::WaveEncoder(AudioFormat &audio_format) + :Encoder(false), + buffer(8192) { - WaveEncoder *encoder = (WaveEncoder *)_encoder; - - delete encoder; -} - -static bool -wave_encoder_open(Encoder *_encoder, - AudioFormat &audio_format, - gcc_unused Error &error) -{ - WaveEncoder *encoder = (WaveEncoder *)_encoder; - assert(audio_format.IsValid()); switch (audio_format.format) { case SampleFormat::S8: - encoder->bits = 8; + bits = 8; break; case SampleFormat::S16: - encoder->bits = 16; + bits = 16; break; case SampleFormat::S24_P32: - encoder->bits = 24; + bits = 24; break; case SampleFormat::S32: - encoder->bits = 32; + bits = 32; break; default: audio_format.format = SampleFormat::S16; - encoder->bits = 16; + bits = 16; break; } - encoder->buffer.Construct(8192); - - auto range = encoder->buffer->Write(); - assert(range.size >= sizeof(wave_header)); - wave_header *header = (wave_header *)range.data; + auto range = buffer.Write(); + assert(range.size >= sizeof(WaveHeader)); + auto *header = (WaveHeader *)range.data; /* create PCM wave header in initial buffer */ fill_wave_header(header, audio_format.channels, - encoder->bits, + bits, audio_format.sample_rate, - (encoder->bits / 8) * audio_format.channels); + (bits / 8) * audio_format.channels); - encoder->buffer->Append(sizeof(*header)); - - return true; -} - -static void -wave_encoder_close(Encoder *_encoder) -{ - WaveEncoder *encoder = (WaveEncoder *)_encoder; - - encoder->buffer.Destruct(); + buffer.Append(sizeof(*header)); } static size_t @@ -194,17 +186,13 @@ return (dst8 - dst_old); } -static bool -wave_encoder_write(Encoder *_encoder, - const void *src, size_t length, - gcc_unused Error &error) +void +WaveEncoder::Write(const void *src, size_t length) { - WaveEncoder *encoder = (WaveEncoder *)_encoder; - - uint8_t *dst = encoder->buffer->Write(length); + uint8_t *dst = buffer.Write(length); if (IsLittleEndian()) { - switch (encoder->bits) { + switch (bits) { case 8: case 16: case 32:// optimized cases @@ -215,7 +203,7 @@ break; } } else { - switch (encoder->bits) { + switch (bits) { case 8: memcpy(dst, src, length); break; @@ -233,35 +221,10 @@ } } - encoder->buffer->Append(length); - return true; -} - -static size_t -wave_encoder_read(Encoder *_encoder, void *dest, size_t length) -{ - WaveEncoder *encoder = (WaveEncoder *)_encoder; - - return encoder->buffer->Read((uint8_t *)dest, length); -} - -static const char * -wave_encoder_get_mime_type(gcc_unused Encoder *_encoder) -{ - return "audio/wav"; + buffer.Append(length); } const EncoderPlugin wave_encoder_plugin = { "wave", wave_encoder_init, - wave_encoder_finish, - wave_encoder_open, - wave_encoder_close, - nullptr, - nullptr, - nullptr, - nullptr, - wave_encoder_write, - wave_encoder_read, - wave_encoder_get_mime_type, }; diff -Nru mpd-0.19.21/src/encoder/plugins/WaveEncoderPlugin.hxx mpd-0.20.9/src/encoder/plugins/WaveEncoderPlugin.hxx --- mpd-0.19.21/src/encoder/plugins/WaveEncoderPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/encoder/plugins/WaveEncoderPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/encoder/ToOutputStream.cxx mpd-0.20.9/src/encoder/ToOutputStream.cxx --- mpd-0.19.21/src/encoder/ToOutputStream.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/encoder/ToOutputStream.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ToOutputStream.hxx" +#include "EncoderInterface.hxx" +#include "fs/io/OutputStream.hxx" + +void +EncoderToOutputStream(OutputStream &os, Encoder &encoder) +{ + while (true) { + /* read from the encoder */ + + char buffer[32768]; + size_t nbytes = encoder.Read(buffer, sizeof(buffer)); + if (nbytes == 0) + return; + + /* write everything to the stream */ + + os.Write(buffer, nbytes); + } +} diff -Nru mpd-0.19.21/src/encoder/ToOutputStream.hxx mpd-0.20.9/src/encoder/ToOutputStream.hxx --- mpd-0.19.21/src/encoder/ToOutputStream.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/encoder/ToOutputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ENCODER_TO_OUTPUT_STREAM_HXX +#define MPD_ENCODER_TO_OUTPUT_STREAM_HXX + +#include "check.h" + +class OutputStream; +class Encoder; + +void +EncoderToOutputStream(OutputStream &os, Encoder &encoder); + +#endif diff -Nru mpd-0.19.21/src/event/BufferedSocket.cxx mpd-0.20.9/src/event/BufferedSocket.cxx --- mpd-0.19.21/src/event/BufferedSocket.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/BufferedSocket.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,9 +19,7 @@ #include "config.h" #include "BufferedSocket.hxx" -#include "system/SocketError.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "net/SocketError.hxx" #include "Compiler.h" #include @@ -45,7 +43,7 @@ if (IsSocketErrorClosed(code)) OnSocketClosed(); else - OnSocketError(NewSocketError(code)); + OnSocketError(std::make_exception_ptr(MakeSocketError(code, "Failed to receive from socket"))); return -1; } @@ -80,12 +78,7 @@ switch (result) { case InputResult::MORE: if (input.IsFull()) { - // TODO - static constexpr Domain buffered_socket_domain("buffered_socket"); - Error error; - error.Set(buffered_socket_domain, - "Input buffer is full"); - OnSocketError(std::move(error)); + OnSocketError(std::make_exception_ptr(std::runtime_error("Input buffer is full"))); return false; } diff -Nru mpd-0.19.21/src/event/BufferedSocket.hxx mpd-0.20.9/src/event/BufferedSocket.hxx --- mpd-0.19.21/src/event/BufferedSocket.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/BufferedSocket.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,10 +24,11 @@ #include "SocketMonitor.hxx" #include "util/StaticFifoBuffer.hxx" +#include + #include #include -class Error; class EventLoop; /** @@ -109,7 +110,7 @@ */ virtual InputResult OnSocketInput(void *data, size_t length) = 0; - virtual void OnSocketError(Error &&error) = 0; + virtual void OnSocketError(std::exception_ptr ep) = 0; virtual void OnSocketClosed() = 0; virtual bool OnSocketReady(unsigned flags) override; diff -Nru mpd-0.19.21/src/event/Call.cxx mpd-0.20.9/src/event/Call.cxx --- mpd-0.19.21/src/event/Call.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/Call.cxx 2017-02-09 20:10:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,6 +25,8 @@ #include "thread/Cond.hxx" #include "Compiler.h" +#include + #include class BlockingCallMonitor final @@ -37,6 +39,8 @@ bool done; + std::exception_ptr exception; + public: BlockingCallMonitor(EventLoop &_loop, std::function &&_f) :DeferredMonitor(_loop), f(std::move(_f)), done(false) {} @@ -50,13 +54,20 @@ while (!done) cond.wait(mutex); mutex.unlock(); + + if (exception) + std::rethrow_exception(exception); } private: virtual void RunDeferred() override { assert(!done); - f(); + try { + f(); + } catch (...) { + exception = std::current_exception(); + } mutex.lock(); done = true; @@ -68,7 +79,7 @@ void BlockingCall(EventLoop &loop, std::function &&f) { - if (loop.IsInside()) { + if (loop.IsInsideOrNull()) { /* we're already inside the loop - we can simply call the function */ f(); diff -Nru mpd-0.19.21/src/event/Call.hxx mpd-0.20.9/src/event/Call.hxx --- mpd-0.19.21/src/event/Call.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/Call.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/DeferredCall.hxx mpd-0.20.9/src/event/DeferredCall.hxx --- mpd-0.19.21/src/event/DeferredCall.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/event/DeferredCall.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_EVENT_DEFERRED_CALL_HXX +#define MPD_EVENT_DEFERRED_CALL_HXX + +#include "check.h" +#include "DeferredMonitor.hxx" +#include "util/BindMethod.hxx" + +/** + * Invoke a method call in the #EventLoop. + * + * This class is thread-safe. + */ +class DeferredCall final : DeferredMonitor { + typedef BoundMethod Callback; + const Callback callback; + +public: + DeferredCall(EventLoop &_loop, Callback _callback) + :DeferredMonitor(_loop), callback(_callback) {} + + using DeferredMonitor::GetEventLoop; + using DeferredMonitor::Schedule; + using DeferredMonitor::Cancel; + +protected: + void RunDeferred() override { + callback(); + } +}; + +#endif diff -Nru mpd-0.19.21/src/event/DeferredMonitor.cxx mpd-0.20.9/src/event/DeferredMonitor.cxx --- mpd-0.19.21/src/event/DeferredMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/DeferredMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/DeferredMonitor.hxx mpd-0.20.9/src/event/DeferredMonitor.hxx --- mpd-0.19.21/src/event/DeferredMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/DeferredMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/FullyBufferedSocket.cxx mpd-0.20.9/src/event/FullyBufferedSocket.cxx --- mpd-0.19.21/src/event/FullyBufferedSocket.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/FullyBufferedSocket.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,20 +19,12 @@ #include "config.h" #include "FullyBufferedSocket.hxx" -#include "system/SocketError.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "net/SocketError.hxx" #include "Compiler.h" #include -#include #include -#ifndef WIN32 -#include -#include -#endif - FullyBufferedSocket::ssize_t FullyBufferedSocket::DirectWrite(const void *data, size_t length) { @@ -48,7 +40,7 @@ if (IsSocketErrorClosed(code)) OnSocketClosed(); else - OnSocketError(NewSocketError(code)); + OnSocketError(std::make_exception_ptr(MakeSocketError(code, "Failed to send to socket"))); } return nbytes; @@ -91,11 +83,7 @@ const bool was_empty = output.IsEmpty(); if (!output.Append(data, length)) { - // TODO - static constexpr Domain buffered_socket_domain("buffered_socket"); - Error error; - error.Set(buffered_socket_domain, "Output buffer is full"); - OnSocketError(std::move(error)); + OnSocketError(std::make_exception_ptr(std::runtime_error("Output buffer is full"))); return false; } diff -Nru mpd-0.19.21/src/event/FullyBufferedSocket.hxx mpd-0.20.9/src/event/FullyBufferedSocket.hxx --- mpd-0.19.21/src/event/FullyBufferedSocket.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/FullyBufferedSocket.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/IdleMonitor.cxx mpd-0.20.9/src/event/IdleMonitor.cxx --- mpd-0.19.21/src/event/IdleMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/IdleMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/IdleMonitor.hxx mpd-0.20.9/src/event/IdleMonitor.hxx --- mpd-0.19.21/src/event/IdleMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/IdleMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/Loop.cxx mpd-0.20.9/src/event/Loop.cxx --- mpd-0.19.21/src/event/Loop.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/Loop.cxx 2017-02-09 20:21:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,8 +19,6 @@ #include "config.h" #include "Loop.hxx" - -#include "system/Clock.hxx" #include "TimeoutMonitor.hxx" #include "SocketMonitor.hxx" #include "IdleMonitor.hxx" @@ -29,13 +27,7 @@ #include EventLoop::EventLoop() - :SocketMonitor(*this), - now_ms(::MonotonicClockMS()), - quit(false), busy(true), -#ifndef NDEBUG - virgin(true), -#endif - thread(ThreadId::Null()) + :SocketMonitor(*this) { SocketMonitor::Open(wake_fd.Get()); SocketMonitor::Schedule(SocketMonitor::READ); @@ -98,13 +90,13 @@ } void -EventLoop::AddTimer(TimeoutMonitor &t, unsigned ms) +EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d) { /* can't use IsInsideOrVirgin() here because libavahi-client modifies the timeout during avahi_client_free() */ assert(IsInsideOrNull()); - timers.insert(TimerRecord(t, now_ms + ms)); + timers.insert(TimerRecord(t, now + d)); again = true; } @@ -121,6 +113,19 @@ } } +/** + * Convert the given timeout specification to a milliseconds integer, + * to be used by functions like poll() and epoll_wait(). Any negative + * value (= never times out) is translated to the magic value -1. + */ +static constexpr int +ExportTimeoutMS(std::chrono::steady_clock::duration timeout) +{ + return timeout >= timeout.zero() + ? int(std::chrono::duration_cast(timeout).count()) + : -1; +} + void EventLoop::Run() { @@ -137,21 +142,21 @@ assert(busy); do { - now_ms = ::MonotonicClockMS(); + now = std::chrono::steady_clock::now(); again = false; /* invoke timers */ - int timeout_ms; + std::chrono::steady_clock::duration timeout; while (true) { auto i = timers.begin(); if (i == timers.end()) { - timeout_ms = -1; + timeout = std::chrono::steady_clock::duration(-1); break; } - timeout_ms = i->due_ms - now_ms; - if (timeout_ms > 0) + timeout = i->due - now; + if (timeout > timeout.zero()) break; TimeoutMonitor &m = i->timer; @@ -190,9 +195,9 @@ /* wait for new event */ - poll_group.ReadEvents(poll_result, timeout_ms); + poll_group.ReadEvents(poll_result, ExportTimeoutMS(timeout)); - now_ms = ::MonotonicClockMS(); + now = std::chrono::steady_clock::now(); mutex.lock(); busy = true; @@ -217,8 +222,9 @@ #ifndef NDEBUG assert(busy); assert(thread.IsInside()); - thread = ThreadId::Null(); #endif + + thread = ThreadId::Null(); } void @@ -249,7 +255,7 @@ void EventLoop::RemoveDeferred(DeferredMonitor &d) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (!d.pending) { assert(std::find(deferred.begin(), diff -Nru mpd-0.19.21/src/event/Loop.hxx mpd-0.20.9/src/event/Loop.hxx --- mpd-0.19.21/src/event/Loop.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/Loop.hxx 2017-06-03 19:51:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,13 +29,13 @@ #include "WakeFD.hxx" #include "SocketMonitor.hxx" +#include #include #include class TimeoutMonitor; class IdleMonitor; class DeferredMonitor; -class SocketMonitor; #include @@ -55,20 +55,20 @@ * Projected monotonic_clock_ms() value when this * timer is due. */ - const unsigned due_ms; + const std::chrono::steady_clock::time_point due; TimeoutMonitor &timer; constexpr TimerRecord(TimeoutMonitor &_timer, - unsigned _due_ms) - :due_ms(_due_ms), timer(_timer) {} + std::chrono::steady_clock::time_point _due) + :due(_due), timer(_timer) {} bool operator<(const TimerRecord &other) const { - return due_ms < other.due_ms; + return due < other.due; } - bool IsDue(unsigned _now_ms) const { - return _now_ms >= due_ms; + bool IsDue(std::chrono::steady_clock::time_point _now) const { + return _now >= due; } }; @@ -80,9 +80,9 @@ Mutex mutex; std::list deferred; - unsigned now_ms; + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - bool quit; + bool quit = false; /** * True when the object has been modified and another check is @@ -96,14 +96,14 @@ * * Protected with #mutex. */ - bool busy; + bool busy = true; #ifndef NDEBUG /** * True if Run() was never called. This is used for assert() * calls. */ - bool virgin; + bool virgin = true; #endif PollGroup poll_group; @@ -112,19 +112,19 @@ /** * A reference to the thread that is currently inside Run(). */ - ThreadId thread; + ThreadId thread = ThreadId::Null(); public: EventLoop(); ~EventLoop(); /** - * A caching wrapper for MonotonicClockMS(). + * A caching wrapper for std::chrono::steady_clock::now(). */ - unsigned GetTimeMS() const { + std::chrono::steady_clock::time_point GetTime() const { assert(IsInside()); - return now_ms; + return now; } /** @@ -158,7 +158,8 @@ void AddIdle(IdleMonitor &i); void RemoveIdle(IdleMonitor &i); - void AddTimer(TimeoutMonitor &t, unsigned ms); + void AddTimer(TimeoutMonitor &t, + std::chrono::steady_clock::duration d); void CancelTimer(TimeoutMonitor &t); /** @@ -198,7 +199,7 @@ * Are we currently running inside this EventLoop's thread? */ gcc_pure - bool IsInside() const { + bool IsInside() const noexcept { assert(!thread.IsNull()); return thread.IsInside(); @@ -206,17 +207,21 @@ #ifndef NDEBUG gcc_pure - bool IsInsideOrVirgin() const { + bool IsInsideOrVirgin() const noexcept { return virgin || IsInside(); } #endif -#ifndef NDEBUG + /** + * Like IsInside(), but also returns true if the thread has + * already ended (or was not started yet). This is useful for + * code which may run during startup or shutdown, when events + * are not yet/anymore handled. + */ gcc_pure - bool IsInsideOrNull() const { + bool IsInsideOrNull() const noexcept { return thread.IsNull() || thread.IsInside(); } -#endif }; #endif /* MAIN_NOTIFY_H */ diff -Nru mpd-0.19.21/src/event/MaskMonitor.cxx mpd-0.20.9/src/event/MaskMonitor.cxx --- mpd-0.19.21/src/event/MaskMonitor.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/event/MaskMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "MaskMonitor.hxx" + +void +MaskMonitor::OrMask(unsigned new_mask) +{ + if (pending_mask.fetch_or(new_mask) == 0) + DeferredMonitor::Schedule(); +} + +void +MaskMonitor::RunDeferred() +{ + const unsigned mask = pending_mask.exchange(0); + if (mask != 0) + callback(mask); +} diff -Nru mpd-0.19.21/src/event/MaskMonitor.hxx mpd-0.20.9/src/event/MaskMonitor.hxx --- mpd-0.19.21/src/event/MaskMonitor.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/event/MaskMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_EVENT_MASK_MONITOR_HXX +#define MPD_EVENT_MASK_MONITOR_HXX + +#include "check.h" +#include "DeferredMonitor.hxx" +#include "util/BindMethod.hxx" + +#include + +/** + * Manage a bit mask of events that have occurred. Every time the + * mask becomes non-zero, OnMask() is called in #EventLoop's thread. + * + * This class is thread-safe. + */ +class MaskMonitor final : DeferredMonitor { + typedef BoundMethod Callback; + const Callback callback; + + std::atomic_uint pending_mask; + +public: + MaskMonitor(EventLoop &_loop, Callback _callback) + :DeferredMonitor(_loop), callback(_callback), pending_mask(0) {} + + using DeferredMonitor::GetEventLoop; + using DeferredMonitor::Cancel; + + void OrMask(unsigned new_mask); + +protected: + /* virtual methode from class DeferredMonitor */ + void RunDeferred() override; +}; + +#endif diff -Nru mpd-0.19.21/src/event/MultiSocketMonitor.cxx mpd-0.20.9/src/event/MultiSocketMonitor.cxx --- mpd-0.19.21/src/event/MultiSocketMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/MultiSocketMonitor.cxx 2017-02-09 19:55:46.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,12 +28,18 @@ #endif MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop) - :IdleMonitor(_loop), TimeoutMonitor(_loop), ready(false) { + :IdleMonitor(_loop), TimeoutMonitor(_loop) { } -MultiSocketMonitor::~MultiSocketMonitor() +void +MultiSocketMonitor::Reset() { - // TODO + assert(GetEventLoop().IsInsideOrNull()); + + fds.clear(); + IdleMonitor::Cancel(); + TimeoutMonitor::Cancel(); + ready = refresh = false; } void @@ -73,9 +79,9 @@ void MultiSocketMonitor::Prepare() { - int timeout_ms = PrepareSockets(); - if (timeout_ms >= 0) - TimeoutMonitor::Schedule(timeout_ms); + const auto timeout = PrepareSockets(); + if (timeout >= timeout.zero()) + TimeoutMonitor::Schedule(timeout); else TimeoutMonitor::Cancel(); diff -Nru mpd-0.19.21/src/event/MultiSocketMonitor.hxx mpd-0.20.9/src/event/MultiSocketMonitor.hxx --- mpd-0.19.21/src/event/MultiSocketMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/MultiSocketMonitor.hxx 2017-02-09 20:10:25.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -96,7 +96,19 @@ friend class SingleFD; - bool ready, refresh; + /** + * DispatchSockets() should be called. + */ + bool ready = false; + + /** + * PrepareSockets() should be called. + * + * Note that this doesn't need to be initialized by the + * constructor; this class is activated with the first + * InvalidateSockets() call, which initializes this flag. + */ + bool refresh; std::forward_list fds; @@ -107,11 +119,26 @@ static constexpr unsigned HANGUP = SocketMonitor::HANGUP; MultiSocketMonitor(EventLoop &_loop); - ~MultiSocketMonitor(); using IdleMonitor::GetEventLoop; -public: + /** + * Clear the socket list and disable all #EventLoop + * registrations. Run this in the #EventLoop thread before + * destroying this object. + * + * Later, this object can be reused and reactivated by calling + * InvalidateSockets(). + * + * Note that this class doesn't have a destructor which calls + * this method, because this would be racy and thus pointless: + * at the time ~MultiSocketMonitor() is called, our virtual + * methods have been morphed to be pure again, and in the + * meantime the #EventLoop thread could invoke those pure + * methods. + */ + void Reset(); + /** * Invalidate the socket list. A call to PrepareSockets() is * scheduled which will then update the list. @@ -121,12 +148,19 @@ IdleMonitor::Schedule(); } + /** + * Add one socket to the list of monitored sockets. + * + * May only be called from PrepareSockets(). + */ void AddSocket(int fd, unsigned events) { fds.emplace_front(*this, fd, events); } /** * Remove all sockets. + * + * May only be called from PrepareSockets(). */ void ClearSocketList(); @@ -135,6 +169,8 @@ * each one; its return value is the events bit mask. A * return value of 0 means the socket will be removed from the * list. + * + * May only be called from PrepareSockets(). */ template void UpdateSocketList(E &&e) { @@ -157,15 +193,26 @@ /** * Replace the socket list with the given file descriptors. * The given pollfd array will be modified by this method. + * + * May only be called from PrepareSockets(). */ void ReplaceSocketList(pollfd *pfds, unsigned n); #endif protected: /** - * @return timeout [ms] or -1 for no timeout + * Override this method and update the socket registrations. + * To do that, call AddSocket(), ClearSocketList(), + * UpdateSocketList() and ReplaceSocketList(). + * + * @return timeout or a negative value for no timeout + */ + virtual std::chrono::steady_clock::duration PrepareSockets() = 0; + + /** + * At least one socket is ready or the timeout has expired. + * This method should be used to perform I/O. */ - virtual int PrepareSockets() = 0; virtual void DispatchSockets() = 0; private: diff -Nru mpd-0.19.21/src/event/PollGroupEPoll.hxx mpd-0.20.9/src/event/PollGroupEPoll.hxx --- mpd-0.19.21/src/event/PollGroupEPoll.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroupEPoll.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollGroup.hxx mpd-0.20.9/src/event/PollGroup.hxx --- mpd-0.19.21/src/event/PollGroup.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroup.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollGroupPoll.cxx mpd-0.20.9/src/event/PollGroupPoll.cxx --- mpd-0.19.21/src/event/PollGroupPoll.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroupPoll.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollGroupPoll.hxx mpd-0.20.9/src/event/PollGroupPoll.hxx --- mpd-0.19.21/src/event/PollGroupPoll.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroupPoll.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollGroupWinSelect.cxx mpd-0.20.9/src/event/PollGroupWinSelect.cxx --- mpd-0.19.21/src/event/PollGroupWinSelect.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroupWinSelect.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollGroupWinSelect.hxx mpd-0.20.9/src/event/PollGroupWinSelect.hxx --- mpd-0.19.21/src/event/PollGroupWinSelect.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollGroupWinSelect.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/PollResultGeneric.hxx mpd-0.20.9/src/event/PollResultGeneric.hxx --- mpd-0.19.21/src/event/PollResultGeneric.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/PollResultGeneric.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/ServerSocket.cxx mpd-0.20.9/src/event/ServerSocket.cxx --- mpd-0.19.21/src/event/ServerSocket.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/ServerSocket.cxx 2017-05-08 14:21:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,27 +19,28 @@ #include "config.h" #include "ServerSocket.hxx" -#include "system/SocketUtil.hxx" -#include "system/SocketError.hxx" +#include "net/StaticSocketAddress.hxx" +#include "net/AllocatedSocketAddress.hxx" +#include "net/SocketAddress.hxx" +#include "net/SocketUtil.hxx" +#include "net/SocketError.hxx" +#include "net/Resolver.hxx" +#include "net/ToString.hxx" #include "event/SocketMonitor.hxx" -#include "system/Resolver.hxx" #include "system/fd_util.h" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" -#include "util/Alloc.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" +#include "util/ScopeExit.hxx" #include "Log.hxx" #include #include -#include #include -#include #include #include -#include #include #ifdef WIN32 @@ -48,43 +49,38 @@ #else #include #include -#include #include #endif -#define DEFAULT_PORT 6600 - class OneServerSocket final : private SocketMonitor { ServerSocket &parent; const unsigned serial; +#ifdef HAVE_UN AllocatedPath path; +#endif - size_t address_length; - struct sockaddr *address; + const AllocatedSocketAddress address; public: + template OneServerSocket(EventLoop &_loop, ServerSocket &_parent, unsigned _serial, - const struct sockaddr *_address, - size_t _address_length) + A &&_address) :SocketMonitor(_loop), parent(_parent), serial(_serial), +#ifdef HAVE_UN path(AllocatedPath::Null()), - address_length(_address_length), - address((sockaddr *)xmemdup(_address, _address_length)) +#endif + address(std::forward(_address)) { - assert(_address != nullptr); - assert(_address_length > 0); } OneServerSocket(const OneServerSocket &other) = delete; OneServerSocket &operator=(const OneServerSocket &other) = delete; ~OneServerSocket() { - free(address); - if (IsDefined()) Close(); } @@ -93,28 +89,30 @@ return serial; } +#ifdef HAVE_UN void SetPath(AllocatedPath &&_path) { assert(path.IsNull()); path = std::move(_path); } +#endif - bool Open(Error &error); + void Open(); using SocketMonitor::IsDefined; using SocketMonitor::Close; gcc_pure - std::string ToString() const { - return sockaddr_to_string(address, address_length); + std::string ToString() const noexcept { + return ::ToString(address); } - void SetFD(int _fd) { + void SetFD(int _fd) noexcept { SocketMonitor::Open(_fd); SocketMonitor::ScheduleRead(); } - void Accept(); + void Accept() noexcept; private: virtual bool OnSocketReady(unsigned flags) override; @@ -148,12 +146,12 @@ } inline void -OneServerSocket::Accept() +OneServerSocket::Accept() noexcept { - struct sockaddr_storage peer_address; + StaticSocketAddress peer_address; size_t peer_address_length = sizeof(peer_address); int peer_fd = - accept_cloexec_nonblock(Get(), (struct sockaddr*)&peer_address, + accept_cloexec_nonblock(Get(), peer_address.GetAddress(), &peer_address_length); if (peer_fd < 0) { const SocketErrorMessage msg; @@ -162,6 +160,8 @@ return; } + peer_address.SetSize(peer_address_length); + if (socket_keepalive(peer_fd)) { const SocketErrorMessage msg; FormatError(server_socket_domain, @@ -169,9 +169,8 @@ (const char *)msg); } - parent.OnAccept(peer_fd, - (const sockaddr &)peer_address, - peer_address_length, get_remote_uid(peer_fd)); + parent.OnAccept(peer_fd, peer_address, + get_remote_uid(peer_fd)); } bool @@ -181,28 +180,25 @@ return true; } -inline bool -OneServerSocket::Open(Error &error) +inline void +OneServerSocket::Open() { assert(!IsDefined()); - int _fd = socket_bind_listen(address->sa_family, + int _fd = socket_bind_listen(address.GetFamily(), SOCK_STREAM, 0, - address, address_length, 5, - error); - if (_fd < 0) - return false; + address, 5); +#ifdef HAVE_UN /* allow everybody to connect */ if (!path.IsNull()) chmod(path.c_str(), 0666); +#endif - /* register in the GLib main loop */ + /* register in the EventLoop */ SetFD(_fd); - - return true; } ServerSocket::ServerSocket(EventLoop &_loop) @@ -212,11 +208,11 @@ declaration */ ServerSocket::~ServerSocket() {} -bool -ServerSocket::Open(Error &error) +void +ServerSocket::Open() { OneServerSocket *good = nullptr, *bad = nullptr; - Error last_error; + std::exception_ptr last_error; for (auto &i : sockets) { assert(i.GetSerial() > 0); @@ -224,30 +220,32 @@ if (bad != nullptr && i.GetSerial() != bad->GetSerial()) { Close(); - error = std::move(last_error); - return false; + std::rethrow_exception(last_error); } - Error error2; - if (!i.Open(error2)) { + try { + i.Open(); + } catch (const std::runtime_error &e) { if (good != nullptr && good->GetSerial() == i.GetSerial()) { const auto address_string = i.ToString(); const auto good_string = good->ToString(); - FormatWarning(server_socket_domain, - "bind to '%s' failed: %s " - "(continuing anyway, because " - "binding to '%s' succeeded)", - address_string.c_str(), - error2.GetMessage(), - good_string.c_str()); + FormatError(e, + "bind to '%s' failed " + "(continuing anyway, because " + "binding to '%s' succeeded)", + address_string.c_str(), + good_string.c_str()); } else if (bad == nullptr) { bad = &i; const auto address_string = i.ToString(); - error2.FormatPrefix("Failed to bind to '%s': ", - address_string.c_str()); - last_error = std::move(error2); + try { + std::throw_with_nested(FormatRuntimeError("Failed to bind to '%s'", + address_string.c_str())); + } catch (...) { + last_error = std::current_exception(); + } } continue; @@ -260,17 +258,14 @@ if (bad != nullptr) { bad = nullptr; - last_error.Clear(); + last_error = nullptr; } } if (bad != nullptr) { Close(); - error = std::move(last_error); - return false; + std::rethrow_exception(last_error); } - - return true; } void @@ -282,33 +277,38 @@ } OneServerSocket & -ServerSocket::AddAddress(const sockaddr &address, size_t address_length) +ServerSocket::AddAddress(SocketAddress address) { sockets.emplace_back(loop, *this, next_serial, - &address, address_length); + address); return sockets.back(); } -bool -ServerSocket::AddFD(int fd, Error &error) +OneServerSocket & +ServerSocket::AddAddress(AllocatedSocketAddress &&address) +{ + sockets.emplace_back(loop, *this, next_serial, + std::move(address)); + + return sockets.back(); +} + +void +ServerSocket::AddFD(int fd) { assert(fd >= 0); - struct sockaddr_storage address; + StaticSocketAddress address; socklen_t address_length = sizeof(address); - if (getsockname(fd, (struct sockaddr *)&address, - &address_length) < 0) { - SetSocketError(error); - error.AddPrefix("Failed to get socket address: "); - return false; - } + if (getsockname(fd, address.GetAddress(), + &address_length) < 0) + throw MakeSocketError("Failed to get socket address"); - OneServerSocket &s = AddAddress((const sockaddr &)address, - address_length); - s.SetFD(fd); + address.SetSize(address_length); - return true; + OneServerSocket &s = AddAddress(address); + s.SetFD(fd); } #ifdef HAVE_TCP @@ -322,7 +322,7 @@ sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; - AddAddress((const sockaddr &)sin, sizeof(sin)); + AddAddress({(const sockaddr *)&sin, sizeof(sin)}); } #ifdef HAVE_IPV6 @@ -335,7 +335,7 @@ sin.sin6_port = htons(port); sin.sin6_family = AF_INET6; - AddAddress((const sockaddr &)sin, sizeof(sin)); + AddAddress({(const sockaddr *)&sin, sizeof(sin)}); } /** @@ -343,7 +343,7 @@ */ gcc_pure static bool -SupportsIPv6() +SupportsIPv6() noexcept { int fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd < 0) @@ -357,14 +357,12 @@ #endif /* HAVE_TCP */ -bool -ServerSocket::AddPort(unsigned port, Error &error) +void +ServerSocket::AddPort(unsigned port) { #ifdef HAVE_TCP - if (port == 0 || port > 0xffff) { - error.Set(server_socket_domain, "Invalid TCP port"); - return false; - } + if (port == 0 || port > 0xffff) + throw std::runtime_error("Invalid TCP port"); #ifdef HAVE_IPV6 if (SupportsIPv6()) @@ -373,71 +371,48 @@ AddPortIPv4(port); ++next_serial; - - return true; #else /* HAVE_TCP */ (void)port; - error.Set(server_socket_domain, "TCP support is disabled"); - return false; + throw std::runtime_error("TCP support is disabled"); #endif /* HAVE_TCP */ } -bool -ServerSocket::AddHost(const char *hostname, unsigned port, Error &error) +void +ServerSocket::AddHost(const char *hostname, unsigned port) { #ifdef HAVE_TCP struct addrinfo *ai = resolve_host_port(hostname, port, - AI_PASSIVE, SOCK_STREAM, - error); - if (ai == nullptr) - return false; + AI_PASSIVE, SOCK_STREAM); + AtScopeExit(ai) { freeaddrinfo(ai); }; for (const struct addrinfo *i = ai; i != nullptr; i = i->ai_next) - AddAddress(*i->ai_addr, i->ai_addrlen); - - freeaddrinfo(ai); + AddAddress(SocketAddress(i->ai_addr, i->ai_addrlen)); ++next_serial; - - return true; #else /* HAVE_TCP */ (void)hostname; (void)port; - error.Set(server_socket_domain, "TCP support is disabled"); - return false; + throw std::runtime_error("TCP support is disabled"); #endif /* HAVE_TCP */ } -bool -ServerSocket::AddPath(AllocatedPath &&path, Error &error) +void +ServerSocket::AddPath(AllocatedPath &&path) { #ifdef HAVE_UN - struct sockaddr_un s_un; + unlink(path.c_str()); - const size_t path_length = path.length(); - if (path_length >= sizeof(s_un.sun_path)) { - error.Set(server_socket_domain, - "UNIX socket path is too long"); - return false; - } - - RemoveFile(path); + AllocatedSocketAddress address; + address.SetLocal(path.c_str()); - s_un.sun_family = AF_UNIX; - memcpy(s_un.sun_path, path.c_str(), path_length + 1); - - OneServerSocket &s = AddAddress((const sockaddr &)s_un, sizeof(s_un)); + OneServerSocket &s = AddAddress(std::move(address)); s.SetPath(std::move(path)); - - return true; #else /* !HAVE_UN */ (void)path; - error.Set(server_socket_domain, - "UNIX domain socket support is disabled"); - return false; + throw std::runtime_error("UNIX domain socket support is disabled"); #endif /* !HAVE_UN */ } diff -Nru mpd-0.19.21/src/event/ServerSocket.hxx mpd-0.20.9/src/event/ServerSocket.hxx --- mpd-0.19.21/src/event/ServerSocket.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/ServerSocket.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,18 +22,10 @@ #include -#include - -struct sockaddr; +class SocketAddress; +class AllocatedSocketAddress; class EventLoop; -class Error; class AllocatedPath; - -typedef void (*server_socket_callback_t)(int fd, - const struct sockaddr *address, - size_t address_length, int uid, - void *ctx); - class OneServerSocket; /** @@ -57,7 +49,8 @@ } private: - OneServerSocket &AddAddress(const sockaddr &address, size_t length); + OneServerSocket &AddAddress(SocketAddress address); + OneServerSocket &AddAddress(AllocatedSocketAddress &&address); /** * Add a listener on a port on all IPv4 interfaces. @@ -77,48 +70,53 @@ /** * Add a listener on a port on all interfaces. * + * Throws #std::runtime_error on error. + * * @param port the TCP port - * @param error_r location to store the error occurring, or nullptr to - * ignore errors - * @return true on success + * @param error location to store the error occurring */ - bool AddPort(unsigned port, Error &error); + void AddPort(unsigned port); /** * Resolves a host name, and adds listeners on all addresses in the * result set. * + * Throws #std::runtime_error on error. + * * @param hostname the host name to be resolved * @param port the TCP port - * @param error_r location to store the error occurring, or nullptr to - * ignore errors - * @return true on success + * @param error location to store the error occurring */ - bool AddHost(const char *hostname, unsigned port, Error &error); + void AddHost(const char *hostname, unsigned port); /** * Add a listener on a Unix domain socket. * + * Throws #std::runtime_error on error. + * * @param path the absolute socket path - * @param error_r location to store the error occurring, or nullptr to - * ignore errors - * @return true on success + * @param error location to store the error occurring */ - bool AddPath(AllocatedPath &&path, Error &error); + void AddPath(AllocatedPath &&path); /** * Add a socket descriptor that is accepting connections. After this * has been called, don't call server_socket_open(), because the * socket is already open. + * + * Throws #std::runtime_error on error. + */ + void AddFD(int fd); + + /** + * Throws #std::runtime_error on error. */ - bool AddFD(int fd, Error &error); + void Open(); - bool Open(Error &error); void Close(); protected: - virtual void OnAccept(int fd, const sockaddr &address, - size_t address_length, int uid) = 0; + virtual void OnAccept(int fd, SocketAddress address, int uid) = 0; }; #endif diff -Nru mpd-0.19.21/src/event/SignalMonitor.cxx mpd-0.20.9/src/event/SignalMonitor.cxx --- mpd-0.19.21/src/event/SignalMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/SignalMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ #ifndef WIN32 -#include "WakeFD.hxx" #include "SocketMonitor.hxx" #include "util/Manual.hxx" #include "system/FatalError.hxx" @@ -116,7 +115,7 @@ static void SignalCallback(int signo) { - assert(signal_handlers[signo] != nullptr); + assert(signal_handlers[signo]); if (!signal_pending[signo].exchange(true)) monitor->WakeUp(); @@ -159,7 +158,7 @@ sa.sa_handler = SIG_DFL; for (unsigned i = 0; i < MAX_SIGNAL; ++i) { - if (signal_handlers[i] != nullptr) { + if (signal_handlers[i]) { x_sigaction(i, sa); signal_handlers[i] = nullptr; } @@ -171,16 +170,10 @@ monitor.Destruct(); } -EventLoop & -SignalMonitorGetEventLoop() -{ - return monitor->GetEventLoop(); -} - void SignalMonitorRegister(int signo, SignalHandler handler) { - assert(signal_handlers[signo] == nullptr); + assert(!signal_handlers[signo]); #ifndef USE_SIGNALFD assert(!signal_pending[signo]); #endif @@ -210,7 +203,7 @@ int signo; while ((signo = fd.Read()) >= 0) { assert(unsigned(signo) < MAX_SIGNAL); - assert(signal_handlers[signo] != nullptr); + assert(signal_handlers[signo]); signal_handlers[signo](); } diff -Nru mpd-0.19.21/src/event/SignalMonitor.hxx mpd-0.20.9/src/event/SignalMonitor.hxx --- mpd-0.19.21/src/event/SignalMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/SignalMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,9 @@ #ifndef WIN32 -typedef void (*SignalHandler)(); +#include "util/BindMethod.hxx" + +typedef BoundMethod SignalHandler; /** * Initialise the signal monitor subsystem. @@ -41,13 +43,6 @@ SignalMonitorFinish(); /** - * Obtain a reference to the #EventLoop that was passed to - * SignalMonitorInit(). - */ -EventLoop & -SignalMonitorGetEventLoop(); - -/** * Register a handler for the specified signal. The handler will be * invoked in a safe context. */ diff -Nru mpd-0.19.21/src/event/SocketMonitor.cxx mpd-0.20.9/src/event/SocketMonitor.cxx --- mpd-0.19.21/src/event/SocketMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/SocketMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,6 @@ #include "SocketMonitor.hxx" #include "Loop.hxx" #include "system/fd_util.h" -#include "Compiler.h" #include diff -Nru mpd-0.19.21/src/event/SocketMonitor.hxx mpd-0.20.9/src/event/SocketMonitor.hxx --- mpd-0.19.21/src/event/SocketMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/SocketMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/event/TimeoutMonitor.cxx mpd-0.20.9/src/event/TimeoutMonitor.cxx --- mpd-0.19.21/src/event/TimeoutMonitor.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/TimeoutMonitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,21 +31,12 @@ } void - -TimeoutMonitor::Schedule(unsigned ms) +TimeoutMonitor::Schedule(std::chrono::steady_clock::duration d) { Cancel(); active = true; - loop.AddTimer(*this, ms); -} - -void -TimeoutMonitor::ScheduleSeconds(unsigned s) -{ - Cancel(); - - Schedule(s * 1000u); + loop.AddTimer(*this, d); } void diff -Nru mpd-0.19.21/src/event/TimeoutMonitor.hxx mpd-0.20.9/src/event/TimeoutMonitor.hxx --- mpd-0.19.21/src/event/TimeoutMonitor.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/TimeoutMonitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,8 @@ #include "check.h" +#include + class EventLoop; /** @@ -56,8 +58,7 @@ return active; } - void Schedule(unsigned ms); - void ScheduleSeconds(unsigned s); + void Schedule(std::chrono::steady_clock::duration d); void Cancel(); protected: diff -Nru mpd-0.19.21/src/event/WakeFD.hxx mpd-0.20.9/src/event/WakeFD.hxx --- mpd-0.19.21/src/event/WakeFD.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/event/WakeFD.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/filter/FilterConfig.cxx mpd-0.20.9/src/filter/FilterConfig.cxx --- mpd-0.19.21/src/filter/FilterConfig.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterConfig.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,43 +21,36 @@ #include "FilterConfig.hxx" #include "plugins/ChainFilterPlugin.hxx" #include "FilterPlugin.hxx" -#include "config/ConfigData.hxx" +#include "config/Param.hxx" #include "config/ConfigOption.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "config/Block.hxx" +#include "util/RuntimeError.hxx" #include #include -static bool -filter_chain_append_new(Filter &chain, const char *template_name, Error &error) +static void +filter_chain_append_new(PreparedFilter &chain, const char *template_name) { - const struct config_param *cfg = - config_find_block(CONF_AUDIO_FILTER, "name", template_name); - if (cfg == nullptr) { - error.Format(config_domain, - "filter template not found: %s", - template_name); - return false; - } + const auto *cfg = config_find_block(ConfigBlockOption::AUDIO_FILTER, + "name", template_name); + if (cfg == nullptr) + throw FormatRuntimeError("Filter template not found: %s", + template_name); // Instantiate one of those filter plugins with the template name as a hint - Filter *f = filter_configured_new(*cfg, error); - if (f == nullptr) - // The error has already been set, just stop. - return false; + PreparedFilter *f = filter_configured_new(*cfg); const char *plugin_name = cfg->GetBlockValue("plugin", "unknown"); filter_chain_append(chain, plugin_name, f); - - return true; } -bool -filter_chain_parse(Filter &chain, const char *spec, Error &error) +void +filter_chain_parse(PreparedFilter &chain, const char *spec) { const char *const end = spec + strlen(spec); @@ -65,9 +58,7 @@ const char *comma = std::find(spec, end, ','); if (comma > spec) { const std::string name(spec, comma); - if (!filter_chain_append_new(chain, name.c_str(), - error)) - return false; + filter_chain_append_new(chain, name.c_str()); } if (comma == end) @@ -75,6 +66,4 @@ spec = comma + 1; } - - return true; } diff -Nru mpd-0.19.21/src/filter/FilterConfig.hxx mpd-0.20.9/src/filter/FilterConfig.hxx --- mpd-0.19.21/src/filter/FilterConfig.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterConfig.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,19 +25,19 @@ #ifndef MPD_FILTER_CONFIG_HXX #define MPD_FILTER_CONFIG_HXX -class Filter; -class Error; +class PreparedFilter; /** * Builds a filter chain from a configuration string on the form * "name1, name2, name3, ..." by looking up each name among the * configured filter sections. + * + * Throws std::runtime_error on error. + * * @param chain the chain to append filters on * @param spec the filter chain specification - * @param error_r space to return an error description - * @return true on success */ -bool -filter_chain_parse(Filter &chain, const char *spec, Error &error); +void +filter_chain_parse(PreparedFilter &chain, const char *spec); #endif diff -Nru mpd-0.19.21/src/filter/FilterInternal.hxx mpd-0.20.9/src/filter/FilterInternal.hxx --- mpd-0.19.21/src/filter/FilterInternal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterInternal.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,47 +25,66 @@ #ifndef MPD_FILTER_INTERNAL_HXX #define MPD_FILTER_INTERNAL_HXX +#include "AudioFormat.hxx" + +#include #include struct AudioFormat; -class Error; template struct ConstBuffer; class Filter { +protected: + AudioFormat out_audio_format; + + explicit Filter(AudioFormat _out_audio_format) + :out_audio_format(_out_audio_format) { + assert(out_audio_format.IsValid()); + } + public: virtual ~Filter() {} /** - * Opens the filter, preparing it for FilterPCM(). - * - * @param filter the filter object - * @param af the audio format of incoming data; the - * plugin may modify the object to enforce another input - * format - * @param error location to store the error occurring, or nullptr - * to ignore errors. - * @return the format of outgoing data or - * AudioFormat::Undefined() on error + * Returns the #AudioFormat produced by FilterPCM(). */ - virtual AudioFormat Open(AudioFormat &af, Error &error) = 0; + const AudioFormat &GetOutAudioFormat() const { + return out_audio_format; + } /** - * Closes the filter. After that, you may call Open() again. + * Reset the filter's state, e.g. drop/flush buffers. */ - virtual void Close() = 0; + virtual void Reset() { + } /** * Filters a block of PCM data. * - * @param filter the filter object + * Throws std::runtime_error on error. + * * @param src the input buffer - * @param error location to store the error occurring, or nullptr - * to ignore errors. * @return the destination buffer on success (will be - * invalidated by Close() or FilterPCM()), nullptr on - * error + * invalidated by deleting this object or the next FilterPCM() + * or Reset() call) + */ + virtual ConstBuffer FilterPCM(ConstBuffer src) = 0; +}; + +class PreparedFilter { +public: + virtual ~PreparedFilter() {} + + /** + * Opens the filter, preparing it for FilterPCM(). + * + * Throws std::runtime_error on error. + * + * @param af the audio format of incoming data; the + * plugin may modify the object to enforce another input + * format */ - virtual ConstBuffer FilterPCM(ConstBuffer src, Error &error) = 0; + virtual Filter *Open(AudioFormat &af) = 0; }; #endif diff -Nru mpd-0.19.21/src/filter/FilterPlugin.cxx mpd-0.20.9/src/filter/FilterPlugin.cxx --- mpd-0.19.21/src/filter/FilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,39 +20,31 @@ #include "config.h" #include "FilterPlugin.hxx" #include "FilterRegistry.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include -Filter * -filter_new(const struct filter_plugin *plugin, - const config_param ¶m, Error &error) +PreparedFilter * +filter_new(const FilterPlugin *plugin, const ConfigBlock &block) { assert(plugin != nullptr); - assert(!error.IsDefined()); - return plugin->init(param, error); + return plugin->init(block); } -Filter * -filter_configured_new(const config_param ¶m, Error &error) +PreparedFilter * +filter_configured_new(const ConfigBlock &block) { - assert(!error.IsDefined()); + const char *plugin_name = block.GetBlockValue("plugin"); + if (plugin_name == nullptr) + throw std::runtime_error("No filter plugin specified"); + + const auto *plugin = filter_plugin_by_name(plugin_name); + if (plugin == nullptr) + throw FormatRuntimeError("No such filter plugin: %s", + plugin_name); - const char *plugin_name = param.GetBlockValue("plugin"); - if (plugin_name == nullptr) { - error.Set(config_domain, "No filter plugin specified"); - return nullptr; - } - - const filter_plugin *plugin = filter_plugin_by_name(plugin_name); - if (plugin == nullptr) { - error.Format(config_domain, - "No such filter plugin: %s", plugin_name); - return nullptr; - } - - return filter_new(plugin, param, error); + return filter_new(plugin, block); } diff -Nru mpd-0.19.21/src/filter/FilterPlugin.hxx mpd-0.20.9/src/filter/FilterPlugin.hxx --- mpd-0.19.21/src/filter/FilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,42 +26,39 @@ #ifndef MPD_FILTER_PLUGIN_HXX #define MPD_FILTER_PLUGIN_HXX -struct config_param; -class Filter; -class Error; +struct ConfigBlock; +class PreparedFilter; -struct filter_plugin { +struct FilterPlugin { const char *name; /** * Allocates and configures a filter. */ - Filter *(*init)(const config_param ¶m, Error &error); + PreparedFilter *(*init)(const ConfigBlock &block); }; /** * Creates a new instance of the specified filter plugin. * + * Throws std::runtime_error on error. + * * @param plugin the filter plugin - * @param param optional configuration section - * @param error location to store the error occurring, or nullptr to - * ignore errors. - * @return a new filter object, or nullptr on error + * @param block configuration section */ -Filter * -filter_new(const struct filter_plugin *plugin, - const config_param ¶m, Error &error); +PreparedFilter * +filter_new(const FilterPlugin *plugin, + const ConfigBlock &block); /** * Creates a new filter, loads configuration and the plugin name from * the specified configuration section. * - * @param param the configuration section - * @param error location to store the error occurring, or nullptr to - * ignore errors. - * @return a new filter object, or nullptr on error + * Throws std::runtime_error on error. + * + * @param block the configuration section */ -Filter * -filter_configured_new(const config_param ¶m, Error &error); +PreparedFilter * +filter_configured_new(const ConfigBlock &block); #endif diff -Nru mpd-0.19.21/src/filter/FilterRegistry.cxx mpd-0.20.9/src/filter/FilterRegistry.cxx --- mpd-0.19.21/src/filter/FilterRegistry.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterRegistry.cxx 2017-05-08 13:04:32.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,17 +23,16 @@ #include -const struct filter_plugin *const filter_plugins[] = { +static const FilterPlugin *const filter_plugins[] = { &null_filter_plugin, &route_filter_plugin, &normalize_filter_plugin, &volume_filter_plugin, - &replay_gain_filter_plugin, nullptr, }; -const struct filter_plugin * -filter_plugin_by_name(const char *name) +const FilterPlugin * +filter_plugin_by_name(const char *name) noexcept { for (unsigned i = 0; filter_plugins[i] != nullptr; ++i) if (strcmp(filter_plugins[i]->name, name) == 0) diff -Nru mpd-0.19.21/src/filter/FilterRegistry.hxx mpd-0.20.9/src/filter/FilterRegistry.hxx --- mpd-0.19.21/src/filter/FilterRegistry.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/FilterRegistry.hxx 2017-05-08 13:04:28.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,16 +28,17 @@ #include "Compiler.h" -extern const struct filter_plugin null_filter_plugin; -extern const struct filter_plugin chain_filter_plugin; -extern const struct filter_plugin convert_filter_plugin; -extern const struct filter_plugin route_filter_plugin; -extern const struct filter_plugin normalize_filter_plugin; -extern const struct filter_plugin volume_filter_plugin; -extern const struct filter_plugin replay_gain_filter_plugin; +struct FilterPlugin; + +extern const FilterPlugin null_filter_plugin; +extern const FilterPlugin chain_filter_plugin; +extern const FilterPlugin convert_filter_plugin; +extern const FilterPlugin route_filter_plugin; +extern const FilterPlugin normalize_filter_plugin; +extern const FilterPlugin volume_filter_plugin; gcc_pure -const struct filter_plugin * -filter_plugin_by_name(const char *name); +const FilterPlugin * +filter_plugin_by_name(const char *name) noexcept; #endif diff -Nru mpd-0.19.21/src/filter/Observer.cxx mpd-0.20.9/src/filter/Observer.cxx --- mpd-0.19.21/src/filter/Observer.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/filter/Observer.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Observer.hxx" +#include "FilterInternal.hxx" +#include "util/ConstBuffer.hxx" + +#include + +class FilterObserver::PreparedProxy final : public PreparedFilter { + FilterObserver &observer; + + PreparedFilter *const prepared_filter; + Proxy *child = nullptr; + +public: + PreparedProxy(FilterObserver &_observer, + PreparedFilter *_prepared_filter) + :observer(_observer), + prepared_filter(_prepared_filter) {} + + ~PreparedProxy() { + assert(child == nullptr); + assert(observer.proxy == this); + + observer.proxy = nullptr; + delete prepared_filter; + } + + void Clear(gcc_unused Proxy *_child) { + assert(child == _child); + child = nullptr; + } + + Filter *Get(); + + Filter *Open(AudioFormat &af) override; +}; + +class FilterObserver::Proxy final : public Filter { + PreparedProxy &parent; + + Filter *const filter; + +public: + Proxy(PreparedProxy &_parent, Filter *_filter) + :Filter(_filter->GetOutAudioFormat()), + parent(_parent), filter(_filter) {} + + ~Proxy() { + parent.Clear(this); + delete filter; + } + + Filter *Get() { + return filter; + } + + ConstBuffer FilterPCM(ConstBuffer src) override { + return filter->FilterPCM(src); + } +}; + +Filter * +FilterObserver::PreparedProxy::Get() +{ + return child != nullptr + ? child->Get() + : nullptr; +} + +Filter * +FilterObserver::PreparedProxy::Open(AudioFormat &af) +{ + assert(child == nullptr); + + Filter *f = prepared_filter->Open(af); + return child = new Proxy(*this, f); +} + +PreparedFilter * +FilterObserver::Set(PreparedFilter *pf) +{ + assert(proxy == nullptr); + + return proxy = new PreparedProxy(*this, pf); +} + +Filter * +FilterObserver::Get() +{ + return proxy != nullptr + ? proxy->Get() + : nullptr; +} diff -Nru mpd-0.19.21/src/filter/Observer.hxx mpd-0.20.9/src/filter/Observer.hxx --- mpd-0.19.21/src/filter/Observer.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/filter/Observer.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FILTER_OBSERVER_HXX +#define MPD_FILTER_OBSERVER_HXX + +#include "check.h" + +class PreparedFilter; +class Filter; + +/** + * A helper class which observes calls to a #PreparedFilter and allows + * the caller to access the #Filter instances created by it. + */ +class FilterObserver { + class PreparedProxy; + class Proxy; + + PreparedProxy *proxy = nullptr; + +public: + /** + * @return a proxy object + */ + PreparedFilter *Set(PreparedFilter *pf); + + Filter *Get(); +}; + +#endif diff -Nru mpd-0.19.21/src/filter/plugins/AutoConvertFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/AutoConvertFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/AutoConvertFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/AutoConvertFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,107 +24,90 @@ #include "filter/FilterInternal.hxx" #include "filter/FilterRegistry.hxx" #include "AudioFormat.hxx" -#include "config/ConfigData.hxx" #include "util/ConstBuffer.hxx" +#include + #include class AutoConvertFilter final : public Filter { /** * The underlying filter. */ - Filter *filter; + std::unique_ptr filter; /** * A convert_filter, just in case conversion is needed. nullptr * if unused. */ - Filter *convert; + std::unique_ptr convert; public: - AutoConvertFilter(Filter *_filter):filter(_filter) {} - ~AutoConvertFilter() { + AutoConvertFilter(std::unique_ptr &&_filter, + std::unique_ptr &&_convert) + :Filter(_filter->GetOutAudioFormat()), + filter(std::move(_filter)), convert(std::move(_convert)) {} + + void Reset() override { + filter->Reset(); + + if (convert) + convert->Reset(); + } + + ConstBuffer FilterPCM(ConstBuffer src) override; +}; + +class PreparedAutoConvertFilter final : public PreparedFilter { + /** + * The underlying filter. + */ + PreparedFilter *const filter; + +public: + PreparedAutoConvertFilter(PreparedFilter *_filter):filter(_filter) {} + ~PreparedAutoConvertFilter() { delete filter; } - virtual AudioFormat Open(AudioFormat &af, Error &error) override; - virtual void Close() override; - virtual ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + Filter *Open(AudioFormat &af) override; }; -AudioFormat -AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error) +Filter * +PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format) { assert(in_audio_format.IsValid()); /* open the "real" filter */ AudioFormat child_audio_format = in_audio_format; - AudioFormat out_audio_format = filter->Open(child_audio_format, error); - if (!out_audio_format.IsDefined()) - return out_audio_format; + std::unique_ptr new_filter(filter->Open(child_audio_format)); /* need to convert? */ + std::unique_ptr convert; if (in_audio_format != child_audio_format) { /* yes - create a convert_filter */ - const config_param empty; - convert = filter_new(&convert_filter_plugin, empty, error); - if (convert == nullptr) { - filter->Close(); - return AudioFormat::Undefined(); - } - - AudioFormat audio_format2 = in_audio_format; - AudioFormat audio_format3 = - convert->Open(audio_format2, error); - if (!audio_format3.IsDefined()) { - delete convert; - filter->Close(); - return AudioFormat::Undefined(); - } - - assert(audio_format2 == in_audio_format); - - if (!convert_filter_set(convert, child_audio_format, error)) { - delete convert; - filter->Close(); - return AudioFormat::Undefined(); - } - } else - /* no */ - convert = nullptr; - - return out_audio_format; -} - -void -AutoConvertFilter::Close() -{ - if (convert != nullptr) { - convert->Close(); - delete convert; + convert.reset(convert_filter_new(in_audio_format, + child_audio_format)); } - filter->Close(); + return new AutoConvertFilter(std::move(new_filter), + std::move(convert)); } ConstBuffer -AutoConvertFilter::FilterPCM(ConstBuffer src, Error &error) +AutoConvertFilter::FilterPCM(ConstBuffer src) { - if (convert != nullptr) { - src = convert->FilterPCM(src, error); - if (src.IsNull()) - return nullptr; - } + if (convert != nullptr) + src = convert->FilterPCM(src); - return filter->FilterPCM(src, error); + return filter->FilterPCM(src); } -Filter * -autoconvert_filter_new(Filter *filter) +PreparedFilter * +autoconvert_filter_new(PreparedFilter *filter) { - return new AutoConvertFilter(filter); + return new PreparedAutoConvertFilter(filter); } diff -Nru mpd-0.19.21/src/filter/plugins/AutoConvertFilterPlugin.hxx mpd-0.20.9/src/filter/plugins/AutoConvertFilterPlugin.hxx --- mpd-0.19.21/src/filter/plugins/AutoConvertFilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/AutoConvertFilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ #ifndef MPD_AUTOCONVERT_FILTER_PLUGIN_HXX #define MPD_AUTOCONVERT_FILTER_PLUGIN_HXX -class Filter; +class PreparedFilter; /** * Creates a new "autoconvert" filter. When opened, it ensures that @@ -28,7 +28,7 @@ * requests a different format, it automatically creates a * convert_filter. */ -Filter * -autoconvert_filter_new(Filter *filter); +PreparedFilter * +autoconvert_filter_new(PreparedFilter *filter); #endif diff -Nru mpd-0.19.21/src/filter/plugins/ChainFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/ChainFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/ChainFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ChainFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,11 @@ #include "filter/FilterInternal.hxx" #include "filter/FilterRegistry.hxx" #include "AudioFormat.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include "util/ConstBuffer.hxx" +#include "util/StringBuffer.hxx" +#include "util/RuntimeError.hxx" +#include #include #include @@ -49,132 +50,123 @@ std::list children; public: + explicit ChainFilter(AudioFormat _audio_format) + :Filter(_audio_format) {} + void Append(const char *name, Filter *filter) { + assert(out_audio_format.IsValid()); + out_audio_format = filter->GetOutAudioFormat(); + assert(out_audio_format.IsValid()); + children.emplace_back(name, filter); } /* virtual methods from class Filter */ - AudioFormat Open(AudioFormat &af, Error &error) override; - void Close() override; - ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; - -private: - /** - * Close all filters in the chain until #until is reached. - * #until itself is not closed. - */ - void CloseUntil(const Filter *until); + void Reset() override; + ConstBuffer FilterPCM(ConstBuffer src) override; }; -static constexpr Domain chain_filter_domain("chain_filter"); +class PreparedChainFilter final : public PreparedFilter { + struct Child { + const char *name; + PreparedFilter *filter; -static Filter * -chain_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) -{ - return new ChainFilter(); -} + Child(const char *_name, PreparedFilter *_filter) + :name(_name), filter(_filter) {} + ~Child() { + delete filter; + } -void -ChainFilter::CloseUntil(const Filter *until) -{ - for (auto &child : children) { - if (child.filter == until) - /* don't close this filter */ - return; + Child(const Child &) = delete; + Child &operator=(const Child &) = delete; - /* close this filter */ - child.filter->Close(); + Filter *Open(const AudioFormat &prev_audio_format); + }; + + std::list children; + +public: + void Append(const char *name, PreparedFilter *filter) { + children.emplace_back(name, filter); } - /* this assertion fails if #until does not exist (anymore) */ - assert(false); - gcc_unreachable(); + /* virtual methods from class PreparedFilter */ + Filter *Open(AudioFormat &af) override; +}; + +static PreparedFilter * +chain_filter_init(gcc_unused const ConfigBlock &block) +{ + return new PreparedChainFilter(); } -static AudioFormat -chain_open_child(const char *name, Filter *filter, - const AudioFormat &prev_audio_format, - Error &error) +Filter * +PreparedChainFilter::Child::Open(const AudioFormat &prev_audio_format) { AudioFormat conv_audio_format = prev_audio_format; - const AudioFormat next_audio_format = - filter->Open(conv_audio_format, error); - if (!next_audio_format.IsDefined()) - return next_audio_format; + Filter *new_filter = filter->Open(conv_audio_format); if (conv_audio_format != prev_audio_format) { - struct audio_format_string s; - - filter->Close(); + delete new_filter; - error.Format(chain_filter_domain, - "Audio format not supported by filter '%s': %s", - name, - audio_format_to_string(prev_audio_format, &s)); - return AudioFormat::Undefined(); + throw FormatRuntimeError("Audio format not supported by filter '%s': %s", + name, + ToString(prev_audio_format).c_str()); } - return next_audio_format; + return new_filter; } -AudioFormat -ChainFilter::Open(AudioFormat &in_audio_format, Error &error) +Filter * +PreparedChainFilter::Open(AudioFormat &in_audio_format) { - AudioFormat audio_format = in_audio_format; + std::unique_ptr chain(new ChainFilter(in_audio_format)); for (auto &child : children) { - audio_format = chain_open_child(child.name, child.filter, - audio_format, error); - if (!audio_format.IsDefined()) { - /* rollback, close all children */ - CloseUntil(child.filter); - break; - } + AudioFormat audio_format = chain->GetOutAudioFormat(); + auto *filter = child.Open(audio_format); + chain->Append(child.name, filter); } - /* return the output format of the last filter */ - return audio_format; + return chain.release(); } void -ChainFilter::Close() +ChainFilter::Reset() { for (auto &child : children) - child.filter->Close(); + child.filter->Reset(); } ConstBuffer -ChainFilter::FilterPCM(ConstBuffer src, Error &error) +ChainFilter::FilterPCM(ConstBuffer src) { for (auto &child : children) { /* feed the output of the previous filter as input into the current one */ - src = child.filter->FilterPCM(src, error); - if (src.IsNull()) - return nullptr; + src = child.filter->FilterPCM(src); } /* return the output of the last filter */ return src; } -const struct filter_plugin chain_filter_plugin = { +const FilterPlugin chain_filter_plugin = { "chain", chain_filter_init, }; -Filter * +PreparedFilter * filter_chain_new(void) { - return new ChainFilter(); + return new PreparedChainFilter(); } void -filter_chain_append(Filter &_chain, const char *name, Filter *filter) +filter_chain_append(PreparedFilter &_chain, const char *name, + PreparedFilter *filter) { - ChainFilter &chain = (ChainFilter &)_chain; + PreparedChainFilter &chain = (PreparedChainFilter &)_chain; chain.Append(name, filter); } diff -Nru mpd-0.19.21/src/filter/plugins/ChainFilterPlugin.hxx mpd-0.20.9/src/filter/plugins/ChainFilterPlugin.hxx --- mpd-0.19.21/src/filter/plugins/ChainFilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ChainFilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,13 +27,13 @@ #ifndef MPD_FILTER_CHAIN_HXX #define MPD_FILTER_CHAIN_HXX -class Filter; +class PreparedFilter; /** * Creates a new filter chain. */ -Filter * -filter_chain_new(void); +PreparedFilter * +filter_chain_new(); /** * Appends a new filter at the end of the filter chain. You must call @@ -43,6 +43,7 @@ * @param filter the filter to be appended to #chain */ void -filter_chain_append(Filter &chain, const char *name, Filter *filter); +filter_chain_append(PreparedFilter &chain, const char *name, + PreparedFilter *filter); #endif diff -Nru mpd-0.19.21/src/filter/plugins/ConvertFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/ConvertFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/ConvertFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ConvertFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,6 +28,9 @@ #include "AudioFormat.hxx" #include "poison.h" +#include +#include + #include class ConvertFilter final : public Filter { @@ -38,108 +41,110 @@ AudioFormat in_audio_format; /** - * The output audio format; the consumer of this plugin - * expects PCM data in this format. - * - * If this is AudioFormat::Undefined(), then the #PcmConvert - * attribute is not open. This can mean that Set() has failed - * or that no conversion is necessary. + * This object is only "open" if #in_audio_format != + * #out_audio_format. */ - AudioFormat out_audio_format; - - Manual state; + PcmConvert state; public: - bool Set(const AudioFormat &_out_audio_format, Error &error); + ConvertFilter(const AudioFormat &audio_format); + ~ConvertFilter(); + + void Set(const AudioFormat &_out_audio_format); + + void Reset() override { + state.Reset(); + } - virtual AudioFormat Open(AudioFormat &af, Error &error) override; - virtual void Close() override; - virtual ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + ConstBuffer FilterPCM(ConstBuffer src) override; }; -static Filter * -convert_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) +class PreparedConvertFilter final : public PreparedFilter { +public: + Filter *Open(AudioFormat &af) override; +}; + +static PreparedFilter * +convert_filter_init(gcc_unused const ConfigBlock &block) { - return new ConvertFilter(); + return new PreparedConvertFilter(); } -bool -ConvertFilter::Set(const AudioFormat &_out_audio_format, Error &error) +void +ConvertFilter::Set(const AudioFormat &_out_audio_format) { assert(in_audio_format.IsValid()); assert(_out_audio_format.IsValid()); if (_out_audio_format == out_audio_format) /* no change */ - return true; + return; - if (out_audio_format.IsValid()) { - out_audio_format.Clear(); - state->Close(); + if (out_audio_format != in_audio_format) { + out_audio_format = in_audio_format; + state.Close(); } if (_out_audio_format == in_audio_format) /* optimized special case: no-op */ - return true; + return; - if (!state->Open(in_audio_format, _out_audio_format, error)) - return false; + state.Open(in_audio_format, _out_audio_format); out_audio_format = _out_audio_format; - return true; } -AudioFormat -ConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) +ConvertFilter::ConvertFilter(const AudioFormat &audio_format) + :Filter(audio_format), in_audio_format(audio_format) { - assert(audio_format.IsValid()); - - in_audio_format = audio_format; - out_audio_format.Clear(); +} - state.Construct(); +Filter * +PreparedConvertFilter::Open(AudioFormat &audio_format) +{ + assert(audio_format.IsValid()); - return in_audio_format; + return new ConvertFilter(audio_format); } -void -ConvertFilter::Close() +ConvertFilter::~ConvertFilter() { assert(in_audio_format.IsValid()); - if (out_audio_format.IsValid()) - state->Close(); - - state.Destruct(); - - poison_undefined(&in_audio_format, sizeof(in_audio_format)); - poison_undefined(&out_audio_format, sizeof(out_audio_format)); + if (out_audio_format != in_audio_format) + state.Close(); } ConstBuffer -ConvertFilter::FilterPCM(ConstBuffer src, Error &error) +ConvertFilter::FilterPCM(ConstBuffer src) { assert(in_audio_format.IsValid()); - if (!out_audio_format.IsValid()) + if (out_audio_format == in_audio_format) /* optimized special case: no-op */ return src; - return state->Convert(src, error); + return state.Convert(src); } -const struct filter_plugin convert_filter_plugin = { +const FilterPlugin convert_filter_plugin = { "convert", convert_filter_init, }; -bool -convert_filter_set(Filter *_filter, AudioFormat out_audio_format, - Error &error) +Filter * +convert_filter_new(const AudioFormat in_audio_format, + const AudioFormat out_audio_format) +{ + std::unique_ptr filter(new ConvertFilter(in_audio_format)); + filter->Set(out_audio_format); + return filter.release(); +} + +void +convert_filter_set(Filter *_filter, AudioFormat out_audio_format) { ConvertFilter *filter = (ConvertFilter *)_filter; - return filter->Set(out_audio_format, error); + filter->Set(out_audio_format); } diff -Nru mpd-0.19.21/src/filter/plugins/ConvertFilterPlugin.hxx mpd-0.20.9/src/filter/plugins/ConvertFilterPlugin.hxx --- mpd-0.19.21/src/filter/plugins/ConvertFilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ConvertFilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,17 +21,21 @@ #define MPD_CONVERT_FILTER_PLUGIN_HXX class Filter; -class Error; struct AudioFormat; +Filter * +convert_filter_new(AudioFormat in_audio_format, + AudioFormat out_audio_format); + /** * Sets the output audio format for the specified filter. You must * call this after the filter has been opened. Since this audio * format switch is a violation of the filter API, this filter must be * the last in a chain. + * + * Throws std::runtime_error on error. */ -bool -convert_filter_set(Filter *filter, AudioFormat out_audio_format, - Error &error); +void +convert_filter_set(Filter *filter, AudioFormat out_audio_format); #endif diff -Nru mpd-0.19.21/src/filter/plugins/NormalizeFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/NormalizeFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/NormalizeFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/NormalizeFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,44 +29,45 @@ #include class NormalizeFilter final : public Filter { - struct Compressor *compressor; + Compressor *const compressor; PcmBuffer buffer; public: + NormalizeFilter(const AudioFormat &audio_format) + :Filter(audio_format), compressor(Compressor_new(0)) { + } + + ~NormalizeFilter() { + Compressor_delete(compressor); + } + /* virtual methods from class Filter */ - AudioFormat Open(AudioFormat &af, Error &error) override; - void Close() override; - ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + ConstBuffer FilterPCM(ConstBuffer src) override; +}; + +class PreparedNormalizeFilter final : public PreparedFilter { +public: + /* virtual methods from class PreparedFilter */ + Filter *Open(AudioFormat &af) override; }; -static Filter * -normalize_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) +static PreparedFilter * +normalize_filter_init(gcc_unused const ConfigBlock &block) { - return new NormalizeFilter(); + return new PreparedNormalizeFilter(); } -AudioFormat -NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) +Filter * +PreparedNormalizeFilter::Open(AudioFormat &audio_format) { audio_format.format = SampleFormat::S16; - compressor = Compressor_new(0); - - return audio_format; -} - -void -NormalizeFilter::Close() -{ - buffer.Clear(); - Compressor_delete(compressor); + return new NormalizeFilter(audio_format); } ConstBuffer -NormalizeFilter::FilterPCM(ConstBuffer src, gcc_unused Error &error) +NormalizeFilter::FilterPCM(ConstBuffer src) { int16_t *dest = (int16_t *)buffer.Get(src.size); memcpy(dest, src.data, src.size); @@ -75,7 +76,7 @@ return { (const void *)dest, src.size }; } -const struct filter_plugin normalize_filter_plugin = { +const FilterPlugin normalize_filter_plugin = { "normalize", normalize_filter_init, }; diff -Nru mpd-0.19.21/src/filter/plugins/NullFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/NullFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/NullFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/NullFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,27 +34,27 @@ class NullFilter final : public Filter { public: - virtual AudioFormat Open(AudioFormat &af, - gcc_unused Error &error) override { - return af; - } - - virtual void Close() override {} + explicit NullFilter(const AudioFormat &af):Filter(af) {} - virtual ConstBuffer FilterPCM(ConstBuffer src, - gcc_unused Error &error) override { + virtual ConstBuffer FilterPCM(ConstBuffer src) override { return src; } }; -static Filter * -null_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) +class PreparedNullFilter final : public PreparedFilter { +public: + virtual Filter *Open(AudioFormat &af) override { + return new NullFilter(af); + } +}; + +static PreparedFilter * +null_filter_init(gcc_unused const ConfigBlock &block) { - return new NullFilter(); + return new PreparedNullFilter(); } -const struct filter_plugin null_filter_plugin = { +const FilterPlugin null_filter_plugin = { "null", null_filter_init, }; diff -Nru mpd-0.19.21/src/filter/plugins/ReplayGainFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/ReplayGainFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/ReplayGainFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ReplayGainFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,39 +19,38 @@ #include "config.h" #include "ReplayGainFilterPlugin.hxx" -#include "filter/FilterPlugin.hxx" #include "filter/FilterInternal.hxx" -#include "filter/FilterRegistry.hxx" #include "AudioFormat.hxx" #include "ReplayGainInfo.hxx" #include "ReplayGainConfig.hxx" #include "mixer/MixerControl.hxx" #include "pcm/Volume.hxx" -#include "pcm/PcmBuffer.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" +#include + #include -#include static constexpr Domain replay_gain_domain("replay_gain"); class ReplayGainFilter final : public Filter { + const ReplayGainConfig config; + /** * If set, then this hardware mixer is used for applying * replay gain, instead of the software volume library. */ - Mixer *mixer; + Mixer *const mixer; /** * The base volume level for scale=1.0, between 1 and 100 * (including). */ - unsigned base; + const unsigned base; - ReplayGainMode mode; + ReplayGainMode mode = ReplayGainMode::OFF; ReplayGainInfo info; @@ -70,25 +69,21 @@ PcmVolume pv; public: - ReplayGainFilter() - :mixer(nullptr), mode(REPLAY_GAIN_OFF) { + ReplayGainFilter(const ReplayGainConfig &_config, + const AudioFormat &audio_format, + Mixer *_mixer, unsigned _base) + :Filter(audio_format), + config(_config), + mixer(_mixer), base(_base) { info.Clear(); - } - void SetMixer(Mixer *_mixer, unsigned _base) { - assert(_mixer == nullptr || (_base > 0 && _base <= 100)); - - mixer = _mixer; - base = _base; - - Update(); + pv.Open(out_audio_format.format); } void SetInfo(const ReplayGainInfo *_info) { - if (_info != nullptr) { + if (_info != nullptr) info = *_info; - info.Complete(); - } else + else info.Clear(); Update(); @@ -100,8 +95,8 @@ return; FormatDebug(replay_gain_domain, - "replay gain mode has changed %d->%d\n", - mode, _mode); + "replay gain mode has changed %s->%s\n", + ToString(mode), ToString(_mode)); mode = _mode; Update(); @@ -113,21 +108,46 @@ void Update(); /* virtual methods from class Filter */ - AudioFormat Open(AudioFormat &af, Error &error) override; - void Close() override; - ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + ConstBuffer FilterPCM(ConstBuffer src) override; +}; + +class PreparedReplayGainFilter final : public PreparedFilter { + const ReplayGainConfig config; + + /** + * If set, then this hardware mixer is used for applying + * replay gain, instead of the software volume library. + */ + Mixer *mixer = nullptr; + + /** + * The base volume level for scale=1.0, between 1 and 100 + * (including). + */ + unsigned base; + +public: + explicit PreparedReplayGainFilter(const ReplayGainConfig _config) + :config(_config) {} + + void SetMixer(Mixer *_mixer, unsigned _base) { + assert(_mixer == nullptr || (_base > 0 && _base <= 100)); + + mixer = _mixer; + base = _base; + } + + /* virtual methods from class Filter */ + Filter *Open(AudioFormat &af) override; }; void ReplayGainFilter::Update() { unsigned volume = PCM_VOLUME_1; - if (mode != REPLAY_GAIN_OFF) { - const auto &tuple = info.tuples[mode]; - float scale = tuple.CalculateScale(replay_gain_preamp, - replay_gain_missing_preamp, - replay_gain_limit); + if (mode != ReplayGainMode::OFF) { + const auto &tuple = info.Get(mode); + float scale = tuple.CalculateScale(config); FormatDebug(replay_gain_domain, "scale=%f\n", (double)scale); @@ -141,69 +161,56 @@ if (_volume > 100) _volume = 100; - Error error; - if (!mixer_set_volume(mixer, _volume, error)) - LogError(error, "Failed to update hardware mixer"); + try { + mixer_set_volume(mixer, _volume); + } catch (const std::runtime_error &e) { + LogError(e, "Failed to update hardware mixer"); + } } else pv.SetVolume(volume); } -static Filter * -replay_gain_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) -{ - return new ReplayGainFilter(); -} - -AudioFormat -ReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error) +PreparedFilter * +NewReplayGainFilter(const ReplayGainConfig &config) { - if (!pv.Open(af.format, error)) - return AudioFormat::Undefined(); - - return af; + return new PreparedReplayGainFilter(config); } -void -ReplayGainFilter::Close() +Filter * +PreparedReplayGainFilter::Open(AudioFormat &af) { - pv.Close(); + return new ReplayGainFilter(config, af, mixer, base); } ConstBuffer -ReplayGainFilter::FilterPCM(ConstBuffer src, gcc_unused Error &error) +ReplayGainFilter::FilterPCM(ConstBuffer src) { return mixer != nullptr ? src : pv.Apply(src); } -const struct filter_plugin replay_gain_filter_plugin = { - "replay_gain", - replay_gain_filter_init, -}; - void -replay_gain_filter_set_mixer(Filter *_filter, Mixer *mixer, +replay_gain_filter_set_mixer(PreparedFilter &_filter, Mixer *mixer, unsigned base) { - ReplayGainFilter *filter = (ReplayGainFilter *)_filter; + auto &filter = (PreparedReplayGainFilter &)_filter; - filter->SetMixer(mixer, base); + filter.SetMixer(mixer, base); } void -replay_gain_filter_set_info(Filter *_filter, const ReplayGainInfo *info) +replay_gain_filter_set_info(Filter &_filter, const ReplayGainInfo *info) { - ReplayGainFilter *filter = (ReplayGainFilter *)_filter; + auto &filter = (ReplayGainFilter &)_filter; - filter->SetInfo(info); + filter.SetInfo(info); } void -replay_gain_filter_set_mode(Filter *_filter, ReplayGainMode mode) +replay_gain_filter_set_mode(Filter &_filter, ReplayGainMode mode) { - ReplayGainFilter *filter = (ReplayGainFilter *)_filter; + auto &filter = (ReplayGainFilter &)_filter; - filter->SetMode(mode); + filter.SetMode(mode); } diff -Nru mpd-0.19.21/src/filter/plugins/ReplayGainFilterPlugin.hxx mpd-0.20.9/src/filter/plugins/ReplayGainFilterPlugin.hxx --- mpd-0.19.21/src/filter/plugins/ReplayGainFilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/ReplayGainFilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,10 +20,16 @@ #ifndef MPD_REPLAY_GAIN_FILTER_PLUGIN_HXX #define MPD_REPLAY_GAIN_FILTER_PLUGIN_HXX -#include "ReplayGainInfo.hxx" +#include "ReplayGainMode.hxx" class Filter; +class PreparedFilter; class Mixer; +struct ReplayGainConfig; +struct ReplayGainInfo; + +PreparedFilter * +NewReplayGainFilter(const ReplayGainConfig &config); /** * Enables or disables the hardware mixer for applying replay gain. @@ -34,19 +40,19 @@ * (including). */ void -replay_gain_filter_set_mixer(Filter *_filter, Mixer *mixer, +replay_gain_filter_set_mixer(PreparedFilter &_filter, Mixer *mixer, unsigned base); /** - * Sets a new #replay_gain_info at the beginning of a new song. + * Sets a new #ReplayGainInfo at the beginning of a new song. * - * @param info the new #replay_gain_info value, or nullptr if no replay + * @param info the new #ReplayGainInfo value, or nullptr if no replay * gain data is available for the current song */ void -replay_gain_filter_set_info(Filter *filter, const ReplayGainInfo *info); +replay_gain_filter_set_info(Filter &filter, const ReplayGainInfo *info); void -replay_gain_filter_set_mode(Filter *filter, ReplayGainMode mode); +replay_gain_filter_set_mode(Filter &filter, ReplayGainMode mode); #endif diff -Nru mpd-0.19.21/src/filter/plugins/RouteFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/RouteFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/RouteFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/RouteFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ #include "config.h" #include "config/ConfigError.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "AudioFormat.hxx" #include "filter/FilterPlugin.hxx" #include "filter/FilterInternal.hxx" @@ -49,55 +49,36 @@ #include "pcm/PcmBuffer.hxx" #include "pcm/Silence.hxx" #include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/ConstBuffer.hxx" #include "util/WritableBuffer.hxx" #include +#include -#include #include #include #include class RouteFilter final : public Filter { /** - * The minimum number of channels we need for output - * to be able to perform all the copies the user has specified - */ - unsigned min_output_channels; - - /** - * The minimum number of input channels we need to - * copy all the data the user has requested. If fewer - * than this many are supplied by the input, undefined - * copy operations are given zeroed sources in stead. - */ - unsigned min_input_channels; - - /** * The set of copy operations to perform on each sample * The index is an output channel to use, the value is * a corresponding input channel from which to take the * data. A -1 means "no source" */ - int8_t sources[MAX_CHANNELS]; + const std::array sources; /** * The actual input format of our signal, once opened */ - AudioFormat input_format; - - /** - * The decided upon output format, once opened - */ - AudioFormat output_format; + const AudioFormat input_format; /** * The size, in bytes, of each multichannel frame in the * input buffer */ - size_t input_frame_size; + const size_t input_frame_size; /** * The size, in bytes, of each multichannel frame in the @@ -111,58 +92,78 @@ PcmBuffer output_buffer; public: + RouteFilter(const AudioFormat &audio_format, unsigned out_channels, + const std::array &_sources); + + /* virtual methods from class Filter */ + ConstBuffer FilterPCM(ConstBuffer src) override; +}; + +class PreparedRouteFilter final : public PreparedFilter { + /** + * The minimum number of channels we need for output + * to be able to perform all the copies the user has specified + */ + unsigned min_output_channels; + + /** + * The minimum number of input channels we need to + * copy all the data the user has requested. If fewer + * than this many are supplied by the input, undefined + * copy operations are given zeroed sources in stead. + */ + unsigned min_input_channels; + + /** + * The set of copy operations to perform on each sample + * The index is an output channel to use, the value is + * a corresponding input channel from which to take the + * data. A -1 means "no source" + */ + std::array sources; + +public: /** * Parse the "routes" section, a string on the form * a>b, c>d, e>f, ... * where a... are non-unique, non-negative integers * and input channel a gets copied to output channel b, etc. - * @param param the configuration block to read + * @param block the configuration block to read * @param filter a route_filter whose min_channels and sources[] to set - * @return true on success, false on error */ - bool Configure(const config_param ¶m, Error &error); + PreparedRouteFilter(const ConfigBlock &block); - /* virtual methods from class Filter */ - AudioFormat Open(AudioFormat &af, Error &error) override; - void Close() override; - ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + /* virtual methods from class PreparedFilter */ + Filter *Open(AudioFormat &af) override; }; -bool -RouteFilter::Configure(const config_param ¶m, Error &error) { - +PreparedRouteFilter::PreparedRouteFilter(const ConfigBlock &block) +{ /* TODO: * With a more clever way of marking "don't copy to output N", * This could easily be merged into a single loop with some * dynamic realloc() instead of one count run and one malloc(). */ - std::fill_n(sources, MAX_CHANNELS, -1); + sources.fill(-1); min_input_channels = 0; min_output_channels = 0; // A cowardly default, just passthrough stereo - const char *routes = param.GetBlockValue("routes", "0>0, 1>1"); + const char *routes = block.GetBlockValue("routes", "0>0, 1>1"); while (true) { routes = StripLeft(routes); char *endptr; const unsigned source = strtoul(routes, &endptr, 10); endptr = StripLeft(endptr); - if (endptr == routes || *endptr != '>') { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (endptr == routes || *endptr != '>') + throw std::runtime_error("Malformed 'routes' specification"); - if (source >= MAX_CHANNELS) { - error.Format(config_domain, - "Invalid source channel number: %u", - source); - return false; - } + if (source >= MAX_CHANNELS) + throw FormatRuntimeError("Invalid source channel number: %u", + source); if (source >= min_input_channels) min_input_channels = source + 1; @@ -171,18 +172,12 @@ unsigned dest = strtoul(routes, &endptr, 10); endptr = StripLeft(endptr); - if (endptr == routes) { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (endptr == routes) + throw std::runtime_error("Malformed 'routes' specification"); - if (dest >= MAX_CHANNELS) { - error.Format(config_domain, - "Invalid destination channel number: %u", - dest); - return false; - } + if (dest >= MAX_CHANNELS) + throw FormatRuntimeError("Invalid destination channel number: %u", + dest); if (dest >= min_output_channels) min_output_channels = dest + 1; @@ -194,56 +189,41 @@ if (*routes == 0) break; - if (*routes != ',') { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (*routes != ',') + throw std::runtime_error("Malformed 'routes' specification"); ++routes; } - - return true; } -static Filter * -route_filter_init(const config_param ¶m, Error &error) +static PreparedFilter * +route_filter_init(const ConfigBlock &block) { - RouteFilter *filter = new RouteFilter(); - if (!filter->Configure(param, error)) { - delete filter; - return nullptr; - } - - return filter; + return new PreparedRouteFilter(block); } -AudioFormat -RouteFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) +RouteFilter::RouteFilter(const AudioFormat &audio_format, + unsigned out_channels, + const std::array &_sources) + :Filter(audio_format), sources(_sources), input_format(audio_format), + input_frame_size(input_format.GetFrameSize()) { - // Copy the input format for later reference - input_format = audio_format; - input_frame_size = input_format.GetFrameSize(); - // Decide on an output format which has enough channels, // and is otherwise identical - output_format = audio_format; - output_format.channels = min_output_channels; + out_audio_format.channels = out_channels; // Precalculate this simple value, to speed up allocation later - output_frame_size = output_format.GetFrameSize(); - - return output_format; + output_frame_size = out_audio_format.GetFrameSize(); } -void -RouteFilter::Close() +Filter * +PreparedRouteFilter::Open(AudioFormat &audio_format) { - output_buffer.Clear(); + return new RouteFilter(audio_format, min_output_channels, sources); } ConstBuffer -RouteFilter::FilterPCM(ConstBuffer src, gcc_unused Error &error) +RouteFilter::FilterPCM(ConstBuffer src) { size_t number_of_frames = src.size / input_frame_size; @@ -263,7 +243,7 @@ for (unsigned int s=0; s= input_format.channels) { // No source for this destination output, @@ -292,7 +272,7 @@ return { result, result_size }; } -const struct filter_plugin route_filter_plugin = { +const FilterPlugin route_filter_plugin = { "route", route_filter_init, }; diff -Nru mpd-0.19.21/src/filter/plugins/VolumeFilterPlugin.cxx mpd-0.20.9/src/filter/plugins/VolumeFilterPlugin.cxx --- mpd-0.19.21/src/filter/plugins/VolumeFilterPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/VolumeFilterPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,15 +25,18 @@ #include "pcm/Volume.hxx" #include "AudioFormat.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" -#include -#include +#include class VolumeFilter final : public Filter { PcmVolume pv; public: + explicit VolumeFilter(const AudioFormat &audio_format) + :Filter(audio_format) { + pv.Open(out_audio_format.format); + } + unsigned GetVolume() const { return pv.GetVolume(); } @@ -43,41 +46,36 @@ } /* virtual methods from class Filter */ - AudioFormat Open(AudioFormat &af, Error &error) override; - void Close() override; - ConstBuffer FilterPCM(ConstBuffer src, - Error &error) override; + ConstBuffer FilterPCM(ConstBuffer src) override; }; -static Filter * -volume_filter_init(gcc_unused const config_param ¶m, - gcc_unused Error &error) -{ - return new VolumeFilter(); -} +class PreparedVolumeFilter final : public PreparedFilter { + PcmVolume pv; -AudioFormat -VolumeFilter::Open(AudioFormat &audio_format, Error &error) -{ - if (!pv.Open(audio_format.format, error)) - return AudioFormat::Undefined(); +public: + /* virtual methods from class Filter */ + Filter *Open(AudioFormat &af) override; +}; - return audio_format; +static PreparedFilter * +volume_filter_init(gcc_unused const ConfigBlock &block) +{ + return new PreparedVolumeFilter(); } -void -VolumeFilter::Close() +Filter * +PreparedVolumeFilter::Open(AudioFormat &audio_format) { - pv.Close(); + return new VolumeFilter(audio_format); } ConstBuffer -VolumeFilter::FilterPCM(ConstBuffer src, gcc_unused Error &error) +VolumeFilter::FilterPCM(ConstBuffer src) { return pv.Apply(src); } -const struct filter_plugin volume_filter_plugin = { +const FilterPlugin volume_filter_plugin = { "volume", volume_filter_init, }; diff -Nru mpd-0.19.21/src/filter/plugins/VolumeFilterPlugin.hxx mpd-0.20.9/src/filter/plugins/VolumeFilterPlugin.hxx --- mpd-0.19.21/src/filter/plugins/VolumeFilterPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/filter/plugins/VolumeFilterPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/fs/AllocatedPath.cxx mpd-0.20.9/src/fs/AllocatedPath.cxx --- mpd-0.19.21/src/fs/AllocatedPath.cxx 2016-08-23 07:52:14.000000000 +0000 +++ mpd-0.20.9/src/fs/AllocatedPath.cxx 2017-05-08 14:49:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,92 +21,58 @@ #include "AllocatedPath.hxx" #include "Domain.hxx" #include "Charset.hxx" -#include "util/Error.hxx" #include "Compiler.h" -#ifdef HAVE_GLIB -#include -#endif - -#include - -#ifdef HAVE_GLIB - -inline AllocatedPath::AllocatedPath(Donate, pointer _value) - :value(_value) { - g_free(_value); -} - -#endif +#include /* no inlining, please */ AllocatedPath::~AllocatedPath() {} AllocatedPath -AllocatedPath::FromUTF8(const char *path_utf8) +AllocatedPath::FromUTF8(const char *path_utf8) noexcept { -#ifdef HAVE_GLIB - char *path = ::PathFromUTF8(path_utf8); - if (path == nullptr) - return AllocatedPath::Null(); - - return AllocatedPath(Donate(), path); +#if defined(HAVE_FS_CHARSET) || defined(WIN32) + try { + return AllocatedPath(::PathFromUTF8(path_utf8)); + } catch (const std::runtime_error &) { + return nullptr; + } #else return FromFS(path_utf8); #endif } AllocatedPath -AllocatedPath::FromUTF8(const char *path_utf8, Error &error) +AllocatedPath::FromUTF8Throw(const char *path_utf8) { - AllocatedPath path = FromUTF8(path_utf8); - if (path.IsNull()) - error.Format(path_domain, - "Failed to convert to file system charset: %s", - path_utf8); - - return path; +#if defined(HAVE_FS_CHARSET) || defined(WIN32) + return AllocatedPath(::PathFromUTF8(path_utf8)); +#else + return FromFS(path_utf8); +#endif } AllocatedPath -AllocatedPath::GetDirectoryName() const +AllocatedPath::GetDirectoryName() const noexcept { return FromFS(PathTraitsFS::GetParent(c_str())); } std::string -AllocatedPath::ToUTF8() const -{ - return ::PathToUTF8(c_str()); -} - -const char * -AllocatedPath::RelativeFS(const char *other_fs) const +AllocatedPath::ToUTF8() const noexcept { - const size_t l = length(); - if (memcmp(data(), other_fs, l) != 0) - return nullptr; - - other_fs += l; - if (*other_fs != 0) { - if (!PathTraitsFS::IsSeparator(*other_fs)) - /* mismatch */ - return nullptr; - - /* skip remaining path separators */ - do { - ++other_fs; - } while (PathTraitsFS::IsSeparator(*other_fs)); + try { + return ::PathToUTF8(c_str()); + } catch (const std::runtime_error &) { + return std::string(); } - - return other_fs; } void -AllocatedPath::ChopSeparators() +AllocatedPath::ChopSeparators() noexcept { size_t l = length(); - const char *p = data(); + const auto *p = data(); while (l >= 2 && PathTraitsFS::IsSeparator(p[l - 1])) { --l; diff -Nru mpd-0.19.21/src/fs/AllocatedPath.hxx mpd-0.20.9/src/fs/AllocatedPath.hxx --- mpd-0.19.21/src/fs/AllocatedPath.hxx 2016-07-29 12:52:00.000000000 +0000 +++ mpd-0.20.9/src/fs/AllocatedPath.hxx 2017-06-03 19:49:25.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,11 +25,10 @@ #include "Traits.hxx" #include "Path.hxx" +#include #include #include -class Error; - /** * A path name in the native file system character set. * @@ -39,24 +38,21 @@ class AllocatedPath { typedef PathTraitsFS::string string; typedef PathTraitsFS::value_type value_type; - typedef PathTraitsFS::pointer pointer; - typedef PathTraitsFS::const_pointer const_pointer; + typedef PathTraitsFS::pointer_type pointer_type; + typedef PathTraitsFS::const_pointer_type const_pointer_type; string value; - struct Donate {}; + AllocatedPath(std::nullptr_t):value() {} + explicit AllocatedPath(const_pointer_type _value):value(_value) {} - /** - * Donate the allocated pointer to a new #AllocatedPath object. - */ - AllocatedPath(Donate, pointer _value); - - AllocatedPath(const_pointer _value):value(_value) {} + AllocatedPath(const_pointer_type _begin, const_pointer_type _end) + :value(_begin, _end) {} AllocatedPath(string &&_value):value(std::move(_value)) {} - static AllocatedPath Build(const_pointer a, size_t a_size, - const_pointer b, size_t b_size) { + static AllocatedPath Build(const_pointer_type a, size_t a_size, + const_pointer_type b, size_t b_size) { return AllocatedPath(PathTraitsFS::Build(a, a_size, b, b_size)); } public: @@ -81,12 +77,12 @@ * @see IsNull() */ gcc_const - static AllocatedPath Null() { - return AllocatedPath(""); + static AllocatedPath Null() noexcept { + return AllocatedPath(nullptr); } gcc_pure - operator Path() const { + operator Path() const noexcept { return Path::FromFS(c_str()); } @@ -94,36 +90,39 @@ * Join two path components with the path separator. */ gcc_pure gcc_nonnull_all - static AllocatedPath Build(const_pointer a, const_pointer b) { + static AllocatedPath Build(const_pointer_type a, + const_pointer_type b) noexcept { return Build(a, PathTraitsFS::GetLength(a), b, PathTraitsFS::GetLength(b)); } gcc_pure gcc_nonnull_all - static AllocatedPath Build(Path a, const_pointer b) { + static AllocatedPath Build(Path a, const_pointer_type b) noexcept { return Build(a.c_str(), b); } gcc_pure gcc_nonnull_all - static AllocatedPath Build(Path a, Path b) { + static AllocatedPath Build(Path a, Path b) noexcept { return Build(a, b.c_str()); } gcc_pure gcc_nonnull_all - static AllocatedPath Build(const_pointer a, const AllocatedPath &b) { + static AllocatedPath Build(const_pointer_type a, + const AllocatedPath &b) noexcept { return Build(a, PathTraitsFS::GetLength(a), b.value.c_str(), b.value.size()); } gcc_pure gcc_nonnull_all - static AllocatedPath Build(const AllocatedPath &a, const_pointer b) { + static AllocatedPath Build(const AllocatedPath &a, + const_pointer_type b) noexcept { return Build(a.value.c_str(), a.value.size(), b, PathTraitsFS::GetLength(b)); } gcc_pure static AllocatedPath Build(const AllocatedPath &a, - const AllocatedPath &b) { + const AllocatedPath &b) noexcept { return Build(a.value.c_str(), a.value.size(), b.value.c_str(), b.value.size()); } @@ -133,16 +132,22 @@ * character set to a #Path instance. */ gcc_pure - static AllocatedPath FromFS(const_pointer fs) { + static AllocatedPath FromFS(const_pointer_type fs) noexcept { return AllocatedPath(fs); } + gcc_pure + static AllocatedPath FromFS(const_pointer_type _begin, + const_pointer_type _end) noexcept { + return AllocatedPath(_begin, _end); + } + /** * Convert a C++ string that is already in the filesystem * character set to a #Path instance. */ gcc_pure - static AllocatedPath FromFS(string &&fs) { + static AllocatedPath FromFS(string &&fs) noexcept { return AllocatedPath(std::move(fs)); } @@ -151,10 +156,14 @@ * Returns return a "nulled" instance on error. */ gcc_pure gcc_nonnull_all - static AllocatedPath FromUTF8(const char *path_utf8); + static AllocatedPath FromUTF8(const char *path_utf8) noexcept; - gcc_pure gcc_nonnull_all - static AllocatedPath FromUTF8(const char *path_utf8, Error &error); + /** + * Convert a UTF-8 C string to an #AllocatedPath instance. + * Throws a std::runtime_error on error. + */ + gcc_nonnull_all + static AllocatedPath FromUTF8Throw(const char *path_utf8); /** * Copy an #AllocatedPath object. @@ -169,11 +178,21 @@ return *this; } + gcc_pure + bool operator==(const AllocatedPath &other) const noexcept { + return value == other.value; + } + + gcc_pure + bool operator!=(const AllocatedPath &other) const noexcept { + return value != other.value; + } + /** * Allows the caller to "steal" the internal value by * providing a rvalue reference to the std::string attribute. */ - std::string &&Steal() { + string &&Steal() { return std::move(value); } @@ -181,7 +200,7 @@ * Check if this is a "nulled" instance. A "nulled" instance * must not be used. */ - bool IsNull() const { + bool IsNull() const noexcept { return value.empty(); } @@ -190,7 +209,7 @@ * * @see IsNull() */ - void SetNull() { + void SetNull() noexcept { value.clear(); } @@ -199,7 +218,7 @@ * elements (which may not be the number of characters). */ gcc_pure - size_t length() const { + size_t length() const noexcept { return value.length(); } @@ -209,7 +228,7 @@ * instance ends. */ gcc_pure - const_pointer c_str() const { + const_pointer_type c_str() const noexcept { return value.c_str(); } @@ -218,7 +237,7 @@ * null-terminated. */ gcc_pure - const_pointer data() const { + const_pointer_type data() const noexcept { return value.data(); } @@ -228,14 +247,14 @@ * (#IsNull returns true). */ gcc_pure - std::string ToUTF8() const; + std::string ToUTF8() const noexcept; /** * Gets directory name of this path. * Returns a "nulled" instance on error. */ gcc_pure - AllocatedPath GetDirectoryName() const; + AllocatedPath GetDirectoryName() const noexcept; /** * Determine the relative part of the given path to this @@ -244,15 +263,17 @@ * nullptr on mismatch. */ gcc_pure - const char *RelativeFS(const char *other_fs) const; + const_pointer_type Relative(Path other_fs) const noexcept { + return PathTraitsFS::Relative(c_str(), other_fs.c_str()); + } /** * Chop trailing directory separators. */ - void ChopSeparators(); + void ChopSeparators() noexcept; gcc_pure - bool IsAbsolute() const { + bool IsAbsolute() const noexcept { return PathTraitsFS::IsAbsolute(c_str()); } }; diff -Nru mpd-0.19.21/src/fs/Charset.cxx mpd-0.20.9/src/fs/Charset.cxx --- mpd-0.19.21/src/fs/Charset.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Charset.cxx 2017-05-08 14:47:45.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,56 +20,35 @@ #include "config.h" #include "Charset.hxx" #include "Domain.hxx" -#include "Limits.hxx" -#include "system/FatalError.hxx" #include "Log.hxx" -#include "Traits.hxx" +#include "lib/icu/Converter.hxx" +#include "util/AllocatedString.hxx" -#ifdef HAVE_GLIB -#include +#ifdef WIN32 +#include "lib/icu/Win32.hxx" +#include #endif #include +#include #include #include -#ifdef HAVE_GLIB - -/** - * Maximal number of bytes required to represent path name in UTF-8 - * (including nul-terminator). - * This value is a rought estimate of upper bound. - * It's based on path name limit in bytes (MPD_PATH_MAX) - * and assumption that some weird encoding could represent some UTF-8 4 byte - * sequences with single byte. - */ -static constexpr size_t MPD_PATH_MAX_UTF8 = (MPD_PATH_MAX - 1) * 4 + 1; +#ifdef HAVE_FS_CHARSET static std::string fs_charset; -gcc_pure -static bool -IsSupportedCharset(const char *charset) -{ - /* convert a space to check if the charset is valid */ - char *test = g_convert(" ", 1, charset, "UTF-8", nullptr, nullptr, nullptr); - if (test == nullptr) - return false; - - g_free(test); - return true; -} +static IcuConverter *fs_converter; void SetFSCharset(const char *charset) { assert(charset != nullptr); + assert(fs_converter == nullptr); - if (!IsSupportedCharset(charset)) - FormatFatalError("invalid filesystem charset: %s", charset); - - fs_charset = charset; + fs_converter = IcuConverter::Create(charset); + assert(fs_converter != nullptr); FormatDebug(path_domain, "SetFSCharset: fs charset is: %s", fs_charset.c_str()); @@ -77,87 +56,86 @@ #endif +void +DeinitFSCharset() noexcept +{ +#ifdef HAVE_ICU_CONVERTER + delete fs_converter; + fs_converter = nullptr; +#endif +} + const char * -GetFSCharset() +GetFSCharset() noexcept { -#ifdef HAVE_GLIB +#ifdef HAVE_FS_CHARSET return fs_charset.empty() ? "UTF-8" : fs_charset.c_str(); +#elif defined(WIN32) + return "ACP"; #else return "UTF-8"; #endif } -static inline void FixSeparators(std::string &s) +static inline PathTraitsUTF8::string && +FixSeparators(PathTraitsUTF8::string &&s) { -#ifdef WIN32 // For whatever reason GCC can't convert constexpr to value reference. // This leads to link errors when passing separators directly. - auto from = PathTraitsFS::SEPARATOR; auto to = PathTraitsUTF8::SEPARATOR; - std::replace(s.begin(), s.end(), from, to); -#else - (void)s; -#endif + decltype(to) from = PathTraitsFS::SEPARATOR; + + if (from != to) + /* convert backslash to slash on WIN32 */ + std::replace(s.begin(), s.end(), from, to); + + return std::move(s); } -std::string -PathToUTF8(const char *path_fs) +PathTraitsUTF8::string +PathToUTF8(PathTraitsFS::const_pointer_type path_fs) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(path_fs != nullptr); #endif -#ifdef HAVE_GLIB - if (fs_charset.empty()) { +#ifdef WIN32 + const auto buffer = WideCharToMultiByte(CP_UTF8, path_fs); + return FixSeparators(PathTraitsUTF8::string(buffer.c_str())); +#else +#ifdef HAVE_FS_CHARSET + if (fs_converter == nullptr) #endif - auto result = std::string(path_fs); - FixSeparators(result); - return result; -#ifdef HAVE_GLIB - } - - GIConv conv = g_iconv_open("utf-8", fs_charset.c_str()); - if (conv == reinterpret_cast(-1)) - return std::string(); - - // g_iconv() does not need nul-terminator, - // std::string could be created without it too. - char path_utf8[MPD_PATH_MAX_UTF8 - 1]; - char *in = const_cast(path_fs); - char *out = path_utf8; - size_t in_left = strlen(path_fs); - size_t out_left = sizeof(path_utf8); - - size_t ret = g_iconv(conv, &in, &in_left, &out, &out_left); + return FixSeparators(path_fs); +#ifdef HAVE_FS_CHARSET - g_iconv_close(conv); - - if (ret == static_cast(-1) || in_left > 0) - return std::string(); - - auto result_path = std::string(path_utf8, sizeof(path_utf8) - out_left); - FixSeparators(result_path); - return result_path; + const auto buffer = fs_converter->ToUTF8(path_fs); + return FixSeparators(PathTraitsUTF8::string(buffer.c_str())); +#endif #endif } -#ifdef HAVE_GLIB +#if defined(HAVE_FS_CHARSET) || defined(WIN32) -char * -PathFromUTF8(const char *path_utf8) +PathTraitsFS::string +PathFromUTF8(PathTraitsUTF8::const_pointer_type path_utf8) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(path_utf8 != nullptr); #endif - if (fs_charset.empty()) - return g_strdup(path_utf8); +#ifdef WIN32 + const auto buffer = MultiByteToWideChar(CP_UTF8, path_utf8); + return PathTraitsFS::string(buffer.c_str()); +#else + if (fs_converter == nullptr) + return path_utf8; - return g_convert(path_utf8, -1, - fs_charset.c_str(), "utf-8", - nullptr, nullptr, nullptr); + const auto buffer = fs_converter->FromUTF8(path_utf8); + return PathTraitsFS::string(buffer.c_str()); +#endif } #endif diff -Nru mpd-0.19.21/src/fs/Charset.hxx mpd-0.20.9/src/fs/Charset.hxx --- mpd-0.19.21/src/fs/Charset.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Charset.hxx 2017-05-08 14:47:42.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,29 +22,44 @@ #include "check.h" #include "Compiler.h" +#include "Traits.hxx" -#include +#if (defined(HAVE_ICU) || defined(HAVE_ICONV)) && !defined(WIN32) +#define HAVE_FS_CHARSET +#endif /** * Gets file system character set name. */ gcc_const const char * -GetFSCharset(); +GetFSCharset() noexcept; +/** + * Throws std::runtime_error on error. + */ void SetFSCharset(const char *charset); +void +DeinitFSCharset() noexcept; + /** * Convert the path to UTF-8. - * Returns empty string on error. + * + * Throws std::runtime_error on error. + */ +gcc_nonnull_all +PathTraitsUTF8::string +PathToUTF8(PathTraitsFS::const_pointer_type path_fs); + +/** + * Convert the path from UTF-8. + * + * Throws std::runtime_error on error. */ -gcc_pure gcc_nonnull_all -std::string -PathToUTF8(const char *path_fs); - -gcc_malloc gcc_nonnull_all -char * -PathFromUTF8(const char *path_utf8); +gcc_nonnull_all +PathTraitsFS::string +PathFromUTF8(PathTraitsUTF8::const_pointer_type path_utf8); #endif diff -Nru mpd-0.19.21/src/fs/CheckFile.cxx mpd-0.20.9/src/fs/CheckFile.cxx --- mpd-0.19.21/src/fs/CheckFile.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/CheckFile.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,42 +21,47 @@ #include "CheckFile.hxx" #include "Log.hxx" #include "config/ConfigError.hxx" -#include "FileSystem.hxx" +#include "FileInfo.hxx" #include "Path.hxx" #include "AllocatedPath.hxx" #include "DirectoryReader.hxx" +#include "system/Error.hxx" #include -#include void CheckDirectoryReadable(Path path_fs) -{ - struct stat st; - if (!StatFile(path_fs, st)) { - FormatErrno(config_domain, - "Failed to stat directory \"%s\"", - path_fs.c_str()); - return; - } +try { + const auto path_utf8 = path_fs.ToUTF8(); - if (!S_ISDIR(st.st_mode)) { + const FileInfo fi(path_fs); + if (!fi.IsDirectory()) { FormatError(config_domain, - "Not a directory: %s", path_fs.c_str()); + "Not a directory: %s", path_utf8.c_str()); return; } #ifndef WIN32 - const auto x = AllocatedPath::Build(path_fs, "."); - if (!StatFile(x, st) && errno == EACCES) - FormatError(config_domain, - "No permission to traverse (\"execute\") directory: %s", - path_fs.c_str()); + try { + const auto x = AllocatedPath::Build(path_fs, + PathTraitsFS::CURRENT_DIRECTORY); + const FileInfo fi2(x); + } catch (const std::system_error &e) { + if (IsAccessDenied(e)) + FormatError(config_domain, + "No permission to traverse (\"execute\") directory: %s", + path_utf8.c_str()); + } #endif - const DirectoryReader reader(path_fs); - if (reader.HasFailed() && errno == EACCES) - FormatError(config_domain, - "No permission to read directory: %s", path_fs.c_str()); - + try { + const DirectoryReader reader(path_fs); + } catch (const std::system_error &e) { + if (IsAccessDenied(e)) + FormatError(config_domain, + "No permission to read directory: %s", + path_fs.ToUTF8().c_str()); + } +} catch (const std::runtime_error &e) { + LogError(e); } diff -Nru mpd-0.19.21/src/fs/CheckFile.hxx mpd-0.20.9/src/fs/CheckFile.hxx --- mpd-0.19.21/src/fs/CheckFile.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/CheckFile.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/fs/Config.cxx mpd-0.20.9/src/fs/Config.cxx --- mpd-0.19.21/src/fs/Config.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Config.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,40 +22,20 @@ #include "Charset.hxx" #include "config/ConfigGlobal.hxx" -#ifdef WIN32 -#include // for GetACP() -#include // for sprintf() -#elif defined(HAVE_GLIB) -#include -#endif - void ConfigureFS() { -#if defined(HAVE_GLIB) || defined(WIN32) - const char *charset = nullptr; - - charset = config_get_string(CONF_FS_CHARSET, nullptr); - if (charset == nullptr) { -#ifndef WIN32 - const gchar **encodings; - g_get_filename_charsets(&encodings); - - if (encodings[0] != nullptr && *encodings[0] != '\0') - charset = encodings[0]; -#else - /* Glib claims that file system encoding is always utf-8 - * on native Win32 (i.e. not Cygwin). - * However this is true only if helpers are used. - * MPD uses regular functions. - * Those functions use encoding determined by GetACP(). */ - static char win_charset[13]; - sprintf(win_charset, "cp%u", GetACP()); - charset = win_charset; -#endif - } - +#ifdef HAVE_FS_CHARSET + const char *charset = config_get_string(ConfigOption::FS_CHARSET); if (charset != nullptr) SetFSCharset(charset); #endif } + +void +DeinitFS() +{ +#ifdef HAVE_FS_CHARSET + DeinitFSCharset(); +#endif +} diff -Nru mpd-0.19.21/src/fs/Config.hxx mpd-0.20.9/src/fs/Config.hxx --- mpd-0.19.21/src/fs/Config.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Config.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,8 +24,13 @@ /** * Performs global one-time initialization of this class. + * + * Throws std::runtime_error on error. */ void ConfigureFS(); +void +DeinitFS(); + #endif diff -Nru mpd-0.19.21/src/fs/DirectoryReader.cxx mpd-0.20.9/src/fs/DirectoryReader.cxx --- mpd-0.19.21/src/fs/DirectoryReader.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/fs/DirectoryReader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DirectoryReader.hxx" +#include "system/Error.hxx" + +#ifdef WIN32 + +DirectoryReader::DirectoryReader(Path dir) + :handle(FindFirstFile(MakeWildcardPath(dir.c_str()), &data)) +{ + if (handle == INVALID_HANDLE_VALUE) + throw FormatLastError("Failed to open %s", dir.c_str()); +} + +#else + +DirectoryReader::DirectoryReader(Path dir) + :dirp(opendir(dir.c_str())) +{ + if (dirp == nullptr) + throw FormatErrno("Failed to open %s", dir.c_str()); +} + +#endif diff -Nru mpd-0.19.21/src/fs/DirectoryReader.hxx mpd-0.20.9/src/fs/DirectoryReader.hxx --- mpd-0.19.21/src/fs/DirectoryReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/DirectoryReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,22 +23,48 @@ #include "check.h" #include "Path.hxx" -#include +#ifdef WIN32 + +#include +#include /** * Reader for directory entries. */ class DirectoryReader { - DIR *const dirp; - dirent *ent; + const HANDLE handle; + WIN32_FIND_DATA data; + bool first = true; + + class MakeWildcardPath { + PathTraitsFS::pointer_type path; + + public: + MakeWildcardPath(PathTraitsFS::const_pointer_type _path) { + auto l = _tcslen(_path); + path = new PathTraitsFS::value_type[l + 3]; + _tcscpy(path, _path); + path[l] = _T('\\'); + path[l + 1] = _T('*'); + path[l + 2] = 0; + } + + ~MakeWildcardPath() { + delete[] path; + } + + operator PathTraitsFS::const_pointer_type() const { + return path; + } + }; + public: /** * Creates new directory reader for the specified #dir. + * + * Throws std::system_error on error. */ - explicit DirectoryReader(Path dir) - : dirp(opendir(dir.c_str())), - ent(nullptr) { - } + explicit DirectoryReader(Path dir); DirectoryReader(const DirectoryReader &other) = delete; DirectoryReader &operator=(const DirectoryReader &other) = delete; @@ -47,22 +73,62 @@ * Destroys this instance. */ ~DirectoryReader() { - if (!HasFailed()) - closedir(dirp); + FindClose(handle); + } + + /** + * Reads next directory entry. + */ + bool ReadEntry() { + if (first) { + first = false; + return true; + } + + return FindNextFile(handle, &data) != 0; + } + + /** + * Extracts directory entry that was previously read by #ReadEntry. + */ + Path GetEntry() const { + return Path::FromFS(data.cFileName); } +}; + +#else + +#include + +/** + * Reader for directory entries. + */ +class DirectoryReader { + DIR *const dirp; + dirent *ent = nullptr; + +public: + /** + * Creates new directory reader for the specified #dir. + * + * Throws std::system_error on error. + */ + explicit DirectoryReader(Path dir); + + DirectoryReader(const DirectoryReader &other) = delete; + DirectoryReader &operator=(const DirectoryReader &other) = delete; /** - * Checks if directory failed to open. + * Destroys this instance. */ - bool HasFailed() const { - return dirp == nullptr; + ~DirectoryReader() { + closedir(dirp); } /** * Checks if directory entry is available. */ bool HasEntry() const { - assert(!HasFailed()); return ent != nullptr; } @@ -70,7 +136,6 @@ * Reads next directory entry. */ bool ReadEntry() { - assert(!HasFailed()); ent = readdir(dirp); return HasEntry(); } @@ -85,3 +150,5 @@ }; #endif + +#endif diff -Nru mpd-0.19.21/src/fs/Domain.cxx mpd-0.20.9/src/fs/Domain.cxx --- mpd-0.19.21/src/fs/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/fs/Domain.hxx mpd-0.20.9/src/fs/Domain.hxx --- mpd-0.19.21/src/fs/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/fs/FileInfo.hxx mpd-0.20.9/src/fs/FileInfo.hxx --- mpd-0.19.21/src/fs/FileInfo.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/fs/FileInfo.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FS_FILE_INFO_HXX +#define MPD_FS_FILE_INFO_HXX + +#include "check.h" +#include "Path.hxx" +#include "system/Error.hxx" + +#include + +#ifdef WIN32 +#include +#else +#include +#endif + +#ifdef WIN32 + +static inline constexpr uint64_t +ConstructUint64(DWORD lo, DWORD hi) +{ + return uint64_t(lo) | (uint64_t(hi) << 32); +} + +static constexpr time_t +FileTimeToTimeT(FILETIME ft) +{ + return (ConstructUint64(ft.dwLowDateTime, ft.dwHighDateTime) + - 116444736000000000) / 10000000; +} + +#endif + +class FileInfo { + friend bool GetFileInfo(Path path, FileInfo &info, + bool follow_symlinks); + friend class FileReader; + +#ifdef WIN32 + WIN32_FILE_ATTRIBUTE_DATA data; +#else + struct stat st; +#endif + +public: + FileInfo() = default; + + FileInfo(Path path, bool follow_symlinks=true) { + if (!GetFileInfo(path, *this, follow_symlinks)) { +#ifdef WIN32 + throw FormatLastError("Failed to access %s", + path.ToUTF8().c_str()); +#else + throw FormatErrno("Failed to access %s", + path.ToUTF8().c_str()); +#endif + } + } + + bool IsRegular() const { +#ifdef WIN32 + return (data.dwFileAttributes & + (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE)) == 0; +#else + return S_ISREG(st.st_mode); +#endif + } + + bool IsDirectory() const { +#ifdef WIN32 + return data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; +#else + return S_ISDIR(st.st_mode); +#endif + } + + uint64_t GetSize() const { +#ifdef WIN32 + return ConstructUint64(data.nFileSizeLow, data.nFileSizeHigh); +#else + return st.st_size; +#endif + } + + time_t GetModificationTime() const { +#ifdef WIN32 + return FileTimeToTimeT(data.ftLastWriteTime); +#else + return st.st_mtime; +#endif + } + +#ifndef WIN32 + uid_t GetUid() const { + return st.st_uid; + } + + mode_t GetMode() const { + return st.st_mode; + } + + dev_t GetDevice() const { + return st.st_dev; + } + + ino_t GetInode() const { + return st.st_ino; + } +#endif +}; + +inline bool +GetFileInfo(Path path, FileInfo &info, bool follow_symlinks=true) +{ +#ifdef WIN32 + (void)follow_symlinks; + return GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, + &info.data); +#else + int ret = follow_symlinks + ? stat(path.c_str(), &info.st) + : lstat(path.c_str(), &info.st); + return ret == 0; +#endif +} + +#endif diff -Nru mpd-0.19.21/src/fs/FileSystem.cxx mpd-0.20.9/src/fs/FileSystem.cxx --- mpd-0.19.21/src/fs/FileSystem.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/FileSystem.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,8 +21,23 @@ #include "FileSystem.hxx" #include "AllocatedPath.hxx" #include "Limits.hxx" +#include "system/Error.hxx" #include +#include + +void +RenameFile(Path oldpath, Path newpath) +{ +#ifdef WIN32 + if (!MoveFileEx(oldpath.c_str(), newpath.c_str(), + MOVEFILE_REPLACE_EXISTING)) + throw MakeLastError("Failed to rename file"); +#else + if (rename(oldpath.c_str(), newpath.c_str()) < 0) + throw MakeErrno("Failed to rename file"); +#endif +} AllocatedPath ReadLink(Path path) @@ -44,3 +59,35 @@ return AllocatedPath::FromFS(buffer); #endif } + +void +TruncateFile(Path path) +{ +#ifdef WIN32 + HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, + TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, + nullptr); + if (h == INVALID_HANDLE_VALUE) + throw FormatLastError("Failed to truncate %s", path.c_str()); + + CloseHandle(h); +#else + int fd = open_cloexec(path.c_str(), O_WRONLY|O_TRUNC, 0); + if (fd < 0) + throw FormatErrno("Failed to truncate %s", path.c_str()); + + close(fd); +#endif +} + +void +RemoveFile(Path path) +{ +#ifdef WIN32 + if (!DeleteFile(path.c_str())) + throw FormatLastError("Failed to delete %s", path.c_str()); +#else + if (unlink(path.c_str()) < 0) + throw FormatErrno("Failed to delete %s", path.c_str()); +#endif +} diff -Nru mpd-0.19.21/src/fs/FileSystem.hxx mpd-0.20.9/src/fs/FileSystem.hxx --- mpd-0.19.21/src/fs/FileSystem.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/FileSystem.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,51 +26,28 @@ #include "Path.hxx" +#ifdef WIN32 +#include +#endif + #include #include #include -class AllocatedPath; -namespace FOpenMode { - /** - * Open mode for reading text files. - */ - constexpr PathTraitsFS::const_pointer ReadText = "r"; - - /** - * Open mode for reading binary files. - */ - constexpr PathTraitsFS::const_pointer ReadBinary = "rb"; - - /** - * Open mode for writing text files. - */ - constexpr PathTraitsFS::const_pointer WriteText = "w"; - - /** - * Open mode for writing binary files. - */ - constexpr PathTraitsFS::const_pointer WriteBinary = "wb"; - - /** - * Open mode for appending text files. - */ - constexpr PathTraitsFS::const_pointer AppendText = "a"; - - /** - * Open mode for appending binary files. - */ - constexpr PathTraitsFS::const_pointer AppendBinary = "ab"; -} +class AllocatedPath; /** * Wrapper for fopen() that uses #Path names. */ static inline FILE * -FOpen(Path file, PathTraitsFS::const_pointer mode) +FOpen(Path file, PathTraitsFS::const_pointer_type mode) { +#ifdef WIN32 + return _tfopen(file.c_str(), mode); +#else return fopen(file.c_str(), mode); +#endif } /** @@ -79,17 +56,22 @@ static inline int OpenFile(Path file, int flags, int mode) { +#ifdef WIN32 + return _topen(file.c_str(), flags, mode); +#else return open_cloexec(file.c_str(), flags, mode); +#endif } -/** +/* * Wrapper for rename() that uses #Path names. + * + * Throws std::system_error on error. */ -static inline bool -RenameFile(Path oldpath, Path newpath) -{ - return rename(oldpath.c_str(), newpath.c_str()) == 0; -} +void +RenameFile(Path oldpath, Path newpath); + +#ifndef WIN32 /** * Wrapper for stat() that uses #Path names. @@ -97,25 +79,27 @@ static inline bool StatFile(Path file, struct stat &buf, bool follow_symlinks = true) { -#ifdef WIN32 - (void)follow_symlinks; - return stat(file.c_str(), &buf) == 0; -#else int ret = follow_symlinks ? stat(file.c_str(), &buf) : lstat(file.c_str(), &buf); return ret == 0; -#endif } +#endif + /** - * Wrapper for unlink() that uses #Path names. + * Truncate a file that exists already. Throws std::system_error on + * error. */ -static inline bool -RemoveFile(Path file) -{ - return unlink(file.c_str()) == 0; -} +void +TruncateFile(Path path); + +/** + * Wrapper for unlink() that uses #Path names. Throws + * std::system_error on error. + */ +void +RemoveFile(Path path); /** * Wrapper for readlink() that uses #Path names. @@ -143,27 +127,21 @@ #endif /** - * Checks is specified path exists and accessible. - */ -static inline bool -CheckAccess(Path path) -{ -#ifdef WIN32 - struct stat buf; - return StatFile(path, buf); -#else - return CheckAccess(path, F_OK); -#endif -} - -/** * Checks if #Path exists and is a regular file. */ static inline bool FileExists(Path path, bool follow_symlinks = true) { +#ifdef WIN32 + (void)follow_symlinks; + + const auto a = GetFileAttributes(path.c_str()); + return a != INVALID_FILE_ATTRIBUTES && + (a & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE)) == 0; +#else struct stat buf; return StatFile(path, buf, follow_symlinks) && S_ISREG(buf.st_mode); +#endif } /** @@ -172,18 +150,28 @@ static inline bool DirectoryExists(Path path, bool follow_symlinks = true) { +#ifdef WIN32 + (void)follow_symlinks; + + const auto a = GetFileAttributes(path.c_str()); + return a != INVALID_FILE_ATTRIBUTES && (a & FILE_ATTRIBUTE_DIRECTORY); +#else struct stat buf; return StatFile(path, buf, follow_symlinks) && S_ISDIR(buf.st_mode); +#endif } /** * Checks if #Path exists. */ static inline bool -PathExists(Path path, bool follow_symlinks = true) +PathExists(Path path) { - struct stat buf; - return StatFile(path, buf, follow_symlinks); +#ifdef WIN32 + return GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES; +#else + return CheckAccess(path, F_OK); +#endif } #endif diff -Nru mpd-0.19.21/src/fs/Glob.hxx mpd-0.20.9/src/fs/Glob.hxx --- mpd-0.19.21/src/fs/Glob.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/fs/Glob.hxx 2017-06-03 20:01:34.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FS_GLOB_XX +#define MPD_FS_GLOB_XX + +#include "check.h" + +#ifdef HAVE_FNMATCH +#define HAVE_CLASS_GLOB +#include +#include +#elif defined(WIN32) +#define HAVE_CLASS_GLOB +#include +#include +#endif + +#ifdef HAVE_CLASS_GLOB +#include "Compiler.h" + +/** + * A pattern that matches file names. It may contain shell wildcards + * (asterisk and question mark). + */ +class Glob { +#if defined(HAVE_FNMATCH) || defined(WIN32) + std::string pattern; +#endif + +public: +#if defined(HAVE_FNMATCH) || defined(WIN32) + explicit Glob(const char *_pattern) + :pattern(_pattern) {} + + Glob(Glob &&other) + :pattern(std::move(other.pattern)) {} +#endif + + gcc_pure + bool Check(const char *name_fs) const noexcept { +#ifdef HAVE_FNMATCH + return fnmatch(pattern.c_str(), name_fs, 0) == 0; +#elif defined(WIN32) + return PathMatchSpecA(name_fs, pattern.c_str()); +#endif + } +}; + +#endif + +#endif diff -Nru mpd-0.19.21/src/fs/io/AutoGunzipReader.cxx mpd-0.20.9/src/fs/io/AutoGunzipReader.cxx --- mpd-0.19.21/src/fs/io/AutoGunzipReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/AutoGunzipReader.cxx 2017-05-08 14:52:29.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,6 @@ #include "config.h" #include "AutoGunzipReader.hxx" #include "GunzipReader.hxx" -#include "util/Error.hxx" AutoGunzipReader::~AutoGunzipReader() { @@ -29,42 +28,33 @@ gcc_pure static bool -IsGzip(const uint8_t data[4]) +IsGzip(const uint8_t data[4]) noexcept { return data[0] == 0x1f && data[1] == 0x8b && data[2] == 0x08 && (data[3] & 0xe0) == 0; } -inline bool -AutoGunzipReader::Detect(Error &error) +inline void +AutoGunzipReader::Detect() { - const uint8_t *data = (const uint8_t *)peek.Peek(4, error); + const uint8_t *data = (const uint8_t *)peek.Peek(4); if (data == nullptr) { - if (error.IsDefined()) - return false; - next = &peek; - return true; + return; } - if (IsGzip(data)) { - gunzip = new GunzipReader(peek, error); - if (!gunzip->IsDefined()) - return false; - - - next = gunzip; - } else + if (IsGzip(data)) + next = gunzip = new GunzipReader(peek); + else next = &peek; - - return true; } size_t -AutoGunzipReader::Read(void *data, size_t size, Error &error) +AutoGunzipReader::Read(void *data, size_t size) { - if (next == nullptr && !Detect(error)) - return false; + if (next == nullptr) + Detect(); - return next->Read(data, size, error); + assert(next != nullptr); + return next->Read(data, size); } diff -Nru mpd-0.19.21/src/fs/io/AutoGunzipReader.hxx mpd-0.20.9/src/fs/io/AutoGunzipReader.hxx --- mpd-0.19.21/src/fs/io/AutoGunzipReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/AutoGunzipReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,8 +24,6 @@ #include "PeekReader.hxx" #include "Compiler.h" -#include - class GunzipReader; /** @@ -33,20 +31,20 @@ * #GunzipReader. */ class AutoGunzipReader final : public Reader { - Reader *next; + Reader *next = nullptr; PeekReader peek; - GunzipReader *gunzip; + GunzipReader *gunzip = nullptr; public: - AutoGunzipReader(Reader &_next) - :next(nullptr), peek(_next), gunzip(nullptr) {} + explicit AutoGunzipReader(Reader &_next) + :peek(_next) {} ~AutoGunzipReader(); /* virtual methods from class Reader */ - virtual size_t Read(void *data, size_t size, Error &error) override; + virtual size_t Read(void *data, size_t size) override; private: - bool Detect(Error &error); + void Detect(); }; #endif diff -Nru mpd-0.19.21/src/fs/io/BufferedOutputStream.cxx mpd-0.20.9/src/fs/io/BufferedOutputStream.cxx --- mpd-0.19.21/src/fs/io/BufferedOutputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/BufferedOutputStream.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,8 +25,13 @@ #include #include +#ifdef _UNICODE +#include "system/Error.hxx" +#include +#endif + bool -BufferedOutputStream::AppendToBuffer(const void *data, size_t size) +BufferedOutputStream::AppendToBuffer(const void *data, size_t size) noexcept { auto r = buffer.Write(); if (r.size < size) @@ -37,41 +42,36 @@ return true; } -bool +void BufferedOutputStream::Write(const void *data, size_t size) { - if (gcc_unlikely(last_error.IsDefined())) - return false; - + /* try to append to the current buffer */ if (AppendToBuffer(data, size)) - return true; + return; - if (!Flush()) - return false; + /* not enough room in the buffer - flush it */ + Flush(); + /* see if there's now enough room */ if (AppendToBuffer(data, size)) - return true; + return; - return os.Write(data, size, last_error); + /* too large for the buffer: direct write */ + os.Write(data, size); } -bool +void BufferedOutputStream::Write(const char *p) { - return Write(p, strlen(p)); + Write(p, strlen(p)); } -bool +void BufferedOutputStream::Format(const char *fmt, ...) { - if (gcc_unlikely(last_error.IsDefined())) - return false; - auto r = buffer.Write(); if (r.IsEmpty()) { - if (!Flush()) - return false; - + Flush(); r = buffer.Write(); } @@ -85,8 +85,7 @@ /* buffer was not large enough; flush it and try again */ - if (!Flush()) - return false; + Flush(); r = buffer.Write(); @@ -107,37 +106,61 @@ } buffer.Append(size); - return true; } -bool -BufferedOutputStream::Flush() +#ifdef _UNICODE + +void +BufferedOutputStream::Write(const wchar_t *p) { - if (!Check()) - return false; + WriteWideToUTF8(p, wcslen(p)); +} - auto r = buffer.Read(); - if (r.IsEmpty()) - return true; +void +BufferedOutputStream::WriteWideToUTF8(const wchar_t *src, size_t src_length) +{ + if (src_length == 0) + return; + + auto r = buffer.Write(); + if (r.IsEmpty()) { + Flush(); + r = buffer.Write(); + } - bool success = os.Write(r.data, r.size, last_error); - if (gcc_likely(success)) - buffer.Consume(r.size); - return success; + int length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + r.data, r.size, nullptr, nullptr); + if (length <= 0) { + const auto error = GetLastError(); + if (error != ERROR_INSUFFICIENT_BUFFER) + throw MakeLastError(error, "UTF-8 conversion failed"); + + /* how much buffer do we need? */ + length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + nullptr, 0, nullptr, nullptr); + if (length <= 0) + throw MakeLastError(error, "UTF-8 conversion failed"); + + /* grow the buffer and try again */ + length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + buffer.Write(length), length, + nullptr, nullptr); + if (length <= 0) + throw MakeLastError(error, "UTF-8 conversion failed"); + } + + buffer.Append(length); } -bool -BufferedOutputStream::Flush(Error &error) -{ - if (!Check(error)) - return false; +#endif +void +BufferedOutputStream::Flush() +{ auto r = buffer.Read(); if (r.IsEmpty()) - return true; + return; - bool success = os.Write(r.data, r.size, error); - if (gcc_likely(success)) - buffer.Consume(r.size); - return success; + os.Write(r.data, r.size); + buffer.Consume(r.size); } diff -Nru mpd-0.19.21/src/fs/io/BufferedOutputStream.hxx mpd-0.20.9/src/fs/io/BufferedOutputStream.hxx --- mpd-0.19.21/src/fs/io/BufferedOutputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/BufferedOutputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,49 +23,60 @@ #include "check.h" #include "Compiler.h" #include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" #include +#ifdef _UNICODE +#include +#endif + class OutputStream; -class Error; +/** + * An #OutputStream wrapper that buffers its output to reduce the + * number of OutputStream::Write() calls. + * + * All wchar_t based strings are converted to UTF-8. + */ class BufferedOutputStream { OutputStream &os; DynamicFifoBuffer buffer; - Error last_error; - public: - BufferedOutputStream(OutputStream &_os) + explicit BufferedOutputStream(OutputStream &_os) :os(_os), buffer(32768) {} - bool Write(const void *data, size_t size); - bool Write(const char *p); - - gcc_printf(2,3) - bool Format(const char *fmt, ...); + void Write(const void *data, size_t size); - gcc_pure - bool Check() const { - return !last_error.IsDefined(); + void Write(const char &ch) { + Write(&ch, sizeof(ch)); } - bool Check(Error &error) const { - if (last_error.IsDefined()) { - error.Set(last_error); - return false; - } else - return true; + void Write(const char *p); + + gcc_printf(2,3) + void Format(const char *fmt, ...); + +#ifdef _UNICODE + void Write(const wchar_t &ch) { + WriteWideToUTF8(&ch, 1); } - bool Flush(); + void Write(const wchar_t *p); +#endif - bool Flush(Error &error); + /** + * Write buffer contents to the #OutputStream. + */ + void Flush(); private: - bool AppendToBuffer(const void *data, size_t size); + bool AppendToBuffer(const void *data, size_t size) noexcept; + +#ifdef _UNICODE + void WriteWideToUTF8(const wchar_t *p, size_t length); +#endif }; #endif diff -Nru mpd-0.19.21/src/fs/io/BufferedReader.cxx mpd-0.20.9/src/fs/io/BufferedReader.cxx --- mpd-0.19.21/src/fs/io/BufferedReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/BufferedReader.cxx 2017-06-04 10:29:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,12 +22,14 @@ #include "Reader.hxx" #include "util/TextFile.hxx" +#include + +#include +#include + bool BufferedReader::Fill(bool need_more) { - if (gcc_unlikely(last_error.IsDefined())) - return false; - if (eof) return !need_more; @@ -41,11 +43,8 @@ assert(!w.IsEmpty()); } - size_t nbytes = reader.Read(w.data, w.size, last_error); + size_t nbytes = reader.Read(w.data, w.size); if (nbytes == 0) { - if (gcc_unlikely(last_error.IsDefined())) - return false; - eof = true; return !need_more; } @@ -54,16 +53,58 @@ return true; } +void * +BufferedReader::ReadFull(size_t size) +{ + while (true) { + auto r = Read(); + if (r.size >= size) + return r.data; + + if (!Fill(true)) + throw std::runtime_error("Premature end of file"); + } +} + +size_t +BufferedReader::ReadFromBuffer(WritableBuffer dest) noexcept +{ + auto src = Read(); + size_t nbytes = std::min(src.size, dest.size); + memcpy(dest.data, src.data, nbytes); + Consume(nbytes); + return nbytes; +} + +void +BufferedReader::ReadFull(WritableBuffer _dest) +{ + auto dest = WritableBuffer::FromVoid(_dest); + assert(dest.size == _dest.size); + + while (true) { + size_t nbytes = ReadFromBuffer(dest.ToVoid()); + dest.skip_front(nbytes); + if (dest.size == 0) + break; + + if (!Fill(true)) + throw std::runtime_error("Premature end of file"); + } +} + char * BufferedReader::ReadLine() { do { char *line = ReadBufferedLine(buffer); - if (line != nullptr) + if (line != nullptr) { + ++line_number; return line; + } } while (Fill(true)); - if (last_error.IsDefined() || !eof || buffer.IsEmpty()) + if (!eof || buffer.IsEmpty()) return nullptr; auto w = buffer.Write(); @@ -78,5 +119,6 @@ char *line = buffer.Read().data; buffer.Clear(); + ++line_number; return line; } diff -Nru mpd-0.19.21/src/fs/io/BufferedReader.hxx mpd-0.20.9/src/fs/io/BufferedReader.hxx --- mpd-0.19.21/src/fs/io/BufferedReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/BufferedReader.hxx 2017-06-04 10:30:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,12 +23,10 @@ #include "check.h" #include "Compiler.h" #include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" #include class Reader; -class Error; class BufferedReader { static constexpr size_t MAX_SIZE = 512 * 1024; @@ -37,39 +35,60 @@ DynamicFifoBuffer buffer; - Error last_error; + bool eof = false; - bool eof; + unsigned line_number = 0; public: - BufferedReader(Reader &_reader) - :reader(_reader), buffer(4096), eof(false) {} + explicit BufferedReader(Reader &_reader) + :reader(_reader), buffer(4096) {} - gcc_pure - bool Check() const { - return !last_error.IsDefined(); - } - - bool Check(Error &error) const { - if (last_error.IsDefined()) { - error.Set(last_error); - return false; - } else - return true; + /** + * Reset the internal state. Should be called after rewinding + * the underlying #Reader. + */ + void Reset() noexcept { + buffer.Clear(); + eof = false; + line_number = 0; } bool Fill(bool need_more); gcc_pure - WritableBuffer Read() const { + WritableBuffer Read() const noexcept { return buffer.Read().ToVoid(); } - void Consume(size_t n) { + /** + * Read a buffer of exactly the given size (without consuming + * it). Throws std::runtime_error if not enough data is + * available. + */ + void *ReadFull(size_t size); + + void Consume(size_t n) noexcept { buffer.Consume(n); } + /** + * Read (and consume) data from the input buffer into the + * given buffer. Does not attempt to refill the buffer. + */ + size_t ReadFromBuffer(WritableBuffer dest) noexcept; + + /** + * Read data into the given buffer and consume it from our + * buffer. Throw an exception if the request cannot be + * forfilled. + */ + void ReadFull(WritableBuffer dest); + char *ReadLine(); + + unsigned GetLineNumber() const noexcept { + return line_number; + } }; #endif diff -Nru mpd-0.19.21/src/fs/io/FileOutputStream.cxx mpd-0.20.9/src/fs/io/FileOutputStream.cxx --- mpd-0.19.21/src/fs/io/FileOutputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/FileOutputStream.cxx 2017-05-08 14:48:25.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,51 +19,96 @@ #include "config.h" #include "FileOutputStream.hxx" -#include "fs/FileSystem.hxx" -#include "system/fd_util.h" -#include "util/Error.hxx" +#include "system/Error.hxx" + +FileOutputStream::FileOutputStream(Path _path, Mode _mode) + :path(_path), mode(_mode) +{ + switch (mode) { + case Mode::CREATE: + OpenCreate(false); + break; + + case Mode::CREATE_VISIBLE: + OpenCreate(true); + break; + + case Mode::APPEND_EXISTING: + OpenAppend(false); + break; + + case Mode::APPEND_OR_CREATE: + OpenAppend(true); + break; + } +} #ifdef WIN32 -FileOutputStream::FileOutputStream(Path _path, Error &error) - :path(_path), - handle(CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, - TRUNCATE_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, - nullptr)) +inline void +FileOutputStream::OpenCreate(gcc_unused bool visible) { - if (handle == INVALID_HANDLE_VALUE) - error.FormatLastError("Failed to create %s", path.c_str()); + handle = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, + nullptr); + if (!IsDefined()) + throw FormatLastError("Failed to create %s", + path.ToUTF8().c_str()); } -bool -FileOutputStream::Write(const void *data, size_t size, Error &error) +inline void +FileOutputStream::OpenAppend(bool create) { - assert(IsDefined()); - - DWORD nbytes; - if (!WriteFile(handle, data, size, &nbytes, nullptr)) { - error.FormatLastError("Failed to write to %s", path.c_str()); - return false; + handle = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, + create ? OPEN_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, + nullptr); + if (!IsDefined()) + throw FormatLastError("Failed to append to %s", + path.ToUTF8().c_str()); + + if (!SeekEOF()) { + auto code = GetLastError(); + Close(); + throw FormatLastError(code, "Failed seek end-of-file of %s", + path.ToUTF8().c_str()); } - if (size_t(nbytes) != size) { - error.FormatLastError(ERROR_DISK_FULL, - "Failed to write to %s", path.c_str()); - return false; - } +} + +uint64_t +FileOutputStream::Tell() const noexcept +{ + LONG high = 0; + DWORD low = SetFilePointer(handle, 0, &high, FILE_CURRENT); + if (low == 0xffffffff) + return 0; + + return uint64_t(high) << 32 | uint64_t(low); +} - return true; +void +FileOutputStream::Write(const void *data, size_t size) +{ + assert(IsDefined()); + + DWORD nbytes; + if (!WriteFile(handle, data, size, &nbytes, nullptr)) + throw FormatLastError("Failed to write to %s", + GetPath().c_str()); + + if (size_t(nbytes) != size) + throw FormatLastError(ERROR_DISK_FULL, "Failed to write to %s", + GetPath().c_str()); } -bool -FileOutputStream::Commit(gcc_unused Error &error) +void +FileOutputStream::Commit() { assert(IsDefined()); - CloseHandle(handle); - handle = INVALID_HANDLE_VALUE; - return true; + Close(); } void @@ -71,9 +116,9 @@ { assert(IsDefined()); - CloseHandle(handle); - handle = INVALID_HANDLE_VALUE; - RemoveFile(path); + Close(); + + DeleteFile(GetPath().c_str()); } #else @@ -82,45 +127,109 @@ #include #include -FileOutputStream::FileOutputStream(Path _path, Error &error) - :path(_path), - fd(open_cloexec(path.c_str(), - O_WRONLY|O_CREAT|O_TRUNC, - 0666)) +#ifdef HAVE_LINKAT +#ifndef O_TMPFILE +/* supported since Linux 3.11 */ +#define __O_TMPFILE 020000000 +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) +#include +#endif + +/** + * Open a file using Linux's O_TMPFILE for writing the given file. + */ +static bool +OpenTempFile(FileDescriptor &fd, Path path) { - if (fd < 0) - error.FormatErrno("Failed to create %s", path.c_str()); + const auto directory = path.GetDirectoryName(); + if (directory.IsNull()) + return false; + + return fd.Open(directory.c_str(), O_TMPFILE|O_WRONLY, 0666); } -bool -FileOutputStream::Write(const void *data, size_t size, Error &error) -{ - assert(IsDefined()); +#endif /* HAVE_LINKAT */ - ssize_t nbytes = write(fd, data, size); - if (nbytes < 0) { - error.FormatErrno("Failed to write to %s", path.c_str()); - return false; - } else if ((size_t)nbytes < size) { - error.FormatErrno(ENOSPC, - "Failed to write to %s", path.c_str()); - return false; +inline void +FileOutputStream::OpenCreate(bool visible) +{ +#ifdef HAVE_LINKAT + /* try Linux's O_TMPFILE first */ + is_tmpfile = !visible && OpenTempFile(fd, GetPath()); + if (!is_tmpfile) { +#endif + /* fall back to plain POSIX */ + if (!fd.Open(GetPath().c_str(), + O_WRONLY|O_CREAT|O_TRUNC, + 0666)) + throw FormatErrno("Failed to create %s", + GetPath().c_str()); +#ifdef HAVE_LINKAT } +#else + (void)visible; +#endif +} + +inline void +FileOutputStream::OpenAppend(bool create) +{ + int flags = O_WRONLY|O_APPEND; + if (create) + flags |= O_CREAT; + + if (!fd.Open(path.c_str(), flags)) + throw FormatErrno("Failed to append to %s", + path.c_str()); +} + +uint64_t +FileOutputStream::Tell() const noexcept +{ + return fd.Tell(); +} - return true; +void +FileOutputStream::Write(const void *data, size_t size) +{ + assert(IsDefined()); + + ssize_t nbytes = fd.Write(data, size); + if (nbytes < 0) + throw FormatErrno("Failed to write to %s", GetPath().c_str()); + else if ((size_t)nbytes < size) + throw FormatErrno(ENOSPC, "Failed to write to %s", + GetPath().c_str()); } -bool -FileOutputStream::Commit(Error &error) +void +FileOutputStream::Commit() { assert(IsDefined()); - bool success = close(fd) == 0; - fd = -1; - if (!success) - error.FormatErrno("Failed to commit %s", path.c_str()); +#ifdef HAVE_LINKAT + if (is_tmpfile) { + unlink(GetPath().c_str()); + + /* hard-link the temporary file to the final path */ + char fd_path[64]; + snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", + fd.Get()); + if (linkat(AT_FDCWD, fd_path, AT_FDCWD, path.c_str(), + AT_SYMLINK_FOLLOW) < 0) + throw FormatErrno("Failed to commit %s", + path.c_str()); + } +#endif - return success; + if (!Close()) { +#ifdef WIN32 + throw FormatLastError("Failed to commit %s", + path.ToUTF8().c_str()); +#else + throw FormatErrno("Failed to commit %s", path.c_str()); +#endif + } } void @@ -128,10 +237,22 @@ { assert(IsDefined()); - close(fd); - fd = -1; + Close(); - RemoveFile(path); + switch (mode) { + case Mode::CREATE: +#ifdef HAVE_LINKAT + if (!is_tmpfile) +#endif + unlink(GetPath().c_str()); + break; + + case Mode::CREATE_VISIBLE: + case Mode::APPEND_EXISTING: + case Mode::APPEND_OR_CREATE: + /* can't roll this back */ + break; + } } #endif diff -Nru mpd-0.19.21/src/fs/io/FileOutputStream.hxx mpd-0.20.9/src/fs/io/FileOutputStream.hxx --- mpd-0.19.21/src/fs/io/FileOutputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/FileOutputStream.hxx 2017-05-08 14:49:57.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,12 @@ #include "fs/AllocatedPath.hxx" #include "Compiler.h" +#ifndef WIN32 +#include "system/FileDescriptor.hxx" +#endif + #include +#include #ifdef WIN32 #include @@ -34,36 +39,106 @@ class Path; class FileOutputStream final : public OutputStream { - AllocatedPath path; + const AllocatedPath path; #ifdef WIN32 - HANDLE handle; + HANDLE handle = INVALID_HANDLE_VALUE; #else - int fd; + FileDescriptor fd = FileDescriptor::Undefined(); +#endif + +#ifdef HAVE_LINKAT + /** + * Was O_TMPFILE used? If yes, then linkat() must be used to + * create a link to this file. + */ + bool is_tmpfile = false; #endif public: - FileOutputStream(Path _path, Error &error); + enum class Mode : uint8_t { + /** + * Create a new file, or replace an existing file. + * File contents may not be visible until Commit() has + * been called. + */ + CREATE, + + /** + * Like #CREATE, but no attempt is made to hide file + * contents during the transaction (e.g. via O_TMPFILE + * or a hidden temporary file). + */ + CREATE_VISIBLE, + + /** + * Append to a file that already exists. If it does + * not, an exception is thrown. + */ + APPEND_EXISTING, + + /** + * Like #APPEND_EXISTING, but create the file if it + * does not exist. + */ + APPEND_OR_CREATE, + }; + +private: + Mode mode; + +public: + explicit FileOutputStream(Path _path, Mode _mode=Mode::CREATE); ~FileOutputStream() { if (IsDefined()) Cancel(); } +public: + Path GetPath() const { + return path; + } + + gcc_pure + uint64_t Tell() const noexcept; + + /* virtual methods from class OutputStream */ + void Write(const void *data, size_t size) override; + + void Commit(); + void Cancel(); + +private: + void OpenCreate(bool visible); + void OpenAppend(bool create); + + bool Close() { + assert(IsDefined()); - bool IsDefined() const { #ifdef WIN32 - return handle != INVALID_HANDLE_VALUE; + CloseHandle(handle); + handle = INVALID_HANDLE_VALUE; + return true; #else - return fd >= 0; + return fd.Close(); #endif } - bool Commit(Error &error); - void Cancel(); +#ifdef WIN32 + bool SeekEOF() { + return SetFilePointer(handle, 0, nullptr, + FILE_END) != 0xffffffff; + } +#endif - /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, Error &error) override; + bool IsDefined() const { +#ifdef WIN32 + return handle != INVALID_HANDLE_VALUE; +#else + return fd.IsDefined(); +#endif + } }; #endif diff -Nru mpd-0.19.21/src/fs/io/FileReader.cxx mpd-0.20.9/src/fs/io/FileReader.cxx --- mpd-0.19.21/src/fs/io/FileReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/FileReader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,36 +19,65 @@ #include "config.h" #include "FileReader.hxx" -#include "system/fd_util.h" -#include "util/Error.hxx" +#include "fs/FileInfo.hxx" +#include "system/Error.hxx" + +#include #ifdef WIN32 -FileReader::FileReader(Path _path, Error &error) +FileReader::FileReader(Path _path) :path(_path), handle(CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)) { if (handle == INVALID_HANDLE_VALUE) - error.FormatLastError("Failed to open %s", path.c_str()); + throw FormatLastError("Failed to open %s", path.ToUTF8().c_str()); +} + +FileInfo +FileReader::GetFileInfo() const +{ + assert(IsDefined()); + + return FileInfo(path); } size_t -FileReader::Read(void *data, size_t size, Error &error) +FileReader::Read(void *data, size_t size) { assert(IsDefined()); DWORD nbytes; - if (!ReadFile(handle, data, size, &nbytes, nullptr)) { - error.FormatLastError("Failed to read from %s", path.c_str()); - nbytes = 0; - } + if (!ReadFile(handle, data, size, &nbytes, nullptr)) + throw FormatLastError("Failed to read from %s", + path.ToUTF8().c_str()); return nbytes; } void +FileReader::Seek(off_t offset) +{ + assert(IsDefined()); + + auto result = SetFilePointer(handle, offset, nullptr, FILE_BEGIN); + if (result == INVALID_SET_FILE_POINTER) + throw MakeLastError("Failed to seek"); +} + +void +FileReader::Skip(off_t offset) +{ + assert(IsDefined()); + + auto result = SetFilePointer(handle, offset, nullptr, FILE_CURRENT); + if (result == INVALID_SET_FILE_POINTER) + throw MakeLastError("Failed to seek"); +} + +void FileReader::Close() { assert(IsDefined()); @@ -58,41 +87,68 @@ #else -#include -#include -#include +FileReader::FileReader(Path _path) + :path(_path) +{ + fd.OpenReadOnly(path.c_str()); + if (!fd.IsDefined()) + throw FormatErrno("Failed to open %s", path.ToUTF8().c_str()); +} -FileReader::FileReader(Path _path, Error &error) - :path(_path), - fd(open_cloexec(path.c_str(), - O_RDONLY, - 0)) +FileInfo +FileReader::GetFileInfo() const { - if (fd < 0) - error.FormatErrno("Failed to open %s", path.c_str()); + assert(IsDefined()); + + FileInfo info; + const bool success = fstat(fd.Get(), &info.st) == 0; + if (!success) + throw FormatErrno("Failed to access %s", + path.ToUTF8().c_str()); + + return info; } size_t -FileReader::Read(void *data, size_t size, Error &error) +FileReader::Read(void *data, size_t size) { assert(IsDefined()); - ssize_t nbytes = read(fd, data, size); - if (nbytes < 0) { - error.FormatErrno("Failed to read from %s", path.c_str()); - nbytes = 0; - } + ssize_t nbytes = fd.Read(data, size); + if (nbytes < 0) + throw FormatErrno("Failed to read from %s", path.ToUTF8().c_str()); return nbytes; } void +FileReader::Seek(off_t offset) +{ + assert(IsDefined()); + + auto result = fd.Seek(offset); + const bool success = result >= 0; + if (!success) + throw MakeErrno("Failed to seek"); +} + +void +FileReader::Skip(off_t offset) +{ + assert(IsDefined()); + + auto result = fd.Skip(offset); + const bool success = result >= 0; + if (!success) + throw MakeErrno("Failed to seek"); +} + +void FileReader::Close() { assert(IsDefined()); - close(fd); - fd = -1; + fd.Close(); } #endif diff -Nru mpd-0.19.21/src/fs/io/FileReader.hxx mpd-0.20.9/src/fs/io/FileReader.hxx --- mpd-0.19.21/src/fs/io/FileReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/FileReader.hxx 2017-05-08 14:42:36.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,13 +25,16 @@ #include "fs/AllocatedPath.hxx" #include "Compiler.h" -#include +#ifndef WIN32 +#include "system/FileDescriptor.hxx" +#endif #ifdef WIN32 #include #endif class Path; +class FileInfo; class FileReader final : public Reader { AllocatedPath path; @@ -39,11 +42,25 @@ #ifdef WIN32 HANDLE handle; #else - int fd; + FileDescriptor fd; #endif public: - FileReader(Path _path, Error &error); + explicit FileReader(Path _path); + +#ifdef WIN32 + FileReader(FileReader &&other) + :path(std::move(other.path)), + handle(other.handle) { + other.handle = INVALID_HANDLE_VALUE; + } +#else + FileReader(FileReader &&other) + :path(std::move(other.path)), + fd(other.fd) { + other.fd.SetUndefined(); + } +#endif ~FileReader() { if (IsDefined()) @@ -51,18 +68,61 @@ } +protected: bool IsDefined() const { #ifdef WIN32 return handle != INVALID_HANDLE_VALUE; #else - return fd >= 0; + return fd.IsDefined(); #endif } +public: +#ifndef WIN32 + FileDescriptor GetFD() const { + return fd; + } +#endif + void Close(); + FileInfo GetFileInfo() const; + + gcc_pure + uint64_t GetSize() const noexcept { +#ifdef WIN32 + LARGE_INTEGER size; + return GetFileSizeEx(handle, &size) + ? size.QuadPart + : 0; +#else + return fd.GetSize(); +#endif + } + + gcc_pure + uint64_t GetPosition() const noexcept { +#ifdef WIN32 + LARGE_INTEGER zero; + zero.QuadPart = 0; + LARGE_INTEGER position; + return SetFilePointerEx(handle, zero, &position, FILE_CURRENT) + ? position.QuadPart + : 0; +#else + return fd.Tell(); +#endif + } + + void Rewind() { + Seek(0); + } + + void Seek(off_t offset); + void Skip(off_t offset); + /* virtual methods from class Reader */ - size_t Read(void *data, size_t size, Error &error) override; + size_t Read(void *data, size_t size) override; }; #endif diff -Nru mpd-0.19.21/src/fs/io/GunzipReader.cxx mpd-0.20.9/src/fs/io/GunzipReader.cxx --- mpd-0.19.21/src/fs/io/GunzipReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/GunzipReader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,12 +19,10 @@ #include "config.h" #include "GunzipReader.hxx" -#include "lib/zlib/Domain.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "lib/zlib/Error.hxx" -GunzipReader::GunzipReader(Reader &_next, Error &error) - :next(_next), eof(false) +GunzipReader::GunzipReader(Reader &_next) + :next(_next) { z.next_in = nullptr; z.avail_in = 0; @@ -33,25 +31,17 @@ z.opaque = Z_NULL; int result = inflateInit2(&z, 16 + MAX_WBITS); - if (result != Z_OK) { - z.opaque = this; - error.Set(zlib_domain, result, zError(result)); - } -} - -GunzipReader::~GunzipReader() -{ - if (IsDefined()) - inflateEnd(&z); + if (result != Z_OK) + throw ZlibError(result); } inline bool -GunzipReader::FillBuffer(Error &error) +GunzipReader::FillBuffer() { auto w = buffer.Write(); assert(!w.IsEmpty()); - size_t nbytes = next.Read(w.data, w.size, error); + size_t nbytes = next.Read(w.data, w.size); if (nbytes == 0) return false; @@ -60,7 +50,7 @@ } size_t -GunzipReader::Read(void *data, size_t size, Error &error) +GunzipReader::Read(void *data, size_t size) { if (eof) return 0; @@ -73,10 +63,8 @@ auto r = buffer.Read(); if (r.IsEmpty()) { - if (FillBuffer(error)) + if (FillBuffer()) r = buffer.Read(); - else if (error.IsDefined()) - return 0; else flush = Z_FINISH; } @@ -88,10 +76,8 @@ if (result == Z_STREAM_END) { eof = true; return size - z.avail_out; - } else if (result != Z_OK) { - error.Set(zlib_domain, result, zError(result)); - return 0; - } + } else if (result != Z_OK) + throw ZlibError(result); buffer.Consume(r.size - z.avail_in); diff -Nru mpd-0.19.21/src/fs/io/GunzipReader.hxx mpd-0.20.9/src/fs/io/GunzipReader.hxx --- mpd-0.19.21/src/fs/io/GunzipReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/GunzipReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,16 +27,13 @@ #include -class Error; -class Domain; - /** * A filter that decompresses data using zlib. */ class GunzipReader final : public Reader { Reader &next; - bool eof; + bool eof = false; z_stream z; @@ -44,25 +41,19 @@ public: /** - * Construct the filter. Call IsDefined() to check whether - * the constructor has succeeded. If not, #error will hold - * information about the failure. + * Construct the filter. */ - GunzipReader(Reader &_next, Error &error); - ~GunzipReader(); + explicit GunzipReader(Reader &_next); - /** - * Check whether the constructor has succeeded. - */ - bool IsDefined() const { - return z.opaque == nullptr; + ~GunzipReader() { + inflateEnd(&z); } /* virtual methods from class Reader */ - virtual size_t Read(void *data, size_t size, Error &error) override; + size_t Read(void *data, size_t size) override; private: - bool FillBuffer(Error &error); + bool FillBuffer(); }; #endif diff -Nru mpd-0.19.21/src/fs/io/GzipOutputStream.cxx mpd-0.20.9/src/fs/io/GzipOutputStream.cxx --- mpd-0.19.21/src/fs/io/GzipOutputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/GzipOutputStream.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,9 @@ #include "config.h" #include "GzipOutputStream.hxx" -#include "lib/zlib/Domain.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "lib/zlib/Error.hxx" -GzipOutputStream::GzipOutputStream(OutputStream &_next, Error &error) +GzipOutputStream::GzipOutputStream(OutputStream &_next) :next(_next) { z.next_in = nullptr; @@ -38,20 +36,17 @@ int result = deflateInit2(&z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | gzip_encoding, 8, Z_DEFAULT_STRATEGY); - if (result != Z_OK) { - z.opaque = this; - error.Set(zlib_domain, result, zError(result)); - } + if (result != Z_OK) + throw ZlibError(result); } GzipOutputStream::~GzipOutputStream() { - if (IsDefined()) - deflateEnd(&z); + deflateEnd(&z); } -bool -GzipOutputStream::Flush(Error &error) +void +GzipOutputStream::Flush() { /* no more input */ z.next_in = nullptr; @@ -63,21 +58,18 @@ z.avail_out = sizeof(output); int result = deflate(&z, Z_FINISH); - if (z.next_out > output && - !next.Write(output, z.next_out - output, error)) - return false; + if (z.next_out > output) + next.Write(output, z.next_out - output); if (result == Z_STREAM_END) - return true; - else if (result != Z_OK) { - error.Set(zlib_domain, result, zError(result)); - return false; - } - } + break; + else if (result != Z_OK) + throw ZlibError(result); + } } -bool -GzipOutputStream::Write(const void *_data, size_t size, Error &error) +void +GzipOutputStream::Write(const void *_data, size_t size) { /* zlib's API requires non-const input pointer */ void *data = const_cast(_data); @@ -91,15 +83,10 @@ z.avail_out = sizeof(output); int result = deflate(&z, Z_NO_FLUSH); - if (result != Z_OK) { - error.Set(zlib_domain, result, zError(result)); - return false; - } - - if (z.next_out > output && - !next.Write(output, z.next_out - output, error)) - return false; - } + if (result != Z_OK) + throw ZlibError(result); - return true; + if (z.next_out > output) + next.Write(output, z.next_out - output); + } } diff -Nru mpd-0.19.21/src/fs/io/GzipOutputStream.hxx mpd-0.20.9/src/fs/io/GzipOutputStream.hxx --- mpd-0.19.21/src/fs/io/GzipOutputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/GzipOutputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,12 +24,8 @@ #include "OutputStream.hxx" #include "Compiler.h" -#include #include -class Error; -class Domain; - /** * A filter that compresses data written to it using zlib, forwarding * compressed data in the "gzip" format. @@ -43,28 +39,19 @@ public: /** - * Construct the filter. Call IsDefined() to check whether - * the constructor has succeeded. If not, #error will hold - * information about the failure. + * Construct the filter. */ - GzipOutputStream(OutputStream &_next, Error &error); + explicit GzipOutputStream(OutputStream &_next); ~GzipOutputStream(); /** - * Check whether the constructor has succeeded. - */ - bool IsDefined() const { - return z.opaque == nullptr; - } - - /** * Finish the file and write all data remaining in zlib's * output buffer. */ - bool Flush(Error &error); + void Flush(); /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, Error &error) override; + void Write(const void *data, size_t size) override; }; #endif diff -Nru mpd-0.19.21/src/fs/io/OutputStream.hxx mpd-0.20.9/src/fs/io/OutputStream.hxx --- mpd-0.19.21/src/fs/io/OutputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/OutputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,18 +21,18 @@ #define MPD_OUTPUT_STREAM_HXX #include "check.h" -#include "Compiler.h" #include -class Error; - class OutputStream { public: OutputStream() = default; OutputStream(const OutputStream &) = delete; - virtual bool Write(const void *data, size_t size, Error &error) = 0; + /** + * Throws std::exception on error. + */ + virtual void Write(const void *data, size_t size) = 0; }; #endif diff -Nru mpd-0.19.21/src/fs/io/PeekReader.cxx mpd-0.20.9/src/fs/io/PeekReader.cxx --- mpd-0.19.21/src/fs/io/PeekReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/PeekReader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ #include const void * -PeekReader::Peek(size_t size, Error &error) +PeekReader::Peek(size_t size) { assert(size > 0); assert(size < sizeof(buffer)); @@ -35,7 +35,7 @@ do { size_t nbytes = next.Read(buffer + buffer_size, - size - buffer_size, error); + size - buffer_size); if (nbytes == 0) return nullptr; @@ -46,7 +46,7 @@ } size_t -PeekReader::Read(void *data, size_t size, Error &error) +PeekReader::Read(void *data, size_t size) { size_t buffer_remaining = buffer_size - buffer_position; if (buffer_remaining > 0) { @@ -56,5 +56,5 @@ return nbytes; } - return next.Read(data, size, error); + return next.Read(data, size); } diff -Nru mpd-0.19.21/src/fs/io/PeekReader.hxx mpd-0.20.9/src/fs/io/PeekReader.hxx --- mpd-0.19.21/src/fs/io/PeekReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/PeekReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,8 +26,6 @@ #include -class AutoGunzipReader; - /** * A filter that allows the caller to peek the first few bytes without * consuming them. The first call must be Peek(), and the following @@ -36,18 +34,18 @@ class PeekReader final : public Reader { Reader &next; - size_t buffer_size, buffer_position; + size_t buffer_size = 0, buffer_position = 0; uint8_t buffer[64]; public: - PeekReader(Reader &_next) - :next(_next), buffer_size(0), buffer_position(0) {} + explicit PeekReader(Reader &_next) + :next(_next) {} - const void *Peek(size_t size, Error &error); + const void *Peek(size_t size); /* virtual methods from class Reader */ - virtual size_t Read(void *data, size_t size, Error &error) override; + virtual size_t Read(void *data, size_t size) override; }; #endif diff -Nru mpd-0.19.21/src/fs/io/Reader.hxx mpd-0.20.9/src/fs/io/Reader.hxx --- mpd-0.19.21/src/fs/io/Reader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/Reader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,8 +25,6 @@ #include -class Error; - /** * An interface that can read bytes from a stream until the stream * ends. @@ -43,10 +41,10 @@ * Read data from the stream. * * @return the number of bytes read into the given buffer or 0 - * on error/end-of-stream + * on end-of-stream */ gcc_nonnull_all - virtual size_t Read(void *data, size_t size, Error &error) = 0; + virtual size_t Read(void *data, size_t size) = 0; }; #endif diff -Nru mpd-0.19.21/src/fs/io/StdioOutputStream.hxx mpd-0.20.9/src/fs/io/StdioOutputStream.hxx --- mpd-0.19.21/src/fs/io/StdioOutputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/StdioOutputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ #include "check.h" #include "OutputStream.hxx" -#include "fs/AllocatedPath.hxx" #include "Compiler.h" #include @@ -31,15 +30,13 @@ FILE *const file; public: - StdioOutputStream(FILE *_file):file(_file) {} + explicit StdioOutputStream(FILE *_file):file(_file) {} /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, - gcc_unused Error &error) override { + void Write(const void *data, size_t size) override { fwrite(data, 1, size, file); /* this class is debug-only and ignores errors */ - return true; } }; diff -Nru mpd-0.19.21/src/fs/io/TextFile.cxx mpd-0.20.9/src/fs/io/TextFile.cxx --- mpd-0.19.21/src/fs/io/TextFile.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/TextFile.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,29 +26,25 @@ #include -TextFile::TextFile(Path path_fs, Error &error) - :file_reader(new FileReader(path_fs, error)), -#ifdef HAVE_ZLIB - gunzip_reader(file_reader->IsDefined() - ? new AutoGunzipReader(*file_reader) - : nullptr), +TextFile::TextFile(Path path_fs) + :file_reader(new FileReader(path_fs)), +#ifdef ENABLE_ZLIB + gunzip_reader(new AutoGunzipReader(*file_reader)), #endif - buffered_reader(file_reader->IsDefined() - ? new BufferedReader(* -#ifdef HAVE_ZLIB - gunzip_reader + buffered_reader(new BufferedReader(* +#ifdef ENABLE_ZLIB + gunzip_reader #else - file_reader + file_reader #endif - ) - : nullptr) + )) { } TextFile::~TextFile() { delete buffered_reader; -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB delete gunzip_reader; #endif delete file_reader; @@ -61,11 +57,3 @@ return buffered_reader->ReadLine(); } - -bool -TextFile::Check(Error &error) const -{ - assert(buffered_reader != nullptr); - - return buffered_reader->Check(error); -} diff -Nru mpd-0.19.21/src/fs/io/TextFile.hxx mpd-0.20.9/src/fs/io/TextFile.hxx --- mpd-0.19.21/src/fs/io/TextFile.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/io/TextFile.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,7 @@ #include "check.h" #include "Compiler.h" -#include - class Path; -class Error; class FileReader; class AutoGunzipReader; class BufferedReader; @@ -34,40 +31,27 @@ class TextFile { FileReader *const file_reader; -#ifdef HAVE_ZLIB +#ifdef ENABLE_ZLIB AutoGunzipReader *const gunzip_reader; #endif BufferedReader *const buffered_reader; public: - TextFile(Path path_fs, Error &error); + explicit TextFile(Path path_fs); TextFile(const TextFile &other) = delete; ~TextFile(); - bool HasFailed() const { - return gcc_unlikely(buffered_reader == nullptr); - } - /** * Reads a line from the input file, and strips trailing * space. There is a reasonable maximum line length, only to * prevent denial of service. * - * Use Check() after nullptr has been returned to check - * whether an error occurred or end-of-file has been reached. - * - * @param file the source file, opened in text mode - * @return a pointer to the line, or nullptr on end-of-file or error + * @return a pointer to the line, or nullptr on end-of-file */ char *ReadLine(); - - /** - * Check whether a ReadLine() call has thrown an error. - */ - bool Check(Error &error) const; }; #endif diff -Nru mpd-0.19.21/src/fs/Limits.hxx mpd-0.20.9/src/fs/Limits.hxx --- mpd-0.19.21/src/fs/Limits.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Limits.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/fs/NarrowPath.hxx mpd-0.20.9/src/fs/NarrowPath.hxx --- mpd-0.19.21/src/fs/NarrowPath.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/fs/NarrowPath.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FS_NARROW_PATH_HXX +#define MPD_FS_NARROW_PATH_HXX + +#include "check.h" +#include "Path.hxx" +#include "util/Macros.hxx" + +#ifdef _UNICODE +#include "lib/icu/Win32.hxx" +#include "util/AllocatedString.hxx" +#include +#else +#include "util/StringPointer.hxx" +#endif + +/** + * A path name that uses the regular (narrow) "char". This is used to + * pass a #Path (which may be represented by wchar_t) to a library + * that accepts only "const char *". + */ +class NarrowPath { +#ifdef _UNICODE + typedef AllocatedString<> Value; +#else + typedef StringPointer<> Value; +#endif + typedef typename Value::const_pointer_type const_pointer_type; + + Value value; + +public: +#ifdef _UNICODE + explicit NarrowPath(Path _path) + :value(WideCharToMultiByte(CP_ACP, _path.c_str())) { + if (value.IsNull()) + /* fall back to empty string */ + value = Value::Empty(); + } +#else + explicit NarrowPath(Path _path):value(_path.c_str()) {} +#endif + + operator const_pointer_type() const { + return c_str(); + } + + const_pointer_type c_str() const { + return value.c_str(); + } +}; + +#endif diff -Nru mpd-0.19.21/src/fs/Path2.cxx mpd-0.20.9/src/fs/Path2.cxx --- mpd-0.19.21/src/fs/Path2.cxx 2016-07-29 12:51:34.000000000 +0000 +++ mpd-0.20.9/src/fs/Path2.cxx 2017-05-08 14:49:29.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ #include "AllocatedPath.hxx" AllocatedPath -Path::GetDirectoryName() const +Path::GetDirectoryName() const noexcept { return AllocatedPath::FromFS(PathTraitsFS::GetParent(c_str())); } diff -Nru mpd-0.19.21/src/fs/Path.cxx mpd-0.20.9/src/fs/Path.cxx --- mpd-0.19.21/src/fs/Path.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Path.cxx 2017-05-08 14:48:38.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,8 +21,25 @@ #include "Path.hxx" #include "Charset.hxx" +#include + std::string -Path::ToUTF8() const +Path::ToUTF8() const noexcept { - return ::PathToUTF8(c_str()); + try { + return ::PathToUTF8(c_str()); + } catch (const std::runtime_error &) { + return std::string(); + } +} + +Path::const_pointer_type +Path::GetSuffix() const noexcept +{ + const auto base = GetBase().c_str(); + const auto *dot = StringFindLast(base, '.'); + if (dot == nullptr || dot == base) + return nullptr; + + return dot + 1; } diff -Nru mpd-0.19.21/src/fs/Path.hxx mpd-0.20.9/src/fs/Path.hxx --- mpd-0.19.21/src/fs/Path.hxx 2016-07-29 12:52:00.000000000 +0000 +++ mpd-0.20.9/src/fs/Path.hxx 2017-06-03 19:47:45.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,6 @@ #include #include -#include class AllocatedPath; @@ -37,14 +36,10 @@ * This class manages a pointer to an existing path string. While an * instance lives, the string must not be invalidated. */ -class Path { - typedef PathTraitsFS::value_type value_type; - typedef PathTraitsFS::pointer pointer; - typedef PathTraitsFS::const_pointer const_pointer; +class Path : public PathTraitsFS::Pointer { + typedef PathTraitsFS::Pointer Base; - const char *value; - - constexpr Path(const_pointer _value):value(_value) {} + constexpr Path(const_pointer_type _value):Base(_value) {} public: /** @@ -66,7 +61,7 @@ * Create a new instance pointing to the specified path * string. */ - static constexpr Path FromFS(const_pointer fs) { + static constexpr Path FromFS(const_pointer_type fs) { return Path(fs); } @@ -80,7 +75,7 @@ * must not be used. */ bool IsNull() const { - return value == nullptr; + return Base::IsNull(); } /** @@ -89,7 +84,7 @@ * @see IsNull() */ void SetNull() { - value = nullptr; + *this = nullptr; } /** @@ -97,10 +92,10 @@ * elements (which may not be the number of characters). */ gcc_pure - size_t length() const { - assert(value != nullptr); + size_t length() const noexcept { + assert(!IsNull()); - return strlen(value); + return PathTraitsFS::GetLength(c_str()); } /** @@ -109,8 +104,8 @@ * instance ends. */ gcc_pure - const_pointer c_str() const { - return value; + const_pointer_type c_str() const noexcept { + return Base::c_str(); } /** @@ -118,8 +113,18 @@ * null-terminated. */ gcc_pure - const_pointer data() const { - return value; + const_pointer_type data() const noexcept { + return c_str(); + } + + /** + * Does the path contain a newline character? (Which is + * usually rejected by MPD because its protocol cannot + * transfer newline characters). + */ + gcc_pure + bool HasNewline() const noexcept { + return PathTraitsFS::Find(c_str(), '\n') != nullptr; } /** @@ -128,15 +133,15 @@ * (#IsNull returns true). */ gcc_pure - std::string ToUTF8() const; + std::string ToUTF8() const noexcept; /** * Determine the "base" file name. * The return value points inside this object. */ gcc_pure - Path GetBase() const { - return FromFS(PathTraitsFS::GetBase(value)); + Path GetBase() const noexcept { + return FromFS(PathTraitsFS::GetBase(c_str())); } /** @@ -144,7 +149,7 @@ * Returns a "nulled" instance on error. */ gcc_pure - AllocatedPath GetDirectoryName() const; + AllocatedPath GetDirectoryName() const noexcept; /** * Determine the relative part of the given path to this @@ -153,14 +158,17 @@ * nullptr on mismatch. */ gcc_pure - const char *RelativeFS(const char *other_fs) const { - return PathTraitsFS::Relative(value, other_fs); + const_pointer_type Relative(Path other_fs) const noexcept { + return PathTraitsFS::Relative(c_str(), other_fs.c_str()); } gcc_pure - bool IsAbsolute() const { + bool IsAbsolute() const noexcept { return PathTraitsFS::IsAbsolute(c_str()); } + + gcc_pure + const_pointer_type GetSuffix() const noexcept; }; #endif diff -Nru mpd-0.19.21/src/fs/StandardDirectory.cxx mpd-0.20.9/src/fs/StandardDirectory.cxx --- mpd-0.19.21/src/fs/StandardDirectory.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/StandardDirectory.cxx 2017-05-08 13:38:39.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,14 +34,13 @@ #include #else #include -#include #include #include #endif #ifdef USE_XDG -#include "util/Error.hxx" #include "util/StringUtil.hxx" +#include "util/StringCompare.hxx" #include "io/TextFile.hxx" #include #include @@ -54,7 +53,7 @@ #include "Main.hxx" #endif -#ifndef WIN32 +#if !defined(WIN32) && !defined(ANDROID) class PasswdEntry { #if defined(HAVE_GETPWNAM_R) || defined(HAVE_GETPWUID_R) @@ -91,28 +90,33 @@ }; #endif -static inline bool IsValidPathString(PathTraitsFS::const_pointer path) +#ifndef ANDROID +static inline bool +IsValidPathString(PathTraitsFS::const_pointer_type path) { return path != nullptr && *path != '\0'; } -static inline bool IsValidDir(PathTraitsFS::const_pointer dir) +static inline bool +IsValidDir(PathTraitsFS::const_pointer_type dir) { return PathTraitsFS::IsAbsolute(dir) && DirectoryExists(Path::FromFS(dir)); } -static inline AllocatedPath SafePathFromFS(PathTraitsFS::const_pointer dir) +static inline AllocatedPath +SafePathFromFS(PathTraitsFS::const_pointer_type dir) { if (IsValidPathString(dir) && IsValidDir(dir)) return AllocatedPath::FromFS(dir); return AllocatedPath::Null(); } +#endif #ifdef WIN32 static AllocatedPath GetStandardDir(int folder_id) { - std::array dir; + std::array dir; auto ret = SHGetFolderPath(nullptr, folder_id | CSIDL_FLAG_DONT_VERIFY, nullptr, SHGFP_TYPE_CURRENT, dir.data()); if (FAILED(ret)) @@ -198,26 +202,29 @@ return true; } -static AllocatedPath GetUserDir(const char *name) -{ +static AllocatedPath +GetUserDir(const char *name) noexcept +try { auto result = AllocatedPath::Null(); auto config_dir = GetUserConfigDir(); if (config_dir.IsNull()) return result; auto dirs_file = AllocatedPath::Build(config_dir, "user-dirs.dirs"); - TextFile input(dirs_file, IgnoreError()); - if (input.HasFailed()) - return result; + + TextFile input(dirs_file); char *line; while ((line = input.ReadLine()) != nullptr) if (ParseConfigLine(line, name, result)) return result; return result; +} catch (const std::exception &e) { + return AllocatedPath::Null(); } #endif -AllocatedPath GetUserConfigDir() +AllocatedPath +GetUserConfigDir() noexcept { #if defined(WIN32) return GetStandardDir(CSIDL_LOCAL_APPDATA); @@ -241,7 +248,8 @@ #endif } -AllocatedPath GetUserMusicDir() +AllocatedPath +GetUserMusicDir() noexcept { #if defined(WIN32) return GetStandardDir(CSIDL_MYMUSIC); @@ -254,7 +262,8 @@ #endif } -AllocatedPath GetUserCacheDir() +AllocatedPath +GetUserCacheDir() noexcept { #ifdef USE_XDG // Check for $XDG_CACHE_HOME @@ -280,14 +289,16 @@ #ifdef WIN32 -AllocatedPath GetSystemConfigDir() +AllocatedPath +GetSystemConfigDir() noexcept { return GetStandardDir(CSIDL_COMMON_APPDATA); } -AllocatedPath GetAppBaseDir() +AllocatedPath +GetAppBaseDir() noexcept { - std::array app; + std::array app; auto ret = GetModuleFileName(nullptr, app.data(), app.size()); // Check for error @@ -304,23 +315,31 @@ #else -AllocatedPath GetHomeDir() +AllocatedPath +GetHomeDir() noexcept { +#ifndef ANDROID auto home = getenv("HOME"); if (IsValidPathString(home) && IsValidDir(home)) return AllocatedPath::FromFS(home); PasswdEntry pw; if (pw.ReadByUid(getuid())) return SafePathFromFS(pw->pw_dir); +#endif return AllocatedPath::Null(); } -AllocatedPath GetHomeDir(const char *user_name) +AllocatedPath +GetHomeDir(const char *user_name) noexcept { +#ifdef ANDROID + (void)user_name; +#else assert(user_name != nullptr); PasswdEntry pw; if (pw.ReadByName(user_name)) return SafePathFromFS(pw->pw_dir); +#endif return AllocatedPath::Null(); } diff -Nru mpd-0.19.21/src/fs/StandardDirectory.hxx mpd-0.20.9/src/fs/StandardDirectory.hxx --- mpd-0.19.21/src/fs/StandardDirectory.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/StandardDirectory.hxx 2017-05-08 13:38:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,45 +26,51 @@ /** * Obtains configuration directory for the current user. */ -AllocatedPath GetUserConfigDir(); +AllocatedPath +GetUserConfigDir() noexcept; /** * Obtains music directory for the current user. */ -AllocatedPath GetUserMusicDir(); +AllocatedPath +GetUserMusicDir() noexcept; /** * Obtains cache directory for the current user. */ gcc_pure AllocatedPath -GetUserCacheDir(); +GetUserCacheDir() noexcept; #ifdef WIN32 /** * Obtains system configuration directory. */ -AllocatedPath GetSystemConfigDir(); +AllocatedPath +GetSystemConfigDir() noexcept; /** * Obtains application application base directory. * Application base directory is a directory that contains 'bin' folder * for current executable. */ -AllocatedPath GetAppBaseDir(); +AllocatedPath +GetAppBaseDir() noexcept; #else /** * Obtains home directory for the current user. */ -AllocatedPath GetHomeDir(); +AllocatedPath +GetHomeDir() noexcept; /** * Obtains home directory for the specified user. */ -AllocatedPath GetHomeDir(const char *user_name); +AllocatedPath +GetHomeDir(const char *user_name) noexcept; #endif diff -Nru mpd-0.19.21/src/fs/Traits.cxx mpd-0.20.9/src/fs/Traits.cxx --- mpd-0.19.21/src/fs/Traits.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Traits.cxx 2017-05-08 14:45:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,13 +19,14 @@ #include "config.h" #include "Traits.hxx" +#include "util/StringCompare.hxx" #include template typename Traits::string -BuildPathImpl(typename Traits::const_pointer a, size_t a_size, - typename Traits::const_pointer b, size_t b_size) +BuildPathImpl(typename Traits::const_pointer_type a, size_t a_size, + typename Traits::const_pointer_type b, size_t b_size) { assert(a != nullptr); assert(b != nullptr); @@ -49,15 +50,15 @@ } template -typename Traits::const_pointer -GetBasePathImpl(typename Traits::const_pointer p) +typename Traits::const_pointer_type +GetBasePathImpl(typename Traits::const_pointer_type p) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); #endif - typename Traits::const_pointer sep = Traits::FindLastSeparator(p); + typename Traits::const_pointer_type sep = Traits::FindLastSeparator(p); return sep != nullptr ? sep + 1 : p; @@ -65,16 +66,16 @@ template typename Traits::string -GetParentPathImpl(typename Traits::const_pointer p) +GetParentPathImpl(typename Traits::const_pointer_type p) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); #endif - typename Traits::const_pointer sep = Traits::FindLastSeparator(p); + typename Traits::const_pointer_type sep = Traits::FindLastSeparator(p); if (sep == nullptr) - return typename Traits::string("."); + return typename Traits::string(Traits::CURRENT_DIRECTORY); if (sep == p) return typename Traits::string(p, p + 1); #ifdef WIN32 @@ -85,20 +86,19 @@ } template -typename Traits::const_pointer -RelativePathImpl(typename Traits::const_pointer base, - typename Traits::const_pointer other) +typename Traits::const_pointer_type +RelativePathImpl(typename Traits::const_pointer_type base, + typename Traits::const_pointer_type other) { assert(base != nullptr); assert(other != nullptr); - const auto base_length = Traits::GetLength(base); - if (memcmp(base, other, base_length * sizeof(*base)) != 0) + other = StringAfterPrefix(other, base); + if (other == nullptr) /* mismatch */ return nullptr; - other += base_length; - if (other != 0) { + if (*other != 0) { if (!Traits::IsSeparator(*other)) /* mismatch */ return nullptr; @@ -113,51 +113,52 @@ } PathTraitsFS::string -PathTraitsFS::Build(PathTraitsFS::const_pointer a, size_t a_size, - PathTraitsFS::const_pointer b, size_t b_size) +PathTraitsFS::Build(const_pointer_type a, size_t a_size, + const_pointer_type b, size_t b_size) noexcept { return BuildPathImpl(a, a_size, b, b_size); } -PathTraitsFS::const_pointer -PathTraitsFS::GetBase(PathTraitsFS::const_pointer p) +PathTraitsFS::const_pointer_type +PathTraitsFS::GetBase(PathTraitsFS::const_pointer_type p) noexcept { return GetBasePathImpl(p); } PathTraitsFS::string -PathTraitsFS::GetParent(PathTraitsFS::const_pointer p) +PathTraitsFS::GetParent(PathTraitsFS::const_pointer_type p) noexcept { return GetParentPathImpl(p); } -PathTraitsFS::const_pointer -PathTraitsFS::Relative(const_pointer base, const_pointer other) +PathTraitsFS::const_pointer_type +PathTraitsFS::Relative(const_pointer_type base, const_pointer_type other) noexcept { return RelativePathImpl(base, other); } PathTraitsUTF8::string -PathTraitsUTF8::Build(PathTraitsUTF8::const_pointer a, size_t a_size, - PathTraitsUTF8::const_pointer b, size_t b_size) +PathTraitsUTF8::Build(const_pointer_type a, size_t a_size, + const_pointer_type b, size_t b_size) noexcept { return BuildPathImpl(a, a_size, b, b_size); } -PathTraitsUTF8::const_pointer -PathTraitsUTF8::GetBase(PathTraitsUTF8::const_pointer p) +PathTraitsUTF8::const_pointer_type +PathTraitsUTF8::GetBase(const_pointer_type p) noexcept { return GetBasePathImpl(p); } PathTraitsUTF8::string -PathTraitsUTF8::GetParent(PathTraitsUTF8::const_pointer p) +PathTraitsUTF8::GetParent(const_pointer_type p) noexcept { return GetParentPathImpl(p); } -PathTraitsUTF8::const_pointer -PathTraitsUTF8::Relative(const_pointer base, const_pointer other) +PathTraitsUTF8::const_pointer_type +PathTraitsUTF8::Relative(const_pointer_type base, + const_pointer_type other) noexcept { return RelativePathImpl(base, other); } diff -Nru mpd-0.19.21/src/fs/Traits.hxx mpd-0.20.9/src/fs/Traits.hxx --- mpd-0.19.21/src/fs/Traits.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/fs/Traits.hxx 2017-06-03 19:47:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,24 +22,38 @@ #include "check.h" #include "Compiler.h" +#include "util/StringPointer.hxx" +#include "util/StringAPI.hxx" #ifdef WIN32 #include "util/CharUtil.hxx" +#include #endif #include -#include #include +#ifdef WIN32 +#define PATH_LITERAL(s) _T(s) +#else +#define PATH_LITERAL(s) (s) +#endif + /** * This class describes the nature of a native filesystem path. */ struct PathTraitsFS { +#ifdef WIN32 + typedef std::wstring string; +#else typedef std::string string; - typedef char value_type; - typedef value_type *pointer; - typedef const value_type *const_pointer; +#endif + typedef string::traits_type char_traits; + typedef char_traits::char_type value_type; + typedef StringPointer Pointer; + typedef Pointer::pointer_type pointer_type; + typedef Pointer::const_pointer_type const_pointer_type; #ifdef WIN32 static constexpr value_type SEPARATOR = '\\'; @@ -47,7 +61,9 @@ static constexpr value_type SEPARATOR = '/'; #endif - static constexpr bool IsSeparator(value_type ch) { + static constexpr const_pointer_type CURRENT_DIRECTORY = PATH_LITERAL("."); + + static constexpr bool IsSeparator(value_type ch) noexcept { return #ifdef WIN32 ch == '/' || @@ -56,31 +72,31 @@ } gcc_pure gcc_nonnull_all - static const_pointer FindLastSeparator(const_pointer p) { + static const_pointer_type FindLastSeparator(const_pointer_type p) noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); #endif #ifdef WIN32 - const_pointer pos = p + GetLength(p); + const_pointer_type pos = p + GetLength(p); while (p != pos && !IsSeparator(*pos)) --pos; return IsSeparator(*pos) ? pos : nullptr; #else - return strrchr(p, SEPARATOR); + return StringFindLast(p, SEPARATOR); #endif } #ifdef WIN32 gcc_pure gcc_nonnull_all - static constexpr bool IsDrive(const_pointer p) { + static constexpr bool IsDrive(const_pointer_type p) noexcept { return IsAlphaASCII(p[0]) && p[1] == ':'; } #endif gcc_pure gcc_nonnull_all - static bool IsAbsolute(const_pointer p) { + static bool IsAbsolute(const_pointer_type p) noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); @@ -94,8 +110,13 @@ } gcc_pure gcc_nonnull_all - static size_t GetLength(const_pointer p) { - return strlen(p); + static size_t GetLength(const_pointer_type p) noexcept { + return StringLength(p); + } + + gcc_pure gcc_nonnull_all + static const_pointer_type Find(const_pointer_type p, value_type ch) noexcept { + return StringFind(p, ch); } /** @@ -103,7 +124,7 @@ * The return value points inside the given string. */ gcc_pure gcc_nonnull_all - static const_pointer GetBase(const_pointer p); + static const_pointer_type GetBase(const_pointer_type p) noexcept; /** * Determine the "parent" file name of the given native path. @@ -111,7 +132,7 @@ * separator in the given input string. */ gcc_pure gcc_nonnull_all - static string GetParent(const_pointer p); + static string GetParent(const_pointer_type p) noexcept; /** * Determine the relative part of the given path to this @@ -120,7 +141,8 @@ * nullptr on mismatch. */ gcc_pure gcc_nonnull_all - static const_pointer Relative(const_pointer base, const_pointer other); + static const_pointer_type Relative(const_pointer_type base, + const_pointer_type other) noexcept; /** * Constructs the path from the given components. @@ -129,11 +151,11 @@ * If both components are empty strings, empty string is returned. */ gcc_pure gcc_nonnull_all - static string Build(const_pointer a, size_t a_size, - const_pointer b, size_t b_size); + static string Build(const_pointer_type a, size_t a_size, + const_pointer_type b, size_t b_size) noexcept; gcc_pure gcc_nonnull_all - static string Build(const_pointer a, const_pointer b) { + static string Build(const_pointer_type a, const_pointer_type b) noexcept { return Build(a, GetLength(a), b, GetLength(b)); } }; @@ -143,18 +165,21 @@ */ struct PathTraitsUTF8 { typedef std::string string; - typedef char value_type; - typedef value_type *pointer; - typedef const value_type *const_pointer; + typedef string::traits_type char_traits; + typedef char_traits::char_type value_type; + typedef value_type *pointer_type; + typedef const value_type *const_pointer_type; static constexpr value_type SEPARATOR = '/'; + static constexpr const_pointer_type CURRENT_DIRECTORY = "."; + static constexpr bool IsSeparator(value_type ch) { return ch == SEPARATOR; } gcc_pure gcc_nonnull_all - static const_pointer FindLastSeparator(const_pointer p) { + static const_pointer_type FindLastSeparator(const_pointer_type p) noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); @@ -165,13 +190,13 @@ #ifdef WIN32 gcc_pure gcc_nonnull_all - static constexpr bool IsDrive(const_pointer p) { + static constexpr bool IsDrive(const_pointer_type p) noexcept { return IsAlphaASCII(p[0]) && p[1] == ':'; } #endif gcc_pure gcc_nonnull_all - static bool IsAbsolute(const_pointer p) { + static bool IsAbsolute(const_pointer_type p) noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(p != nullptr); @@ -185,8 +210,13 @@ } gcc_pure gcc_nonnull_all - static size_t GetLength(const_pointer p) { - return strlen(p); + static size_t GetLength(const_pointer_type p) noexcept { + return StringLength(p); + } + + gcc_pure gcc_nonnull_all + static const_pointer_type Find(const_pointer_type p, value_type ch) noexcept { + return StringFind(p, ch); } /** @@ -194,7 +224,7 @@ * The return value points inside the given string. */ gcc_pure gcc_nonnull_all - static const_pointer GetBase(const_pointer p); + static const_pointer_type GetBase(const_pointer_type p) noexcept; /** * Determine the "parent" file name of the given UTF-8 path. @@ -202,7 +232,7 @@ * separator in the given input string. */ gcc_pure gcc_nonnull_all - static string GetParent(const_pointer p); + static string GetParent(const_pointer_type p) noexcept; /** * Determine the relative part of the given path to this @@ -211,7 +241,8 @@ * nullptr on mismatch. */ gcc_pure gcc_nonnull_all - static const_pointer Relative(const_pointer base, const_pointer other); + static const_pointer_type Relative(const_pointer_type base, + const_pointer_type other) noexcept; /** * Constructs the path from the given components. @@ -220,11 +251,11 @@ * If both components are empty strings, empty string is returned. */ gcc_pure gcc_nonnull_all - static string Build(const_pointer a, size_t a_size, - const_pointer b, size_t b_size); + static string Build(const_pointer_type a, size_t a_size, + const_pointer_type b, size_t b_size) noexcept; gcc_pure gcc_nonnull_all - static string Build(const_pointer a, const_pointer b) { + static string Build(const_pointer_type a, const_pointer_type b) noexcept { return Build(a, GetLength(a), b, GetLength(b)); } }; diff -Nru mpd-0.19.21/src/GlobalEvents.cxx mpd-0.20.9/src/GlobalEvents.cxx --- mpd-0.19.21/src/GlobalEvents.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/GlobalEvents.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "GlobalEvents.hxx" -#include "util/Manual.hxx" -#include "event/DeferredMonitor.hxx" - -#include - -#include - -namespace GlobalEvents { - class Monitor final : public DeferredMonitor { - public: - Monitor(EventLoop &_loop):DeferredMonitor(_loop) {} - - protected: - virtual void RunDeferred() override; - }; - - static Manual monitor; - - static std::atomic_uint flags; - static Handler handlers[MAX]; -} - -/** - * Invoke the callback for a certain event. - */ -static void -InvokeGlobalEvent(GlobalEvents::Event event) -{ - assert((unsigned)event < GlobalEvents::MAX); - assert(GlobalEvents::handlers[event] != nullptr); - - GlobalEvents::handlers[event](); -} - -void -GlobalEvents::Monitor::RunDeferred() -{ - const unsigned f = flags.exchange(0); - - for (unsigned i = 0; i < MAX; ++i) - if (f & (1u << i)) - /* invoke the event handler */ - InvokeGlobalEvent(Event(i)); -} - -void -GlobalEvents::Initialize(EventLoop &loop) -{ - monitor.Construct(loop); -} - -void -GlobalEvents::Deinitialize() -{ - monitor.Destruct(); -} - -void -GlobalEvents::Register(Event event, Handler callback) -{ - assert((unsigned)event < MAX); - assert(handlers[event] == nullptr); - - handlers[event] = callback; -} - -void -GlobalEvents::Emit(Event event) -{ - assert((unsigned)event < MAX); - - const unsigned mask = 1u << unsigned(event); - if (GlobalEvents::flags.fetch_or(mask) == 0) - monitor->Schedule(); -} diff -Nru mpd-0.19.21/src/GlobalEvents.hxx mpd-0.20.9/src/GlobalEvents.hxx --- mpd-0.19.21/src/GlobalEvents.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/GlobalEvents.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_GLOBAL_EVENTS_HXX -#define MPD_GLOBAL_EVENTS_HXX - -#ifdef WIN32 -#include -/* DELETE is a WIN32 macro that poisons our namespace; this is a - kludge to allow us to use it anyway */ -#ifdef DELETE -#undef DELETE -#endif -#endif - -class EventLoop; - -namespace GlobalEvents { - enum Event { - /** an idle event was emitted */ - IDLE, - - /** must call playlist_sync() */ - PLAYLIST, - - /** the current song's tag has changed */ - TAG, - -#ifdef WIN32 - /** shutdown requested */ - SHUTDOWN, -#endif - - MAX - }; - - typedef void (*Handler)(); - - void Initialize(EventLoop &loop); - - void Deinitialize(); - - void Register(Event event, Handler handler); - - void Emit(Event event); -} - -#endif /* MAIN_NOTIFY_H */ Binary files /tmp/tmpGCkHaC/AJfAPzac0A/mpd-0.19.21/src/haiku/App_MusicPD and /tmp/tmpGCkHaC/3hAEzZlnLH/mpd-0.20.9/src/haiku/App_MusicPD differ diff -Nru mpd-0.19.21/src/IcyMetaDataParser.cxx mpd-0.20.9/src/IcyMetaDataParser.cxx --- mpd-0.19.21/src/IcyMetaDataParser.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/IcyMetaDataParser.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@ #include "tag/Tag.hxx" #include "tag/TagBuilder.hxx" #include "util/Domain.hxx" +#include "util/StringView.hxx" #include "Log.hxx" #include @@ -76,7 +77,7 @@ } if (length > 0) - tag.AddItem(type, value, length); + tag.AddItem(type, {value, length}); } static void diff -Nru mpd-0.19.21/src/IcyMetaDataParser.hxx mpd-0.20.9/src/IcyMetaDataParser.hxx --- mpd-0.19.21/src/IcyMetaDataParser.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/IcyMetaDataParser.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/Idle.cxx mpd-0.20.9/src/Idle.cxx --- mpd-0.19.21/src/Idle.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Idle.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,66 +24,15 @@ #include "config.h" #include "Idle.hxx" -#include "GlobalEvents.hxx" -#include "util/ASCII.hxx" - -#include +#include "Main.hxx" +#include "Instance.hxx" #include -static std::atomic_uint idle_flags; - -static const char *const idle_names[] = { - "database", - "stored_playlist", - "playlist", - "player", - "mixer", - "output", - "options", - "sticker", - "update", - "subscription", - "message", - "neighbor", - "mount", - nullptr -}; - void idle_add(unsigned flags) { assert(flags != 0); - unsigned old_flags = idle_flags.fetch_or(flags); - - if ((old_flags & flags) != flags) - GlobalEvents::Emit(GlobalEvents::IDLE); -} - -unsigned -idle_get(void) -{ - return idle_flags.exchange(0); -} - -const char*const* -idle_get_names(void) -{ - return idle_names; -} - -unsigned -idle_parse_name(const char *name) -{ -#if !CLANG_CHECK_VERSION(3,6) - /* disabled on clang due to -Wtautological-pointer-compare */ - assert(name != nullptr); -#endif - - for (unsigned i = 0; idle_names[i] != nullptr; ++i) - if (StringEqualsCaseASCII(name, idle_names[i])) - return 1 << i; - - return 0; + instance->EmitIdle(flags); } diff -Nru mpd-0.19.21/src/IdleFlags.cxx mpd-0.20.9/src/IdleFlags.cxx --- mpd-0.19.21/src/IdleFlags.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/IdleFlags.cxx 2017-05-08 13:03:21.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Support library for the "idle" command. + * + */ + +#include "config.h" +#include "IdleFlags.hxx" +#include "util/ASCII.hxx" + +#include + +static const char *const idle_names[] = { + "database", + "stored_playlist", + "playlist", + "player", + "mixer", + "output", + "options", + "sticker", + "update", + "subscription", + "message", + "neighbor", + "mount", + nullptr +}; + +const char*const* +idle_get_names() noexcept +{ + return idle_names; +} + +unsigned +idle_parse_name(const char *name) noexcept +{ +#if !CLANG_CHECK_VERSION(3,6) + /* disabled on clang due to -Wtautological-pointer-compare */ + assert(name != nullptr); +#endif + + for (unsigned i = 0; idle_names[i] != nullptr; ++i) + if (StringEqualsCaseASCII(name, idle_names[i])) + return 1 << i; + + return 0; +} diff -Nru mpd-0.19.21/src/IdleFlags.hxx mpd-0.20.9/src/IdleFlags.hxx --- mpd-0.19.21/src/IdleFlags.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/IdleFlags.hxx 2017-05-08 13:03:18.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Support library for the "idle" command. + * + */ + +#ifndef MPD_IDLE_FLAGS_HXX +#define MPD_IDLE_FLAGS_HXX + +#include "Compiler.h" + +/** song database has been updated*/ +static constexpr unsigned IDLE_DATABASE = 0x1; + +/** a stored playlist has been modified, created, deleted or + renamed */ +static constexpr unsigned IDLE_STORED_PLAYLIST = 0x2; + +/** the current playlist has been modified */ +static constexpr unsigned IDLE_PLAYLIST = 0x4; + +/** the player state has changed: play, stop, pause, seek, ... */ +static constexpr unsigned IDLE_PLAYER = 0x8; + +/** the volume has been modified */ +static constexpr unsigned IDLE_MIXER = 0x10; + +/** an audio output device has been enabled or disabled */ +static constexpr unsigned IDLE_OUTPUT = 0x20; + +/** options have changed: crossfade; random; repeat; ... */ +static constexpr unsigned IDLE_OPTIONS = 0x40; + +/** a sticker has been modified. */ +static constexpr unsigned IDLE_STICKER = 0x80; + +/** a database update has started or finished. */ +static constexpr unsigned IDLE_UPDATE = 0x100; + +/** a client has subscribed or unsubscribed to/from a channel */ +static constexpr unsigned IDLE_SUBSCRIPTION = 0x200; + +/** a message on the subscribed channel was received */ +static constexpr unsigned IDLE_MESSAGE = 0x400; + +/** a neighbor was found or lost */ +static constexpr unsigned IDLE_NEIGHBOR = 0x800; + +/** the mount list has changed */ +static constexpr unsigned IDLE_MOUNT = 0x1000; + +/** + * Get idle names + */ +gcc_const +const char*const* +idle_get_names() noexcept; + +/** + * Parse an idle name and return its mask. Returns 0 if the given + * name is unknown. + */ +gcc_nonnull_all gcc_pure +unsigned +idle_parse_name(const char *name) noexcept; + +#endif diff -Nru mpd-0.19.21/src/Idle.hxx mpd-0.20.9/src/Idle.hxx --- mpd-0.19.21/src/Idle.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Idle.hxx 2017-05-08 13:24:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,47 +25,7 @@ #ifndef MPD_IDLE_HXX #define MPD_IDLE_HXX -#include "Compiler.h" - -/** song database has been updated*/ -static constexpr unsigned IDLE_DATABASE = 0x1; - -/** a stored playlist has been modified, created, deleted or - renamed */ -static constexpr unsigned IDLE_STORED_PLAYLIST = 0x2; - -/** the current playlist has been modified */ -static constexpr unsigned IDLE_PLAYLIST = 0x4; - -/** the player state has changed: play, stop, pause, seek, ... */ -static constexpr unsigned IDLE_PLAYER = 0x8; - -/** the volume has been modified */ -static constexpr unsigned IDLE_MIXER = 0x10; - -/** an audio output device has been enabled or disabled */ -static constexpr unsigned IDLE_OUTPUT = 0x20; - -/** options have changed: crossfade; random; repeat; ... */ -static constexpr unsigned IDLE_OPTIONS = 0x40; - -/** a sticker has been modified. */ -static constexpr unsigned IDLE_STICKER = 0x80; - -/** a database update has started or finished. */ -static constexpr unsigned IDLE_UPDATE = 0x100; - -/** a client has subscribed or unsubscribed to/from a channel */ -static constexpr unsigned IDLE_SUBSCRIPTION = 0x200; - -/** a message on the subscribed channel was received */ -static constexpr unsigned IDLE_MESSAGE = 0x400; - -/** a neighbor was found or lost */ -static constexpr unsigned IDLE_NEIGHBOR = 0x800; - -/** the mount list has changed */ -static constexpr unsigned IDLE_MOUNT = 0x1000; +#include "IdleFlags.hxx" /** * Adds idle flag (with bitwise "or") and queues notifications to all @@ -74,24 +34,4 @@ void idle_add(unsigned flags); -/** - * Atomically reads and resets the global idle flags value. - */ -unsigned -idle_get(void); - -/** - * Get idle names - */ -const char*const* -idle_get_names(void); - -/** - * Parse an idle name and return its mask. Returns 0 if the given - * name is unknown. - */ -gcc_nonnull_all gcc_pure -unsigned -idle_parse_name(const char *name); - #endif diff -Nru mpd-0.19.21/src/input/AsyncInputStream.cxx mpd-0.20.9/src/input/AsyncInputStream.cxx --- mpd-0.19.21/src/input/AsyncInputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/AsyncInputStream.cxx 2017-06-04 10:33:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,20 +21,23 @@ #include "AsyncInputStream.hxx" #include "Domain.hxx" #include "tag/Tag.hxx" -#include "event/Call.hxx" #include "thread/Cond.hxx" #include "IOThread.hxx" -#include "util/HugeAllocator.hxx" + +#include #include #include AsyncInputStream::AsyncInputStream(const char *_url, Mutex &_mutex, Cond &_cond, - void *_buffer, size_t _buffer_size, + size_t _buffer_size, size_t _resume_at) - :InputStream(_url, _mutex, _cond), DeferredMonitor(io_thread_get()), - buffer((uint8_t *)_buffer, _buffer_size), + :InputStream(_url, _mutex, _cond), + deferred_resume(io_thread_get(), BIND_THIS_METHOD(DeferredResume)), + deferred_seek(io_thread_get(), BIND_THIS_METHOD(DeferredSeek)), + allocation(_buffer_size), + buffer((uint8_t *)allocation.get(), _buffer_size), resume_at(_resume_at), open(true), paused(false), @@ -46,34 +49,23 @@ delete tag; buffer.Clear(); - HugeFree(buffer.Write().data, buffer.GetCapacity()); } void -AsyncInputStream::SetTag(Tag *_tag) +AsyncInputStream::SetTag(Tag *_tag) noexcept { delete tag; tag = _tag; } void -AsyncInputStream::Pause() +AsyncInputStream::Pause() noexcept { assert(io_thread_inside()); paused = true; } -void -AsyncInputStream::PostponeError(Error &&error) -{ - assert(io_thread_inside()); - - seek_state = SeekState::NONE; - postponed_error = std::move(error); - cond.broadcast(); -} - inline void AsyncInputStream::Resume() { @@ -81,43 +73,40 @@ if (paused) { paused = false; + DoResume(); } } -bool -AsyncInputStream::Check(Error &error) +void +AsyncInputStream::Check() { - bool success = !postponed_error.IsDefined(); - if (!success) { - error = std::move(postponed_error); - postponed_error.Clear(); + if (postponed_exception) { + auto e = std::move(postponed_exception); + postponed_exception = std::exception_ptr(); + std::rethrow_exception(e); } - - return success; } bool -AsyncInputStream::IsEOF() +AsyncInputStream::IsEOF() noexcept { return (KnownSize() && offset >= size) || (!open && buffer.IsEmpty()); } -bool -AsyncInputStream::Seek(offset_type new_offset, Error &error) +void +AsyncInputStream::Seek(offset_type new_offset) { assert(IsReady()); assert(seek_state == SeekState::NONE); if (new_offset == offset) /* no-op */ - return true; + return; - if (!IsSeekable()) { - error.Set(input_domain, "Not seekable"); - return false; - } + if (!IsSeekable()) + throw std::runtime_error("Not seekable"); /* check if we can fast-forward the buffer */ @@ -136,26 +125,23 @@ } if (new_offset == offset) - return true; + return; /* no: ask the implementation to seek */ seek_offset = new_offset; seek_state = SeekState::SCHEDULED; - DeferredMonitor::Schedule(); + deferred_seek.Schedule(); while (seek_state != SeekState::NONE) cond.wait(mutex); - if (!Check(error)) - return false; - - return true; + Check(); } void -AsyncInputStream::SeekDone() +AsyncInputStream::SeekDone() noexcept { assert(io_thread_inside()); assert(IsSeekPending()); @@ -178,23 +164,22 @@ } bool -AsyncInputStream::IsAvailable() +AsyncInputStream::IsAvailable() noexcept { - return postponed_error.IsDefined() || + return postponed_exception || IsEOF() || !buffer.IsEmpty(); } size_t -AsyncInputStream::Read(void *ptr, size_t read_size, Error &error) +AsyncInputStream::Read(void *ptr, size_t read_size) { assert(!io_thread_inside()); /* wait for data */ CircularBuffer::Range r; while (true) { - if (!Check(error)) - return 0; + Check(); r = buffer.Read(); if (!r.IsEmpty() || IsEOF()) @@ -210,13 +195,24 @@ offset += (offset_type)nbytes; if (paused && buffer.GetSize() < resume_at) - DeferredMonitor::Schedule(); + deferred_resume.Schedule(); return nbytes; } void -AsyncInputStream::AppendToBuffer(const void *data, size_t append_size) +AsyncInputStream::CommitWriteBuffer(size_t nbytes) noexcept +{ + buffer.Append(nbytes); + + if (!IsReady()) + SetReady(); + else + cond.broadcast(); +} + +void +AsyncInputStream::AppendToBuffer(const void *data, size_t append_size) noexcept { auto w = buffer.Write(); assert(!w.IsEmpty()); @@ -242,16 +238,36 @@ } void -AsyncInputStream::RunDeferred() +AsyncInputStream::DeferredResume() noexcept { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); - Resume(); + try { + Resume(); + } catch (...) { + postponed_exception = std::current_exception(); + cond.broadcast(); + } +} + +void +AsyncInputStream::DeferredSeek() noexcept +{ + const std::lock_guard protect(mutex); + if (seek_state != SeekState::SCHEDULED) + return; + + try { + Resume(); - if (seek_state == SeekState::SCHEDULED) { seek_state = SeekState::PENDING; buffer.Clear(); paused = false; + DoSeek(seek_offset); + } catch (...) { + seek_state = SeekState::NONE; + postponed_exception = std::current_exception(); + cond.broadcast(); } } diff -Nru mpd-0.19.21/src/input/AsyncInputStream.hxx mpd-0.20.9/src/input/AsyncInputStream.hxx --- mpd-0.19.21/src/input/AsyncInputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/AsyncInputStream.hxx 2017-06-04 10:33:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,9 +21,11 @@ #define MPD_ASYNC_INPUT_STREAM_HXX #include "InputStream.hxx" -#include "event/DeferredMonitor.hxx" +#include "event/DeferredCall.hxx" +#include "util/HugeAllocator.hxx" #include "util/CircularBuffer.hxx" -#include "util/Error.hxx" + +#include /** * Helper class for moving asynchronous (non-blocking) InputStream @@ -31,11 +33,16 @@ * buffer, and that buffer is then consumed by another thread using * the regular #InputStream API. */ -class AsyncInputStream : public InputStream, private DeferredMonitor { +class AsyncInputStream : public InputStream { enum class SeekState : uint8_t { NONE, SCHEDULED, PENDING }; + DeferredCall deferred_resume; + DeferredCall deferred_seek; + + HugeAllocation allocation; + CircularBuffer buffer; const size_t resume_at; @@ -59,37 +66,41 @@ offset_type seek_offset; protected: - Error postponed_error; + std::exception_ptr postponed_exception; public: + /** + * @param _buffer a buffer allocated with HugeAllocate(); the + * destructor will free it using HugeFree() + */ AsyncInputStream(const char *_url, Mutex &_mutex, Cond &_cond, - void *_buffer, size_t _buffer_size, + size_t _buffer_size, size_t _resume_at); virtual ~AsyncInputStream(); /* virtual methods from InputStream */ - bool Check(Error &error) final; - bool IsEOF() final; - bool Seek(offset_type new_offset, Error &error) final; + void Check() final; + bool IsEOF() noexcept final; + void Seek(offset_type new_offset) final; Tag *ReadTag() final; - bool IsAvailable() final; - size_t Read(void *ptr, size_t read_size, Error &error) final; + bool IsAvailable() noexcept final; + size_t Read(void *ptr, size_t read_size) final; protected: /** * Pass an tag from the I/O thread to the client thread. */ - void SetTag(Tag *_tag); + void SetTag(Tag *_tag) noexcept; - void ClearTag() { + void ClearTag() noexcept { SetTag(nullptr); } - void Pause(); + void Pause() noexcept; - bool IsPaused() const { + bool IsPaused() const noexcept { return paused; } @@ -98,20 +109,15 @@ * continue feeding Read() calls from the buffer until it runs * empty. */ - void SetClosed() { + void SetClosed() noexcept { open = false; } - /** - * Pass an error from the I/O thread to the client thread. - */ - void PostponeError(Error &&error); - - bool IsBufferEmpty() const { + bool IsBufferEmpty() const noexcept { return buffer.IsEmpty(); } - bool IsBufferFull() const { + bool IsBufferFull() const noexcept { return buffer.IsFull(); } @@ -119,15 +125,21 @@ * Determine how many bytes can be added to the buffer. */ gcc_pure - size_t GetBufferSpace() const { + size_t GetBufferSpace() const noexcept { return buffer.GetSpace(); } + CircularBuffer::Range PrepareWriteBuffer() noexcept { + return buffer.Write(); + } + + void CommitWriteBuffer(size_t nbytes) noexcept; + /** * Append data to the buffer. The size must fit into the * buffer; see GetBufferSpace(). */ - void AppendToBuffer(const void *data, size_t append_size); + void AppendToBuffer(const void *data, size_t append_size) noexcept; /** * Implement code here that will resume the stream after it @@ -142,7 +154,7 @@ */ virtual void DoSeek(offset_type new_offset) = 0; - bool IsSeekPending() const { + bool IsSeekPending() const noexcept { return seek_state == SeekState::PENDING; } @@ -150,13 +162,14 @@ * Call this after seeking has finished. It will notify the * client thread. */ - void SeekDone(); + void SeekDone() noexcept; private: void Resume(); - /* virtual methods from DeferredMonitor */ - void RunDeferred() final; + /* for DeferredCall */ + void DeferredResume() noexcept; + void DeferredSeek() noexcept; }; #endif diff -Nru mpd-0.19.21/src/input/Domain.cxx mpd-0.20.9/src/input/Domain.cxx --- mpd-0.19.21/src/input/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/Domain.hxx mpd-0.20.9/src/input/Domain.hxx --- mpd-0.19.21/src/input/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/IcyInputStream.cxx mpd-0.20.9/src/input/IcyInputStream.cxx --- mpd-0.19.21/src/input/IcyInputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/IcyInputStream.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -79,13 +79,13 @@ } size_t -IcyInputStream::Read(void *ptr, size_t read_size, Error &error) +IcyInputStream::Read(void *ptr, size_t read_size) { if (!IsEnabled()) - return ProxyInputStream::Read(ptr, read_size, error); + return ProxyInputStream::Read(ptr, read_size); while (true) { - size_t nbytes = ProxyInputStream::Read(ptr, read_size, error); + size_t nbytes = ProxyInputStream::Read(ptr, read_size); if (nbytes == 0) return 0; diff -Nru mpd-0.19.21/src/input/IcyInputStream.hxx mpd-0.20.9/src/input/IcyInputStream.hxx --- mpd-0.19.21/src/input/IcyInputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/IcyInputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -62,7 +62,7 @@ /* virtual methods from InputStream */ void Update() override; Tag *ReadTag() override; - size_t Read(void *ptr, size_t size, Error &error) override; + size_t Read(void *ptr, size_t size) override; }; #endif diff -Nru mpd-0.19.21/src/input/Init.cxx mpd-0.20.9/src/input/Init.cxx --- mpd-0.19.21/src/input/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Init.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,19 +21,21 @@ #include "Init.hxx" #include "Registry.hxx" #include "InputPlugin.hxx" -#include "util/Error.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "Log.hxx" +#include "PluginUnavailable.hxx" +#include "util/RuntimeError.hxx" + +#include #include -#include -bool -input_stream_global_init(Error &error) +void +input_stream_global_init() { - const config_param empty; + const ConfigBlock empty; for (unsigned i = 0; input_plugins[i] != nullptr; ++i) { const InputPlugin *plugin = input_plugins[i]; @@ -42,41 +44,29 @@ assert(*plugin->name != 0); assert(plugin->open != nullptr); - const struct config_param *param = - config_find_block(CONF_INPUT, "plugin", plugin->name); - if (param == nullptr) { - param = ∅ - } else if (!param->GetBlockValue("enabled", true)) + const auto *block = + config_find_block(ConfigBlockOption::INPUT, "plugin", + plugin->name); + if (block == nullptr) { + block = ∅ + } else if (!block->GetBlockValue("enabled", true)) /* the plugin is disabled in mpd.conf */ continue; - InputPlugin::InitResult result = plugin->init != nullptr - ? plugin->init(*param, error) - : InputPlugin::InitResult::SUCCESS; - - switch (result) { - case InputPlugin::InitResult::SUCCESS: + try { + if (plugin->init != nullptr) + plugin->init(*block); input_plugins_enabled[i] = true; - break; - - case InputPlugin::InitResult::ERROR: - error.FormatPrefix("Failed to initialize input plugin '%s': ", - plugin->name); - return false; - - case InputPlugin::InitResult::UNAVAILABLE: - if (error.IsDefined()) { - FormatError(error, - "Input plugin '%s' is unavailable", - plugin->name); - error.Clear(); - } - - break; + } catch (const PluginUnavailable &e) { + FormatError(e, + "Input plugin '%s' is unavailable", + plugin->name); + continue; + } catch (const std::runtime_error &e) { + std::throw_with_nested(FormatRuntimeError("Failed to initialize input plugin '%s'", + plugin->name)); } } - - return true; } void input_stream_global_finish(void) diff -Nru mpd-0.19.21/src/input/Init.hxx mpd-0.20.9/src/input/Init.hxx --- mpd-0.19.21/src/input/Init.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Init.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,17 +20,16 @@ #ifndef MPD_INPUT_INIT_HXX #define MPD_INPUT_INIT_HXX -class Error; - /** - * Initializes this library and all input_stream implementations. + * Initializes this library and all #InputStream implementations. */ -bool -input_stream_global_init(Error &error); +void +input_stream_global_init(); /** - * Deinitializes this library and all input_stream implementations. + * Deinitializes this library and all #InputStream implementations. */ -void input_stream_global_finish(void); +void +input_stream_global_finish(); #endif diff -Nru mpd-0.19.21/src/input/InputPlugin.hxx mpd-0.20.9/src/input/InputPlugin.hxx --- mpd-0.19.21/src/input/InputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/InputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,52 +34,34 @@ #endif #endif -struct config_param; +struct ConfigBlock; class InputStream; -class Error; struct Tag; struct InputPlugin { - enum class InitResult { - /** - * A fatal error has occurred (e.g. misconfiguration). - * The #Error has been set. - */ - ERROR, - - /** - * The plugin was initialized successfully and is - * ready to be used. - */ - SUCCESS, - - /** - * The plugin is not available and shall be disabled. - * The #Error may be set describing the situation (to - * be logged). - */ - UNAVAILABLE, - }; - const char *name; /** * Global initialization. This method is called when MPD starts. * - * @return true on success, false if the plugin should be - * disabled + * Throws #PluginUnavailable if the plugin is not available + * and shall be disabled. + * + * Throws std::runtime_error on (fatal) error. */ - InitResult (*init)(const config_param ¶m, Error &error); + void (*init)(const ConfigBlock &block); /** * Global deinitialization. Called once before MPD shuts * down (only if init() has returned true). */ - void (*finish)(void); + void (*finish)(); + /** + * Throws std::runtime_error on error. + */ InputStream *(*open)(const char *uri, - Mutex &mutex, Cond &cond, - Error &error); + Mutex &mutex, Cond &cond); }; #endif diff -Nru mpd-0.19.21/src/input/InputStream.cxx mpd-0.20.9/src/input/InputStream.cxx --- mpd-0.19.21/src/input/InputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/InputStream.cxx 2017-05-08 14:34:45.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,9 @@ #include "config.h" #include "InputStream.hxx" #include "thread/Cond.hxx" -#include "util/StringUtil.hxx" +#include "util/StringCompare.hxx" + +#include #include @@ -28,10 +30,9 @@ { } -bool -InputStream::Check(gcc_unused Error &error) +void +InputStream::Check() { - return true; } void @@ -63,7 +64,7 @@ void InputStream::LockWaitReady() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); WaitReady(); } @@ -74,30 +75,36 @@ */ gcc_pure static bool -ExpensiveSeeking(const char *uri) +ExpensiveSeeking(const char *uri) noexcept { return StringStartsWith(uri, "http://") || StringStartsWith(uri, "https://"); } bool -InputStream::CheapSeeking() const +InputStream::CheapSeeking() const noexcept { return IsSeekable() && !ExpensiveSeeking(uri.c_str()); } -bool -InputStream::Seek(gcc_unused offset_type new_offset, - gcc_unused Error &error) +void +InputStream::Seek(gcc_unused offset_type new_offset) { - return false; + throw std::runtime_error("Seeking is not implemented"); } -bool -InputStream::LockSeek(offset_type _offset, Error &error) +void +InputStream::LockSeek(offset_type _offset) { - const ScopeLock protect(mutex); - return Seek(_offset, error); + const std::lock_guard protect(mutex); + Seek(_offset); +} + +void +InputStream::LockSkip(offset_type _offset) +{ + const std::lock_guard protect(mutex); + Skip(_offset); } Tag * @@ -109,18 +116,47 @@ Tag * InputStream::LockReadTag() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); return ReadTag(); } bool -InputStream::IsAvailable() +InputStream::IsAvailable() noexcept { return true; } size_t -InputStream::LockRead(void *ptr, size_t _size, Error &error) +InputStream::LockRead(void *ptr, size_t _size) +{ +#if !CLANG_CHECK_VERSION(3,6) + /* disabled on clang due to -Wtautological-pointer-compare */ + assert(ptr != nullptr); +#endif + assert(_size > 0); + + const std::lock_guard protect(mutex); + return Read(ptr, _size); +} + +void +InputStream::ReadFull(void *_ptr, size_t _size) +{ + uint8_t *ptr = (uint8_t *)_ptr; + + size_t nbytes_total = 0; + while (_size > 0) { + size_t nbytes = Read(ptr + nbytes_total, _size); + if (nbytes == 0) + throw std::runtime_error("Unexpected end of file"); + + nbytes_total += nbytes; + _size -= nbytes; + } +} + +void +InputStream::LockReadFull(void *ptr, size_t _size) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ @@ -128,14 +164,13 @@ #endif assert(_size > 0); - const ScopeLock protect(mutex); - return Read(ptr, _size, error); + const std::lock_guard protect(mutex); + ReadFull(ptr, _size); } bool -InputStream::LockIsEOF() +InputStream::LockIsEOF() noexcept { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); return IsEOF(); } - diff -Nru mpd-0.19.21/src/input/InputStream.hxx mpd-0.20.9/src/input/InputStream.hxx --- mpd-0.19.21/src/input/InputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/InputStream.hxx 2017-06-03 19:49:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,16 +22,15 @@ #include "check.h" #include "Offset.hxx" +#include "Ptr.hxx" #include "thread/Mutex.hxx" #include "Compiler.h" #include #include -#include class Cond; -class Error; struct Tag; class InputStream { @@ -115,26 +114,25 @@ * Opens a new input stream. You may not access it until the "ready" * flag is set. * + * Throws std::runtime_error on error. + * * @param mutex a mutex that is used to protect this object; must be * locked before calling any of the public methods * @param cond a cond that gets signalled when the state of * this object changes; may be nullptr if the caller doesn't want to get * notifications - * @return an #InputStream object on success, nullptr on error + * @return an #InputStream object on success */ gcc_nonnull_all - gcc_malloc - static InputStream *Open(const char *uri, Mutex &mutex, Cond &cond, - Error &error); + static InputStreamPtr Open(const char *uri, Mutex &mutex, Cond &cond); /** * Just like Open(), but waits for the stream to become ready. * It is a wrapper for Open(), WaitReady() and Check(). */ - gcc_malloc gcc_nonnull_all - static InputStream *OpenReady(const char *uri, - Mutex &mutex, Cond &cond, - Error &error); + gcc_nonnull_all + static InputStreamPtr OpenReady(const char *uri, + Mutex &mutex, Cond &cond); /** * The absolute URI which was used to open this stream. @@ -155,10 +153,9 @@ /** * Check for errors that may have occurred in the I/O thread. - * - * @return false on error + * Throws std::runtime_error on error. */ - virtual bool Check(Error &error); + virtual void Check(); /** * Update the public attributes. Call before accessing attributes @@ -187,20 +184,20 @@ void LockWaitReady(); gcc_pure - bool HasMimeType() const { + bool HasMimeType() const noexcept { assert(ready); return !mime.empty(); } gcc_pure - const char *GetMimeType() const { + const char *GetMimeType() const noexcept { assert(ready); return mime.empty() ? nullptr : mime.c_str(); } - void ClearMimeType() { + void ClearMimeType() noexcept { mime.clear(); } @@ -217,43 +214,36 @@ mime = std::move(_mime); } - gcc_nonnull_all - void OverrideMimeType(const char *_mime) { - assert(ready); - - mime = _mime; - } - gcc_pure - bool KnownSize() const { + bool KnownSize() const noexcept { assert(ready); return size != UNKNOWN_SIZE; } gcc_pure - offset_type GetSize() const { + offset_type GetSize() const noexcept { assert(ready); assert(KnownSize()); return size; } - void AddOffset(offset_type delta) { + void AddOffset(offset_type delta) noexcept { assert(ready); offset += delta; } gcc_pure - offset_type GetOffset() const { + offset_type GetOffset() const noexcept { assert(ready); return offset; } gcc_pure - offset_type GetRest() const { + offset_type GetRest() const noexcept { assert(ready); assert(KnownSize()); @@ -261,7 +251,7 @@ } gcc_pure - bool IsSeekable() const { + bool IsSeekable() const noexcept { assert(ready); return seekable; @@ -271,7 +261,7 @@ * Determines whether seeking is cheap. This is true for local files. */ gcc_pure - bool CheapSeeking() const; + bool CheapSeeking() const noexcept; /** * Seeks to the specified position in the stream. This will most @@ -279,42 +269,53 @@ * * The caller must lock the mutex. * + * Throws std::runtime_error on error. + * * @param offset the relative offset */ - virtual bool Seek(offset_type offset, Error &error); + virtual void Seek(offset_type offset); /** * Wrapper for Seek() which locks and unlocks the mutex; the * caller must not be holding it already. */ - bool LockSeek(offset_type offset, Error &error); + void LockSeek(offset_type offset); /** * Rewind to the beginning of the stream. This is a wrapper * for Seek(0, error). */ - bool Rewind(Error &error) { - return Seek(0, error); + void Rewind() { + Seek(0); + } + + void LockRewind() { + LockSeek(0); } - bool LockRewind(Error &error) { - return LockSeek(0, error); + /** + * Skip input bytes. + */ + void Skip(offset_type _offset) { + Seek(GetOffset() + _offset); } + void LockSkip(offset_type _offset); + /** * Returns true if the stream has reached end-of-file. * * The caller must lock the mutex. */ gcc_pure - virtual bool IsEOF() = 0; + virtual bool IsEOF() noexcept = 0; /** * Wrapper for IsEOF() which locks and unlocks the mutex; the * caller must not be holding it already. */ gcc_pure - bool LockIsEOF(); + bool LockIsEOF() noexcept; /** * Reads the tag from the stream. @@ -342,7 +343,7 @@ * The caller must lock the mutex. */ gcc_pure - virtual bool IsAvailable(); + virtual bool IsAvailable() noexcept; /** * Reads data from the stream into the caller-supplied buffer. @@ -350,20 +351,46 @@ * * The caller must lock the mutex. * - * @param is the InputStream object + * Throws std::runtime_error on error. + * * @param ptr the buffer to read into * @param size the maximum number of bytes to read * @return the number of bytes read */ gcc_nonnull_all - virtual size_t Read(void *ptr, size_t size, Error &error) = 0; + virtual size_t Read(void *ptr, size_t size) = 0; /** * Wrapper for Read() which locks and unlocks the mutex; * the caller must not be holding it already. + * + * Throws std::runtime_error on error. + */ + gcc_nonnull_all + size_t LockRead(void *ptr, size_t size); + + /** + * Reads the whole data from the stream into the caller-supplied buffer. + * + * The caller must lock the mutex. + * + * Throws std::runtime_error on error. + * + * @param ptr the buffer to read into + * @param size the number of bytes to read + * @return true if the whole data was read, false otherwise. + */ + gcc_nonnull_all + void ReadFull(void *ptr, size_t size); + + /** + * Wrapper for ReadFull() which locks and unlocks the mutex; + * the caller must not be holding it already. + * + * Throws std::runtime_error on error. */ gcc_nonnull_all - size_t LockRead(void *ptr, size_t size, Error &error); + void LockReadFull(void *ptr, size_t size); }; #endif diff -Nru mpd-0.19.21/src/input/LocalOpen.cxx mpd-0.20.9/src/input/LocalOpen.cxx --- mpd-0.19.21/src/input/LocalOpen.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/LocalOpen.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ #endif #include "fs/Path.hxx" -#include "util/Error.hxx" +#include "system/Error.hxx" #include @@ -35,21 +35,25 @@ #include #endif -InputStream * -OpenLocalInputStream(Path path, Mutex &mutex, Cond &cond, Error &error) +InputStreamPtr +OpenLocalInputStream(Path path, Mutex &mutex, Cond &cond) { - assert(!error.IsDefined()); + InputStreamPtr is; - InputStream *is = OpenFileInputStream(path, mutex, cond, error); #ifdef ENABLE_ARCHIVE - if (is == nullptr && error.IsDomain(errno_domain) && - error.GetCode() == ENOTDIR) { - /* ENOTDIR means this may be a path inside an archive - file */ - Error error2; - is = OpenArchiveInputStream(path, mutex, cond, error2); - if (is == nullptr && error2.IsDefined()) - error = std::move(error2); + try { +#endif + is = OpenFileInputStream(path, mutex, cond); +#ifdef ENABLE_ARCHIVE + } catch (const std::system_error &e) { + if (IsPathNotFound(e)) { + /* ENOTDIR means this may be a path inside an archive + file */ + is = OpenArchiveInputStream(path, mutex, cond); + if (!is) + throw; + } else + throw; } #endif diff -Nru mpd-0.19.21/src/input/LocalOpen.hxx mpd-0.20.9/src/input/LocalOpen.hxx --- mpd-0.19.21/src/input/LocalOpen.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/LocalOpen.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,18 +21,19 @@ #define MPD_INPUT_LOCAL_OPEN_HXX #include "check.h" +#include "Ptr.hxx" -class InputStream; class Path; class Mutex; class Cond; -class Error; /** * Open a "local" file. This is a wrapper for the input plugins * "file" and "archive". + * + * Throws std::runtime_error on error. */ -InputStream * -OpenLocalInputStream(Path path, Mutex &mutex, Cond &cond, Error &error); +InputStreamPtr +OpenLocalInputStream(Path path, Mutex &mutex, Cond &cond); #endif diff -Nru mpd-0.19.21/src/input/Offset.hxx mpd-0.20.9/src/input/Offset.hxx --- mpd-0.19.21/src/input/Offset.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Offset.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/Open.cxx mpd-0.20.9/src/input/Open.cxx --- mpd-0.19.21/src/input/Open.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Open.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,53 +25,43 @@ #include "Domain.hxx" #include "plugins/RewindInputPlugin.hxx" #include "fs/Traits.hxx" -#include "fs/Path.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "fs/AllocatedPath.hxx" -InputStream * +#include + +InputStreamPtr InputStream::Open(const char *url, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { - if (PathTraitsFS::IsAbsolute(url)) - /* TODO: the parameter is UTF-8, not filesystem charset */ - return OpenLocalInputStream(Path::FromFS(url), - mutex, cond, error); + if (PathTraitsUTF8::IsAbsolute(url)) { + const auto path = AllocatedPath::FromUTF8Throw(url); + return OpenLocalInputStream(path, mutex, cond); + } input_plugins_for_each_enabled(plugin) { InputStream *is; - is = plugin->open(url, mutex, cond, error); + is = plugin->open(url, mutex, cond); if (is != nullptr) { is = input_rewind_open(is); - return is; - } else if (error.IsDefined()) - return nullptr; + return InputStreamPtr(is); + } } - error.Set(input_domain, "Unrecognized URI"); - return nullptr; + throw std::runtime_error("Unrecognized URI"); } -InputStream * +InputStreamPtr InputStream::OpenReady(const char *uri, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { - InputStream *is = Open(uri, mutex, cond, error); - if (is == nullptr) - return nullptr; - - mutex.lock(); - is->WaitReady(); - bool success = is->Check(error); - mutex.unlock(); - - if (!success) { - delete is; - is = nullptr; + auto is = Open(uri, mutex, cond); + + { + const std::lock_guard protect(mutex); + is->WaitReady(); + is->Check(); } return is; diff -Nru mpd-0.19.21/src/input/plugins/AlsaInputPlugin.cxx mpd-0.20.9/src/input/plugins/AlsaInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/AlsaInputPlugin.cxx 2016-11-16 18:49:26.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/AlsaInputPlugin.cxx 2017-02-10 14:05:28.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,24 +27,20 @@ #include "config.h" #include "AlsaInputPlugin.hxx" #include "../InputPlugin.hxx" -#include "../InputStream.hxx" +#include "../AsyncInputStream.hxx" +#include "event/Call.hxx" #include "util/Domain.hxx" -#include "util/Error.hxx" -#include "util/StringUtil.hxx" +#include "util/RuntimeError.hxx" +#include "util/StringCompare.hxx" #include "util/ReusableArray.hxx" #include "Log.hxx" #include "event/MultiSocketMonitor.hxx" #include "event/DeferredMonitor.hxx" -#include "event/Call.hxx" -#include "thread/Mutex.hxx" -#include "thread/Cond.hxx" #include "IOThread.hxx" #include -#include - #include #include @@ -57,41 +53,35 @@ static constexpr int default_channels = 2; // stereo static constexpr unsigned int default_rate = 44100; // cd quality -/** - * This value should be the same as the read buffer size defined in - * PcmDecoderPlugin.cxx:pcm_stream_decode(). - * We use it to calculate how many audio frames to buffer in the alsa driver - * before reading from the device. snd_pcm_readi() blocks until that many - * frames are ready. - */ -static constexpr size_t read_buffer_size = 4096; +static constexpr size_t ALSA_MAX_BUFFERED = default_rate * default_channels * 2; +static constexpr size_t ALSA_RESUME_AT = ALSA_MAX_BUFFERED / 2; class AlsaInputStream final - : public InputStream, + : public AsyncInputStream, MultiSocketMonitor, DeferredMonitor { - snd_pcm_t *capture_handle; - size_t frame_size; - int frames_to_read; - bool eof; /** - * Is somebody waiting for data? This is set by method - * Available(). + * The configured name of the ALSA device. */ - std::atomic_bool waiting; + const std::string device; + + snd_pcm_t *const capture_handle; + const size_t frame_size; ReusableArray pfd_buffer; public: AlsaInputStream(EventLoop &loop, const char *_uri, Mutex &_mutex, Cond &_cond, + const char *_device, snd_pcm_t *_handle, int _frame_size) - :InputStream(_uri, _mutex, _cond), + :AsyncInputStream(_uri, _mutex, _cond, + ALSA_MAX_BUFFERED, ALSA_RESUME_AT), MultiSocketMonitor(loop), DeferredMonitor(loop), + device(_device), capture_handle(_handle), - frame_size(_frame_size), - eof(false) + frame_size(_frame_size) { assert(_uri != nullptr); assert(_handle != nullptr); @@ -102,44 +92,43 @@ SetMimeType("audio/x-mpd-cdda-pcm"); InputStream::SetReady(); - frames_to_read = read_buffer_size / frame_size; - snd_pcm_start(capture_handle); DeferredMonitor::Schedule(); } ~AlsaInputStream() { + BlockingCall(MultiSocketMonitor::GetEventLoop(), [this](){ + MultiSocketMonitor::Reset(); + DeferredMonitor::Cancel(); + }); + snd_pcm_close(capture_handle); } - using DeferredMonitor::GetEventLoop; - - static InputStream *Create(const char *uri, Mutex &mutex, Cond &cond, - Error &error); + static InputStream *Create(const char *uri, Mutex &mutex, Cond &cond); - /* virtual methods from InputStream */ +protected: + /* virtual methods from AsyncInputStream */ + virtual void DoResume() override { + snd_pcm_resume(capture_handle); - bool IsEOF() override { - return eof; + InvalidateSockets(); } - bool IsAvailable() override { - if (snd_pcm_avail(capture_handle) > frames_to_read) - return true; - - if (!waiting.exchange(true)) - SafeInvalidateSockets(); - - return false; + virtual void DoSeek(gcc_unused offset_type new_offset) override { + /* unreachable because seekable==false */ + SeekDone(); } - size_t Read(void *ptr, size_t size, Error &error) override; - private: static snd_pcm_t *OpenDevice(const char *device, int rate, - snd_pcm_format_t format, int channels, - Error &error); + snd_pcm_format_t format, int channels); + + void Pause() { + AsyncInputStream::Pause(); + InvalidateSockets(); + } int Recover(int err); @@ -151,20 +140,18 @@ InvalidateSockets(); } - virtual int PrepareSockets() override; + virtual std::chrono::steady_clock::duration PrepareSockets() override; virtual void DispatchSockets() override; }; inline InputStream * -AlsaInputStream::Create(const char *uri, Mutex &mutex, Cond &cond, - Error &error) +AlsaInputStream::Create(const char *uri, Mutex &mutex, Cond &cond) { - const char *const scheme = "alsa://"; - if (!StringStartsWith(uri, scheme)) + const char *device = StringAfterPrefix(uri, "alsa://"); + if (device == nullptr) return nullptr; - const char *device = uri + strlen(scheme); - if (strlen(device) == 0) + if (*device == 0) device = default_device; /* placeholders - eventually user-requested audio format will @@ -174,50 +161,26 @@ snd_pcm_format_t format = default_format; int channels = default_channels; - snd_pcm_t *handle = OpenDevice(device, rate, format, channels, - error); - if (handle == nullptr) - return nullptr; + snd_pcm_t *handle = OpenDevice(device, rate, format, channels); int frame_size = snd_pcm_format_width(format) / 8 * channels; return new AlsaInputStream(io_thread_get(), uri, mutex, cond, - handle, frame_size); -} - -size_t -AlsaInputStream::Read(void *ptr, size_t read_size, Error &error) -{ - assert(ptr != nullptr); - - int num_frames = read_size / frame_size; - int ret; - while ((ret = snd_pcm_readi(capture_handle, ptr, num_frames)) < 0) { - if (Recover(ret) < 0) { - eof = true; - error.Format(alsa_input_domain, - "PCM error - stream aborted"); - return 0; - } - } - - size_t nbytes = ret * frame_size; - offset += nbytes; - return nbytes; + device, handle, frame_size); } -int +std::chrono::steady_clock::duration AlsaInputStream::PrepareSockets() { - if (!waiting) { + if (IsPaused()) { ClearSocketList(); - return -1; + return std::chrono::steady_clock::duration(-1); } int count = snd_pcm_poll_descriptors_count(capture_handle); - if (count < 0) { + if (count <= 0) { ClearSocketList(); - return -1; + return std::chrono::steady_clock::duration(-1); } struct pollfd *pfds = pfd_buffer.Get(count); @@ -227,17 +190,37 @@ count = 0; ReplaceSocketList(pfds, count); - return -1; + return std::chrono::steady_clock::duration(-1); } void AlsaInputStream::DispatchSockets() { - waiting = false; + const std::lock_guard protect(mutex); + + auto w = PrepareWriteBuffer(); + const snd_pcm_uframes_t w_frames = w.size / frame_size; + if (w_frames == 0) { + /* buffer is full */ + Pause(); + return; + } + + snd_pcm_sframes_t n_frames; + while ((n_frames = snd_pcm_readi(capture_handle, + w.data, w_frames)) < 0) { + if (n_frames == -EAGAIN) + return; + + if (Recover(n_frames) < 0) { + postponed_exception = std::make_exception_ptr(std::runtime_error("PCM error - stream aborted")); + cond.broadcast(); + return; + } + } - const ScopeLock protect(mutex); - /* wake up the thread that is waiting for more data */ - cond.broadcast(); + size_t nbytes = n_frames * frame_size; + CommitWriteBuffer(nbytes); } inline int @@ -245,129 +228,169 @@ { switch(err) { case -EPIPE: - LogDebug(alsa_input_domain, "Buffer Overrun"); - // drop through -#if GCC_CHECK_VERSION(7,0) - [[fallthrough]]; -#endif + FormatDebug(alsa_input_domain, + "Overrun on ALSA capture device \"%s\"", + device.c_str()); + break; case -ESTRPIPE: - case -EINTR: - err = snd_pcm_recover(capture_handle, err, 1); + FormatDebug(alsa_input_domain, + "ALSA capture device \"%s\" was suspended", + device.c_str()); break; - default: - // something broken somewhere, give up - err = -1; } - return err; -} -inline snd_pcm_t * -AlsaInputStream::OpenDevice(const char *device, - int rate, snd_pcm_format_t format, int channels, - Error &error) -{ - snd_pcm_t *capture_handle; - int err; - if ((err = snd_pcm_open(&capture_handle, device, - SND_PCM_STREAM_CAPTURE, 0)) < 0) { - error.Format(alsa_input_domain, "Failed to open device: %s (%s)", device, snd_strerror(err)); - return nullptr; - } + switch (snd_pcm_state(capture_handle)) { + case SND_PCM_STATE_PAUSED: + err = snd_pcm_pause(capture_handle, /* disable */ 0); + break; - snd_pcm_hw_params_t *hw_params; - if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { - error.Format(alsa_input_domain, "Cannot allocate hardware parameter structure (%s)", snd_strerror(err)); - snd_pcm_close(capture_handle); - return nullptr; - } + case SND_PCM_STATE_SUSPENDED: + err = snd_pcm_resume(capture_handle); + if (err == -EAGAIN) + return 0; + /* fall-through to snd_pcm_prepare: */ +#if GCC_CHECK_VERSION(7,0) + [[fallthrough]]; +#endif + case SND_PCM_STATE_OPEN: + case SND_PCM_STATE_SETUP: + case SND_PCM_STATE_XRUN: + err = snd_pcm_prepare(capture_handle); + if (err == 0) + err = snd_pcm_start(capture_handle); + break; - if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { - error.Format(alsa_input_domain, "Cannot initialize hardware parameter structure (%s)", snd_strerror(err)); - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - return nullptr; - } + case SND_PCM_STATE_DISCONNECTED: + break; - if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { - error.Format(alsa_input_domain, "Cannot set access type (%s)", snd_strerror (err)); - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - return nullptr; + case SND_PCM_STATE_PREPARED: + case SND_PCM_STATE_RUNNING: + case SND_PCM_STATE_DRAINING: + /* this is no error, so just keep running */ + err = 0; + break; } - if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, format)) < 0) { - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - error.Format(alsa_input_domain, "Cannot set sample format (%s)", snd_strerror (err)); - return nullptr; - } - if ((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, channels)) < 0) { - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - error.Format(alsa_input_domain, "Cannot set channels (%s)", snd_strerror (err)); - return nullptr; - } + return err; +} - if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, rate, 0)) < 0) { - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - error.Format(alsa_input_domain, "Cannot set sample rate (%s)", snd_strerror (err)); - return nullptr; - } +static void +ConfigureCapture(snd_pcm_t *capture_handle, + int rate, snd_pcm_format_t format, int channels) +{ + int err; - /* period needs to be big enough so that poll() doesn't fire too often, - * but small enough that buffer overruns don't occur if Read() is not - * invoked often enough. - * the calculation here is empirical; however all measurements were - * done using 44100:16:2. When we extend this plugin to support - * other audio formats then this may need to be revisited */ - snd_pcm_uframes_t period = read_buffer_size * 2; - int direction = -1; - if ((err = snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, - &period, &direction)) < 0) { - error.Format(alsa_input_domain, "Cannot set period size (%s)", - snd_strerror(err)); - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - return nullptr; - } + snd_pcm_hw_params_t *hw_params; + snd_pcm_hw_params_alloca(&hw_params); - if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) { - error.Format(alsa_input_domain, "Cannot set parameters (%s)", - snd_strerror(err)); - snd_pcm_hw_params_free(hw_params); - snd_pcm_close(capture_handle); - return nullptr; - } + if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) + throw FormatRuntimeError("Cannot initialize hardware parameter structure (%s)", + snd_strerror(err)); + + if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + throw FormatRuntimeError("Cannot set access type (%s)", + snd_strerror(err)); + + if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, format)) < 0) + throw FormatRuntimeError("Cannot set sample format (%s)", + snd_strerror(err)); + + if ((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, channels)) < 0) + throw FormatRuntimeError("Cannot set channels (%s)", + snd_strerror(err)); + + if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, rate, 0)) < 0) + throw FormatRuntimeError("Cannot set sample rate (%s)", + snd_strerror(err)); + + snd_pcm_uframes_t buffer_size_min, buffer_size_max; + snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min); + snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max); + unsigned buffer_time_min, buffer_time_max; + snd_pcm_hw_params_get_buffer_time_min(hw_params, &buffer_time_min, 0); + snd_pcm_hw_params_get_buffer_time_max(hw_params, &buffer_time_max, 0); + FormatDebug(alsa_input_domain, "buffer: size=%u..%u time=%u..%u", + (unsigned)buffer_size_min, (unsigned)buffer_size_max, + buffer_time_min, buffer_time_max); + + snd_pcm_uframes_t period_size_min, period_size_max; + snd_pcm_hw_params_get_period_size_min(hw_params, &period_size_min, 0); + snd_pcm_hw_params_get_period_size_max(hw_params, &period_size_max, 0); + unsigned period_time_min, period_time_max; + snd_pcm_hw_params_get_period_time_min(hw_params, &period_time_min, 0); + snd_pcm_hw_params_get_period_time_max(hw_params, &period_time_max, 0); + FormatDebug(alsa_input_domain, "period: size=%u..%u time=%u..%u", + (unsigned)period_size_min, (unsigned)period_size_max, + period_time_min, period_time_max); + + /* choose the maximum possible buffer_size ... */ + snd_pcm_hw_params_set_buffer_size(capture_handle, hw_params, + buffer_size_max); + + /* ... and calculate the period_size to have four periods in + one buffer; this way, we get woken up often enough to avoid + buffer overruns, but not too often */ + snd_pcm_uframes_t buffer_size; + if (snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size) == 0) { + snd_pcm_uframes_t period_size = buffer_size / 4; + int direction = -1; + if ((err = snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, + &period_size, &direction)) < 0) + throw FormatRuntimeError("Cannot set period size (%s)", + snd_strerror(err)); + } + + if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) + throw FormatRuntimeError("Cannot set parameters (%s)", + snd_strerror(err)); + + snd_pcm_uframes_t alsa_buffer_size; + err = snd_pcm_hw_params_get_buffer_size(hw_params, &alsa_buffer_size); + if (err < 0) + throw FormatRuntimeError("snd_pcm_hw_params_get_buffer_size() failed: %s", + snd_strerror(-err)); + + snd_pcm_uframes_t alsa_period_size; + err = snd_pcm_hw_params_get_period_size(hw_params, &alsa_period_size, + nullptr); + if (err < 0) + throw FormatRuntimeError("snd_pcm_hw_params_get_period_size() failed: %s", + snd_strerror(-err)); - snd_pcm_hw_params_free (hw_params); + FormatDebug(alsa_input_domain, "buffer_size=%u period_size=%u", + (unsigned)alsa_buffer_size, (unsigned)alsa_period_size); snd_pcm_sw_params_t *sw_params; + snd_pcm_sw_params_alloca(&sw_params); - snd_pcm_sw_params_malloc(&sw_params); snd_pcm_sw_params_current(capture_handle, sw_params); - if ((err = snd_pcm_sw_params_set_start_threshold(capture_handle, sw_params, - period)) < 0) { - error.Format(alsa_input_domain, - "unable to set start threshold (%s)", snd_strerror(err)); - snd_pcm_sw_params_free(sw_params); - snd_pcm_close(capture_handle); - return nullptr; - } + if ((err = snd_pcm_sw_params(capture_handle, sw_params)) < 0) + throw FormatRuntimeError("unable to install sw params (%s)", + snd_strerror(err)); +} - if ((err = snd_pcm_sw_params(capture_handle, sw_params)) < 0) { - error.Format(alsa_input_domain, - "unable to install sw params (%s)", snd_strerror(err)); - snd_pcm_sw_params_free(sw_params); +inline snd_pcm_t * +AlsaInputStream::OpenDevice(const char *device, + int rate, snd_pcm_format_t format, int channels) +{ + snd_pcm_t *capture_handle; + int err; + if ((err = snd_pcm_open(&capture_handle, device, + SND_PCM_STREAM_CAPTURE, + SND_PCM_NONBLOCK)) < 0) + throw FormatRuntimeError("Failed to open device: %s (%s)", + device, snd_strerror(err)); + + try { + ConfigureCapture(capture_handle, rate, format, channels); + } catch (...) { snd_pcm_close(capture_handle); - return nullptr; + throw; } - snd_pcm_sw_params_free(sw_params); - snd_pcm_prepare(capture_handle); return capture_handle; @@ -376,9 +399,9 @@ /*######################### Plugin Functions ##############################*/ static InputStream * -alsa_input_open(const char *uri, Mutex &mutex, Cond &cond, Error &error) +alsa_input_open(const char *uri, Mutex &mutex, Cond &cond) { - return AlsaInputStream::Create(uri, mutex, cond, error); + return AlsaInputStream::Create(uri, mutex, cond); } const struct InputPlugin input_plugin_alsa = { diff -Nru mpd-0.19.21/src/input/plugins/AlsaInputPlugin.hxx mpd-0.20.9/src/input/plugins/AlsaInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/AlsaInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/AlsaInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/ArchiveInputPlugin.cxx mpd-0.20.9/src/input/plugins/ArchiveInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/ArchiveInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/ArchiveInputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,26 +25,30 @@ #include "archive/ArchivePlugin.hxx" #include "archive/ArchiveFile.hxx" #include "../InputPlugin.hxx" -#include "fs/Traits.hxx" +#include "../InputStream.hxx" #include "fs/Path.hxx" -#include "util/Alloc.hxx" #include "Log.hxx" +#include "util/ScopeExit.hxx" + +#include #include -InputStream * -OpenArchiveInputStream(Path path, Mutex &mutex, Cond &cond, Error &error) +InputStreamPtr +OpenArchiveInputStream(Path path, Mutex &mutex, Cond &cond) { const ArchivePlugin *arplug; - InputStream *is; char *pname = strdup(path.c_str()); + AtScopeExit(pname) { + free(pname); + }; + // archive_lookup will modify pname when true is returned const char *archive, *filename, *suffix; if (!archive_lookup(pname, &archive, &filename, &suffix)) { FormatDebug(archive_domain, "not an archive, lookup %s failed", pname); - free(pname); return nullptr; } @@ -53,28 +57,21 @@ if (!arplug) { FormatWarning(archive_domain, "can't handle archive %s", archive); - free(pname); return nullptr; } - auto file = archive_file_open(arplug, Path::FromFS(archive), error); - if (file == nullptr) { - free(pname); - return nullptr; - } + auto file = archive_file_open(arplug, Path::FromFS(archive)); - //setup fileops - is = file->OpenStream(filename, mutex, cond, error); - free(pname); - file->Close(); + AtScopeExit(file) { + file->Close(); + }; - return is; + return InputStreamPtr(file->OpenStream(filename, mutex, cond)); } static InputStream * input_archive_open(gcc_unused const char *filename, - gcc_unused Mutex &mutex, gcc_unused Cond &cond, - gcc_unused Error &error) + gcc_unused Mutex &mutex, gcc_unused Cond &cond) { /* dummy method; use OpenArchiveInputStream() instead */ diff -Nru mpd-0.19.21/src/input/plugins/ArchiveInputPlugin.hxx mpd-0.20.9/src/input/plugins/ArchiveInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/ArchiveInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/ArchiveInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,15 +20,15 @@ #ifndef MPD_INPUT_ARCHIVE_HXX #define MPD_INPUT_ARCHIVE_HXX -class InputStream; +#include "input/Ptr.hxx" + class Path; class Mutex; class Cond; -class Error; extern const struct InputPlugin input_plugin_archive; -InputStream * -OpenArchiveInputStream(Path path, Mutex &mutex, Cond &cond, Error &error); +InputStreamPtr +OpenArchiveInputStream(Path path, Mutex &mutex, Cond &cond); #endif diff -Nru mpd-0.19.21/src/input/plugins/CdioParanoiaInputPlugin.cxx mpd-0.20.9/src/input/plugins/CdioParanoiaInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/CdioParanoiaInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/CdioParanoiaInputPlugin.cxx 2017-05-08 14:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,20 +26,19 @@ #include "../InputStream.hxx" #include "../InputPlugin.hxx" #include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "util/StringCompare.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "system/ByteOrder.hxx" #include "fs/AllocatedPath.hxx" #include "Log.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "config/ConfigError.hxx" #include #include -#include #include #include -#include #include #ifdef HAVE_CDIO_PARANOIA_PARANOIA_H @@ -97,33 +96,28 @@ } /* virtual methods from InputStream */ - bool IsEOF() override; - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + bool IsEOF() noexcept override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; }; static constexpr Domain cdio_domain("cdio"); static bool default_reverse_endian; -static InputPlugin::InitResult -input_cdio_init(const config_param ¶m, Error &error) +static void +input_cdio_init(const ConfigBlock &block) { - const char *value = param.GetBlockValue("default_byte_order"); + const char *value = block.GetBlockValue("default_byte_order"); if (value != nullptr) { if (strcmp(value, "little_endian") == 0) default_reverse_endian = IsBigEndian(); else if (strcmp(value, "big_endian") == 0) default_reverse_endian = IsLittleEndian(); - else { - error.Format(config_domain, 0, - "Unrecognized 'default_byte_order' setting: %s", - value); - return InputPlugin::InitResult::ERROR; - } + else + throw FormatRuntimeError("Unrecognized 'default_byte_order' setting: %s", + value); } - - return InputPlugin::InitResult::SUCCESS; } struct cdio_uri { @@ -132,7 +126,7 @@ }; static bool -parse_cdio_uri(struct cdio_uri *dest, const char *src, Error &error) +parse_cdio_uri(struct cdio_uri *dest, const char *src) { if (!StringStartsWith(src, "cdda://")) return false; @@ -149,7 +143,7 @@ const char *slash = strrchr(src, '/'); if (slash == nullptr) { /* play the whole CD in the specified drive */ - g_strlcpy(dest->device, src, sizeof(dest->device)); + CopyString(dest->device, src, sizeof(dest->device)); dest->track = -1; return true; } @@ -165,10 +159,8 @@ char *endptr; dest->track = strtoul(track, &endptr, 10); - if (*endptr != 0) { - error.Set(cdio_domain, "Malformed track number"); - return false; - } + if (*endptr != 0) + throw std::runtime_error("Malformed track number"); if (endptr == track) /* play the whole CD */ @@ -192,35 +184,28 @@ static InputStream * input_cdio_open(const char *uri, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { struct cdio_uri parsed_uri; - if (!parse_cdio_uri(&parsed_uri, uri, error)) + if (!parse_cdio_uri(&parsed_uri, uri)) return nullptr; /* get list of CD's supporting CD-DA */ const AllocatedPath device = parsed_uri.device[0] != 0 ? AllocatedPath::FromFS(parsed_uri.device) : cdio_detect_device(); - if (device.IsNull()) { - error.Set(cdio_domain, - "Unable find or access a CD-ROM drive with an audio CD in it."); - return nullptr; - } + if (device.IsNull()) + throw std::runtime_error("Unable find or access a CD-ROM drive with an audio CD in it."); /* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */ const auto cdio = cdio_open(device.c_str(), DRIVER_UNKNOWN); - if (cdio == nullptr) { - error.Set(cdio_domain, "Failed to open CD drive"); - return nullptr; - } + if (cdio == nullptr) + throw std::runtime_error("Failed to open CD drive"); const auto drv = cdio_cddap_identify_cdio(cdio, 1, nullptr); if (drv == nullptr) { - error.Set(cdio_domain, "Unable to identify audio CD disc."); cdio_destroy(cdio); - return nullptr; + throw std::runtime_error("Unable to identify audio CD disc."); } cdda_verbose_set(drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); @@ -228,12 +213,12 @@ if (0 != cdio_cddap_open(drv)) { cdio_cddap_close_no_free_cdio(drv); cdio_destroy(cdio); - error.Set(cdio_domain, "Unable to open disc."); - return nullptr; + throw std::runtime_error("Unable to open disc."); } bool reverse_endian; - switch (data_bigendianp(drv)) { + const int be = data_bigendianp(drv); + switch (be) { case -1: LogDebug(cdio_domain, "drive returns unknown audio data"); reverse_endian = default_reverse_endian; @@ -250,11 +235,10 @@ break; default: - error.Format(cdio_domain, "Drive returns unknown data type %d", - data_bigendianp(drv)); cdio_cddap_close_no_free_cdio(drv); cdio_destroy(cdio); - return nullptr; + throw FormatRuntimeError("Drive returns unknown data type %d", + be); } lsn_t lsn_from, lsn_to; @@ -271,30 +255,26 @@ lsn_from, lsn_to); } -bool -CdioParanoiaInputStream::Seek(offset_type new_offset, Error &error) +void +CdioParanoiaInputStream::Seek(offset_type new_offset) { - if (new_offset > size) { - error.Format(cdio_domain, "Invalid offset to seek %ld (%ld)", - (long int)new_offset, (long int)size); - return false; - } + if (new_offset > size) + throw FormatRuntimeError("Invalid offset to seek %ld (%ld)", + (long int)new_offset, (long int)size); /* simple case */ if (new_offset == offset) - return true; + return; /* calculate current LSN */ lsn_relofs = new_offset / CDIO_CD_FRAMESIZE_RAW; offset = new_offset; cdio_paranoia_seek(para, lsn_from + lsn_relofs, SEEK_SET); - - return true; } size_t -CdioParanoiaInputStream::Read(void *ptr, size_t length, Error &error) +CdioParanoiaInputStream::Read(void *ptr, size_t length) { size_t nbytes = 0; int diff; @@ -324,11 +304,9 @@ if (s_mess) { free(s_mess); } - if (!rbuf) { - error.Set(cdio_domain, - "paranoia read error. Stopping."); - return 0; - } + if (!rbuf) + throw std::runtime_error("paranoia read error"); + //store current buffer memcpy(buffer, rbuf, CDIO_CD_FRAMESIZE_RAW); buffer_lsn = lsn_relofs; @@ -362,7 +340,7 @@ } bool -CdioParanoiaInputStream::IsEOF() +CdioParanoiaInputStream::IsEOF() noexcept { return lsn_from + lsn_relofs > lsn_to; } diff -Nru mpd-0.19.21/src/input/plugins/CdioParanoiaInputPlugin.hxx mpd-0.20.9/src/input/plugins/CdioParanoiaInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/CdioParanoiaInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/CdioParanoiaInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/CurlInputPlugin.cxx mpd-0.20.9/src/input/plugins/CurlInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/CurlInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/CurlInputPlugin.cxx 2017-03-01 15:44:11.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,25 +19,26 @@ #include "config.h" #include "CurlInputPlugin.hxx" +#include "lib/curl/Easy.hxx" +#include "lib/curl/Global.hxx" +#include "lib/curl/Request.hxx" +#include "lib/curl/Handler.hxx" +#include "lib/curl/Slist.hxx" #include "../AsyncInputStream.hxx" #include "../IcyInputStream.hxx" #include "../InputPlugin.hxx" #include "config/ConfigGlobal.hxx" -#include "config/ConfigData.hxx" -#include "tag/Tag.hxx" +#include "config/Block.hxx" #include "tag/TagBuilder.hxx" -#include "event/SocketMonitor.hxx" -#include "event/TimeoutMonitor.hxx" #include "event/Call.hxx" #include "IOThread.hxx" #include "util/ASCII.hxx" #include "util/StringUtil.hxx" #include "util/NumberParser.hxx" -#include "util/CircularBuffer.hxx" -#include "util/HugeAllocator.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" +#include "PluginUnavailable.hxx" #include #include @@ -60,38 +61,32 @@ */ static const size_t CURL_RESUME_AT = 384 * 1024; -struct CurlInputStream final : public AsyncInputStream { +struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler { /* some buffers which were passed to libcurl, which we have too free */ char range[32]; - struct curl_slist *request_headers; + CurlSlist request_headers; - /** the curl handles */ - CURL *easy; - - /** error message provided by libcurl */ - char error_buffer[CURL_ERROR_SIZE]; + CurlRequest *request = nullptr; /** parser for icy-metadata */ IcyInputStream *icy; - CurlInputStream(const char *_url, Mutex &_mutex, Cond &_cond, - void *_buffer) + CurlInputStream(const char *_url, Mutex &_mutex, Cond &_cond) :AsyncInputStream(_url, _mutex, _cond, - _buffer, CURL_MAX_BUFFERED, + CURL_MAX_BUFFERED, CURL_RESUME_AT), - request_headers(nullptr), - icy(new IcyInputStream(this)) {} + icy(new IcyInputStream(this)) { + } ~CurlInputStream(); CurlInputStream(const CurlInputStream &) = delete; CurlInputStream &operator=(const CurlInputStream &) = delete; - static InputStream *Open(const char *url, Mutex &mutex, Cond &cond, - Error &error); + static InputStream *Open(const char *url, Mutex &mutex, Cond &cond); - bool InitEasy(Error &error); + void InitEasy(); /** * Frees the current "libcurl easy" handle, and everything @@ -110,141 +105,22 @@ void FreeEasyIndirect(); /** - * Called when a new response begins. This is used to discard - * headers from previous responses (for example authentication - * and redirects). + * The DoSeek() implementation invoked in the IOThread. */ - void ResponseBoundary(); - - void HeaderReceived(const char *name, std::string &&value); - - size_t DataReceived(const void *ptr, size_t size); + void SeekInternal(offset_type new_offset); - /** - * A HTTP request is finished. - * - * Runs in the I/O thread. The caller must not hold locks. - */ - void RequestDone(CURLcode result, long status); + /* virtual methods from CurlResponseHandler */ + void OnHeaders(unsigned status, + std::multimap &&headers) override; + void OnData(ConstBuffer data) override; + void OnEnd() override; + void OnError(std::exception_ptr e) override; /* virtual methods from AsyncInputStream */ virtual void DoResume() override; virtual void DoSeek(offset_type new_offset) override; }; -class CurlMulti; - -/** - * Monitor for one socket created by CURL. - */ -class CurlSocket final : SocketMonitor { - CurlMulti &multi; - -public: - CurlSocket(CurlMulti &_multi, EventLoop &_loop, int _fd) - :SocketMonitor(_fd, _loop), multi(_multi) {} - - ~CurlSocket() { - /* TODO: sometimes, CURL uses CURL_POLL_REMOVE after - closing the socket, and sometimes, it uses - CURL_POLL_REMOVE just to move the (still open) - connection to the pool; in the first case, - Abandon() would be most appropriate, but it breaks - the second case - is that a CURL bug? is there a - better solution? */ - } - - /** - * Callback function for CURLMOPT_SOCKETFUNCTION. - */ - static int SocketFunction(CURL *easy, - curl_socket_t s, int action, - void *userp, void *socketp); - - virtual bool OnSocketReady(unsigned flags) override; - -private: - static constexpr int FlagsToCurlCSelect(unsigned flags) { - return (flags & (READ | HANGUP) ? CURL_CSELECT_IN : 0) | - (flags & WRITE ? CURL_CSELECT_OUT : 0) | - (flags & ERROR ? CURL_CSELECT_ERR : 0); - } - - gcc_const - static unsigned CurlPollToFlags(int action) { - switch (action) { - case CURL_POLL_NONE: - return 0; - - case CURL_POLL_IN: - return READ; - - case CURL_POLL_OUT: - return WRITE; - - case CURL_POLL_INOUT: - return READ|WRITE; - } - - assert(false); - gcc_unreachable(); - } -}; - -/** - * Manager for the global CURLM object. - */ -class CurlMulti final : private TimeoutMonitor { - CURLM *const multi; - -public: - CurlMulti(EventLoop &_loop, CURLM *_multi); - - ~CurlMulti() { - curl_multi_cleanup(multi); - } - - bool Add(CurlInputStream *c, Error &error); - void Remove(CurlInputStream *c); - - /** - * Check for finished HTTP responses. - * - * Runs in the I/O thread. The caller must not hold locks. - */ - void ReadInfo(); - - void Assign(curl_socket_t fd, CurlSocket &cs) { - curl_multi_assign(multi, fd, &cs); - } - - void SocketAction(curl_socket_t fd, int ev_bitmask); - - void InvalidateSockets() { - SocketAction(CURL_SOCKET_TIMEOUT, 0); - } - - /** - * This is a kludge to allow pausing/resuming a stream with - * libcurl < 7.32.0. Read the curl_easy_pause manpage for - * more information. - */ - void ResumeSockets() { - int running_handles; - curl_multi_socket_all(multi, &running_handles); - } - -private: - static int TimerFunction(CURLM *multi, long timeout_ms, void *userp); - - virtual void OnTimeout() override; -}; - -/** - * libcurl version number encoded in a 24 bit integer. - */ -static unsigned curl_version_num; - /** libcurl should accept "ICY 200 OK" */ static struct curl_slist *http_200_aliases; @@ -254,41 +130,9 @@ static bool verify_peer, verify_host; -static CurlMulti *curl_multi; +static CurlGlobal *curl_global; -static constexpr Domain http_domain("http"); static constexpr Domain curl_domain("curl"); -static constexpr Domain curlm_domain("curlm"); - -CurlMulti::CurlMulti(EventLoop &_loop, CURLM *_multi) - :TimeoutMonitor(_loop), multi(_multi) -{ - curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, - CurlSocket::SocketFunction); - curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, this); - - curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, TimerFunction); - curl_multi_setopt(multi, CURLMOPT_TIMERDATA, this); -} - -/** - * Find a request by its CURL "easy" handle. - * - * Runs in the I/O thread. No lock needed. - */ -gcc_pure -static CurlInputStream * -input_curl_find_request(CURL *easy) -{ - assert(io_thread_inside()); - - void *p; - CURLcode code = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &p); - if (code != CURLE_OK) - return nullptr; - - return (CurlInputStream *)p; -} void CurlInputStream::DoResume() @@ -296,126 +140,22 @@ assert(io_thread_inside()); mutex.unlock(); - - curl_easy_pause(easy, CURLPAUSE_CONT); - - if (curl_version_num < 0x072000) - /* libcurl older than 7.32.0 does not update - its sockets after curl_easy_pause(); force - libcurl to do it now */ - curl_multi->ResumeSockets(); - - curl_multi->InvalidateSockets(); - + request->Resume(); mutex.lock(); } -int -CurlSocket::SocketFunction(gcc_unused CURL *easy, - curl_socket_t s, int action, - void *userp, void *socketp) { - CurlMulti &multi = *(CurlMulti *)userp; - CurlSocket *cs = (CurlSocket *)socketp; - - assert(io_thread_inside()); - - if (action == CURL_POLL_REMOVE) { - delete cs; - return 0; - } - - if (cs == nullptr) { - cs = new CurlSocket(multi, io_thread_get(), s); - multi.Assign(s, *cs); - } else { -#ifdef USE_EPOLL - /* when using epoll, we need to unregister the socket - each time this callback is invoked, because older - CURL versions may omit the CURL_POLL_REMOVE call - when the socket has been closed and recreated with - the same file number (bug found in CURL 7.26, CURL - 7.33 not affected); in that case, epoll refuses the - EPOLL_CTL_MOD because it does not know the new - socket yet */ - cs->Cancel(); -#endif - } - - unsigned flags = CurlPollToFlags(action); - if (flags != 0) - cs->Schedule(flags); - return 0; -} - -bool -CurlSocket::OnSocketReady(unsigned flags) -{ - assert(io_thread_inside()); - - multi.SocketAction(Get(), FlagsToCurlCSelect(flags)); - return true; -} - -/** - * Runs in the I/O thread. No lock needed. - */ -inline bool -CurlMulti::Add(CurlInputStream *c, Error &error) -{ - assert(io_thread_inside()); - assert(c != nullptr); - assert(c->easy != nullptr); - - CURLMcode mcode = curl_multi_add_handle(multi, c->easy); - if (mcode != CURLM_OK) { - error.Format(curlm_domain, mcode, - "curl_multi_add_handle() failed: %s", - curl_multi_strerror(mcode)); - return false; - } - - InvalidateSockets(); - return true; -} - -/** - * Call input_curl_easy_add() in the I/O thread. May be called from - * any thread. Caller must not hold a mutex. - */ -static bool -input_curl_easy_add_indirect(CurlInputStream *c, Error &error) -{ - assert(c != nullptr); - assert(c->easy != nullptr); - - bool result; - BlockingCall(io_thread_get(), [c, &error, &result](){ - result = curl_multi->Add(c, error); - }); - return result; -} - -inline void -CurlMulti::Remove(CurlInputStream *c) -{ - curl_multi_remove_handle(multi, c->easy); -} - void CurlInputStream::FreeEasy() { assert(io_thread_inside()); - if (easy == nullptr) + if (request == nullptr) return; - curl_multi->Remove(this); - - curl_easy_cleanup(easy); - easy = nullptr; + delete request; + request = nullptr; - curl_slist_free_all(request_headers); - request_headers = nullptr; + request_headers.Clear(); } void @@ -423,112 +163,117 @@ { BlockingCall(io_thread_get(), [this](){ FreeEasy(); - curl_multi->InvalidateSockets(); + curl_global->InvalidateSockets(); }); - - assert(easy == nullptr); } -inline void -CurlInputStream::RequestDone(CURLcode result, long status) +void +CurlInputStream::OnHeaders(unsigned status, + std::multimap &&headers) { assert(io_thread_inside()); - assert(!postponed_error.IsDefined()); + assert(!postponed_exception); - FreeEasy(); - AsyncInputStream::SetClosed(); + if (status < 200 || status >= 300) + throw FormatRuntimeError("got HTTP status %ld", status); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); - if (result != CURLE_OK) { - postponed_error.Format(curl_domain, result, - "curl failed: %s", error_buffer); - } else if (status < 200 || status >= 300) { - postponed_error.Format(http_domain, status, - "got HTTP status %ld", - status); + if (IsSeekPending()) { + /* don't update metadata while seeking */ + SeekDone(); + return; } - if (IsSeekPending()) - SeekDone(); - else if (!IsReady()) - SetReady(); - else - cond.broadcast(); -} + if (!icy->IsEnabled() && + headers.find("accept-ranges") != headers.end()) + /* a stream with icy-metadata is not seekable */ + seekable = true; -static void -input_curl_handle_done(CURL *easy_handle, CURLcode result) -{ - CurlInputStream *c = input_curl_find_request(easy_handle); - assert(c != nullptr); + auto i = headers.find("content-length"); + if (i != headers.end()) + size = offset + ParseUint64(i->second.c_str()); - long status = 0; - curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &status); + i = headers.find("content-type"); + if (i != headers.end()) + SetMimeType(std::move(i->second)); - c->RequestDone(result, status); -} + i = headers.find("icy-name"); + if (i == headers.end()) { + i = headers.find("ice-name"); + if (i == headers.end()) + i = headers.find("x-audiocast-name"); + } -void -CurlMulti::SocketAction(curl_socket_t fd, int ev_bitmask) -{ - int running_handles; - CURLMcode mcode = curl_multi_socket_action(multi, fd, ev_bitmask, - &running_handles); - if (mcode != CURLM_OK) - FormatError(curlm_domain, - "curl_multi_socket_action() failed: %s", - curl_multi_strerror(mcode)); + if (i != headers.end()) { + TagBuilder tag_builder; + tag_builder.AddItem(TAG_NAME, i->second.c_str()); - ReadInfo(); -} + SetTag(tag_builder.CommitNew()); + } -/** - * Check for finished HTTP responses. - * - * Runs in the I/O thread. The caller must not hold locks. - */ -inline void -CurlMulti::ReadInfo() -{ - assert(io_thread_inside()); + if (!icy->IsEnabled()) { + i = headers.find("icy-metaint"); - CURLMsg *msg; - int msgs_in_queue; + if (i != headers.end()) { + size_t icy_metaint = ParseUint64(i->second.c_str()); +#ifndef WIN32 + /* Windows doesn't know "%z" */ + FormatDebug(curl_domain, "icy-metaint=%zu", icy_metaint); +#endif + + if (icy_metaint > 0) { + icy->Enable(icy_metaint); - while ((msg = curl_multi_info_read(multi, - &msgs_in_queue)) != nullptr) { - if (msg->msg == CURLMSG_DONE) - input_curl_handle_done(msg->easy_handle, msg->data.result); + /* a stream with icy-metadata is not + seekable */ + seekable = false; + } + } } + + SetReady(); } -int -CurlMulti::TimerFunction(gcc_unused CURLM *_multi, long timeout_ms, void *userp) +void +CurlInputStream::OnData(ConstBuffer data) { - CurlMulti &multi = *(CurlMulti *)userp; - assert(_multi == multi.multi); + assert(data.size > 0); + + const std::lock_guard protect(mutex); + + if (IsSeekPending()) + SeekDone(); - if (timeout_ms < 0) { - multi.Cancel(); - return 0; + if (data.size > GetBufferSpace()) { + AsyncInputStream::Pause(); + throw CurlRequest::Pause(); } - if (timeout_ms >= 0 && timeout_ms < 10) - /* CURL 7.21.1 likes to report "timeout=0", which - means we're running in a busy loop. Quite a bad - idea to waste so much CPU. Let's use a lower limit - of 10ms. */ - timeout_ms = 10; + AppendToBuffer(data.data, data.size); +} - multi.Schedule(timeout_ms); - return 0; +void +CurlInputStream::OnEnd() +{ + cond.broadcast(); + + AsyncInputStream::SetClosed(); } void -CurlMulti::OnTimeout() +CurlInputStream::OnError(std::exception_ptr e) { - SocketAction(CURL_SOCKET_TIMEOUT, 0); + postponed_exception = std::move(e); + + if (IsSeekPending()) + SeekDone(); + else if (!IsReady()) + SetReady(); + else + cond.broadcast(); + + AsyncInputStream::SetClosed(); } /* @@ -536,16 +281,12 @@ * */ -static InputPlugin::InitResult -input_curl_init(const config_param ¶m, Error &error) +static void +input_curl_init(const ConfigBlock &block) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); - if (code != CURLE_OK) { - error.Format(curl_domain, code, - "curl_global_init() failed: %s", - curl_easy_strerror(code)); - return InputPlugin::InitResult::UNAVAILABLE; - } + if (code != CURLE_OK) + throw PluginUnavailable(curl_easy_strerror(code)); const auto version_info = curl_version_info(CURLVERSION_FIRST); if (version_info != nullptr) { @@ -553,46 +294,42 @@ if (version_info->features & CURL_VERSION_SSL) FormatDebug(curl_domain, "with %s", version_info->ssl_version); - - curl_version_num = version_info->version_num; } http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK"); - proxy = param.GetBlockValue("proxy"); - proxy_port = param.GetBlockValue("proxy_port", 0u); - proxy_user = param.GetBlockValue("proxy_user"); - proxy_password = param.GetBlockValue("proxy_password"); + proxy = block.GetBlockValue("proxy"); + proxy_port = block.GetBlockValue("proxy_port", 0u); + proxy_user = block.GetBlockValue("proxy_user"); + proxy_password = block.GetBlockValue("proxy_password"); if (proxy == nullptr) { /* deprecated proxy configuration */ - proxy = config_get_string(CONF_HTTP_PROXY_HOST, nullptr); - proxy_port = config_get_positive(CONF_HTTP_PROXY_PORT, 0); - proxy_user = config_get_string(CONF_HTTP_PROXY_USER, nullptr); - proxy_password = config_get_string(CONF_HTTP_PROXY_PASSWORD, + proxy = config_get_string(ConfigOption::HTTP_PROXY_HOST); + proxy_port = config_get_positive(ConfigOption::HTTP_PROXY_PORT, 0); + proxy_user = config_get_string(ConfigOption::HTTP_PROXY_USER); + proxy_password = config_get_string(ConfigOption::HTTP_PROXY_PASSWORD, ""); } - verify_peer = param.GetBlockValue("verify_peer", true); - verify_host = param.GetBlockValue("verify_host", true); + verify_peer = block.GetBlockValue("verify_peer", true); + verify_host = block.GetBlockValue("verify_host", true); - CURLM *multi = curl_multi_init(); - if (multi == nullptr) { + try { + curl_global = new CurlGlobal(io_thread_get()); + } catch (const std::runtime_error &e) { + LogError(e); curl_slist_free_all(http_200_aliases); curl_global_cleanup(); - error.Set(curl_domain, 0, "curl_multi_init() failed"); - return InputPlugin::InitResult::UNAVAILABLE; + throw PluginUnavailable("curl_multi_init() failed"); } - - curl_multi = new CurlMulti(io_thread_get(), multi); - return InputPlugin::InitResult::SUCCESS; } static void input_curl_finish(void) { BlockingCall(io_thread_get(), [](){ - delete curl_multi; + delete curl_global; }); curl_slist_free_all(http_200_aliases); @@ -606,268 +343,108 @@ FreeEasyIndirect(); } -inline void -CurlInputStream::ResponseBoundary() -{ - /* undo all effects of HeaderReceived() because the previous - response was not applicable for this stream */ - - if (IsSeekPending()) - /* don't update metadata while seeking */ - return; - - seekable = false; - size = UNKNOWN_SIZE; - ClearMimeType(); - ClearTag(); - - // TODO: reset the IcyInputStream? -} - -inline void -CurlInputStream::HeaderReceived(const char *name, std::string &&value) -{ - if (IsSeekPending()) - /* don't update metadata while seeking */ - return; - - if (StringEqualsCaseASCII(name, "accept-ranges")) { - /* a stream with icy-metadata is not seekable */ - if (!icy->IsEnabled()) - seekable = true; - } else if (StringEqualsCaseASCII(name, "content-length")) { - size = offset + ParseUint64(value.c_str()); - } else if (StringEqualsCaseASCII(name, "content-type")) { - SetMimeType(std::move(value)); - } else if (StringEqualsCaseASCII(name, "icy-name") || - StringEqualsCaseASCII(name, "ice-name") || - StringEqualsCaseASCII(name, "x-audiocast-name")) { - TagBuilder tag_builder; - tag_builder.AddItem(TAG_NAME, value.c_str()); - - SetTag(tag_builder.CommitNew()); - } else if (StringEqualsCaseASCII(name, "icy-metaint")) { - if (icy->IsEnabled()) - return; - - size_t icy_metaint = ParseUint64(value.c_str()); - FormatDebug(curl_domain, "icy-metaint=%zu", icy_metaint); - - if (icy_metaint > 0) { - icy->Enable(icy_metaint); - - /* a stream with icy-metadata is not - seekable */ - seekable = false; - } - } -} - -/** called by curl when new data is available */ -static size_t -input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream) -{ - CurlInputStream &c = *(CurlInputStream *)stream; - - size *= nmemb; - - const char *header = (const char *)ptr; - if (size > 5 && memcmp(header, "HTTP/", 5) == 0) { - c.ResponseBoundary(); - return size; - } - - const char *end = header + size; - - char name[64]; - - const char *value = (const char *)memchr(header, ':', size); - if (value == nullptr || (size_t)(value - header) >= sizeof(name)) - return size; - - memcpy(name, header, value - header); - name[value - header] = 0; - - /* skip the colon */ - - ++value; - - /* strip the value */ - - value = StripLeft(value, end); - end = StripRight(value, end); - - c.HeaderReceived(name, std::string(value, end)); - return size; -} - -inline size_t -CurlInputStream::DataReceived(const void *ptr, size_t received_size) -{ - assert(received_size > 0); - - const ScopeLock protect(mutex); - - if (IsSeekPending()) - SeekDone(); - - if (received_size > GetBufferSpace()) { - AsyncInputStream::Pause(); - return CURL_WRITEFUNC_PAUSE; - } - - AppendToBuffer(ptr, received_size); - return received_size; -} - -/** called by curl when new data is available */ -static size_t -input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) -{ - CurlInputStream &c = *(CurlInputStream *)stream; - - size *= nmemb; - if (size == 0) - return 0; - - return c.DataReceived(ptr, size); -} - -bool -CurlInputStream::InitEasy(Error &error) +void +CurlInputStream::InitEasy() { - easy = curl_easy_init(); - if (easy == nullptr) { - error.Set(curl_domain, "curl_easy_init() failed"); - return false; - } + request = new CurlRequest(*curl_global, GetURI(), *this); - curl_easy_setopt(easy, CURLOPT_PRIVATE, (void *)this); - curl_easy_setopt(easy, CURLOPT_USERAGENT, - "Music Player Daemon " VERSION); - curl_easy_setopt(easy, CURLOPT_HEADERFUNCTION, - input_curl_headerfunction); - curl_easy_setopt(easy, CURLOPT_WRITEHEADER, this); - curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, - input_curl_writefunction); - curl_easy_setopt(easy, CURLOPT_WRITEDATA, this); - curl_easy_setopt(easy, CURLOPT_HTTP200ALIASES, http_200_aliases); - curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1l); - curl_easy_setopt(easy, CURLOPT_NETRC, 1l); - curl_easy_setopt(easy, CURLOPT_MAXREDIRS, 5l); - curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1l); - curl_easy_setopt(easy, CURLOPT_ERRORBUFFER, error_buffer); - curl_easy_setopt(easy, CURLOPT_NOPROGRESS, 1l); - curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1l); - curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT, 10l); + request->SetOption(CURLOPT_HTTP200ALIASES, http_200_aliases); + request->SetOption(CURLOPT_FOLLOWLOCATION, 1l); + request->SetOption(CURLOPT_MAXREDIRS, 5l); + request->SetOption(CURLOPT_FAILONERROR, 1l); if (proxy != nullptr) - curl_easy_setopt(easy, CURLOPT_PROXY, proxy); + request->SetOption(CURLOPT_PROXY, proxy); if (proxy_port > 0) - curl_easy_setopt(easy, CURLOPT_PROXYPORT, (long)proxy_port); + request->SetOption(CURLOPT_PROXYPORT, (long)proxy_port); if (proxy_user != nullptr && proxy_password != nullptr) { char proxy_auth_str[1024]; snprintf(proxy_auth_str, sizeof(proxy_auth_str), "%s:%s", proxy_user, proxy_password); - curl_easy_setopt(easy, CURLOPT_PROXYUSERPWD, proxy_auth_str); + request->SetOption(CURLOPT_PROXYUSERPWD, proxy_auth_str); } - curl_easy_setopt(easy, CURLOPT_SSL_VERIFYPEER, verify_peer ? 1l : 0l); - curl_easy_setopt(easy, CURLOPT_SSL_VERIFYHOST, verify_host ? 2l : 0l); - - CURLcode code = curl_easy_setopt(easy, CURLOPT_URL, GetURI()); - if (code != CURLE_OK) { - error.Format(curl_domain, code, - "curl_easy_setopt() failed: %s", - curl_easy_strerror(code)); - return false; - } + request->SetOption(CURLOPT_SSL_VERIFYPEER, verify_peer ? 1l : 0l); + request->SetOption(CURLOPT_SSL_VERIFYHOST, verify_host ? 2l : 0l); - request_headers = nullptr; - request_headers = curl_slist_append(request_headers, - "Icy-Metadata: 1"); - curl_easy_setopt(easy, CURLOPT_HTTPHEADER, request_headers); + request_headers.Clear(); + request_headers.Append("Icy-Metadata: 1"); + request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get()); - return true; + request->Start(); } void -CurlInputStream::DoSeek(offset_type new_offset) +CurlInputStream::SeekInternal(offset_type new_offset) { - assert(IsReady()); - /* close the old connection and open a new one */ - mutex.unlock(); - - FreeEasyIndirect(); + FreeEasy(); offset = new_offset; if (offset == size) { /* seek to EOF: simulate empty result; avoid triggering a "416 Requested Range Not Satisfiable" response */ - mutex.lock(); SeekDone(); return; } - Error error; - if (!InitEasy(postponed_error)) { - mutex.lock(); - PostponeError(std::move(error)); - return; - } + InitEasy(); /* send the "Range" header */ if (offset > 0) { - sprintf(range, "%lld-", (long long)offset); - curl_easy_setopt(easy, CURLOPT_RANGE, range); +#ifdef WIN32 + // TODO: what can we use on Windows to format 64 bit? + sprintf(range, "%lu-", (long)offset); +#else + sprintf(range, "%llu-", (unsigned long long)offset); +#endif + request->SetOption(CURLOPT_RANGE, range); } +} - if (!input_curl_easy_add_indirect(this, error)) { - mutex.lock(); - PostponeError(std::move(error)); - return; - } +void +CurlInputStream::DoSeek(offset_type new_offset) +{ + assert(IsReady()); - mutex.lock(); - offset = new_offset; + const ScopeUnlock unlock(mutex); + + BlockingCall(io_thread_get(), [this, new_offset](){ + SeekInternal(new_offset); + }); } inline InputStream * -CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond, - Error &error) +CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond) { - void *buffer = HugeAllocate(CURL_MAX_BUFFERED); - if (buffer == nullptr) { - error.Set(curl_domain, "Out of memory"); - return nullptr; - } - - CurlInputStream *c = new CurlInputStream(url, mutex, cond, buffer); + CurlInputStream *c = new CurlInputStream(url, mutex, cond); - if (!c->InitEasy(error) || !input_curl_easy_add_indirect(c, error)) { + try { + BlockingCall(io_thread_get(), [c](){ + c->InitEasy(); + }); + } catch (...) { delete c; - return nullptr; + throw; } return c->icy; } static InputStream * -input_curl_open(const char *url, Mutex &mutex, Cond &cond, - Error &error) +input_curl_open(const char *url, Mutex &mutex, Cond &cond) { - if (memcmp(url, "http://", 7) != 0 && - memcmp(url, "https://", 8) != 0) + if (strncmp(url, "http://", 7) != 0 && + strncmp(url, "https://", 8) != 0) return nullptr; - return CurlInputStream::Open(url, mutex, cond, error); + return CurlInputStream::Open(url, mutex, cond); } const struct InputPlugin input_plugin_curl = { diff -Nru mpd-0.19.21/src/input/plugins/CurlInputPlugin.hxx mpd-0.20.9/src/input/plugins/CurlInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/CurlInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/CurlInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/FfmpegInputPlugin.cxx mpd-0.20.9/src/input/plugins/FfmpegInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/FfmpegInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/FfmpegInputPlugin.cxx 2017-05-08 14:46:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,16 +22,16 @@ #include "config.h" #include "FfmpegInputPlugin.hxx" +#include "lib/ffmpeg/Init.hxx" #include "lib/ffmpeg/Domain.hxx" #include "lib/ffmpeg/Error.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "PluginUnavailable.hxx" +#include "util/StringCompare.hxx" extern "C" { #include -#include } struct FfmpegInputStream final : public InputStream { @@ -59,9 +59,9 @@ } /* virtual methods from InputStream */ - bool IsEOF() override; - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + bool IsEOF() noexcept override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; }; static inline bool @@ -71,25 +71,19 @@ return avio_enum_protocols(&opaque, 0) != nullptr; } -static InputPlugin::InitResult -input_ffmpeg_init(gcc_unused const config_param ¶m, - Error &error) +static void +input_ffmpeg_init(gcc_unused const ConfigBlock &block) { - av_register_all(); + FfmpegInit(); /* disable this plugin if there's no registered protocol */ - if (!input_ffmpeg_supported()) { - error.Set(ffmpeg_domain, "No protocol"); - return InputPlugin::InitResult::UNAVAILABLE; - } - - return InputPlugin::InitResult::SUCCESS; + if (!input_ffmpeg_supported()) + throw PluginUnavailable("No protocol"); } static InputStream * input_ffmpeg_open(const char *uri, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { if (!StringStartsWith(uri, "gopher://") && !StringStartsWith(uri, "rtp://") && @@ -101,24 +95,22 @@ AVIOContext *h; auto result = avio_open(&h, uri, AVIO_FLAG_READ); - if (result != 0) { - SetFfmpegError(error, result); - return nullptr; - } + if (result != 0) + throw MakeFfmpegError(result); return new FfmpegInputStream(uri, mutex, cond, h); } size_t -FfmpegInputStream::Read(void *ptr, size_t read_size, Error &error) +FfmpegInputStream::Read(void *ptr, size_t read_size) { auto result = avio_read(h, (unsigned char *)ptr, read_size); if (result <= 0) { if (result < 0) - SetFfmpegError(error, result, "avio_read() failed"); + throw MakeFfmpegError(result, "avio_read() failed"); eof = true; - return false; + return 0; } offset += result; @@ -126,24 +118,21 @@ } bool -FfmpegInputStream::IsEOF() +FfmpegInputStream::IsEOF() noexcept { return eof; } -bool -FfmpegInputStream::Seek(offset_type new_offset, Error &error) +void +FfmpegInputStream::Seek(offset_type new_offset) { auto result = avio_seek(h, new_offset, SEEK_SET); - if (result < 0) { - SetFfmpegError(error, result, "avio_seek() failed"); - return false; - } + if (result < 0) + throw MakeFfmpegError(result, "avio_seek() failed"); offset = result; eof = false; - return true; } const InputPlugin input_plugin_ffmpeg = { diff -Nru mpd-0.19.21/src/input/plugins/FfmpegInputPlugin.hxx mpd-0.20.9/src/input/plugins/FfmpegInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/FfmpegInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/FfmpegInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/FileInputPlugin.cxx mpd-0.20.9/src/input/plugins/FileInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/FileInputPlugin.cxx 2016-11-17 21:16:06.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/FileInputPlugin.cxx 2017-05-08 14:38:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,113 +21,82 @@ #include "FileInputPlugin.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" -#include "fs/FileSystem.hxx" #include "fs/Path.hxx" -#include "system/fd_util.h" -#include "open.h" +#include "fs/FileInfo.hxx" +#include "fs/io/FileReader.hxx" +#include "system/FileDescriptor.hxx" +#include "util/RuntimeError.hxx" #include -#include -#include - -static constexpr Domain file_domain("file"); +#include class FileInputStream final : public InputStream { - const int fd; + FileReader reader; public: - FileInputStream(const char *path, int _fd, off_t _size, + FileInputStream(const char *path, FileReader &&_reader, off_t _size, Mutex &_mutex, Cond &_cond) :InputStream(path, _mutex, _cond), - fd(_fd) { + reader(std::move(_reader)) { size = _size; seekable = true; SetReady(); } - ~FileInputStream() { - close(fd); - } - /* virtual methods from InputStream */ - bool IsEOF() override { + bool IsEOF() noexcept override { return GetOffset() >= GetSize(); } - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; }; -InputStream * +InputStreamPtr OpenFileInputStream(Path path, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { - const int fd = OpenFile(path, O_RDONLY|O_BINARY, 0); - if (fd < 0) { - error.FormatErrno("Failed to open \"%s\"", - path.c_str()); - return nullptr; - } + FileReader reader(path); - struct stat st; - if (fstat(fd, &st) < 0) { - error.FormatErrno("Failed to stat \"%s\"", path.c_str()); - close(fd); - return nullptr; - } + const FileInfo info = reader.GetFileInfo(); - if (!S_ISREG(st.st_mode)) { - error.Format(file_domain, "Not a regular file: %s", - path.c_str()); - close(fd); - return nullptr; - } + if (!info.IsRegular()) + throw FormatRuntimeError("Not a regular file: %s", + path.c_str()); #ifdef POSIX_FADV_SEQUENTIAL - posix_fadvise(fd, (off_t)0, st.st_size, POSIX_FADV_SEQUENTIAL); + posix_fadvise(reader.GetFD().Get(), (off_t)0, info.GetSize(), + POSIX_FADV_SEQUENTIAL); #endif - return new FileInputStream(path.c_str(), fd, st.st_size, mutex, cond); + return InputStreamPtr(new FileInputStream(path.ToUTF8().c_str(), + std::move(reader), info.GetSize(), + mutex, cond)); } static InputStream * input_file_open(gcc_unused const char *filename, - gcc_unused Mutex &mutex, gcc_unused Cond &cond, - gcc_unused Error &error) + gcc_unused Mutex &mutex, gcc_unused Cond &cond) { /* dummy method; use OpenFileInputStream() instead */ return nullptr; } -bool -FileInputStream::Seek(offset_type new_offset, Error &error) +void +FileInputStream::Seek(offset_type new_offset) { - auto result = lseek(fd, (off_t)new_offset, SEEK_SET); - if (result < 0) { - error.SetErrno("Failed to seek"); - return false; - } - - offset = (offset_type)result; - return true; + reader.Seek((off_t)new_offset); + offset = new_offset; } size_t -FileInputStream::Read(void *ptr, size_t read_size, Error &error) +FileInputStream::Read(void *ptr, size_t read_size) { - ssize_t nbytes = read(fd, ptr, read_size); - if (nbytes < 0) { - error.SetErrno("Failed to read"); - return 0; - } - + size_t nbytes = reader.Read(ptr, read_size); offset += nbytes; - return (size_t)nbytes; + return nbytes; } const InputPlugin input_plugin_file = { diff -Nru mpd-0.19.21/src/input/plugins/FileInputPlugin.hxx mpd-0.20.9/src/input/plugins/FileInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/FileInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/FileInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,17 +20,16 @@ #ifndef MPD_INPUT_FILE_HXX #define MPD_INPUT_FILE_HXX -class InputStream; +#include "input/Ptr.hxx" + class Path; class Mutex; class Cond; -class Error; extern const struct InputPlugin input_plugin_file; -InputStream * +InputStreamPtr OpenFileInputStream(Path path, - Mutex &mutex, Cond &cond, - Error &error); + Mutex &mutex, Cond &cond); #endif diff -Nru mpd-0.19.21/src/input/plugins/MmsInputPlugin.cxx mpd-0.20.9/src/input/plugins/MmsInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/MmsInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/MmsInputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,12 +21,13 @@ #include "MmsInputPlugin.hxx" #include "input/ThreadInputStream.hxx" #include "input/InputPlugin.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "system/Error.hxx" +#include "util/StringCompare.hxx" #include +#include + static constexpr size_t MMS_BUFFER_SIZE = 256 * 1024; class MmsInputStream final : public ThreadInputStream { @@ -39,27 +40,23 @@ } protected: - virtual bool Open(gcc_unused Error &error) override; - virtual size_t ThreadRead(void *ptr, size_t size, - Error &error) override; + virtual void Open() override; + virtual size_t ThreadRead(void *ptr, size_t size) override; void Close() override { mmsx_close(mms); } }; -static constexpr Domain mms_domain("mms"); - -bool -MmsInputStream::Open(Error &error) +void +MmsInputStream::Open() { Unlock(); mms = mmsx_connect(nullptr, nullptr, GetURI(), 128 * 1024); if (mms == nullptr) { Lock(); - error.Set(mms_domain, "mmsx_connect() failed"); - return false; + throw std::runtime_error("mmsx_connect() failed"); } Lock(); @@ -67,13 +64,11 @@ /* TODO: is this correct? at least this selects the ffmpeg decoder, which seems to work fine */ SetMimeType("audio/x-ms-wma"); - return true; } static InputStream * input_mms_open(const char *url, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { if (!StringStartsWith(url, "mms://") && !StringStartsWith(url, "mmsh://") && @@ -82,15 +77,12 @@ return nullptr; auto m = new MmsInputStream(url, mutex, cond); - auto is = m->Start(error); - if (is == nullptr) - delete m; - - return is; + m->Start(); + return m; } size_t -MmsInputStream::ThreadRead(void *ptr, size_t read_size, Error &error) +MmsInputStream::ThreadRead(void *ptr, size_t read_size) { /* unfortunately, mmsx_read() blocks until the whole buffer has been filled; to avoid big latencies, limit the size of @@ -102,7 +94,7 @@ int nbytes = mmsx_read(nullptr, mms, (char *)ptr, read_size); if (nbytes <= 0) { if (nbytes < 0) - error.SetErrno("mmsx_read() failed"); + throw MakeErrno("mmsx_read() failed"); return 0; } diff -Nru mpd-0.19.21/src/input/plugins/MmsInputPlugin.hxx mpd-0.20.9/src/input/plugins/MmsInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/MmsInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/MmsInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/NfsInputPlugin.cxx mpd-0.20.9/src/input/plugins/NfsInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/NfsInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/NfsInputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,20 +21,11 @@ #include "NfsInputPlugin.hxx" #include "../AsyncInputStream.hxx" #include "../InputPlugin.hxx" -#include "lib/nfs/Domain.hxx" #include "lib/nfs/Glue.hxx" #include "lib/nfs/FileReader.hxx" -#include "util/HugeAllocator.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" - -extern "C" { -#include -} +#include "util/StringCompare.hxx" #include -#include -#include /** * Do not buffer more than this number of bytes. It should be a @@ -54,11 +45,9 @@ bool reconnect_on_resume, reconnecting; public: - NfsInputStream(const char *_uri, - Mutex &_mutex, Cond &_cond, - void *_buffer) + NfsInputStream(const char *_uri, Mutex &_mutex, Cond &_cond) :AsyncInputStream(_uri, _mutex, _cond, - _buffer, NFS_MAX_BUFFERED, + NFS_MAX_BUFFERED, NFS_RESUME_AT), reconnect_on_resume(false), reconnecting(false) {} @@ -66,14 +55,14 @@ DeferClose(); } - bool Open(Error &error) { + void Open() { assert(!IsReady()); - return NfsFileReader::Open(GetURI(), error); + NfsFileReader::Open(GetURI()); } private: - bool DoRead(); + void DoRead(); protected: /* virtual methods from AsyncInputStream */ @@ -84,38 +73,34 @@ /* virtual methods from NfsFileReader */ void OnNfsFileOpen(uint64_t size) override; void OnNfsFileRead(const void *data, size_t size) override; - void OnNfsFileError(Error &&error) override; + void OnNfsFileError(std::exception_ptr &&e) override; }; -bool +void NfsInputStream::DoRead() { assert(NfsFileReader::IsIdle()); int64_t remaining = size - next_offset; if (remaining <= 0) - return true; + return; const size_t buffer_space = GetBufferSpace(); if (buffer_space == 0) { Pause(); - return true; + return; } size_t nbytes = std::min(std::min(remaining, 32768), buffer_space); - mutex.unlock(); - Error error; - bool success = NfsFileReader::Read(next_offset, nbytes, error); - mutex.lock(); - - if (!success) { - PostponeError(std::move(error)); - return false; + try { + const ScopeUnlock unlock(mutex); + NfsFileReader::Read(next_offset, nbytes); + } catch (...) { + postponed_exception = std::current_exception(); + cond.broadcast(); } - - return true; } void @@ -128,17 +113,10 @@ reconnect_on_resume = false; reconnecting = true; - mutex.unlock(); - NfsFileReader::Close(); + ScopeUnlock unlock(mutex); - Error error; - bool success = NfsFileReader::Open(GetURI(), error); - mutex.lock(); - - if (!success) { - postponed_error = std::move(error); - cond.broadcast(); - } + NfsFileReader::Close(); + NfsFileReader::Open(GetURI()); return; } @@ -151,9 +129,10 @@ void NfsInputStream::DoSeek(offset_type new_offset) { - mutex.unlock(); - NfsFileReader::CancelRead(); - mutex.lock(); + { + const ScopeUnlock unlock(mutex); + NfsFileReader::CancelRead(); + } next_offset = offset = new_offset; SeekDone(); @@ -163,7 +142,7 @@ void NfsInputStream::OnNfsFileOpen(uint64_t _size) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (reconnecting) { /* reconnect has succeeded */ @@ -183,7 +162,7 @@ void NfsInputStream::OnNfsFileRead(const void *data, size_t data_size) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(!IsBufferFull()); assert(IsBufferFull() == (GetBufferSpace() == 0)); AppendToBuffer(data, data_size); @@ -194,9 +173,9 @@ } void -NfsInputStream::OnNfsFileError(Error &&error) +NfsInputStream::OnNfsFileError(std::exception_ptr &&e) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (IsPaused()) { /* while we're paused, don't report this error to the @@ -209,7 +188,7 @@ return; } - postponed_error = std::move(error); + postponed_exception = std::move(e); if (IsSeekPending()) SeekDone(); @@ -224,11 +203,10 @@ * */ -static InputPlugin::InitResult -input_nfs_init(const config_param &, Error &) +static void +input_nfs_init(const ConfigBlock &) { nfs_init(); - return InputPlugin::InitResult::SUCCESS; } static void @@ -239,22 +217,17 @@ static InputStream * input_nfs_open(const char *uri, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { if (!StringStartsWith(uri, "nfs://")) return nullptr; - void *buffer = HugeAllocate(NFS_MAX_BUFFERED); - if (buffer == nullptr) { - error.Set(nfs_domain, "Out of memory"); - return nullptr; - } - - NfsInputStream *is = new NfsInputStream(uri, mutex, cond, buffer); - if (!is->Open(error)) { + NfsInputStream *is = new NfsInputStream(uri, mutex, cond); + try { + is->Open(); + } catch (...) { delete is; - return nullptr; + throw; } return is; diff -Nru mpd-0.19.21/src/input/plugins/NfsInputPlugin.hxx mpd-0.20.9/src/input/plugins/NfsInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/NfsInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/NfsInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/RewindInputPlugin.cxx mpd-0.20.9/src/input/plugins/RewindInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/RewindInputPlugin.cxx 2016-08-05 16:14:49.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/RewindInputPlugin.cxx 2017-05-08 14:37:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -59,12 +59,12 @@ ProxyInputStream::Update(); } - bool IsEOF() override { + bool IsEOF() noexcept override { return !ReadingFromBuffer() && ProxyInputStream::IsEOF(); } - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; private: /** @@ -77,7 +77,7 @@ }; size_t -RewindInputStream::Read(void *ptr, size_t read_size, Error &error) +RewindInputStream::Read(void *ptr, size_t read_size) { if (ReadingFromBuffer()) { /* buffered read */ @@ -96,7 +96,7 @@ } else { /* pass method call to underlying stream */ - size_t nbytes = input.Read(ptr, read_size, error); + size_t nbytes = input.Read(ptr, read_size); if (input.GetOffset() > (offset_type)sizeof(buffer)) /* disable buffering */ @@ -116,9 +116,8 @@ } } -bool -RewindInputStream::Seek(offset_type new_offset, - Error &error) +void +RewindInputStream::Seek(offset_type new_offset) { assert(IsReady()); @@ -131,14 +130,12 @@ head = (size_t)new_offset; offset = new_offset; - - return true; } else { /* disable the buffer, because input has left the buffered range now */ tail = 0; - return ProxyInputStream::Seek(new_offset, error); + ProxyInputStream::Seek(new_offset); } } diff -Nru mpd-0.19.21/src/input/plugins/RewindInputPlugin.hxx mpd-0.20.9/src/input/plugins/RewindInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/RewindInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/RewindInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/plugins/SmbclientInputPlugin.cxx mpd-0.20.9/src/input/plugins/SmbclientInputPlugin.cxx --- mpd-0.19.21/src/input/plugins/SmbclientInputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/SmbclientInputPlugin.cxx 2017-05-08 14:41:56.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,11 +23,14 @@ #include "lib/smbclient/Mutex.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "PluginUnavailable.hxx" +#include "system/Error.hxx" +#include "util/StringCompare.hxx" #include +#include + class SmbclientInputStream final : public InputStream { SMBCCTX *ctx; int fd; @@ -52,12 +55,12 @@ /* virtual methods from InputStream */ - bool IsEOF() override { + bool IsEOF() noexcept override { return offset >= size; } - size_t Read(void *ptr, size_t size, Error &error) override; - bool Seek(offset_type offset, Error &error) override; + size_t Read(void *ptr, size_t size) override; + void Seek(offset_type offset) override; }; /* @@ -65,90 +68,83 @@ * */ -static InputPlugin::InitResult -input_smbclient_init(gcc_unused const config_param ¶m, Error &error) +static void +input_smbclient_init(gcc_unused const ConfigBlock &block) { - if (!SmbclientInit(error)) - return InputPlugin::InitResult::UNAVAILABLE; + try { + SmbclientInit(); + } catch (const std::runtime_error &e) { + // TODO: use std::throw_with_nested()? + throw PluginUnavailable(e.what()); + } // TODO: create one global SMBCCTX here? - // TODO: evaluate config_param, call smbc_setOption*() - - return InputPlugin::InitResult::SUCCESS; + // TODO: evaluate ConfigBlock, call smbc_setOption*() } static InputStream * input_smbclient_open(const char *uri, - Mutex &mutex, Cond &cond, - Error &error) + Mutex &mutex, Cond &cond) { if (!StringStartsWith(uri, "smb://")) return nullptr; - const ScopeLock protect(smbclient_mutex); + const std::lock_guard protect(smbclient_mutex); SMBCCTX *ctx = smbc_new_context(); - if (ctx == nullptr) { - error.SetErrno("smbc_new_context() failed"); - return nullptr; - } + if (ctx == nullptr) + throw MakeErrno("smbc_new_context() failed"); SMBCCTX *ctx2 = smbc_init_context(ctx); if (ctx2 == nullptr) { - error.SetErrno("smbc_init_context() failed"); + int e = errno; smbc_free_context(ctx, 1); - return nullptr; + throw MakeErrno(e, "smbc_init_context() failed"); } ctx = ctx2; int fd = smbc_open(uri, O_RDONLY, 0); if (fd < 0) { - error.SetErrno("smbc_open() failed"); + int e = errno; smbc_free_context(ctx, 1); - return nullptr; + throw MakeErrno(e, "smbc_open() failed"); } struct stat st; if (smbc_fstat(fd, &st) < 0) { - error.SetErrno("smbc_fstat() failed"); - smbc_close(fd); + int e = errno; smbc_free_context(ctx, 1); - return nullptr; + throw MakeErrno(e, "smbc_fstat() failed"); } return new SmbclientInputStream(uri, mutex, cond, ctx, fd, st); } size_t -SmbclientInputStream::Read(void *ptr, size_t read_size, Error &error) +SmbclientInputStream::Read(void *ptr, size_t read_size) { smbclient_mutex.lock(); ssize_t nbytes = smbc_read(fd, ptr, read_size); smbclient_mutex.unlock(); - if (nbytes < 0) { - error.SetErrno("smbc_read() failed"); - nbytes = 0; - } + if (nbytes < 0) + throw MakeErrno("smbc_read() failed"); offset += nbytes; return nbytes; } -bool -SmbclientInputStream::Seek(offset_type new_offset, Error &error) +void +SmbclientInputStream::Seek(offset_type new_offset) { smbclient_mutex.lock(); off_t result = smbc_lseek(fd, new_offset, SEEK_SET); smbclient_mutex.unlock(); - if (result < 0) { - error.SetErrno("smbc_lseek() failed"); - return false; - } + if (result < 0) + throw MakeErrno("smbc_lseek() failed"); offset = result; - return true; } const InputPlugin input_plugin_smbclient = { diff -Nru mpd-0.19.21/src/input/plugins/SmbclientInputPlugin.hxx mpd-0.20.9/src/input/plugins/SmbclientInputPlugin.hxx --- mpd-0.19.21/src/input/plugins/SmbclientInputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/plugins/SmbclientInputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/ProxyInputStream.cxx mpd-0.20.9/src/input/ProxyInputStream.cxx --- mpd-0.19.21/src/input/ProxyInputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/ProxyInputStream.cxx 2017-05-08 14:35:09.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,9 +19,6 @@ #include "config.h" #include "ProxyInputStream.hxx" -#include "tag/Tag.hxx" - -#include ProxyInputStream::ProxyInputStream(InputStream *_input) :InputStream(_input->GetURI(), _input->mutex, _input->cond), @@ -52,10 +49,10 @@ } } -bool -ProxyInputStream::Check(Error &error) +void +ProxyInputStream::Check() { - return input.Check(error); + input.Check(); } void @@ -65,16 +62,15 @@ CopyAttributes(); } -bool -ProxyInputStream::Seek(offset_type new_offset, Error &error) +void +ProxyInputStream::Seek(offset_type new_offset) { - bool success = input.Seek(new_offset, error); + input.Seek(new_offset); CopyAttributes(); - return success; } bool -ProxyInputStream::IsEOF() +ProxyInputStream::IsEOF() noexcept { return input.IsEOF(); } @@ -86,15 +82,15 @@ } bool -ProxyInputStream::IsAvailable() +ProxyInputStream::IsAvailable() noexcept { return input.IsAvailable(); } size_t -ProxyInputStream::Read(void *ptr, size_t read_size, Error &error) +ProxyInputStream::Read(void *ptr, size_t read_size) { - size_t nbytes = input.Read(ptr, read_size, error); + size_t nbytes = input.Read(ptr, read_size); CopyAttributes(); return nbytes; } diff -Nru mpd-0.19.21/src/input/ProxyInputStream.hxx mpd-0.20.9/src/input/ProxyInputStream.hxx --- mpd-0.19.21/src/input/ProxyInputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/ProxyInputStream.hxx 2017-05-08 14:36:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -43,13 +43,13 @@ ProxyInputStream &operator=(const ProxyInputStream &) = delete; /* virtual methods from InputStream */ - bool Check(Error &error) override; + void Check() override; void Update() override; - bool Seek(offset_type new_offset, Error &error) override; - bool IsEOF() override; + void Seek(offset_type new_offset) override; + bool IsEOF() noexcept override; Tag *ReadTag() override; - bool IsAvailable() override; - size_t Read(void *ptr, size_t read_size, Error &error) override; + bool IsAvailable() noexcept override; + size_t Read(void *ptr, size_t read_size) override; protected: /** diff -Nru mpd-0.19.21/src/input/Ptr.hxx mpd-0.20.9/src/input/Ptr.hxx --- mpd-0.19.21/src/input/Ptr.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/input/Ptr.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_INPUT_STREAM_PTR_HXX +#define MPD_INPUT_STREAM_PTR_HXX + +#include + +class InputStream; + +typedef std::unique_ptr InputStreamPtr; + +#endif diff -Nru mpd-0.19.21/src/input/Reader.cxx mpd-0.20.9/src/input/Reader.cxx --- mpd-0.19.21/src/input/Reader.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/input/Reader.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Reader.hxx" +#include "InputStream.hxx" + +size_t +InputStreamReader::Read(void *data, size_t size) +{ + size_t nbytes = is.LockRead(data, size); + assert(nbytes > 0 || is.IsEOF()); + + return nbytes; +} diff -Nru mpd-0.19.21/src/input/Reader.hxx mpd-0.20.9/src/input/Reader.hxx --- mpd-0.19.21/src/input/Reader.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/input/Reader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_INPUT_READER_HXX +#define MPD_INPUT_READER_HXX + +#include "check.h" +#include "fs/io/Reader.hxx" +#include "Compiler.h" + +struct Decoder; +class InputStream; + +/** + * A #Reader implementation which forwards all read calls to + * InputStream::Read() and logs errors. + */ +class InputStreamReader final : public Reader { + InputStream &is; + +public: + explicit InputStreamReader(InputStream &_is) + :is(_is) {} + + /* virtual methods from class Reader */ + size_t Read(void *data, size_t size) override; +}; + +#endif diff -Nru mpd-0.19.21/src/input/Registry.cxx mpd-0.20.9/src/input/Registry.cxx --- mpd-0.19.21/src/input/Registry.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Registry.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ #include "util/Macros.hxx" #include "plugins/FileInputPlugin.hxx" -#ifdef HAVE_ALSA +#ifdef ENABLE_ALSA #include "plugins/AlsaInputPlugin.hxx" #endif @@ -34,7 +34,7 @@ #include "plugins/CurlInputPlugin.hxx" #endif -#ifdef HAVE_FFMPEG +#ifdef ENABLE_FFMPEG #include "plugins/FfmpegInputPlugin.hxx" #endif @@ -56,7 +56,7 @@ const InputPlugin *const input_plugins[] = { &input_plugin_file, -#ifdef HAVE_ALSA +#ifdef ENABLE_ALSA &input_plugin_alsa, #endif #ifdef ENABLE_ARCHIVE @@ -65,7 +65,7 @@ #ifdef ENABLE_CURL &input_plugin_curl, #endif -#ifdef HAVE_FFMPEG +#ifdef ENABLE_FFMPEG &input_plugin_ffmpeg, #endif #ifdef ENABLE_SMBCLIENT diff -Nru mpd-0.19.21/src/input/Registry.hxx mpd-0.20.9/src/input/Registry.hxx --- mpd-0.19.21/src/input/Registry.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/Registry.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/input/TextInputStream.cxx mpd-0.20.9/src/input/TextInputStream.cxx --- mpd-0.19.21/src/input/TextInputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/TextInputStream.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,12 +20,18 @@ #include "config.h" #include "TextInputStream.hxx" #include "InputStream.hxx" -#include "util/Error.hxx" #include "util/TextFile.hxx" #include "Log.hxx" +#include + #include +TextInputStream::TextInputStream(InputStreamPtr &&_is) + :is(std::move(_is)) {} + +TextInputStream::~TextInputStream() {} + char * TextInputStream::ReadLine() { @@ -53,15 +59,17 @@ character */ --dest.size; - Error error; - size_t nbytes = is.LockRead(dest.data, dest.size, error); - if (nbytes > 0) - buffer.Append(nbytes); - else if (error.IsDefined()) { - LogError(error); + size_t nbytes; + + try { + nbytes = is->LockRead(dest.data, dest.size); + } catch (const std::runtime_error &e) { + LogError(e); return nullptr; } + buffer.Append(nbytes); + line = ReadBufferedLine(buffer); if (line != nullptr) return line; diff -Nru mpd-0.19.21/src/input/TextInputStream.hxx mpd-0.20.9/src/input/TextInputStream.hxx --- mpd-0.19.21/src/input/TextInputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/TextInputStream.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,27 +20,30 @@ #ifndef MPD_TEXT_INPUT_STREAM_HXX #define MPD_TEXT_INPUT_STREAM_HXX +#include "input/Ptr.hxx" #include "util/StaticFifoBuffer.hxx" -class InputStream; - class TextInputStream { - InputStream &is; + InputStreamPtr is; StaticFifoBuffer buffer; public: /** - * Wraps an existing #input_stream object into a #TextInputStream, + * Wraps an existing #InputStream object into a #TextInputStream, * to read its contents as text lines. * - * @param _is an open #input_stream object + * @param _is an open #InputStream object */ - explicit TextInputStream(InputStream &_is) - :is(_is) {} + explicit TextInputStream(InputStreamPtr &&_is); + ~TextInputStream(); TextInputStream(const TextInputStream &) = delete; TextInputStream& operator=(const TextInputStream &) = delete; + InputStreamPtr &&StealInputStream() { + return std::move(is); + } + /** * Reads the next line from the stream with newline character stripped. * diff -Nru mpd-0.19.21/src/input/ThreadInputStream.cxx mpd-0.20.9/src/input/ThreadInputStream.cxx --- mpd-0.19.21/src/input/ThreadInputStream.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/ThreadInputStream.cxx 2017-05-08 14:36:55.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,10 +28,11 @@ ThreadInputStream::~ThreadInputStream() { - Lock(); - close = true; - wake_cond.signal(); - Unlock(); + { + const std::lock_guard lock(mutex); + close = true; + wake_cond.signal(); + } Cancel(); @@ -44,23 +45,16 @@ } } -InputStream * -ThreadInputStream::Start(Error &error) +void +ThreadInputStream::Start() { assert(buffer == nullptr); void *p = HugeAllocate(buffer_size); - if (p == nullptr) { - error.SetErrno(); - return nullptr; - } + assert(p != nullptr); buffer = new CircularBuffer((uint8_t *)p, buffer_size); - - if (!thread.Start(ThreadFunc, this, error)) - return nullptr; - - return this; + thread.Start(ThreadFunc, this); } inline void @@ -68,10 +62,13 @@ { FormatThreadName("input:%s", plugin); - Lock(); - if (!Open(postponed_error)) { + const std::lock_guard lock(mutex); + + try { + Open(); + } catch (...) { + postponed_exception = std::current_exception(); cond.broadcast(); - Unlock(); return; } @@ -79,23 +76,27 @@ SetReady(); while (!close) { - assert(!postponed_error.IsDefined()); + assert(!postponed_exception); auto w = buffer->Write(); if (w.IsEmpty()) { wake_cond.wait(mutex); } else { - Unlock(); + size_t nbytes; - Error error; - size_t nbytes = ThreadRead(w.data, w.size, error); + try { + const ScopeUnlock unlock(mutex); + nbytes = ThreadRead(w.data, w.size); + } catch (...) { + postponed_exception = std::current_exception(); + cond.broadcast(); + break; + } - Lock(); cond.broadcast(); if (nbytes == 0) { eof = true; - postponed_error = std::move(error); break; } @@ -103,8 +104,6 @@ } } - Unlock(); - Close(); } @@ -115,37 +114,31 @@ tis.ThreadFunc(); } -bool -ThreadInputStream::Check(Error &error) +void +ThreadInputStream::Check() { assert(!thread.IsInside()); - if (postponed_error.IsDefined()) { - error = std::move(postponed_error); - return false; - } - - return true; + if (postponed_exception) + std::rethrow_exception(postponed_exception); } bool -ThreadInputStream::IsAvailable() +ThreadInputStream::IsAvailable() noexcept { assert(!thread.IsInside()); - return !buffer->IsEmpty() || eof || postponed_error.IsDefined(); + return !buffer->IsEmpty() || eof || postponed_exception; } inline size_t -ThreadInputStream::Read(void *ptr, size_t read_size, Error &error) +ThreadInputStream::Read(void *ptr, size_t read_size) { assert(!thread.IsInside()); while (true) { - if (postponed_error.IsDefined()) { - error = std::move(postponed_error); - return 0; - } + if (postponed_exception) + std::rethrow_exception(postponed_exception); auto r = buffer->Read(); if (!r.IsEmpty()) { @@ -165,7 +158,7 @@ } bool -ThreadInputStream::IsEOF() +ThreadInputStream::IsEOF() noexcept { assert(!thread.IsInside()); diff -Nru mpd-0.19.21/src/input/ThreadInputStream.hxx mpd-0.20.9/src/input/ThreadInputStream.hxx --- mpd-0.19.21/src/input/ThreadInputStream.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/input/ThreadInputStream.hxx 2017-05-08 14:37:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,8 @@ #include "InputStream.hxx" #include "thread/Thread.hxx" #include "thread/Cond.hxx" -#include "util/Error.hxx" + +#include #include @@ -51,20 +52,20 @@ */ Cond wake_cond; - Error postponed_error; + std::exception_ptr postponed_exception; const size_t buffer_size; - CircularBuffer *buffer; + CircularBuffer *buffer = nullptr; /** * Shall the stream be closed? */ - bool close; + bool close = false; /** * Has the end of the stream been seen by the thread? */ - bool eof; + bool eof = false; public: ThreadInputStream(const char *_plugin, @@ -72,24 +73,20 @@ size_t _buffer_size) :InputStream(_uri, _mutex, _cond), plugin(_plugin), - buffer_size(_buffer_size), - buffer(nullptr), - close(false), eof(false) {} + buffer_size(_buffer_size) {} virtual ~ThreadInputStream(); /** * Initialize the object and start the thread. - * - * @return false on error */ - InputStream *Start(Error &error); + void Start(); /* virtual methods from InputStream */ - bool Check(Error &error) override final; - bool IsEOF() override final; - bool IsAvailable() override final; - size_t Read(void *ptr, size_t size, Error &error) override final; + void Check() override final; + bool IsEOF() noexcept final; + bool IsAvailable() noexcept final; + size_t Read(void *ptr, size_t size) override final; protected: void SetMimeType(const char *_mime) { @@ -107,9 +104,10 @@ * * The #InputStream is locked. Unlock/relock it if you do a * blocking operation. + * + * Throws std::runtime_error on error. */ - virtual bool Open(gcc_unused Error &error) { - return true; + virtual void Open() { } /** @@ -117,9 +115,11 @@ * * The #InputStream is not locked. * - * @return 0 on end-of-file or on error + * Throws std::runtime_error on error. + * + * @return 0 on end-of-file */ - virtual size_t ThreadRead(void *ptr, size_t size, Error &error) = 0; + virtual size_t ThreadRead(void *ptr, size_t size) = 0; /** * Optional deinitialization before leaving the thread. diff -Nru mpd-0.19.21/src/Instance.cxx mpd-0.20.9/src/Instance.cxx --- mpd-0.19.21/src/Instance.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Instance.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,37 +25,27 @@ #ifdef ENABLE_DATABASE #include "db/DatabaseError.hxx" -#include "db/LightSong.hxx" #ifdef ENABLE_SQLITE #include "sticker/StickerDatabase.hxx" #include "sticker/SongSticker.hxx" #endif +#endif -Database * -Instance::GetDatabase(Error &error) -{ - if (database == nullptr) - error.Set(db_domain, DB_DISABLED, "No database"); - return database; -} +#include -#endif +#ifdef ENABLE_DATABASE -void -Instance::TagModified() +const Database & +Instance::GetDatabaseOrThrow() const { - partition->TagModified(); -} + if (database == nullptr) + throw DatabaseError(DatabaseErrorCode::DISABLED, + "No database"); -void -Instance::SyncWithPlayer() -{ - partition->SyncWithPlayer(); + return *database; } -#ifdef ENABLE_DATABASE - void Instance::OnDatabaseModified() { @@ -65,22 +55,24 @@ stats_invalidate(); partition->DatabaseModified(*database); - idle_add(IDLE_DATABASE); } void -Instance::OnDatabaseSongRemoved(const LightSong &song) +Instance::OnDatabaseSongRemoved(const char *uri) { assert(database != nullptr); #ifdef ENABLE_SQLITE /* if the song has a sticker, remove it */ - if (sticker_enabled()) - sticker_song_delete(song); + if (sticker_enabled()) { + try { + sticker_song_delete(uri); + } catch (const std::runtime_error &) { + } + } #endif - const auto uri = song.GetURI(); - partition->DeleteSong(uri.c_str()); + partition->StaleSong(uri); } #endif @@ -90,13 +82,13 @@ void Instance::FoundNeighbor(gcc_unused const NeighborInfo &info) { - idle_add(IDLE_NEIGHBOR); + partition->EmitIdle(IDLE_NEIGHBOR); } void Instance::LostNeighbor(gcc_unused const NeighborInfo &info) { - idle_add(IDLE_NEIGHBOR); + partition->EmitIdle(IDLE_NEIGHBOR); } #endif diff -Nru mpd-0.19.21/src/Instance.hxx mpd-0.20.9/src/Instance.hxx --- mpd-0.19.21/src/Instance.hxx 2016-10-20 10:22:59.000000000 +0000 +++ mpd-0.20.9/src/Instance.hxx 2017-05-08 13:25:38.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,8 @@ #define MPD_INSTANCE_HXX #include "check.h" +#include "event/Loop.hxx" +#include "event/MaskMonitor.hxx" #include "Compiler.h" #ifdef ENABLE_NEIGHBOR_PLUGINS @@ -35,14 +37,22 @@ class UpdateService; #endif -class EventLoop; -class Error; class ClientList; struct Partition; +class StateFile; + +/** + * A utility class which, when used as the first base class, ensures + * that the #EventLoop gets initialized before the other base classes. + */ +struct EventLoopHolder { + EventLoop event_loop; +}; struct Instance final + : EventLoopHolder #if defined(ENABLE_DATABASE) || defined(ENABLE_NEIGHBOR_PLUGINS) - : + , #endif #ifdef ENABLE_DATABASE public DatabaseListener @@ -54,7 +64,7 @@ public NeighborListener #endif { - EventLoop *event_loop; + MaskMonitor idle_monitor; #ifdef ENABLE_NEIGHBOR_PLUGINS NeighborGlue *neighbors; @@ -67,20 +77,29 @@ * This is really a #CompositeStorage. To avoid heavy include * dependencies, we declare it as just #Storage. */ - Storage *storage; + Storage *storage = nullptr; - UpdateService *update; + UpdateService *update = nullptr; #endif ClientList *client_list; Partition *partition; - Instance() { -#ifdef ENABLE_DATABASE - storage = nullptr; - update = nullptr; -#endif + StateFile *state_file; + + Instance() + :idle_monitor(event_loop, BIND_THIS_METHOD(OnIdle)), state_file(nullptr) {} + + /** + * Initiate shutdown. Wrapper for EventLoop::Break(). + */ + void Shutdown() { + event_loop.Break(); + } + + void EmitIdle(unsigned mask) { + idle_monitor.OrMask(mask); } #ifdef ENABLE_DATABASE @@ -89,31 +108,32 @@ * if this MPD configuration has no database (no * music_directory was configured). */ - Database *GetDatabase(Error &error); -#endif - - /** - * A tag in the play queue has been modified by the player - * thread. Propagate the change to all subsystems. - */ - void TagModified(); + Database *GetDatabase() { + return database; + } /** - * Synchronize the player with the play queue. + * Returns the global #Database instance. Throws + * DatabaseError if this MPD configuration has no database (no + * music_directory was configured). */ - void SyncWithPlayer(); + const Database &GetDatabaseOrThrow() const; +#endif private: #ifdef ENABLE_DATABASE - virtual void OnDatabaseModified() override; - virtual void OnDatabaseSongRemoved(const LightSong &song) override; + void OnDatabaseModified() override; + void OnDatabaseSongRemoved(const char *uri) override; #endif #ifdef ENABLE_NEIGHBOR_PLUGINS /* virtual methods from class NeighborListener */ - virtual void FoundNeighbor(const NeighborInfo &info) override; - virtual void LostNeighbor(const NeighborInfo &info) override; + void FoundNeighbor(const NeighborInfo &info) override; + void LostNeighbor(const NeighborInfo &info) override; #endif + + /* callback for #idle_monitor */ + void OnIdle(unsigned mask); }; #endif diff -Nru mpd-0.19.21/src/IOThread.cxx mpd-0.20.9/src/IOThread.cxx --- mpd-0.19.21/src/IOThread.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/IOThread.cxx 2017-05-08 13:20:38.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,8 +24,6 @@ #include "thread/Thread.hxx" #include "thread/Name.hxx" #include "event/Loop.hxx" -#include "system/FatalError.hxx" -#include "util/Error.hxx" #include @@ -74,11 +72,8 @@ assert(io.loop != nullptr); assert(!io.thread.IsDefined()); - const ScopeLock protect(io.mutex); - - Error error; - if (!io.thread.Start(io_thread_func, nullptr, error)) - FatalError(error); + const std::lock_guard protect(io.mutex); + io.thread.Start(io_thread_func, nullptr); } void @@ -101,7 +96,7 @@ } EventLoop & -io_thread_get() +io_thread_get() noexcept { assert(io.loop != nullptr); @@ -109,7 +104,7 @@ } bool -io_thread_inside(void) +io_thread_inside() noexcept { return io.thread.IsInside(); } diff -Nru mpd-0.19.21/src/IOThread.hxx mpd-0.20.9/src/IOThread.hxx --- mpd-0.19.21/src/IOThread.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/IOThread.hxx 2017-05-08 13:20:43.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,7 @@ class EventLoop; void -io_thread_init(void); +io_thread_init(); void io_thread_start(); @@ -36,7 +36,7 @@ * only. */ void -io_thread_run(void); +io_thread_run(); /** * Ask the I/O thread to quit, but does not wait for it. Usually, you @@ -44,20 +44,20 @@ * includes this. */ void -io_thread_quit(void); +io_thread_quit(); void -io_thread_deinit(void); +io_thread_deinit(); gcc_const EventLoop & -io_thread_get(); +io_thread_get() noexcept; /** * Is the current thread the I/O thread? */ gcc_pure bool -io_thread_inside(void); +io_thread_inside() noexcept; #endif diff -Nru mpd-0.19.21/src/java/Class.hxx mpd-0.20.9/src/java/Class.hxx --- mpd-0.19.21/src/java/Class.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Class.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/Exception.hxx mpd-0.20.9/src/java/Exception.hxx --- mpd-0.19.21/src/java/Exception.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Exception.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Max Kellermann + * Copyright (C) 2010-2012 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/File.cxx mpd-0.20.9/src/java/File.cxx --- mpd-0.19.21/src/java/File.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/File.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 Max Kellermann + * Copyright (C) 2010-2014 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/File.hxx mpd-0.20.9/src/java/File.hxx --- mpd-0.19.21/src/java/File.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/File.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 Max Kellermann + * Copyright (C) 2010-2014 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/Global.cxx mpd-0.20.9/src/java/Global.cxx --- mpd-0.19.21/src/java/Global.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Global.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/Global.hxx mpd-0.20.9/src/java/Global.hxx --- mpd-0.19.21/src/java/Global.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Global.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/Object.hxx mpd-0.20.9/src/java/Object.hxx --- mpd-0.19.21/src/java/Object.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Object.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/Ref.hxx mpd-0.20.9/src/java/Ref.hxx --- mpd-0.19.21/src/java/Ref.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/Ref.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/String.cxx mpd-0.20.9/src/java/String.cxx --- mpd-0.19.21/src/java/String.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/String.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/java/String.hxx mpd-0.20.9/src/java/String.hxx --- mpd-0.19.21/src/java/String.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/java/String.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Max Kellermann + * Copyright (C) 2010-2011 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/lib/curl/Easy.hxx mpd-0.20.9/src/lib/curl/Easy.hxx --- mpd-0.19.21/src/lib/curl/Easy.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Easy.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_EASY_HXX +#define CURL_EASY_HXX + +#include + +#include +#include +#include + +/** + * An OO wrapper for a "CURL*" (a libCURL "easy" handle). + */ +class CurlEasy { + CURL *handle = nullptr; + +public: + /** + * Allocate a new CURL*. + * + * Throws std::runtime_error on error. + */ + CurlEasy() + :handle(curl_easy_init()) + { + if (handle == nullptr) + throw std::runtime_error("curl_easy_init() failed"); + } + + /** + * Create an empty instance. + */ + CurlEasy(std::nullptr_t):handle(nullptr) {} + + CurlEasy(CurlEasy &&src):handle(std::exchange(src.handle, nullptr)) {} + + ~CurlEasy() { + if (handle != nullptr) + curl_easy_cleanup(handle); + } + + operator bool() const { + return handle != nullptr; + } + + CurlEasy &operator=(CurlEasy &&src) { + std::swap(handle, src.handle); + return *this; + } + + CURL *Get() { + return handle; + } + + template + void SetOption(CURLoption option, T value) { + CURLcode code = curl_easy_setopt(handle, option, value); + if (code != CURLE_OK) + throw std::runtime_error(curl_easy_strerror(code)); + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Global.cxx mpd-0.20.9/src/lib/curl/Global.cxx --- mpd-0.19.21/src/lib/curl/Global.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Global.cxx 2017-06-04 10:34:25.000000000 +0000 @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2008-2016 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Global.hxx" +#include "Request.hxx" +#include "IOThread.hxx" +#include "Log.hxx" +#include "event/SocketMonitor.hxx" +#include "util/RuntimeError.hxx" +#include "util/Domain.hxx" + +static constexpr Domain curlm_domain("curlm"); + +/** + * Monitor for one socket created by CURL. + */ +class CurlSocket final : SocketMonitor { + CurlGlobal &global; + +public: + CurlSocket(CurlGlobal &_global, EventLoop &_loop, int _fd) + :SocketMonitor(_fd, _loop), global(_global) {} + + ~CurlSocket() { + /* TODO: sometimes, CURL uses CURL_POLL_REMOVE after + closing the socket, and sometimes, it uses + CURL_POLL_REMOVE just to move the (still open) + connection to the pool; in the first case, + Abandon() would be most appropriate, but it breaks + the second case - is that a CURL bug? is there a + better solution? */ + } + + /** + * Callback function for CURLMOPT_SOCKETFUNCTION. + */ + static int SocketFunction(CURL *easy, + curl_socket_t s, int action, + void *userp, void *socketp) noexcept; + + virtual bool OnSocketReady(unsigned flags) override; + +private: + static constexpr int FlagsToCurlCSelect(unsigned flags) { + return (flags & (READ | HANGUP) ? CURL_CSELECT_IN : 0) | + (flags & WRITE ? CURL_CSELECT_OUT : 0) | + (flags & ERROR ? CURL_CSELECT_ERR : 0); + } + + gcc_const + static unsigned CurlPollToFlags(int action) noexcept { + switch (action) { + case CURL_POLL_NONE: + return 0; + + case CURL_POLL_IN: + return READ; + + case CURL_POLL_OUT: + return WRITE; + + case CURL_POLL_INOUT: + return READ|WRITE; + } + + assert(false); + gcc_unreachable(); + } +}; + +CurlGlobal::CurlGlobal(EventLoop &_loop) + :TimeoutMonitor(_loop), DeferredMonitor(_loop) +{ + multi.SetOption(CURLMOPT_SOCKETFUNCTION, CurlSocket::SocketFunction); + multi.SetOption(CURLMOPT_SOCKETDATA, this); + + multi.SetOption(CURLMOPT_TIMERFUNCTION, TimerFunction); + multi.SetOption(CURLMOPT_TIMERDATA, this); +} + +int +CurlSocket::SocketFunction(gcc_unused CURL *easy, + curl_socket_t s, int action, + void *userp, void *socketp) noexcept { + auto &global = *(CurlGlobal *)userp; + CurlSocket *cs = (CurlSocket *)socketp; + + assert(io_thread_inside()); + + if (action == CURL_POLL_REMOVE) { + delete cs; + return 0; + } + + if (cs == nullptr) { + cs = new CurlSocket(global, io_thread_get(), s); + global.Assign(s, *cs); + } else { +#ifdef USE_EPOLL + /* when using epoll, we need to unregister the socket + each time this callback is invoked, because older + CURL versions may omit the CURL_POLL_REMOVE call + when the socket has been closed and recreated with + the same file number (bug found in CURL 7.26, CURL + 7.33 not affected); in that case, epoll refuses the + EPOLL_CTL_MOD because it does not know the new + socket yet */ + cs->Cancel(); +#endif + } + + unsigned flags = CurlPollToFlags(action); + if (flags != 0) + cs->Schedule(flags); + return 0; +} + +bool +CurlSocket::OnSocketReady(unsigned flags) +{ + assert(io_thread_inside()); + + global.SocketAction(Get(), FlagsToCurlCSelect(flags)); + return true; +} + +/** + * Runs in the I/O thread. No lock needed. + * + * Throws std::runtime_error on error. + */ +void +CurlGlobal::Add(CURL *easy, CurlRequest &request) +{ + assert(io_thread_inside()); + assert(easy != nullptr); + + curl_easy_setopt(easy, CURLOPT_PRIVATE, &request); + + CURLMcode mcode = curl_multi_add_handle(multi.Get(), easy); + if (mcode != CURLM_OK) + throw FormatRuntimeError("curl_multi_add_handle() failed: %s", + curl_multi_strerror(mcode)); + + InvalidateSockets(); +} + +void +CurlGlobal::Remove(CURL *easy) +{ + assert(io_thread_inside()); + assert(easy != nullptr); + + curl_multi_remove_handle(multi.Get(), easy); + + InvalidateSockets(); +} + +static CurlRequest * +ToRequest(CURL *easy) +{ + void *p; + CURLcode code = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &p); + if (code != CURLE_OK) + return nullptr; + + return (CurlRequest *)p; +} + +/** + * Check for finished HTTP responses. + * + * Runs in the I/O thread. The caller must not hold locks. + */ +inline void +CurlGlobal::ReadInfo() +{ + assert(io_thread_inside()); + + CURLMsg *msg; + int msgs_in_queue; + + while ((msg = curl_multi_info_read(multi.Get(), + &msgs_in_queue)) != nullptr) { + if (msg->msg == CURLMSG_DONE) { + auto *request = ToRequest(msg->easy_handle); + if (request != nullptr) + request->Done(msg->data.result); + } + } +} + +inline void +CurlGlobal::UpdateTimeout(long timeout_ms) +{ + if (timeout_ms < 0) { + TimeoutMonitor::Cancel(); + return; + } + + if (timeout_ms < 10) + /* CURL 7.21.1 likes to report "timeout=0", which + means we're running in a busy loop. Quite a bad + idea to waste so much CPU. Let's use a lower limit + of 10ms. */ + timeout_ms = 10; + + TimeoutMonitor::Schedule(std::chrono::milliseconds(timeout_ms)); +} + +int +CurlGlobal::TimerFunction(gcc_unused CURLM *_global, long timeout_ms, void *userp) +{ + auto &global = *(CurlGlobal *)userp; + assert(_global == global.multi.Get()); + + global.UpdateTimeout(timeout_ms); + return 0; +} + +void +CurlGlobal::OnTimeout() +{ + SocketAction(CURL_SOCKET_TIMEOUT, 0); +} + +void +CurlGlobal::SocketAction(curl_socket_t fd, int ev_bitmask) +{ + int running_handles; + CURLMcode mcode = curl_multi_socket_action(multi.Get(), fd, ev_bitmask, + &running_handles); + if (mcode != CURLM_OK) + FormatError(curlm_domain, + "curl_multi_socket_action() failed: %s", + curl_multi_strerror(mcode)); + + DeferredMonitor::Schedule(); +} + +void +CurlGlobal::RunDeferred() +{ + ReadInfo(); +} diff -Nru mpd-0.19.21/src/lib/curl/Global.hxx mpd-0.20.9/src/lib/curl/Global.hxx --- mpd-0.19.21/src/lib/curl/Global.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Global.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008-2016 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_GLOBAL_HXX +#define CURL_GLOBAL_HXX + +#include "Multi.hxx" +#include "event/TimeoutMonitor.hxx" +#include "event/DeferredMonitor.hxx" + +class CurlSocket; +class CurlRequest; + +/** + * Manager for the global CURLM object. + */ +class CurlGlobal final : TimeoutMonitor, DeferredMonitor { + CurlMulti multi; + +public: + explicit CurlGlobal(EventLoop &_loop); + + using TimeoutMonitor::GetEventLoop; + + void Add(CURL *easy, CurlRequest &request); + void Remove(CURL *easy); + + /** + * Check for finished HTTP responses. + * + * Runs in the I/O thread. The caller must not hold locks. + */ + void ReadInfo(); + + void Assign(curl_socket_t fd, CurlSocket &cs) { + curl_multi_assign(multi.Get(), fd, &cs); + } + + void SocketAction(curl_socket_t fd, int ev_bitmask); + + void InvalidateSockets() { + SocketAction(CURL_SOCKET_TIMEOUT, 0); + } + + /** + * This is a kludge to allow pausing/resuming a stream with + * libcurl < 7.32.0. Read the curl_easy_pause manpage for + * more information. + */ + void ResumeSockets() { + int running_handles; + curl_multi_socket_all(multi.Get(), &running_handles); + } + +private: + void UpdateTimeout(long timeout_ms); + static int TimerFunction(CURLM *global, long timeout_ms, void *userp); + + /* virtual methods from class TimeoutMonitor */ + void OnTimeout() override; + + /* virtual methods from class DeferredMonitor */ + void RunDeferred() override; +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Handler.hxx mpd-0.20.9/src/lib/curl/Handler.hxx --- mpd-0.19.21/src/lib/curl/Handler.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Handler.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_HANDLER_HXX +#define CURL_HANDLER_HXX + +#include "util/ConstBuffer.hxx" + +#include +#include +#include + +class CurlResponseHandler { +public: + virtual void OnHeaders(unsigned status, + std::multimap &&headers) = 0; + virtual void OnData(ConstBuffer data) = 0; + virtual void OnEnd() = 0; + virtual void OnError(std::exception_ptr e) = 0; +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Multi.hxx mpd-0.20.9/src/lib/curl/Multi.hxx --- mpd-0.19.21/src/lib/curl/Multi.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Multi.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_MULTI_HXX +#define CURL_MULTI_HXX + +#include + +#include +#include +#include + +/** + * An OO wrapper for a "CURLM*" (a libCURL "multi" handle). + */ +class CurlMulti { + CURLM *handle = nullptr; + +public: + /** + * Allocate a new CURLM*. + * + * Throws std::runtime_error on error. + */ + CurlMulti() + :handle(curl_multi_init()) + { + if (handle == nullptr) + throw std::runtime_error("curl_multi_init() failed"); + } + + /** + * Create an empty instance. + */ + CurlMulti(std::nullptr_t):handle(nullptr) {} + + CurlMulti(CurlMulti &&src):handle(std::exchange(src.handle, nullptr)) {} + + ~CurlMulti() { + if (handle != nullptr) + curl_multi_cleanup(handle); + } + + operator bool() const { + return handle != nullptr; + } + + CurlMulti &operator=(CurlMulti &&src) { + std::swap(handle, src.handle); + return *this; + } + + CURLM *Get() { + return handle; + } + + template + void SetOption(CURLMoption option, T value) { + auto code = curl_multi_setopt(handle, option, value); + if (code != CURLM_OK) + throw std::runtime_error(curl_multi_strerror(code)); + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Request.cxx mpd-0.20.9/src/lib/curl/Request.cxx --- mpd-0.19.21/src/lib/curl/Request.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Request.cxx 2017-05-08 14:39:19.000000000 +0000 @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2008-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Request.hxx" +#include "Global.hxx" +#include "Version.hxx" +#include "Handler.hxx" +#include "util/RuntimeError.hxx" +#include "util/StringUtil.hxx" +#include "util/StringView.hxx" +#include "util/CharUtil.hxx" + +#include + +#include + +#include +#include + +CurlRequest::CurlRequest(CurlGlobal &_global, const char *url, + CurlResponseHandler &_handler) + :DeferredMonitor(_global.GetEventLoop()), + global(_global), handler(_handler) +{ + error_buffer[0] = 0; + + easy.SetOption(CURLOPT_PRIVATE, (void *)this); + easy.SetOption(CURLOPT_USERAGENT, "Music Player Daemon " VERSION); + easy.SetOption(CURLOPT_HEADERFUNCTION, _HeaderFunction); + easy.SetOption(CURLOPT_WRITEHEADER, this); + easy.SetOption(CURLOPT_WRITEFUNCTION, WriteFunction); + easy.SetOption(CURLOPT_WRITEDATA, this); + easy.SetOption(CURLOPT_NETRC, 1l); + easy.SetOption(CURLOPT_ERRORBUFFER, error_buffer); + easy.SetOption(CURLOPT_NOPROGRESS, 1l); + easy.SetOption(CURLOPT_NOSIGNAL, 1l); + easy.SetOption(CURLOPT_CONNECTTIMEOUT, 10l); + easy.SetOption(CURLOPT_URL, url); +} + +CurlRequest::~CurlRequest() +{ + FreeEasy(); +} + +void +CurlRequest::Start() +{ + assert(!registered); + + global.Add(easy.Get(), *this); + registered = true; +} + +void +CurlRequest::Stop() +{ + if (!registered) + return; + + global.Remove(easy.Get()); + registered = false; +} + +void +CurlRequest::FreeEasy() +{ + if (!easy) + return; + + Stop(); + easy = nullptr; +} + +void +CurlRequest::Resume() +{ + assert(registered); + + curl_easy_pause(easy.Get(), CURLPAUSE_CONT); + + if (IsCurlOlderThan(0x072000)) + /* libcurl older than 7.32.0 does not update + its sockets after curl_easy_pause(); force + libcurl to do it now */ + global.ResumeSockets(); + + global.InvalidateSockets(); +} + +void +CurlRequest::FinishHeaders() +{ + if (state != State::HEADERS) + return; + + state = State::BODY; + + long status = 0; + curl_easy_getinfo(easy.Get(), CURLINFO_RESPONSE_CODE, &status); + + handler.OnHeaders(status, std::move(headers)); +} + +void +CurlRequest::FinishBody() +{ + FinishHeaders(); + + if (state != State::BODY) + return; + + state = State::CLOSED; + handler.OnEnd(); +} + +void +CurlRequest::Done(CURLcode result) +{ + Stop(); + + try { + if (result != CURLE_OK) { + StripRight(error_buffer); + const char *msg = error_buffer; + if (*msg == 0) + msg = curl_easy_strerror(result); + throw FormatRuntimeError("CURL failed: %s", msg); + } + } catch (...) { + state = State::CLOSED; + handler.OnError(std::current_exception()); + return; + } + + try { + FinishBody(); + } catch (...) { + state = State::CLOSED; + handler.OnError(std::current_exception()); + } +} + +gcc_pure +static bool +IsResponseBoundaryHeader(StringView s) noexcept +{ + return s.size > 5 && (memcmp(s.data, "HTTP/", 5) == 0 || + /* the proprietary "ICY 200 OK" is + emitted by Shoutcast */ + memcmp(s.data, "ICY 2", 5) == 0); +} + +inline void +CurlRequest::HeaderFunction(StringView s) +{ + if (state > State::HEADERS) + return; + + if (IsResponseBoundaryHeader(s)) { + /* this is the boundary to a new response, for example + after a redirect */ + headers.clear(); + return; + } + + const char *header = s.data; + const char *end = StripRight(header, header + s.size); + + const char *value = s.Find(':'); + if (value == nullptr) + return; + + std::string name(header, value); + std::transform(name.begin(), name.end(), name.begin(), ToLowerASCII); + + /* skip the colon */ + + ++value; + + /* strip the value */ + + value = StripLeft(value, end); + end = StripRight(value, end); + + headers.emplace(std::move(name), std::string(value, end)); +} + +size_t +CurlRequest::_HeaderFunction(void *ptr, size_t size, size_t nmemb, void *stream) +{ + CurlRequest &c = *(CurlRequest *)stream; + + size *= nmemb; + + c.HeaderFunction({(const char *)ptr, size}); + return size; +} + +inline size_t +CurlRequest::DataReceived(const void *ptr, size_t received_size) +{ + assert(received_size > 0); + + try { + FinishHeaders(); + handler.OnData({ptr, received_size}); + return received_size; + } catch (Pause) { + return CURL_WRITEFUNC_PAUSE; + } catch (...) { + state = State::CLOSED; + /* move the CurlResponseHandler::OnError() call into a + "safe" stack frame */ + postponed_error = std::current_exception(); + DeferredMonitor::Schedule(); + return CURL_WRITEFUNC_PAUSE; + } + +} + +size_t +CurlRequest::WriteFunction(void *ptr, size_t size, size_t nmemb, void *stream) +{ + CurlRequest &c = *(CurlRequest *)stream; + + size *= nmemb; + if (size == 0) + return 0; + + return c.DataReceived(ptr, size); +} + +void +CurlRequest::RunDeferred() +{ + assert(postponed_error); + + handler.OnError(postponed_error); +} diff -Nru mpd-0.19.21/src/lib/curl/Request.hxx mpd-0.20.9/src/lib/curl/Request.hxx --- mpd-0.19.21/src/lib/curl/Request.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Request.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2008-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_REQUEST_HXX +#define CURL_REQUEST_HXX + +#include "Easy.hxx" +#include "event/DeferredMonitor.hxx" + +#include +#include +#include + +struct StringView; +class CurlGlobal; +class CurlResponseHandler; + +class CurlRequest final : DeferredMonitor { + CurlGlobal &global; + + CurlResponseHandler &handler; + + /** the curl handle */ + CurlEasy easy; + + enum class State { + HEADERS, + BODY, + CLOSED, + } state = State::HEADERS; + + std::multimap headers; + + /** + * An exception caught by DataReceived(), which will be + * forwarded into a "safe" stack frame by + * DeferredMonitor::RunDeferred(). This works around the + * problem that libcurl crashes if you call + * curl_multi_remove_handle() from within the WRITEFUNCTION + * (i.e. DataReceived()). + */ + std::exception_ptr postponed_error; + + /** error message provided by libcurl */ + char error_buffer[CURL_ERROR_SIZE]; + + bool registered = false; + +public: + /** + * To start sending the request, call Start(). + */ + CurlRequest(CurlGlobal &_global, const char *url, + CurlResponseHandler &_handler); + ~CurlRequest(); + + CurlRequest(const CurlRequest &) = delete; + CurlRequest &operator=(const CurlRequest &) = delete; + + /** + * Register this request via CurlGlobal::Add(), which starts + * the request. + * + * This method must be called in the event loop thread. + */ + void Start(); + + /** + * Unregister this request via CurlGlobal::Remove(). + * + * This method must be called in the event loop thread. + */ + void Stop(); + + CURL *Get() { + return easy.Get(); + } + + template + void SetOption(CURLoption option, T value) { + easy.SetOption(option, value); + } + + /** + * CurlResponseHandler::OnData() shall throw this to pause the + * stream. Call Resume() to resume the transfer. + */ + struct Pause {}; + + void Resume(); + + /** + * A HTTP request is finished. Called by #CurlGlobal. + */ + void Done(CURLcode result); + +private: + /** + * Frees the current "libcurl easy" handle, and everything + * associated with it. + */ + void FreeEasy(); + + void FinishHeaders(); + void FinishBody(); + + size_t DataReceived(const void *ptr, size_t size); + + void HeaderFunction(StringView s); + + /** called by curl when new data is available */ + static size_t _HeaderFunction(void *ptr, size_t size, size_t nmemb, + void *stream); + + /** called by curl when new data is available */ + static size_t WriteFunction(void *ptr, size_t size, size_t nmemb, + void *stream); + + /* virtual methods from class DeferredMonitor */ + void RunDeferred() override; +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Slist.hxx mpd-0.20.9/src/lib/curl/Slist.hxx --- mpd-0.19.21/src/lib/curl/Slist.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Slist.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_SLIST_HXX +#define CURL_SLIST_HXX + +#include + +#include + +/** + * OO wrapper for "struct curl_slist *". + */ +class CurlSlist { + struct curl_slist *head = nullptr; + +public: + CurlSlist() = default; + + CurlSlist(CurlSlist &&src) + :head(std::exchange(src.head, nullptr)) {} + + ~CurlSlist() { + if (head != nullptr) + curl_slist_free_all(head); + } + + CurlSlist &operator=(CurlSlist &&src) { + std::swap(head, src.head); + return *this; + } + + struct curl_slist *Get() { + return head; + } + + void Clear() { + curl_slist_free_all(head); + head = nullptr; + } + + void Append(const char *value) { + auto *new_head = curl_slist_append(head, value); + if (new_head == nullptr) + throw std::runtime_error("curl_slist_append() failed"); + head = new_head; + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/curl/Version.cxx mpd-0.20.9/src/lib/curl/Version.cxx --- mpd-0.19.21/src/lib/curl/Version.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Version.cxx 2017-05-08 14:36:32.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Version.hxx" + +#include + +bool +IsCurlOlderThan(unsigned version_num) noexcept +{ + const auto *const info = curl_version_info(CURLVERSION_FIRST); + return info == nullptr || info->version_num < version_num; +} diff -Nru mpd-0.19.21/src/lib/curl/Version.hxx mpd-0.20.9/src/lib/curl/Version.hxx --- mpd-0.19.21/src/lib/curl/Version.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/curl/Version.hxx 2017-05-08 14:36:29.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_VERSION_HXX +#define CURL_VERSION_HXX + +#include "Compiler.h" + +gcc_const +bool +IsCurlOlderThan(unsigned version_num) noexcept; + +#endif diff -Nru mpd-0.19.21/src/lib/expat/ExpatParser.cxx mpd-0.20.9/src/lib/expat/ExpatParser.cxx --- mpd-0.19.21/src/lib/expat/ExpatParser.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/expat/ExpatParser.cxx 2017-05-08 14:54:39.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,59 +19,20 @@ #include "config.h" #include "ExpatParser.hxx" -#include "input/InputStream.hxx" #include "util/ASCII.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include -static constexpr Domain expat_domain("expat"); - void -ExpatParser::SetError(Error &error) -{ - XML_Error code = XML_GetErrorCode(parser); - error.Format(expat_domain, int(code), "XML parser failed: %s", - XML_ErrorString(code)); -} - -bool -ExpatParser::Parse(const char *data, size_t length, bool is_final, - Error &error) +ExpatParser::Parse(const char *data, size_t length, bool is_final) { - bool success = XML_Parse(parser, data, length, - is_final) == XML_STATUS_OK; - if (!success) - SetError(error); - - return success; -} - -bool -ExpatParser::Parse(InputStream &is, Error &error) -{ - assert(is.IsReady()); - - while (true) { - char buffer[4096]; - size_t nbytes = is.LockRead(buffer, sizeof(buffer), error); - if (nbytes == 0) - break; - - if (!Parse(buffer, nbytes, false, error)) - return false; - } - - if (error.IsDefined()) - return false; - - return Parse("", 0, true, error); + if (XML_Parse(parser, data, length, is_final) != XML_STATUS_OK) + throw ExpatError(parser); } const char * ExpatParser::GetAttribute(const XML_Char **atts, - const char *name) + const char *name) noexcept { for (unsigned i = 0; atts[i] != nullptr; i += 2) if (strcmp(atts[i], name) == 0) @@ -82,7 +43,7 @@ const char * ExpatParser::GetAttributeCase(const XML_Char **atts, - const char *name) + const char *name) noexcept { for (unsigned i = 0; atts[i] != nullptr; i += 2) if (StringEqualsCaseASCII(atts[i], name)) diff -Nru mpd-0.19.21/src/lib/expat/ExpatParser.hxx mpd-0.20.9/src/lib/expat/ExpatParser.hxx --- mpd-0.19.21/src/lib/expat/ExpatParser.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/expat/ExpatParser.hxx 2017-05-08 14:54:57.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,46 +25,64 @@ #include +#include + class InputStream; -class Error; + +class ExpatError final : public std::runtime_error { +public: + explicit ExpatError(XML_Error code) + :std::runtime_error(XML_ErrorString(code)) {} + + explicit ExpatError(XML_Parser parser) + :ExpatError(XML_GetErrorCode(parser)) {} +}; + +struct ExpatNamespaceSeparator { + char separator; +}; class ExpatParser final { const XML_Parser parser; public: - ExpatParser(void *userData) + explicit ExpatParser(void *userData) :parser(XML_ParserCreate(nullptr)) { XML_SetUserData(parser, userData); } + ExpatParser(ExpatNamespaceSeparator ns, void *userData) + :parser(XML_ParserCreateNS(nullptr, ns.separator)) { + XML_SetUserData(parser, userData); + } + ~ExpatParser() { XML_ParserFree(parser); } + ExpatParser(const ExpatParser &) = delete; + ExpatParser &operator=(const ExpatParser &) = delete; + void SetElementHandler(XML_StartElementHandler start, - XML_EndElementHandler end) { + XML_EndElementHandler end) noexcept { XML_SetElementHandler(parser, start, end); } - void SetCharacterDataHandler(XML_CharacterDataHandler charhndl) { + void SetCharacterDataHandler(XML_CharacterDataHandler charhndl) noexcept { XML_SetCharacterDataHandler(parser, charhndl); } - bool Parse(const char *data, size_t length, bool is_final, - Error &error); + void Parse(const char *data, size_t length, bool is_final); - bool Parse(InputStream &is, Error &error); + void Parse(InputStream &is); gcc_pure static const char *GetAttribute(const XML_Char **atts, - const char *name); + const char *name) noexcept; gcc_pure static const char *GetAttributeCase(const XML_Char **atts, - const char *name); - -private: - void SetError(Error &error); + const char *name) noexcept; }; /** @@ -80,24 +98,29 @@ parser.SetCharacterDataHandler(CharacterData); } - bool Parse(const char *data, size_t length, bool is_final, - Error &error) { - return parser.Parse(data, length, is_final, error); + explicit CommonExpatParser(ExpatNamespaceSeparator ns) + :parser(ns, this) { + parser.SetElementHandler(StartElement, EndElement); + parser.SetCharacterDataHandler(CharacterData); + } + + void Parse(const char *data, size_t length, bool is_final) { + parser.Parse(data, length, is_final); } - bool Parse(InputStream &is, Error &error) { - return parser.Parse(is, error); + void Parse(InputStream &is) { + parser.Parse(is); } gcc_pure static const char *GetAttribute(const XML_Char **atts, - const char *name) { + const char *name) noexcept { return ExpatParser::GetAttribute(atts, name); } gcc_pure static const char *GetAttributeCase(const XML_Char **atts, - const char *name) { + const char *name) noexcept { return ExpatParser::GetAttributeCase(atts, name); } diff -Nru mpd-0.19.21/src/lib/expat/StreamExpatParser.cxx mpd-0.20.9/src/lib/expat/StreamExpatParser.cxx --- mpd-0.19.21/src/lib/expat/StreamExpatParser.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/expat/StreamExpatParser.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ExpatParser.hxx" +#include "input/InputStream.hxx" + +void +ExpatParser::Parse(InputStream &is) +{ + assert(is.IsReady()); + + while (true) { + char buffer[4096]; + size_t nbytes = is.LockRead(buffer, sizeof(buffer)); + if (nbytes == 0) + break; + + Parse(buffer, nbytes, false); + } + + Parse("", 0, true); +} diff -Nru mpd-0.19.21/src/lib/ffmpeg/Buffer.hxx mpd-0.20.9/src/lib/ffmpeg/Buffer.hxx --- mpd-0.19.21/src/lib/ffmpeg/Buffer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Buffer.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -51,6 +51,7 @@ av_free(data); } + gcc_malloc void *Get(size_t min_size) { #ifdef HAVE_AV_FAST_MALLOC av_fast_malloc(&data, &size, min_size); diff -Nru mpd-0.19.21/src/lib/ffmpeg/Domain.cxx mpd-0.20.9/src/lib/ffmpeg/Domain.cxx --- mpd-0.19.21/src/lib/ffmpeg/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/Domain.hxx mpd-0.20.9/src/lib/ffmpeg/Domain.hxx --- mpd-0.19.21/src/lib/ffmpeg/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/Error.cxx mpd-0.20.9/src/lib/ffmpeg/Error.cxx --- mpd-0.19.21/src/lib/ffmpeg/Error.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Error.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,25 +19,24 @@ #include "config.h" #include "Error.hxx" -#include "Domain.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" extern "C" { #include } -void -SetFfmpegError(Error &error, int errnum) +std::runtime_error +MakeFfmpegError(int errnum) { char msg[256]; av_strerror(errnum, msg, sizeof(msg)); - error.Set(ffmpeg_domain, errnum, msg); + return std::runtime_error(msg); } -void -SetFfmpegError(Error &error, int errnum, const char *prefix) +std::runtime_error +MakeFfmpegError(int errnum, const char *prefix) { char msg[256]; av_strerror(errnum, msg, sizeof(msg)); - error.Format(ffmpeg_domain, errnum, "%s: %s", prefix, msg); + return FormatRuntimeError("%s: %s", prefix, msg); } diff -Nru mpd-0.19.21/src/lib/ffmpeg/Error.hxx mpd-0.20.9/src/lib/ffmpeg/Error.hxx --- mpd-0.19.21/src/lib/ffmpeg/Error.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Error.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,12 +20,12 @@ #ifndef MPD_FFMPEG_ERROR_HXX #define MPD_FFMPEG_ERROR_HXX -class Error; +#include -void -SetFfmpegError(Error &error, int errnum); +std::runtime_error +MakeFfmpegError(int errnum); -void -SetFfmpegError(Error &error, int errnum, const char *prefix); +std::runtime_error +MakeFfmpegError(int errnum, const char *prefix); #endif diff -Nru mpd-0.19.21/src/lib/ffmpeg/Init.cxx mpd-0.20.9/src/lib/ffmpeg/Init.cxx --- mpd-0.19.21/src/lib/ffmpeg/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Init.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/Init.hxx mpd-0.20.9/src/lib/ffmpeg/Init.hxx --- mpd-0.19.21/src/lib/ffmpeg/Init.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Init.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/LogCallback.cxx mpd-0.20.9/src/lib/ffmpeg/LogCallback.cxx --- mpd-0.19.21/src/lib/ffmpeg/LogCallback.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/LogCallback.cxx 2017-05-08 15:21:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ gcc_const static LogLevel -FfmpegImportLogLevel(int level) +FfmpegImportLogLevel(int level) noexcept { if (level <= AV_LOG_FATAL) return LogLevel::ERROR; diff -Nru mpd-0.19.21/src/lib/ffmpeg/LogCallback.hxx mpd-0.20.9/src/lib/ffmpeg/LogCallback.hxx --- mpd-0.19.21/src/lib/ffmpeg/LogCallback.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/LogCallback.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/LogError.cxx mpd-0.20.9/src/lib/ffmpeg/LogError.cxx --- mpd-0.19.21/src/lib/ffmpeg/LogError.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/LogError.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/LogError.hxx mpd-0.20.9/src/lib/ffmpeg/LogError.hxx --- mpd-0.19.21/src/lib/ffmpeg/LogError.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/LogError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/ffmpeg/Time.hxx mpd-0.20.9/src/lib/ffmpeg/Time.hxx --- mpd-0.19.21/src/lib/ffmpeg/Time.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/ffmpeg/Time.hxx 2017-05-08 15:09:00.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -36,9 +36,12 @@ #undef SampleFormat #endif +/** + * Convert a FFmpeg time stamp to a floating point value (in seconds). + */ gcc_const static inline double -FfmpegTimeToDouble(int64_t t, const AVRational time_base) +FfmpegTimeToDouble(int64_t t, const AVRational time_base) noexcept { assert(t != (int64_t)AV_NOPTS_VALUE); @@ -46,6 +49,9 @@ / (double)1024; } +/** + * Convert a std::ratio to a #AVRational. + */ template static inline constexpr AVRational RatioToAVRational() @@ -58,7 +64,7 @@ */ gcc_const static inline SongTime -FromFfmpegTime(int64_t t, const AVRational time_base) +FromFfmpegTime(int64_t t, const AVRational time_base) noexcept { assert(t != (int64_t)AV_NOPTS_VALUE); @@ -71,7 +77,7 @@ */ gcc_const static inline SignedSongTime -FromFfmpegTimeChecked(int64_t t, const AVRational time_base) +FromFfmpegTimeChecked(int64_t t, const AVRational time_base) noexcept { return t != (int64_t)AV_NOPTS_VALUE ? SignedSongTime(FromFfmpegTime(t, time_base)) @@ -83,7 +89,7 @@ */ gcc_const static inline int64_t -ToFfmpegTime(SongTime t, const AVRational time_base) +ToFfmpegTime(SongTime t, const AVRational time_base) noexcept { return av_rescale_q(t.count(), RatioToAVRational(), diff -Nru mpd-0.19.21/src/lib/icu/Collate.cxx mpd-0.20.9/src/lib/icu/Collate.cxx --- mpd-0.19.21/src/lib/icu/Collate.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Collate.cxx 2017-05-08 13:37:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,26 +19,32 @@ #include "config.h" #include "Collate.hxx" +#include "util/AllocatedString.hxx" #ifdef HAVE_ICU -#include "Error.hxx" -#include "util/WritableBuffer.hxx" +#include "Util.hxx" +#include "util/AllocatedArray.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include #include -#elif defined(HAVE_GLIB) -#include #else #include #include #endif +#ifdef WIN32 +#include "Win32.hxx" +#include "util/AllocatedString.hxx" +#include +#endif + +#include +#include + #include #include -#include #ifdef HAVE_ICU static UCollator *collator; @@ -46,80 +52,31 @@ #ifdef HAVE_ICU -bool -IcuCollateInit(Error &error) +void +IcuCollateInit() { assert(collator == nullptr); - assert(!error.IsDefined()); UErrorCode code = U_ZERO_ERROR; collator = ucol_open("", &code); - if (collator == nullptr) { - error.Format(icu_domain, int(code), - "ucol_open() failed: %s", u_errorName(code)); - return false; - } - - return true; + if (collator == nullptr) + throw FormatRuntimeError("ucol_open() failed: %s", + u_errorName(code)); } void -IcuCollateFinish() +IcuCollateFinish() noexcept { assert(collator != nullptr); ucol_close(collator); } -static WritableBuffer -UCharFromUTF8(const char *src) -{ - assert(src != nullptr); - - const size_t src_length = strlen(src); - const size_t dest_capacity = src_length; - UChar *dest = new UChar[dest_capacity]; - - UErrorCode error_code = U_ZERO_ERROR; - int32_t dest_length; - u_strFromUTF8(dest, dest_capacity, &dest_length, - src, src_length, - &error_code); - if (U_FAILURE(error_code)) { - delete[] dest; - return nullptr; - } - - return { dest, size_t(dest_length) }; -} - -static WritableBuffer -UCharToUTF8(ConstBuffer src) -{ - assert(!src.IsNull()); - - /* worst-case estimate */ - size_t dest_capacity = 4 * src.size; - - char *dest = new char[dest_capacity]; - - UErrorCode error_code = U_ZERO_ERROR; - int32_t dest_length; - u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size, - &error_code); - if (U_FAILURE(error_code)) { - delete[] dest; - return nullptr; - } - - return { dest, size_t(dest_length) }; -} - #endif gcc_pure int -IcuCollate(const char *a, const char *b) +IcuCollate(const char *a, const char *b) noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ @@ -136,30 +93,58 @@ #else /* fall back to ucol_strcoll() */ - const auto au = UCharFromUTF8(a); - const auto bu = UCharFromUTF8(b); + try { + const auto au = UCharFromUTF8(a); + const auto bu = UCharFromUTF8(b); + + return ucol_strcoll(collator, au.begin(), au.size(), + bu.begin(), bu.size()); + } catch (const std::runtime_error &) { + /* fall back to plain strcasecmp() */ + return strcasecmp(a, b); + } +#endif - int result = !au.IsNull() && !bu.IsNull() - ? (int)ucol_strcoll(collator, au.data, au.size, - bu.data, bu.size) - : strcasecmp(a, b); +#elif defined(WIN32) + AllocatedString wa = nullptr, wb = nullptr; - delete[] au.data; - delete[] bu.data; + try { + wa = MultiByteToWideChar(CP_UTF8, a); + } catch (const std::runtime_error &) { + try { + wb = MultiByteToWideChar(CP_UTF8, b); + return -1; + } catch (const std::runtime_error &) { + return 0; + } + } - return result; -#endif + try { + wb = MultiByteToWideChar(CP_UTF8, b); + } catch (const std::runtime_error &) { + return 1; + } -#elif defined(HAVE_GLIB) - return g_utf8_collate(a, b); + auto result = CompareStringEx(LOCALE_NAME_INVARIANT, + LINGUISTIC_IGNORECASE, + wa.c_str(), -1, + wb.c_str(), -1, + nullptr, nullptr, 0); + if (result != 0) + /* "To maintain the C runtime convention of comparing + strings, the value 2 can be subtracted from a + nonzero return value." */ + result -= 2; + + return result; #else - return strcasecmp(a, b); + return strcoll(a, b); #endif } -std::string +AllocatedString<> IcuCaseFold(const char *src) -{ +try { #ifdef HAVE_ICU assert(collator != nullptr); #if !CLANG_CHECK_VERSION(3,6) @@ -169,37 +154,57 @@ const auto u = UCharFromUTF8(src); if (u.IsNull()) - return std::string(src); + return AllocatedString<>::Duplicate(src); - size_t folded_capacity = u.size * 2u; - UChar *folded = new UChar[folded_capacity]; + AllocatedArray folded(u.size() * 2u); UErrorCode error_code = U_ZERO_ERROR; - size_t folded_length = u_strFoldCase(folded, folded_capacity, - u.data, u.size, - U_FOLD_CASE_DEFAULT, - &error_code); - delete[] u.data; - if (folded_length == 0 || error_code != U_ZERO_ERROR) { - delete[] folded; - return std::string(src); - } + size_t folded_length = u_strFoldCase(folded.begin(), folded.size(), + u.begin(), u.size(), + U_FOLD_CASE_DEFAULT, + &error_code); + if (folded_length == 0 || error_code != U_ZERO_ERROR) + return AllocatedString<>::Duplicate(src); + + folded.SetSize(folded_length); + return UCharToUTF8({folded.begin(), folded.size()}); + +#elif defined(WIN32) + const auto u = MultiByteToWideChar(CP_UTF8, src); + + const int size = LCMapStringEx(LOCALE_NAME_INVARIANT, + LCMAP_SORTKEY|LINGUISTIC_IGNORECASE, + u.c_str(), -1, nullptr, 0, + nullptr, nullptr, 0); + if (size <= 0) + return AllocatedString<>::Duplicate(src); + + std::unique_ptr buffer(new wchar_t[size]); + if (LCMapStringEx(LOCALE_NAME_INVARIANT, + LCMAP_SORTKEY|LINGUISTIC_IGNORECASE, + u.c_str(), -1, buffer.get(), size, + nullptr, nullptr, 0) <= 0) + return AllocatedString<>::Duplicate(src); + + return WideCharToMultiByte(CP_UTF8, buffer.get()); - auto result2 = UCharToUTF8({folded, folded_length}); - delete[] folded; - if (result2.IsNull()) - return std::string(src); - - std::string result(result2.data, result2.size); - delete[] result2.data; -#elif defined(HAVE_GLIB) - char *tmp = g_utf8_casefold(src, -1); - std::string result(tmp); - g_free(tmp); #else - std::string result(src); - std::transform(result.begin(), result.end(), result.begin(), tolower); + size_t size = strlen(src) + 1; + std::unique_ptr buffer(new char[size]); + size_t nbytes = strxfrm(buffer.get(), src, size); + if (nbytes >= size) { + /* buffer too small - reallocate and try again */ + buffer.reset(); + size = nbytes + 1; + buffer.reset(new char[size]); + nbytes = strxfrm(buffer.get(), src, size); + } + + assert(nbytes < size); + assert(buffer[nbytes] == 0); + + return AllocatedString<>::Donate(buffer.release()); #endif - return result; +} catch (const std::runtime_error &) { + return AllocatedString<>::Duplicate(src); } - diff -Nru mpd-0.19.21/src/lib/icu/Collate.hxx mpd-0.20.9/src/lib/icu/Collate.hxx --- mpd-0.19.21/src/lib/icu/Collate.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Collate.hxx 2017-05-08 13:37:12.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,22 +23,23 @@ #include "check.h" #include "Compiler.h" -#include +template class AllocatedString; -class Error; - -bool -IcuCollateInit(Error &error); +/** + * Throws #std::runtime_error on error. + */ +void +IcuCollateInit(); void -IcuCollateFinish(); +IcuCollateFinish() noexcept; gcc_pure gcc_nonnull_all int -IcuCollate(const char *a, const char *b); +IcuCollate(const char *a, const char *b) noexcept; -gcc_pure gcc_nonnull_all -std::string +gcc_nonnull_all +AllocatedString IcuCaseFold(const char *src); #endif diff -Nru mpd-0.19.21/src/lib/icu/Converter.cxx mpd-0.20.9/src/lib/icu/Converter.cxx --- mpd-0.19.21/src/lib/icu/Converter.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Converter.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,162 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Converter.hxx" +#include "util/Macros.hxx" +#include "util/AllocatedString.hxx" +#include "util/AllocatedArray.hxx" +#include "util/ConstBuffer.hxx" +#include "util/FormatString.hxx" + +#include + +#include + +#ifdef HAVE_ICU +#include "Util.hxx" +#include +#elif defined(HAVE_ICONV) +#include "system/Error.hxx" +#endif + +#ifdef HAVE_ICU + +IcuConverter::~IcuConverter() +{ + ucnv_close(converter); +} + +#endif + +#ifdef HAVE_ICU_CONVERTER + +IcuConverter * +IcuConverter::Create(const char *charset) +{ +#ifdef HAVE_ICU + UErrorCode code = U_ZERO_ERROR; + UConverter *converter = ucnv_open(charset, &code); + if (converter == nullptr) + throw std::runtime_error(FormatString("Failed to initialize charset '%s': %s", + charset, u_errorName(code)).c_str()); + + return new IcuConverter(converter); +#elif defined(HAVE_ICONV) + iconv_t to = iconv_open("utf-8", charset); + iconv_t from = iconv_open(charset, "utf-8"); + if (to == (iconv_t)-1 || from == (iconv_t)-1) { + int e = errno; + if (to != (iconv_t)-1) + iconv_close(to); + if (from != (iconv_t)-1) + iconv_close(from); + throw FormatErrno(e, "Failed to initialize charset '%s'", + charset); + } + + return new IcuConverter(to, from); +#endif +} + +#ifdef HAVE_ICU +#elif defined(HAVE_ICONV) + +static AllocatedString +DoConvert(iconv_t conv, const char *src) +{ + // TODO: dynamic buffer? + char buffer[4096]; + char *in = const_cast(src); + char *out = buffer; + size_t in_left = strlen(src); + size_t out_left = sizeof(buffer); + + size_t n = iconv(conv, &in, &in_left, &out, &out_left); + + if (n == static_cast(-1)) + throw MakeErrno("Charset conversion failed"); + + if (in_left > 0) + throw std::runtime_error("Charset conversion failed"); + + return AllocatedString<>::Duplicate(buffer, sizeof(buffer) - out_left); +} + +#endif + +AllocatedString +IcuConverter::ToUTF8(const char *s) const +{ +#ifdef HAVE_ICU + const std::lock_guard protect(mutex); + + ucnv_resetToUnicode(converter); + + // TODO: dynamic buffer? + UChar buffer[4096], *target = buffer; + const char *source = s; + + UErrorCode code = U_ZERO_ERROR; + + ucnv_toUnicode(converter, &target, buffer + ARRAY_SIZE(buffer), + &source, source + strlen(source), + nullptr, true, &code); + if (code != U_ZERO_ERROR) + throw std::runtime_error(FormatString("Failed to convert to Unicode: %s", + u_errorName(code)).c_str()); + + const size_t target_length = target - buffer; + return UCharToUTF8({buffer, target_length}); +#elif defined(HAVE_ICONV) + return DoConvert(to_utf8, s); +#endif +} + +AllocatedString +IcuConverter::FromUTF8(const char *s) const +{ +#ifdef HAVE_ICU + const std::lock_guard protect(mutex); + + const auto u = UCharFromUTF8(s); + + ucnv_resetFromUnicode(converter); + + // TODO: dynamic buffer? + char buffer[4096], *target = buffer; + const UChar *source = u.begin(); + UErrorCode code = U_ZERO_ERROR; + + ucnv_fromUnicode(converter, &target, buffer + ARRAY_SIZE(buffer), + &source, u.end(), + nullptr, true, &code); + + if (code != U_ZERO_ERROR) + throw std::runtime_error(FormatString("Failed to convert from Unicode: %s", + u_errorName(code)).c_str()); + + return AllocatedString<>::Duplicate(buffer, target); + +#elif defined(HAVE_ICONV) + return DoConvert(from_utf8, s); +#endif +} + +#endif diff -Nru mpd-0.19.21/src/lib/icu/Converter.hxx mpd-0.20.9/src/lib/icu/Converter.hxx --- mpd-0.19.21/src/lib/icu/Converter.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Converter.hxx 2017-05-08 14:22:13.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ICU_CONVERTER_HXX +#define MPD_ICU_CONVERTER_HXX + +#include "check.h" +#include "Compiler.h" + +#ifdef HAVE_ICU +#include "thread/Mutex.hxx" +#define HAVE_ICU_CONVERTER +#elif defined(HAVE_ICONV) +#include +#define HAVE_ICU_CONVERTER +#endif + +#ifdef HAVE_ICU_CONVERTER + +#ifdef HAVE_ICU +struct UConverter; +#endif + +template class AllocatedString; + +/** + * This class can convert strings with a certain character set to and + * from UTF-8. + */ +class IcuConverter { +#ifdef HAVE_ICU + /** + * ICU's UConverter class is not thread-safe. This mutex + * serializes simultaneous calls. + */ + mutable Mutex mutex; + + UConverter *const converter; + + IcuConverter(UConverter *_converter):converter(_converter) {} +#elif defined(HAVE_ICONV) + const iconv_t to_utf8, from_utf8; + + IcuConverter(iconv_t _to, iconv_t _from) + :to_utf8(_to), from_utf8(_from) {} +#endif + +public: +#ifdef HAVE_ICU + ~IcuConverter(); +#elif defined(HAVE_ICONV) + ~IcuConverter() { + iconv_close(to_utf8); + iconv_close(from_utf8); + } +#endif + + /** + * Throws std::runtime_error on error. + */ + static IcuConverter *Create(const char *charset); + + /** + * Convert the string to UTF-8. + * + * Throws std::runtime_error on error. + */ + gcc_nonnull_all + AllocatedString ToUTF8(const char *s) const; + + /** + * Convert the string from UTF-8. + * + * Throws std::runtime_error on error. + */ + gcc_nonnull_all + AllocatedString FromUTF8(const char *s) const; +}; + +#endif + +#endif diff -Nru mpd-0.19.21/src/lib/icu/Error.cxx mpd-0.20.9/src/lib/icu/Error.cxx --- mpd-0.19.21/src/lib/icu/Error.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Error.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Error.hxx" -#include "util/Domain.hxx" - -const Domain icu_domain("icu"); diff -Nru mpd-0.19.21/src/lib/icu/Error.hxx mpd-0.20.9/src/lib/icu/Error.hxx --- mpd-0.19.21/src/lib/icu/Error.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Error.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_ICU_ERROR_HXX -#define MPD_ICU_ERROR_HXX - -#include "check.h" - -class Domain; - -extern const Domain icu_domain; - -#endif diff -Nru mpd-0.19.21/src/lib/icu/Init.cxx mpd-0.20.9/src/lib/icu/Init.cxx --- mpd-0.19.21/src/lib/icu/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Init.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,24 +19,21 @@ #include "config.h" #include "Init.hxx" -#include "Error.hxx" #include "Collate.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include -bool -IcuInit(Error &error) +void +IcuInit() { UErrorCode code = U_ZERO_ERROR; u_init(&code); - if (U_FAILURE(code)) { - error.Format(icu_domain, int(code), - "u_init() failed: %s", u_errorName(code)); - return false; - } + if (U_FAILURE(code)) + throw FormatRuntimeError("u_init() failed: %s", + u_errorName(code)); - return IcuCollateInit(error); + IcuCollateInit(); } void diff -Nru mpd-0.19.21/src/lib/icu/Init.hxx mpd-0.20.9/src/lib/icu/Init.hxx --- mpd-0.19.21/src/lib/icu/Init.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Init.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,19 +22,17 @@ #include "check.h" -class Error; - #ifdef HAVE_ICU -bool -IcuInit(Error &error); +void +IcuInit(); void IcuFinish(); #else -static inline bool IcuInit(Error &) { return true; } +static inline void IcuInit() {} static inline void IcuFinish() {} #endif diff -Nru mpd-0.19.21/src/lib/icu/Util.cxx mpd-0.20.9/src/lib/icu/Util.cxx --- mpd-0.19.21/src/lib/icu/Util.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Util.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Util.hxx" +#include "util/AllocatedString.hxx" +#include "util/AllocatedArray.hxx" +#include "util/WritableBuffer.hxx" +#include "util/ConstBuffer.hxx" + +#include + +#include +#include + +#include +#include + +AllocatedArray +UCharFromUTF8(const char *src) +{ + assert(src != nullptr); + + const size_t src_length = strlen(src); + const size_t dest_capacity = src_length; + AllocatedArray dest(dest_capacity); + + UErrorCode error_code = U_ZERO_ERROR; + int32_t dest_length; + u_strFromUTF8(dest.begin(), dest_capacity, &dest_length, + src, src_length, + &error_code); + if (U_FAILURE(error_code)) + throw std::runtime_error(u_errorName(error_code)); + + dest.SetSize(dest_length); + return dest; +} + +AllocatedString<> +UCharToUTF8(ConstBuffer src) +{ + assert(!src.IsNull()); + + /* worst-case estimate */ + size_t dest_capacity = 4 * src.size; + + std::unique_ptr dest(new char[dest_capacity + 1]); + + UErrorCode error_code = U_ZERO_ERROR; + int32_t dest_length; + u_strToUTF8(dest.get(), dest_capacity, &dest_length, + src.data, src.size, + &error_code); + if (U_FAILURE(error_code)) + throw std::runtime_error(u_errorName(error_code)); + + dest[dest_length] = 0; + return AllocatedString<>::Donate(dest.release()); +} diff -Nru mpd-0.19.21/src/lib/icu/Util.hxx mpd-0.20.9/src/lib/icu/Util.hxx --- mpd-0.19.21/src/lib/icu/Util.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Util.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ICU_UTIL_HXX +#define MPD_ICU_UTIL_HXX + +#include "check.h" + +#include + +template struct ConstBuffer; +template class AllocatedArray; +template class AllocatedString; + +/** + * Wrapper for u_strFromUTF8(). + * + * Throws std::runtime_error on error. + */ +AllocatedArray +UCharFromUTF8(const char *src); + +/** + * Wrapper for u_strToUTF8(). + * + * Throws std::runtime_error on error. + */ +AllocatedString +UCharToUTF8(ConstBuffer src); + +#endif diff -Nru mpd-0.19.21/src/lib/icu/Win32.cxx mpd-0.20.9/src/lib/icu/Win32.cxx --- mpd-0.19.21/src/lib/icu/Win32.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Win32.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Win32.hxx" +#include "system/Error.hxx" +#include "util/AllocatedString.hxx" + +#include + +#include + +AllocatedString +WideCharToMultiByte(unsigned code_page, const wchar_t *src) +{ + int length = WideCharToMultiByte(code_page, 0, src, -1, nullptr, 0, + nullptr, nullptr); + if (length <= 0) + throw MakeLastError("Failed to convert from Unicode"); + + std::unique_ptr buffer(new char[length]); + length = WideCharToMultiByte(code_page, 0, src, -1, + buffer.get(), length, + nullptr, nullptr); + if (length <= 0) + throw MakeLastError("Failed to convert from Unicode"); + + return AllocatedString::Donate(buffer.release()); +} + +AllocatedString +MultiByteToWideChar(unsigned code_page, const char *src) +{ + int length = MultiByteToWideChar(code_page, 0, src, -1, nullptr, 0); + if (length <= 0) + throw MakeLastError("Failed to convert to Unicode"); + + std::unique_ptr buffer(new wchar_t[length]); + length = MultiByteToWideChar(code_page, 0, src, -1, + buffer.get(), length); + if (length <= 0) + throw MakeLastError("Failed to convert to Unicode"); + + return AllocatedString::Donate(buffer.release()); +} diff -Nru mpd-0.19.21/src/lib/icu/Win32.hxx mpd-0.20.9/src/lib/icu/Win32.hxx --- mpd-0.19.21/src/lib/icu/Win32.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/icu/Win32.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ICU_WIN32_HXX +#define MPD_ICU_WIN32_HXX + +#include "check.h" +#include "Compiler.h" + +#include + +template class AllocatedString; + +/** + * Throws std::system_error on error. + */ +gcc_pure gcc_nonnull_all +AllocatedString +WideCharToMultiByte(unsigned code_page, const wchar_t *src); + +/** + * Throws std::system_error on error. + */ +gcc_pure gcc_nonnull_all +AllocatedString +MultiByteToWideChar(unsigned code_page, const char *src); + +#endif diff -Nru mpd-0.19.21/src/lib/nfs/Base.cxx mpd-0.20.9/src/lib/nfs/Base.cxx --- mpd-0.19.21/src/lib/nfs/Base.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Base.cxx 2017-05-08 14:39:12.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -46,7 +46,7 @@ } const char * -nfs_check_base(const char *server, const char *path) +nfs_check_base(const char *server, const char *path) noexcept { assert(server != nullptr); assert(path != nullptr); diff -Nru mpd-0.19.21/src/lib/nfs/Base.hxx mpd-0.20.9/src/lib/nfs/Base.hxx --- mpd-0.19.21/src/lib/nfs/Base.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Base.hxx 2017-05-08 14:39:09.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -41,6 +41,6 @@ */ gcc_pure const char * -nfs_check_base(const char *server, const char *path); +nfs_check_base(const char *server, const char *path) noexcept; #endif diff -Nru mpd-0.19.21/src/lib/nfs/Blocking.cxx mpd-0.20.9/src/lib/nfs/Blocking.cxx --- mpd-0.19.21/src/lib/nfs/Blocking.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Blocking.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,12 +20,12 @@ #include "config.h" #include "Blocking.hxx" #include "Connection.hxx" -#include "Domain.hxx" #include "event/Call.hxx" -#include "util/Error.hxx" -bool -BlockingNfsOperation::Run(Error &_error) +constexpr std::chrono::steady_clock::duration BlockingNfsOperation::timeout; + +void +BlockingNfsOperation::Run() { /* subscribe to the connection, which will invoke either OnNfsConnectionReady() or OnNfsConnectionFailed() */ @@ -33,40 +33,37 @@ [this](){ connection.AddLease(*this); }); /* wait for completion */ - if (!LockWaitFinished()) { - _error.Set(nfs_domain, 0, "Timeout"); - return false; - } + if (!LockWaitFinished()) + throw std::runtime_error("Timeout"); /* check for error */ - if (error.IsDefined()) { - _error = std::move(error); - return false; - } - - return true; + if (error) + std::rethrow_exception(std::move(error)); } void BlockingNfsOperation::OnNfsConnectionReady() { - if (!Start(error)) { + try { + Start(); + } catch (...) { + error = std::current_exception(); connection.RemoveLease(*this); LockSetFinished(); } } void -BlockingNfsOperation::OnNfsConnectionFailed(const Error &_error) +BlockingNfsOperation::OnNfsConnectionFailed(std::exception_ptr e) { - error.Set(_error); + error = std::move(e); LockSetFinished(); } void -BlockingNfsOperation::OnNfsConnectionDisconnected(const Error &_error) +BlockingNfsOperation::OnNfsConnectionDisconnected(std::exception_ptr e) { - error.Set(_error); + error = std::move(e); LockSetFinished(); } @@ -80,10 +77,10 @@ } void -BlockingNfsOperation::OnNfsError(Error &&_error) +BlockingNfsOperation::OnNfsError(std::exception_ptr &&e) { connection.RemoveLease(*this); - error = std::move(_error); + error = std::move(e); LockSetFinished(); } diff -Nru mpd-0.19.21/src/lib/nfs/Blocking.hxx mpd-0.20.9/src/lib/nfs/Blocking.hxx --- mpd-0.19.21/src/lib/nfs/Blocking.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Blocking.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,8 @@ #include "Lease.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" -#include "util/Error.hxx" + +#include class NfsConnection; @@ -35,14 +36,15 @@ * thread, and method Run() waits for completion. */ class BlockingNfsOperation : protected NfsCallback, NfsLease { - static constexpr unsigned timeout_ms = 60000; + static constexpr std::chrono::steady_clock::duration timeout = + std::chrono::minutes(1); Mutex mutex; Cond cond; bool finished; - Error error; + std::exception_ptr error; protected: NfsConnection &connection; @@ -51,13 +53,16 @@ BlockingNfsOperation(NfsConnection &_connection) :finished(false), connection(_connection) {} - bool Run(Error &error); + /** + * Throws std::runtime_error on error. + */ + void Run(); private: bool LockWaitFinished() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); while (!finished) - if (!cond.timed_wait(mutex, timeout_ms)) + if (!cond.timed_wait(mutex, timeout)) return false; return true; @@ -68,22 +73,22 @@ * thread. */ void LockSetFinished() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); finished = true; cond.signal(); } /* virtual methods from NfsLease */ void OnNfsConnectionReady() final; - void OnNfsConnectionFailed(const Error &error) final; - void OnNfsConnectionDisconnected(const Error &error) final; + void OnNfsConnectionFailed(std::exception_ptr e) final; + void OnNfsConnectionDisconnected(std::exception_ptr e) final; /* virtual methods from NfsCallback */ void OnNfsCallback(unsigned status, void *data) final; - void OnNfsError(Error &&error) final; + void OnNfsError(std::exception_ptr &&e) final; protected: - virtual bool Start(Error &error) = 0; + virtual void Start() = 0; virtual void HandleResult(unsigned status, void *data) = 0; }; diff -Nru mpd-0.19.21/src/lib/nfs/Callback.hxx mpd-0.20.9/src/lib/nfs/Callback.hxx --- mpd-0.19.21/src/lib/nfs/Callback.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Callback.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,12 +22,24 @@ #include "check.h" -class Error; +#include +/** + * Callbacks for an asynchronous libnfs operation. + * + * Note that no callback is invoked for cancelled operations. + */ class NfsCallback { public: + /** + * The operation completed successfully. + */ virtual void OnNfsCallback(unsigned status, void *data) = 0; - virtual void OnNfsError(Error &&error) = 0; + + /** + * An error has occurred. + */ + virtual void OnNfsError(std::exception_ptr &&e) = 0; }; #endif diff -Nru mpd-0.19.21/src/lib/nfs/Cancellable.hxx mpd-0.20.9/src/lib/nfs/Cancellable.hxx --- mpd-0.19.21/src/lib/nfs/Cancellable.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Cancellable.hxx 2017-05-08 14:40:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -91,29 +91,29 @@ }; gcc_pure - iterator Find(reference_type p) { + iterator Find(reference_type p) noexcept { return std::find_if(list.begin(), list.end(), MatchPointer(p)); } gcc_pure - const_iterator Find(const_reference_type p) const { + const_iterator Find(const_reference_type p) const noexcept { return std::find_if(list.begin(), list.end(), MatchPointer(p)); } gcc_pure - iterator Find(CT &c) { + iterator Find(CT &c) noexcept { return list.iterator_to(c); } gcc_pure - const_iterator Find(const CT &c) const { + const_iterator Find(const CT &c) const noexcept { return list.iterator_to(c); } public: #ifndef NDEBUG gcc_pure - bool IsEmpty() const { + bool IsEmpty() const noexcept { for (const auto &c : list) if (!c.IsCancelled()) return false; @@ -123,7 +123,7 @@ #endif gcc_pure - bool Contains(const_reference_type p) const { + bool Contains(const_reference_type p) const noexcept { return Find(p) != list.end(); } @@ -151,7 +151,7 @@ i->Cancel(); } - CT &Get(reference_type p) { + CT &Get(reference_type p) noexcept { auto i = Find(p); assert(i != list.end()); diff -Nru mpd-0.19.21/src/lib/nfs/Connection.cxx mpd-0.20.9/src/lib/nfs/Connection.cxx --- mpd-0.19.21/src/lib/nfs/Connection.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Connection.cxx 2017-02-01 20:45:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,10 @@ #include "config.h" #include "Connection.hxx" #include "Lease.hxx" -#include "Domain.hxx" #include "Callback.hxx" #include "event/Loop.hxx" #include "system/fd_util.h" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" extern "C" { #include @@ -34,92 +33,68 @@ #include /* for POLLIN, POLLOUT */ -static constexpr unsigned NFS_MOUNT_TIMEOUT = 60; +static constexpr std::chrono::steady_clock::duration NFS_MOUNT_TIMEOUT = + std::chrono::minutes(1); -inline bool +inline void NfsConnection::CancellableCallback::Stat(nfs_context *ctx, - const char *path, - Error &error) + const char *path) { assert(connection.GetEventLoop().IsInside()); int result = nfs_stat_async(ctx, path, Callback, this); - if (result < 0) { - error.Format(nfs_domain, "nfs_stat_async() failed: %s", - nfs_get_error(ctx)); - return false; - } - - return true; + if (result < 0) + throw FormatRuntimeError("nfs_stat_async() failed: %s", + nfs_get_error(ctx)); } -inline bool +inline void NfsConnection::CancellableCallback::OpenDirectory(nfs_context *ctx, - const char *path, - Error &error) + const char *path) { assert(connection.GetEventLoop().IsInside()); int result = nfs_opendir_async(ctx, path, Callback, this); - if (result < 0) { - error.Format(nfs_domain, "nfs_opendir_async() failed: %s", - nfs_get_error(ctx)); - return false; - } - - return true; + if (result < 0) + throw FormatRuntimeError("nfs_opendir_async() failed: %s", + nfs_get_error(ctx)); } -inline bool +inline void NfsConnection::CancellableCallback::Open(nfs_context *ctx, - const char *path, int flags, - Error &error) + const char *path, int flags) { assert(connection.GetEventLoop().IsInside()); int result = nfs_open_async(ctx, path, flags, Callback, this); - if (result < 0) { - error.Format(nfs_domain, "nfs_open_async() failed: %s", - nfs_get_error(ctx)); - return false; - } - - return true; + if (result < 0) + throw FormatRuntimeError("nfs_open_async() failed: %s", + nfs_get_error(ctx)); } -inline bool +inline void NfsConnection::CancellableCallback::Stat(nfs_context *ctx, - struct nfsfh *fh, - Error &error) + struct nfsfh *fh) { assert(connection.GetEventLoop().IsInside()); int result = nfs_fstat_async(ctx, fh, Callback, this); - if (result < 0) { - error.Format(nfs_domain, "nfs_fstat_async() failed: %s", - nfs_get_error(ctx)); - return false; - } - - return true; + if (result < 0) + throw FormatRuntimeError("nfs_fstat_async() failed: %s", + nfs_get_error(ctx)); } -inline bool +inline void NfsConnection::CancellableCallback::Read(nfs_context *ctx, struct nfsfh *fh, - uint64_t offset, size_t size, - Error &error) + uint64_t offset, size_t size) { assert(connection.GetEventLoop().IsInside()); int result = nfs_pread_async(ctx, fh, offset, size, Callback, this); - if (result < 0) { - error.Format(nfs_domain, "nfs_pread_async() failed: %s", - nfs_get_error(ctx)); - return false; - } - - return true; + if (result < 0) + throw FormatRuntimeError("nfs_pread_async() failed: %s", + nfs_get_error(ctx)); } inline void @@ -160,8 +135,7 @@ if (err >= 0) cb.OnNfsCallback((unsigned)err, data); else - cb.OnNfsError(Error(nfs_domain, err, - (const char *)data)); + cb.OnNfsError(std::make_exception_ptr(std::runtime_error((const char *)data))); } else { if (open) { /* a nfs_open_async() call was cancelled - to @@ -234,37 +208,38 @@ active_leases.remove(&lease); } -bool -NfsConnection::Stat(const char *path, NfsCallback &callback, Error &error) +void +NfsConnection::Stat(const char *path, NfsCallback &callback) { assert(GetEventLoop().IsInside()); assert(!callbacks.Contains(callback)); auto &c = callbacks.Add(callback, *this, false); - if (!c.Stat(context, path, error)) { + try { + c.Stat(context, path); + } catch (...) { callbacks.Remove(c); - return false; + throw; } ScheduleSocket(); - return true; } -bool -NfsConnection::OpenDirectory(const char *path, NfsCallback &callback, - Error &error) +void +NfsConnection::OpenDirectory(const char *path, NfsCallback &callback) { assert(GetEventLoop().IsInside()); assert(!callbacks.Contains(callback)); auto &c = callbacks.Add(callback, *this, true); - if (!c.OpenDirectory(context, path, error)) { + try { + c.OpenDirectory(context, path); + } catch (...) { callbacks.Remove(c); - return false; + throw; } ScheduleSocket(); - return true; } const struct nfsdirent * @@ -283,54 +258,56 @@ return nfs_closedir(context, dir); } -bool -NfsConnection::Open(const char *path, int flags, NfsCallback &callback, - Error &error) +void +NfsConnection::Open(const char *path, int flags, NfsCallback &callback) { assert(GetEventLoop().IsInside()); assert(!callbacks.Contains(callback)); auto &c = callbacks.Add(callback, *this, true); - if (!c.Open(context, path, flags, error)) { + try { + c.Open(context, path, flags); + } catch (...) { callbacks.Remove(c); - return false; + throw; } ScheduleSocket(); - return true; } -bool -NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback, Error &error) +void +NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback) { assert(GetEventLoop().IsInside()); assert(!callbacks.Contains(callback)); auto &c = callbacks.Add(callback, *this, false); - if (!c.Stat(context, fh, error)) { + try { + c.Stat(context, fh); + } catch (...) { callbacks.Remove(c); - return false; + throw; } ScheduleSocket(); - return true; } -bool +void NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size, - NfsCallback &callback, Error &error) + NfsCallback &callback) { assert(GetEventLoop().IsInside()); assert(!callbacks.Contains(callback)); auto &c = callbacks.Add(callback, *this, false); - if (!c.Read(context, fh, offset, size, error)) { + try { + c.Read(context, fh, offset, size); + } catch (...) { callbacks.Remove(c); - return false; + throw; } ScheduleSocket(); - return true; } void @@ -419,6 +396,17 @@ assert(GetEventLoop().IsInside()); assert(context != nullptr); + const int which_events = nfs_which_events(context); + + if (which_events == POLLOUT && SocketMonitor::IsDefined()) + /* kludge: if libnfs asks only for POLLOUT, it means + that it is currently waiting for the connect() to + finish - rpc_reconnect_requeue() may have been + called from inside nfs_service(); we must now + unregister the old socket and register the new one + instead */ + SocketMonitor::Steal(); + if (!SocketMonitor::IsDefined()) { int _fd = nfs_get_fd(context); if (_fd < 0) @@ -428,7 +416,8 @@ SocketMonitor::Open(_fd); } - SocketMonitor::Schedule(libnfs_to_events(nfs_which_events(context))); + SocketMonitor::Schedule(libnfs_to_events(which_events) + | SocketMonitor::HANGUP); } inline int @@ -465,10 +454,14 @@ bool closed = false; const bool was_mounted = mount_finished; - if (!mount_finished) + if (!mount_finished || (flags & SocketMonitor::HANGUP) != 0) /* until the mount is finished, the NFS client may use various sockets, therefore we unregister and re-register it each time */ + /* also re-register the socket if we got a HANGUP, + which is a sure sign that libnfs will close the + socket, which can lead to a race condition if + epoll_ctl() is called later */ SocketMonitor::Steal(); const int result = Service(flags); @@ -479,7 +472,7 @@ } if (!was_mounted && mount_finished) { - if (postponed_mount_error.IsDefined()) { + if (postponed_mount_error) { DestroyContext(); closed = true; BroadcastMountError(std::move(postponed_mount_error)); @@ -487,11 +480,10 @@ BroadcastMountSuccess(); } else if (result < 0) { /* the connection has failed */ - Error error; - error.Format(nfs_domain, "NFS connection has failed: %s", - nfs_get_error(context)); - BroadcastError(std::move(error)); + auto e = FormatRuntimeError("NFS connection has failed: %s", + nfs_get_error(context)); + BroadcastError(std::make_exception_ptr(e)); DestroyContext(); closed = true; @@ -499,15 +491,13 @@ /* this happens when rpc_reconnect_requeue() is called after the connection broke, but autoreconnect was disabled - nfs_service() returns 0 */ - Error error; + const char *msg = nfs_get_error(context); if (msg == nullptr) - error.Set(nfs_domain, "NFS socket disappeared"); - else - error.Format(nfs_domain, - "NFS socket disappeared: %s", msg); + msg = ""; + auto e = FormatRuntimeError("NFS socket disappeared: %s", msg); - BroadcastError(std::move(error)); + BroadcastError(std::make_exception_ptr(e)); DestroyContext(); closed = true; @@ -539,9 +529,9 @@ TimeoutMonitor::Cancel(); if (status < 0) { - postponed_mount_error.Format(nfs_domain, status, - "nfs_mount_async() failed: %s", - nfs_get_error(context)); + auto e = FormatRuntimeError("nfs_mount_async() failed: %s", + nfs_get_error(context)); + postponed_mount_error = std::make_exception_ptr(e); return; } } @@ -555,22 +545,20 @@ c->MountCallback(status, nfs, data); } -inline bool -NfsConnection::MountInternal(Error &error) +inline void +NfsConnection::MountInternal() { assert(GetEventLoop().IsInside()); assert(context == nullptr); context = nfs_init_context(); - if (context == nullptr) { - error.Set(nfs_domain, "nfs_init_context() failed"); - return false; - } + if (context == nullptr) + throw std::runtime_error("nfs_init_context() failed"); - postponed_mount_error.Clear(); + postponed_mount_error = std::exception_ptr(); mount_finished = false; - TimeoutMonitor::ScheduleSeconds(NFS_MOUNT_TIMEOUT); + TimeoutMonitor::Schedule(NFS_MOUNT_TIMEOUT); #ifndef NDEBUG in_service = false; @@ -580,16 +568,14 @@ if (nfs_mount_async(context, server.c_str(), export_name.c_str(), MountCallback, this) != 0) { - error.Format(nfs_domain, - "nfs_mount_async() failed: %s", - nfs_get_error(context)); + auto e = FormatRuntimeError("nfs_mount_async() failed: %s", + nfs_get_error(context)); nfs_destroy_context(context); context = nullptr; - return false; + throw e; } ScheduleSocket(); - return true; } void @@ -605,31 +591,31 @@ } void -NfsConnection::BroadcastMountError(Error &&error) +NfsConnection::BroadcastMountError(std::exception_ptr &&e) { assert(GetEventLoop().IsInside()); while (!new_leases.empty()) { auto l = new_leases.front(); new_leases.pop_front(); - l->OnNfsConnectionFailed(error); + l->OnNfsConnectionFailed(e); } - OnNfsConnectionError(std::move(error)); + OnNfsConnectionError(std::move(e)); } void -NfsConnection::BroadcastError(Error &&error) +NfsConnection::BroadcastError(std::exception_ptr &&e) { assert(GetEventLoop().IsInside()); while (!active_leases.empty()) { auto l = active_leases.front(); active_leases.pop_front(); - l->OnNfsConnectionDisconnected(error); + l->OnNfsConnectionDisconnected(e); } - BroadcastMountError(std::move(error)); + BroadcastMountError(std::move(e)); } void @@ -641,7 +627,7 @@ mount_finished = true; DestroyContext(); - BroadcastMountError(Error(nfs_domain, "Mount timeout")); + BroadcastMountError(std::make_exception_ptr(std::runtime_error("Mount timeout"))); } void @@ -650,9 +636,10 @@ assert(GetEventLoop().IsInside()); if (context == nullptr) { - Error error; - if (!MountInternal(error)) { - BroadcastMountError(std::move(error)); + try { + MountInternal(); + } catch (...) { + BroadcastMountError(std::current_exception()); return; } } diff -Nru mpd-0.19.21/src/lib/nfs/Connection.hxx mpd-0.20.9/src/lib/nfs/Connection.hxx --- mpd-0.19.21/src/lib/nfs/Connection.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Connection.hxx 2017-06-04 10:34:44.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,23 +20,21 @@ #ifndef MPD_NFS_CONNECTION_HXX #define MPD_NFS_CONNECTION_HXX -#include "Lease.hxx" #include "Cancellable.hxx" #include "event/SocketMonitor.hxx" #include "event/TimeoutMonitor.hxx" #include "event/DeferredMonitor.hxx" -#include "util/Error.hxx" - -#include #include #include #include +#include struct nfs_context; struct nfsdir; struct nfsdirent; class NfsCallback; +class NfsLease; /** * An asynchronous connection to a NFS server. @@ -67,17 +65,12 @@ connection(_connection), open(_open), close_fh(nullptr) {} - bool Stat(nfs_context *context, const char *path, - Error &error); - bool OpenDirectory(nfs_context *context, const char *path, - Error &error); - bool Open(nfs_context *context, const char *path, int flags, - Error &error); - bool Stat(nfs_context *context, struct nfsfh *fh, - Error &error); - bool Read(nfs_context *context, struct nfsfh *fh, - uint64_t offset, size_t size, - Error &error); + void Stat(nfs_context *context, const char *path); + void OpenDirectory(nfs_context *context, const char *path); + void Open(nfs_context *context, const char *path, int flags); + void Stat(nfs_context *context, struct nfsfh *fh); + void Read(nfs_context *context, struct nfsfh *fh, + uint64_t offset, size_t size); /** * Cancel the operation and schedule a call to @@ -117,7 +110,7 @@ */ std::forward_list deferred_close; - Error postponed_mount_error; + std::exception_ptr postponed_mount_error; #ifndef NDEBUG /** @@ -142,7 +135,7 @@ public: gcc_nonnull_all NfsConnection(EventLoop &_loop, - const char *_server, const char *_export_name) + const char *_server, const char *_export_name) noexcept :SocketMonitor(_loop), TimeoutMonitor(_loop), DeferredMonitor(_loop), server(_server), export_name(_export_name), @@ -154,16 +147,16 @@ ~NfsConnection(); gcc_pure - const char *GetServer() const { + const char *GetServer() const noexcept { return server.c_str(); } gcc_pure - const char *GetExportName() const { + const char *GetExportName() const noexcept { return export_name.c_str(); } - EventLoop &GetEventLoop() { + EventLoop &GetEventLoop() noexcept { return SocketMonitor::GetEventLoop(); } @@ -177,25 +170,32 @@ void AddLease(NfsLease &lease); void RemoveLease(NfsLease &lease); - bool Stat(const char *path, NfsCallback &callback, Error &error); + void Stat(const char *path, NfsCallback &callback); - bool OpenDirectory(const char *path, NfsCallback &callback, - Error &error); + void OpenDirectory(const char *path, NfsCallback &callback); const struct nfsdirent *ReadDirectory(struct nfsdir *dir); void CloseDirectory(struct nfsdir *dir); - bool Open(const char *path, int flags, NfsCallback &callback, - Error &error); - bool Stat(struct nfsfh *fh, NfsCallback &callback, Error &error); - bool Read(struct nfsfh *fh, uint64_t offset, size_t size, - NfsCallback &callback, Error &error); + /** + * Throws std::runtime_error on error. + */ + void Open(const char *path, int flags, NfsCallback &callback); + + void Stat(struct nfsfh *fh, NfsCallback &callback); + + /** + * Throws std::runtime_error on error. + */ + void Read(struct nfsfh *fh, uint64_t offset, size_t size, + NfsCallback &callback); + void Cancel(NfsCallback &callback); void Close(struct nfsfh *fh); void CancelAndClose(struct nfsfh *fh, NfsCallback &callback); protected: - virtual void OnNfsConnectionError(Error &&error) = 0; + virtual void OnNfsConnectionError(std::exception_ptr &&e) = 0; private: void DestroyContext(); @@ -210,10 +210,10 @@ */ void DeferClose(struct nfsfh *fh); - bool MountInternal(Error &error); + void MountInternal(); void BroadcastMountSuccess(); - void BroadcastMountError(Error &&error); - void BroadcastError(Error &&error); + void BroadcastMountError(std::exception_ptr &&e); + void BroadcastError(std::exception_ptr &&e); static void MountCallback(int status, nfs_context *nfs, void *data, void *private_data); diff -Nru mpd-0.19.21/src/lib/nfs/Domain.cxx mpd-0.20.9/src/lib/nfs/Domain.cxx --- mpd-0.19.21/src/lib/nfs/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Domain.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Domain.hxx" -#include "util/Domain.hxx" - -const Domain nfs_domain("nfs"); diff -Nru mpd-0.19.21/src/lib/nfs/Domain.hxx mpd-0.20.9/src/lib/nfs/Domain.hxx --- mpd-0.19.21/src/lib/nfs/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Domain.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_NFS_DOMAIN_HXX -#define MPD_NFS_DOMAIN_HXX - -class Domain; - -extern const Domain nfs_domain; - -#endif diff -Nru mpd-0.19.21/src/lib/nfs/FileReader.cxx mpd-0.20.9/src/lib/nfs/FileReader.cxx --- mpd-0.19.21/src/lib/nfs/FileReader.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/FileReader.cxx 2017-02-08 07:43:46.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,17 +22,16 @@ #include "Glue.hxx" #include "Base.hxx" #include "Connection.hxx" -#include "Domain.hxx" #include "event/Call.hxx" #include "IOThread.hxx" -#include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "util/StringCompare.hxx" #include #include #include #include +#include NfsFileReader::NfsFileReader() :DeferredMonitor(io_thread_get()), state(State::INITIAL) @@ -90,23 +89,19 @@ BlockingCall(io_thread_get(), [this](){ Close(); }); } -bool -NfsFileReader::Open(const char *uri, Error &error) +void +NfsFileReader::Open(const char *uri) { assert(state == State::INITIAL); - if (!StringStartsWith(uri, "nfs://")) { - error.Set(nfs_domain, "Malformed nfs:// URI"); - return false; - } + if (!StringStartsWith(uri, "nfs://")) + throw std::runtime_error("Malformed nfs:// URI"); uri += 6; const char *slash = strchr(uri, '/'); - if (slash == nullptr) { - error.Set(nfs_domain, "Malformed nfs:// URI"); - return false; - } + if (slash == nullptr) + throw std::runtime_error("Malformed nfs:// URI"); server = std::string(uri, slash); @@ -120,10 +115,8 @@ path = new_path; } else { slash = strrchr(uri + 1, '/'); - if (slash == nullptr || slash[1] == 0) { - error.Set(nfs_domain, "Malformed nfs:// URI"); - return false; - } + if (slash == nullptr || slash[1] == 0) + throw std::runtime_error("Malformed nfs:// URI"); export_name = std::string(uri, slash); path = slash; @@ -131,19 +124,15 @@ state = State::DEFER; DeferredMonitor::Schedule(); - return true; } -bool -NfsFileReader::Read(uint64_t offset, size_t size, Error &error) +void +NfsFileReader::Read(uint64_t offset, size_t size) { assert(state == State::IDLE); - if (!connection->Read(fh, offset, size, *this, error)) - return false; - + connection->Read(fh, offset, size, *this); state = State::READ; - return true; } void @@ -160,9 +149,10 @@ { assert(state == State::MOUNT); - Error error; - if (!connection->Open(path, O_RDONLY, *this, error)) { - OnNfsFileError(std::move(error)); + try { + connection->Open(path, O_RDONLY, *this); + } catch (...) { + OnNfsFileError(std::current_exception()); return; } @@ -170,27 +160,23 @@ } void -NfsFileReader::OnNfsConnectionFailed(const Error &error) +NfsFileReader::OnNfsConnectionFailed(std::exception_ptr e) { assert(state == State::MOUNT); state = State::INITIAL; - Error copy; - copy.Set(error); - OnNfsFileError(std::move(copy)); + OnNfsFileError(std::move(e)); } void -NfsFileReader::OnNfsConnectionDisconnected(const Error &error) +NfsFileReader::OnNfsConnectionDisconnected(std::exception_ptr e) { assert(state > State::MOUNT); CancelOrClose(); - Error copy; - copy.Set(error); - OnNfsFileError(std::move(copy)); + OnNfsFileError(std::move(e)); } inline void @@ -202,9 +188,10 @@ fh = _fh; - Error error; - if (!connection->Stat(fh, *this, error)) { - OnNfsFileError(std::move(error)); + try { + connection->Stat(fh, *this); + } catch (...) { + OnNfsFileError(std::current_exception()); return; } @@ -220,7 +207,7 @@ assert(st != nullptr); if (!S_ISREG(st->st_mode)) { - OnNfsFileError(Error(nfs_domain, "Not a regular file")); + OnNfsFileError(std::make_exception_ptr(std::runtime_error("Not a regular file"))); return; } @@ -256,7 +243,7 @@ } void -NfsFileReader::OnNfsError(Error &&error) +NfsFileReader::OnNfsError(std::exception_ptr &&e) { switch (state) { case State::INITIAL: @@ -282,7 +269,7 @@ break; } - OnNfsFileError(std::move(error)); + OnNfsFileError(std::move(e)); } void diff -Nru mpd-0.19.21/src/lib/nfs/FileReader.hxx mpd-0.20.9/src/lib/nfs/FileReader.hxx --- mpd-0.19.21/src/lib/nfs/FileReader.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/FileReader.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,14 +27,22 @@ #include "Compiler.h" #include +#include #include #include -#include struct nfsfh; class NfsConnection; +/** + * A helper class which helps with reading from a file. It obtains a + * connection lease (#NfsLease), opens the given file, "stats" the + * file, and finally allos you to read its contents. + * + * To get started, derive your class from it and implement the pure + * virtual methods, construct an instance, and call Open(). + */ class NfsFileReader : NfsLease, NfsCallback, DeferredMonitor { enum class State { INITIAL, @@ -62,8 +70,31 @@ void Close(); void DeferClose(); - bool Open(const char *uri, Error &error); - bool Read(uint64_t offset, size_t size, Error &error); + /** + * Open the file. This method is thread-safe. + * + * Throws std::runtime_error on error. + */ + void Open(const char *uri); + + /** + * Attempt to read from the file. This may only be done after + * OnNfsFileOpen() has been called. Only one read operation + * may be performed at a time. + * + * This method is not thread-safe and must be called from + * within the I/O thread. + * + * Throws std::runtime_error on error. + */ + void Read(uint64_t offset, size_t size); + + /** + * Cancel the most recent Read() call. + * + * This method is not thread-safe and must be called from + * within the I/O thread. + */ void CancelRead(); bool IsIdle() const { @@ -71,9 +102,28 @@ } protected: + /** + * The file has been opened successfully. It is a regular + * file, and its size is known. It is ready to be read from + * using Read(). + * + * This method will be called from within the I/O thread. + */ virtual void OnNfsFileOpen(uint64_t size) = 0; + + /** + * A Read() has completed successfully. + * + * This method will be called from within the I/O thread. + */ virtual void OnNfsFileRead(const void *data, size_t size) = 0; - virtual void OnNfsFileError(Error &&error) = 0; + + /** + * An error has occurred, which can be either while waiting + * for OnNfsFileOpen(), or while waiting for OnNfsFileRead(), + * or if disconnected while idle. + */ + virtual void OnNfsFileError(std::exception_ptr &&e) = 0; private: /** @@ -87,12 +137,12 @@ /* virtual methods from NfsLease */ void OnNfsConnectionReady() final; - void OnNfsConnectionFailed(const Error &error) final; - void OnNfsConnectionDisconnected(const Error &error) final; + void OnNfsConnectionFailed(std::exception_ptr e) final; + void OnNfsConnectionDisconnected(std::exception_ptr e) final; /* virtual methods from NfsCallback */ void OnNfsCallback(unsigned status, void *data) final; - void OnNfsError(Error &&error) final; + void OnNfsError(std::exception_ptr &&e) final; /* virtual methods from DeferredMonitor */ void RunDeferred() final; diff -Nru mpd-0.19.21/src/lib/nfs/Glue.cxx mpd-0.20.9/src/lib/nfs/Glue.cxx --- mpd-0.19.21/src/lib/nfs/Glue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Glue.cxx 2017-05-08 14:46:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -50,7 +50,7 @@ } NfsConnection & -nfs_get_connection(const char *server, const char *export_name) +nfs_get_connection(const char *server, const char *export_name) noexcept { assert(in_use > 0); assert(io_thread_inside()); diff -Nru mpd-0.19.21/src/lib/nfs/Glue.hxx mpd-0.20.9/src/lib/nfs/Glue.hxx --- mpd-0.19.21/src/lib/nfs/Glue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Glue.hxx 2017-05-08 14:37:59.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -33,6 +33,6 @@ gcc_pure NfsConnection & -nfs_get_connection(const char *server, const char *export_name); +nfs_get_connection(const char *server, const char *export_name) noexcept; #endif diff -Nru mpd-0.19.21/src/lib/nfs/Lease.hxx mpd-0.20.9/src/lib/nfs/Lease.hxx --- mpd-0.19.21/src/lib/nfs/Lease.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Lease.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ #include "check.h" -class Error; +#include class NfsLease { public: @@ -36,13 +36,13 @@ * The #NfsConnection has failed to mount the server's export. * This is being called instead of OnNfsConnectionReady(). */ - virtual void OnNfsConnectionFailed(const Error &error) = 0; + virtual void OnNfsConnectionFailed(std::exception_ptr e) = 0; /** * The #NfsConnection has failed after OnNfsConnectionReady() * had been called already. */ - virtual void OnNfsConnectionDisconnected(const Error &error) = 0; + virtual void OnNfsConnectionDisconnected(std::exception_ptr e) = 0; }; #endif diff -Nru mpd-0.19.21/src/lib/nfs/Manager.cxx mpd-0.20.9/src/lib/nfs/Manager.cxx --- mpd-0.19.21/src/lib/nfs/Manager.cxx 2016-08-05 16:05:30.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Manager.cxx 2017-05-08 14:40:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,13 +21,14 @@ #include "Manager.hxx" #include "event/Loop.hxx" #include "Log.hxx" +#include "util/DeleteDisposer.hxx" #include void -NfsManager::ManagedConnection::OnNfsConnectionError(Error &&error) +NfsManager::ManagedConnection::OnNfsConnectionError(std::exception_ptr &&e) { - FormatError(error, "NFS error on %s:%s", GetServer(), GetExportName()); + FormatError(e, "NFS error on %s:%s", GetServer(), GetExportName()); /* defer deletion so the caller (i.e. NfsConnection::OnSocketReady()) can still use this @@ -37,7 +38,7 @@ inline bool NfsManager::Compare::operator()(const LookupKey a, - const ManagedConnection &b) const + const ManagedConnection &b) const noexcept { int result = strcmp(a.server, b.GetServer()); if (result != 0) @@ -49,7 +50,7 @@ inline bool NfsManager::Compare::operator()(const ManagedConnection &a, - const LookupKey b) const + const LookupKey b) const noexcept { int result = strcmp(a.GetServer(), b.server); if (result != 0) @@ -61,7 +62,7 @@ inline bool NfsManager::Compare::operator()(const ManagedConnection &a, - const ManagedConnection &b) const + const ManagedConnection &b) const noexcept { int result = strcmp(a.GetServer(), b.GetServer()); if (result != 0) @@ -77,13 +78,11 @@ CollectGarbage(); - connections.clear_and_dispose([](ManagedConnection *c){ - delete c; - }); + connections.clear_and_dispose(DeleteDisposer()); } NfsConnection & -NfsManager::GetConnection(const char *server, const char *export_name) +NfsManager::GetConnection(const char *server, const char *export_name) noexcept { assert(server != nullptr); assert(export_name != nullptr); @@ -107,9 +106,7 @@ { assert(GetEventLoop().IsInside()); - garbage.clear_and_dispose([](ManagedConnection *c){ - delete c; - }); + garbage.clear_and_dispose(DeleteDisposer()); } void diff -Nru mpd-0.19.21/src/lib/nfs/Manager.hxx mpd-0.20.9/src/lib/nfs/Manager.hxx --- mpd-0.19.21/src/lib/nfs/Manager.hxx 2016-08-05 16:05:12.000000000 +0000 +++ mpd-0.20.9/src/lib/nfs/Manager.hxx 2017-05-08 14:47:09.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -53,21 +53,21 @@ protected: /* virtual methods from NfsConnection */ - void OnNfsConnectionError(Error &&error) override; + void OnNfsConnectionError(std::exception_ptr &&e) override; }; struct Compare { gcc_pure bool operator()(const LookupKey a, - const ManagedConnection &b) const; + const ManagedConnection &b) const noexcept; gcc_pure bool operator()(const ManagedConnection &a, - const LookupKey b) const; + const LookupKey b) const noexcept; gcc_pure bool operator()(const ManagedConnection &a, - const ManagedConnection &b) const; + const ManagedConnection &b) const noexcept; }; /** @@ -99,7 +99,7 @@ gcc_pure NfsConnection &GetConnection(const char *server, - const char *export_name); + const char *export_name) noexcept; private: void ScheduleDelete(ManagedConnection &c) { diff -Nru mpd-0.19.21/src/lib/pulse/Domain.cxx mpd-0.20.9/src/lib/pulse/Domain.cxx --- mpd-0.19.21/src/lib/pulse/Domain.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,24 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Domain.hxx" +#include "util/Domain.hxx" + +const Domain pulse_domain("pulse"); diff -Nru mpd-0.19.21/src/lib/pulse/Domain.hxx mpd-0.20.9/src/lib/pulse/Domain.hxx --- mpd-0.19.21/src/lib/pulse/Domain.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PULSE_DOMAIN_HXX +#define MPD_PULSE_DOMAIN_HXX + +class Domain; + +extern const Domain pulse_domain; + +#endif diff -Nru mpd-0.19.21/src/lib/pulse/Error.cxx mpd-0.20.9/src/lib/pulse/Error.cxx --- mpd-0.19.21/src/lib/pulse/Error.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/Error.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Error.hxx" +#include "util/RuntimeError.hxx" + +#include +#include + +std::runtime_error +MakePulseError(pa_context *context, const char *prefix) +{ + const int e = pa_context_errno(context); + return FormatRuntimeError("%s: %s", prefix, pa_strerror(e)); +} diff -Nru mpd-0.19.21/src/lib/pulse/Error.hxx mpd-0.20.9/src/lib/pulse/Error.hxx --- mpd-0.19.21/src/lib/pulse/Error.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/Error.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PULSE_ERROR_HXX +#define MPD_PULSE_ERROR_HXX + +#include + +struct pa_context; + +std::runtime_error +MakePulseError(pa_context *context, const char *prefix); + +#endif diff -Nru mpd-0.19.21/src/lib/pulse/LockGuard.hxx mpd-0.20.9/src/lib/pulse/LockGuard.hxx --- mpd-0.19.21/src/lib/pulse/LockGuard.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/LockGuard.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PULSE_LOCK_GUARD_HXX +#define MPD_PULSE_LOCK_GUARD_HXX + +#include + +namespace Pulse { + +class LockGuard { + struct pa_threaded_mainloop *const mainloop; + +public: + explicit LockGuard(struct pa_threaded_mainloop *_mainloop) + :mainloop(_mainloop) { + pa_threaded_mainloop_lock(mainloop); + } + + ~LockGuard() { + pa_threaded_mainloop_unlock(mainloop); + } + + LockGuard(const LockGuard &) = delete; + LockGuard &operator=(const LockGuard &) = delete; +}; + +}; + +#endif diff -Nru mpd-0.19.21/src/lib/pulse/LogError.cxx mpd-0.20.9/src/lib/pulse/LogError.cxx --- mpd-0.19.21/src/lib/pulse/LogError.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/LogError.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "LogError.hxx" +#include "Domain.hxx" +#include "Log.hxx" + +#include +#include + +void +LogPulseError(pa_context *context, const char *prefix) +{ + const int e = pa_context_errno(context); + FormatError(pulse_domain, "%s: %s", prefix, pa_strerror(e)); +} diff -Nru mpd-0.19.21/src/lib/pulse/LogError.hxx mpd-0.20.9/src/lib/pulse/LogError.hxx --- mpd-0.19.21/src/lib/pulse/LogError.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/pulse/LogError.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PULSE_LOG_ERROR_HXX +#define MPD_PULSE_LOG_ERROR_HXX + +struct pa_context; + +void +LogPulseError(pa_context *context, const char *prefix); + +#endif diff -Nru mpd-0.19.21/src/lib/smbclient/Domain.cxx mpd-0.20.9/src/lib/smbclient/Domain.cxx --- mpd-0.19.21/src/lib/smbclient/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/smbclient/Domain.hxx mpd-0.20.9/src/lib/smbclient/Domain.hxx --- mpd-0.19.21/src/lib/smbclient/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/smbclient/Init.cxx mpd-0.20.9/src/lib/smbclient/Init.cxx --- mpd-0.19.21/src/lib/smbclient/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Init.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "Init.hxx" #include "Mutex.hxx" #include "thread/Mutex.hxx" -#include "util/Error.hxx" +#include "system/Error.hxx" #include @@ -40,16 +40,12 @@ strcpy(pw, ""); } -bool -SmbclientInit(Error &error) +void +SmbclientInit() { - const ScopeLock protect(smbclient_mutex); + const std::lock_guard protect(smbclient_mutex); constexpr int debug = 0; - if (smbc_init(mpd_smbc_get_auth_data, debug) < 0) { - error.SetErrno("smbc_init() failed"); - return false; - } - - return true; + if (smbc_init(mpd_smbc_get_auth_data, debug) < 0) + throw MakeErrno("smbc_init() failed"); } diff -Nru mpd-0.19.21/src/lib/smbclient/Init.hxx mpd-0.20.9/src/lib/smbclient/Init.hxx --- mpd-0.19.21/src/lib/smbclient/Init.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Init.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,14 +20,12 @@ #ifndef MPD_SMBCLIENT_INIT_HXX #define MPD_SMBCLIENT_INIT_HXX -#include "check.h" - -class Error; - /** * Initialize libsmbclient. + * + * Throws std::runtime_error on error. */ -bool -SmbclientInit(Error &error); +void +SmbclientInit(); #endif diff -Nru mpd-0.19.21/src/lib/smbclient/Mutex.cxx mpd-0.20.9/src/lib/smbclient/Mutex.cxx --- mpd-0.19.21/src/lib/smbclient/Mutex.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Mutex.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/smbclient/Mutex.hxx mpd-0.20.9/src/lib/smbclient/Mutex.hxx --- mpd-0.19.21/src/lib/smbclient/Mutex.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/smbclient/Mutex.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/sqlite/Error.cxx mpd-0.20.9/src/lib/sqlite/Error.cxx --- mpd-0.19.21/src/lib/sqlite/Error.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/sqlite/Error.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "Error.hxx" + +#include + +#include + +static std::string +MakeSqliteErrorMessage(sqlite3 *db, const char *msg) +{ + return std::string(msg) + ": " + sqlite3_errmsg(db); +} + +SqliteError::SqliteError(sqlite3 *db, int _code, const char *msg) + :std::runtime_error(MakeSqliteErrorMessage(db, msg)), code(_code) {} + +SqliteError::SqliteError(sqlite3_stmt *stmt, int _code, const char *msg) + :SqliteError(sqlite3_db_handle(stmt), _code, msg) {} diff -Nru mpd-0.19.21/src/lib/sqlite/Error.hxx mpd-0.20.9/src/lib/sqlite/Error.hxx --- mpd-0.19.21/src/lib/sqlite/Error.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/sqlite/Error.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SQLITE_ERROR_HXX +#define MPD_SQLITE_ERROR_HXX + +#include + +struct sqlite3; +struct sqlite3_stmt; + +class SqliteError final : public std::runtime_error { + int code; + +public: + SqliteError(sqlite3 *db, int _code, const char *msg); + SqliteError(sqlite3_stmt *stmt, int _code, const char *msg); + + int GetCode() const { + return code; + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/sqlite/Util.hxx mpd-0.20.9/src/lib/sqlite/Util.hxx --- mpd-0.19.21/src/lib/sqlite/Util.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/sqlite/Util.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SQLITE_UTIL_HXX +#define MPD_SQLITE_UTIL_HXX + +#include "Error.hxx" + +#include + +#include + +/** + * Throws #SqliteError on error. + */ +static void +Bind(sqlite3_stmt *stmt, unsigned i, const char *value) +{ + int result = sqlite3_bind_text(stmt, i, value, -1, nullptr); + if (result != SQLITE_OK) + throw SqliteError(stmt, result, "sqlite3_bind_text() failed"); +} + +template +static void +BindAll2(gcc_unused sqlite3_stmt *stmt, gcc_unused unsigned i) +{ + assert(int(i - 1) == sqlite3_bind_parameter_count(stmt)); +} + +template +static void +BindAll2(sqlite3_stmt *stmt, unsigned i, + const char *value, Args&&... args) +{ + Bind(stmt, i, value); + BindAll2(stmt, i + 1, std::forward(args)...); +} + +/** + * Throws #SqliteError on error. + */ +template +static void +BindAll(sqlite3_stmt *stmt, Args&&... args) +{ + assert(int(sizeof...(args)) == sqlite3_bind_parameter_count(stmt)); + + BindAll2(stmt, 1, std::forward(args)...); +} + +/** + * Call sqlite3_stmt() repepatedly until something other than + * SQLITE_BUSY is returned. + */ +static int +ExecuteBusy(sqlite3_stmt *stmt) +{ + int result; + do { + result = sqlite3_step(stmt); + } while (result == SQLITE_BUSY); + + return result; +} + +/** + * Wrapper for ExecuteBusy() that returns true on SQLITE_ROW. + * + * Throws #SqliteError on error. + */ +static bool +ExecuteRow(sqlite3_stmt *stmt) +{ + int result = ExecuteBusy(stmt); + if (result == SQLITE_ROW) + return true; + + if (result != SQLITE_DONE) + throw SqliteError(stmt, result, "sqlite3_step() failed"); + + return false; +} + +/** + * Wrapper for ExecuteBusy() that interprets everything other than + * SQLITE_DONE as error. + * + * Throws #SqliteError on error. + */ +static void +ExecuteCommand(sqlite3_stmt *stmt) +{ + int result = ExecuteBusy(stmt); + if (result != SQLITE_DONE) + throw SqliteError(stmt, result, "sqlite3_step() failed"); +} + +/** + * Wrapper for ExecuteCommand() that returns the number of rows + * modified via sqlite3_changes(). + * + * Throws #SqliteError on error. + */ +static inline unsigned +ExecuteChanges(sqlite3_stmt *stmt) +{ + ExecuteCommand(stmt); + + return sqlite3_changes(sqlite3_db_handle(stmt)); +} + +/** + * Wrapper for ExecuteChanges() that returns true if at least one row + * was modified. Returns false if nothing was modified. + * + * Throws #SqliteError on error. + */ +static inline bool +ExecuteModified(sqlite3_stmt *stmt) +{ + return ExecuteChanges(stmt) > 0; +} + +template +static inline void +ExecuteForEach(sqlite3_stmt *stmt, F &&f) +{ + while (true) { + int result = ExecuteBusy(stmt); + switch (result) { + case SQLITE_ROW: + f(); + break; + + case SQLITE_DONE: + return; + + default: + throw SqliteError(stmt, result, "sqlite3_step() failed"); + } + } +} + +#endif diff -Nru mpd-0.19.21/src/lib/upnp/Action.hxx mpd-0.20.9/src/lib/upnp/Action.hxx --- mpd-0.19.21/src/lib/upnp/Action.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Action.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/upnp/Callback.hxx mpd-0.20.9/src/lib/upnp/Callback.hxx --- mpd-0.19.21/src/lib/upnp/Callback.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Callback.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/lib/upnp/ClientInit.cxx mpd-0.20.9/src/lib/upnp/ClientInit.cxx --- mpd-0.19.21/src/lib/upnp/ClientInit.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/ClientInit.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,12 +21,13 @@ #include "ClientInit.hxx" #include "Init.hxx" #include "Callback.hxx" -#include "Domain.hxx" #include "thread/Mutex.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include +#include + static Mutex upnp_client_init_mutex; static unsigned upnp_client_ref; static UpnpClient_Handle upnp_client_handle; @@ -44,50 +45,44 @@ return callback.Invoke(et, evp); } -static bool -DoInit(Error &error) +static void +DoInit() { auto code = UpnpRegisterClient(UpnpClientCallback, nullptr, &upnp_client_handle); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpRegisterClient() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } - - return true; + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpRegisterClient() failed: %s", + UpnpGetErrorMessage(code)); } -bool -UpnpClientGlobalInit(UpnpClient_Handle &handle, Error &error) +void +UpnpClientGlobalInit(UpnpClient_Handle &handle) { - if (!UpnpGlobalInit(error)) - return false; + UpnpGlobalInit(); - upnp_client_init_mutex.lock(); - bool success = upnp_client_ref > 0 || DoInit(error); - upnp_client_init_mutex.unlock(); - - if (success) { - ++upnp_client_ref; - handle = upnp_client_handle; - } else + try { + const std::lock_guard protect(upnp_client_init_mutex); + if (upnp_client_ref == 0) + DoInit(); + } catch (...) { UpnpGlobalFinish(); + throw; + } - return success; + ++upnp_client_ref; + handle = upnp_client_handle; } void UpnpClientGlobalFinish() { - upnp_client_init_mutex.lock(); - - assert(upnp_client_ref > 0); - if (--upnp_client_ref == 0) - UpnpUnRegisterClient(upnp_client_handle); + { + const std::lock_guard protect(upnp_client_init_mutex); - upnp_client_init_mutex.unlock(); + assert(upnp_client_ref > 0); + if (--upnp_client_ref == 0) + UpnpUnRegisterClient(upnp_client_handle); + } UpnpGlobalFinish(); } diff -Nru mpd-0.19.21/src/lib/upnp/ClientInit.hxx mpd-0.20.9/src/lib/upnp/ClientInit.hxx --- mpd-0.19.21/src/lib/upnp/ClientInit.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/ClientInit.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,10 +24,8 @@ #include -class Error; - -bool -UpnpClientGlobalInit(UpnpClient_Handle &handle, Error &error); +void +UpnpClientGlobalInit(UpnpClient_Handle &handle); void UpnpClientGlobalFinish(); diff -Nru mpd-0.19.21/src/lib/upnp/ContentDirectoryService.cxx mpd-0.20.9/src/lib/upnp/ContentDirectoryService.cxx --- mpd-0.19.21/src/lib/upnp/ContentDirectoryService.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/ContentDirectoryService.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,13 +19,13 @@ #include "config.h" #include "ContentDirectoryService.hxx" -#include "Domain.hxx" +#include "UniqueIxml.hxx" #include "Device.hxx" #include "ixmlwrap.hxx" #include "Util.hxx" #include "Action.hxx" #include "util/UriUtil.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" ContentDirectoryService::ContentDirectoryService(const UPnPDevice &device, const UPnPService &service) @@ -49,46 +49,34 @@ /* this destructor exists here just so it won't get inlined */ } -bool -ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl, - std::list &result, - Error &error) const +std::list +ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl) const { - assert(result.empty()); + UniqueIxmlDocument request(UpnpMakeAction("GetSearchCapabilities", m_serviceType.c_str(), + 0, + nullptr, nullptr)); + if (!request) + throw std::runtime_error("UpnpMakeAction() failed"); - IXML_Document *request = - UpnpMakeAction("GetSearchCapabilities", m_serviceType.c_str(), - 0, - nullptr, nullptr); - if (request == 0) { - error.Set(upnp_domain, "UpnpMakeAction() failed"); - return false; - } - - IXML_Document *response; + IXML_Document *_response; auto code = UpnpSendAction(hdl, m_actionURL.c_str(), m_serviceType.c_str(), - 0 /*devUDN*/, request, &response); - ixmlDocument_free(request); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSendAction() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } + 0 /*devUDN*/, request.get(), &_response); + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSendAction() failed: %s", + UpnpGetErrorMessage(code)); - const char *s = ixmlwrap::getFirstElementValue(response, "SearchCaps"); - if (s == nullptr || *s == 0) { - ixmlDocument_free(response); - return true; - } + UniqueIxmlDocument response(_response); - bool success = true; - if (!csvToStrings(s, result)) { - error.Set(upnp_domain, "Bad response"); - success = false; - } + std::list result; + + const char *s = ixmlwrap::getFirstElementValue(response.get(), + "SearchCaps"); + if (s == nullptr || *s == 0) + return result; + + if (!csvToStrings(s, result)) + throw std::runtime_error("Bad response"); - ixmlDocument_free(response); - return success; + return result; } diff -Nru mpd-0.19.21/src/lib/upnp/ContentDirectoryService.hxx mpd-0.20.9/src/lib/upnp/ContentDirectoryService.hxx --- mpd-0.19.21/src/lib/upnp/ContentDirectoryService.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/ContentDirectoryService.hxx 2017-06-04 10:39:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,6 @@ #include #include -class Error; class UPnPDevice; struct UPnPService; class UPnPDirContent; @@ -62,7 +61,8 @@ /** * Construct by copying data from device and service objects. * - * The discovery service does this: use getDirServices() + * The discovery service does this: use + * UPnPDeviceDirectory::GetDirectories() */ ContentDirectoryService(const UPnPDevice &device, const UPnPService &service); @@ -75,17 +75,14 @@ /** Read a container's children list into dirbuf. * * @param objectId the UPnP object Id for the container. Root has Id "0" - * @param[out] dirbuf stores the entries we read. */ - bool readDir(UpnpClient_Handle handle, - const char *objectId, UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent readDir(UpnpClient_Handle handle, + const char *objectId) const; - bool readDirSlice(UpnpClient_Handle handle, + void readDirSlice(UpnpClient_Handle handle, const char *objectId, unsigned offset, unsigned count, UPnPDirContent& dirbuf, - unsigned &didread, unsigned &total, - Error &error) const; + unsigned &didread, unsigned &total) const; /** Search the content directory service. * @@ -95,39 +92,34 @@ * @param searchstring an UPnP searchcriteria string. Check the * UPnP document: UPnP-av-ContentDirectory-v1-Service-20020625.pdf * section 2.5.5. Maybe we'll provide an easier way some day... - * @param[out] dirbuf stores the entries we read. */ - bool search(UpnpClient_Handle handle, - const char *objectId, const char *searchstring, - UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent search(UpnpClient_Handle handle, + const char *objectId, + const char *searchstring) const; /** Read metadata for a given node. * * @param objectId the UPnP object Id. Root has Id "0" - * @param[out] dirbuf stores the entries we read. At most one entry will be - * returned. */ - bool getMetadata(UpnpClient_Handle handle, - const char *objectId, UPnPDirContent &dirbuf, - Error &error) const; + UPnPDirContent getMetadata(UpnpClient_Handle handle, + const char *objectId) const; /** Retrieve search capabilities * + * Throws std::runtime_error on error. + * * @param[out] result an empty vector: no search, or a single '*' element: * any tag can be used in a search, or a list of usable tag names. */ - bool getSearchCapabilities(UpnpClient_Handle handle, - std::list &result, - Error &error) const; + std::list getSearchCapabilities(UpnpClient_Handle handle) const; gcc_pure - std::string GetURI() const { + std::string GetURI() const noexcept { return "upnp://" + m_deviceId + "/" + m_serviceType; } /** Retrieve the "friendly name" for this server, useful for display. */ - const char *getFriendlyName() const { + const char *getFriendlyName() const noexcept { return m_friendlyName.c_str(); } }; diff -Nru mpd-0.19.21/src/lib/upnp/Device.cxx mpd-0.20.9/src/lib/upnp/Device.cxx --- mpd-0.19.21/src/lib/upnp/Device.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Device.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,9 +21,6 @@ #include "Device.hxx" #include "Util.hxx" #include "lib/expat/ExpatParser.hxx" -#include "util/Error.hxx" - -#include #include @@ -100,15 +97,12 @@ } }; -bool -UPnPDevice::Parse(const std::string &url, const char *description, - Error &error) +void +UPnPDevice::Parse(const std::string &url, const char *description) { { UPnPDeviceParser mparser(*this); - if (!mparser.Parse(description, strlen(description), - true, error)) - return false; + mparser.Parse(description, strlen(description), true); } if (URLBase.empty()) { @@ -129,6 +123,4 @@ } } } - - return true; } diff -Nru mpd-0.19.21/src/lib/upnp/Device.hxx mpd-0.20.9/src/lib/upnp/Device.hxx --- mpd-0.19.21/src/lib/upnp/Device.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Device.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,8 +23,6 @@ #include #include -class Error; - /** * UPnP Description phase: interpreting the device description which we * downloaded from the URL obtained by the discovery phase. @@ -81,8 +79,7 @@ * @param url where the description came from * @param description the xml device description */ - bool Parse(const std::string &url, const char *description, - Error &error); + void Parse(const std::string &url, const char *description); }; #endif /* _UPNPDEV_HXX_INCLUDED_ */ diff -Nru mpd-0.19.21/src/lib/upnp/Discovery.cxx mpd-0.20.9/src/lib/upnp/Discovery.cxx --- mpd-0.19.21/src/lib/upnp/Discovery.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Discovery.cxx 2017-05-08 15:14:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,10 +19,10 @@ #include "config.h" #include "Discovery.hxx" -#include "Domain.hxx" #include "ContentDirectoryService.hxx" -#include "system/Clock.hxx" #include "Log.hxx" +#include "util/ScopeExit.hxx" +#include "util/RuntimeError.hxx" #include @@ -36,7 +36,7 @@ // version 1 gcc_pure static bool -isCDService(const char *st) +isCDService(const char *st) noexcept { constexpr size_t sz = sizeof(ContentDirectorySType) - 3; return memcmp(ContentDirectorySType, st, sz) == 0; @@ -47,7 +47,7 @@ gcc_pure static bool -isMSDevice(const char *st) +isMSDevice(const char *st) noexcept { constexpr size_t sz = sizeof(MediaServerDType) - 3; return memcmp(MediaServerDType, st, sz) == 0; @@ -74,7 +74,7 @@ inline void UPnPDeviceDirectory::LockAdd(ContentDirectoryDescriptor &&d) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); for (auto &i : directories) { if (i.id == d.id) { @@ -92,7 +92,7 @@ inline void UPnPDeviceDirectory::LockRemove(const std::string &id) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); for (auto i = directories.begin(), end = directories.end(); i != end; ++i) { @@ -107,12 +107,12 @@ } inline void -UPnPDeviceDirectory::discoExplorer() +UPnPDeviceDirectory::Explore() { for (;;) { - DiscoveredTask *tsk = 0; - if (!discoveredQueue.take(tsk)) { - discoveredQueue.workerExit(); + std::unique_ptr tsk; + if (!queue.take(tsk)) { + queue.workerExit(); return; } @@ -127,31 +127,28 @@ continue; } - // Update or insert the device - ContentDirectoryDescriptor d(std::move(tsk->deviceId), - MonotonicClockS(), tsk->expires); + AtScopeExit(buf){ free(buf); }; - { - Error error2; - bool success = d.Parse(tsk->url, buf, error2); - free(buf); - if (!success) { - delete tsk; - LogError(error2); - continue; - } + // Update or insert the device + ContentDirectoryDescriptor d(std::move(tsk->device_id), + std::chrono::steady_clock::now(), + tsk->expires); + + try { + d.Parse(tsk->url, buf); + } catch (const std::exception &e) { + LogError(e); } LockAdd(std::move(d)); - delete tsk; } } void * -UPnPDeviceDirectory::discoExplorer(void *ctx) +UPnPDeviceDirectory::Explore(void *ctx) { UPnPDeviceDirectory &directory = *(UPnPDeviceDirectory *)ctx; - directory.discoExplorer(); + directory.Explore(); return (void*)1; } @@ -161,7 +158,7 @@ if (isMSDevice(disco->DeviceType) || isCDService(disco->ServiceType)) { DiscoveredTask *tp = new DiscoveredTask(disco); - if (discoveredQueue.put(tp)) + if (queue.put(tp)) return UPNP_E_FINISH; } @@ -209,11 +206,10 @@ return UPNP_E_SUCCESS; } -bool -UPnPDeviceDirectory::expireDevices(Error &error) +void +UPnPDeviceDirectory::ExpireDevices() { - const ScopeLock protect(mutex); - const unsigned now = MonotonicClockS(); + const auto now = std::chrono::steady_clock::now(); bool didsomething = false; for (auto it = directories.begin(); @@ -227,17 +223,14 @@ } if (didsomething) - return search(error); - - return true; + Search(); } UPnPDeviceDirectory::UPnPDeviceDirectory(UpnpClient_Handle _handle, UPnPDiscoveryListener *_listener) :handle(_handle), listener(_listener), - discoveredQueue("DiscoveredQueue"), - m_searchTimeout(2), m_lastSearch(0) + queue("DiscoveredQueue") { } @@ -246,57 +239,45 @@ /* this destructor exists here just so it won't get inlined */ } -bool -UPnPDeviceDirectory::Start(Error &error) +void +UPnPDeviceDirectory::Start() { - if (!discoveredQueue.start(1, discoExplorer, this)) { - error.Set(upnp_domain, "Discover work queue start failed"); - return false; - } + if (!queue.start(1, Explore, this)) + throw std::runtime_error("Discover work queue start failed"); - return search(error); + Search(); } -bool -UPnPDeviceDirectory::search(Error &error) +void +UPnPDeviceDirectory::Search() { - const unsigned now = MonotonicClockS(); - if (now - m_lastSearch < 10) - return true; - m_lastSearch = now; + const auto now = std::chrono::steady_clock::now(); + if (now - last_search < std::chrono::seconds(10)) + return; + last_search = now; // We search both for device and service just in case. - int code = UpnpSearchAsync(handle, m_searchTimeout, + int code = UpnpSearchAsync(handle, search_timeout, ContentDirectorySType, GetUpnpCookie()); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSearchAsync() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSearchAsync() failed: %s", + UpnpGetErrorMessage(code)); - code = UpnpSearchAsync(handle, m_searchTimeout, + code = UpnpSearchAsync(handle, search_timeout, MediaServerDType, GetUpnpCookie()); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpSearchAsync() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } - - return true; + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpSearchAsync() failed: %s", + UpnpGetErrorMessage(code)); } -bool -UPnPDeviceDirectory::getDirServices(std::vector &out, - Error &error) +std::vector +UPnPDeviceDirectory::GetDirectories() { - // Has locking, do it before our own lock - if (!expireDevices(error)) - return false; + const std::lock_guard protect(mutex); - const ScopeLock protect(mutex); + ExpireDevices(); + std::vector out; for (auto dit = directories.begin(); dit != directories.end(); dit++) { for (const auto &service : dit->device.services) { @@ -306,35 +287,27 @@ } } - return true; + return out; } -bool -UPnPDeviceDirectory::getServer(const char *friendlyName, - ContentDirectoryService &server, - Error &error) +ContentDirectoryService +UPnPDeviceDirectory::GetServer(const char *friendly_name) { - // Has locking, do it before our own lock - if (!expireDevices(error)) - return false; + const std::lock_guard protect(mutex); - const ScopeLock protect(mutex); + ExpireDevices(); for (const auto &i : directories) { const auto &device = i.device; - if (device.friendlyName != friendlyName) + if (device.friendlyName != friendly_name) continue; - for (const auto &service : device.services) { - if (isCDService(service.serviceType.c_str())) { - server = ContentDirectoryService(device, - service); - return true; - } - } + for (const auto &service : device.services) + if (isCDService(service.serviceType.c_str())) + return ContentDirectoryService(device, + service); } - error.Set(upnp_domain, "Server not found"); - return false; + throw std::runtime_error("Server not found"); } diff -Nru mpd-0.19.21/src/lib/upnp/Discovery.hxx mpd-0.20.9/src/lib/upnp/Discovery.hxx --- mpd-0.19.21/src/lib/upnp/Discovery.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Discovery.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,6 @@ #include "Device.hxx" #include "WorkQueue.hxx" #include "thread/Mutex.hxx" -#include "util/Error.hxx" #include "Compiler.h" #include @@ -32,6 +31,8 @@ #include #include #include +#include +#include class ContentDirectoryService; @@ -55,13 +56,13 @@ */ struct DiscoveredTask { std::string url; - std::string deviceId; - unsigned expires; // Seconds valid + std::string device_id; + std::chrono::steady_clock::duration expires; DiscoveredTask(const Upnp_Discovery *disco) :url(disco->Location), - deviceId(disco->DeviceId), - expires(disco->Expires) {} + device_id(disco->DeviceId), + expires(std::chrono::seconds(disco->Expires)) {} }; /** @@ -75,20 +76,20 @@ UPnPDevice device; /** - * The MonotonicClockS() time stamp when this device - * expires. + * The time stamp when this device expires. */ - unsigned expires; + std::chrono::steady_clock::time_point expires; ContentDirectoryDescriptor() = default; ContentDirectoryDescriptor(std::string &&_id, - unsigned last, int exp) - :id(std::move(_id)), expires(last + exp + 20) {} + std::chrono::steady_clock::time_point last, + std::chrono::steady_clock::duration exp) + :id(std::move(_id)), + expires(last + exp + std::chrono::seconds(20)) {} - bool Parse(const std::string &url, const char *description, - Error &_error) { - return device.Parse(url, description, _error); + void Parse(const std::string &url, const char *description) { + device.Parse(url, description); } }; @@ -97,19 +98,19 @@ Mutex mutex; std::list directories; - WorkQueue discoveredQueue; + WorkQueue> queue; /** * The UPnP device search timeout, which should actually be * called delay because it's the base of a random delay that * the devices apply to avoid responding all at the same time. */ - int m_searchTimeout; + int search_timeout = 2; /** - * The MonotonicClockS() time stamp of the last search. + * The time stamp of the last search. */ - unsigned m_lastSearch; + std::chrono::steady_clock::time_point last_search = std::chrono::steady_clock::time_point(); public: UPnPDeviceDirectory(UpnpClient_Handle _handle, @@ -119,27 +120,27 @@ UPnPDeviceDirectory(const UPnPDeviceDirectory &) = delete; UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &) = delete; - bool Start(Error &error); + void Start(); /** Retrieve the directory services currently seen on the network */ - bool getDirServices(std::vector &, Error &); + std::vector GetDirectories(); /** * Get server by friendly name. */ - bool getServer(const char *friendlyName, - ContentDirectoryService &server, - Error &error); + ContentDirectoryService GetServer(const char *friendly_name); private: - bool search(Error &error); + void Search(); /** * Look at the devices and get rid of those which have not * been seen for too long. We do this when listing the top * directory. + * + * Caller must lock #mutex. */ - bool expireDevices(Error &error); + void ExpireDevices(); void LockAdd(ContentDirectoryDescriptor &&d); void LockRemove(const std::string &id); @@ -149,12 +150,11 @@ * devices appearing and disappearing, and update the * directory pool accordingly. */ - static void *discoExplorer(void *); - void discoExplorer(); + static void *Explore(void *); + void Explore(); int OnAlive(Upnp_Discovery *disco); int OnByeBye(Upnp_Discovery *disco); - int cluCallBack(Upnp_EventType et, void *evp); /* virtual methods from class UpnpCallback */ virtual int Invoke(Upnp_EventType et, void *evp) override; diff -Nru mpd-0.19.21/src/lib/upnp/Domain.cxx mpd-0.20.9/src/lib/upnp/Domain.cxx --- mpd-0.19.21/src/lib/upnp/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Domain.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "Domain.hxx" -#include "util/Domain.hxx" - -const Domain upnp_domain("upnp"); diff -Nru mpd-0.19.21/src/lib/upnp/Domain.hxx mpd-0.20.9/src/lib/upnp/Domain.hxx --- mpd-0.19.21/src/lib/upnp/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Domain.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_UPNP_DOMAIN_HXX -#define MPD_UPNP_DOMAIN_HXX - -class Domain; - -extern const Domain upnp_domain; - -#endif diff -Nru mpd-0.19.21/src/lib/upnp/Init.cxx mpd-0.20.9/src/lib/upnp/Init.cxx --- mpd-0.19.21/src/lib/upnp/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Init.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,52 +19,47 @@ #include "config.h" #include "Init.hxx" -#include "Domain.hxx" #include "thread/Mutex.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include #include #include +#include + static Mutex upnp_init_mutex; static unsigned upnp_ref; -static bool -DoInit(Error &error) +static void +DoInit() { auto code = UpnpInit(0, 0); - if (code != UPNP_E_SUCCESS) { - error.Format(upnp_domain, code, - "UpnpInit() failed: %s", - UpnpGetErrorMessage(code)); - return false; - } + if (code != UPNP_E_SUCCESS) + throw FormatRuntimeError("UpnpInit() failed: %s", + UpnpGetErrorMessage(code)); UpnpSetMaxContentLength(2000*1024); // Servers sometimes make error (e.g.: minidlna returns bad utf-8) ixmlRelaxParser(1); - - return true; } -bool -UpnpGlobalInit(Error &error) +void +UpnpGlobalInit() { - const ScopeLock protect(upnp_init_mutex); + const std::lock_guard protect(upnp_init_mutex); - if (upnp_ref == 0 && !DoInit(error)) - return false; + if (upnp_ref == 0) + DoInit(); ++upnp_ref; - return true; } void UpnpGlobalFinish() { - const ScopeLock protect(upnp_init_mutex); + const std::lock_guard protect(upnp_init_mutex); assert(upnp_ref > 0); diff -Nru mpd-0.19.21/src/lib/upnp/Init.hxx mpd-0.20.9/src/lib/upnp/Init.hxx --- mpd-0.19.21/src/lib/upnp/Init.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Init.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,10 +22,8 @@ #include "check.h" -class Error; - -bool -UpnpGlobalInit(Error &error); +void +UpnpGlobalInit(); void UpnpGlobalFinish(); diff -Nru mpd-0.19.21/src/lib/upnp/ixmlwrap.cxx mpd-0.20.9/src/lib/upnp/ixmlwrap.cxx --- mpd-0.19.21/src/lib/upnp/ixmlwrap.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/ixmlwrap.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -16,29 +16,26 @@ */ #include "ixmlwrap.hxx" +#include "UniqueIxml.hxx" namespace ixmlwrap { const char * getFirstElementValue(IXML_Document *doc, const char *name) { - const char *ret = nullptr; - IXML_NodeList *nodes = - ixmlDocument_getElementsByTagName(doc, name); - - if (nodes) { - IXML_Node *first = ixmlNodeList_item(nodes, 0); - if (first) { - IXML_Node *dnode = ixmlNode_getFirstChild(first); - if (dnode) { - ret = ixmlNode_getNodeValue(dnode); - } - } + UniqueIxmlNodeList nodes(ixmlDocument_getElementsByTagName(doc, name)); + if (!nodes) + return nullptr; + + IXML_Node *first = ixmlNodeList_item(nodes.get(), 0); + if (!first) + return nullptr; + + IXML_Node *dnode = ixmlNode_getFirstChild(first); + if (!dnode) + return nullptr; - ixmlNodeList_free(nodes); - } - - return ret; + return ixmlNode_getNodeValue(dnode); } } diff -Nru mpd-0.19.21/src/lib/upnp/UniqueIxml.hxx mpd-0.20.9/src/lib/upnp/UniqueIxml.hxx --- mpd-0.19.21/src/lib/upnp/UniqueIxml.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/UniqueIxml.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_UPNP_UNIQUE_XML_HXX +#define MPD_UPNP_UNIQUE_XML_HXX + +#include + +#include + +struct UpnpIxmlDeleter { + void operator()(IXML_Document *doc) { + ixmlDocument_free(doc); + } + + void operator()(IXML_NodeList *nl) { + ixmlNodeList_free(nl); + } +}; + +typedef std::unique_ptr UniqueIxmlDocument; +typedef std::unique_ptr UniqueIxmlNodeList; + +#endif diff -Nru mpd-0.19.21/src/lib/upnp/Util.cxx mpd-0.20.9/src/lib/upnp/Util.cxx --- mpd-0.19.21/src/lib/upnp/Util.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Util.cxx 2017-05-08 15:14:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,13 +19,11 @@ #include "Util.hxx" -#include - #include /** Get rid of white space at both ends */ void -trimstring(std::string &s, const char *ws) +trimstring(std::string &s, const char *ws) noexcept { auto pos = s.find_first_not_of(ws); if (pos == std::string::npos) { @@ -40,14 +38,14 @@ } static void -path_catslash(std::string &s) +path_catslash(std::string &s) noexcept { if (s.empty() || s.back() != '/') s += '/'; } std::string -path_getfather(const std::string &s) +path_getfather(const std::string &s) noexcept { std::string father = s; @@ -73,20 +71,19 @@ std::list stringToTokens(const std::string &str, - const char *delims, bool skipinit) + const char delim) noexcept { std::list tokens; - std::string::size_type startPos = 0; + std::string::size_type startPos = str.find_first_not_of(delim, 0); // Skip initial delims, return empty if this eats all. - if (skipinit && - (startPos = str.find_first_not_of(delims, 0)) == std::string::npos) + if (startPos == std::string::npos) return tokens; while (startPos < str.size()) { // Find next delimiter or end of string (end of token) - auto pos = str.find_first_of(delims, startPos); + auto pos = str.find_first_of(delim, startPos); // Add token to the vector and adjust start if (pos == std::string::npos) { @@ -108,7 +105,7 @@ template bool -csvToStrings(const char *s, T &tokens) +csvToStrings(const char *s, T &tokens) noexcept { assert(tokens.empty()); @@ -135,4 +132,4 @@ } } -template bool csvToStrings>(const char *, std::list &); +template bool csvToStrings>(const char *, std::list &) noexcept; diff -Nru mpd-0.19.21/src/lib/upnp/Util.hxx mpd-0.20.9/src/lib/upnp/Util.hxx --- mpd-0.19.21/src/lib/upnp/Util.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/Util.hxx 2017-05-08 15:13:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,18 +26,17 @@ #include void -trimstring(std::string &s, const char *ws = " \t\n"); +trimstring(std::string &s, const char *ws = " \t\n") noexcept; std::string -path_getfather(const std::string &s); +path_getfather(const std::string &s) noexcept; gcc_pure std::list -stringToTokens(const std::string &str, - const char *delims = "/", bool skipinit = true); +stringToTokens(const std::string &str, char delim) noexcept; template bool -csvToStrings(const char *s, T &tokens); +csvToStrings(const char *s, T &tokens) noexcept; #endif /* _UPNPP_H_X_INCLUDED_ */ diff -Nru mpd-0.19.21/src/lib/upnp/WorkQueue.hxx mpd-0.20.9/src/lib/upnp/WorkQueue.hxx --- mpd-0.19.21/src/lib/upnp/WorkQueue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/upnp/WorkQueue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -52,11 +52,11 @@ // Status // Worker threads having called exit - unsigned n_workers_exited; - bool ok; + unsigned n_workers_exited = 0; + bool ok = false; - unsigned n_threads; - pthread_t *threads; + unsigned n_threads = 0; + pthread_t *threads = nullptr; // Synchronization std::queue queue; @@ -66,16 +66,10 @@ public: /** Create a WorkQueue - * @param name for message printing - * @param hi number of tasks on queue before clients blocks. Default 0 - * meaning no limit. hi == -1 means that the queue is disabled. - * @param lo minimum count of tasks before worker starts. Default 1. - */ - WorkQueue(const char *_name) - :name(_name), - n_workers_exited(0), - ok(false), - n_threads(0), threads(nullptr) + * @param _name for message printing + */ + explicit WorkQueue(const char *_name) + :name(_name) { } @@ -83,23 +77,27 @@ setTerminateAndWait(); } + WorkQueue(const WorkQueue &) = delete; + WorkQueue &operator=(const WorkQueue &) = delete; + /** Start the worker threads. * * @param nworkers number of threads copies to start. - * @param start_routine thread function. It should loop + * @param workproc thread function. It should loop * taking (QueueWorker::take()) and executing tasks. * @param arg initial parameter to thread function. * @return true if ok. */ bool start(unsigned nworkers, void *(*workproc)(void *), void *arg) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(nworkers > 0); assert(!ok); assert(n_threads == 0); assert(threads == nullptr); + ok = true; n_threads = nworkers; threads = new pthread_t[n_threads]; @@ -112,7 +110,6 @@ } } - ok = true; return true; } @@ -123,7 +120,7 @@ template bool put(U &&u) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); queue.emplace(std::forward(u)); @@ -138,7 +135,7 @@ */ void setTerminateAndWait() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); // Wait for all worker threads to have called workerExit() ok = false; @@ -169,7 +166,7 @@ */ bool take(T &tp) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (!ok) return false; @@ -195,7 +192,7 @@ */ void workerExit() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); n_workers_exited++; ok = false; diff -Nru mpd-0.19.21/src/lib/xiph/OggFind.cxx mpd-0.20.9/src/lib/xiph/OggFind.cxx --- mpd-0.19.21/src/lib/xiph/OggFind.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggFind.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "OggFind.hxx" +#include "lib/xiph/OggSyncState.hxx" +#include "input/InputStream.hxx" + +#include + +bool +OggFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet) +{ + while (true) { + int r = ogg_stream_packetout(&os, &packet); + if (r == 0) { + if (!oy.ExpectPageIn(os)) + return false; + + continue; + } else if (r > 0 && packet.e_o_s) + return true; + } +} + +bool +OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is, + offset_type offset) +{ + oy.Reset(); + + /* reset the stream to clear any previous partial packet + data */ + ogg_stream_reset(&os); + + try { + is.LockSeek(offset); + } catch (const std::runtime_error &) { + return false; + } + + return oy.ExpectPageSeekIn(os); +} + +bool +OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, + InputStream &is) +{ + if (!is.KnownSize()) + return false; + + if (is.GetRest() < 65536) + return OggFindEOS(oy, os, packet); + + if (!is.CheapSeeking()) + return false; + + return OggSeekPageAtOffset(oy, os, is, is.GetSize() - 65536) && + OggFindEOS(oy, os, packet); +} diff -Nru mpd-0.19.21/src/lib/xiph/OggFind.hxx mpd-0.20.9/src/lib/xiph/OggFind.hxx --- mpd-0.19.21/src/lib/xiph/OggFind.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggFind.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_FIND_HXX +#define MPD_OGG_FIND_HXX + +#include "check.h" +#include "input/Offset.hxx" + +#include + +class OggSyncState; +class InputStream; + +/** + * Skip all pages/packets until an end-of-stream (EOS) packet for the + * specified stream is found. + * + * @return true if the EOS packet was found + */ +bool +OggFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet); + +/** + * Seek the #InputStream and find the next Ogg page. + */ +bool +OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is, + offset_type offset); + +/** + * Try to find the end-of-stream (EOS) packet. Seek to the end of the + * file if necessary. + * + * @return true if the EOS packet was found + */ +bool +OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, + InputStream &is); + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggPacket.cxx mpd-0.20.9/src/lib/xiph/OggPacket.cxx --- mpd-0.19.21/src/lib/xiph/OggPacket.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggPacket.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "OggPacket.hxx" +#include "OggSyncState.hxx" +#include "OggStreamState.hxx" + +bool +OggReadPacket(OggSyncState &sync, OggStreamState &stream, ogg_packet &packet) +{ + while (true) { + if (stream.PacketOut(packet)) + return true; + + if (!sync.ExpectPageIn(stream)) + return false; + } +} diff -Nru mpd-0.19.21/src/lib/xiph/OggPacket.hxx mpd-0.20.9/src/lib/xiph/OggPacket.hxx --- mpd-0.19.21/src/lib/xiph/OggPacket.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggPacket.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_PACKET_HXX +#define MPD_OGG_PACKET_HXX + +#include "check.h" + +#include + +class OggSyncState; +class OggStreamState; + +/** + * Read the next packet. If necessary, feed more data into + * #OggSyncState and feed more pages into #OggStreamState. + */ +bool +OggReadPacket(OggSyncState &sync, OggStreamState &stream, ogg_packet &packet); + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggPage.hxx mpd-0.20.9/src/lib/xiph/OggPage.hxx --- mpd-0.19.21/src/lib/xiph/OggPage.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggPage.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_PAGE_HXX +#define MPD_OGG_PAGE_HXX + +#include "check.h" + +#include + +#include +#include +#include + +static size_t +ReadPage(const ogg_page &page, void *_buffer, size_t size) +{ + assert(page.header_len > 0 || page.body_len > 0); + + size_t header_len = (size_t)page.header_len; + size_t body_len = (size_t)page.body_len; + assert(header_len <= size); + + if (header_len + body_len > size) + /* TODO: better overflow handling */ + body_len = size - header_len; + + uint8_t *buffer = (uint8_t *)_buffer; + memcpy(buffer, page.header, header_len); + memcpy(buffer + header_len, page.body, body_len); + + return header_len + body_len; +} + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggSerial.cxx mpd-0.20.9/src/lib/xiph/OggSerial.cxx --- mpd-0.19.21/src/lib/xiph/OggSerial.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggSerial.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "OggSerial.hxx" +#include "Compiler.h" + +#include +#include + +static std::atomic_uint next_ogg_serial; + +int +GenerateOggSerial() +{ + unsigned serial = ++next_ogg_serial; + if (gcc_unlikely(serial < 16)) { + /* first-time initialization: seed with a clock value, + which is random enough for our use */ + + /* this code is not race-free, but good enough */ + using namespace std::chrono; + const auto now = steady_clock::now().time_since_epoch(); + const auto now_ms = duration_cast(now); + const unsigned seed = now_ms.count(); + next_ogg_serial = serial = seed; + } + + return serial; +} + diff -Nru mpd-0.19.21/src/lib/xiph/OggSerial.hxx mpd-0.20.9/src/lib/xiph/OggSerial.hxx --- mpd-0.19.21/src/lib/xiph/OggSerial.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggSerial.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_SERIAL_HXX +#define MPD_OGG_SERIAL_HXX + +/** + * Generate the next pseudo-random Ogg serial. + */ +int +GenerateOggSerial(); + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggStreamState.hxx mpd-0.20.9/src/lib/xiph/OggStreamState.hxx --- mpd-0.19.21/src/lib/xiph/OggStreamState.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggStreamState.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,94 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_STREAM_STATE_HXX +#define MPD_OGG_STREAM_STATE_HXX + +#include "check.h" + +#include + +#include +#include +#include + +class OggStreamState { + ogg_stream_state state; + +public: + explicit OggStreamState(int serialno) { + ogg_stream_init(&state, serialno); + } + + /** + * Initialize a decoding #ogg_stream_state with the first + * page. + */ + explicit OggStreamState(ogg_page &page) { + ogg_stream_init(&state, ogg_page_serialno(&page)); + PageIn(page); + } + + ~OggStreamState() { + ogg_stream_clear(&state); + } + + operator ogg_stream_state &() { + return state; + } + + void Reinitialize(int serialno) { + ogg_stream_reset_serialno(&state, serialno); + } + + long GetSerialNo() const { + return state.serialno; + } + + void Reset() { + ogg_stream_reset(&state); + } + + /* encoding */ + + void PacketIn(const ogg_packet &packet) { + ogg_stream_packetin(&state, + const_cast(&packet)); + } + + bool PageOut(ogg_page &page) { + return ogg_stream_pageout(&state, &page) != 0; + } + + bool Flush(ogg_page &page) { + return ogg_stream_flush(&state, &page) != 0; + } + + /* decoding */ + + bool PageIn(ogg_page &page) { + return ogg_stream_pagein(&state, &page) == 0; + } + + int PacketOut(ogg_packet &packet) { + return ogg_stream_packetout(&state, &packet); + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggSyncState.cxx mpd-0.20.9/src/lib/xiph/OggSyncState.cxx --- mpd-0.19.21/src/lib/xiph/OggSyncState.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggSyncState.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "OggSyncState.hxx" +#include "fs/io/Reader.hxx" + +bool +OggSyncState::Feed(size_t size) +{ + char *buffer = ogg_sync_buffer(&oy, size); + if (buffer == nullptr) + return false; + + size_t nbytes = reader.Read(buffer, size); + if (nbytes == 0) + return false; + + ogg_sync_wrote(&oy, nbytes); + return true; +} + +bool +OggSyncState::ExpectPage(ogg_page &page) +{ + while (true) { + int r = ogg_sync_pageout(&oy, &page); + if (r != 0) + return r > 0; + + if (!Feed(1024)) + return false; + } +} + +bool +OggSyncState::ExpectPageIn(ogg_stream_state &os) +{ + ogg_page page; + if (!ExpectPage(page)) + return false; + + ogg_stream_pagein(&os, &page); + return true; +} + +bool +OggSyncState::ExpectPageSeek(ogg_page &page) +{ + size_t remaining_skipped = 32768; + + while (true) { + int r = ogg_sync_pageseek(&oy, &page); + if (r > 0) + return true; + + if (r < 0) { + /* skipped -r bytes */ + size_t nbytes = -r; + if (nbytes > remaining_skipped) + /* still no ogg page - we lost our + patience, abort */ + return false; + + remaining_skipped -= nbytes; + continue; + } + + if (!Feed(1024)) + return false; + } +} + +bool +OggSyncState::ExpectPageSeekIn(ogg_stream_state &os) +{ + ogg_page page; + if (!ExpectPageSeek(page)) + return false; + + ogg_stream_pagein(&os, &page); + return true; +} diff -Nru mpd-0.19.21/src/lib/xiph/OggSyncState.hxx mpd-0.20.9/src/lib/xiph/OggSyncState.hxx --- mpd-0.19.21/src/lib/xiph/OggSyncState.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggSyncState.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_SYNC_STATE_HXX +#define MPD_OGG_SYNC_STATE_HXX + +#include "check.h" + +#include + +#include + +class Reader; + +/** + * Wrapper for an ogg_sync_state. + */ +class OggSyncState { + ogg_sync_state oy; + + Reader &reader; + +public: + explicit OggSyncState(Reader &_reader) + :reader(_reader) { + ogg_sync_init(&oy); + } + + ~OggSyncState() { + ogg_sync_clear(&oy); + } + + OggSyncState(const OggSyncState &) = delete; + OggSyncState &operator=(const OggSyncState &) = delete; + + void Reset() { + ogg_sync_reset(&oy); + } + + bool Feed(size_t size); + + bool ExpectPage(ogg_page &page); + + bool ExpectPageIn(ogg_stream_state &os); + + bool ExpectPageSeek(ogg_page &page); + + bool ExpectPageSeekIn(ogg_stream_state &os); +}; + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/OggVisitor.cxx mpd-0.20.9/src/lib/xiph/OggVisitor.cxx --- mpd-0.19.21/src/lib/xiph/OggVisitor.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggVisitor.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,101 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "OggVisitor.hxx" + +#include + +void +OggVisitor::EndStream() +{ + if (!has_stream) + return; + + has_stream = false; + OnOggEnd(); +} + +inline bool +OggVisitor::ReadNextPage() +{ + ogg_page page; + if (!sync.ExpectPage(page)) + return false; + + const auto page_serialno = ogg_page_serialno(&page); + if (page_serialno != stream.GetSerialNo()) { + EndStream(); + stream.Reinitialize(page_serialno); + } + + stream.PageIn(page); + return true; +} + +inline void +OggVisitor::HandlePacket(const ogg_packet &packet) +{ + if (packet.b_o_s) { + EndStream(); + has_stream = true; + OnOggBeginning(packet); + return; + } + + if (!has_stream) + /* fail if BOS is missing */ + throw std::runtime_error("BOS packet expected"); + + if (packet.e_o_s) { + EndStream(); + return; + } + + OnOggPacket(packet); +} + +inline void +OggVisitor::HandlePackets() +{ + ogg_packet packet; + while (stream.PacketOut(packet) == 1) + HandlePacket(packet); +} + +void +OggVisitor::Visit() +{ + do { + HandlePackets(); + } while (ReadNextPage()); +} + +void +OggVisitor::PostSeek() +{ + sync.Reset(); + + /* reset the stream to clear any previous partial packet + data */ + stream.Reset(); + + /* find the next Ogg page and feed it into the stream */ + sync.ExpectPageSeekIn(stream); +} diff -Nru mpd-0.19.21/src/lib/xiph/OggVisitor.hxx mpd-0.20.9/src/lib/xiph/OggVisitor.hxx --- mpd-0.19.21/src/lib/xiph/OggVisitor.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/OggVisitor.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_VISITOR_HXX +#define MPD_OGG_VISITOR_HXX + +#include "check.h" +#include "OggSyncState.hxx" +#include "OggStreamState.hxx" + +#include + +#include + +class Reader; + +/** + * Abstract class which iterates over Ogg packets in a #Reader. + * Subclass it and implement the virtual methods. + */ +class OggVisitor { + OggSyncState sync; + OggStreamState stream; + + bool has_stream = false; + +public: + explicit OggVisitor(Reader &reader) + :sync(reader), stream(0) {} + + long GetSerialNo() const { + return stream.GetSerialNo(); + } + + void Visit(); + + /** + * Call this method after seeking the #Reader. + */ + void PostSeek(); + +private: + void EndStream(); + bool ReadNextPage(); + void HandlePacket(const ogg_packet &packet); + void HandlePackets(); + +protected: + virtual void OnOggBeginning(const ogg_packet &packet) = 0; + virtual void OnOggPacket(const ogg_packet &packet) = 0; + virtual void OnOggEnd() = 0; +}; + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/VorbisComment.hxx mpd-0.20.9/src/lib/xiph/VorbisComment.hxx --- mpd-0.19.21/src/lib/xiph/VorbisComment.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/VorbisComment.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_VORBIS_COMMENT_HXX +#define MPD_VORBIS_COMMENT_HXX + +#include "check.h" + +#include + +/** + * OO wrapper for a #vorbis_comment instance. + */ +class VorbisComment { + vorbis_comment vc; + +public: + VorbisComment() { + vorbis_comment_init(&vc); + } + + ~VorbisComment() { + vorbis_comment_clear(&vc); + } + + VorbisComment(const VorbisComment &) = delete; + VorbisComment &operator=(const VorbisComment &) = delete; + + operator vorbis_comment &() { + return vc; + } + + operator vorbis_comment *() { + return &vc; + } + + void AddTag(const char *tag, const char *contents) { + vorbis_comment_add_tag(&vc, tag, contents); + } +}; + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/VorbisComments.cxx mpd-0.20.9/src/lib/xiph/VorbisComments.cxx --- mpd-0.19.21/src/lib/xiph/VorbisComments.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/VorbisComments.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "VorbisComments.hxx" +#include "XiphTags.hxx" +#include "tag/TagTable.hxx" +#include "tag/TagHandler.hxx" +#include "tag/TagBuilder.hxx" +#include "tag/VorbisComment.hxx" +#include "tag/ReplayGain.hxx" +#include "ReplayGainInfo.hxx" +#include "util/DivideString.hxx" + +bool +vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments) +{ + rgi.Clear(); + + bool found = false; + + while (*comments) { + if (ParseReplayGainVorbis(rgi, *comments)) + found = true; + + comments++; + } + + return found; +} + +/** + * Check if the comment's name equals the passed name, and if so, copy + * the comment value into the tag. + */ +static bool +vorbis_copy_comment(const char *comment, + const char *name, TagType tag_type, + const TagHandler &handler, void *handler_ctx) +{ + const char *value; + + value = vorbis_comment_value(comment, name); + if (value != nullptr) { + tag_handler_invoke_tag(handler, handler_ctx, tag_type, value); + return true; + } + + return false; +} + +static void +vorbis_scan_comment(const char *comment, + const TagHandler &handler, void *handler_ctx) +{ + if (handler.pair != nullptr) { + const DivideString split(comment, '='); + if (split.IsDefined() && !split.IsEmpty()) + tag_handler_invoke_pair(handler, handler_ctx, + split.GetFirst(), + split.GetSecond()); + } + + for (const struct tag_table *i = xiph_tags; i->name != nullptr; ++i) + if (vorbis_copy_comment(comment, i->name, i->type, + handler, handler_ctx)) + return; + + for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) + if (vorbis_copy_comment(comment, + tag_item_names[i], TagType(i), + handler, handler_ctx)) + return; +} + +void +vorbis_comments_scan(char **comments, + const TagHandler &handler, void *handler_ctx) +{ + while (*comments) + vorbis_scan_comment(*comments++, + handler, handler_ctx); + +} + +Tag * +vorbis_comments_to_tag(char **comments) +{ + TagBuilder tag_builder; + vorbis_comments_scan(comments, add_tag_handler, &tag_builder); + return tag_builder.IsEmpty() + ? nullptr + : tag_builder.CommitNew(); +} diff -Nru mpd-0.19.21/src/lib/xiph/VorbisComments.hxx mpd-0.20.9/src/lib/xiph/VorbisComments.hxx --- mpd-0.19.21/src/lib/xiph/VorbisComments.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/VorbisComments.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_VORBIS_COMMENTS_HXX +#define MPD_VORBIS_COMMENTS_HXX + +#include "check.h" + +struct ReplayGainInfo; +struct TagHandler; +struct Tag; + +bool +vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments); + +void +vorbis_comments_scan(char **comments, + const TagHandler &handler, void *handler_ctx); + +Tag * +vorbis_comments_to_tag(char **comments); + +#endif diff -Nru mpd-0.19.21/src/lib/xiph/XiphTags.cxx mpd-0.20.9/src/lib/xiph/XiphTags.cxx --- mpd-0.19.21/src/lib/xiph/XiphTags.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/XiphTags.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* This File contains additional Tags for Xiph-Based Formats like Ogg-Vorbis, + * Flac and Opus which will be used in addition to the Tags in tag/TagNames.c + * see https://www.xiph.org/vorbis/doc/v-comment.html for further Info + */ +#include "config.h" +#include "XiphTags.hxx" + +const struct tag_table xiph_tags[] = { + { "tracknumber", TAG_TRACK }, + { "discnumber", TAG_DISC }, + { "description", TAG_COMMENT }, + { nullptr, TAG_NUM_OF_ITEM_TYPES } +}; diff -Nru mpd-0.19.21/src/lib/xiph/XiphTags.hxx mpd-0.20.9/src/lib/xiph/XiphTags.hxx --- mpd-0.19.21/src/lib/xiph/XiphTags.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/xiph/XiphTags.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_XIPH_TAGS_HXX +#define MPD_XIPH_TAGS_HXX + +#include "check.h" +#include "tag/TagTable.hxx" + +extern const struct tag_table xiph_tags[]; + +#endif diff -Nru mpd-0.19.21/src/lib/zlib/Domain.cxx mpd-0.20.9/src/lib/zlib/Domain.cxx --- mpd-0.19.21/src/lib/zlib/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/zlib/Domain.cxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Domain.hxx" -#include "util/Domain.hxx" - -const Domain zlib_domain("zlib"); diff -Nru mpd-0.19.21/src/lib/zlib/Domain.hxx mpd-0.20.9/src/lib/zlib/Domain.hxx --- mpd-0.19.21/src/lib/zlib/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/lib/zlib/Domain.hxx 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_ZLIB_DOMAIN_HXX -#define MPD_ZLIB_DOMAIN_HXX - -class Domain; - -extern const Domain zlib_domain; - -#endif diff -Nru mpd-0.19.21/src/lib/zlib/Error.cxx mpd-0.20.9/src/lib/zlib/Error.cxx --- mpd-0.19.21/src/lib/zlib/Error.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/zlib/Error.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Error.hxx" + +#include + +const char * +ZlibError::what() const noexcept +{ + return zError(code); +} diff -Nru mpd-0.19.21/src/lib/zlib/Error.hxx mpd-0.20.9/src/lib/zlib/Error.hxx --- mpd-0.19.21/src/lib/zlib/Error.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/lib/zlib/Error.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ZLIB_ERROR_HXX +#define MPD_ZLIB_ERROR_HXX + +#include + +class ZlibError final : public std::exception { + int code; + +public: + explicit ZlibError(int _code):code(_code) {} + + int GetCode() const { + return code; + } + + const char *what() const noexcept override; +}; + +#endif diff -Nru mpd-0.19.21/src/Listen.cxx mpd-0.20.9/src/Listen.cxx --- mpd-0.19.21/src/Listen.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Listen.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,13 @@ #include "config.h" #include "Listen.hxx" #include "client/Client.hxx" -#include "config/ConfigData.hxx" +#include "config/Param.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" +#include "net/SocketAddress.hxx" #include "event/ServerSocket.hxx" -#include "util/Error.hxx" +#include "system/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "fs/AllocatedPath.hxx" #include "Log.hxx" @@ -48,73 +50,65 @@ :ServerSocket(_loop), partition(_partition) {} private: - virtual void OnAccept(int fd, const sockaddr &address, - size_t address_length, int uid) { + void OnAccept(int fd, SocketAddress address, int uid) override { client_new(GetEventLoop(), partition, - fd, &address, address_length, uid); + fd, address, uid); } }; static ClientListener *listen_socket; int listen_port; -static bool +/** + * Throws #std::runtime_error on error. + */ +static void listen_add_config_param(unsigned int port, - const struct config_param *param, - Error &error_r) + const ConfigParam *param) { assert(param != nullptr); if (0 == strcmp(param->value.c_str(), "any")) { - return listen_socket->AddPort(port, error_r); + listen_socket->AddPort(port); } else if (param->value[0] == '/' || param->value[0] == '~') { - auto path = config_parse_path(param, error_r); - return !path.IsNull() && - listen_socket->AddPath(std::move(path), error_r); + listen_socket->AddPath(param->GetPath()); } else { - return listen_socket->AddHost(param->value.c_str(), port, - error_r); + listen_socket->AddHost(param->value.c_str(), port); } } #ifdef ENABLE_SYSTEMD_DAEMON static bool -listen_systemd_activation(Error &error_r) +listen_systemd_activation() { int n = sd_listen_fds(true); if (n <= 0) { if (n < 0) - FormatErrno(listen_domain, -n, - "sd_listen_fds() failed"); + throw MakeErrno(-n, "sd_listen_fds() failed"); return false; } for (int i = SD_LISTEN_FDS_START, end = SD_LISTEN_FDS_START + n; i != end; ++i) - if (!listen_socket->AddFD(i, error_r)) - return false; + listen_socket->AddFD(i); return true; } #endif -bool -listen_global_init(EventLoop &loop, Partition &partition, Error &error) +void +listen_global_init(EventLoop &loop, Partition &partition) { - int port = config_get_positive(CONF_PORT, DEFAULT_PORT); - const struct config_param *param = - config_get_param(CONF_BIND_TO_ADDRESS); + int port = config_get_positive(ConfigOption::PORT, DEFAULT_PORT); + const auto *param = config_get_param(ConfigOption::BIND_TO_ADDRESS); listen_socket = new ClientListener(loop, partition); #ifdef ENABLE_SYSTEMD_DAEMON - if (listen_systemd_activation(error)) - return true; - - if (error.IsDefined()) - return false; + if (listen_systemd_activation()) + return; #endif if (param != nullptr) { @@ -122,32 +116,35 @@ for all values */ do { - if (!listen_add_config_param(port, param, error)) { + try { + listen_add_config_param(port, param); + } catch (const std::runtime_error &e) { delete listen_socket; - error.FormatPrefix("Failed to listen on %s (line %i): ", - param->value.c_str(), - param->line); - return false; + std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)", + param->value.c_str(), + param->line)); } } while ((param = param->next) != nullptr); } else { /* no "bind_to_address" configured, bind the configured port on all interfaces */ - if (!listen_socket->AddPort(port, error)) { + try { + listen_socket->AddPort(port); + } catch (const std::runtime_error &e) { delete listen_socket; - error.FormatPrefix("Failed to listen on *:%d: ", port); - return false; + std::throw_with_nested(FormatRuntimeError("Failed to listen on *:%d: ", port)); } } - if (!listen_socket->Open(error)) { + try { + listen_socket->Open(); + } catch (const std::runtime_error &e) { delete listen_socket; - return false; + throw; } listen_port = port; - return true; } void listen_global_finish(void) diff -Nru mpd-0.19.21/src/Listen.hxx mpd-0.20.9/src/Listen.hxx --- mpd-0.19.21/src/Listen.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Listen.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,14 +21,14 @@ #define MPD_LISTEN_HXX class EventLoop; -class Error; struct Partition; extern int listen_port; -bool -listen_global_init(EventLoop &loop, Partition &partition, Error &error); +void +listen_global_init(EventLoop &loop, Partition &partition); -void listen_global_finish(void); +void +listen_global_finish(); #endif diff -Nru mpd-0.19.21/src/LocateUri.cxx mpd-0.20.9/src/LocateUri.cxx --- mpd-0.19.21/src/LocateUri.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/LocateUri.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "LocateUri.hxx" +#include "client/Client.hxx" +#include "fs/AllocatedPath.hxx" +#include "ls.hxx" +#include "util/UriUtil.hxx" +#include "util/StringCompare.hxx" + +#ifdef ENABLE_DATABASE +#include "storage/StorageInterface.hxx" +#endif + +static LocatedUri +LocateFileUri(const char *uri, const Client *client +#ifdef ENABLE_DATABASE + , const Storage *storage +#endif + ) +{ + auto path = AllocatedPath::FromUTF8Throw(uri); + +#ifdef ENABLE_DATABASE + if (storage != nullptr) { + const char *suffix = storage->MapToRelativeUTF8(uri); + if (suffix != nullptr) + /* this path was relative to the music + directory */ + return LocatedUri(LocatedUri::Type::RELATIVE, suffix); + } +#endif + + if (client != nullptr) + client->AllowFile(path); + + return LocatedUri(LocatedUri::Type::PATH, uri, std::move(path)); +} + +static LocatedUri +LocateAbsoluteUri(const char *uri +#ifdef ENABLE_DATABASE + , const Storage *storage +#endif + ) +{ + if (!uri_supported_scheme(uri)) + throw std::runtime_error("Unsupported URI scheme"); + +#ifdef ENABLE_DATABASE + if (storage != nullptr) { + const char *suffix = storage->MapToRelativeUTF8(uri); + if (suffix != nullptr) + return LocatedUri(LocatedUri::Type::RELATIVE, suffix); + } +#endif + + return LocatedUri(LocatedUri::Type::ABSOLUTE, uri); +} + +LocatedUri +LocateUri(const char *uri, const Client *client +#ifdef ENABLE_DATABASE + , const Storage *storage +#endif + ) +{ + /* skip the obsolete "file://" prefix */ + const char *path_utf8 = StringAfterPrefix(uri, "file://"); + if (path_utf8 != nullptr) { + if (!PathTraitsUTF8::IsAbsolute(path_utf8)) + throw std::runtime_error("Malformed file:// URI"); + + return LocateFileUri(path_utf8, client +#ifdef ENABLE_DATABASE + , storage +#endif + ); + } else if (PathTraitsUTF8::IsAbsolute(uri)) + return LocateFileUri(uri, client +#ifdef ENABLE_DATABASE + , storage +#endif + ); + else if (uri_has_scheme(uri)) + return LocateAbsoluteUri(uri +#ifdef ENABLE_DATABASE + , storage +#endif + ); + else + return LocatedUri(LocatedUri::Type::RELATIVE, uri); +} diff -Nru mpd-0.19.21/src/LocateUri.hxx mpd-0.20.9/src/LocateUri.hxx --- mpd-0.19.21/src/LocateUri.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/LocateUri.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_LOCATE_URI_HXX +#define MPD_LOCATE_URI_HXX + +#include "check.h" +#include "Compiler.h" +#include "fs/AllocatedPath.hxx" + +#ifdef WIN32 +#include +/* damn you, windows.h! */ +#ifdef ABSOLUTE +#undef ABSOLUTE +#endif +#ifdef RELATIVE +#undef RELATIVE +#endif +#endif + +class Client; + +#ifdef ENABLE_DATABASE +class Storage; +#endif + +struct LocatedUri { + enum class Type { + /** + * An absolute URI with a supported scheme. + */ + ABSOLUTE, + + /** + * A relative URI path. + */ + RELATIVE, + + /** + * A local file. The #path attribute is valid. + */ + PATH, + } type; + + const char *canonical_uri; + + /** + * Contains the local file path if type==FILE. + */ + AllocatedPath path; + + LocatedUri(Type _type, const char *_uri, + AllocatedPath &&_path=AllocatedPath::Null()) + :type(_type), canonical_uri(_uri), path(std::move(_path)) {} +}; + +/** + * Classify a URI. + * + * Throws #std::runtime_error on error. + * + * @param client the #Client that is used to determine whether a local + * file is allowed; nullptr disables the check and allows all local + * files + * @param storage a #Storage instance which may be used to convert + * absolute URIs to relative ones, using Storage::MapToRelativeUTF8(); + * that feature is disabled if this parameter is nullptr + */ +LocatedUri +LocateUri(const char *uri, const Client *client +#ifdef ENABLE_DATABASE + , const Storage *storage +#endif + ); + +#endif diff -Nru mpd-0.19.21/src/LogBackend.cxx mpd-0.20.9/src/LogBackend.cxx --- mpd-0.19.21/src/LogBackend.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/LogBackend.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,6 @@ #include "util/Domain.hxx" #include "util/StringUtil.hxx" -#ifdef HAVE_GLIB -#include -#endif - #include #include #include @@ -65,10 +61,6 @@ static LogLevel log_threshold = LogLevel::INFO; -#ifdef HAVE_GLIB -static const char *log_charset; -#endif - static bool enable_timestamp; #ifdef HAVE_SYSLOG @@ -81,16 +73,6 @@ log_threshold = _threshold; } -#ifdef HAVE_GLIB - -void -SetLogCharset(const char *_charset) -{ - log_charset = _charset; -} - -#endif - void EnableLogTimestamp() { @@ -175,20 +157,6 @@ static void FileLog(const Domain &domain, const char *message) { -#ifdef HAVE_GLIB - char *converted; - - if (log_charset != nullptr) { - converted = g_convert_with_fallback(message, -1, - log_charset, "utf-8", - nullptr, nullptr, - nullptr, nullptr); - if (converted != nullptr) - message = converted; - } else - converted = nullptr; -#endif - fprintf(stderr, "%s%s: %.*s\n", enable_timestamp ? log_date() : "", domain.GetName(), @@ -199,10 +167,6 @@ to have an effect on WIN32 */ fflush(stderr); #endif - -#ifdef HAVE_GLIB - g_free(converted); -#endif } #endif /* !ANDROID */ diff -Nru mpd-0.19.21/src/LogBackend.hxx mpd-0.20.9/src/LogBackend.hxx --- mpd-0.19.21/src/LogBackend.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/LogBackend.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,13 +26,6 @@ void SetLogThreshold(LogLevel _threshold); -#ifdef HAVE_GLIB - -void -SetLogCharset(const char *_charset); - -#endif - void EnableLogTimestamp(); diff -Nru mpd-0.19.21/src/Log.cxx mpd-0.20.9/src/Log.cxx --- mpd-0.19.21/src/Log.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Log.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,13 +19,16 @@ #include "config.h" #include "LogV.hxx" -#include "util/Error.hxx" +#include "util/Domain.hxx" + +#include -#include #include #include #include +static constexpr Domain exception_domain("exception"); + void LogFormatV(const Domain &domain, LogLevel level, const char *fmt, va_list ap) { @@ -89,20 +92,75 @@ } void -LogError(const Error &error) +LogError(const std::exception &e) +{ + Log(exception_domain, LogLevel::ERROR, e.what()); + + try { + std::rethrow_if_nested(e); + } catch (const std::exception &nested) { + LogError(nested, "nested"); + } catch (...) { + Log(exception_domain, LogLevel::ERROR, + "Unrecognized nested exception"); + } +} + +void +LogError(const std::exception &e, const char *msg) +{ + FormatError(exception_domain, "%s: %s", msg, e.what()); + + try { + std::rethrow_if_nested(e); + } catch (const std::exception &nested) { + LogError(nested); + } catch (...) { + Log(exception_domain, LogLevel::ERROR, + "Unrecognized nested exception"); + } +} + +void +FormatError(const std::exception &e, const char *fmt, ...) +{ + char msg[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + + LogError(e, msg); +} + +void +LogError(const std::exception_ptr &ep) { - Log(error.GetDomain(), LogLevel::ERROR, error.GetMessage()); + try { + std::rethrow_exception(ep); + } catch (const std::exception &e) { + LogError(e); + } catch (...) { + Log(exception_domain, LogLevel::ERROR, + "Unrecognized exception"); + } } void -LogError(const Error &error, const char *msg) +LogError(const std::exception_ptr &ep, const char *msg) { - LogFormat(error.GetDomain(), LogLevel::ERROR, "%s: %s", - msg, error.GetMessage()); + try { + std::rethrow_exception(ep); + } catch (const std::exception &e) { + LogError(e, msg); + } catch (...) { + FormatError(exception_domain, + "%s: Unrecognized exception", msg); + } } void -FormatError(const Error &error, const char *fmt, ...) +FormatError(const std::exception_ptr &ep, const char *fmt, ...) { char msg[1024]; va_list ap; @@ -110,7 +168,7 @@ vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); - LogError(error, msg); + LogError(ep, msg); } void diff -Nru mpd-0.19.21/src/Log.hxx mpd-0.20.9/src/Log.hxx --- mpd-0.19.21/src/Log.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Log.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,8 @@ #include "LogLevel.hxx" #include "Compiler.h" -class Error; +#include + class Domain; void @@ -79,19 +80,29 @@ Log(domain, LogLevel::ERROR, msg); } +void +LogError(const std::exception &e); + +void +LogError(const std::exception &e, const char *msg); + gcc_printf(2,3) void -FormatError(const Domain &domain, const char *fmt, ...); +FormatError(const std::exception &e, const char *fmt, ...); void -LogError(const Error &error); +LogError(const std::exception_ptr &ep); void -LogError(const Error &error, const char *msg); +LogError(const std::exception_ptr &ep, const char *msg); gcc_printf(2,3) void -FormatError(const Error &error, const char *fmt, ...); +FormatError(const std::exception_ptr &ep, const char *fmt, ...); + +gcc_printf(2,3) +void +FormatError(const Domain &domain, const char *fmt, ...); void LogErrno(const Domain &domain, int e, const char *msg); diff -Nru mpd-0.19.21/src/LogInit.cxx mpd-0.20.9/src/LogInit.cxx --- mpd-0.19.21/src/LogInit.cxx 2016-12-04 19:13:24.000000000 +0000 +++ mpd-0.20.9/src/LogInit.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,25 +21,19 @@ #include "LogInit.hxx" #include "LogBackend.hxx" #include "Log.hxx" -#include "config/ConfigData.hxx" +#include "config/Param.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" -#include "system/FatalError.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" -#include "system/FatalError.hxx" - -#ifdef HAVE_GLIB -#include -#endif +#include "util/RuntimeError.hxx" +#include "system/Error.hxx" #include #include #include #include -#include #include #define LOG_LEVEL_SECURE LogLevel::INFO @@ -58,9 +52,9 @@ { assert(fd >= 0); if (dup2(fd, STDOUT_FILENO) < 0) - FatalSystemError("Failed to dup2 stdout"); + throw MakeErrno("Failed to dup2 stdout"); if (dup2(fd, STDERR_FILENO) < 0) - FatalSystemError("Failed to dup2 stderr"); + throw MakeErrno("Failed to dup2 stderr"); } static int @@ -71,25 +65,30 @@ return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666); } -static bool -log_init_file(unsigned line, Error &error) +static void +log_init_file(int line) { assert(!out_path.IsNull()); out_fd = open_log_file(); if (out_fd < 0) { +#ifdef WIN32 + const std::string out_path_utf8 = out_path.ToUTF8(); + throw FormatRuntimeError("failed to open log file \"%s\" (config line %d)", + out_path_utf8.c_str(), line); +#else + int e = errno; const std::string out_path_utf8 = out_path.ToUTF8(); - error.FormatErrno("failed to open log file \"%s\" (config line %u)", + throw FormatErrno(e, "failed to open log file \"%s\" (config line %d)", out_path_utf8.c_str(), line); - return false; +#endif } EnableLogTimestamp(); - return true; } static inline LogLevel -parse_log_level(const char *value, unsigned line) +parse_log_level(const char *value, int line) { if (0 == strcmp(value, "default")) return LogLevel::DEFAULT; @@ -97,10 +96,9 @@ return LOG_LEVEL_SECURE; else if (0 == strcmp(value, "verbose")) return LogLevel::DEBUG; - else { - FormatFatalError("unknown log level \"%s\" at line %u", - value, line); - } + else + throw FormatRuntimeError("unknown log level \"%s\" at line %d", + value, line); } #endif @@ -119,54 +117,36 @@ #endif } -bool -log_init(bool verbose, bool use_stdout, Error &error) +void +log_init(bool verbose, bool use_stdout) { #ifdef ANDROID (void)verbose; (void)use_stdout; - (void)error; - - return true; #else - const struct config_param *param; - -#ifdef HAVE_GLIB - const char *charset; - g_get_charset(&charset); - SetLogCharset(charset); -#endif - if (verbose) SetLogThreshold(LogLevel::DEBUG); - else if ((param = config_get_param(CONF_LOG_LEVEL)) != nullptr) + else if (const auto ¶m = config_get_param(ConfigOption::LOG_LEVEL)) SetLogThreshold(parse_log_level(param->value.c_str(), param->line)); if (use_stdout) { - return true; + out_fd = STDOUT_FILENO; } else { - param = config_get_param(CONF_LOG_FILE); + const auto *param = config_get_param(ConfigOption::LOG_FILE); if (param == nullptr) { -#ifdef HAVE_SYSLOG /* no configuration: default to syslog (if available) */ - LogInitSysLog(); - return true; -#else - error.Set(log_domain, - "config parameter 'log_file' not found"); - return false; +#ifndef HAVE_SYSLOG + throw std::runtime_error("config parameter 'log_file' not found"); #endif #ifdef HAVE_SYSLOG } else if (strcmp(param->value.c_str(), "syslog") == 0) { LogInitSysLog(); - return true; #endif } else { - out_path = config_get_path(CONF_LOG_FILE, error); - return !out_path.IsNull() && - log_init_file(param->line, error); + out_path = param->GetPath(); + log_init_file(param->line); } } #endif @@ -193,12 +173,10 @@ #endif } -void setup_log_output(bool use_stdout) +void setup_log_output() { -#ifdef ANDROID - (void)use_stdout; -#else - if (use_stdout) +#ifndef ANDROID + if (out_fd == STDOUT_FILENO) return; fflush(nullptr); @@ -216,10 +194,6 @@ redirect_logs(out_fd); close(out_fd); out_fd = -1; - -#ifdef HAVE_GLIB - SetLogCharset(nullptr); -#endif #endif } diff -Nru mpd-0.19.21/src/LogInit.hxx mpd-0.20.9/src/LogInit.hxx --- mpd-0.19.21/src/LogInit.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/LogInit.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,6 @@ #ifndef MPD_LOG_INIT_HXX #define MPD_LOG_INIT_HXX -class Error; - /** * Configure a logging destination for daemon startup, before the * configuration file is read. This allows the daemon to use the @@ -33,14 +31,19 @@ void log_early_init(bool verbose); -bool -log_init(bool verbose, bool use_stdout, Error &error); +/** + * Throws #std::runtime_error on error. + */ +void +log_init(bool verbose, bool use_stdout); void -log_deinit(void); +log_deinit(); -void setup_log_output(bool use_stdout); +void +setup_log_output(); -int cycle_log_files(void); +int +cycle_log_files(); #endif /* LOG_H */ diff -Nru mpd-0.19.21/src/LogLevel.hxx mpd-0.20.9/src/LogLevel.hxx --- mpd-0.19.21/src/LogLevel.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/LogLevel.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/LogV.hxx mpd-0.20.9/src/LogV.hxx --- mpd-0.19.21/src/LogV.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/LogV.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/ls.cxx mpd-0.20.9/src/ls.cxx --- mpd-0.19.21/src/ls.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/ls.cxx 2017-05-08 13:15:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,9 +19,9 @@ #include "config.h" #include "ls.hxx" -#include "util/StringUtil.hxx" +#include "client/Response.hxx" +#include "util/StringCompare.hxx" #include "util/UriUtil.hxx" -#include "client/Client.hxx" #include @@ -30,7 +30,7 @@ * is detected at runtime and displayed as a urlhandler if the client is * connected by IPC socket. */ -static const char *remoteUrlPrefixes[] = { +static const char *const remoteUrlPrefixes[] = { #if defined(ENABLE_CURL) "http://", "https://", @@ -41,7 +41,7 @@ "mmst://", "mmsu://", #endif -#ifdef HAVE_FFMPEG +#ifdef ENABLE_FFMPEG "gopher://", "rtp://", "rtsp://", @@ -58,7 +58,7 @@ #ifdef ENABLE_CDIO_PARANOIA "cdda://", #endif -#ifdef HAVE_ALSA +#ifdef ENABLE_ALSA "alsa://", #endif NULL @@ -66,7 +66,7 @@ void print_supported_uri_schemes_to_fp(FILE *fp) { - const char **prefixes = remoteUrlPrefixes; + const char *const*prefixes = remoteUrlPrefixes; #ifdef HAVE_UN fprintf(fp, " file://"); @@ -78,19 +78,21 @@ fprintf(fp,"\n"); } -void print_supported_uri_schemes(Client &client) +void +print_supported_uri_schemes(Response &r) { - const char **prefixes = remoteUrlPrefixes; + const char *const *prefixes = remoteUrlPrefixes; while (*prefixes) { - client_printf(client, "handler: %s\n", *prefixes); + r.Format("handler: %s\n", *prefixes); prefixes++; } } -bool uri_supported_scheme(const char *uri) +bool +uri_supported_scheme(const char *uri) noexcept { - const char **urlPrefixes = remoteUrlPrefixes; + const char *const*urlPrefixes = remoteUrlPrefixes; assert(uri_has_scheme(uri)); diff -Nru mpd-0.19.21/src/ls.hxx mpd-0.20.9/src/ls.hxx --- mpd-0.19.21/src/ls.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/ls.hxx 2017-05-08 13:15:43.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,7 @@ #include -class Client; +class Response; /** * Checks whether the scheme of the specified URI is supported by MPD. @@ -32,13 +32,14 @@ * uri_has_scheme() first. */ gcc_pure -bool uri_supported_scheme(const char *url); +bool +uri_supported_scheme(const char *url) noexcept; /** * Send a list of supported URI schemes to the client. This is the * response to the "urlhandlers" command. */ -void print_supported_uri_schemes(Client &client); +void print_supported_uri_schemes(Response &r); /** * Send a list of supported URI schemes to a file pointer. diff -Nru mpd-0.19.21/src/Main.cxx mpd-0.20.9/src/Main.cxx --- mpd-0.19.21/src/Main.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Main.cxx 2017-05-16 05:20:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,10 +22,9 @@ #include "Instance.hxx" #include "CommandLine.hxx" #include "PlaylistFile.hxx" -#include "PlaylistGlobal.hxx" #include "MusicChunk.hxx" #include "StateFile.hxx" -#include "PlayerThread.hxx" +#include "player/Thread.hxx" #include "Mapper.hxx" #include "Permission.hxx" #include "Listen.hxx" @@ -34,11 +33,10 @@ #include "command/AllCommands.hxx" #include "Partition.hxx" #include "tag/TagConfig.hxx" -#include "ReplayGainConfig.hxx" +#include "ReplayGainGlobal.hxx" #include "Idle.hxx" #include "Log.hxx" #include "LogInit.hxx" -#include "GlobalEvents.hxx" #include "input/Init.hxx" #include "event/Loop.hxx" #include "IOThread.hxx" @@ -47,22 +45,22 @@ #include "playlist/PlaylistRegistry.hxx" #include "zeroconf/ZeroconfGlue.hxx" #include "decoder/DecoderList.hxx" -#include "AudioConfig.hxx" +#include "AudioParser.hxx" #include "pcm/PcmConvert.hxx" #include "unix/SignalHandlers.hxx" -#include "unix/Daemon.hxx" #include "system/FatalError.hxx" -#include "util/UriUtil.hxx" -#include "util/Error.hxx" -#include "thread/Id.hxx" #include "thread/Slack.hxx" #include "lib/icu/Init.hxx" #include "config/ConfigGlobal.hxx" -#include "config/ConfigData.hxx" +#include "config/Param.hxx" #include "config/ConfigDefaults.hxx" #include "config/ConfigOption.hxx" #include "config/ConfigError.hxx" -#include "Stats.hxx" +#include "util/RuntimeError.hxx" + +#ifdef ENABLE_DAEMON +#include "unix/Daemon.hxx" +#endif #ifdef ENABLE_DATABASE #include "db/update/Service.hxx" @@ -98,8 +96,8 @@ #include "org_musicpd_Bridge.h" #endif -#ifdef HAVE_GLIB -#include +#ifdef ENABLE_SYSTEMD_DAEMON +#include #endif #include @@ -119,7 +117,21 @@ #include -static constexpr unsigned DEFAULT_BUFFER_SIZE = 4096; +static constexpr size_t KILOBYTE = 1024; +static constexpr size_t MEGABYTE = 1024 * KILOBYTE; + +static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE; + +static +#if GCC_OLDER_THAN(5,0) +/* gcc 4.x has no "constexpr" for std::max() */ +const +#else +constexpr +#endif +size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32, + 64 * KILOBYTE); + static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10; #ifdef ANDROID @@ -128,55 +140,49 @@ Instance *instance; -static StateFile *state_file; +struct Config { + ReplayGainConfig replay_gain; +}; -#ifndef ANDROID +static Config +LoadConfig() +{ + return {LoadReplayGainConfig()}; +} -static bool -glue_daemonize_init(const struct options *options, Error &error) +#ifdef ENABLE_DAEMON + +static void +glue_daemonize_init(const struct options *options) { - auto pid_file = config_get_path(CONF_PID_FILE, error); - if (pid_file.IsNull() && error.IsDefined()) - return false; - - daemonize_init(config_get_string(CONF_USER, nullptr), - config_get_string(CONF_GROUP, nullptr), - std::move(pid_file)); + daemonize_init(config_get_string(ConfigOption::USER, nullptr), + config_get_string(ConfigOption::GROUP, nullptr), + config_get_path(ConfigOption::PID_FILE)); if (options->kill) daemonize_kill(); - - return true; } #endif -static bool -glue_mapper_init(Error &error) +static void +glue_mapper_init() { - auto playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error); - if (playlist_dir.IsNull() && error.IsDefined()) - return false; - - mapper_init(std::move(playlist_dir)); - return true; + mapper_init(config_get_path(ConfigOption::PLAYLIST_DIR)); } #ifdef ENABLE_DATABASE -static bool -InitStorage(Error &error) +static void +InitStorage() { - Storage *storage = CreateConfiguredStorage(io_thread_get(), error); + Storage *storage = CreateConfiguredStorage(io_thread_get()); if (storage == nullptr) - return !error.IsDefined(); - - assert(!error.IsDefined()); + return; CompositeStorage *composite = new CompositeStorage(); instance->storage = composite; composite->Mount("", storage); - return true; } /** @@ -187,20 +193,13 @@ static bool glue_db_init_and_load(void) { - Error error; instance->database = - CreateConfiguredDatabase(*instance->event_loop, *instance, - error); - if (instance->database == nullptr) { - if (error.IsDefined()) - FatalError(error); - else - return true; - } + CreateConfiguredDatabase(instance->event_loop, *instance); + if (instance->database == nullptr) + return true; if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) { - if (!InitStorage(error)) - FatalError(error); + InitStorage(); if (instance->storage == nullptr) { delete instance->database; @@ -217,14 +216,17 @@ "because the database does not need it"); } - if (!instance->database->Open(error)) - FatalError(error); + try { + instance->database->Open(); + } catch (...) { + std::throw_with_nested(std::runtime_error("Failed to open database plugin")); + } if (!instance->database->IsPlugin(simple_db_plugin)) return true; SimpleDatabase &db = *(SimpleDatabase *)instance->database; - instance->update = new UpdateService(*instance->event_loop, db, + instance->update = new UpdateService(instance->event_loop, db, static_cast(*instance->storage), *instance); @@ -245,49 +247,41 @@ * Configure and initialize the sticker subsystem. */ static void -glue_sticker_init(void) +glue_sticker_init() { #ifdef ENABLE_SQLITE - Error error; - auto sticker_file = config_get_path(CONF_STICKER_FILE, error); - if (sticker_file.IsNull()) { - if (error.IsDefined()) - FatalError(error); + auto sticker_file = config_get_path(ConfigOption::STICKER_FILE); + if (sticker_file.IsNull()) return; - } - if (!sticker_global_init(std::move(sticker_file), error)) - FatalError(error); + sticker_global_init(std::move(sticker_file)); #endif } -static bool -glue_state_file_init(Error &error) +static void +glue_state_file_init() { - auto path_fs = config_get_path(CONF_STATE_FILE, error); + auto path_fs = config_get_path(ConfigOption::STATE_FILE); if (path_fs.IsNull()) { - if (error.IsDefined()) - return false; - #ifdef ANDROID const auto cache_dir = GetUserCacheDir(); if (cache_dir.IsNull()) - return true; + return; path_fs = AllocatedPath::Build(cache_dir, "state"); #else - return true; + return; #endif } - unsigned interval = config_get_unsigned(CONF_STATE_FILE_INTERVAL, - StateFile::DEFAULT_INTERVAL); - - state_file = new StateFile(std::move(path_fs), interval, - *instance->partition, - *instance->event_loop); - state_file->Read(); - return true; + const auto interval = + config_get_unsigned(ConfigOption::STATE_FILE_INTERVAL, + StateFile::DEFAULT_INTERVAL); + + instance->state_file = new StateFile(std::move(path_fs), interval, + *instance->partition, + instance->event_loop); + instance->state_file->Read(); } /** @@ -313,12 +307,12 @@ * Initialize the decoder and player core, including the music pipe. */ static void -initialize_decoder_and_player(void) +initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config) { - const struct config_param *param; + const ConfigParam *param; size_t buffer_size; - param = config_get_param(CONF_AUDIO_BUFFER_SIZE); + param = config_get_param(ConfigOption::AUDIO_BUFFER_SIZE); if (param != nullptr) { char *test; long tmp = strtol(param->value.c_str(), &test, 10); @@ -326,12 +320,17 @@ FormatFatalError("buffer size \"%s\" is not a " "positive integer, line %i", param->value.c_str(), param->line); - buffer_size = tmp; + buffer_size = tmp * KILOBYTE; + + if (buffer_size < MIN_BUFFER_SIZE) { + FormatWarning(config_domain, "buffer size %lu is too small, using %lu bytes instead", + (unsigned long)buffer_size, + (unsigned long)MIN_BUFFER_SIZE); + buffer_size = MIN_BUFFER_SIZE; + } } else buffer_size = DEFAULT_BUFFER_SIZE; - buffer_size *= 1024; - const unsigned buffered_chunks = buffer_size / CHUNK_SIZE; if (buffered_chunks >= 1 << 15) @@ -339,7 +338,7 @@ (unsigned long)buffer_size); float perc; - param = config_get_param(CONF_BUFFER_BEFORE_PLAY); + param = config_get_param(ConfigOption::BUFFER_BEFORE_PLAY); if (param != nullptr) { char *test; perc = strtod(param->value.c_str(), &test); @@ -349,6 +348,19 @@ "than 100 percent, line %i", param->value.c_str(), param->line); } + + if (perc > 80) { + /* this upper limit should avoid deadlocks + which can occur because the DecoderThread + cannot ever fill the music buffer to + exactly 100%; a few chunks always need to + be available to generate silence in + Player::SendSilence() */ + FormatError(config_domain, + "buffer_before_play is too large (%f%%), capping at 80%%; please fix your configuration", + perc); + perc = 80; + } } else perc = DEFAULT_BUFFER_BEFORE_PLAY; @@ -357,45 +369,51 @@ buffered_before_play = buffered_chunks; const unsigned max_length = - config_get_positive(CONF_MAX_PLAYLIST_LENGTH, + config_get_positive(ConfigOption::MAX_PLAYLIST_LENGTH, DEFAULT_PLAYLIST_MAX_LENGTH); + AudioFormat configured_audio_format = AudioFormat::Undefined(); + param = config_get_param(ConfigOption::AUDIO_OUTPUT_FORMAT); + if (param != nullptr) { + try { + configured_audio_format = ParseAudioFormat(param->value.c_str(), + true); + } catch (const std::runtime_error &) { + std::throw_with_nested(FormatRuntimeError("error parsing line %i", + param->line)); + } + } + instance->partition = new Partition(*instance, max_length, buffered_chunks, - buffered_before_play); + buffered_before_play, + configured_audio_format, + replay_gain_config); + + try { + param = config_get_param(ConfigOption::REPLAYGAIN); + if (param != nullptr) + instance->partition->replay_gain_mode = + FromString(param->value.c_str()); + } catch (...) { + std::throw_with_nested(FormatRuntimeError("Failed to parse line %i", + param->line)); + } } -/** - * Handler for GlobalEvents::IDLE. - */ -static void -idle_event_emitted(void) +void +Instance::OnIdle(unsigned flags) { /* send "idle" notifications to all subscribed clients */ - unsigned flags = idle_get(); - if (flags != 0) - instance->client_list->IdleAdd(flags); + client_list->IdleAdd(flags); if (flags & (IDLE_PLAYLIST|IDLE_PLAYER|IDLE_MIXER|IDLE_OUTPUT) && state_file != nullptr) state_file->CheckModified(); } -#ifdef WIN32 - -/** - * Handler for GlobalEvents::SHUTDOWN. - */ -static void -shutdown_event_emitted(void) -{ - instance->event_loop->Break(); -} - -#endif - #ifndef ANDROID int main(int argc, char *argv[]) @@ -409,38 +427,29 @@ #endif -static int mpd_main_after_fork(struct options); +static int +mpd_main_after_fork(const Config &config); #ifdef ANDROID static inline #endif int mpd_main(int argc, char *argv[]) -{ +try { struct options options; - Error error; -#ifndef ANDROID +#ifdef ENABLE_DAEMON daemonize_close_stdin(); +#endif +#ifndef ANDROID #ifdef HAVE_LOCALE_H /* initialize locale */ setlocale(LC_CTYPE,""); -#endif - -#ifdef HAVE_GLIB - g_set_application_name("Music Player Daemon"); - -#if !GLIB_CHECK_VERSION(2,32,0) - /* enable GLib's thread safety code */ - g_thread_init(nullptr); -#endif + setlocale(LC_COLLATE, ""); #endif #endif - if (!IcuInit(error)) { - LogError(error); - return EXIT_FAILURE; - } + IcuInit(); winsock_init(); io_thread_init(); @@ -450,47 +459,32 @@ (void)argc; (void)argv; - { - const auto sdcard = Environment::getExternalStorageDirectory(); - if (!sdcard.IsNull()) { - const auto config_path = - AllocatedPath::Build(sdcard, "mpd.conf"); - if (FileExists(config_path) && - !ReadConfigFile(config_path, error)) { - LogError(error); - return EXIT_FAILURE; - } - } + const auto sdcard = Environment::getExternalStorageDirectory(); + if (!sdcard.IsNull()) { + const auto config_path = + AllocatedPath::Build(sdcard, "mpd.conf"); + if (FileExists(config_path)) + ReadConfigFile(config_path); } #else - if (!parse_cmdline(argc, argv, &options, error)) { - LogError(error); - return EXIT_FAILURE; - } + ParseCommandLine(argc, argv, &options); +#endif - if (!glue_daemonize_init(&options, error)) { - LogError(error); - return EXIT_FAILURE; - } + const auto config = LoadConfig(); + +#ifdef ENABLE_DAEMON + glue_daemonize_init(&options); #endif - stats_global_init(); TagLoadConfig(); - if (!log_init(options.verbose, options.log_stderr, error)) { - LogError(error); - return EXIT_FAILURE; - } + log_init(options.verbose, options.log_stderr); instance = new Instance(); - instance->event_loop = new EventLoop(); #ifdef ENABLE_NEIGHBOR_PLUGINS instance->neighbors = new NeighborGlue(); - if (!instance->neighbors->Init(io_thread_get(), *instance, error)) { - LogError(error); - return EXIT_FAILURE; - } + instance->neighbors->Init(io_thread_get(), *instance); if (instance->neighbors->IsEmpty()) { delete instance->neighbors; @@ -498,18 +492,15 @@ } #endif - const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10); + const unsigned max_clients = + config_get_positive(ConfigOption::MAX_CONN, 10); instance->client_list = new ClientList(max_clients); - initialize_decoder_and_player(); + initialize_decoder_and_player(config.replay_gain); - if (!listen_global_init(*instance->event_loop, *instance->partition, - error)) { - LogError(error); - return EXIT_FAILURE; - } + listen_global_init(instance->event_loop, *instance->partition); -#ifndef ANDROID +#ifdef ENABLE_DAEMON daemonize_set_user(); daemonize_begin(options.daemon); #endif @@ -522,43 +513,32 @@ This must be run after forking; if dispatch is called before forking, the child process will have a broken internal dispatch state. */ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - exit(mpd_main_after_fork(options)); + exit(mpd_main_after_fork(config)); }); dispatch_main(); return EXIT_FAILURE; // unreachable, because dispatch_main never returns #else - return mpd_main_after_fork(options); + return mpd_main_after_fork(config); #endif +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } -static int mpd_main_after_fork(struct options options) -{ - Error error; - - GlobalEvents::Initialize(*instance->event_loop); - GlobalEvents::Register(GlobalEvents::IDLE, idle_event_emitted); -#ifdef WIN32 - GlobalEvents::Register(GlobalEvents::SHUTDOWN, shutdown_event_emitted); -#endif - +static int +mpd_main_after_fork(const Config &config) +try { ConfigureFS(); - if (!glue_mapper_init(error)) { - LogError(error); - return EXIT_FAILURE; - } + glue_mapper_init(); initPermissions(); - playlist_global_init(); spl_global_init(); #ifdef ENABLE_ARCHIVE archive_plugin_init_all(); #endif - if (!pcm_convert_global_init(error)) { - LogError(error); - return EXIT_FAILURE; - } + pcm_convert_global_init(); decoder_plugin_init_all(); @@ -569,36 +549,34 @@ glue_sticker_init(); command_init(); - initAudioConfig(); - instance->partition->outputs.Configure(*instance->event_loop, - instance->partition->pc); - client_manager_init(); - replay_gain_global_init(); - if (!input_stream_global_init(error)) { - LogError(error); - return EXIT_FAILURE; - } + instance->partition->outputs.Configure(instance->event_loop, + config.replay_gain, + instance->partition->pc); + instance->partition->UpdateEffectiveReplayGainMode(); + client_manager_init(); + input_stream_global_init(); playlist_list_global_init(); -#ifndef ANDROID +#ifdef ENABLE_DAEMON daemonize_commit(); +#endif - setup_log_output(options.log_stderr); +#ifndef ANDROID + setup_log_output(); - SignalHandlersInit(*instance->event_loop); + SignalHandlersInit(instance->event_loop); #endif io_thread_start(); #ifdef ENABLE_NEIGHBOR_PLUGINS - if (instance->neighbors != nullptr && - !instance->neighbors->Open(error)) - FatalError(error); + if (instance->neighbors != nullptr) + instance->neighbors->Open(); #endif - ZeroconfInit(*instance->event_loop); + ZeroconfInit(instance->event_loop); StartPlayerThread(instance->partition->pc); @@ -612,22 +590,17 @@ } #endif - if (!glue_state_file_init(error)) { - LogError(error); - return EXIT_FAILURE; - } - - instance->partition->outputs.SetReplayGainMode(replay_gain_get_real_mode(instance->partition->playlist.queue.random)); + glue_state_file_init(); #ifdef ENABLE_DATABASE - if (config_get_bool(CONF_AUTO_UPDATE, false)) { + if (config_get_bool(ConfigOption::AUTO_UPDATE, false)) { #ifdef ENABLE_INOTIFY if (instance->storage != nullptr && instance->update != nullptr) - mpd_inotify_init(*instance->event_loop, + mpd_inotify_init(instance->event_loop, *instance->storage, *instance->update, - config_get_unsigned(CONF_AUTO_UPDATE_DEPTH, + config_get_unsigned(ConfigOption::AUTO_UPDATE_DEPTH, INT_MAX)); #else FormatWarning(config_domain, @@ -640,7 +613,7 @@ /* enable all audio outputs (if not already done by playlist_state_restore() */ - instance->partition->pc.UpdateAudio(); + instance->partition->pc.LockUpdateAudio(); #ifdef WIN32 win32_app_started(); @@ -650,8 +623,12 @@ a huge value to allow the kernel to reduce CPU wakeups */ SetThreadTimerSlackMS(100); +#ifdef ENABLE_SYSTEMD_DAEMON + sd_notify(0, "READY=1"); +#endif + /* run the main loop */ - instance->event_loop->Run(); + instance->event_loop.Run(); #ifdef WIN32 win32_app_stopping(); @@ -666,9 +643,9 @@ instance->update->CancelAllAsync(); #endif - if (state_file != nullptr) { - state_file->Write(); - delete state_file; + if (instance->state_file != nullptr) { + instance->state_file->Write(); + delete instance->state_file; } instance->partition->pc.Kill(); @@ -698,8 +675,6 @@ sticker_global_finish(); #endif - GlobalEvents::Deinitialize(); - playlist_list_global_finish(); input_stream_global_finish(); @@ -707,6 +682,8 @@ mapper_finish(); #endif + DeinitFS(); + delete instance->partition; command_finish(); decoder_plugin_deinit_all(); @@ -718,12 +695,13 @@ #ifndef ANDROID SignalHandlersFinish(); #endif - delete instance->event_loop; delete instance; instance = nullptr; -#ifndef ANDROID + +#ifdef ENABLE_DAEMON daemonize_finish(); #endif + #ifdef WIN32 WSACleanup(); #endif @@ -732,6 +710,9 @@ log_deinit(); return EXIT_SUCCESS; +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } #ifdef ANDROID @@ -757,7 +738,7 @@ Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass) { if (instance != nullptr) - instance->event_loop->Break(); + instance->Shutdown(); } #endif diff -Nru mpd-0.19.21/src/Main.hxx mpd-0.20.9/src/Main.hxx --- mpd-0.19.21/src/Main.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Main.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -61,7 +61,7 @@ * This function should be called just before entering main loop. */ void -win32_app_started(void); +win32_app_started(); /** * When running as a service reports to service control manager @@ -71,7 +71,7 @@ * This function should be called just after leaving main loop. */ void -win32_app_stopping(void); +win32_app_stopping(); #endif diff -Nru mpd-0.19.21/src/Mapper.cxx mpd-0.20.9/src/Mapper.cxx --- mpd-0.19.21/src/Mapper.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Mapper.cxx 2017-05-08 13:11:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,9 +24,8 @@ #include "config.h" #include "Mapper.hxx" #include "fs/AllocatedPath.hxx" -#include "fs/Traits.hxx" -#include "fs/Charset.hxx" #include "fs/CheckFile.hxx" +#include "util/StringCompare.hxx" #ifdef ENABLE_DATABASE #include "storage/StorageInterface.hxx" @@ -59,14 +58,15 @@ mapper_set_playlist_dir(std::move(_playlist_dir)); } -void mapper_finish(void) +void +mapper_finish() noexcept { } #ifdef ENABLE_DATABASE AllocatedPath -map_uri_fs(const char *uri) +map_uri_fs(const char *uri) noexcept { assert(uri != nullptr); assert(*uri != '/'); @@ -86,9 +86,9 @@ } std::string -map_fs_to_utf8(const char *path_fs) +map_fs_to_utf8(Path path_fs) noexcept { - if (PathTraitsFS::IsSeparator(path_fs[0])) { + if (path_fs.IsAbsolute()) { if (instance->storage == nullptr) return std::string(); @@ -96,24 +96,26 @@ if (music_dir_fs.IsNull()) return std::string(); - path_fs = music_dir_fs.RelativeFS(path_fs); - if (path_fs == nullptr || *path_fs == 0) + auto relative = music_dir_fs.Relative(path_fs); + if (relative == nullptr || StringIsEmpty(relative)) return std::string(); + + path_fs = Path::FromFS(relative); } - return PathToUTF8(path_fs); + return path_fs.ToUTF8(); } #endif const AllocatedPath & -map_spl_path(void) +map_spl_path() noexcept { return playlist_dir_fs; } AllocatedPath -map_spl_utf8_to_fs(const char *name) +map_spl_utf8_to_fs(const char *name) noexcept { if (playlist_dir_fs.IsNull()) return AllocatedPath::Null(); diff -Nru mpd-0.19.21/src/Mapper.hxx mpd-0.20.9/src/Mapper.hxx --- mpd-0.19.21/src/Mapper.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/Mapper.hxx 2017-05-08 13:11:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -30,12 +30,14 @@ #define PLAYLIST_FILE_SUFFIX ".m3u" +class Path; class AllocatedPath; void mapper_init(AllocatedPath &&playlist_dir); -void mapper_finish(void); +void +mapper_finish() noexcept; #ifdef ENABLE_DATABASE @@ -46,7 +48,7 @@ */ gcc_pure AllocatedPath -map_uri_fs(const char *uri); +map_uri_fs(const char *uri) noexcept; /** * Maps a file system path (relative to the music directory or @@ -58,7 +60,7 @@ */ gcc_pure std::string -map_fs_to_utf8(const char *path_fs); +map_fs_to_utf8(Path path_fs) noexcept; #endif @@ -67,7 +69,7 @@ */ gcc_const const AllocatedPath & -map_spl_path(void); +map_spl_path() noexcept; /** * Maps a playlist name (without the ".m3u" suffix) to a file system @@ -77,6 +79,6 @@ */ gcc_pure AllocatedPath -map_spl_utf8_to_fs(const char *name); +map_spl_utf8_to_fs(const char *name) noexcept; #endif diff -Nru mpd-0.19.21/src/mixer/Listener.hxx mpd-0.20.9/src/mixer/Listener.hxx --- mpd-0.19.21/src/mixer/Listener.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/Listener.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/mixer/MixerAll.cxx mpd-0.20.9/src/mixer/MixerAll.cxx --- mpd-0.19.21/src/mixer/MixerAll.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerAll.cxx 2017-05-08 13:02:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,13 +24,15 @@ #include "MixerList.hxx" #include "output/Internal.hxx" #include "pcm/Volume.hxx" -#include "util/Error.hxx" #include "Log.hxx" +#include + #include +gcc_pure static int -output_mixer_get_volume(const AudioOutput &ao) +output_mixer_get_volume(const AudioOutput &ao) noexcept { if (!ao.enabled) return -1; @@ -39,18 +41,18 @@ if (mixer == nullptr) return -1; - Error error; - int volume = mixer_get_volume(mixer, error); - if (volume < 0 && error.IsDefined()) - FormatError(error, + try { + return mixer_get_volume(mixer); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to read mixer for '%s'", - ao.name); - - return volume; + ao.GetName()); + return -1; + } } int -MultipleOutputs::GetVolume() const +MultipleOutputs::GetVolume() const noexcept { unsigned ok = 0; int total = 0; @@ -70,7 +72,7 @@ } static bool -output_mixer_set_volume(AudioOutput &ao, unsigned volume) +output_mixer_set_volume(AudioOutput &ao, unsigned volume) noexcept { assert(volume <= 100); @@ -81,18 +83,19 @@ if (mixer == nullptr) return false; - Error error; - bool success = mixer_set_volume(mixer, volume, error); - if (!success && error.IsDefined()) - FormatError(error, + try { + mixer_set_volume(mixer, volume); + return true; + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to set mixer for '%s'", - ao.name); - - return success; + ao.GetName()); + return false; + } } bool -MultipleOutputs::SetVolume(unsigned volume) +MultipleOutputs::SetVolume(unsigned volume) noexcept { assert(volume <= 100); @@ -105,7 +108,7 @@ } static int -output_mixer_get_software_volume(const AudioOutput &ao) +output_mixer_get_software_volume(const AudioOutput &ao) noexcept { if (!ao.enabled) return -1; @@ -114,11 +117,11 @@ if (mixer == nullptr || !mixer->IsPlugin(software_mixer_plugin)) return -1; - return mixer_get_volume(mixer, IgnoreError()); + return mixer_get_volume(mixer); } int -MultipleOutputs::GetSoftwareVolume() const +MultipleOutputs::GetSoftwareVolume() const noexcept { unsigned ok = 0; int total = 0; @@ -138,7 +141,7 @@ } void -MultipleOutputs::SetSoftwareVolume(unsigned volume) +MultipleOutputs::SetSoftwareVolume(unsigned volume) noexcept { assert(volume <= PCM_VOLUME_1); @@ -146,7 +149,8 @@ const auto mixer = ao->mixer; if (mixer != nullptr && - &mixer->plugin == &software_mixer_plugin) - mixer_set_volume(mixer, volume, IgnoreError()); + (&mixer->plugin == &software_mixer_plugin || + &mixer->plugin == &null_mixer_plugin)) + mixer_set_volume(mixer, volume); } } diff -Nru mpd-0.19.21/src/mixer/MixerControl.cxx mpd-0.20.9/src/mixer/MixerControl.cxx --- mpd-0.19.21/src/mixer/MixerControl.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerControl.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,6 @@ #include "config.h" #include "MixerControl.hxx" #include "MixerInternal.hxx" -#include "util/Error.hxx" #include @@ -28,10 +27,9 @@ mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao, MixerListener &listener, - const config_param ¶m, - Error &error) + const ConfigBlock &block) { - Mixer *mixer = plugin.init(event_loop, ao, listener, param, error); + Mixer *mixer = plugin.init(event_loop, ao, listener, block); assert(mixer == nullptr || mixer->IsPlugin(plugin)); @@ -50,20 +48,24 @@ delete mixer; } -bool -mixer_open(Mixer *mixer, Error &error) +void +mixer_open(Mixer *mixer) { - bool success; - assert(mixer != nullptr); - const ScopeLock protect(mixer->mutex); - - success = mixer->open || (mixer->open = mixer->Open(error)); + const std::lock_guard protect(mixer->mutex); - mixer->failed = !success; + if (mixer->open) + return; - return success; + try { + mixer->Open(); + mixer->open = true; + mixer->failed = false; + } catch (...) { + mixer->failed = true; + throw; + } } static void @@ -81,7 +83,7 @@ { assert(mixer != nullptr); - const ScopeLock protect(mixer->mutex); + const std::lock_guard protect(mixer->mutex); if (mixer->open) mixer_close_internal(mixer); @@ -109,39 +111,41 @@ } int -mixer_get_volume(Mixer *mixer, Error &error) +mixer_get_volume(Mixer *mixer) { int volume; assert(mixer != nullptr); - if (mixer->plugin.global && !mixer->failed && - !mixer_open(mixer, error)) - return -1; + if (mixer->plugin.global && !mixer->failed) + mixer_open(mixer); - const ScopeLock protect(mixer->mutex); + const std::lock_guard protect(mixer->mutex); if (mixer->open) { - volume = mixer->GetVolume(error); - if (volume < 0 && error.IsDefined()) + try { + volume = mixer->GetVolume(); + } catch (...) { mixer_failed(mixer); + throw; + } } else volume = -1; return volume; } -bool -mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) +void +mixer_set_volume(Mixer *mixer, unsigned volume) { assert(mixer != nullptr); assert(volume <= 100); - if (mixer->plugin.global && !mixer->failed && - !mixer_open(mixer, error)) - return false; + if (mixer->plugin.global && !mixer->failed) + mixer_open(mixer); - const ScopeLock protect(mixer->mutex); + const std::lock_guard protect(mixer->mutex); - return mixer->open && mixer->SetVolume(volume, error); + if (mixer->open) + mixer->SetVolume(volume); } diff -Nru mpd-0.19.21/src/mixer/MixerControl.hxx mpd-0.20.9/src/mixer/MixerControl.hxx --- mpd-0.19.21/src/mixer/MixerControl.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerControl.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,31 +19,35 @@ /** \file * - * Functions which manipulate a #mixer object. + * Functions which manipulate a #Mixer object. */ #ifndef MPD_MIXER_CONTROL_HXX #define MPD_MIXER_CONTROL_HXX -class Error; class Mixer; class EventLoop; struct AudioOutput; struct MixerPlugin; class MixerListener; -struct config_param; +struct ConfigBlock; +/** + * Throws std::runtime_error on error. + */ Mixer * mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao, MixerListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); void mixer_free(Mixer *mixer); -bool -mixer_open(Mixer *mixer, Error &error); +/** + * Throws std::runtime_error on error. + */ +void +mixer_open(Mixer *mixer); void mixer_close(Mixer *mixer); @@ -55,10 +59,16 @@ void mixer_auto_close(Mixer *mixer); +/** + * Throws std::runtime_error on error. + */ int -mixer_get_volume(Mixer *mixer, Error &error); +mixer_get_volume(Mixer *mixer); -bool -mixer_set_volume(Mixer *mixer, unsigned volume, Error &error); +/** + * Throws std::runtime_error on error. + */ +void +mixer_set_volume(Mixer *mixer, unsigned volume); #endif diff -Nru mpd-0.19.21/src/mixer/MixerInternal.hxx mpd-0.20.9/src/mixer/MixerInternal.hxx --- mpd-0.19.21/src/mixer/MixerInternal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerInternal.hxx 2017-06-04 10:37:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -67,9 +67,9 @@ /** * Open mixer device * - * @return true on success, false on error + * Throws std::runtime_error on error. */ - virtual bool Open(Error &error) = 0; + virtual void Open() = 0; /** * Close mixer device @@ -79,19 +79,21 @@ /** * Reads the current volume. * + * Throws std::runtime_error on error. + * * @return the current volume (0..100 including) or -1 if - * unavailable or on error (error set, mixer will be closed) + * unavailable */ - gcc_pure - virtual int GetVolume(Error &error) = 0; + virtual int GetVolume() = 0; /** * Sets the volume. * - * @param volume the new volume (0..100 including) @return - * true on success, false on error + * Throws std::runtime_error on error. + * + * @param volume the new volume (0..100 including) */ - virtual bool SetVolume(unsigned volume, Error &error) = 0; + virtual void SetVolume(unsigned volume) = 0; }; #endif diff -Nru mpd-0.19.21/src/mixer/MixerList.hxx mpd-0.20.9/src/mixer/MixerList.hxx --- mpd-0.19.21/src/mixer/MixerList.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerList.hxx 2017-02-01 20:58:30.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,8 +27,10 @@ struct MixerPlugin; +extern const MixerPlugin null_mixer_plugin; extern const MixerPlugin software_mixer_plugin; extern const MixerPlugin alsa_mixer_plugin; +extern const MixerPlugin haiku_mixer_plugin; extern const MixerPlugin oss_mixer_plugin; extern const MixerPlugin roar_mixer_plugin; extern const MixerPlugin pulse_mixer_plugin; diff -Nru mpd-0.19.21/src/mixer/MixerPlugin.hxx mpd-0.20.9/src/mixer/MixerPlugin.hxx --- mpd-0.19.21/src/mixer/MixerPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,27 +27,25 @@ #ifndef MPD_MIXER_PLUGIN_HXX #define MPD_MIXER_PLUGIN_HXX -struct config_param; +struct ConfigBlock; struct AudioOutput; class Mixer; class MixerListener; class EventLoop; -class Error; struct MixerPlugin { /** * Alocates and configures a mixer device. * + * Throws std::runtime_error on error. + * * @param ao the associated AudioOutput * @param param the configuration section - * @param error_r location to store the error occurring, or - * nullptr to ignore errors - * @return a mixer object, or nullptr on error + * @return a mixer object */ Mixer *(*init)(EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); /** * If true, then the mixer is automatically opened, even if diff -Nru mpd-0.19.21/src/mixer/MixerType.cxx mpd-0.20.9/src/mixer/MixerType.cxx --- mpd-0.19.21/src/mixer/MixerType.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerType.cxx 2017-05-08 13:05:28.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,17 +23,19 @@ #include #include -enum mixer_type -mixer_type_parse(const char *input) +MixerType +mixer_type_parse(const char *input) noexcept { assert(input != NULL); if (strcmp(input, "none") == 0 || strcmp(input, "disabled") == 0) - return MIXER_TYPE_NONE; + return MixerType::NONE; else if (strcmp(input, "hardware") == 0) - return MIXER_TYPE_HARDWARE; + return MixerType::HARDWARE; else if (strcmp(input, "software") == 0) - return MIXER_TYPE_SOFTWARE; + return MixerType::SOFTWARE; + else if (strcmp(input, "null") == 0) + return MixerType::NULL_; else - return MIXER_TYPE_UNKNOWN; + return MixerType::UNKNOWN; } diff -Nru mpd-0.19.21/src/mixer/MixerType.hxx mpd-0.20.9/src/mixer/MixerType.hxx --- mpd-0.19.21/src/mixer/MixerType.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/MixerType.hxx 2017-05-08 13:05:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,28 +20,34 @@ #ifndef MPD_MIXER_TYPE_HXX #define MPD_MIXER_TYPE_HXX -enum mixer_type { +#include "Compiler.h" + +enum class MixerType { /** parser error */ - MIXER_TYPE_UNKNOWN, + UNKNOWN, /** mixer disabled */ - MIXER_TYPE_NONE, + NONE, + + /** "null" mixer (virtual fake) */ + NULL_, /** software mixer with pcm_volume() */ - MIXER_TYPE_SOFTWARE, + SOFTWARE, /** hardware mixer (output's plugin) */ - MIXER_TYPE_HARDWARE, + HARDWARE, }; /** - * Parses a "mixer_type" setting from the configuration file. + * Parses a #MixerType setting from the configuration file. * - * @param input the configured string value; must not be NULL - * @return a #mixer_type value; MIXER_TYPE_UNKNOWN means #input could - * not be parsed + * @param input the configured string value; must not be NULL @return + * a #MixerType value; #MixerType::UNKNOWN means #input could not be + * parsed */ -enum mixer_type -mixer_type_parse(const char *input); +gcc_pure +MixerType +mixer_type_parse(const char *input) noexcept; #endif diff -Nru mpd-0.19.21/src/mixer/plugins/AlsaMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/AlsaMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/AlsaMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/AlsaMixerPlugin.cxx 2017-05-08 15:10:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,18 +23,21 @@ #include "output/OutputAPI.hxx" #include "event/MultiSocketMonitor.hxx" #include "event/DeferredMonitor.hxx" -#include "event/Loop.hxx" +#include "event/Call.hxx" #include "util/ASCII.hxx" #include "util/ReusableArray.hxx" -#include "util/Clamp.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" -#include +extern "C" { +#include "volume_mapping.h" +} #include +#include + #define VOLUME_MIXER_ALSA_DEFAULT "default" #define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "PCM" static constexpr unsigned VOLUME_MIXER_ALSA_INDEX_DEFAULT = 0; @@ -51,12 +54,19 @@ DeferredMonitor::Schedule(); } + ~AlsaMixerMonitor() { + BlockingCall(MultiSocketMonitor::GetEventLoop(), [this](){ + MultiSocketMonitor::Reset(); + DeferredMonitor::Cancel(); + }); + } + private: virtual void RunDeferred() override { InvalidateSockets(); } - virtual int PrepareSockets() override; + virtual std::chrono::steady_clock::duration PrepareSockets() override; virtual void DispatchSockets() override; }; @@ -69,9 +79,6 @@ snd_mixer_t *handle; snd_mixer_elem_t *elem; - long volume_min; - long volume_max; - int volume_set; AlsaMixerMonitor *monitor; @@ -82,28 +89,28 @@ virtual ~AlsaMixer(); - void Configure(const config_param ¶m); - bool Setup(Error &error); + void Configure(const ConfigBlock &block); + void Setup(); /* virtual methods from class Mixer */ - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + void Open() override; + void Close() override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static constexpr Domain alsa_mixer_domain("alsa_mixer"); -int +std::chrono::steady_clock::duration AlsaMixerMonitor::PrepareSockets() { if (mixer == nullptr) { ClearSocketList(); - return -1; + return std::chrono::steady_clock::duration(-1); } int count = snd_mixer_poll_descriptors_count(mixer); - if (count < 0) + if (count <= 0) count = 0; struct pollfd *pfds = pfd_buffer.Get(count); @@ -113,7 +120,7 @@ count = 0; ReplaceSocketList(pfds, count); - return -1; + return std::chrono::steady_clock::duration(-1); } void @@ -149,8 +156,11 @@ snd_mixer_elem_get_callback_private(elem); if (mask & SND_CTL_EVENT_MASK_VALUE) { - int volume = mixer.GetVolume(IgnoreError()); - mixer.listener.OnMixerVolumeChanged(mixer, volume); + try { + int volume = mixer.GetVolume(); + mixer.listener.OnMixerVolumeChanged(mixer, volume); + } catch (const std::runtime_error &) { + } } return 0; @@ -162,24 +172,23 @@ */ inline void -AlsaMixer::Configure(const config_param ¶m) +AlsaMixer::Configure(const ConfigBlock &block) { - device = param.GetBlockValue("mixer_device", + device = block.GetBlockValue("mixer_device", VOLUME_MIXER_ALSA_DEFAULT); - control = param.GetBlockValue("mixer_control", + control = block.GetBlockValue("mixer_control", VOLUME_MIXER_ALSA_CONTROL_DEFAULT); - index = param.GetBlockValue("mixer_index", + index = block.GetBlockValue("mixer_index", VOLUME_MIXER_ALSA_INDEX_DEFAULT); } static Mixer * alsa_mixer_init(EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - const config_param ¶m, - gcc_unused Error &error) + const ConfigBlock &block) { AlsaMixer *am = new AlsaMixer(event_loop, listener); - am->Configure(param); + am->Configure(block); return am; } @@ -192,7 +201,8 @@ gcc_pure static snd_mixer_elem_t * -alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx) +alsa_mixer_lookup_elem(snd_mixer_t *handle, + const char *name, unsigned idx) noexcept { for (snd_mixer_elem_t *elem = snd_mixer_first_elem(handle); elem != nullptr; elem = snd_mixer_elem_next(elem)) { @@ -206,74 +216,52 @@ return nullptr; } -inline bool -AlsaMixer::Setup(Error &error) +inline void +AlsaMixer::Setup() { int err; - if ((err = snd_mixer_attach(handle, device)) < 0) { - error.Format(alsa_mixer_domain, err, - "failed to attach to %s: %s", - device, snd_strerror(err)); - return false; - } - - if ((err = snd_mixer_selem_register(handle, nullptr, - nullptr)) < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_selem_register() failed: %s", - snd_strerror(err)); - return false; - } - - if ((err = snd_mixer_load(handle)) < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_load() failed: %s\n", - snd_strerror(err)); - return false; - } + if ((err = snd_mixer_attach(handle, device)) < 0) + throw FormatRuntimeError("failed to attach to %s: %s", + device, snd_strerror(err)); + + if ((err = snd_mixer_selem_register(handle, nullptr, nullptr)) < 0) + throw FormatRuntimeError("snd_mixer_selem_register() failed: %s", + snd_strerror(err)); + + if ((err = snd_mixer_load(handle)) < 0) + throw FormatRuntimeError("snd_mixer_load() failed: %s\n", + snd_strerror(err)); elem = alsa_mixer_lookup_elem(handle, control, index); - if (elem == nullptr) { - error.Format(alsa_mixer_domain, 0, - "no such mixer control: %s", control); - return false; - } - - snd_mixer_selem_get_playback_volume_range(elem, &volume_min, - &volume_max); + if (elem == nullptr) + throw FormatRuntimeError("no such mixer control: %s", control); snd_mixer_elem_set_callback_private(elem, this); snd_mixer_elem_set_callback(elem, alsa_mixer_elem_callback); monitor = new AlsaMixerMonitor(event_loop, handle); - - return true; } -inline bool -AlsaMixer::Open(Error &error) +void +AlsaMixer::Open() { int err; - volume_set = -1; - err = snd_mixer_open(&handle, 0); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_open() failed: %s", snd_strerror(err)); - return false; - } - - if (!Setup(error)) { + if (err < 0) + throw FormatRuntimeError("snd_mixer_open() failed: %s", + snd_strerror(err)); + + try { + Setup(); + } catch (...) { snd_mixer_close(handle); - return false; + throw; } - - return true; } -inline void +void AlsaMixer::Close() { assert(handle != nullptr); @@ -284,71 +272,30 @@ snd_mixer_close(handle); } -inline int -AlsaMixer::GetVolume(Error &error) +int +AlsaMixer::GetVolume() { int err; - int ret; - long level; assert(handle != nullptr); err = snd_mixer_handle_events(handle); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_handle_events() failed: %s", - snd_strerror(err)); - return false; - } - - err = snd_mixer_selem_get_playback_volume(elem, - SND_MIXER_SCHN_FRONT_LEFT, - &level); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "failed to read ALSA volume: %s", - snd_strerror(err)); - return false; - } - - ret = ((volume_set / 100.0) * (volume_max - volume_min) - + volume_min) + 0.5; - if (volume_set > 0 && ret == level) { - ret = volume_set; - } else { - ret = (int)(100 * (((float)(level - volume_min)) / - (volume_max - volume_min)) + 0.5); - } + if (err < 0) + throw FormatRuntimeError("snd_mixer_handle_events() failed: %s", + snd_strerror(err)); - return ret; + return lrint(100 * get_normalized_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT)); } -inline bool -AlsaMixer::SetVolume(unsigned volume, Error &error) +void +AlsaMixer::SetVolume(unsigned volume) { - float vol; - long level; - int err; - assert(handle != nullptr); - vol = volume; - - volume_set = vol + 0.5; - - level = (long)(((vol / 100.0) * (volume_max - volume_min) + - volume_min) + 0.5); - level = Clamp(level, volume_min, volume_max); - - err = snd_mixer_selem_set_playback_volume_all(elem, level); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "failed to set ALSA volume: %s", - snd_strerror(err)); - return false; - } - - return true; + int err = set_normalized_playback_volume(elem, 0.01*volume, 1); + if (err < 0) + throw FormatRuntimeError("failed to set ALSA volume: %s", + snd_strerror(err)); } const MixerPlugin alsa_mixer_plugin = { diff -Nru mpd-0.19.21/src/mixer/plugins/HaikuMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/HaikuMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/HaikuMixerPlugin.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/HaikuMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft + * Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen + * Copyright (C) 2014-2015 François 'mmu_man' Revol + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include "config.h" +#include "mixer/MixerInternal.hxx" +#include "output/plugins/HaikuOutputPlugin.hxx" +#include "Compiler.h" + +class HaikuMixer final : public Mixer { + /** the base mixer class */ + HaikuOutput &self; + +public: + HaikuMixer(HaikuOutput &_output, MixerListener &_listener) + :Mixer(haiku_mixer_plugin, _listener), + self(_output) {} + + /* virtual methods from class Mixer */ + virtual bool Open(gcc_unused Error &error) override { + return true; + } + + virtual void Close() override { + } + + virtual int GetVolume(Error &error) override; + virtual bool SetVolume(unsigned volume, Error &error) override; +}; + +static Mixer * +haiku_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, + MixerListener &listener, + gcc_unused const ConfigBlock &block, + gcc_unused Error &error) +{ + return new HaikuMixer((HaikuOutput &)ao, listener); +} + +int +HaikuMixer::GetVolume(gcc_unused Error &error) +{ + return haiku_output_get_volume(self); +} + +bool +HaikuMixer::SetVolume(unsigned volume, gcc_unused Error &error) +{ + return haiku_output_set_volume(self, volume); +} + +const MixerPlugin haiku_mixer_plugin = { + haiku_mixer_init, + false, +}; diff -Nru mpd-0.19.21/src/mixer/plugins/NullMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/NullMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/NullMixerPlugin.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/NullMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "mixer/MixerInternal.hxx" + +class NullMixer final : public Mixer { + /** + * The current volume in percent (0..100). + */ + unsigned volume; + +public: + NullMixer(MixerListener &_listener) + :Mixer(null_mixer_plugin, _listener), + volume(100) + { + } + + /* virtual methods from class Mixer */ + void Open() override { + } + + void Close() override { + } + + int GetVolume() override { + return volume; + } + + void SetVolume(unsigned _volume) override { + volume = _volume; + } +}; + +static Mixer * +null_mixer_init(gcc_unused EventLoop &event_loop, + gcc_unused AudioOutput &ao, + MixerListener &listener, + gcc_unused const ConfigBlock &block) +{ + return new NullMixer(listener); +} + +const MixerPlugin null_mixer_plugin = { + null_mixer_init, + true, +}; diff -Nru mpd-0.19.21/src/mixer/plugins/OssMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/OssMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/OssMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/OssMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,12 @@ #include "config.h" #include "mixer/MixerInternal.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "system/fd_util.h" +#include "system/Error.hxx" #include "util/ASCII.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -49,16 +50,18 @@ int volume_control; public: - OssMixer(MixerListener &_listener) - :Mixer(oss_mixer_plugin, _listener) {} + OssMixer(MixerListener &_listener, const ConfigBlock &block) + :Mixer(oss_mixer_plugin, _listener) { + Configure(block); + } - bool Configure(const config_param ¶m, Error &error); + void Configure(const ConfigBlock &block); /* virtual methods from class Mixer */ - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + void Open() override; + void Close() override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static constexpr Domain oss_mixer_domain("oss_mixer"); @@ -78,39 +81,27 @@ return -1; } -inline bool -OssMixer::Configure(const config_param ¶m, Error &error) +inline void +OssMixer::Configure(const ConfigBlock &block) { - device = param.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT); - control = param.GetBlockValue("mixer_control"); + device = block.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT); + control = block.GetBlockValue("mixer_control"); if (control != NULL) { volume_control = oss_find_mixer(control); - if (volume_control < 0) { - error.Format(oss_mixer_domain, 0, - "no such mixer control: %s", control); - return false; - } + if (volume_control < 0) + throw FormatRuntimeError("no such mixer control: %s", + control); } else volume_control = SOUND_MIXER_PCM; - - return true; } static Mixer * oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - const config_param ¶m, - Error &error) + const ConfigBlock &block) { - OssMixer *om = new OssMixer(listener); - - if (!om->Configure(param, error)) { - delete om; - return nullptr; - } - - return om; + return new OssMixer(listener, block); } void @@ -121,38 +112,32 @@ close(device_fd); } -bool -OssMixer::Open(Error &error) +void +OssMixer::Open() { device_fd = open_cloexec(device, O_RDONLY, 0); - if (device_fd < 0) { - error.FormatErrno("failed to open %s", device); - return false; - } - - if (control) { - int devmask = 0; + if (device_fd < 0) + throw FormatErrno("failed to open %s", device); - if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - error.SetErrno("READ_DEVMASK failed"); - Close(); - return false; - } - - if (((1 << volume_control) & devmask) == 0) { - error.Format(oss_mixer_domain, 0, - "mixer control \"%s\" not usable", - control); - Close(); - return false; + try { + if (control) { + int devmask = 0; + + if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) + throw MakeErrno("READ_DEVMASK failed"); + + if (((1 << volume_control) & devmask) == 0) + throw FormatErrno("mixer control \"%s\" not usable", + control); } + } catch (...) { + Close(); + throw; } - - return true; } int -OssMixer::GetVolume(Error &error) +OssMixer::GetVolume() { int left, right, level; int ret; @@ -160,10 +145,8 @@ assert(device_fd >= 0); ret = ioctl(device_fd, MIXER_READ(volume_control), &level); - if (ret < 0) { - error.SetErrno("failed to read OSS volume"); - return false; - } + if (ret < 0) + throw MakeErrno("failed to read OSS volume"); left = level & 0xff; right = (level & 0xff00) >> 8; @@ -177,24 +160,18 @@ return left; } -bool -OssMixer::SetVolume(unsigned volume, Error &error) +void +OssMixer::SetVolume(unsigned volume) { int level; - int ret; assert(device_fd >= 0); assert(volume <= 100); level = (volume << 8) + volume; - ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level); - if (ret < 0) { - error.SetErrno("failed to set OSS volume"); - return false; - } - - return true; + if (ioctl(device_fd, MIXER_WRITE(volume_control), &level) < 0) + throw MakeErrno("failed to set OSS volume"); } const MixerPlugin oss_mixer_plugin = { diff -Nru mpd-0.19.21/src/mixer/plugins/PulseMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/PulseMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/PulseMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/PulseMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,18 +19,19 @@ #include "config.h" #include "PulseMixerPlugin.hxx" +#include "lib/pulse/Domain.hxx" +#include "lib/pulse/LogError.hxx" +#include "lib/pulse/LockGuard.hxx" #include "mixer/MixerInternal.hxx" #include "mixer/Listener.hxx" #include "output/plugins/PulseOutputPlugin.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" -#include "Log.hxx" #include #include #include #include -#include + +#include #include @@ -52,22 +53,19 @@ void Offline(); void VolumeCallback(const pa_sink_input_info *i, int eol); void Update(pa_context *context, pa_stream *stream); - int GetVolumeInternal(Error &error); + int GetVolumeInternal(); /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } - virtual void Close() override { + void Close() override { } - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; -static constexpr Domain pulse_mixer_domain("pulse_mixer"); - void PulseMixer::Offline() { @@ -93,7 +91,7 @@ online = true; volume = i->volume; - listener.OnMixerVolumeChanged(*this, GetVolumeInternal(IgnoreError())); + listener.OnMixerVolumeChanged(*this, GetVolumeInternal()); } /** @@ -120,9 +118,8 @@ pa_stream_get_index(stream), pulse_mixer_volume_cb, this); if (o == nullptr) { - FormatError(pulse_mixer_domain, - "pa_context_get_sink_input_info() failed: %s", - pa_strerror(pa_context_errno(context))); + LogPulseError(context, + "pa_context_get_sink_input_info() failed"); Offline(); return; } @@ -142,9 +139,8 @@ (pa_subscription_mask_t)PA_SUBSCRIPTION_MASK_SINK_INPUT, nullptr, nullptr); if (o == nullptr) { - FormatError(pulse_mixer_domain, - "pa_context_subscribe() failed: %s", - pa_strerror(pa_context_errno(context))); + LogPulseError(context, + "pa_context_subscribe() failed"); return; } @@ -167,8 +163,7 @@ static Mixer * pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { PulseOutput &po = (PulseOutput &)ao; PulseMixer *pm = new PulseMixer(po, listener); @@ -184,47 +179,37 @@ } int -PulseMixer::GetVolume(gcc_unused Error &error) +PulseMixer::GetVolume() { - pulse_output_lock(output); + Pulse::LockGuard lock(pulse_output_get_mainloop(output)); - int result = GetVolumeInternal(error); - pulse_output_unlock(output); - - return result; + return GetVolumeInternal(); } /** * Pulse mainloop lock must be held by caller */ int -PulseMixer::GetVolumeInternal(gcc_unused Error &error) +PulseMixer::GetVolumeInternal() { return online ? (int)((100 * (pa_cvolume_avg(&volume) + 1)) / PA_VOLUME_NORM) : -1; } -bool -PulseMixer::SetVolume(unsigned new_volume, Error &error) +void +PulseMixer::SetVolume(unsigned new_volume) { - pulse_output_lock(output); + Pulse::LockGuard lock(pulse_output_get_mainloop(output)); - if (!online) { - pulse_output_unlock(output); - error.Set(pulse_mixer_domain, "disconnected"); - return false; - } + if (!online) + throw std::runtime_error("disconnected"); struct pa_cvolume cvolume; pa_cvolume_set(&cvolume, volume.channels, (new_volume * PA_VOLUME_NORM + 50) / 100); - bool success = pulse_output_set_volume(output, &cvolume, error); - if (success) - volume = cvolume; - - pulse_output_unlock(output); - return success; + pulse_output_set_volume(output, &cvolume); + volume = cvolume; } const MixerPlugin pulse_mixer_plugin = { diff -Nru mpd-0.19.21/src/mixer/plugins/PulseMixerPlugin.hxx mpd-0.20.9/src/mixer/plugins/PulseMixerPlugin.hxx --- mpd-0.19.21/src/mixer/plugins/PulseMixerPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/PulseMixerPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/mixer/plugins/RoarMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/RoarMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/RoarMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/RoarMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft * Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen * @@ -34,36 +34,34 @@ self(_output) {} /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } virtual void Close() override { } - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static Mixer * roar_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new RoarMixer((RoarOutput &)ao, listener); } int -RoarMixer::GetVolume(gcc_unused Error &error) +RoarMixer::GetVolume() { return roar_output_get_volume(self); } -bool -RoarMixer::SetVolume(unsigned volume, gcc_unused Error &error) +void +RoarMixer::SetVolume(unsigned volume) { - return roar_output_set_volume(self, volume); + roar_output_set_volume(self, volume); } const MixerPlugin roar_mixer_plugin = { diff -Nru mpd-0.19.21/src/mixer/plugins/SoftwareMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/SoftwareMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/SoftwareMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/SoftwareMixerPlugin.cxx 2017-05-08 15:00:09.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,80 +25,53 @@ #include "filter/FilterInternal.hxx" #include "filter/plugins/VolumeFilterPlugin.hxx" #include "pcm/Volume.hxx" -#include "config/ConfigData.hxx" -#include "util/Error.hxx" +#include "config/Block.hxx" #include #include -static Filter * -CreateVolumeFilter() -{ - return filter_new(&volume_filter_plugin, config_param(), - IgnoreError()); -} - class SoftwareMixer final : public Mixer { - Filter *filter; - - /** - * If this is true, then this object "owns" the #Filter - * instance (see above). It will be set to false by - * software_mixer_get_filter(); after that, the caller will be - * responsible for the #Filter. - */ - bool owns_filter; + Filter *filter = nullptr; /** * The current volume in percent (0..100). */ - unsigned volume; + unsigned volume = 100; public: SoftwareMixer(MixerListener &_listener) - :Mixer(software_mixer_plugin, _listener), - filter(CreateVolumeFilter()), - owns_filter(true), - volume(100) + :Mixer(software_mixer_plugin, _listener) { - assert(filter != nullptr); - } - - virtual ~SoftwareMixer() { - if (owns_filter) - delete filter; } - Filter *GetFilter(); + void SetFilter(Filter *_filter); /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } virtual void Close() override { } - virtual int GetVolume(gcc_unused Error &error) override { + int GetVolume() override { return volume; } - virtual bool SetVolume(unsigned volume, Error &error) override; + void SetVolume(unsigned volume) override; }; static Mixer * software_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new SoftwareMixer(listener); } gcc_const static unsigned -PercentVolumeToSoftwareVolume(unsigned volume) +PercentVolumeToSoftwareVolume(unsigned volume) noexcept { assert(volume <= 100); @@ -111,14 +84,15 @@ return 0; } -bool -SoftwareMixer::SetVolume(unsigned new_volume, gcc_unused Error &error) +void +SoftwareMixer::SetVolume(unsigned new_volume) { assert(new_volume <= 100); volume = new_volume; - volume_filter_set(filter, PercentVolumeToSoftwareVolume(new_volume)); - return true; + + if (filter != nullptr) + volume_filter_set(filter, PercentVolumeToSoftwareVolume(new_volume)); } const MixerPlugin software_mixer_plugin = { @@ -126,19 +100,19 @@ true, }; -inline Filter * -SoftwareMixer::GetFilter() +inline void +SoftwareMixer::SetFilter(Filter *_filter) { - assert(owns_filter); + filter = _filter; - owns_filter = false; - return filter; + if (filter != nullptr) + volume_filter_set(filter, + PercentVolumeToSoftwareVolume(volume)); } -Filter * -software_mixer_get_filter(Mixer *mixer) +void +software_mixer_set_filter(Mixer &mixer, Filter *filter) { - SoftwareMixer *sm = (SoftwareMixer *)mixer; - assert(sm->IsPlugin(software_mixer_plugin)); - return sm->GetFilter(); + SoftwareMixer &sm = (SoftwareMixer &)mixer; + sm.SetFilter(filter); } diff -Nru mpd-0.19.21/src/mixer/plugins/SoftwareMixerPlugin.hxx mpd-0.20.9/src/mixer/plugins/SoftwareMixerPlugin.hxx --- mpd-0.19.21/src/mixer/plugins/SoftwareMixerPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/SoftwareMixerPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,10 +24,12 @@ class Filter; /** - * Returns the (volume) filter associated with this mixer. All users - * of this mixer plugin should install this filter. + * Attach a #VolumeFilter to this mixer. The #VolumeFilter is the + * entity which actually applies the volume; it is created and managed + * by the output. Mixer::SetVolume() calls will be forwarded to + * volume_filter_set(). */ -Filter * -software_mixer_get_filter(Mixer *mixer); +void +software_mixer_set_filter(Mixer &mixer, Filter *filter); #endif diff -Nru mpd-0.19.21/src/mixer/plugins/volume_mapping.c mpd-0.20.9/src/mixer/plugins/volume_mapping.c --- mpd-0.19.21/src/mixer/plugins/volume_mapping.c 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/volume_mapping.c 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2010 Clemens Ladisch + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * The functions in this file map the value ranges of ALSA mixer controls onto + * the interval 0..1. + * + * The mapping is designed so that the position in the interval is proportional + * to the volume as a human ear would perceive it (i.e., the position is the + * cubic root of the linear sample multiplication factor). For controls with + * a small range (24 dB or less), the mapping is linear in the dB values so + * that each step has the same size visually. Only for controls without dB + * information, a linear mapping of the hardware volume register values is used + * (this is the same algorithm as used in the old alsamixer). + * + * When setting the volume, 'dir' is the rounding direction: + * -1/0/1 = down/nearest/up. + */ + +#include +#include +#include "volume_mapping.h" + +#ifdef __UCLIBC__ +/* 10^x = 10^(log e^x) = (e^x)^log10 = e^(x * log 10) */ +#define exp10(x) (exp((x) * log(10))) +#endif /* __UCLIBC__ */ + +#define MAX_LINEAR_DB_SCALE 24 + +static inline bool use_linear_dB_scale(long dBmin, long dBmax) +{ + return dBmax - dBmin <= MAX_LINEAR_DB_SCALE * 100; +} + +static long lrint_dir(double x, int dir) +{ + if (dir > 0) + return lrint(ceil(x)); + else if (dir < 0) + return lrint(floor(x)); + else + return lrint(x); +} + +enum ctl_dir { PLAYBACK, CAPTURE }; + +static int (* const get_dB_range[2])(snd_mixer_elem_t *, long *, long *) = { + snd_mixer_selem_get_playback_dB_range, + snd_mixer_selem_get_capture_dB_range, +}; +static int (* const get_raw_range[2])(snd_mixer_elem_t *, long *, long *) = { + snd_mixer_selem_get_playback_volume_range, + snd_mixer_selem_get_capture_volume_range, +}; +static int (* const get_dB[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *) = { + snd_mixer_selem_get_playback_dB, + snd_mixer_selem_get_capture_dB, +}; +static int (* const get_raw[2])(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *) = { + snd_mixer_selem_get_playback_volume, + snd_mixer_selem_get_capture_volume, +}; +static int (* const set_dB[2])(snd_mixer_elem_t *, long, int) = { + snd_mixer_selem_set_playback_dB_all, + snd_mixer_selem_set_capture_dB_all, +}; +static int (* const set_raw[2])(snd_mixer_elem_t *, long) = { + snd_mixer_selem_set_playback_volume_all, + snd_mixer_selem_set_capture_volume_all, +}; + +static double get_normalized_volume(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t channel, + enum ctl_dir ctl_dir) +{ + long min, max, value; + double normalized, min_norm; + int err; + + err = get_dB_range[ctl_dir](elem, &min, &max); + if (err < 0 || min >= max) { + err = get_raw_range[ctl_dir](elem, &min, &max); + if (err < 0 || min == max) + return 0; + + err = get_raw[ctl_dir](elem, channel, &value); + if (err < 0) + return 0; + + return (value - min) / (double)(max - min); + } + + err = get_dB[ctl_dir](elem, channel, &value); + if (err < 0) + return 0; + + if (use_linear_dB_scale(min, max)) + return (value - min) / (double)(max - min); + + normalized = exp10((value - max) / 6000.0); + if (min != SND_CTL_TLV_DB_GAIN_MUTE) { + min_norm = exp10((min - max) / 6000.0); + normalized = (normalized - min_norm) / (1 - min_norm); + } + + return normalized; +} + +static int set_normalized_volume(snd_mixer_elem_t *elem, + double volume, + int dir, + enum ctl_dir ctl_dir) +{ + long min, max, value; + double min_norm; + int err; + + err = get_dB_range[ctl_dir](elem, &min, &max); + if (err < 0 || min >= max) { + err = get_raw_range[ctl_dir](elem, &min, &max); + if (err < 0) + return err; + + value = lrint_dir(volume * (max - min), dir) + min; + return set_raw[ctl_dir](elem, value); + } + + if (use_linear_dB_scale(min, max)) { + value = lrint_dir(volume * (max - min), dir) + min; + return set_dB[ctl_dir](elem, value, dir); + } + + if (min != SND_CTL_TLV_DB_GAIN_MUTE) { + min_norm = exp10((min - max) / 6000.0); + volume = volume * (1 - min_norm) + min_norm; + } + value = lrint_dir(6000.0 * log10(volume), dir) + max; + return set_dB[ctl_dir](elem, value, dir); +} + +double get_normalized_playback_volume(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t channel) +{ + return get_normalized_volume(elem, channel, PLAYBACK); +} + +double get_normalized_capture_volume(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t channel) +{ + return get_normalized_volume(elem, channel, CAPTURE); +} + + +int set_normalized_playback_volume(snd_mixer_elem_t *elem, + double volume, + int dir) +{ + return set_normalized_volume(elem, volume, dir, PLAYBACK); +} + +int set_normalized_capture_volume(snd_mixer_elem_t *elem, + double volume, + int dir) +{ + return set_normalized_volume(elem, volume, dir, CAPTURE); +} diff -Nru mpd-0.19.21/src/mixer/plugins/volume_mapping.h mpd-0.20.9/src/mixer/plugins/volume_mapping.h --- mpd-0.19.21/src/mixer/plugins/volume_mapping.h 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/volume_mapping.h 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef VOLUME_MAPPING_H_INCLUDED +#define VOLUME_MAPPING_H_INCLUDED + +#include + +double get_normalized_playback_volume(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t channel); +double get_normalized_capture_volume(snd_mixer_elem_t *elem, + snd_mixer_selem_channel_id_t channel); +int set_normalized_playback_volume(snd_mixer_elem_t *elem, + double volume, + int dir); +int set_normalized_capture_volume(snd_mixer_elem_t *elem, + double volume, + int dir); + +#endif diff -Nru mpd-0.19.21/src/mixer/plugins/WinmmMixerPlugin.cxx mpd-0.20.9/src/mixer/plugins/WinmmMixerPlugin.cxx --- mpd-0.19.21/src/mixer/plugins/WinmmMixerPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/plugins/WinmmMixerPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,11 +21,11 @@ #include "mixer/MixerInternal.hxx" #include "output/OutputAPI.hxx" #include "output/plugins/WinmmOutputPlugin.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include +#include + #include #include #include @@ -40,19 +40,16 @@ } /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } - virtual void Close() override { + void Close() override { } - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; -static constexpr Domain winmm_mixer_domain("winmm_mixer"); - static inline int winmm_volume_decode(DWORD volume) { @@ -69,40 +66,33 @@ static Mixer * winmm_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new WinmmMixer((WinmmOutput &)ao, listener); } int -WinmmMixer::GetVolume(Error &error) +WinmmMixer::GetVolume() { DWORD volume; HWAVEOUT handle = winmm_output_get_handle(output); MMRESULT result = waveOutGetVolume(handle, &volume); - if (result != MMSYSERR_NOERROR) { - error.Set(winmm_mixer_domain, "Failed to get winmm volume"); - return -1; - } + if (result != MMSYSERR_NOERROR) + throw std::runtime_error("Failed to get winmm volume"); return winmm_volume_decode(volume); } -bool -WinmmMixer::SetVolume(unsigned volume, Error &error) +void +WinmmMixer::SetVolume(unsigned volume) { DWORD value = winmm_volume_encode(volume); HWAVEOUT handle = winmm_output_get_handle(output); MMRESULT result = waveOutSetVolume(handle, value); - if (result != MMSYSERR_NOERROR) { - error.Set(winmm_mixer_domain, "Failed to set winmm volume"); - return false; - } - - return true; + if (result != MMSYSERR_NOERROR) + throw std::runtime_error("Failed to set winmm volume"); } const MixerPlugin winmm_mixer_plugin = { diff -Nru mpd-0.19.21/src/mixer/Volume.cxx mpd-0.20.9/src/mixer/Volume.cxx --- mpd-0.19.21/src/mixer/Volume.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/Volume.cxx 2017-05-08 13:03:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "Volume.hxx" #include "output/MultipleOutputs.hxx" #include "Idle.hxx" -#include "util/StringUtil.hxx" +#include "util/StringCompare.hxx" #include "util/Domain.hxx" #include "system/PeriodClock.hxx" #include "fs/io/BufferedOutputStream.hxx" @@ -42,17 +42,17 @@ static PeriodClock hardware_volume_clock; void -InvalidateHardwareVolume() +InvalidateHardwareVolume() noexcept { /* flush the hardware volume cache */ last_hardware_volume = -1; } int -volume_level_get(const MultipleOutputs &outputs) +volume_level_get(const MultipleOutputs &outputs) noexcept { if (last_hardware_volume >= 0 && - !hardware_volume_clock.CheckUpdate(1000)) + !hardware_volume_clock.CheckUpdate(std::chrono::seconds(1))) /* throttle access to hardware mixers */ return last_hardware_volume; @@ -98,10 +98,10 @@ char *end = nullptr; long int sv; - if (!StringStartsWith(line, SW_VOLUME_STATE)) + line = StringAfterPrefix(line, SW_VOLUME_STATE); + if (line == nullptr) return false; - line += sizeof(SW_VOLUME_STATE) - 1; sv = strtol(line, &end, 10); if (*end == 0 && sv >= 0 && sv <= 100) software_volume_change(outputs, sv); @@ -118,7 +118,7 @@ } unsigned -sw_volume_state_get_hash(void) +sw_volume_state_get_hash() noexcept { return volume_software_set; } diff -Nru mpd-0.19.21/src/mixer/Volume.hxx mpd-0.20.9/src/mixer/Volume.hxx --- mpd-0.19.21/src/mixer/Volume.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/mixer/Volume.hxx 2017-05-08 13:03:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,11 +26,11 @@ class BufferedOutputStream; void -InvalidateHardwareVolume(); +InvalidateHardwareVolume() noexcept; gcc_pure int -volume_level_get(const MultipleOutputs &outputs); +volume_level_get(const MultipleOutputs &outputs) noexcept; bool volume_level_change(MultipleOutputs &outputs, unsigned volume); @@ -49,6 +49,6 @@ */ gcc_pure unsigned -sw_volume_state_get_hash(void); +sw_volume_state_get_hash() noexcept; #endif diff -Nru mpd-0.19.21/src/MixRampInfo.hxx mpd-0.20.9/src/MixRampInfo.hxx --- mpd-0.19.21/src/MixRampInfo.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MixRampInfo.hxx 2017-06-03 19:43:37.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,45 +31,45 @@ public: MixRampInfo() = default; - void Clear() { + void Clear() noexcept { start.clear(); end.clear(); } gcc_pure - bool IsDefined() const { + bool IsDefined() const noexcept { return !start.empty() || !end.empty(); } gcc_pure - const char *GetStart() const { + const char *GetStart() const noexcept { return start.empty() ? nullptr : start.c_str(); } gcc_pure - const char *GetEnd() const { + const char *GetEnd() const noexcept { return end.empty() ? nullptr : end.c_str(); } - void SetStart(const char *new_value) { + void SetStart(const char *new_value) noexcept { if (new_value == nullptr) start.clear(); else start = new_value; } - void SetStart(std::string &&new_value) { + void SetStart(std::string &&new_value) noexcept { start = std::move(new_value); } - void SetEnd(const char *new_value) { + void SetEnd(const char *new_value) noexcept { if (new_value == nullptr) end.clear(); else end = new_value; } - void SetEnd(std::string &&new_value) { + void SetEnd(std::string &&new_value) noexcept { end = std::move(new_value); } }; diff -Nru mpd-0.19.21/src/MusicBuffer.cxx mpd-0.20.9/src/MusicBuffer.cxx --- mpd-0.19.21/src/MusicBuffer.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicBuffer.cxx 2017-05-08 13:22:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,29 +20,26 @@ #include "config.h" #include "MusicBuffer.hxx" #include "MusicChunk.hxx" -#include "system/FatalError.hxx" #include -MusicBuffer::MusicBuffer(unsigned num_chunks) +MusicBuffer::MusicBuffer(unsigned num_chunks) noexcept :buffer(num_chunks) { - if (buffer.IsOOM()) - FatalError("Failed to allocate buffer"); } MusicChunk * -MusicBuffer::Allocate() +MusicBuffer::Allocate() noexcept { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); return buffer.Allocate(); } void -MusicBuffer::Return(MusicChunk *chunk) +MusicBuffer::Return(MusicChunk *chunk) noexcept { assert(chunk != nullptr); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (chunk->other != nullptr) { assert(chunk->other->other == nullptr); diff -Nru mpd-0.19.21/src/MusicBuffer.hxx mpd-0.20.9/src/MusicBuffer.hxx --- mpd-0.19.21/src/MusicBuffer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicBuffer.hxx 2017-06-03 19:34:15.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ * @param num_chunks the number of #MusicChunk reserved in * this buffer */ - MusicBuffer(unsigned num_chunks); + MusicBuffer(unsigned num_chunks) noexcept; #ifndef NDEBUG /** @@ -60,7 +60,7 @@ * music_buffer_new(). */ gcc_pure - unsigned GetSize() const { + unsigned GetSize() const noexcept { return buffer.GetCapacity(); } @@ -71,13 +71,13 @@ * @return an empty chunk or nullptr if there are no chunks * available */ - MusicChunk *Allocate(); + MusicChunk *Allocate() noexcept; /** * Returns a chunk to the buffer. It can be reused by * Allocate() then. */ - void Return(MusicChunk *chunk); + void Return(MusicChunk *chunk) noexcept; }; #endif diff -Nru mpd-0.19.21/src/MusicChunk.cxx mpd-0.20.9/src/MusicChunk.cxx --- mpd-0.19.21/src/MusicChunk.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicChunk.cxx 2017-05-08 13:21:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ #ifndef NDEBUG bool -MusicChunk::CheckFormat(const AudioFormat other_format) const +MusicChunk::CheckFormat(const AudioFormat other_format) const noexcept { assert(other_format.IsValid()); @@ -41,7 +41,7 @@ WritableBuffer MusicChunk::Write(const AudioFormat af, - SongTime data_time, uint16_t _bit_rate) + SongTime data_time, uint16_t _bit_rate) noexcept { assert(CheckFormat(af)); assert(length == 0 || audio_format.IsValid()); @@ -64,7 +64,7 @@ } bool -MusicChunk::Expand(const AudioFormat af, size_t _length) +MusicChunk::Expand(const AudioFormat af, size_t _length) noexcept { const size_t frame_size = af.GetFrameSize(); diff -Nru mpd-0.19.21/src/MusicChunk.hxx mpd-0.20.9/src/MusicChunk.hxx --- mpd-0.19.21/src/MusicChunk.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicChunk.hxx 2017-05-08 13:21:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -48,7 +48,7 @@ * An optional chunk which should be mixed into this chunk. * This is used for cross-fading. */ - MusicChunk *other; + MusicChunk *other = nullptr; /** * The current mix ratio for cross-fading: 1.0 means play 100% @@ -57,7 +57,7 @@ float mix_ratio; /** number of bytes stored in this chunk */ - uint16_t length; + uint16_t length = 0; /** current bit rate of the source file */ uint16_t bit_rate; @@ -71,7 +71,7 @@ * object is owned by this chunk, and must be freed when this * chunk is deinitialized. */ - Tag *tag; + Tag *tag = nullptr; /** * Replay gain information associated with this chunk. @@ -84,7 +84,7 @@ * changed since the last chunk. The magic value 0 indicates * that there is no replay gain info available. */ - unsigned replay_gain_serial; + unsigned replay_gain_serial = 0; /** the data (probably PCM) */ uint8_t data[CHUNK_SIZE]; @@ -93,14 +93,14 @@ AudioFormat audio_format; #endif - MusicChunk() - :other(nullptr), - length(0), - tag(nullptr), - replay_gain_serial(0) {} + MusicChunk() = default; + + MusicChunk(const MusicChunk &) = delete; ~MusicChunk(); + MusicChunk &operator=(const MusicChunk &) = delete; + bool IsEmpty() const { return length == 0 && tag == nullptr; } @@ -111,7 +111,7 @@ * specified audio_format. */ gcc_pure - bool CheckFormat(AudioFormat audio_format) const; + bool CheckFormat(AudioFormat audio_format) const noexcept; #endif /** @@ -119,30 +119,26 @@ * where you may write into. After you are finished, call * Expand(). * - * @param chunk the MusicChunk object - * @param audio_format the audio format for the appended data; + * @param af the audio format for the appended data; * must stay the same for the life cycle of this chunk * @param data_time the time within the song * @param bit_rate the current bit rate of the source file - * @param max_length_r the maximum write length is returned - * here * @return a writable buffer, or nullptr if the chunk is full */ WritableBuffer Write(AudioFormat af, SongTime data_time, - uint16_t bit_rate); + uint16_t bit_rate) noexcept; /** * Increases the length of the chunk after the caller has written to * the buffer returned by Write(). * - * @param chunk the MusicChunk object - * @param audio_format the audio format for the appended data; must + * @param af the audio format for the appended data; must * stay the same for the life cycle of this chunk * @param length the number of bytes which were appended * @return true if the chunk is full */ - bool Expand(AudioFormat af, size_t length); + bool Expand(AudioFormat af, size_t length) noexcept; }; #endif diff -Nru mpd-0.19.21/src/MusicPipe.cxx mpd-0.20.9/src/MusicPipe.cxx --- mpd-0.19.21/src/MusicPipe.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicPipe.cxx 2017-06-03 19:34:15.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,9 +25,9 @@ #ifndef NDEBUG bool -MusicPipe::Contains(const MusicChunk *chunk) const +MusicPipe::Contains(const MusicChunk *chunk) const noexcept { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); for (const MusicChunk *i = head; i != nullptr; i = i->next) if (i == chunk) @@ -39,9 +39,9 @@ #endif MusicChunk * -MusicPipe::Shift() +MusicPipe::Shift() noexcept { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); MusicChunk *chunk = head; if (chunk != nullptr) { @@ -73,7 +73,7 @@ } void -MusicPipe::Clear(MusicBuffer &buffer) +MusicPipe::Clear(MusicBuffer &buffer) noexcept { MusicChunk *chunk; @@ -82,12 +82,12 @@ } void -MusicPipe::Push(MusicChunk *chunk) +MusicPipe::Push(MusicChunk *chunk) noexcept { assert(!chunk->IsEmpty()); assert(chunk->length == 0 || chunk->audio_format.IsValid()); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(size > 0 || !audio_format.IsDefined()); assert(!audio_format.IsDefined() || diff -Nru mpd-0.19.21/src/MusicPipe.hxx mpd-0.20.9/src/MusicPipe.hxx --- mpd-0.19.21/src/MusicPipe.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/MusicPipe.hxx 2017-06-03 19:34:37.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -38,31 +38,28 @@ */ class MusicPipe { /** the first chunk */ - MusicChunk *head; + MusicChunk *head = nullptr; /** a pointer to the tail of the chunk */ - MusicChunk **tail_r; + MusicChunk **tail_r = &head; /** the current number of chunks */ - unsigned size; + unsigned size = 0; /** a mutex which protects #head and #tail_r */ mutable Mutex mutex; #ifndef NDEBUG - AudioFormat audio_format; + AudioFormat audio_format = AudioFormat::Undefined(); #endif public: /** * Creates a new #MusicPipe object. It is empty. */ - MusicPipe() - :head(nullptr), tail_r(&head), size(0) { -#ifndef NDEBUG - audio_format.Clear(); -#endif - } + MusicPipe() = default; + + MusicPipe(const MusicPipe &) = delete; /** * Frees the object. It must be empty now. @@ -72,13 +69,15 @@ assert(tail_r == &head); } + MusicPipe &operator=(const MusicPipe &) = delete; + #ifndef NDEBUG /** * Checks if the audio format if the chunk is equal to the specified * audio_format. */ gcc_pure - bool CheckFormat(AudioFormat other) const { + bool CheckFormat(AudioFormat other) const noexcept { return !audio_format.IsDefined() || audio_format == other; } @@ -87,7 +86,7 @@ * Checks if the specified chunk is enqueued in the music pipe. */ gcc_pure - bool Contains(const MusicChunk *chunk) const; + bool Contains(const MusicChunk *chunk) const noexcept; #endif /** @@ -95,37 +94,37 @@ * nullptr if the pipe is empty. */ gcc_pure - const MusicChunk *Peek() const { + const MusicChunk *Peek() const noexcept { return head; } /** * Removes the first chunk from the head, and returns it. */ - MusicChunk *Shift(); + MusicChunk *Shift() noexcept; /** * Clears the whole pipe and returns the chunks to the buffer. * * @param buffer the buffer object to return the chunks to */ - void Clear(MusicBuffer &buffer); + void Clear(MusicBuffer &buffer) noexcept; /** * Pushes a chunk to the tail of the pipe. */ - void Push(MusicChunk *chunk); + void Push(MusicChunk *chunk) noexcept; /** * Returns the number of chunks currently in this pipe. */ gcc_pure - unsigned GetSize() const { + unsigned GetSize() const noexcept { return size; } gcc_pure - bool IsEmpty() const { + bool IsEmpty() const noexcept { return GetSize() == 0; } }; diff -Nru mpd-0.19.21/src/neighbor/Explorer.hxx mpd-0.20.9/src/neighbor/Explorer.hxx --- mpd-0.19.21/src/neighbor/Explorer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Explorer.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ #include -class Error; class NeighborListener; struct NeighborInfo; @@ -54,8 +53,10 @@ /** * Start exploring the neighborhood. + * + * Throws std::runtime_error on error. */ - virtual bool Open(Error &error) = 0; + virtual void Open() = 0; /** * Stop exploring. diff -Nru mpd-0.19.21/src/neighbor/Glue.cxx mpd-0.20.9/src/neighbor/Glue.cxx --- mpd-0.19.21/src/neighbor/Glue.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Glue.cxx 2017-05-08 15:13:28.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,9 +24,11 @@ #include "NeighborPlugin.hxx" #include "Info.hxx" #include "config/ConfigGlobal.hxx" -#include "config/ConfigData.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "config/Block.hxx" +#include "util/RuntimeError.hxx" + +#include NeighborGlue::Explorer::~Explorer() { @@ -37,57 +39,50 @@ static NeighborExplorer * CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener, - const config_param ¶m, Error &error) + const ConfigBlock &block) { - const char *plugin_name = param.GetBlockValue("plugin"); - if (plugin_name == nullptr) { - error.Set(config_domain, - "Missing \"plugin\" configuration"); - return nullptr; - } + const char *plugin_name = block.GetBlockValue("plugin"); + if (plugin_name == nullptr) + throw std::runtime_error("Missing \"plugin\" configuration"); const NeighborPlugin *plugin = GetNeighborPluginByName(plugin_name); - if (plugin == nullptr) { - error.Format(config_domain, "No such neighbor plugin: %s", - plugin_name); - return nullptr; - } + if (plugin == nullptr) + throw FormatRuntimeError("No such neighbor plugin: %s", + plugin_name); - return plugin->create(loop, listener, param, error); + return plugin->create(loop, listener, block); } -bool -NeighborGlue::Init(EventLoop &loop, NeighborListener &listener, Error &error) +void +NeighborGlue::Init(EventLoop &loop, NeighborListener &listener) { - for (const config_param *param = config_get_param(CONF_NEIGHBORS); - param != nullptr; param = param->next) { - NeighborExplorer *explorer = - CreateNeighborExplorer(loop, listener, *param, error); - if (explorer == nullptr) { - error.FormatPrefix("Line %i: ", param->line); - return false; + for (const auto *block = config_get_block(ConfigBlockOption::NEIGHBORS); + block != nullptr; block = block->next) { + try { + auto *explorer = + CreateNeighborExplorer(loop, listener, *block); + explorers.emplace_front(explorer); + } catch (...) { + std::throw_with_nested(FormatRuntimeError("Line %i: ", + block->line)); } - - explorers.emplace_front(explorer); } - - return true; } -bool -NeighborGlue::Open(Error &error) +void +NeighborGlue::Open() { for (auto i = explorers.begin(), end = explorers.end(); i != end; ++i) { - if (!i->explorer->Open(error)) { + try { + i->explorer->Open(); + } catch (...) { /* roll back */ for (auto k = explorers.begin(); k != i; ++k) k->explorer->Close(); - return false; + throw; } } - - return true; } void @@ -98,7 +93,7 @@ } NeighborGlue::List -NeighborGlue::GetList() const +NeighborGlue::GetList() const noexcept { List result; diff -Nru mpd-0.19.21/src/neighbor/Glue.hxx mpd-0.20.9/src/neighbor/Glue.hxx --- mpd-0.19.21/src/neighbor/Glue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Glue.hxx 2017-05-08 15:13:30.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,8 +26,6 @@ #include -struct config_param; -class Error; class EventLoop; class NeighborExplorer; class NeighborListener; @@ -60,9 +58,12 @@ return explorers.empty(); } - bool Init(EventLoop &loop, NeighborListener &listener, Error &error); + /** + * Throws std::runtime_error on error. + */ + void Init(EventLoop &loop, NeighborListener &listener); - bool Open(Error &error); + void Open(); void Close(); /** @@ -70,7 +71,7 @@ * plugins. */ gcc_pure - List GetList() const; + List GetList() const noexcept; }; #endif diff -Nru mpd-0.19.21/src/neighbor/Info.hxx mpd-0.20.9/src/neighbor/Info.hxx --- mpd-0.19.21/src/neighbor/Info.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Info.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/neighbor/Listener.hxx mpd-0.20.9/src/neighbor/Listener.hxx --- mpd-0.19.21/src/neighbor/Listener.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Listener.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/neighbor/NeighborPlugin.hxx mpd-0.20.9/src/neighbor/NeighborPlugin.hxx --- mpd-0.19.21/src/neighbor/NeighborPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/NeighborPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,7 @@ #ifndef MPD_NEIGHBOR_PLUGIN_HXX #define MPD_NEIGHBOR_PLUGIN_HXX -struct config_param; -class Error; +struct ConfigBlock; class EventLoop; class NeighborListener; class NeighborExplorer; @@ -33,8 +32,7 @@ * Allocates and configures a #NeighborExplorer instance. */ NeighborExplorer *(*create)(EventLoop &loop, NeighborListener &listener, - const config_param ¶m, - Error &error); + const ConfigBlock &block); }; #endif diff -Nru mpd-0.19.21/src/neighbor/plugins/SmbclientNeighborPlugin.cxx mpd-0.20.9/src/neighbor/plugins/SmbclientNeighborPlugin.cxx --- mpd-0.19.21/src/neighbor/plugins/SmbclientNeighborPlugin.cxx 2016-08-23 07:47:48.000000000 +0000 +++ mpd-0.20.9/src/neighbor/plugins/SmbclientNeighborPlugin.cxx 2017-06-04 10:42:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -30,14 +30,10 @@ #include "thread/Cond.hxx" #include "thread/Thread.hxx" #include "thread/Name.hxx" -#include "util/Macros.hxx" -#include "util/Domain.hxx" -#include "util/Error.hxx" #include "Log.hxx" #include -#include #include class SmbclientNeighborExplorer final : public NeighborExplorer { @@ -52,12 +48,12 @@ Server(const Server &) = delete; gcc_pure - bool operator==(const Server &other) const { + bool operator==(const Server &other) const noexcept { return name == other.name; } gcc_pure - NeighborInfo Export() const { + NeighborInfo Export() const noexcept { return { "smb://" + name + "/", comment }; } }; @@ -76,7 +72,7 @@ :NeighborExplorer(_listener) {} /* virtual methods from class NeighborExplorer */ - virtual bool Open(Error &error) override; + void Open() override; virtual void Close() override; virtual List GetList() const override; @@ -86,11 +82,11 @@ static void ThreadFunc(void *ctx); }; -bool -SmbclientNeighborExplorer::Open(Error &error) +void +SmbclientNeighborExplorer::Open() { quit = false; - return thread.Start(ThreadFunc, this, error); + thread.Start(ThreadFunc, this); } void @@ -107,7 +103,7 @@ NeighborExplorer::List SmbclientNeighborExplorer::GetList() const { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); /* List list; for (const auto &i : servers) @@ -173,10 +169,10 @@ gcc_pure static NeighborExplorer::List -DetectServers() +DetectServers() noexcept { NeighborExplorer::List list; - const ScopeLock protect(smbclient_mutex); + const std::lock_guard protect(smbclient_mutex); ReadServers(list, "smb://"); return list; } @@ -185,7 +181,7 @@ static NeighborExplorer::List::const_iterator FindBeforeServerByURI(NeighborExplorer::List::const_iterator prev, NeighborExplorer::List::const_iterator end, - const std::string &uri) + const std::string &uri) noexcept { for (auto i = std::next(prev); i != end; prev = i, i = std::next(prev)) if (i->uri == uri) @@ -255,7 +251,7 @@ break; // TODO: sleep for how long? - cond.timed_wait(mutex, 10000); + cond.timed_wait(mutex, std::chrono::seconds(10)); } mutex.unlock(); @@ -273,11 +269,9 @@ static NeighborExplorer * smbclient_neighbor_create(gcc_unused EventLoop &loop, NeighborListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { - if (!SmbclientInit(error)) - return nullptr; + SmbclientInit(); return new SmbclientNeighborExplorer(listener); } diff -Nru mpd-0.19.21/src/neighbor/plugins/SmbclientNeighborPlugin.hxx mpd-0.20.9/src/neighbor/plugins/SmbclientNeighborPlugin.hxx --- mpd-0.19.21/src/neighbor/plugins/SmbclientNeighborPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/plugins/SmbclientNeighborPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/neighbor/plugins/UpnpNeighborPlugin.cxx mpd-0.20.9/src/neighbor/plugins/UpnpNeighborPlugin.cxx --- mpd-0.19.21/src/neighbor/plugins/UpnpNeighborPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/plugins/UpnpNeighborPlugin.cxx 2017-06-04 10:40:16.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,7 +19,6 @@ #include "config.h" #include "UpnpNeighborPlugin.hxx" -#include "lib/upnp/Domain.hxx" #include "lib/upnp/ClientInit.hxx" #include "lib/upnp/Discovery.hxx" #include "lib/upnp/ContentDirectoryService.hxx" @@ -29,6 +28,8 @@ #include "neighbor/Info.hxx" #include "Log.hxx" +#include + class UpnpNeighborExplorer final : public NeighborExplorer, UPnPDiscoveryListener { struct Server { @@ -42,12 +43,12 @@ Server(const Server &) = delete; gcc_pure - bool operator==(const Server &other) const { + bool operator==(const Server &other) const noexcept { return name == other.name; } gcc_pure - NeighborInfo Export() const { + NeighborInfo Export() const noexcept { return { "smb://" + name + "/", comment }; } }; @@ -59,7 +60,7 @@ :NeighborExplorer(_listener) {} /* virtual methods from class NeighborExplorer */ - virtual bool Open(Error &error) override; + void Open() override; virtual void Close() override; virtual List GetList() const override; @@ -69,21 +70,21 @@ virtual void LostUPnP(const ContentDirectoryService &service) override; }; -bool -UpnpNeighborExplorer::Open(Error &error) +void +UpnpNeighborExplorer::Open() { UpnpClient_Handle handle; - if (!UpnpClientGlobalInit(handle, error)) - return false; + UpnpClientGlobalInit(handle); discovery = new UPnPDeviceDirectory(handle, this); - if (!discovery->Start(error)) { + + try { + discovery->Start(); + } catch (...) { delete discovery; UpnpClientGlobalFinish(); - return false; + throw; } - - return true; } void @@ -98,10 +99,10 @@ { std::vector tmp; - { - Error error; - if (!discovery->getDirServices(tmp, error)) - LogError(error); + try { + tmp = discovery->GetDirectories(); + } catch (const std::runtime_error &e) { + LogError(e); } List result; @@ -127,8 +128,7 @@ static NeighborExplorer * upnp_neighbor_create(gcc_unused EventLoop &loop, NeighborListener &listener, - gcc_unused const config_param ¶m, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new UpnpNeighborExplorer(listener); } diff -Nru mpd-0.19.21/src/neighbor/plugins/UpnpNeighborPlugin.hxx mpd-0.20.9/src/neighbor/plugins/UpnpNeighborPlugin.hxx --- mpd-0.19.21/src/neighbor/plugins/UpnpNeighborPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/plugins/UpnpNeighborPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/neighbor/Registry.cxx mpd-0.20.9/src/neighbor/Registry.cxx --- mpd-0.19.21/src/neighbor/Registry.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Registry.cxx 2017-05-08 14:11:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,14 +29,14 @@ #ifdef ENABLE_SMBCLIENT &smbclient_neighbor_plugin, #endif -#ifdef HAVE_LIBUPNP +#ifdef ENABLE_UPNP &upnp_neighbor_plugin, #endif nullptr }; const NeighborPlugin * -GetNeighborPluginByName(const char *name) +GetNeighborPluginByName(const char *name) noexcept { for (auto i = neighbor_plugins; *i != nullptr; ++i) if (strcmp((*i)->name, name) == 0) diff -Nru mpd-0.19.21/src/neighbor/Registry.hxx mpd-0.20.9/src/neighbor/Registry.hxx --- mpd-0.19.21/src/neighbor/Registry.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/neighbor/Registry.hxx 2017-05-08 14:11:46.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -32,6 +32,6 @@ gcc_pure const NeighborPlugin * -GetNeighborPluginByName(const char *name); +GetNeighborPluginByName(const char *name) noexcept; #endif diff -Nru mpd-0.19.21/src/net/AllocatedSocketAddress.cxx mpd-0.20.9/src/net/AllocatedSocketAddress.cxx --- mpd-0.19.21/src/net/AllocatedSocketAddress.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/AllocatedSocketAddress.cxx 2017-05-08 14:19:58.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AllocatedSocketAddress.hxx" + +#include + +#ifdef HAVE_UN +#include +#endif + +AllocatedSocketAddress & +AllocatedSocketAddress::operator=(SocketAddress src) +{ + if (src.IsNull()) { + Clear(); + } else { + SetSize(src.GetSize()); + memcpy(address, src.GetAddress(), size); + } + + return *this; +} + +void +AllocatedSocketAddress::SetSize(size_type new_size) noexcept +{ + if (size == new_size) + return; + + free(address); + size = new_size; + address = (struct sockaddr *)malloc(size); +} + +#ifdef HAVE_UN + +void +AllocatedSocketAddress::SetLocal(const char *path) noexcept +{ + const bool is_abstract = *path == '@'; + + /* sun_path must be null-terminated unless it's an abstract + socket */ + const size_t path_length = strlen(path) + !is_abstract; + + struct sockaddr_un *sun; + SetSize(sizeof(*sun) - sizeof(sun->sun_path) + path_length); + sun = (struct sockaddr_un *)address; + sun->sun_family = AF_UNIX; + memcpy(sun->sun_path, path, path_length); + + if (is_abstract) + sun->sun_path[0] = 0; +} + +#endif diff -Nru mpd-0.19.21/src/net/AllocatedSocketAddress.hxx mpd-0.20.9/src/net/AllocatedSocketAddress.hxx --- mpd-0.19.21/src/net/AllocatedSocketAddress.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/AllocatedSocketAddress.hxx 2017-06-03 20:02:28.000000000 +0000 @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ALLOCATED_SOCKET_ADDRESS_HPP +#define ALLOCATED_SOCKET_ADDRESS_HPP + +#include "SocketAddress.hxx" +#include "Features.hxx" +#include "Compiler.h" + +#include + +#include + +struct sockaddr; + +class AllocatedSocketAddress { +public: + typedef SocketAddress::size_type size_type; + +private: + struct sockaddr *address; + size_type size; + + AllocatedSocketAddress(struct sockaddr *_address, + size_type _size) + :address(_address), size(_size) {} + +public: + AllocatedSocketAddress():address(nullptr), size(0) {} + + explicit AllocatedSocketAddress(SocketAddress src) + :address(nullptr), size(0) { + *this = src; + } + + AllocatedSocketAddress(const AllocatedSocketAddress &) = delete; + + AllocatedSocketAddress(AllocatedSocketAddress &&src) + :address(src.address), size(src.size) { + src.address = nullptr; + src.size = 0; + } + + ~AllocatedSocketAddress() { + free(address); + } + + AllocatedSocketAddress &operator=(SocketAddress src); + + AllocatedSocketAddress &operator=(const AllocatedSocketAddress &) = delete; + + AllocatedSocketAddress &operator=(AllocatedSocketAddress &&src) noexcept { + std::swap(address, src.address); + std::swap(size, src.size); + return *this; + } + + gcc_pure + bool operator==(SocketAddress other) const noexcept { + return (SocketAddress)*this == other; + } + + bool operator!=(SocketAddress &other) const noexcept { + return !(*this == other); + } + + gcc_const + static AllocatedSocketAddress Null() noexcept { + return AllocatedSocketAddress(nullptr, 0); + } + + bool IsNull() const noexcept { + return address == nullptr; + } + + size_type GetSize() const noexcept { + return size; + } + + const struct sockaddr *GetAddress() const noexcept { + return address; + } + + operator SocketAddress() const noexcept { + return SocketAddress(address, size); + } + + operator const struct sockaddr *() const noexcept { + return address; + } + + int GetFamily() const noexcept { + return address->sa_family; + } + + /** + * Does the object have a well-defined address? Check !IsNull() + * before calling this method. + */ + bool IsDefined() const noexcept { + return GetFamily() != AF_UNSPEC; + } + + void Clear() noexcept { + free(address); + address = nullptr; + size = 0; + } + +#ifdef HAVE_UN + /** + * Make this a "local" address (UNIX domain socket). If the path + * begins with a '@', then the rest specifies an "abstract" local + * address. + */ + void SetLocal(const char *path) noexcept; +#endif + +private: + void SetSize(size_type new_size) noexcept; +}; + +#endif diff -Nru mpd-0.19.21/src/net/Features.hxx mpd-0.20.9/src/net/Features.hxx --- mpd-0.19.21/src/net/Features.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/Features.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef NET_FEATURES_HXX +#define NET_FEATURES_HXX + +/* feature macros are defined in config.h, and this header verifies + that it has been included earlier */ +#include "check.h" + +#endif diff -Nru mpd-0.19.21/src/net/Resolver.cxx mpd-0.20.9/src/net/Resolver.cxx --- mpd-0.19.21/src/net/Resolver.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/Resolver.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Resolver.hxx" +#include "util/RuntimeError.hxx" + +#include + +#ifdef WIN32 +#include +#else +#include +#include +#include +#endif + +#include +#include + +struct addrinfo * +resolve_host_port(const char *host_port, unsigned default_port, + int flags, int socktype) +{ + std::string p(host_port); + const char *host = p.c_str(), *port = nullptr; + + if (host_port[0] == '[') { + /* IPv6 needs enclosing square braces, to + differentiate between IP colons and the port + separator */ + + size_t q = p.find(']', 1); + if (q != p.npos && p[q + 1] == ':' && p[q + 2] != 0) { + p[q] = 0; + port = host + q + 2; + ++host; + } + } + + if (port == nullptr) { + /* port is after the colon, but only if it's the only + colon (don't split IPv6 addresses) */ + + auto q = p.find(':'); + if (q != p.npos && p[q + 1] != 0 && + p.find(':', q + 1) == p.npos) { + p[q] = 0; + port = host + q + 1; + } + } + + char buffer[32]; + if (port == nullptr && default_port != 0) { + snprintf(buffer, sizeof(buffer), "%u", default_port); + port = buffer; + } + + if ((flags & AI_PASSIVE) != 0 && strcmp(host, "*") == 0) + host = nullptr; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = flags; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = socktype; + + struct addrinfo *ai; + int ret = getaddrinfo(host, port, &hints, &ai); + if (ret != 0) + throw FormatRuntimeError("Failed to look up '%s': %s", + host_port, gai_strerror(ret)); + + return ai; +} diff -Nru mpd-0.19.21/src/net/Resolver.hxx mpd-0.20.9/src/net/Resolver.hxx --- mpd-0.19.21/src/net/Resolver.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/Resolver.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_RESOLVER_HXX +#define MPD_RESOLVER_HXX + +#include "check.h" +#include "Compiler.h" + +struct addrinfo; + +/** + * Resolve a specification in the form "host", "host:port", + * "[host]:port". This is a convenience wrapper for getaddrinfo(). + * + * Throws #std::runtime_error on error. + * + * @param default_port a default port number that will be used if none + * is given in the string (if applicable); pass 0 to go without a + * default + * @return an #addrinfo linked list that must be freed with + * freeaddrinfo() + */ +addrinfo * +resolve_host_port(const char *host_port, unsigned default_port, + int flags, int socktype); + +#endif diff -Nru mpd-0.19.21/src/net/SocketAddress.cxx mpd-0.20.9/src/net/SocketAddress.cxx --- mpd-0.19.21/src/net/SocketAddress.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketAddress.cxx 2017-05-08 14:19:11.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "SocketAddress.hxx" + +#include + +bool +SocketAddress::operator==(SocketAddress other) const noexcept +{ + return size == other.size && memcmp(address, other.address, size) == 0; +} diff -Nru mpd-0.19.21/src/net/SocketAddress.hxx mpd-0.20.9/src/net/SocketAddress.hxx --- mpd-0.19.21/src/net/SocketAddress.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketAddress.hxx 2017-05-08 14:19:05.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SOCKET_ADDRESS_HXX +#define SOCKET_ADDRESS_HXX + +#include "Compiler.h" + +#include + +#ifdef WIN32 +#include +#else +#include +#endif + +/** + * An OO wrapper for struct sockaddr. + */ +class SocketAddress { +public: +#ifdef WIN32 + typedef int size_type; +#else + typedef socklen_t size_type; +#endif + +private: + const struct sockaddr *address; + size_type size; + +public: + SocketAddress() = default; + + constexpr SocketAddress(std::nullptr_t):address(nullptr), size(0) {} + + constexpr SocketAddress(const struct sockaddr *_address, + size_type _size) + :address(_address), size(_size) {} + + static constexpr SocketAddress Null() { + return nullptr; + } + + constexpr bool IsNull() const { + return address == nullptr; + } + + const struct sockaddr *GetAddress() const { + return address; + } + + constexpr size_type GetSize() const { + return size; + } + + constexpr int GetFamily() const { + return address->sa_family; + } + + /** + * Does the object have a well-defined address? Check !IsNull() + * before calling this method. + */ + bool IsDefined() const { + return GetFamily() != AF_UNSPEC; + } + + gcc_pure + bool operator==(const SocketAddress other) const noexcept; + + bool operator!=(const SocketAddress other) const noexcept { + return !(*this == other); + } +}; + +#endif diff -Nru mpd-0.19.21/src/net/SocketError.cxx mpd-0.20.9/src/net/SocketError.cxx --- mpd-0.19.21/src/net/SocketError.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketError.cxx 2017-05-08 14:17:17.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SocketError.hxx" +#include "util/Macros.hxx" + +#include + +#ifdef WIN32 + +SocketErrorMessage::SocketErrorMessage(socket_error_t code) noexcept +{ +#ifdef _UNICODE + wchar_t buffer[ARRAY_SIZE(msg)]; +#else + auto *buffer = msg; +#endif + + DWORD nbytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + nullptr, code, 0, + buffer, ARRAY_SIZE(msg), nullptr); + if (nbytes == 0) { + strcpy(msg, "Unknown error"); + return; + } + +#ifdef _UNICODE + auto length = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, + msg, ARRAY_SIZE(msg), + nullptr, nullptr); + if (length <= 0) { + strcpy(msg, "WideCharToMultiByte() error"); + return; + } +#endif +} + +#else + +SocketErrorMessage::SocketErrorMessage(socket_error_t code) noexcept + :msg(strerror(code)) {} + +#endif diff -Nru mpd-0.19.21/src/net/SocketError.hxx mpd-0.20.9/src/net/SocketError.hxx --- mpd-0.19.21/src/net/SocketError.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketError.hxx 2017-05-08 14:19:35.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SOCKET_ERROR_HXX +#define MPD_SOCKET_ERROR_HXX + +#include "Compiler.h" +#include "system/Error.hxx" + +#ifdef WIN32 +#include +typedef DWORD socket_error_t; +#else +#include +typedef int socket_error_t; +#endif + +gcc_pure +static inline socket_error_t +GetSocketError() noexcept +{ +#ifdef WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +} + +gcc_const +static inline bool +IsSocketErrorAgain(socket_error_t code) noexcept +{ +#ifdef WIN32 + return code == WSAEINPROGRESS; +#else + return code == EAGAIN; +#endif +} + +gcc_const +static inline bool +IsSocketErrorInterruped(socket_error_t code) noexcept +{ +#ifdef WIN32 + return code == WSAEINTR; +#else + return code == EINTR; +#endif +} + +gcc_const +static inline bool +IsSocketErrorClosed(socket_error_t code) noexcept +{ +#ifdef WIN32 + return code == WSAECONNRESET; +#else + return code == EPIPE || code == ECONNRESET; +#endif +} + +/** + * Helper class that formats a socket error message into a + * human-readable string. On Windows, a buffer is necessary for this, + * and this class hosts the buffer. + */ +class SocketErrorMessage { +#ifdef WIN32 + char msg[256]; +#else + const char *const msg; +#endif + +public: + explicit SocketErrorMessage(socket_error_t code=GetSocketError()) noexcept; + + operator const char *() const { + return msg; + } +}; + +gcc_const +static inline std::system_error +MakeSocketError(socket_error_t code, const char *msg) noexcept +{ +#ifdef WIN32 + return MakeLastError(code, msg); +#else + return MakeErrno(code, msg); +#endif +} + +gcc_pure +static inline std::system_error +MakeSocketError(const char *msg) noexcept +{ + return MakeSocketError(GetSocketError(), msg); +} + +#endif diff -Nru mpd-0.19.21/src/net/SocketUtil.cxx mpd-0.20.9/src/net/SocketUtil.cxx --- mpd-0.19.21/src/net/SocketUtil.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketUtil.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SocketUtil.hxx" +#include "SocketAddress.hxx" +#include "SocketError.hxx" +#include "system/fd_util.h" + +int +socket_bind_listen(int domain, int type, int protocol, + SocketAddress address, + int backlog) +{ + int fd, ret; + const int reuse = 1; + + fd = socket_cloexec_nonblock(domain, type, protocol); + if (fd < 0) + throw MakeSocketError("Failed to create socket"); + + ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &reuse, sizeof(reuse)); + if (ret < 0) { + auto error = GetSocketError(); + close_socket(fd); + throw MakeSocketError(error, "setsockopt() failed"); + } + + ret = bind(fd, address.GetAddress(), address.GetSize()); + if (ret < 0) { + auto error = GetSocketError(); + close_socket(fd); + throw MakeSocketError(error, "Failed to bind socket"); + } + + ret = listen(fd, backlog); + if (ret < 0) { + auto error = GetSocketError(); + close_socket(fd); + throw MakeSocketError(error, "Failed to listen on socket"); + } + +#if defined(HAVE_STRUCT_UCRED) && defined(SO_PASSCRED) + setsockopt(fd, SOL_SOCKET, SO_PASSCRED, + (const char *) &reuse, sizeof(reuse)); +#endif + + return fd; +} + +int +socket_keepalive(int fd) +{ + const int reuse = 1; + + return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, + (const char *)&reuse, sizeof(reuse)); +} diff -Nru mpd-0.19.21/src/net/SocketUtil.hxx mpd-0.20.9/src/net/SocketUtil.hxx --- mpd-0.19.21/src/net/SocketUtil.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/SocketUtil.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * This library provides easy helper functions for working with + * sockets. + * + */ + +#ifndef MPD_SOCKET_UTIL_HXX +#define MPD_SOCKET_UTIL_HXX + +class SocketAddress; + +/** + * Creates a socket listening on the specified address. This is a + * shortcut for socket(), bind() and listen(). + * + * Throws #std::system_error on error. + * + * @param domain the socket domain, e.g. PF_INET6 + * @param type the socket type, e.g. SOCK_STREAM + * @param protocol the protocol, usually 0 to let the kernel choose + * @param address the address to listen on + * @param backlog the backlog parameter for the listen() system call + * @param error location to store the error occurring, or NULL to + * ignore errors + * @return the socket file descriptor + */ +int +socket_bind_listen(int domain, int type, int protocol, + SocketAddress address, + int backlog); + +int +socket_keepalive(int fd); + +#endif diff -Nru mpd-0.19.21/src/net/StaticSocketAddress.cxx mpd-0.20.9/src/net/StaticSocketAddress.cxx --- mpd-0.19.21/src/net/StaticSocketAddress.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/StaticSocketAddress.cxx 2017-05-08 14:20:17.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "StaticSocketAddress.hxx" + +#include + +#include + +StaticSocketAddress & +StaticSocketAddress::operator=(SocketAddress other) noexcept +{ + size = std::min(other.GetSize(), GetCapacity()); + memcpy(&address, other.GetAddress(), size); + return *this; +} diff -Nru mpd-0.19.21/src/net/StaticSocketAddress.hxx mpd-0.20.9/src/net/StaticSocketAddress.hxx --- mpd-0.19.21/src/net/StaticSocketAddress.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/StaticSocketAddress.hxx 2017-06-03 20:01:58.000000000 +0000 @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef STATIC_SOCKET_ADDRESS_HXX +#define STATIC_SOCKET_ADDRESS_HXX + +#include "SocketAddress.hxx" +#include "Compiler.h" + +#include + +/** + * An OO wrapper for struct sockaddr_storage. + */ +class StaticSocketAddress { +public: + typedef SocketAddress::size_type size_type; + +private: + size_type size; + struct sockaddr_storage address; + +public: + StaticSocketAddress() = default; + + StaticSocketAddress &operator=(SocketAddress other) noexcept; + + operator SocketAddress() const noexcept { + return SocketAddress(reinterpret_cast(&address), + size); + } + + struct sockaddr *GetAddress() noexcept { + return reinterpret_cast(&address); + } + + const struct sockaddr *GetAddress() const noexcept { + return reinterpret_cast(&address); + } + + constexpr size_type GetCapacity() const noexcept { + return sizeof(address); + } + + size_type GetSize() const noexcept { + return size; + } + + void SetSize(size_type _size) noexcept { + assert(_size > 0); + assert(size_t(_size) <= sizeof(address)); + + size = _size; + } + + int GetFamily() const noexcept { + return address.ss_family; + } + + bool IsDefined() const noexcept { + return GetFamily() != AF_UNSPEC; + } + + void Clear() noexcept { + address.ss_family = AF_UNSPEC; + } + + gcc_pure + bool operator==(SocketAddress other) const noexcept { + return (SocketAddress)*this == other; + } + + bool operator!=(SocketAddress &other) const noexcept { + return !(*this == other); + } +}; + +#endif diff -Nru mpd-0.19.21/src/net/ToString.cxx mpd-0.20.9/src/net/ToString.cxx --- mpd-0.19.21/src/net/ToString.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/ToString.cxx 2017-05-08 13:19:17.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2011-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ToString.hxx" +#include "Features.hxx" +#include "SocketAddress.hxx" + +#include + +#ifdef WIN32 +#include +#else +#include +#ifdef HAVE_TCP +#include +#endif +#endif + +#ifdef HAVE_UN +#include +#endif + +#include +#include + +#ifdef HAVE_UN + +static std::string +LocalAddressToString(const struct sockaddr_un &s_un, size_t size) noexcept +{ + const size_t prefix_size = (size_t) + ((struct sockaddr_un *)nullptr)->sun_path; + assert(size >= prefix_size); + + size_t result_length = size - prefix_size; + + /* remove the trailing null terminator */ + if (result_length > 0 && s_un.sun_path[result_length - 1] == 0) + --result_length; + + if (result_length == 0) + return "local"; + + std::string result(s_un.sun_path, result_length); + + /* replace all null bytes with '@'; this also handles abstract + addresses (Linux specific) */ + std::replace(result.begin(), result.end(), '\0', '@'); + + return result; +} + +#endif + +#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) + +gcc_pure +static bool +IsV4Mapped(SocketAddress address) noexcept +{ + if (address.GetFamily() != AF_INET6) + return false; + + const auto &a6 = *(const struct sockaddr_in6 *)address.GetAddress(); + return IN6_IS_ADDR_V4MAPPED(&a6.sin6_addr); +} + +/** + * Convert "::ffff:127.0.0.1" to "127.0.0.1". + */ +static SocketAddress +UnmapV4(SocketAddress src, struct sockaddr_in &buffer) noexcept +{ + assert(IsV4Mapped(src)); + + const auto &src6 = *(const struct sockaddr_in6 *)src.GetAddress(); + memset(&buffer, 0, sizeof(buffer)); + buffer.sin_family = AF_INET; + memcpy(&buffer.sin_addr, ((const char *)&src6.sin6_addr) + 12, + sizeof(buffer.sin_addr)); + buffer.sin_port = src6.sin6_port; + + return { (const struct sockaddr *)&buffer, sizeof(buffer) }; +} + +#endif + +std::string +ToString(SocketAddress address) noexcept +{ +#ifdef HAVE_UN + if (address.GetFamily() == AF_UNIX) + /* return path of UNIX domain sockets */ + return LocalAddressToString(*(const sockaddr_un *)address.GetAddress(), + address.GetSize()); +#endif + +#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) + struct sockaddr_in in_buffer; + if (IsV4Mapped(address)) + address = UnmapV4(address, in_buffer); +#endif + + char host[NI_MAXHOST], serv[NI_MAXSERV]; + int ret = getnameinfo(address.GetAddress(), address.GetSize(), + host, sizeof(host), serv, sizeof(serv), + NI_NUMERICHOST|NI_NUMERICSERV); + if (ret != 0) + return "unknown"; + +#ifdef HAVE_IPV6 + if (strchr(host, ':') != nullptr) { + std::string result("["); + result.append(host); + result.append("]:"); + result.append(serv); + return result; + } +#endif + + std::string result(host); + result.push_back(':'); + result.append(serv); + return result; +} diff -Nru mpd-0.19.21/src/net/ToString.hxx mpd-0.20.9/src/net/ToString.hxx --- mpd-0.19.21/src/net/ToString.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/net/ToString.hxx 2017-05-08 13:18:59.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NET_TO_STRING_HXX +#define NET_TO_STRING_HXX + +#include "check.h" +#include "Compiler.h" + +#include + +class SocketAddress; + +/** + * Converts the specified socket address into a string in the form + * "IP:PORT". + */ +gcc_pure +std::string +ToString(SocketAddress address) noexcept; + +#endif diff -Nru mpd-0.19.21/src/notify.cxx mpd-0.20.9/src/notify.cxx --- mpd-0.19.21/src/notify.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/notify.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ void notify::Wait() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); while (!pending) cond.wait(mutex); pending = false; @@ -32,7 +32,7 @@ void notify::Signal() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); pending = true; cond.signal(); } @@ -40,6 +40,6 @@ void notify::Clear() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); pending = false; } diff -Nru mpd-0.19.21/src/notify.hxx mpd-0.20.9/src/notify.hxx --- mpd-0.19.21/src/notify.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/notify.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,12 +26,7 @@ struct notify { Mutex mutex; Cond cond; - bool pending; - -#ifdef __GLIBC__ - constexpr -#endif - notify():pending(false) {} + bool pending = false; /** * Wait for a notification. Return immediately if we have already diff -Nru mpd-0.19.21/src/open.h mpd-0.20.9/src/open.h --- mpd-0.19.21/src/open.h 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/open.h 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/Client.hxx mpd-0.20.9/src/output/Client.hxx --- mpd-0.19.21/src/output/Client.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/Client.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OUTPUT_CLIENT_HXX +#define MPD_OUTPUT_CLIENT_HXX + +#include "check.h" + +/** + * An interface between the #AudioOutput and the #Player. + */ +class AudioOutputClient { +public: + /** + * Notify the client that we have consumed a few chunks. This + * is called from within the output thread. The client may + * perform actions to refill the #MusicPipe. + */ + virtual void ChunksConsumed() = 0; + + /** + * The #AudioOutput has modified the "enabled" flag, and the + * client shall make the #AudioOutput apply this new setting. + * This is called from any thread, one which can't send an + * AudioOutput::Command to the output thread; only the client + * can do that safely. + */ + virtual void ApplyEnabled() = 0; +}; + +#endif diff -Nru mpd-0.19.21/src/output/Domain.cxx mpd-0.20.9/src/output/Domain.cxx --- mpd-0.19.21/src/output/Domain.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Domain.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/Domain.hxx mpd-0.20.9/src/output/Domain.hxx --- mpd-0.19.21/src/output/Domain.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Domain.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/Finish.cxx mpd-0.20.9/src/output/Finish.cxx --- mpd-0.19.21/src/output/Finish.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Finish.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,15 +34,15 @@ if (mixer != nullptr) mixer_free(mixer); - delete replay_gain_filter; - delete other_replay_gain_filter; - delete filter; + delete prepared_replay_gain_filter; + delete prepared_other_replay_gain_filter; + delete prepared_filter; } void audio_output_free(AudioOutput *ao) { - assert(!ao->open); + assert(!ao->IsOpen()); assert(!ao->fail_timer.IsDefined()); assert(!ao->thread.IsDefined()); diff -Nru mpd-0.19.21/src/output/Init.cxx mpd-0.20.9/src/output/Init.cxx --- mpd-0.19.21/src/output/Init.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Init.cxx 2017-05-08 13:05:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -35,9 +35,12 @@ #include "filter/plugins/ChainFilterPlugin.hxx" #include "config/ConfigError.hxx" #include "config/ConfigGlobal.hxx" -#include "util/Error.hxx" +#include "config/Block.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" +#include + #include #include @@ -46,28 +49,20 @@ #define AUDIO_OUTPUT_FORMAT "format" #define AUDIO_FILTERS "filters" -AudioOutput::AudioOutput(const AudioOutputPlugin &_plugin) - :plugin(_plugin), - mixer(nullptr), - enabled(true), really_enabled(false), - open(false), - pause(false), - allow_play(true), - in_playback_loop(false), - woken_for_play(false), - filter(nullptr), - replay_gain_filter(nullptr), - other_replay_gain_filter(nullptr), - command(AO_COMMAND_NONE) +AudioOutput::AudioOutput(const AudioOutputPlugin &_plugin, + const ConfigBlock &block) + :plugin(_plugin) { assert(plugin.finish != nullptr); assert(plugin.open != nullptr); assert(plugin.close != nullptr); assert(plugin.play != nullptr); + + Configure(block); } static const AudioOutputPlugin * -audio_output_detect(Error &error) +audio_output_detect() { LogDefault(output_domain, "Attempt to detect audio output device"); @@ -82,8 +77,7 @@ return plugin; } - error.Set(output_domain, "Unable to detect an audio device"); - return nullptr; + throw std::runtime_error("Unable to detect an audio device"); } /** @@ -94,55 +88,63 @@ * mixer_enabled, if the mixer_type setting is not configured. */ gcc_pure -static enum mixer_type -audio_output_mixer_type(const config_param ¶m) +static MixerType +audio_output_mixer_type(const ConfigBlock &block) noexcept { /* read the local "mixer_type" setting */ - const char *p = param.GetBlockValue("mixer_type"); + const char *p = block.GetBlockValue("mixer_type"); if (p != nullptr) return mixer_type_parse(p); /* try the local "mixer_enabled" setting next (deprecated) */ - if (!param.GetBlockValue("mixer_enabled", true)) - return MIXER_TYPE_NONE; + if (!block.GetBlockValue("mixer_enabled", true)) + return MixerType::NONE; /* fall back to the global "mixer_type" setting (also deprecated) */ - return mixer_type_parse(config_get_string(CONF_MIXER_TYPE, + return mixer_type_parse(config_get_string(ConfigOption::MIXER_TYPE, "hardware")); } +static PreparedFilter * +CreateVolumeFilter() +{ + return filter_new(&volume_filter_plugin, ConfigBlock()); +} + static Mixer * audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao, - const config_param ¶m, + const ConfigBlock &block, const MixerPlugin *plugin, - Filter &filter_chain, - MixerListener &listener, - Error &error) + PreparedFilter &filter_chain, + MixerListener &listener) { Mixer *mixer; - switch (audio_output_mixer_type(param)) { - case MIXER_TYPE_NONE: - case MIXER_TYPE_UNKNOWN: + switch (audio_output_mixer_type(block)) { + case MixerType::NONE: + case MixerType::UNKNOWN: return nullptr; - case MIXER_TYPE_HARDWARE: + case MixerType::NULL_: + return mixer_new(event_loop, null_mixer_plugin, ao, listener, + block); + + case MixerType::HARDWARE: if (plugin == nullptr) return nullptr; return mixer_new(event_loop, *plugin, ao, listener, - param, error); + block); - case MIXER_TYPE_SOFTWARE: + case MixerType::SOFTWARE: mixer = mixer_new(event_loop, software_mixer_plugin, ao, listener, - config_param(), - IgnoreError()); + ConfigBlock()); assert(mixer != nullptr); filter_chain_append(filter_chain, "software_mixer", - software_mixer_get_filter(mixer)); + ao.volume_filter.Set(CreateVolumeFilter())); return mixer; } @@ -150,25 +152,18 @@ gcc_unreachable(); } -bool -AudioOutput::Configure(const config_param ¶m, Error &error) +void +AudioOutput::Configure(const ConfigBlock &block) { - if (!param.IsNull()) { - name = param.GetBlockValue(AUDIO_OUTPUT_NAME); - if (name == nullptr) { - error.Set(config_domain, - "Missing \"name\" configuration"); - return false; - } - - const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT); - if (p != nullptr) { - bool success = - audio_format_parse(config_audio_format, - p, true, error); - if (!success) - return false; - } else + if (!block.IsNull()) { + name = block.GetBlockValue(AUDIO_OUTPUT_NAME); + if (name == nullptr) + throw std::runtime_error("Missing \"name\" configuration"); + + const char *p = block.GetBlockValue(AUDIO_OUTPUT_FORMAT); + if (p != nullptr) + config_audio_format = ParseAudioFormat(p, true); + else config_audio_format.Clear(); } else { name = "default detected output"; @@ -176,161 +171,141 @@ config_audio_format.Clear(); } - tags = param.GetBlockValue("tags", true); - always_on = param.GetBlockValue("always_on", false); - enabled = param.GetBlockValue("enabled", true); + tags = block.GetBlockValue("tags", true); + always_on = block.GetBlockValue("always_on", false); + enabled = block.GetBlockValue("enabled", true); /* set up the filter chain */ - filter = filter_chain_new(); - assert(filter != nullptr); + prepared_filter = filter_chain_new(); + assert(prepared_filter != nullptr); /* create the normalization filter (if configured) */ - if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) { - Filter *normalize_filter = - filter_new(&normalize_filter_plugin, config_param(), - IgnoreError()); + if (config_get_bool(ConfigOption::VOLUME_NORMALIZATION, false)) { + auto *normalize_filter = + filter_new(&normalize_filter_plugin, ConfigBlock()); assert(normalize_filter != nullptr); - filter_chain_append(*filter, "normalize", + filter_chain_append(*prepared_filter, "normalize", autoconvert_filter_new(normalize_filter)); } - Error filter_error; - filter_chain_parse(*filter, - param.GetBlockValue(AUDIO_FILTERS, ""), - filter_error); - - // It's not really fatal - Part of the filter chain has been set up already - // and even an empty one will work (if only with unexpected behaviour) - if (filter_error.IsDefined()) - FormatError(filter_error, + try { + filter_chain_parse(*prepared_filter, + block.GetBlockValue(AUDIO_FILTERS, "")); + } catch (const std::runtime_error &e) { + /* It's not really fatal - Part of the filter chain + has been set up already and even an empty one will + work (if only with unexpected behaviour) */ + FormatError(e, "Failed to initialize filter chain for '%s'", name); - - /* done */ - - return true; + } } -static bool -audio_output_setup(EventLoop &event_loop, AudioOutput &ao, +inline void +AudioOutput::Setup(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, MixerListener &mixer_listener, - const config_param ¶m, - Error &error) + const ConfigBlock &block) { /* create the replay_gain filter */ const char *replay_gain_handler = - param.GetBlockValue("replay_gain_handler", "software"); + block.GetBlockValue("replay_gain_handler", "software"); if (strcmp(replay_gain_handler, "none") != 0) { - ao.replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, IgnoreError()); - assert(ao.replay_gain_filter != nullptr); - - ao.replay_gain_serial = 0; - - ao.other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, - IgnoreError()); - assert(ao.other_replay_gain_filter != nullptr); - - ao.other_replay_gain_serial = 0; + prepared_replay_gain_filter = + NewReplayGainFilter(replay_gain_config); + assert(prepared_replay_gain_filter != nullptr); + + prepared_other_replay_gain_filter = + NewReplayGainFilter(replay_gain_config); + assert(prepared_other_replay_gain_filter != nullptr); } else { - ao.replay_gain_filter = nullptr; - ao.other_replay_gain_filter = nullptr; + prepared_replay_gain_filter = nullptr; + prepared_other_replay_gain_filter = nullptr; } /* set up the mixer */ - Error mixer_error; - ao.mixer = audio_output_load_mixer(event_loop, ao, param, - ao.plugin.mixer_plugin, - *ao.filter, - mixer_listener, - mixer_error); - if (ao.mixer == nullptr && mixer_error.IsDefined()) - FormatError(mixer_error, + try { + mixer = audio_output_load_mixer(event_loop, *this, block, + plugin.mixer_plugin, + *prepared_filter, + mixer_listener); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to initialize hardware mixer for '%s'", - ao.name); + name); + } /* use the hardware mixer for replay gain? */ if (strcmp(replay_gain_handler, "mixer") == 0) { - if (ao.mixer != nullptr) - replay_gain_filter_set_mixer(ao.replay_gain_filter, - ao.mixer, 100); + if (mixer != nullptr) + replay_gain_filter_set_mixer(*prepared_replay_gain_filter, + mixer, 100); else FormatError(output_domain, - "No such mixer for output '%s'", ao.name); + "No such mixer for output '%s'", name); } else if (strcmp(replay_gain_handler, "software") != 0 && - ao.replay_gain_filter != nullptr) { - error.Set(config_domain, - "Invalid \"replay_gain_handler\" value"); - return false; + prepared_replay_gain_filter != nullptr) { + throw std::runtime_error("Invalid \"replay_gain_handler\" value"); } /* the "convert" filter must be the last one in the chain */ - ao.convert_filter = filter_new(&convert_filter_plugin, config_param(), - IgnoreError()); - assert(ao.convert_filter != nullptr); - - filter_chain_append(*ao.filter, "convert", ao.convert_filter); + auto *f = filter_new(&convert_filter_plugin, ConfigBlock()); + assert(f != nullptr); - return true; + filter_chain_append(*prepared_filter, "convert", + convert_filter.Set(f)); } AudioOutput * -audio_output_new(EventLoop &event_loop, const config_param ¶m, +audio_output_new(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + const ConfigBlock &block, MixerListener &mixer_listener, - PlayerControl &pc, - Error &error) + AudioOutputClient &client) { const AudioOutputPlugin *plugin; - if (!param.IsNull()) { + if (!block.IsNull()) { const char *p; - p = param.GetBlockValue(AUDIO_OUTPUT_TYPE); - if (p == nullptr) { - error.Set(config_domain, - "Missing \"type\" configuration"); - return nullptr; - } + p = block.GetBlockValue(AUDIO_OUTPUT_TYPE); + if (p == nullptr) + throw std::runtime_error("Missing \"type\" configuration"); plugin = AudioOutputPlugin_get(p); - if (plugin == nullptr) { - error.Format(config_domain, - "No such audio output plugin: %s", p); - return nullptr; - } + if (plugin == nullptr) + throw FormatRuntimeError("No such audio output plugin: %s", p); } else { LogWarning(output_domain, "No 'AudioOutput' defined in config file"); - plugin = audio_output_detect(error); - if (plugin == nullptr) - return nullptr; + plugin = audio_output_detect(); FormatDefault(output_domain, "Successfully detected a %s audio device", plugin->name); } - AudioOutput *ao = ao_plugin_init(plugin, param, error); - if (ao == nullptr) - return nullptr; + AudioOutput *ao = ao_plugin_init(plugin, block); + assert(ao != nullptr); - if (!audio_output_setup(event_loop, *ao, mixer_listener, - param, error)) { + try { + ao->Setup(event_loop, replay_gain_config, + mixer_listener, block); + } catch (...) { ao_plugin_finish(ao); - return nullptr; + throw; } - ao->player_control = &pc; + ao->client = &client; return ao; } diff -Nru mpd-0.19.21/src/output/Internal.cxx mpd-0.20.9/src/output/Internal.cxx --- mpd-0.19.21/src/output/Internal.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/Internal.cxx 2017-05-08 12:52:36.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Internal.hxx" + +bool +AudioOutput::IsChunkConsumed(const MusicChunk &chunk) const noexcept +{ + if (!open) + return true; + + return source.IsChunkConsumed(chunk); +} diff -Nru mpd-0.19.21/src/output/Internal.hxx mpd-0.20.9/src/output/Internal.hxx --- mpd-0.19.21/src/output/Internal.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Internal.hxx 2017-05-08 12:52:10.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,52 +20,53 @@ #ifndef MPD_OUTPUT_INTERNAL_HXX #define MPD_OUTPUT_INTERNAL_HXX +#include "Source.hxx" +#include "SharedPipeConsumer.hxx" #include "AudioFormat.hxx" -#include "pcm/PcmBuffer.hxx" -#include "pcm/PcmDither.hxx" -#include "ReplayGainInfo.hxx" +#include "filter/Observer.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "thread/Thread.hxx" #include "system/PeriodClock.hxx" -class Error; -class Filter; +#include + +class PreparedFilter; class MusicPipe; class EventLoop; class Mixer; class MixerListener; +class AudioOutputClient; struct MusicChunk; -struct config_param; -struct PlayerControl; +struct ConfigBlock; struct AudioOutputPlugin; - -enum audio_output_command { - AO_COMMAND_NONE = 0, - AO_COMMAND_ENABLE, - AO_COMMAND_DISABLE, - AO_COMMAND_OPEN, - - /** - * This command is invoked when the input audio format - * changes. - */ - AO_COMMAND_REOPEN, - - AO_COMMAND_CLOSE, - AO_COMMAND_PAUSE, - - /** - * Drains the internal (hardware) buffers of the device. This - * operation may take a while to complete. - */ - AO_COMMAND_DRAIN, - - AO_COMMAND_CANCEL, - AO_COMMAND_KILL -}; +struct ReplayGainConfig; struct AudioOutput { + enum class Command { + NONE, + ENABLE, + DISABLE, + + /** + * Open the output, or reopen it if it is already + * open, adjusting for input #AudioFormat changes. + */ + OPEN, + + CLOSE, + PAUSE, + + /** + * Drains the internal (hardware) buffers of the device. This + * operation may take a while to complete. + */ + DRAIN, + + CANCEL, + KILL + }; + /** * The device's configured display name. */ @@ -81,7 +82,7 @@ * May be nullptr if none is available, or if software volume is * configured. */ - Mixer *mixer; + Mixer *mixer = nullptr; /** * Will this output receive tags from the decoder? The @@ -99,13 +100,13 @@ /** * Has the user enabled this device? */ - bool enabled; + bool enabled = true; /** * Is this device actually enabled, i.e. the "enable" method * has succeeded? */ - bool really_enabled; + bool really_enabled = false; /** * Is the device (already) open and functional? @@ -115,13 +116,13 @@ * output thread and read accesses outside of it may only be * performed while the lock is held. */ - bool open; + bool open = false; /** * Is the device paused? i.e. the output thread is in the * ao_pause() loop. */ - bool pause; + bool pause = false; /** * When this flag is set, the output thread will not do any @@ -130,7 +131,7 @@ * This is used to synchronize the "clear" operation on the * shared music pipe during the CANCEL command. */ - bool allow_play; + bool allow_play = true; /** * True while the OutputThread is inside ao_play(). This @@ -138,14 +139,14 @@ * OutputThread when new chunks are added to the MusicPipe, * because the OutputThread is already watching that. */ - bool in_playback_loop; + bool in_playback_loop = false; /** * Has the OutputThread been woken up to play more chunks? * This is set by audio_output_play() and reset by ao_play() * to reduce the number of duplicate wakeups. */ - bool woken_for_play; + bool woken_for_play = false; /** * If not nullptr, the device has failed, and this timer is used @@ -160,10 +161,12 @@ AudioFormat config_audio_format; /** - * The audio_format in which audio data is received from the - * player thread (which in turn receives it from the decoder). + * The #AudioFormat which is emitted by the #Filter, with + * #config_audio_format already applied. This is used to + * decide whether this object needs to be closed and reopened + * upon #AudioFormat changes. */ - AudioFormat in_audio_format; + AudioFormat filter_audio_format; /** * The audio_format which is really sent to the device. This @@ -174,45 +177,29 @@ AudioFormat out_audio_format; /** - * The buffer used to allocate the cross-fading result. - */ - PcmBuffer cross_fade_buffer; - - /** - * The dithering state for cross-fading two streams. - */ - PcmDither cross_fade_dither; - - /** * The filter object of this audio output. This is an * instance of chain_filter_plugin. */ - Filter *filter; + PreparedFilter *prepared_filter = nullptr; /** - * The replay_gain_filter_plugin instance of this audio - * output. + * The #VolumeFilter instance of this audio output. It is + * used by the #SoftwareMixer. */ - Filter *replay_gain_filter; + FilterObserver volume_filter; /** - * The serial number of the last replay gain info. 0 means no - * replay gain info was available. + * The replay_gain_filter_plugin instance of this audio + * output. */ - unsigned replay_gain_serial; + PreparedFilter *prepared_replay_gain_filter = nullptr; /** * The replay_gain_filter_plugin instance of this audio * output, to be applied to the second chunk during * cross-fading. */ - Filter *other_replay_gain_filter; - - /** - * The serial number of the last replay gain info by the - * "other" chunk during cross-fading. - */ - unsigned other_replay_gain_serial; + PreparedFilter *prepared_other_replay_gain_filter = nullptr; /** * The convert_filter_plugin instance of this audio output. @@ -220,7 +207,7 @@ * for converting the input data into the appropriate format * for this audio output. */ - Filter *convert_filter; + FilterObserver convert_filter; /** * The thread handle, or nullptr if the output thread isn't @@ -231,18 +218,27 @@ /** * The next command to be performed by the output thread. */ - enum audio_output_command command; + Command command = Command::NONE; /** - * The music pipe which provides music chunks to be played. + * Additional data for #command. Protected by #mutex. */ - const MusicPipe *pipe; + struct Request { + /** + * The #AudioFormat requested by #Command::OPEN. + */ + AudioFormat audio_format; + + /** + * The #MusicPipe passed to #Command::OPEN. + */ + const MusicPipe *pipe; + } request; /** - * This mutex protects #open, #fail_timer, #current_chunk and - * #current_chunk_finished. + * This mutex protects #open, #fail_timer, #pipe. */ - Mutex mutex; + mutable Mutex mutex; /** * This condition object wakes up the output thread after @@ -254,37 +250,74 @@ * The PlayerControl object which "owns" this output. This * object is needed to signal command completion. */ - PlayerControl *player_control; + AudioOutputClient *client; + + /** + * Source of audio data. + */ + AudioOutputSource source; /** - * The #MusicChunk which is currently being played. All - * chunks before this one may be returned to the - * #music_buffer, because they are not going to be used by - * this output anymore. + * The error that occurred in the output thread. It is + * cleared whenever the output is opened successfully. + * + * Protected by #mutex. */ - const MusicChunk *current_chunk; + std::exception_ptr last_error; /** - * Has the output finished playing #current_chunk? + * Throws #std::runtime_error on error. */ - bool current_chunk_finished; + AudioOutput(const AudioOutputPlugin &_plugin, + const ConfigBlock &block); - AudioOutput(const AudioOutputPlugin &_plugin); ~AudioOutput(); - bool Configure(const config_param ¶m, Error &error); +private: + void Configure(const ConfigBlock &block); + +public: + void Setup(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + MixerListener &mixer_listener, + const ConfigBlock &block); void StartThread(); void StopThread(); - void Finish(); + void BeginDestroy(); + void FinishDestroy(); + const char *GetName() const { + return name; + } + + /** + * Caller must lock the mutex. + */ + bool IsEnabled() const { + return enabled; + } + + /** + * Caller must lock the mutex. + */ bool IsOpen() const { return open; } + /** + * Caller must lock the mutex. + */ bool IsCommandFinished() const { - return command == AO_COMMAND_NONE; + return command == Command::NONE; + } + + /** + * Caller must lock the mutex. + */ + const std::exception_ptr &GetLastError() const { + return last_error; } /** @@ -299,7 +332,7 @@ * * Caller must lock the mutex. */ - void CommandAsync(audio_output_command cmd); + void CommandAsync(Command cmd); /** * Sends a command to the #AudioOutput object and waits for @@ -307,23 +340,44 @@ * * Caller must lock the mutex. */ - void CommandWait(audio_output_command cmd); + void CommandWait(Command cmd); /** * Lock the #AudioOutput object and execute the command * synchronously. */ - void LockCommandWait(audio_output_command cmd); + void LockCommandWait(Command cmd); /** - * Enables the device. + * Enables the device, but don't wait for completion. + * + * Caller must lock the mutex. */ - void LockEnableWait(); + void EnableAsync(); /** - * Disables the device. + * Disables the device, but don't wait for completion. + * + * Caller must lock the mutex. */ - void LockDisableWait(); + void DisableAsync(); + + /** + * Attempt to enable or disable the device as specified by the + * #enabled attribute; attempt to sync it with #really_enabled + * (wrapper for EnableAsync() or DisableAsync()). + * + * Caller must lock the mutex. + */ + void EnableDisableAsync() { + if (enabled == really_enabled) + return; + + if (enabled) + EnableAsync(); + else + DisableAsync(); + } void LockPauseAsync(); @@ -340,7 +394,9 @@ */ void LockRelease(); - void SetReplayGainMode(ReplayGainMode mode); + void SetReplayGainMode(ReplayGainMode _mode) { + source.SetReplayGainMode(_mode); + } /** * Caller must lock the mutex. @@ -351,10 +407,12 @@ * Opens or closes the device, depending on the "enabled" * flag. * + * @param force true to ignore the #fail_timer * @return true if the device is open */ bool LockUpdate(const AudioFormat audio_format, - const MusicPipe &mp); + const MusicPipe &mp, + bool force); void LockPlay(); @@ -372,25 +430,63 @@ */ void LockAllowPlay(); + /** + * Did we already consumed this chunk? + * + * Caller must lock the mutex. + */ + gcc_pure + bool IsChunkConsumed(const MusicChunk &chunk) const noexcept; + + gcc_pure + bool LockIsChunkConsumed(const MusicChunk &chunk) noexcept { + const std::lock_guard protect(mutex); + return IsChunkConsumed(chunk); + } + + void ClearTailChunk(const MusicChunk &chunk) { + source.ClearTailChunk(chunk); + } + private: void CommandFinished(); - bool Enable(); + /** + * Throws #std::runtime_error on error. + */ + void Enable(); + void Disable(); + /** + * Throws #std::runtime_error on error. + */ void Open(); + + /** + * Invoke OutputPlugin::open() and configure the + * #ConvertFilter. + * + * Throws #std::runtime_error on error. + * + * Caller must not lock the mutex. + */ + void OpenOutputAndConvert(AudioFormat audio_format); + void Close(bool drain); - void Reopen(); - AudioFormat OpenFilter(AudioFormat &format, Error &error_r); + /** + * Close the output plugin. + * + * Mutex must not be locked. + */ + void CloseOutput(bool drain); /** * Mutex must not be locked. */ void CloseFilter(); - void ReopenFilter(); - /** * Wait until the output's delay reaches zero. * @@ -399,10 +495,9 @@ */ bool WaitForDelay(); - gcc_pure - const MusicChunk *GetNextChunk() const; + bool FillSourceOrClose(); - bool PlayChunk(const MusicChunk *chunk); + bool PlayChunk(); /** * Plays all remaining chunks, until the tail of the pipe has @@ -429,11 +524,15 @@ */ extern struct notify audio_output_client_notify; +/** + * Throws #std::runtime_error on error. + */ AudioOutput * -audio_output_new(EventLoop &event_loop, const config_param ¶m, +audio_output_new(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + const ConfigBlock &block, MixerListener &mixer_listener, - PlayerControl &pc, - Error &error); + AudioOutputClient &client); void audio_output_free(AudioOutput *ao); diff -Nru mpd-0.19.21/src/output/MultipleOutputs.cxx mpd-0.20.9/src/output/MultipleOutputs.cxx --- mpd-0.19.21/src/output/MultipleOutputs.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/MultipleOutputs.cxx 2017-05-08 12:59:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,86 +19,85 @@ #include "config.h" #include "MultipleOutputs.hxx" -#include "PlayerControl.hxx" #include "Internal.hxx" #include "Domain.hxx" #include "MusicBuffer.hxx" #include "MusicPipe.hxx" #include "MusicChunk.hxx" -#include "system/FatalError.hxx" -#include "util/Error.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" #include "notify.hxx" +#include "util/RuntimeError.hxx" + +#include #include #include MultipleOutputs::MultipleOutputs(MixerListener &_mixer_listener) - :mixer_listener(_mixer_listener), - input_audio_format(AudioFormat::Undefined()), - buffer(nullptr), pipe(nullptr), - elapsed_time(SignedSongTime::Negative()) + :mixer_listener(_mixer_listener) { } MultipleOutputs::~MultipleOutputs() { - for (auto i : outputs) { - i->LockDisableWait(); - i->Finish(); - } + /* parallel destruction */ + for (auto i : outputs) + i->BeginDestroy(); + for (auto i : outputs) + i->FinishDestroy(); } static AudioOutput * -LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener, - PlayerControl &pc, const config_param ¶m) -{ - Error error; - AudioOutput *output = audio_output_new(event_loop, param, - mixer_listener, - pc, error); - if (output == nullptr) { - if (param.line > 0) - FormatFatalError("line %i: %s", - param.line, - error.GetMessage()); - else - FatalError(error); - } - - return output; +LoadOutput(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + MixerListener &mixer_listener, + AudioOutputClient &client, const ConfigBlock &block) +try { + return audio_output_new(event_loop, replay_gain_config, block, + mixer_listener, + client); +} catch (const std::runtime_error &e) { + if (block.line > 0) + std::throw_with_nested(FormatRuntimeError("Failed to configure output in line %i", + block.line)); + else + throw; } void -MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc) +MultipleOutputs::Configure(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + AudioOutputClient &client) { - for (const config_param *param = config_get_param(CONF_AUDIO_OUTPUT); + for (const auto *param = config_get_block(ConfigBlockOption::AUDIO_OUTPUT); param != nullptr; param = param->next) { - auto output = LoadOutput(event_loop, mixer_listener, - pc, *param); - if (FindByName(output->name) != nullptr) - FormatFatalError("output devices with identical " - "names: %s", output->name); + auto output = LoadOutput(event_loop, replay_gain_config, + mixer_listener, + client, *param); + if (FindByName(output->GetName()) != nullptr) + throw FormatRuntimeError("output devices with identical " + "names: %s", output->GetName()); outputs.push_back(output); } if (outputs.empty()) { /* auto-detect device */ - const config_param empty; - auto output = LoadOutput(event_loop, mixer_listener, - pc, empty); + const ConfigBlock empty; + auto output = LoadOutput(event_loop, replay_gain_config, + mixer_listener, + client, empty); outputs.push_back(output); } } AudioOutput * -MultipleOutputs::FindByName(const char *name) const +MultipleOutputs::FindByName(const char *name) const noexcept { for (auto i : outputs) - if (strcmp(i->name, name) == 0) + if (strcmp(i->GetName(), name) == 0) return i; return nullptr; @@ -107,27 +106,24 @@ void MultipleOutputs::EnableDisable() { - for (auto ao : outputs) { - bool enabled; + /* parallel execution */ - ao->mutex.lock(); - enabled = ao->really_enabled; - ao->mutex.unlock(); + for (auto ao : outputs) { + const std::lock_guard lock(ao->mutex); + ao->EnableDisableAsync(); + } - if (ao->enabled != enabled) { - if (ao->enabled) - ao->LockEnableWait(); - else - ao->LockDisableWait(); - } + for (auto ao : outputs) { + const std::lock_guard lock(ao->mutex); + ao->WaitForCommand(); } } bool -MultipleOutputs::AllFinished() const +MultipleOutputs::AllFinished() const noexcept { for (auto ao : outputs) { - const ScopeLock protect(ao->mutex); + const std::lock_guard protect(ao->mutex); if (ao->IsOpen() && !ao->IsCommandFinished()) return false; } @@ -136,7 +132,7 @@ } void -MultipleOutputs::WaitAll() +MultipleOutputs::WaitAll() noexcept { while (!AllFinished()) audio_output_client_notify.Wait(); @@ -149,23 +145,8 @@ ao->LockAllowPlay(); } -static void -audio_output_reset_reopen(AudioOutput *ao) -{ - const ScopeLock protect(ao->mutex); - - ao->fail_timer.Reset(); -} - -void -MultipleOutputs::ResetReopen() -{ - for (auto ao : outputs) - audio_output_reset_reopen(ao); -} - bool -MultipleOutputs::Update() +MultipleOutputs::Update(bool force) { bool ret = false; @@ -173,7 +154,7 @@ return false; for (auto ao : outputs) - ret = ao->LockUpdate(input_audio_format, *pipe) + ret = ao->LockUpdate(input_audio_format, *pipe, force) || ret; return ret; @@ -186,32 +167,27 @@ ao->SetReplayGainMode(mode); } -bool -MultipleOutputs::Play(MusicChunk *chunk, Error &error) +void +MultipleOutputs::Play(MusicChunk *chunk) { assert(buffer != nullptr); assert(pipe != nullptr); assert(chunk != nullptr); assert(chunk->CheckFormat(input_audio_format)); - if (!Update()) { + if (!Update(false)) /* TODO: obtain real error */ - error.Set(output_domain, "Failed to open audio output"); - return false; - } + throw std::runtime_error("Failed to open audio output"); pipe->Push(chunk); for (auto ao : outputs) ao->LockPlay(); - - return true; } -bool +void MultipleOutputs::Open(const AudioFormat audio_format, - MusicBuffer &_buffer, - Error &error) + MusicBuffer &_buffer) { bool ret = false, enabled = false; @@ -233,71 +209,51 @@ input_audio_format = audio_format; - ResetReopen(); EnableDisable(); - Update(); + Update(true); + + std::exception_ptr first_error; for (auto ao : outputs) { - if (ao->enabled) + const std::lock_guard lock(ao->mutex); + + if (ao->IsEnabled()) enabled = true; - if (ao->open) + if (ao->IsOpen()) ret = true; + else if (!first_error) + first_error = ao->GetLastError(); } - if (!enabled) - error.Set(output_domain, "All audio outputs are disabled"); - else if (!ret) - /* TODO: obtain real error */ - error.Set(output_domain, "Failed to open audio output"); - - if (!ret) + if (!enabled) { + /* close all devices if there was an error */ + Close(); + throw std::runtime_error("All audio outputs are disabled"); + } else if (!ret) { /* close all devices if there was an error */ Close(); - return ret; -} - -/** - * Has the specified audio output already consumed this chunk? - */ -gcc_pure -static bool -chunk_is_consumed_in(const AudioOutput *ao, - gcc_unused const MusicPipe *pipe, - const MusicChunk *chunk) -{ - if (!ao->open) - return true; - - if (ao->current_chunk == nullptr) - return false; - - assert(chunk == ao->current_chunk || - pipe->Contains(ao->current_chunk)); - - if (chunk != ao->current_chunk) { - assert(chunk->next != nullptr); - return true; + if (first_error) + /* we have details, so throw that */ + std::rethrow_exception(first_error); + else + throw std::runtime_error("Failed to open audio output"); } - - return ao->current_chunk_finished && chunk->next == nullptr; } bool -MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const +MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const noexcept { - for (auto ao : outputs) { - const ScopeLock protect(ao->mutex); - if (!chunk_is_consumed_in(ao, pipe, chunk)) + for (auto ao : outputs) + if (!ao->LockIsChunkConsumed(*chunk)) return false; - } return true; } inline void -MultipleOutputs::ClearTailChunk(gcc_unused const MusicChunk *chunk, +MultipleOutputs::ClearTailChunk(const MusicChunk *chunk, bool *locked) { assert(chunk->next == nullptr); @@ -309,16 +265,14 @@ /* this mutex will be unlocked by the caller when it's ready */ ao->mutex.lock(); - locked[i] = ao->open; + locked[i] = ao->IsOpen(); if (!locked[i]) { ao->mutex.unlock(); continue; } - assert(ao->current_chunk == chunk); - assert(ao->current_chunk_finished); - ao->current_chunk = nullptr; + ao->ClearTailChunk(*chunk); } } @@ -370,26 +324,10 @@ return 0; } -bool -MultipleOutputs::Wait(PlayerControl &pc, unsigned threshold) -{ - pc.Lock(); - - if (Check() < threshold) { - pc.Unlock(); - return true; - } - - pc.Wait(); - pc.Unlock(); - - return Check() < threshold; -} - void MultipleOutputs::Pause() { - Update(); + Update(false); for (auto ao : outputs) ao->LockPauseAsync(); diff -Nru mpd-0.19.21/src/output/MultipleOutputs.hxx mpd-0.20.9/src/output/MultipleOutputs.hxx --- mpd-0.19.21/src/output/MultipleOutputs.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/MultipleOutputs.hxx 2017-06-03 19:34:15.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ #define OUTPUT_ALL_H #include "AudioFormat.hxx" -#include "ReplayGainInfo.hxx" +#include "ReplayGainMode.hxx" #include "Chrono.hxx" #include "Compiler.h" @@ -35,39 +35,38 @@ #include -struct AudioFormat; class MusicBuffer; class MusicPipe; class EventLoop; class MixerListener; +class AudioOutputClient; struct MusicChunk; -struct PlayerControl; struct AudioOutput; -class Error; +struct ReplayGainConfig; class MultipleOutputs { MixerListener &mixer_listener; std::vector outputs; - AudioFormat input_audio_format; + AudioFormat input_audio_format = AudioFormat::Undefined(); /** * The #MusicBuffer object where consumed chunks are returned. */ - MusicBuffer *buffer; + MusicBuffer *buffer = nullptr; /** * The #MusicPipe object which feeds all audio outputs. It is * filled by audio_output_all_play(). */ - MusicPipe *pipe; + MusicPipe *pipe = nullptr; /** * The "elapsed_time" stamp of the most recently finished * chunk. */ - SignedSongTime elapsed_time; + SignedSongTime elapsed_time = SignedSongTime::Negative(); public: /** @@ -77,14 +76,16 @@ MultipleOutputs(MixerListener &_mixer_listener); ~MultipleOutputs(); - void Configure(EventLoop &event_loop, PlayerControl &pc); + void Configure(EventLoop &event_loop, + const ReplayGainConfig &replay_gain_config, + AudioOutputClient &client); /** * Returns the total number of audio output devices, including * those which are disabled right now. */ gcc_pure - unsigned Size() const { + unsigned Size() const noexcept { return outputs.size(); } @@ -108,7 +109,7 @@ * Returns nullptr if the name does not exist. */ gcc_pure - AudioOutput *FindByName(const char *name) const; + AudioOutput *FindByName(const char *name) const noexcept; /** * Checks the "enabled" flag of all audio outputs, and if one has @@ -119,13 +120,13 @@ /** * Opens all audio outputs which are not disabled. * + * Throws #std::runtime_error on error. + * * @param audio_format the preferred audio format - * @param buffer the #music_buffer where consumed #MusicChunk objects + * @param _buffer the #music_buffer where consumed #MusicChunk objects * should be returned - * @return true on success, false on failure */ - bool Open(const AudioFormat audio_format, MusicBuffer &_buffer, - Error &error); + void Open(const AudioFormat audio_format, MusicBuffer &_buffer); /** * Closes all audio outputs. @@ -144,11 +145,11 @@ * Enqueue a #MusicChunk object for playing, i.e. pushes it to a * #MusicPipe. * + * Throws #std::runtime_error on error (all closed then). + * * @param chunk the #MusicChunk object to be played - * @return true on success, false if no audio output was able to play - * (all closed then) */ - bool Play(MusicChunk *chunk, Error &error); + void Play(MusicChunk *chunk); /** * Checks if the output devices have drained their music pipe, and @@ -159,16 +160,6 @@ unsigned Check(); /** - * Checks if the size of the #MusicPipe is below the #threshold. If - * not, it attempts to synchronize with all output threads, and waits - * until another #MusicChunk is finished. - * - * @param threshold the maximum number of chunks in the pipe - * @return true if there are less than #threshold chunks in the pipe - */ - bool Wait(PlayerControl &pc, unsigned threshold); - - /** * Puts all audio outputs into pause mode. Most implementations will * simply close it then. */ @@ -195,7 +186,7 @@ * finished yet. */ gcc_pure - SignedSongTime GetElapsedTime() const { + SignedSongTime GetElapsedTime() const noexcept { return elapsed_time; } @@ -204,7 +195,7 @@ * 0..100). Returns -1 if no mixer can be queried. */ gcc_pure - int GetVolume() const; + int GetVolume() const noexcept; /** * Sets the volume on all available mixers. @@ -212,7 +203,7 @@ * @param volume the volume (range 0..100) * @return true on success, false on failure */ - bool SetVolume(unsigned volume); + bool SetVolume(unsigned volume) noexcept; /** * Similar to GetVolume(), but gets the volume only for @@ -220,7 +211,7 @@ * function fails if no software mixer is configured. */ gcc_pure - int GetSoftwareVolume() const; + int GetSoftwareVolume() const noexcept; /** * Similar to SetVolume(), but sets the volume only for @@ -228,7 +219,7 @@ * function cannot fail, because the underlying software * mixers cannot fail either. */ - void SetSoftwareVolume(unsigned volume); + void SetSoftwareVolume(unsigned volume) noexcept; private: /** @@ -236,9 +227,9 @@ * command. */ gcc_pure - bool AllFinished() const; + bool AllFinished() const noexcept; - void WaitAll(); + void WaitAll() noexcept; /** * Signals all audio outputs which are open. @@ -246,24 +237,17 @@ void AllowPlay(); /** - * Resets the "reopen" flag on all audio devices. MPD should - * immediately retry to open the device instead of waiting for - * the timeout when the user wants to start playback. - */ - void ResetReopen(); - - /** * Opens all output devices which are enabled, but closed. * * @return true if there is at least open output device which * is open */ - bool Update(); + bool Update(bool force); /** * Has this chunk been consumed by all audio outputs? */ - bool IsChunkConsumed(const MusicChunk *chunk) const; + bool IsChunkConsumed(const MusicChunk *chunk) const noexcept; /** * There's only one chunk left in the pipe (#pipe), and all diff -Nru mpd-0.19.21/src/output/OutputAPI.hxx mpd-0.20.9/src/output/OutputAPI.hxx --- mpd-0.19.21/src/output/OutputAPI.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputAPI.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ #include "Internal.hxx" #include "AudioFormat.hxx" #include "tag/Tag.hxx" -#include "config/ConfigData.hxx" +#include "config/Block.hxx" // IWYU pragma: end_exports diff -Nru mpd-0.19.21/src/output/OutputCommand.cxx mpd-0.20.9/src/output/OutputCommand.cxx --- mpd-0.19.21/src/output/OutputCommand.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputCommand.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,8 @@ #include "OutputCommand.hxx" #include "MultipleOutputs.hxx" #include "Internal.hxx" -#include "PlayerControl.hxx" +#include "Client.hxx" +#include "player/Control.hxx" #include "mixer/MixerControl.hxx" #include "mixer/Volume.hxx" #include "Idle.hxx" @@ -53,7 +54,7 @@ idle_add(IDLE_MIXER); } - ao.player_control->UpdateAudio(); + ao.client->ApplyEnabled(); ++audio_output_state_version; @@ -80,7 +81,7 @@ idle_add(IDLE_MIXER); } - ao.player_control->UpdateAudio(); + ao.client->ApplyEnabled(); ++audio_output_state_version; @@ -106,7 +107,7 @@ } } - ao.player_control->UpdateAudio(); + ao.client->ApplyEnabled(); ++audio_output_state_version; diff -Nru mpd-0.19.21/src/output/OutputCommand.hxx mpd-0.20.9/src/output/OutputCommand.hxx --- mpd-0.19.21/src/output/OutputCommand.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputCommand.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/OutputControl.cxx mpd-0.20.9/src/output/OutputControl.cxx --- mpd-0.19.21/src/output/OutputControl.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputControl.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,14 +24,15 @@ #include "mixer/MixerControl.hxx" #include "notify.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx" -#include "util/Error.hxx" #include "Log.hxx" +#include + #include -/** after a failure, wait this number of seconds before +/** after a failure, wait this duration before automatically reopening the device */ -static constexpr unsigned REOPEN_AFTER = 10; +static constexpr PeriodClock::Duration REOPEN_AFTER = std::chrono::seconds(10); struct notify audio_output_client_notify; @@ -46,7 +47,7 @@ } void -AudioOutput::CommandAsync(audio_output_command cmd) +AudioOutput::CommandAsync(Command cmd) { assert(IsCommandFinished()); @@ -55,30 +56,21 @@ } void -AudioOutput::CommandWait(audio_output_command cmd) +AudioOutput::CommandWait(Command cmd) { CommandAsync(cmd); WaitForCommand(); } void -AudioOutput::LockCommandWait(audio_output_command cmd) +AudioOutput::LockCommandWait(Command cmd) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); CommandWait(cmd); } void -AudioOutput::SetReplayGainMode(ReplayGainMode mode) -{ - if (replay_gain_filter != nullptr) - replay_gain_filter_set_mode(replay_gain_filter, mode); - if (other_replay_gain_filter != nullptr) - replay_gain_filter_set_mode(other_replay_gain_filter, mode); -} - -void -AudioOutput::LockEnableWait() +AudioOutput::EnableAsync() { if (!thread.IsDefined()) { if (plugin.enable == nullptr) { @@ -92,11 +84,11 @@ StartThread(); } - LockCommandWait(AO_COMMAND_ENABLE); + CommandAsync(Command::ENABLE); } void -AudioOutput::LockDisableWait() +AudioOutput::DisableAsync() { if (!thread.IsDefined()) { if (plugin.disable == nullptr) @@ -109,7 +101,7 @@ return; } - LockCommandWait(AO_COMMAND_DISABLE); + CommandAsync(Command::DISABLE); } inline bool @@ -120,42 +112,30 @@ fail_timer.Reset(); - if (open && audio_format == in_audio_format) { - assert(pipe == &mp || (always_on && pause)); - - if (pause) { - current_chunk = nullptr; - pipe = ∓ - - /* unpause with the CANCEL command; this is a - hack, but suits well for forcing the thread - to leave the ao_pause() thread, and we need - to flush the device buffer anyway */ - - /* we're not using audio_output_cancel() here, - because that function is asynchronous */ - CommandWait(AO_COMMAND_CANCEL); - } + if (open && audio_format == request.audio_format) { + assert(request.pipe == &mp || (always_on && pause)); - return true; + if (!pause) + /* already open, already the right parameters + - nothing needs to be done */ + return true; } - in_audio_format = audio_format; - current_chunk = nullptr; - - pipe = ∓ + request.audio_format = audio_format; + request.pipe = ∓ if (!thread.IsDefined()) StartThread(); - CommandWait(open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN); + CommandWait(Command::OPEN); const bool open2 = open; if (open2 && mixer != nullptr) { - Error error; - if (!mixer_open(mixer, error)) - FormatWarning(output_domain, - "Failed to open mixer for '%s'", name); + try { + mixer_open(mixer); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to open mixer for '%s'", name); + } } return open2; @@ -172,19 +152,20 @@ assert(!open || !fail_timer.IsDefined()); if (open) - CommandWait(AO_COMMAND_CLOSE); + CommandWait(Command::CLOSE); else fail_timer.Reset(); } bool AudioOutput::LockUpdate(const AudioFormat audio_format, - const MusicPipe &mp) + const MusicPipe &mp, + bool force) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (enabled && really_enabled) { - if (!fail_timer.IsDefined() || + if (force || !fail_timer.IsDefined() || fail_timer.Check(REOPEN_AFTER * 1000)) { return Open(audio_format, mp); } @@ -197,7 +178,7 @@ void AudioOutput::LockPlay() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(allow_play); @@ -216,38 +197,38 @@ mixer_auto_close()) */ mixer_auto_close(mixer); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(allow_play); if (IsOpen()) - CommandAsync(AO_COMMAND_PAUSE); + CommandAsync(Command::PAUSE); } void AudioOutput::LockDrainAsync() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(allow_play); if (IsOpen()) - CommandAsync(AO_COMMAND_DRAIN); + CommandAsync(Command::DRAIN); } void AudioOutput::LockCancelAsync() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (IsOpen()) { allow_play = false; - CommandAsync(AO_COMMAND_CANCEL); + CommandAsync(Command::CANCEL); } } void AudioOutput::LockAllowPlay() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); allow_play = true; if (IsOpen()) @@ -268,7 +249,7 @@ { assert(!open || !fail_timer.IsDefined()); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); CloseWait(); } @@ -278,19 +259,27 @@ assert(thread.IsDefined()); assert(allow_play); - LockCommandWait(AO_COMMAND_KILL); + LockCommandWait(Command::KILL); thread.Join(); } void -AudioOutput::Finish() +AudioOutput::BeginDestroy() { - LockCloseWait(); + if (mixer != nullptr) + mixer_auto_close(mixer); - assert(!fail_timer.IsDefined()); + if (thread.IsDefined()) { + const std::lock_guard protect(mutex); + CommandAsync(Command::KILL); + } +} +void +AudioOutput::FinishDestroy() +{ if (thread.IsDefined()) - StopThread(); + thread.Join(); audio_output_free(this); } diff -Nru mpd-0.19.21/src/output/OutputPlugin.cxx mpd-0.20.9/src/output/OutputPlugin.cxx --- mpd-0.19.21/src/output/OutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputPlugin.cxx 2017-05-08 12:53:40.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,13 +23,12 @@ AudioOutput * ao_plugin_init(const AudioOutputPlugin *plugin, - const config_param ¶m, - Error &error) + const ConfigBlock &block) { assert(plugin != nullptr); assert(plugin->init != nullptr); - return plugin->init(param, error); + return plugin->init(block); } void @@ -38,12 +37,11 @@ ao->plugin.finish(ao); } -bool -ao_plugin_enable(AudioOutput *ao, Error &error_r) +void +ao_plugin_enable(AudioOutput *ao) { - return ao->plugin.enable != nullptr - ? ao->plugin.enable(ao, error_r) - : true; + if (ao->plugin.enable != nullptr) + ao->plugin.enable(ao); } void @@ -53,11 +51,10 @@ ao->plugin.disable(ao); } -bool -ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +void +ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format) { - return ao->plugin.open(ao, audio_format, error); + ao->plugin.open(ao, audio_format); } void @@ -66,26 +63,25 @@ ao->plugin.close(ao); } -unsigned -ao_plugin_delay(AudioOutput *ao) +std::chrono::steady_clock::duration +ao_plugin_delay(AudioOutput *ao) noexcept { return ao->plugin.delay != nullptr ? ao->plugin.delay(ao) - : 0; + : std::chrono::steady_clock::duration::zero(); } void -ao_plugin_send_tag(AudioOutput *ao, const Tag *tag) +ao_plugin_send_tag(AudioOutput *ao, const Tag &tag) { if (ao->plugin.send_tag != nullptr) ao->plugin.send_tag(ao, tag); } size_t -ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size) { - return ao->plugin.play(ao, chunk, size, error); + return ao->plugin.play(ao, chunk, size); } void diff -Nru mpd-0.19.21/src/output/OutputPlugin.hxx mpd-0.20.9/src/output/OutputPlugin.hxx --- mpd-0.19.21/src/output/OutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputPlugin.hxx 2017-05-08 12:53:19.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,14 +22,15 @@ #include "Compiler.h" +#include + #include -struct config_param; +struct ConfigBlock; struct AudioFormat; struct Tag; struct AudioOutput; struct MixerPlugin; -class Error; /** * A plugin which controls an audio output device. @@ -44,19 +45,18 @@ * Test if this plugin can provide a default output, in case * none has been configured. This method is optional. */ - bool (*test_default_device)(void); + bool (*test_default_device)(); /** * Configure and initialize the device, but do not open it * yet. * + * Throws #std::runtime_error on error. + * * @param param the configuration section, or nullptr if there is * no configuration - * @return nullptr on error, or an opaque pointer to the plugin's - * data */ - AudioOutput *(*init)(const config_param ¶m, - Error &error); + AudioOutput *(*init)(const ConfigBlock &block); /** * Free resources allocated by this device. @@ -65,13 +65,11 @@ /** * Enable the device. This may allocate resources, preparing - * for the device to be opened. Enabling a device cannot - * fail: if an error occurs during that, it should be reported - * by the open() method. + * for the device to be opened. * - * @return true on success, false on error + * Throws #std::runtime_error on error. */ - bool (*enable)(AudioOutput *data, Error &error); + void (*enable)(AudioOutput *data); /** * Disables the device. It is closed before this method is @@ -82,11 +80,12 @@ /** * Really open the device. * + * Throws #std::runtime_error on error. + * * @param audio_format the audio format in which data is going * to be delivered; may be modified by the plugin */ - bool (*open)(AudioOutput *data, AudioFormat &audio_format, - Error &error); + void (*open)(AudioOutput *data, AudioFormat &audio_format); /** * Close the device. @@ -94,29 +93,31 @@ void (*close)(AudioOutput *data); /** - * Returns a positive number if the output thread shall delay - * the next call to play() or pause(). This should be - * implemented instead of doing a sleep inside the plugin, - * because this allows MPD to listen to commands meanwhile. + * Returns a positive number if the output thread shall further + * delay the next call to play() or pause(), which will happen + * until this function returns 0. This should be implemented + * instead of doing a sleep inside the plugin, because this + * allows MPD to listen to commands meanwhile. * - * @return the number of milliseconds to wait + * @return the duration to wait */ - unsigned (*delay)(AudioOutput *data); + std::chrono::steady_clock::duration (*delay)(AudioOutput *data) noexcept; /** * Display metadata for the next chunk. Optional method, * because not all devices can display metadata. */ - void (*send_tag)(AudioOutput *data, const Tag *tag); + void (*send_tag)(AudioOutput *data, const Tag &tag); /** * Play a chunk of audio data. * - * @return the number of bytes played, or 0 on error + * Throws #std::runtime_error on error. + * + * @return the number of bytes played */ size_t (*play)(AudioOutput *data, - const void *chunk, size_t size, - Error &error); + const void *chunk, size_t size); /** * Wait until the device has finished playing. @@ -137,15 +138,15 @@ * disconnected. Plugins which do not support pausing will * simply be closed, and have to be reopened when unpaused. * - * @return false on error (output will be closed then), true - * for continue to pause + * @return false on error (output will be closed by caller), + * true for continue to pause */ bool (*pause)(AudioOutput *data); /** * The mixer plugin associated with this output plugin. This * may be nullptr if no mixer plugin is implemented. When - * created, this mixer plugin gets the same #config_param as + * created, this mixer plugin gets the same #ConfigParam as * this audio output device. */ const MixerPlugin *mixer_plugin; @@ -162,35 +163,32 @@ gcc_malloc AudioOutput * ao_plugin_init(const AudioOutputPlugin *plugin, - const config_param ¶m, - Error &error); + const ConfigBlock &block); void ao_plugin_finish(AudioOutput *ao); -bool -ao_plugin_enable(AudioOutput *ao, Error &error); +void +ao_plugin_enable(AudioOutput *ao); void ao_plugin_disable(AudioOutput *ao); -bool -ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error); +void +ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format); void ao_plugin_close(AudioOutput *ao); gcc_pure -unsigned -ao_plugin_delay(AudioOutput *ao); +std::chrono::steady_clock::duration +ao_plugin_delay(AudioOutput *ao) noexcept; void -ao_plugin_send_tag(AudioOutput *ao, const Tag *tag); +ao_plugin_send_tag(AudioOutput *ao, const Tag &tag); size_t -ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error); +ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size); void ao_plugin_drain(AudioOutput *ao); diff -Nru mpd-0.19.21/src/output/OutputPrint.cxx mpd-0.20.9/src/output/OutputPrint.cxx --- mpd-0.19.21/src/output/OutputPrint.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputPrint.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,18 +26,17 @@ #include "OutputPrint.hxx" #include "MultipleOutputs.hxx" #include "Internal.hxx" -#include "client/Client.hxx" +#include "client/Response.hxx" void -printAudioDevices(Client &client, const MultipleOutputs &outputs) +printAudioDevices(Response &r, const MultipleOutputs &outputs) { for (unsigned i = 0, n = outputs.Size(); i != n; ++i) { const AudioOutput &ao = outputs.Get(i); - client_printf(client, - "outputid: %i\n" - "outputname: %s\n" - "outputenabled: %i\n", - i, ao.name, ao.enabled); + r.Format("outputid: %i\n" + "outputname: %s\n" + "outputenabled: %i\n", + i, ao.GetName(), ao.IsEnabled()); } } diff -Nru mpd-0.19.21/src/output/OutputPrint.hxx mpd-0.20.9/src/output/OutputPrint.hxx --- mpd-0.19.21/src/output/OutputPrint.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputPrint.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,10 +25,10 @@ #ifndef MPD_OUTPUT_PRINT_HXX #define MPD_OUTPUT_PRINT_HXX -class Client; +class Response; class MultipleOutputs; void -printAudioDevices(Client &client, const MultipleOutputs &outputs); +printAudioDevices(Response &r, const MultipleOutputs &outputs); #endif diff -Nru mpd-0.19.21/src/output/OutputState.cxx mpd-0.20.9/src/output/OutputState.cxx --- mpd-0.19.21/src/output/OutputState.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputState.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -29,9 +29,8 @@ #include "Domain.hxx" #include "Log.hxx" #include "fs/io/BufferedOutputStream.hxx" -#include "util/StringUtil.hxx" +#include "util/StringCompare.hxx" -#include #include #define AUDIO_DEVICE_STATE "audio_device_state:" @@ -44,8 +43,10 @@ { for (unsigned i = 0, n = outputs.Size(); i != n; ++i) { const AudioOutput &ao = outputs.Get(i); + const std::lock_guard lock(ao.mutex); - os.Format(AUDIO_DEVICE_STATE "%d:%s\n", ao.enabled, ao.name); + os.Format(AUDIO_DEVICE_STATE "%d:%s\n", + ao.IsEnabled(), ao.GetName()); } } @@ -56,11 +57,10 @@ char *endptr; const char *name; - if (!StringStartsWith(line, AUDIO_DEVICE_STATE)) + line = StringAfterPrefix(line, AUDIO_DEVICE_STATE); + if (line == nullptr) return false; - line += sizeof(AUDIO_DEVICE_STATE) - 1; - value = strtol(line, &endptr, 10); if (*endptr != ':' || (value != 0 && value != 1)) return false; diff -Nru mpd-0.19.21/src/output/OutputState.hxx mpd-0.20.9/src/output/OutputState.hxx --- mpd-0.19.21/src/output/OutputState.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputState.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -41,6 +41,6 @@ * whether the state has changed and the state file should be saved. */ unsigned -audio_output_state_get_version(void); +audio_output_state_get_version(); #endif diff -Nru mpd-0.19.21/src/output/OutputThread.cxx mpd-0.20.9/src/output/OutputThread.cxx --- mpd-0.19.21/src/output/OutputThread.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/OutputThread.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,59 +19,58 @@ #include "config.h" #include "Internal.hxx" +#include "Client.hxx" #include "OutputAPI.hxx" #include "Domain.hxx" #include "pcm/PcmMix.hxx" -#include "pcm/Domain.hxx" #include "notify.hxx" #include "filter/FilterInternal.hxx" #include "filter/plugins/ConvertFilterPlugin.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx" -#include "PlayerControl.hxx" +#include "mixer/MixerInternal.hxx" +#include "mixer/plugins/SoftwareMixerPlugin.hxx" #include "MusicPipe.hxx" #include "MusicChunk.hxx" #include "thread/Util.hxx" #include "thread/Slack.hxx" #include "thread/Name.hxx" -#include "system/FatalError.hxx" -#include "util/Error.hxx" #include "util/ConstBuffer.hxx" +#include "util/StringBuffer.hxx" +#include "util/ScopeExit.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include "Compiler.h" +#include + #include #include void AudioOutput::CommandFinished() { - assert(command != AO_COMMAND_NONE); - command = AO_COMMAND_NONE; + assert(command != Command::NONE); + command = Command::NONE; - mutex.unlock(); + const ScopeUnlock unlock(mutex); audio_output_client_notify.Signal(); - mutex.lock(); } -inline bool +inline void AudioOutput::Enable() { if (really_enabled) - return true; + return; - mutex.unlock(); - Error error; - bool success = ao_plugin_enable(this, error); - mutex.lock(); - if (!success) { - FormatError(error, - "Failed to enable \"%s\" [%s]", - name, plugin.name); - return false; + try { + const ScopeUnlock unlock(mutex); + ao_plugin_enable(this); + } catch (const std::runtime_error &e) { + std::throw_with_nested(FormatRuntimeError("Failed to enable output \"%s\" [%s]", + name, plugin.name)); } really_enabled = true; - return true; } inline void @@ -83,160 +82,126 @@ if (really_enabled) { really_enabled = false; - mutex.unlock(); + const ScopeUnlock unlock(mutex); ao_plugin_disable(this); - mutex.lock(); } } -inline AudioFormat -AudioOutput::OpenFilter(AudioFormat &format, Error &error_r) -{ - assert(format.IsValid()); - - /* the replay_gain filter cannot fail here */ - if (replay_gain_filter != nullptr && - !replay_gain_filter->Open(format, error_r).IsDefined()) - return AudioFormat::Undefined(); - - if (other_replay_gain_filter != nullptr && - !other_replay_gain_filter->Open(format, error_r).IsDefined()) { - if (replay_gain_filter != nullptr) - replay_gain_filter->Close(); - return AudioFormat::Undefined(); - } - - const AudioFormat af = filter->Open(format, error_r); - if (!af.IsDefined()) { - if (replay_gain_filter != nullptr) - replay_gain_filter->Close(); - if (other_replay_gain_filter != nullptr) - other_replay_gain_filter->Close(); - } - - return af; -} - void AudioOutput::CloseFilter() { - if (replay_gain_filter != nullptr) - replay_gain_filter->Close(); - if (other_replay_gain_filter != nullptr) - other_replay_gain_filter->Close(); + if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin)) + software_mixer_set_filter(*mixer, nullptr); - filter->Close(); + source.Close(); } inline void AudioOutput::Open() { - bool success; - Error error; - struct audio_format_string af_string; - - assert(!open); - assert(pipe != nullptr); - assert(current_chunk == nullptr); - assert(in_audio_format.IsValid()); + assert(request.audio_format.IsValid()); fail_timer.Reset(); /* enable the device (just in case the last enable has failed) */ + Enable(); - if (!Enable()) - /* still no luck */ - return; - - /* open the filter */ + AudioFormat f; - const AudioFormat filter_audio_format = - OpenFilter(in_audio_format, error); - if (!filter_audio_format.IsDefined()) { - FormatError(error, "Failed to open filter for \"%s\" [%s]", - name, plugin.name); + try { + f = source.Open(request.audio_format, *request.pipe, + prepared_replay_gain_filter, + prepared_other_replay_gain_filter, + prepared_filter); - fail_timer.Update(); - return; + if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin)) + software_mixer_set_filter(*mixer, volume_filter.Get()); + } catch (const std::runtime_error &e) { + std::throw_with_nested(FormatRuntimeError("Failed to open filter for \"%s\" [%s]", + name, plugin.name)); } - assert(filter_audio_format.IsValid()); - - out_audio_format = filter_audio_format; - out_audio_format.ApplyMask(config_audio_format); + const auto cf = f.WithMask(config_audio_format); - mutex.unlock(); + if (open && cf != filter_audio_format) { + /* if the filter's output format changes, the output + must be reopened as well */ + CloseOutput(true); + open = false; + } - const AudioFormat retry_audio_format = out_audio_format; + filter_audio_format = cf; - retry_without_dsd: - success = ao_plugin_open(this, out_audio_format, error); - mutex.lock(); + if (!open) { + try { + OpenOutputAndConvert(filter_audio_format); + } catch (...) { + CloseFilter(); + throw; + } - assert(!open); + open = true; + } else if (f != out_audio_format) { + /* reconfigure the final ConvertFilter for its new + input AudioFormat */ + + try { + convert_filter_set(convert_filter.Get(), + out_audio_format); + } catch (const std::runtime_error &e) { + Close(false); + std::throw_with_nested(FormatRuntimeError("Failed to convert for \"%s\" [%s]", + name, plugin.name)); + } + } - if (!success) { - FormatError(error, "Failed to open \"%s\" [%s]", - name, plugin.name); + if (f != source.GetInputAudioFormat() || f != out_audio_format) + FormatDebug(output_domain, "converting in=%s -> f=%s -> out=%s", + ToString(source.GetInputAudioFormat()).c_str(), + ToString(f).c_str(), + ToString(out_audio_format).c_str()); +} - mutex.unlock(); - CloseFilter(); - mutex.lock(); +void +AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format) +{ + out_audio_format = desired_audio_format; - fail_timer.Update(); - return; + try { + ao_plugin_open(this, out_audio_format); + } catch (const std::runtime_error &e) { + std::throw_with_nested(FormatRuntimeError("Failed to open \"%s\" [%s]", + name, plugin.name)); } - if (!convert_filter_set(convert_filter, out_audio_format, - error)) { - FormatError(error, "Failed to convert for \"%s\" [%s]", - name, plugin.name); + FormatDebug(output_domain, + "opened plugin=%s name=\"%s\" audio_format=%s", + plugin.name, name, + ToString(out_audio_format).c_str()); - mutex.unlock(); + try { + convert_filter_set(convert_filter.Get(), out_audio_format); + } catch (const std::runtime_error &e) { ao_plugin_close(this); - if (error.IsDomain(pcm_domain) && - out_audio_format.format == SampleFormat::DSD) { + if (out_audio_format.format == SampleFormat::DSD) { /* if the audio output supports DSD, but not the given sample rate, it asks MPD to resample; resampling DSD however is not implemented; our last resort is to give up DSD and fall back to PCM */ - // TODO: clean up this workaround - + LogError(e); FormatError(output_domain, "Retrying without DSD"); - out_audio_format = retry_audio_format; - out_audio_format.format = SampleFormat::FLOAT; - - /* clear the Error to allow reusing it */ - error.Clear(); - - /* sorry for the "goto" - this is a workaround - for the stable branch that should be as - unintrusive as possible */ - goto retry_without_dsd; + desired_audio_format.format = SampleFormat::FLOAT; + OpenOutputAndConvert(desired_audio_format); + return; } - CloseFilter(); - mutex.lock(); - - fail_timer.Update(); - return; + std::throw_with_nested(FormatRuntimeError("Failed to convert for \"%s\" [%s]", + name, plugin.name)); } - - open = true; - - FormatDebug(output_domain, - "opened plugin=%s name=\"%s\" audio_format=%s", - plugin.name, name, - audio_format_to_string(out_audio_format, &af_string)); - - if (in_audio_format != out_audio_format) - FormatDebug(output_domain, "converting from %s", - audio_format_to_string(in_audio_format, - &af_string)); } void @@ -244,86 +209,26 @@ { assert(open); - pipe = nullptr; - - current_chunk = nullptr; open = false; - mutex.unlock(); + const ScopeUnlock unlock(mutex); - if (drain) - ao_plugin_drain(this); - else - ao_plugin_cancel(this); - - ao_plugin_close(this); + CloseOutput(drain); CloseFilter(); - mutex.lock(); - FormatDebug(output_domain, "closed plugin=%s name=\"%s\"", plugin.name, name); } -void -AudioOutput::ReopenFilter() -{ - Error error; - - mutex.unlock(); - CloseFilter(); - mutex.lock(); - - const AudioFormat filter_audio_format = - OpenFilter(in_audio_format, error); - if (!filter_audio_format.IsDefined() || - !convert_filter_set(convert_filter, out_audio_format, - error)) { - FormatError(error, - "Failed to open filter for \"%s\" [%s]", - name, plugin.name); - - /* this is a little code duplication from Close(), - but we cannot call this function because we must - not call filter_close(filter) again */ - - pipe = nullptr; - - current_chunk = nullptr; - open = false; - fail_timer.Update(); - - mutex.unlock(); - ao_plugin_close(this); - mutex.lock(); - - return; - } -} - -void -AudioOutput::Reopen() +inline void +AudioOutput::CloseOutput(bool drain) { - if (!config_audio_format.IsFullyDefined()) { - if (open) { - const MusicPipe *mp = pipe; - Close(true); - pipe = mp; - } - - /* no audio format is configured: copy in->out, let - the output's open() method determine the effective - out_audio_format */ - out_audio_format = in_audio_format; - out_audio_format.ApplyMask(config_audio_format); - } - - if (open) - /* the audio format has changed, and all filters have - to be reconfigured */ - ReopenFilter(); + if (drain) + ao_plugin_drain(this); else - Open(); + ao_plugin_cancel(this); + + ao_plugin_close(this); } /** @@ -336,154 +241,70 @@ AudioOutput::WaitForDelay() { while (true) { - unsigned delay = ao_plugin_delay(this); - if (delay == 0) + const auto delay = ao_plugin_delay(this); + if (delay <= std::chrono::steady_clock::duration::zero()) return true; (void)cond.timed_wait(mutex, delay); - if (command != AO_COMMAND_NONE) + if (command != Command::NONE) return false; } } -static ConstBuffer -ao_chunk_data(AudioOutput *ao, const MusicChunk *chunk, - Filter *replay_gain_filter, - unsigned *replay_gain_serial_p) -{ - assert(chunk != nullptr); - assert(!chunk->IsEmpty()); - assert(chunk->CheckFormat(ao->in_audio_format)); - - ConstBuffer data(chunk->data, chunk->length); - - (void)ao; - - assert(data.size % ao->in_audio_format.GetFrameSize() == 0); - - if (!data.IsEmpty() && replay_gain_filter != nullptr) { - if (chunk->replay_gain_serial != *replay_gain_serial_p) { - replay_gain_filter_set_info(replay_gain_filter, - chunk->replay_gain_serial != 0 - ? &chunk->replay_gain_info - : nullptr); - *replay_gain_serial_p = chunk->replay_gain_serial; - } - - Error error; - data = replay_gain_filter->FilterPCM(data, error); - if (data.IsNull()) - FormatError(error, "\"%s\" [%s] failed to filter", - ao->name, ao->plugin.name); - } - - return data; -} - -static ConstBuffer -ao_filter_chunk(AudioOutput *ao, const MusicChunk *chunk) -{ - ConstBuffer data = - ao_chunk_data(ao, chunk, ao->replay_gain_filter, - &ao->replay_gain_serial); - if (data.IsEmpty()) - return data; - - /* cross-fade */ - - if (chunk->other != nullptr) { - ConstBuffer other_data = - ao_chunk_data(ao, chunk->other, - ao->other_replay_gain_filter, - &ao->other_replay_gain_serial); - if (other_data.IsNull()) - return nullptr; - - if (other_data.IsEmpty()) - return data; - - /* if the "other" chunk is longer, then that trailer - is used as-is, without mixing; it is part of the - "next" song being faded in, and if there's a rest, - it means cross-fading ends here */ - - if (data.size > other_data.size) - data.size = other_data.size; - - float mix_ratio = chunk->mix_ratio; - if (mix_ratio >= 0) - /* reverse the mix ratio (because the - arguments to pcm_mix() are reversed), but - only if the mix ratio is non-negative; a - negative mix ratio is a MixRamp special - case */ - mix_ratio = 1.0 - mix_ratio; - - void *dest = ao->cross_fade_buffer.Get(other_data.size); - memcpy(dest, other_data.data, other_data.size); - if (!pcm_mix(ao->cross_fade_dither, dest, data.data, data.size, - ao->in_audio_format.format, - mix_ratio)) { - FormatError(output_domain, - "Cannot cross-fade format %s", - sample_format_to_string(ao->in_audio_format.format)); - return nullptr; - } - - data.data = dest; - data.size = other_data.size; - } - - /* apply filter chain */ - - Error error; - data = ao->filter->FilterPCM(data, error); - if (data.IsNull()) { - FormatError(error, "\"%s\" [%s] failed to filter", - ao->name, ao->plugin.name); - return nullptr; - } - - return data; +bool +AudioOutput::FillSourceOrClose() +try { + return source.Fill(mutex); +} catch (const std::runtime_error &e) { + FormatError(e, "Failed to filter for output \"%s\" [%s]", + name, plugin.name); + + Close(false); + + /* don't automatically reopen this device for 10 + seconds */ + fail_timer.Update(); + return false; } inline bool -AudioOutput::PlayChunk(const MusicChunk *chunk) +AudioOutput::PlayChunk() { - assert(filter != nullptr); - - if (tags && gcc_unlikely(chunk->tag != nullptr)) { - mutex.unlock(); - ao_plugin_send_tag(this, chunk->tag); - mutex.lock(); - } - - auto data = ConstBuffer::FromVoid(ao_filter_chunk(this, chunk)); - if (data.IsNull()) { - Close(false); - - /* don't automatically reopen this device for 10 - seconds */ - fail_timer.Update(); - return false; + if (tags) { + const auto *tag = source.ReadTag(); + if (tag != nullptr) { + const ScopeUnlock unlock(mutex); + try { + ao_plugin_send_tag(this, *tag); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to send tag to \"%s\" [%s]", + name, plugin.name); + } + } } - Error error; + while (command == Command::NONE) { + const auto data = source.PeekData(); + if (data.IsEmpty()) + break; - while (!data.IsEmpty() && command == AO_COMMAND_NONE) { if (!WaitForDelay()) break; - mutex.unlock(); - size_t nbytes = ao_plugin_play(this, data.data, data.size, - error); - mutex.lock(); - if (nbytes == 0) { - /* play()==0 means failure */ - FormatError(error, "\"%s\" [%s] failed to play", + size_t nbytes; + + try { + const ScopeUnlock unlock(mutex); + nbytes = ao_plugin_play(this, data.data, data.size); + } catch (const std::runtime_error &e) { + FormatError(e, "\"%s\" [%s] failed to play", name, plugin.name); + nbytes = 0; + } + + if (nbytes == 0) { Close(false); /* don't automatically reopen this device for @@ -494,63 +315,50 @@ return false; } - assert(nbytes <= data.size); assert(nbytes % out_audio_format.GetFrameSize() == 0); - data.data += nbytes; - data.size -= nbytes; + source.ConsumeData(nbytes); } return true; } -inline const MusicChunk * -AudioOutput::GetNextChunk() const -{ - return current_chunk != nullptr - /* continue the previous play() call */ - ? current_chunk->next - /* get the first chunk from the pipe */ - : pipe->Peek(); -} - inline bool AudioOutput::Play() { - assert(pipe != nullptr); - - const MusicChunk *chunk = GetNextChunk(); - if (chunk == nullptr) + if (!FillSourceOrClose()) /* no chunk available */ return false; - current_chunk_finished = false; - assert(!in_playback_loop); in_playback_loop = true; - while (chunk != nullptr && command == AO_COMMAND_NONE) { - assert(!current_chunk_finished); + AtScopeExit(this) { + assert(in_playback_loop); + in_playback_loop = false; + }; - current_chunk = chunk; + unsigned n = 0; - if (!PlayChunk(chunk)) { - assert(current_chunk == nullptr); - break; - } - - assert(current_chunk == chunk); - chunk = chunk->next; - } + do { + if (command != Command::NONE) + return true; - assert(in_playback_loop); - in_playback_loop = false; + if (++n >= 64) { + /* wake up the player every now and then to + give it a chance to refill the pipe before + it runs empty */ + const ScopeUnlock unlock(mutex); + client->ChunksConsumed(); + n = 0; + } - current_chunk_finished = true; + if (!PlayChunk()) + break; + } while (FillSourceOrClose()); - mutex.unlock(); - player_control->LockSignal(); - mutex.lock(); + const ScopeUnlock unlock(mutex); + client->ChunksConsumed(); return true; } @@ -558,9 +366,10 @@ inline void AudioOutput::Pause() { - mutex.unlock(); - ao_plugin_cancel(this); - mutex.lock(); + { + const ScopeUnlock unlock(mutex); + ao_plugin_cancel(this); + } pause = true; CommandFinished(); @@ -569,15 +378,21 @@ if (!WaitForDelay()) break; - mutex.unlock(); - bool success = ao_plugin_pause(this); - mutex.lock(); + bool success; + try { + const ScopeUnlock unlock(mutex); + success = ao_plugin_pause(this); + } catch (const std::runtime_error &e) { + FormatError(e, "\"%s\" [%s] failed to pause", + name, plugin.name); + success = false; + } if (!success) { Close(false); break; } - } while (command == AO_COMMAND_NONE); + } while (command == Command::NONE); pause = false; } @@ -587,45 +402,62 @@ { FormatThreadName("output:%s", name); - SetThreadRealtime(); + try { + SetThreadRealtime(); + } catch (const std::runtime_error &e) { + LogError(e, + "OutputThread could not get realtime scheduling, continuing anyway"); + } + SetThreadTimerSlackUS(100); - mutex.lock(); + const std::lock_guard lock(mutex); - while (1) { + while (true) { switch (command) { - case AO_COMMAND_NONE: + case Command::NONE: break; - case AO_COMMAND_ENABLE: - Enable(); + case Command::ENABLE: + last_error = nullptr; + + try { + Enable(); + } catch (const std::runtime_error &e) { + LogError(e); + fail_timer.Update(); + last_error = std::current_exception(); + } + CommandFinished(); break; - case AO_COMMAND_DISABLE: + case Command::DISABLE: Disable(); CommandFinished(); break; - case AO_COMMAND_OPEN: - Open(); - CommandFinished(); - break; + case Command::OPEN: + last_error = nullptr; + + try { + Open(); + } catch (const std::runtime_error &e) { + LogError(e); + fail_timer.Update(); + last_error = std::current_exception(); + } - case AO_COMMAND_REOPEN: - Reopen(); CommandFinished(); break; - case AO_COMMAND_CLOSE: - assert(open); - assert(pipe != nullptr); - - Close(false); + case Command::CLOSE: + if (open) + Close(false); CommandFinished(); break; - case AO_COMMAND_PAUSE: + case Command::PAUSE: if (!open) { /* the output has failed after audio_output_all_pause() has @@ -642,35 +474,30 @@ the new command first */ continue; - case AO_COMMAND_DRAIN: + case Command::DRAIN: if (open) { - assert(current_chunk == nullptr); - assert(pipe->Peek() == nullptr); - - mutex.unlock(); + const ScopeUnlock unlock(mutex); ao_plugin_drain(this); - mutex.lock(); } CommandFinished(); continue; - case AO_COMMAND_CANCEL: - current_chunk = nullptr; + case Command::CANCEL: + source.Cancel(); if (open) { - mutex.unlock(); + const ScopeUnlock unlock(mutex); ao_plugin_cancel(this); - mutex.lock(); } CommandFinished(); continue; - case AO_COMMAND_KILL: - current_chunk = nullptr; + case Command::KILL: + Disable(); + source.Cancel(); CommandFinished(); - mutex.unlock(); return; } @@ -679,7 +506,7 @@ chunks in the pipe */ continue; - if (command == AO_COMMAND_NONE) { + if (command == Command::NONE) { woken_for_play = false; cond.wait(mutex); } @@ -696,9 +523,7 @@ void AudioOutput::StartThread() { - assert(command == AO_COMMAND_NONE); + assert(command == Command::NONE); - Error error; - if (!thread.Start(Task, this, error)) - FatalError(error); + thread.Start(Task, this); } diff -Nru mpd-0.19.21/src/output/plugins/AlsaOutputPlugin.cxx mpd-0.20.9/src/output/plugins/AlsaOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/AlsaOutputPlugin.cxx 2016-11-16 18:49:48.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/AlsaOutputPlugin.cxx 2017-06-04 10:38:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,12 @@ #include "config.h" #include "AlsaOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "mixer/MixerList.hxx" #include "pcm/PcmExport.hxx" -#include "config/ConfigError.hxx" +#include "system/ByteOrder.hxx" #include "util/Manual.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/ConstBuffer.hxx" #include "Log.hxx" @@ -38,16 +39,20 @@ #define HAVE_ALSA_DSD #endif +#if SND_LIB_VERSION >= 0x1001d +/* alsa-lib supports DSD_U32 since version 1.0.29 */ +#define HAVE_ALSA_DSD_U32 +#endif + static const char default_device[] = "default"; static constexpr unsigned MPD_ALSA_BUFFER_TIME_US = 500000; static constexpr unsigned MPD_ALSA_RETRY_NR = 5; -typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer, - snd_pcm_uframes_t size); +class AlsaOutput { + friend struct AudioOutputWrapper; -struct AlsaOutput { AudioOutput base; Manual pcm_export; @@ -56,38 +61,30 @@ * The configured name of the ALSA device; empty for the * default device */ - std::string device; - - /** use memory mapped I/O? */ - bool use_mmap; + const std::string device; +#ifdef ENABLE_DSD /** - * Enable DSD over PCM according to the DoP standard standard? + * Enable DSD over PCM according to the DoP standard? * * @see http://dsd-guide.com/dop-open-standard */ - bool dop; + const bool dop; +#endif /** libasound's buffer_time setting (in microseconds) */ - unsigned int buffer_time; + const unsigned buffer_time; /** libasound's period_time setting (in microseconds) */ - unsigned int period_time; + const unsigned period_time; /** the mode flags passed to snd_pcm_open */ - int mode; + int mode = 0; /** the libasound PCM device handle */ snd_pcm_t *pcm; /** - * a pointer to the libasound writei() function, which is - * snd_pcm_writei() or snd_pcm_mmap_writei(), depending on the - * use_mmap configuration - */ - alsa_writei_t *writei; - - /** * The size of one audio frame passed to method play(). */ size_t in_frame_size; @@ -126,97 +123,105 @@ */ uint8_t *silence; - AlsaOutput() - :base(alsa_output_plugin), - mode(0), writei(snd_pcm_writei) { +public: + AlsaOutput(const ConfigBlock &block); + + ~AlsaOutput() { + /* free libasound's config cache */ + snd_config_update_free_global(); } - bool Configure(const config_param ¶m, Error &error); -}; + gcc_pure + const char *GetDevice() const noexcept { + return device.empty() ? default_device : device.c_str(); + } -static constexpr Domain alsa_output_domain("alsa_output"); + static AlsaOutput *Create(const ConfigBlock &block); -static const char * -alsa_device(const AlsaOutput *ad) -{ - return ad->device.empty() ? default_device : ad->device.c_str(); -} + void Enable(); + void Disable(); -inline bool -AlsaOutput::Configure(const config_param ¶m, Error &error) -{ - if (!base.Configure(param, error)) - return false; + void Open(AudioFormat &audio_format); + void Close(); - device = param.GetBlockValue("device", ""); + size_t PlayRaw(ConstBuffer data); + size_t Play(const void *chunk, size_t size); + void Drain(); + void Cancel(); - use_mmap = param.GetBlockValue("use_mmap", false); +private: + /** + * Set up the snd_pcm_t object which was opened by the caller. + * Set up the configured settings and the audio format. + * + * Throws #std::runtime_error on error. + */ + void Setup(AudioFormat &audio_format, PcmExport::Params ¶ms); + +#ifdef ENABLE_DSD + void SetupDop(AudioFormat audio_format, + PcmExport::Params ¶ms); +#endif + + void SetupOrDop(AudioFormat &audio_format, PcmExport::Params ¶ms); + + int Recover(int err); + + /** + * Write silence to the ALSA device. + */ + void WriteSilence(snd_pcm_uframes_t nframes) { + snd_pcm_writei(pcm, silence, nframes); + } - dop = param.GetBlockValue("dop", false) || - /* legacy name from MPD 0.18 and older: */ - param.GetBlockValue("dsd_usb", false); +}; - buffer_time = param.GetBlockValue("buffer_time", - MPD_ALSA_BUFFER_TIME_US); - period_time = param.GetBlockValue("period_time", 0u); +static constexpr Domain alsa_output_domain("alsa_output"); +AlsaOutput::AlsaOutput(const ConfigBlock &block) + :base(alsa_output_plugin, block), + device(block.GetBlockValue("device", "")), +#ifdef ENABLE_DSD + dop(block.GetBlockValue("dop", false) || + /* legacy name from MPD 0.18 and older: */ + block.GetBlockValue("dsd_usb", false)), +#endif + buffer_time(block.GetBlockValue("buffer_time", + MPD_ALSA_BUFFER_TIME_US)), + period_time(block.GetBlockValue("period_time", 0u)) +{ #ifdef SND_PCM_NO_AUTO_RESAMPLE - if (!param.GetBlockValue("auto_resample", true)) + if (!block.GetBlockValue("auto_resample", true)) mode |= SND_PCM_NO_AUTO_RESAMPLE; #endif #ifdef SND_PCM_NO_AUTO_CHANNELS - if (!param.GetBlockValue("auto_channels", true)) + if (!block.GetBlockValue("auto_channels", true)) mode |= SND_PCM_NO_AUTO_CHANNELS; #endif #ifdef SND_PCM_NO_AUTO_FORMAT - if (!param.GetBlockValue("auto_format", true)) + if (!block.GetBlockValue("auto_format", true)) mode |= SND_PCM_NO_AUTO_FORMAT; #endif - - return true; } -static AudioOutput * -alsa_init(const config_param ¶m, Error &error) -{ - AlsaOutput *ad = new AlsaOutput(); - - if (!ad->Configure(param, error)) { - delete ad; - return nullptr; - } - - return &ad->base; -} - -static void -alsa_finish(AudioOutput *ao) +inline AlsaOutput * +AlsaOutput::Create(const ConfigBlock &block) { - AlsaOutput *ad = (AlsaOutput *)ao; - - delete ad; - - /* free libasound's config cache */ - snd_config_update_free_global(); + return new AlsaOutput(block); } -static bool -alsa_output_enable(AudioOutput *ao, gcc_unused Error &error) +inline void +AlsaOutput::Enable() { - AlsaOutput *ad = (AlsaOutput *)ao; - - ad->pcm_export.Construct(); - return true; + pcm_export.Construct(); } -static void -alsa_output_disable(AudioOutput *ao) +inline void +AlsaOutput::Disable() { - AlsaOutput *ad = (AlsaOutput *)ao; - - ad->pcm_export.Destruct(); + pcm_export.Destruct(); } static bool @@ -242,8 +247,9 @@ * enum. Returns SND_PCM_FORMAT_UNKNOWN if there is no according ALSA * PCM format. */ +gcc_const static snd_pcm_format_t -get_bitformat(SampleFormat sample_format) +ToAlsaPcmFormat(SampleFormat sample_format) noexcept { switch (sample_format) { case SampleFormat::UNDEFINED: @@ -281,7 +287,7 @@ * SND_PCM_FORMAT_UNKNOWN if the format cannot be byte-swapped. */ static snd_pcm_format_t -byteswap_bitformat(snd_pcm_format_t fmt) +ByteSwapAlsaPcmFormat(snd_pcm_format_t fmt) noexcept { switch (fmt) { case SND_PCM_FORMAT_S16_LE: return SND_PCM_FORMAT_S16_BE; @@ -297,6 +303,21 @@ return SND_PCM_FORMAT_S24_3BE; case SND_PCM_FORMAT_S32_BE: return SND_PCM_FORMAT_S32_LE; + +#ifdef HAVE_ALSA_DSD_U32 + case SND_PCM_FORMAT_DSD_U16_LE: + return SND_PCM_FORMAT_DSD_U16_BE; + + case SND_PCM_FORMAT_DSD_U16_BE: + return SND_PCM_FORMAT_DSD_U16_LE; + + case SND_PCM_FORMAT_DSD_U32_LE: + return SND_PCM_FORMAT_DSD_U32_BE; + + case SND_PCM_FORMAT_DSD_U32_BE: + return SND_PCM_FORMAT_DSD_U32_LE; +#endif + default: return SND_PCM_FORMAT_UNKNOWN; } } @@ -306,7 +327,7 @@ * Returns SND_PCM_FORMAT_UNKNOWN if not. */ static snd_pcm_format_t -alsa_to_packed_format(snd_pcm_format_t fmt) +PackAlsaPcmFormat(snd_pcm_format_t fmt) { switch (fmt) { case SND_PCM_FORMAT_S24_LE: @@ -325,23 +346,23 @@ * fall back to the packed version. */ static int -alsa_try_format_or_packed(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, - snd_pcm_format_t fmt, bool *packed_r) +AlsaTryFormatOrPacked(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + snd_pcm_format_t fmt, PcmExport::Params ¶ms) { int err = snd_pcm_hw_params_set_format(pcm, hwparams, fmt); if (err == 0) - *packed_r = false; + params.pack24 = false; if (err != -EINVAL) return err; - fmt = alsa_to_packed_format(fmt); + fmt = PackAlsaPcmFormat(fmt); if (fmt == SND_PCM_FORMAT_UNKNOWN) return -EINVAL; err = snd_pcm_hw_params_set_format(pcm, hwparams, fmt); if (err == 0) - *packed_r = true; + params.pack24 = true; return err; } @@ -351,46 +372,95 @@ * reversed host byte order if was not supported. */ static int -alsa_output_try_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, - SampleFormat sample_format, - bool *packed_r, bool *reverse_endian_r) +AlsaTryFormatOrByteSwap(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + snd_pcm_format_t fmt, + PcmExport::Params ¶ms) { - snd_pcm_format_t alsa_format = get_bitformat(sample_format); - if (alsa_format == SND_PCM_FORMAT_UNKNOWN) - return -EINVAL; - - int err = alsa_try_format_or_packed(pcm, hwparams, alsa_format, - packed_r); + int err = AlsaTryFormatOrPacked(pcm, hwparams, fmt, params); if (err == 0) - *reverse_endian_r = false; + params.reverse_endian = false; if (err != -EINVAL) return err; - alsa_format = byteswap_bitformat(alsa_format); - if (alsa_format == SND_PCM_FORMAT_UNKNOWN) + fmt = ByteSwapAlsaPcmFormat(fmt); + if (fmt == SND_PCM_FORMAT_UNKNOWN) return -EINVAL; - err = alsa_try_format_or_packed(pcm, hwparams, alsa_format, packed_r); + err = AlsaTryFormatOrPacked(pcm, hwparams, fmt, params); if (err == 0) - *reverse_endian_r = true; + params.reverse_endian = true; return err; } /** + * Attempts to configure the specified sample format. On DSD_U8 + * failure, attempt to switch to DSD_U32 or DSD_U16. + */ +static int +AlsaTryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + snd_pcm_format_t fmt, PcmExport::Params ¶ms) +{ + int err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params); + +#if defined(ENABLE_DSD) && defined(HAVE_ALSA_DSD_U32) + if (err == 0) { + params.dsd_u16 = false; + params.dsd_u32 = false; + } + + if (err == -EINVAL && fmt == SND_PCM_FORMAT_DSD_U8) { + /* attempt to switch to DSD_U32 */ + fmt = IsLittleEndian() + ? SND_PCM_FORMAT_DSD_U32_LE + : SND_PCM_FORMAT_DSD_U32_BE; + err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params); + if (err == 0) + params.dsd_u32 = true; + else + fmt = SND_PCM_FORMAT_DSD_U8; + } + + if (err == -EINVAL && fmt == SND_PCM_FORMAT_DSD_U8) { + /* attempt to switch to DSD_U16 */ + fmt = IsLittleEndian() + ? SND_PCM_FORMAT_DSD_U16_LE + : SND_PCM_FORMAT_DSD_U16_BE; + err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params); + if (err == 0) + params.dsd_u16 = true; + else + fmt = SND_PCM_FORMAT_DSD_U8; + } +#endif + + return err; +} + +static int +AlsaTryFormat(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + SampleFormat sample_format, + PcmExport::Params ¶ms) +{ + snd_pcm_format_t alsa_format = ToAlsaPcmFormat(sample_format); + if (alsa_format == SND_PCM_FORMAT_UNKNOWN) + return -EINVAL; + + return AlsaTryFormatDsd(pcm, hwparams, alsa_format, params); +} + +/** * Configure a sample format, and probe other formats if that fails. */ static int -alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, - AudioFormat &audio_format, - bool *packed_r, bool *reverse_endian_r) +AlsaSetupFormat(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + AudioFormat &audio_format, + PcmExport::Params ¶ms) { /* try the input format first */ - int err = alsa_output_try_format(pcm, hwparams, - audio_format.format, - packed_r, reverse_endian_r); + int err = AlsaTryFormat(pcm, hwparams, audio_format.format, params); /* if unsupported by the hardware, try other formats */ @@ -409,8 +479,7 @@ if (mpd_format == audio_format.format) continue; - err = alsa_output_try_format(pcm, hwparams, mpd_format, - packed_r, reverse_endian_r); + err = AlsaTryFormat(pcm, hwparams, mpd_format, params); if (err == 0) audio_format.format = mpd_format; } @@ -419,91 +488,69 @@ } /** - * Set up the snd_pcm_t object which was opened by the caller. Set up - * the configured settings and the audio format. + * Wrapper for snd_pcm_hw_params(). + * + * @param buffer_time the configured buffer time, or 0 if not configured + * @param period_time the configured period time, or 0 if not configured + * @param audio_format an #AudioFormat to be configured (or modified) + * by this function + * @param params to be modified by this function */ -static bool -alsa_setup(AlsaOutput *ad, AudioFormat &audio_format, - bool *packed_r, bool *reverse_endian_r, Error &error) +static void +AlsaSetupHw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, + unsigned buffer_time, unsigned period_time, + AudioFormat &audio_format, PcmExport::Params ¶ms) { - unsigned int sample_rate = audio_format.sample_rate; - unsigned int channels = audio_format.channels; int err; - const char *cmd = nullptr; unsigned retry = MPD_ALSA_RETRY_NR; - unsigned int period_time, period_time_ro; - unsigned int buffer_time; + unsigned int period_time_ro = period_time; - period_time_ro = period_time = ad->period_time; configure_hw: /* configure HW params */ - snd_pcm_hw_params_t *hwparams; - snd_pcm_hw_params_alloca(&hwparams); - cmd = "snd_pcm_hw_params_any"; - err = snd_pcm_hw_params_any(ad->pcm, hwparams); + err = snd_pcm_hw_params_any(pcm, hwparams); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params_any() failed: %s", + snd_strerror(-err)); - if (ad->use_mmap) { - err = snd_pcm_hw_params_set_access(ad->pcm, hwparams, - SND_PCM_ACCESS_MMAP_INTERLEAVED); - if (err < 0) { - FormatWarning(alsa_output_domain, - "Cannot set mmap'ed mode on ALSA device \"%s\": %s", - alsa_device(ad), snd_strerror(-err)); - LogWarning(alsa_output_domain, - "Falling back to direct write mode"); - ad->use_mmap = false; - } else - ad->writei = snd_pcm_mmap_writei; - } - - if (!ad->use_mmap) { - cmd = "snd_pcm_hw_params_set_access"; - err = snd_pcm_hw_params_set_access(ad->pcm, hwparams, - SND_PCM_ACCESS_RW_INTERLEAVED); - if (err < 0) - goto error; - ad->writei = snd_pcm_writei; - } - - err = alsa_output_setup_format(ad->pcm, hwparams, audio_format, - packed_r, reverse_endian_r); - if (err < 0) { - error.Format(alsa_output_domain, err, - "ALSA device \"%s\" does not support format %s: %s", - alsa_device(ad), - sample_format_to_string(audio_format.format), - snd_strerror(-err)); - return false; - } + err = snd_pcm_hw_params_set_access(pcm, hwparams, + SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) + throw FormatRuntimeError("snd_pcm_hw_params_set_access() failed: %s", + snd_strerror(-err)); - snd_pcm_format_t format; - if (snd_pcm_hw_params_get_format(hwparams, &format) == 0) - FormatDebug(alsa_output_domain, - "format=%s (%s)", snd_pcm_format_name(format), - snd_pcm_format_description(format)); + err = AlsaSetupFormat(pcm, hwparams, audio_format, params); + if (err < 0) + throw FormatRuntimeError("Failed to configure format %s: %s", + sample_format_to_string(audio_format.format), + snd_strerror(-err)); - err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams, + unsigned int channels = audio_format.channels; + err = snd_pcm_hw_params_set_channels_near(pcm, hwparams, &channels); - if (err < 0) { - error.Format(alsa_output_domain, err, - "ALSA device \"%s\" does not support %i channels: %s", - alsa_device(ad), (int)audio_format.channels, - snd_strerror(-err)); - return false; - } + if (err < 0) + throw FormatRuntimeError("Failed to configure %i channels: %s", + (int)audio_format.channels, + snd_strerror(-err)); + audio_format.channels = (int8_t)channels; - err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams, - &sample_rate, nullptr); - if (err < 0 || sample_rate == 0) { - error.Format(alsa_output_domain, err, - "ALSA device \"%s\" does not support %u Hz audio", - alsa_device(ad), audio_format.sample_rate); - return false; - } - audio_format.sample_rate = sample_rate; + const unsigned requested_sample_rate = + params.CalcOutputSampleRate(audio_format.sample_rate); + unsigned output_sample_rate = requested_sample_rate; + + err = snd_pcm_hw_params_set_rate_near(pcm, hwparams, + &output_sample_rate, nullptr); + if (err < 0) + throw FormatRuntimeError("Failed to configure sample rate %u Hz: %s", + requested_sample_rate, + snd_strerror(-err)); + + if (output_sample_rate == 0) + throw FormatRuntimeError("Failed to configure sample rate %u Hz", + audio_format.sample_rate); + + if (output_sample_rate != requested_sample_rate) + audio_format.sample_rate = params.CalcInputSampleRate(output_sample_rate); snd_pcm_uframes_t buffer_size_min, buffer_size_max; snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min); @@ -525,13 +572,12 @@ (unsigned)period_size_min, (unsigned)period_size_max, period_time_min, period_time_max); - if (ad->buffer_time > 0) { - buffer_time = ad->buffer_time; - cmd = "snd_pcm_hw_params_set_buffer_time_near"; - err = snd_pcm_hw_params_set_buffer_time_near(ad->pcm, hwparams, + if (buffer_time > 0) { + err = snd_pcm_hw_params_set_buffer_time_near(pcm, hwparams, &buffer_time, nullptr); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params_set_buffer_time_near() failed: %s", + snd_strerror(-err)); } else { err = snd_pcm_hw_params_get_buffer_time(hwparams, &buffer_time, nullptr); @@ -549,63 +595,89 @@ if (period_time_ro > 0) { period_time = period_time_ro; - cmd = "snd_pcm_hw_params_set_period_time_near"; - err = snd_pcm_hw_params_set_period_time_near(ad->pcm, hwparams, + err = snd_pcm_hw_params_set_period_time_near(pcm, hwparams, &period_time, nullptr); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params_set_period_time_near() failed: %s", + snd_strerror(-err)); } - cmd = "snd_pcm_hw_params"; - err = snd_pcm_hw_params(ad->pcm, hwparams); + err = snd_pcm_hw_params(pcm, hwparams); if (err == -EPIPE && --retry > 0 && period_time_ro > 0) { period_time_ro = period_time_ro >> 1; goto configure_hw; } else if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params() failed: %s", + snd_strerror(-err)); if (retry != MPD_ALSA_RETRY_NR) FormatDebug(alsa_output_domain, "ALSA period_time set to %d", period_time); +} - snd_pcm_uframes_t alsa_buffer_size; - cmd = "snd_pcm_hw_params_get_buffer_size"; - err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size); - if (err < 0) - goto error; +/** + * Wrapper for snd_pcm_sw_params(). + */ +static void +AlsaSetupSw(snd_pcm_t *pcm, snd_pcm_uframes_t start_threshold, + snd_pcm_uframes_t avail_min) +{ + snd_pcm_sw_params_t *swparams; + snd_pcm_sw_params_alloca(&swparams); - snd_pcm_uframes_t alsa_period_size; - cmd = "snd_pcm_hw_params_get_period_size"; - err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, - nullptr); + int err = snd_pcm_sw_params_current(pcm, swparams); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_sw_params_current() failed: %s", + snd_strerror(-err)); - /* configure SW params */ - snd_pcm_sw_params_t *swparams; - snd_pcm_sw_params_alloca(&swparams); + err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, + start_threshold); + if (err < 0) + throw FormatRuntimeError("snd_pcm_sw_params_set_start_threshold() failed: %s", + snd_strerror(-err)); - cmd = "snd_pcm_sw_params_current"; - err = snd_pcm_sw_params_current(ad->pcm, swparams); + err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_sw_params_set_avail_min() failed: %s", + snd_strerror(-err)); - cmd = "snd_pcm_sw_params_set_start_threshold"; - err = snd_pcm_sw_params_set_start_threshold(ad->pcm, swparams, - alsa_buffer_size - - alsa_period_size); + err = snd_pcm_sw_params(pcm, swparams); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_sw_params() failed: %s", + snd_strerror(-err)); +} + +inline void +AlsaOutput::Setup(AudioFormat &audio_format, + PcmExport::Params ¶ms) +{ + snd_pcm_hw_params_t *hwparams; + snd_pcm_hw_params_alloca(&hwparams); + + AlsaSetupHw(pcm, hwparams, + buffer_time, period_time, + audio_format, params); + + snd_pcm_format_t format; + if (snd_pcm_hw_params_get_format(hwparams, &format) == 0) + FormatDebug(alsa_output_domain, + "format=%s (%s)", snd_pcm_format_name(format), + snd_pcm_format_description(format)); - cmd = "snd_pcm_sw_params_set_avail_min"; - err = snd_pcm_sw_params_set_avail_min(ad->pcm, swparams, - alsa_period_size); + snd_pcm_uframes_t alsa_buffer_size; + int err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params_get_buffer_size() failed: %s", + snd_strerror(-err)); - cmd = "snd_pcm_sw_params"; - err = snd_pcm_sw_params(ad->pcm, swparams); + snd_pcm_uframes_t alsa_period_size; + err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, + nullptr); if (err < 0) - goto error; + throw FormatRuntimeError("snd_pcm_hw_params_get_period_size() failed: %s", + snd_strerror(-err)); + + AlsaSetupSw(pcm, alsa_buffer_size - alsa_period_size, + alsa_period_size); FormatDebug(alsa_output_domain, "buffer_size=%u period_size=%u", (unsigned)alsa_buffer_size, (unsigned)alsa_period_size); @@ -618,231 +690,250 @@ happen again. */ alsa_period_size = 1; - ad->period_frames = alsa_period_size; - ad->period_position = 0; + period_frames = alsa_period_size; + period_position = 0; - ad->silence = new uint8_t[snd_pcm_frames_to_bytes(ad->pcm, - alsa_period_size)]; - snd_pcm_format_set_silence(format, ad->silence, - alsa_period_size * channels); + silence = new uint8_t[snd_pcm_frames_to_bytes(pcm, alsa_period_size)]; + snd_pcm_format_set_silence(format, silence, + alsa_period_size * audio_format.channels); - return true; - -error: - error.Format(alsa_output_domain, err, - "Error opening ALSA device \"%s\" (%s): %s", - alsa_device(ad), cmd, snd_strerror(-err)); - return false; } -static bool -alsa_setup_dop(AlsaOutput *ad, const AudioFormat audio_format, - bool *shift8_r, bool *packed_r, bool *reverse_endian_r, - Error &error) +#ifdef ENABLE_DSD + +inline void +AlsaOutput::SetupDop(const AudioFormat audio_format, + PcmExport::Params ¶ms) { - assert(ad->dop); + assert(dop); assert(audio_format.format == SampleFormat::DSD); - /* pass 24 bit to alsa_setup() */ + /* pass 24 bit to AlsaSetup() */ AudioFormat dop_format = audio_format; dop_format.format = SampleFormat::S24_P32; - dop_format.sample_rate /= 2; const AudioFormat check = dop_format; - if (!alsa_setup(ad, dop_format, packed_r, reverse_endian_r, error)) - return false; + Setup(dop_format, params); /* if the device allows only 32 bit, shift all DoP samples left by 8 bit and leave the lower 8 bit cleared; the DSD-over-USB documentation does not specify whether this is legal, but there is anecdotical evidence that this is possible (and the only option for some devices) */ - *shift8_r = dop_format.format == SampleFormat::S32; + params.shift8 = dop_format.format == SampleFormat::S32; if (dop_format.format == SampleFormat::S32) dop_format.format = SampleFormat::S24_P32; if (dop_format != check) { /* no bit-perfect playback, which is required for DSD over USB */ - error.Format(alsa_output_domain, - "Failed to configure DSD-over-PCM on ALSA device \"%s\"", - alsa_device(ad)); - delete[] ad->silence; - return false; + delete[] silence; + throw std::runtime_error("Failed to configure DSD-over-PCM"); } - - return true; } -static bool -alsa_setup_or_dop(AlsaOutput *ad, AudioFormat &audio_format, - Error &error) -{ - bool shift8 = false, packed, reverse_endian; +#endif - const bool dop = ad->dop && - audio_format.format == SampleFormat::DSD; - const bool success = dop - ? alsa_setup_dop(ad, audio_format, - &shift8, &packed, &reverse_endian, - error) - : alsa_setup(ad, audio_format, &packed, &reverse_endian, - error); - if (!success) - return false; +inline void +AlsaOutput::SetupOrDop(AudioFormat &audio_format, PcmExport::Params ¶ms) +{ +#ifdef ENABLE_DSD + std::exception_ptr dop_error; + if (dop && audio_format.format == SampleFormat::DSD) { + try { + params.dop = true; + SetupDop(audio_format, params); + return; + } catch (...) { + dop_error = std::current_exception(); + params.dop = false; + } + } - ad->pcm_export->Open(audio_format.format, - audio_format.channels, - dop, shift8, packed, reverse_endian); - return true; + try { +#endif + Setup(audio_format, params); +#ifdef ENABLE_DSD + } catch (...) { + if (dop_error) + /* if DoP was attempted, prefer returning the + original DoP error instead of the fallback + error */ + std::rethrow_exception(dop_error); + else + throw; + } +#endif } -static bool -alsa_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) +inline void +AlsaOutput::Open(AudioFormat &audio_format) { - AlsaOutput *ad = (AlsaOutput *)ao; - - int err = snd_pcm_open(&ad->pcm, alsa_device(ad), - SND_PCM_STREAM_PLAYBACK, ad->mode); - if (err < 0) { - error.Format(alsa_output_domain, err, - "Failed to open ALSA device \"%s\": %s", - alsa_device(ad), snd_strerror(err)); - return false; - } + int err = snd_pcm_open(&pcm, GetDevice(), + SND_PCM_STREAM_PLAYBACK, mode); + if (err < 0) + throw FormatRuntimeError("Failed to open ALSA device \"%s\": %s", + GetDevice(), snd_strerror(err)); FormatDebug(alsa_output_domain, "opened %s type=%s", - snd_pcm_name(ad->pcm), - snd_pcm_type_name(snd_pcm_type(ad->pcm))); + snd_pcm_name(pcm), + snd_pcm_type_name(snd_pcm_type(pcm))); - if (!alsa_setup_or_dop(ad, audio_format, error)) { - snd_pcm_close(ad->pcm); - return false; - } + PcmExport::Params params; + params.alsa_channel_order = true; - ad->in_frame_size = audio_format.GetFrameSize(); - ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format); + try { + SetupOrDop(audio_format, params); + } catch (...) { + snd_pcm_close(pcm); + std::throw_with_nested(FormatRuntimeError("Error opening ALSA device \"%s\"", + GetDevice())); + } + +#ifdef ENABLE_DSD + if (params.dop) + FormatDebug(alsa_output_domain, "DoP (DSD over PCM) enabled"); +#endif - ad->must_prepare = false; + pcm_export->Open(audio_format.format, + audio_format.channels, + params); - return true; -} + in_frame_size = audio_format.GetFrameSize(); + out_frame_size = pcm_export->GetFrameSize(audio_format); -/** - * Write silence to the ALSA device. - */ -static void -alsa_write_silence(AlsaOutput *ad, snd_pcm_uframes_t nframes) -{ - ad->writei(ad->pcm, ad->silence, nframes); + must_prepare = false; } -static int -alsa_recover(AlsaOutput *ad, int err) +inline int +AlsaOutput::Recover(int err) { if (err == -EPIPE) { FormatDebug(alsa_output_domain, - "Underrun on ALSA device \"%s\"", alsa_device(ad)); + "Underrun on ALSA device \"%s\"", + GetDevice()); } else if (err == -ESTRPIPE) { FormatDebug(alsa_output_domain, "ALSA device \"%s\" was suspended", - alsa_device(ad)); + GetDevice()); } - switch (snd_pcm_state(ad->pcm)) { + switch (snd_pcm_state(pcm)) { case SND_PCM_STATE_PAUSED: - err = snd_pcm_pause(ad->pcm, /* disable */ 0); + err = snd_pcm_pause(pcm, /* disable */ 0); break; case SND_PCM_STATE_SUSPENDED: - err = snd_pcm_resume(ad->pcm); + err = snd_pcm_resume(pcm); if (err == -EAGAIN) return 0; /* fall-through to snd_pcm_prepare: */ #if GCC_CHECK_VERSION(7,0) [[fallthrough]]; #endif + case SND_PCM_STATE_OPEN: case SND_PCM_STATE_SETUP: case SND_PCM_STATE_XRUN: - ad->period_position = 0; - err = snd_pcm_prepare(ad->pcm); + period_position = 0; + err = snd_pcm_prepare(pcm); break; case SND_PCM_STATE_DISCONNECTED: break; /* this is no error, so just keep running */ + case SND_PCM_STATE_PREPARED: case SND_PCM_STATE_RUNNING: + case SND_PCM_STATE_DRAINING: err = 0; break; - default: - /* unknown state, do nothing */ - break; } return err; } -static void -alsa_drain(AudioOutput *ao) +inline void +AlsaOutput::Drain() { - AlsaOutput *ad = (AlsaOutput *)ao; - - if (snd_pcm_state(ad->pcm) != SND_PCM_STATE_RUNNING) + if (snd_pcm_state(pcm) != SND_PCM_STATE_RUNNING) return; - if (ad->period_position > 0) { + if (period_position > 0) { /* generate some silence to finish the partial period */ snd_pcm_uframes_t nframes = - ad->period_frames - ad->period_position; - alsa_write_silence(ad, nframes); + period_frames - period_position; + WriteSilence(nframes); } - snd_pcm_drain(ad->pcm); + snd_pcm_drain(pcm); - ad->period_position = 0; + period_position = 0; } -static void -alsa_cancel(AudioOutput *ao) +inline void +AlsaOutput::Cancel() { - AlsaOutput *ad = (AlsaOutput *)ao; + period_position = 0; + must_prepare = true; - ad->period_position = 0; - ad->must_prepare = true; + snd_pcm_drop(pcm); - snd_pcm_drop(ad->pcm); + pcm_export->Reset(); } -static void -alsa_close(AudioOutput *ao) +inline void +AlsaOutput::Close() { - AlsaOutput *ad = (AlsaOutput *)ao; - - snd_pcm_close(ad->pcm); - delete[] ad->silence; + snd_pcm_close(pcm); + delete[] silence; } -static size_t -alsa_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +AlsaOutput::PlayRaw(ConstBuffer data) { - AlsaOutput *ad = (AlsaOutput *)ao; + if (data.IsEmpty()) + return 0; - assert(size > 0); - assert(size % ad->in_frame_size == 0); + assert(data.size % out_frame_size == 0); - if (ad->must_prepare) { - ad->must_prepare = false; + const size_t n_frames = data.size / out_frame_size; + assert(n_frames > 0); - int err = snd_pcm_prepare(ad->pcm); - if (err < 0) { - error.Set(alsa_output_domain, err, snd_strerror(-err)); - return 0; + while (true) { + const auto frames_written = snd_pcm_writei(pcm, data.data, + n_frames); + if (frames_written > 0) { + period_position = (period_position + frames_written) + % period_frames; + + return frames_written * out_frame_size; } + + if (frames_written < 0 && frames_written != -EAGAIN && + frames_written != -EINTR && + Recover(frames_written) < 0) + throw FormatRuntimeError("snd_pcm_writei() failed: %s", + snd_strerror(-frames_written)); + } + +} + +inline size_t +AlsaOutput::Play(const void *chunk, size_t size) +{ + assert(size > 0); + assert(size % in_frame_size == 0); + + if (must_prepare) { + must_prepare = false; + + int err = snd_pcm_prepare(pcm); + if (err < 0) + throw FormatRuntimeError("snd_pcm_prepare() failed: %s", + snd_strerror(-err)); } - const auto e = ad->pcm_export->Export({chunk, size}); + const auto e = pcm_export->Export({chunk, size}); if (e.size == 0) /* the DoP (DSD over PCM) filter converts two frames at a time and ignores the last odd frame; if there @@ -852,46 +943,26 @@ been played */ return size; - chunk = e.data; - size = e.size; - - assert(size % ad->out_frame_size == 0); - - size /= ad->out_frame_size; - assert(size > 0); - - while (true) { - snd_pcm_sframes_t ret = ad->writei(ad->pcm, chunk, size); - if (ret > 0) { - ad->period_position = (ad->period_position + ret) - % ad->period_frames; - - size_t bytes_written = ret * ad->out_frame_size; - return ad->pcm_export->CalcSourceSize(bytes_written); - } - - if (ret < 0 && ret != -EAGAIN && ret != -EINTR && - alsa_recover(ad, ret) < 0) { - error.Set(alsa_output_domain, ret, snd_strerror(-ret)); - return 0; - } - } + const size_t bytes_written = PlayRaw(e); + return pcm_export->CalcSourceSize(bytes_written); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin alsa_output_plugin = { "alsa", alsa_test_default_device, - alsa_init, - alsa_finish, - alsa_output_enable, - alsa_output_disable, - alsa_open, - alsa_close, + &Wrapper::Init, + &Wrapper::Finish, + &Wrapper::Enable, + &Wrapper::Disable, + &Wrapper::Open, + &Wrapper::Close, nullptr, nullptr, - alsa_play, - alsa_drain, - alsa_cancel, + &Wrapper::Play, + &Wrapper::Drain, + &Wrapper::Cancel, nullptr, &alsa_mixer_plugin, diff -Nru mpd-0.19.21/src/output/plugins/AlsaOutputPlugin.hxx mpd-0.20.9/src/output/plugins/AlsaOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/AlsaOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/AlsaOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/AoOutputPlugin.cxx mpd-0.20.9/src/output/plugins/AoOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/AoOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/AoOutputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,12 +20,14 @@ #include "config.h" #include "AoOutputPlugin.hxx" #include "../OutputAPI.hxx" -#include "util/Error.hxx" +#include "system/Error.hxx" +#include "util/DivideString.hxx" +#include "util/SplitString.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include -#include #include @@ -37,27 +39,21 @@ struct AoOutput { AudioOutput base; - size_t write_size; + const size_t write_size; int driver; - ao_option *options; + ao_option *options = nullptr; ao_device *device; - AoOutput() - :base(ao_output_plugin) {} - - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); - } - - bool Configure(const config_param ¶m, Error &error); + AoOutput(const ConfigBlock &block); }; static constexpr Domain ao_output_domain("ao_output"); -static void -ao_output_error(Error &error_r) + +static std::system_error +MakeAoError() { - const char *error; + const char *error = "Unknown libao failure"; switch (errno) { case AO_ENODRIVER: @@ -79,93 +75,55 @@ case AO_EFAIL: error = "Generic libao failure"; break; - - default: - error_r.SetErrno(); - return; } - error_r.Set(ao_output_domain, errno, error); + return MakeErrno(errno, error); } -inline bool -AoOutput::Configure(const config_param ¶m, Error &error) +AoOutput::AoOutput(const ConfigBlock &block) + :base(ao_output_plugin, block), + write_size(block.GetBlockValue("write_size", 1024u)) { - const char *value; - - options = nullptr; - - write_size = param.GetBlockValue("write_size", 1024u); - if (ao_output_ref == 0) { ao_initialize(); } ao_output_ref++; - value = param.GetBlockValue("driver", "default"); + const char *value = block.GetBlockValue("driver", "default"); if (0 == strcmp(value, "default")) driver = ao_default_driver_id(); else driver = ao_driver_id(value); - if (driver < 0) { - error.Format(ao_output_domain, - "\"%s\" is not a valid ao driver", - value); - return false; - } + if (driver < 0) + throw FormatRuntimeError("\"%s\" is not a valid ao driver", + value); ao_info *ai = ao_driver_info(driver); - if (ai == nullptr) { - error.Set(ao_output_domain, "problems getting driver info"); - return false; - } + if (ai == nullptr) + throw std::runtime_error("problems getting driver info"); FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n", - ai->short_name, param.GetBlockValue("name", nullptr)); + ai->short_name, block.GetBlockValue("name", nullptr)); - value = param.GetBlockValue("options", nullptr); + value = block.GetBlockValue("options", nullptr); if (value != nullptr) { - gchar **_options = g_strsplit(value, ";", 0); - - for (unsigned i = 0; _options[i] != nullptr; ++i) { - gchar **key_value = g_strsplit(_options[i], "=", 2); + for (const auto &i : SplitString(value, ';')) { + const DivideString ss(i.c_str(), '=', true); - if (key_value[0] == nullptr || key_value[1] == nullptr) { - error.Format(ao_output_domain, - "problems parsing options \"%s\"", - _options[i]); - return false; - } + if (!ss.IsDefined()) + throw FormatRuntimeError("problems parsing options \"%s\"", + i.c_str()); - ao_append_option(&options, key_value[0], - key_value[1]); - - g_strfreev(key_value); + ao_append_option(&options, ss.GetFirst(), ss.GetSecond()); } - - g_strfreev(_options); } - - return true; } static AudioOutput * -ao_output_init(const config_param ¶m, Error &error) +ao_output_init(const ConfigBlock &block) { - AoOutput *ad = new AoOutput(); - - if (!ad->Initialize(param, error)) { - delete ad; - return nullptr; - } - - if (!ad->Configure(param, error)) { - delete ad; - return nullptr; - } - - return &ad->base; + return &(new AoOutput(block))->base; } static void @@ -190,9 +148,8 @@ ao_close(ad->device); } -static bool -ao_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +static void +ao_output_open(AudioOutput *ao, AudioFormat &audio_format) { ao_sample_format format = OUR_AO_FORMAT_INITIALIZER; AoOutput *ad = (AoOutput *)ao; @@ -221,12 +178,8 @@ ad->device = ao_open_live(ad->driver, &format, ad->options); - if (ad->device == nullptr) { - ao_output_error(error); - return false; - } - - return true; + if (ad->device == nullptr) + throw MakeAoError(); } /** @@ -247,18 +200,15 @@ } static size_t -ao_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +ao_output_play(AudioOutput *ao, const void *chunk, size_t size) { AoOutput *ad = (AoOutput *)ao; if (size > ad->write_size) size = ad->write_size; - if (ao_play_deconst(ad->device, chunk, size) == 0) { - ao_output_error(error); - return 0; - } + if (ao_play_deconst(ad->device, chunk, size) == 0) + throw MakeAoError(); return size; } diff -Nru mpd-0.19.21/src/output/plugins/AoOutputPlugin.hxx mpd-0.20.9/src/output/plugins/AoOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/AoOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/AoOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/FifoOutputPlugin.cxx mpd-0.20.9/src/output/plugins/FifoOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/FifoOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/FifoOutputPlugin.cxx 2017-05-08 15:10:30.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,13 +19,14 @@ #include "config.h" #include "FifoOutputPlugin.hxx" -#include "config/ConfigError.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "../Timer.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" -#include "util/Error.hxx" +#include "fs/FileInfo.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include "open.h" @@ -33,48 +34,67 @@ #include #include -#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */ +class FifoOutput { + friend struct AudioOutputWrapper; -struct FifoOutput { AudioOutput base; - AllocatedPath path; + const AllocatedPath path; std::string path_utf8; - int input; - int output; - bool created; + int input = -1; + int output = -1; + bool created = false; Timer *timer; - FifoOutput() - :base(fifo_output_plugin), - path(AllocatedPath::Null()), input(-1), output(-1), - created(false) {} +public: + FifoOutput(const ConfigBlock &block); - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); + ~FifoOutput() { + CloseFifo(); } - bool Create(Error &error); - bool Check(Error &error); + static FifoOutput *Create(const ConfigBlock &block); + + void Create(); + void Check(); void Delete(); - bool Open(Error &error); + void OpenFifo(); + void CloseFifo(); + + void Open(AudioFormat &audio_format); void Close(); + + std::chrono::steady_clock::duration Delay() const noexcept; + size_t Play(const void *chunk, size_t size); + void Cancel(); }; static constexpr Domain fifo_output_domain("fifo_output"); +FifoOutput::FifoOutput(const ConfigBlock &block) + :base(fifo_output_plugin, block), + path(block.GetPath("path")) +{ + if (path.IsNull()) + throw std::runtime_error("No \"path\" parameter specified"); + + path_utf8 = path.ToUTF8(); + + OpenFifo(); +} + inline void FifoOutput::Delete() { FormatDebug(fifo_output_domain, "Removing FIFO \"%s\"", path_utf8.c_str()); - if (!RemoveFile(path)) { - FormatErrno(fifo_output_domain, - "Could not remove FIFO \"%s\"", - path_utf8.c_str()); + try { + RemoveFile(path); + } catch (const std::runtime_error &e) { + LogError(e, "Could not remove FIFO"); return; } @@ -82,7 +102,7 @@ } void -FifoOutput::Close() +FifoOutput::CloseFifo() { if (input >= 0) { close(input); @@ -94,180 +114,113 @@ output = -1; } - struct stat st; - if (created && StatFile(path, st)) + FileInfo fi; + if (created && GetFileInfo(path, fi)) Delete(); } -inline bool -FifoOutput::Create(Error &error) +inline void +FifoOutput::Create() { - if (!MakeFifo(path, 0666)) { - error.FormatErrno("Couldn't create FIFO \"%s\"", + if (!MakeFifo(path, 0666)) + throw FormatErrno("Couldn't create FIFO \"%s\"", path_utf8.c_str()); - return false; - } created = true; - return true; } -inline bool -FifoOutput::Check(Error &error) +inline void +FifoOutput::Check() { struct stat st; if (!StatFile(path, st)) { if (errno == ENOENT) { /* Path doesn't exist */ - return Create(error); + Create(); + return; } - error.FormatErrno("Failed to stat FIFO \"%s\"", + throw FormatErrno("Failed to stat FIFO \"%s\"", path_utf8.c_str()); - return false; - } - - if (!S_ISFIFO(st.st_mode)) { - error.Format(fifo_output_domain, - "\"%s\" already exists, but is not a FIFO", - path_utf8.c_str()); - return false; } - return true; + if (!S_ISFIFO(st.st_mode)) + throw FormatRuntimeError("\"%s\" already exists, but is not a FIFO", + path_utf8.c_str()); } -inline bool -FifoOutput::Open(Error &error) -{ - if (!Check(error)) - return false; +inline void +FifoOutput::OpenFifo() +try { + Check(); input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); - if (input < 0) { - error.FormatErrno("Could not open FIFO \"%s\" for reading", + if (input < 0) + throw FormatErrno("Could not open FIFO \"%s\" for reading", path_utf8.c_str()); - Close(); - return false; - } output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); - if (output < 0) { - error.FormatErrno("Could not open FIFO \"%s\" for writing", + if (output < 0) + throw FormatErrno("Could not open FIFO \"%s\" for writing", path_utf8.c_str()); - Close(); - return false; - } - - return true; -} - -static bool -fifo_open(FifoOutput *fd, Error &error) -{ - return fd->Open(error); -} - -static AudioOutput * -fifo_output_init(const config_param ¶m, Error &error) -{ - FifoOutput *fd = new FifoOutput(); - - fd->path = param.GetBlockPath("path", error); - if (fd->path.IsNull()) { - delete fd; - - if (!error.IsDefined()) - error.Set(config_domain, - "No \"path\" parameter specified"); - return nullptr; - } - - fd->path_utf8 = fd->path.ToUTF8(); - - if (!fd->Initialize(param, error)) { - delete fd; - return nullptr; - } - - if (!fifo_open(fd, error)) { - delete fd; - return nullptr; - } - - return &fd->base; +} catch (...) { + CloseFifo(); + throw; } -static void -fifo_output_finish(AudioOutput *ao) +inline FifoOutput * +FifoOutput::Create(const ConfigBlock &block) { - FifoOutput *fd = (FifoOutput *)ao; - - fd->Close(); - delete fd; + return new FifoOutput(block); } -static bool -fifo_output_open(AudioOutput *ao, AudioFormat &audio_format, - gcc_unused Error &error) +void +FifoOutput::Open(AudioFormat &audio_format) { - FifoOutput *fd = (FifoOutput *)ao; - - fd->timer = new Timer(audio_format); - - return true; + timer = new Timer(audio_format); } -static void -fifo_output_close(AudioOutput *ao) +void +FifoOutput::Close() { - FifoOutput *fd = (FifoOutput *)ao; - - delete fd->timer; + delete timer; } -static void -fifo_output_cancel(AudioOutput *ao) +inline void +FifoOutput::Cancel() { - FifoOutput *fd = (FifoOutput *)ao; - char buf[FIFO_BUFFER_SIZE]; - int bytes = 1; - - fd->timer->Reset(); + timer->Reset(); - while (bytes > 0 && errno != EINTR) - bytes = read(fd->input, buf, FIFO_BUFFER_SIZE); + ssize_t bytes; + do { + char buffer[16384]; + bytes = read(input, buffer, sizeof(buffer)); + } while (bytes > 0 && errno != EINTR); if (bytes < 0 && errno != EAGAIN) { FormatErrno(fifo_output_domain, "Flush of FIFO \"%s\" failed", - fd->path_utf8.c_str()); + path_utf8.c_str()); } } -static unsigned -fifo_output_delay(AudioOutput *ao) +inline std::chrono::steady_clock::duration +FifoOutput::Delay() const noexcept { - FifoOutput *fd = (FifoOutput *)ao; - - return fd->timer->IsStarted() - ? fd->timer->GetDelay() - : 0; + return timer->IsStarted() + ? timer->GetDelay() + : std::chrono::steady_clock::duration::zero(); } -static size_t -fifo_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +FifoOutput::Play(const void *chunk, size_t size) { - FifoOutput *fd = (FifoOutput *)ao; - ssize_t bytes; - - if (!fd->timer->IsStarted()) - fd->timer->Start(); - fd->timer->Add(size); + if (!timer->IsStarted()) + timer->Start(); + timer->Add(size); while (true) { - bytes = write(fd->output, chunk, size); + ssize_t bytes = write(output, chunk, size); if (bytes > 0) return (size_t)bytes; @@ -275,33 +228,34 @@ switch (errno) { case EAGAIN: /* The pipe is full, so empty it */ - fifo_output_cancel(&fd->base); + Cancel(); continue; case EINTR: continue; } - error.FormatErrno("Failed to write to FIFO %s", - fd->path_utf8.c_str()); - return 0; + throw FormatErrno("Failed to write to FIFO %s", + path_utf8.c_str()); } } } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin fifo_output_plugin = { "fifo", nullptr, - fifo_output_init, - fifo_output_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - fifo_output_open, - fifo_output_close, - fifo_output_delay, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - fifo_output_play, + &Wrapper::Play, nullptr, - fifo_output_cancel, + &Wrapper::Cancel, nullptr, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/FifoOutputPlugin.hxx mpd-0.20.9/src/output/plugins/FifoOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/FifoOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/FifoOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/HaikuOutputPlugin.cxx mpd-0.20.9/src/output/plugins/HaikuOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/HaikuOutputPlugin.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/HaikuOutputPlugin.cxx 2017-05-16 05:11:47.000000000 +0000 @@ -0,0 +1,482 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * Copyright (C) 2014-2015 François 'mmu_man' Revol + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "HaikuOutputPlugin.hxx" +#include "../OutputAPI.hxx" +#include "../Wrapper.hxx" +#include "mixer/MixerList.hxx" +#include "util/Domain.hxx" +#include "Log.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define UTF8_PLAY "\xE2\x96\xB6" + +class HaikuOutput { + friend struct AudioOutputWrapper; + friend int haiku_output_get_volume(HaikuOutput &haiku); + friend bool haiku_output_set_volume(HaikuOutput &haiku, unsigned volume); + + AudioOutput base; + + size_t write_size; + + media_raw_audio_format format; + BSoundPlayer* sound_player; + + sem_id new_buffer; + sem_id buffer_done; + + uint8* buffer; + size_t buffer_size; + size_t buffer_filled; + + unsigned buffer_delay; + +public: + HaikuOutput(const ConfigBlock &block) + :base(haiku_output_plugin, block), + /* XXX: by default we should let the MediaKit propose the buffer size */ + write_size(block.GetBlockValue("write_size", 4096u)) {} + + ~HaikuOutput(); + + static HaikuOutput *Create(const ConfigBlock &block); + + void Open(AudioFormat &audio_format); + void Close(); + + size_t Play(const void *chunk, size_t size); + void Cancel(); + + std::chrono::steady_clock::duration Delay() noexcept; + + void FillBuffer(void* _buffer, size_t size, + gcc_unused const media_raw_audio_format& _format); + + void SendTag(const Tag &tag); +}; + +static constexpr Domain haiku_output_domain("haiku_output"); + +static void +initialize_application() +{ + // required to send the notification with a bitmap + // TODO: actually Run() it and handle B_QUIT_REQUESTED + // TODO: use some locking? + if (be_app == NULL) { + FormatDebug(haiku_output_domain, "creating be_app\n"); + new BApplication("application/x-vnd.MusicPD"); + } +} + +static void +finalize_application() +{ + // TODO: use some locking? + delete be_app; + be_app = NULL; + FormatDebug(haiku_output_domain, "deleting be_app\n"); +} + +static bool +haiku_test_default_device(void) +{ + BSoundPlayer testPlayer; + return testPlayer.InitCheck() == B_OK; + +} + +inline HaikuOutput * +HaikuOutput::Create(const ConfigBlock &block) +{ + initialize_application(); + + return new HaikuOutput(block); +} + +void +HaikuOutput::Close() +{ + sound_player->SetHasData(false); + delete_sem(new_buffer); + delete_sem(buffer_done); + sound_player->Stop(); + delete sound_player; + sound_player = nullptr; +} + + + +HaikuOutput::~HaikuOutput() +{ + delete_sem(new_buffer); + delete_sem(buffer_done); + + finalize_application(); +} + +static void +fill_buffer(void* cookie, void* buffer, size_t size, + const media_raw_audio_format& format) +{ + HaikuOutput *ad = (HaikuOutput *)cookie; + ad->FillBuffer(buffer, size, format); +} + + +void +HaikuOutput::FillBuffer(void* _buffer, size_t size, + gcc_unused const media_raw_audio_format& _format) +{ + + buffer = (uint8*)_buffer; + buffer_size = size; + buffer_filled = 0; + bigtime_t start = system_time(); + release_sem(new_buffer); + acquire_sem(buffer_done); + bigtime_t w = system_time() - start; + + if (w > 5000LL) { + FormatDebug(haiku_output_domain, + "haiku:fill_buffer waited %Ldus\n", w); + } + + if (buffer_filled < buffer_size) { + memset(buffer + buffer_filled, 0, + buffer_size - buffer_filled); + FormatDebug(haiku_output_domain, + "haiku:fill_buffer filled %d size %d clearing remainder\n", + (int)buffer_filled, (int)buffer_size); + + } +} + +inline void +HaikuOutput::Open(AudioFormat &audio_format) +{ + status_t err; + format = media_multi_audio_format::wildcard; + + switch (audio_format.format) { + case SampleFormat::S8: + format.format = media_raw_audio_format::B_AUDIO_CHAR; + break; + + case SampleFormat::S16: + format.format = media_raw_audio_format::B_AUDIO_SHORT; + break; + + case SampleFormat::S32: + format.format = media_raw_audio_format::B_AUDIO_INT; + break; + + case SampleFormat::FLOAT: + format.format = media_raw_audio_format::B_AUDIO_FLOAT; + break; + + default: + /* fall back to float */ + audio_format.format = SampleFormat::FLOAT; + format.format = media_raw_audio_format::B_AUDIO_FLOAT; + break; + } + + format.frame_rate = audio_format.sample_rate; + format.byte_order = B_MEDIA_HOST_ENDIAN; + format.channel_count = audio_format.channels; + + buffer_size = 0; + + if (write_size) + format.buffer_size = write_size; + else + format.buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor( + format.channel_count, format.format, + format.frame_rate, B_UNKNOWN_BUS) * 2; + + FormatDebug(haiku_output_domain, + "using haiku driver ad: bs: %d ws: %d " + "channels %d rate %f fmt %08lx bs %d\n", + (int)buffer_size, (int)write_size, + (int)format.channel_count, format.frame_rate, + format.format, (int)format.buffer_size); + + sound_player = new BSoundPlayer(&format, "MPD Output", + fill_buffer, NULL, this); + + err = sound_player->InitCheck(); + if (err != B_OK) { + delete sound_player; + sound_player = NULL; + throw MakeErrno(err, "BSoundPlayer::InitCheck() failed"); + } + + // calculate the allowable delay for the buffer (ms) + buffer_delay = format.buffer_size; + buffer_delay /= (format.format & + media_raw_audio_format::B_AUDIO_SIZE_MASK); + buffer_delay /= format.channel_count; + buffer_delay *= 1000 / format.frame_rate; + // half of the total buffer play time + buffer_delay /= 2; + FormatDebug(haiku_output_domain, + "buffer delay: %d ms\n", buffer_delay); + + new_buffer = create_sem(0, "New buffer request"); + buffer_done = create_sem(0, "Buffer done"); + + sound_player->SetVolume(1.0); + sound_player->Start(); + sound_player->SetHasData(false); +} + +inline size_t +HaikuOutput::Play(const void *chunk, size_t size) +{ + BSoundPlayer* const soundPlayer = sound_player; + const uint8 *data = (const uint8 *)chunk; + + if (size == 0) { + soundPlayer->SetHasData(false); + return 0; + } + + if (!soundPlayer->HasData()) + soundPlayer->SetHasData(true); + acquire_sem(new_buffer); + + size_t bytesLeft = size; + while (bytesLeft > 0) { + if (buffer_filled == buffer_size) { + // Request another buffer from BSoundPlayer + release_sem(buffer_done); + acquire_sem(new_buffer); + } + + const size_t copyBytes = std::min(bytesLeft, buffer_size + - buffer_filled); + memcpy(buffer + buffer_filled, data, + copyBytes); + buffer_filled += copyBytes; + data += copyBytes; + bytesLeft -= copyBytes; + } + + + if (buffer_filled < buffer_size) { + // Continue filling this buffer the next time this function is called + release_sem(new_buffer); + } else { + // Buffer is full + release_sem(buffer_done); + //soundPlayer->SetHasData(false); + } + + return size; +} + +inline std::chrono::steady_clock::duration +HaikuOutput::Delay() noexcept +{ + unsigned delay = buffer_filled ? 0 : buffer_delay; + + //FormatDebug(haiku_output_domain, + // "delay=%d\n", delay / 2); + // XXX: doesn't work + //return (delay / 2) ? 1 : 0; + (void)delay; + + return std::chrono::steady_clock::duration::zero(); +} + +inline void +HaikuOutput::SendTag(const Tag &tag) +{ + status_t err; + + /* lazily initialized */ + static BBitmap *icon = NULL; + + if (icon == NULL) { + BAppFileInfo info; + BResources resources; + err = resources.SetToImage((const void *)&HaikuOutput::SendTag); + BFile file(resources.File()); + err = info.SetTo(&file); + icon = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1, + (float)B_LARGE_ICON - 1), B_BITMAP_NO_SERVER_LINK, B_RGBA32); + err = info.GetIcon(icon, B_LARGE_ICON); + if (err != B_OK) { + delete icon; + icon = NULL; + } + } + + BNotification notification(B_INFORMATION_NOTIFICATION); + + BString messageId("mpd_"); + messageId << find_thread(NULL); + notification.SetMessageID(messageId); + + notification.SetGroup("Music Player Daemon"); + + char timebuf[16]; + unsigned seconds = 0; + if (!tag.duration.IsNegative()) { + seconds = tag.duration.ToS(); + snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d", + seconds / 3600, (seconds % 3600) / 60, seconds % 60); + } + + BString artist; + BString album; + BString title; + BString track; + BString name; + + for (const auto &item : tag) + { + switch (item.type) { + case TAG_ARTIST: + case TAG_ALBUM_ARTIST: + if (artist.Length() == 0) + artist << item.value; + break; + case TAG_ALBUM: + if (album.Length() == 0) + album << item.value; + break; + case TAG_TITLE: + if (title.Length() == 0) + title << item.value; + break; + case TAG_TRACK: + if (track.Length() == 0) + track << item.value; + break; + case TAG_NAME: + if (name.Length() == 0) + name << item.value; + break; + case TAG_GENRE: + case TAG_DATE: + case TAG_PERFORMER: + case TAG_COMMENT: + case TAG_DISC: + case TAG_COMPOSER: + case TAG_MUSICBRAINZ_ARTISTID: + case TAG_MUSICBRAINZ_ALBUMID: + case TAG_MUSICBRAINZ_ALBUMARTISTID: + case TAG_MUSICBRAINZ_TRACKID: + default: + FormatDebug(haiku_output_domain, + "tag item: type %d value '%s'\n", item.type, item.value); + break; + } + } + + notification.SetTitle(UTF8_PLAY " Now Playing:"); + + BStringList content; + if (name.Length()) + content.Add(name); + if (artist.Length()) + content.Add(artist); + if (album.Length()) + content.Add(album); + if (track.Length()) + content.Add(track); + if (title.Length()) + content.Add(title); + + if (content.CountStrings() == 0) + content.Add("(Unknown)"); + + BString full = content.Join(" " B_UTF8_BULLET " "); + + if (seconds > 0) + full << " (" << timebuf << ")"; + + notification.SetContent(full); + + err = notification.SetIcon(icon); + + notification.Send(); +} + +int +haiku_output_get_volume(HaikuOutput &haiku) +{ + BSoundPlayer* const soundPlayer = haiku.sound_player; + + if (soundPlayer == NULL || soundPlayer->InitCheck() != B_OK) + return 0; + + return (int)(soundPlayer->Volume() * 100 + 0.5); +} + +bool +haiku_output_set_volume(HaikuOutput &haiku, unsigned volume) +{ + BSoundPlayer* const soundPlayer = haiku.sound_player; + + if (soundPlayer == NULL || soundPlayer->InitCheck() != B_OK) + return false; + + soundPlayer->SetVolume((float)volume / 100); + return true; +} + +typedef AudioOutputWrapper Wrapper; + +const struct AudioOutputPlugin haiku_output_plugin = { + "haiku", + haiku_test_default_device, + &Wrapper::Init, + &Wrapper::Finish, + nullptr, + nullptr, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, + &Wrapper::SendTag, + &Wrapper::Play, + nullptr, + nullptr, + nullptr, + + &haiku_mixer_plugin, +}; diff -Nru mpd-0.19.21/src/output/plugins/HaikuOutputPlugin.hxx mpd-0.20.9/src/output/plugins/HaikuOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/HaikuOutputPlugin.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/HaikuOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * Copyright (C) 2014-2015 François 'mmu_man' Revol + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_HAIKU_OUTPUT_PLUGIN_HXX +#define MPD_HAIKU_OUTPUT_PLUGIN_HXX + +class HaikuOutput; + +extern const struct AudioOutputPlugin haiku_output_plugin; + +int +haiku_output_get_volume(HaikuOutput &haiku); + +bool +haiku_output_set_volume(HaikuOutput &haiku, unsigned volume); + +#endif diff -Nru mpd-0.19.21/src/output/plugins/httpd/HttpdClient.cxx mpd-0.20.9/src/output/plugins/httpd/HttpdClient.cxx --- mpd-0.19.21/src/output/plugins/httpd/HttpdClient.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/HttpdClient.cxx 2017-05-08 15:12:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,9 +21,10 @@ #include "HttpdClient.hxx" #include "HttpdInternal.hxx" #include "util/ASCII.hxx" +#include "util/AllocatedString.hxx" #include "Page.hxx" #include "IcyMetaDataServer.hxx" -#include "system/SocketError.hxx" +#include "net/SocketError.hxx" #include "Log.hxx" #include @@ -55,7 +56,7 @@ void HttpdClient::LockClose() { - const ScopeLock protect(httpd.mutex); + const std::lock_guard protect(httpd.mutex); Close(); } @@ -141,7 +142,8 @@ bool HttpdClient::SendResponse() { - char buffer[1024], *allocated = nullptr; + char buffer[1024]; + AllocatedString<> allocated = nullptr; const char *response; assert(state == RESPONSE); @@ -162,11 +164,12 @@ response = buffer; } else if (metadata_requested) { - response = allocated = + allocated = icy_server_metadata_header(httpd.name, httpd.genre, httpd.website, httpd.content_type, metaint); + response = allocated.c_str(); } else { /* revert to a normal HTTP request */ snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\n" @@ -180,7 +183,6 @@ } ssize_t nbytes = SocketMonitor::Write(response, strlen(response)); - delete[] allocated; if (gcc_unlikely(nbytes < 0)) { const SocketErrorMessage msg; FormatWarning(httpd_output_domain, @@ -258,7 +260,7 @@ } ssize_t -HttpdClient::GetBytesTillMetaData() const +HttpdClient::GetBytesTillMetaData() const noexcept { if (metadata_requested && current_page->size - current_position > metaint - metadata_fill) @@ -270,7 +272,7 @@ inline bool HttpdClient::TryWrite() { - const ScopeLock protect(httpd.mutex); + const std::lock_guard protect(httpd.mutex); assert(state == RESPONSE); @@ -472,9 +474,9 @@ } void -HttpdClient::OnSocketError(Error &&error) +HttpdClient::OnSocketError(std::exception_ptr ep) { - LogError(error); + LogError(ep); } void diff -Nru mpd-0.19.21/src/output/plugins/httpd/HttpdClient.hxx mpd-0.20.9/src/output/plugins/httpd/HttpdClient.hxx --- mpd-0.19.21/src/output/plugins/httpd/HttpdClient.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/HttpdClient.hxx 2017-05-08 15:12:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,6 +23,9 @@ #include "event/BufferedSocket.hxx" #include "Compiler.h" +#include +#include + #include #include @@ -31,7 +34,9 @@ class HttpdOutput; class Page; -class HttpdClient final : BufferedSocket { +class HttpdClient final + : BufferedSocket, + public boost::intrusive::list_base_hook> { /** * The httpd output object this client is connected to. */ @@ -124,7 +129,7 @@ public: /** * @param httpd the HTTP output device - * @param fd the socket file descriptor + * @param _fd the socket file descriptor */ HttpdClient(HttpdOutput &httpd, int _fd, EventLoop &_loop, bool _metadata_supported); @@ -163,7 +168,7 @@ bool SendResponse(); gcc_pure - ssize_t GetBytesTillMetaData() const; + ssize_t GetBytesTillMetaData() const noexcept; ssize_t TryWritePage(const Page &page, size_t position); ssize_t TryWritePageN(const Page &page, size_t position, ssize_t n); @@ -186,7 +191,7 @@ protected: virtual bool OnSocketReady(unsigned flags) override; virtual InputResult OnSocketInput(void *data, size_t length) override; - virtual void OnSocketError(Error &&error) override; + void OnSocketError(std::exception_ptr ep) override; virtual void OnSocketClosed() override; }; diff -Nru mpd-0.19.21/src/output/plugins/httpd/HttpdInternal.hxx mpd-0.20.9/src/output/plugins/httpd/HttpdInternal.hxx --- mpd-0.19.21/src/output/plugins/httpd/HttpdInternal.hxx 2016-08-23 07:47:48.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/HttpdInternal.hxx 2017-06-04 10:38:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -25,6 +25,7 @@ #ifndef MPD_OUTPUT_HTTPD_INTERNAL_H #define MPD_OUTPUT_HTTPD_INTERNAL_H +#include "HttpdClient.hxx" #include "output/Internal.hxx" #include "output/Timer.hxx" #include "thread/Mutex.hxx" @@ -33,22 +34,18 @@ #include "util/Cast.hxx" #include "Compiler.h" -#ifdef _LIBCPP_VERSION -/* can't use incomplete template arguments with libc++ */ -#include "HttpdClient.hxx" -#endif +#include -#include #include #include -struct config_param; -class Error; +struct ConfigBlock; class EventLoop; class ServerSocket; class HttpdClient; class Page; -struct Encoder; +class PreparedEncoder; +class Encoder; struct Tag; class HttpdOutput final : ServerSocket, DeferredMonitor { @@ -63,6 +60,7 @@ /** * The configured encoder plugin. */ + PreparedEncoder *prepared_encoder = nullptr; Encoder *encoder; /** @@ -135,7 +133,8 @@ * A linked list containing all clients which are currently * connected. */ - std::forward_list clients; + boost::intrusive::list> clients; /** * A temporary buffer for the httpd_output_read_page() @@ -147,12 +146,16 @@ * The maximum and current number of clients connected * at the same time. */ - unsigned clients_max, clients_cnt; + unsigned clients_max; public: - HttpdOutput(EventLoop &_loop); + HttpdOutput(EventLoop &_loop, const ConfigBlock &block); ~HttpdOutput(); + operator AudioOutput *() { + return &base; + } + #if CLANG_OR_GCC_VERSION(4,7) constexpr #endif @@ -162,33 +165,20 @@ using DeferredMonitor::GetEventLoop; - bool Init(const config_param ¶m, Error &error); - - bool Configure(const config_param ¶m, Error &error); - - AudioOutput *InitAndConfigure(const config_param ¶m, - Error &error) { - if (!Init(param, error)) - return nullptr; - - if (!Configure(param, error)) - return nullptr; - - return &base; - } - - bool Bind(Error &error); + void Bind(); void Unbind(); /** * Caller must lock the mutex. + * + * Throws #std::runtime_error on error. */ - bool OpenEncoder(AudioFormat &audio_format, Error &error); + void OpenEncoder(AudioFormat &audio_format); /** * Caller must lock the mutex. */ - bool Open(AudioFormat &audio_format, Error &error); + void Open(AudioFormat &audio_format); /** * Caller must lock the mutex. @@ -201,7 +191,7 @@ * Caller must lock the mutex. */ gcc_pure - bool HasClients() const { + bool HasClients() const noexcept { return !clients.empty(); } @@ -209,8 +199,8 @@ * Check whether there is at least one client. */ gcc_pure - bool LockHasClients() const { - const ScopeLock protect(mutex); + bool LockHasClients() const noexcept { + const std::lock_guard protect(mutex); return HasClients(); } @@ -228,7 +218,7 @@ void SendHeader(HttpdClient &client) const; gcc_pure - unsigned Delay() const; + std::chrono::steady_clock::duration Delay() const noexcept; /** * Reads data from the encoder (as much as available) and @@ -248,19 +238,21 @@ */ void BroadcastFromEncoder(); - bool EncodeAndPlay(const void *chunk, size_t size, Error &error); + /** + * Throws #std::runtime_error on error. + */ + void EncodeAndPlay(const void *chunk, size_t size); - void SendTag(const Tag *tag); + void SendTag(const Tag &tag); - size_t Play(const void *chunk, size_t size, Error &error); + size_t Play(const void *chunk, size_t size); void CancelAllClients(); private: virtual void RunDeferred() override; - virtual void OnAccept(int fd, const sockaddr &address, - size_t address_length, int uid) override; + void OnAccept(int fd, SocketAddress address, int uid) override; }; extern const class Domain httpd_output_domain; diff -Nru mpd-0.19.21/src/output/plugins/httpd/HttpdOutputPlugin.cxx mpd-0.20.9/src/output/plugins/httpd/HttpdOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/httpd/HttpdOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/HttpdOutputPlugin.cxx 2017-05-08 15:23:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,22 +22,23 @@ #include "HttpdInternal.hxx" #include "HttpdClient.hxx" #include "output/OutputAPI.hxx" +#include "encoder/EncoderInterface.hxx" #include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderList.hxx" -#include "system/Resolver.hxx" +#include "net/SocketAddress.hxx" +#include "net/ToString.hxx" #include "Page.hxx" #include "IcyMetaDataServer.hxx" #include "system/fd_util.h" #include "IOThread.hxx" #include "event/Call.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" +#include "util/DeleteDisposer.hxx" #include "Log.hxx" #include -#include -#include #include #include @@ -49,12 +50,43 @@ const Domain httpd_output_domain("httpd_output"); inline -HttpdOutput::HttpdOutput(EventLoop &_loop) +HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) :ServerSocket(_loop), DeferredMonitor(_loop), - base(httpd_output_plugin), + base(httpd_output_plugin, block), encoder(nullptr), unflushed_input(0), metadata(nullptr) { + /* read configuration */ + name = block.GetBlockValue("name", "Set name in config"); + genre = block.GetBlockValue("genre", "Set genre in config"); + website = block.GetBlockValue("website", "Set website in config"); + + unsigned port = block.GetBlockValue("port", 8000u); + + const char *encoder_name = + block.GetBlockValue("encoder", "vorbis"); + const auto encoder_plugin = encoder_plugin_get(encoder_name); + if (encoder_plugin == nullptr) + throw FormatRuntimeError("No such encoder: %s", encoder_name); + + clients_max = block.GetBlockValue("max_clients", 0u); + + /* set up bind_to_address */ + + const char *bind_to_address = block.GetBlockValue("bind_to_address"); + if (bind_to_address != nullptr && strcmp(bind_to_address, "any") != 0) + AddHost(bind_to_address, port); + else + AddPort(port); + + /* initialize encoder */ + + prepared_encoder = encoder_init(*encoder_plugin, block); + + /* determine content type */ + content_type = prepared_encoder->GetMimeType(); + if (content_type == nullptr) + content_type = "application/octet-stream"; } HttpdOutput::~HttpdOutput() @@ -62,21 +94,17 @@ if (metadata != nullptr) metadata->Unref(); - if (encoder != nullptr) - encoder_finish(encoder); - + delete prepared_encoder; } -inline bool -HttpdOutput::Bind(Error &error) +inline void +HttpdOutput::Bind() { open = false; - bool result = false; - BlockingCall(GetEventLoop(), [this, &error, &result](){ - result = ServerSocket::Open(error); + BlockingCall(GetEventLoop(), [this](){ + ServerSocket::Open(); }); - return result; } inline void @@ -89,67 +117,10 @@ }); } -inline bool -HttpdOutput::Configure(const config_param ¶m, Error &error) -{ - /* read configuration */ - name = param.GetBlockValue("name", "Set name in config"); - genre = param.GetBlockValue("genre", "Set genre in config"); - website = param.GetBlockValue("website", "Set website in config"); - - unsigned port = param.GetBlockValue("port", 8000u); - - const char *encoder_name = - param.GetBlockValue("encoder", "vorbis"); - const auto encoder_plugin = encoder_plugin_get(encoder_name); - if (encoder_plugin == nullptr) { - error.Format(httpd_output_domain, - "No such encoder: %s", encoder_name); - return false; - } - - clients_max = param.GetBlockValue("max_clients", 0u); - - /* set up bind_to_address */ - - const char *bind_to_address = param.GetBlockValue("bind_to_address"); - bool success = bind_to_address != nullptr && - strcmp(bind_to_address, "any") != 0 - ? AddHost(bind_to_address, port, error) - : AddPort(port, error); - if (!success) - return false; - - /* initialize encoder */ - - encoder = encoder_init(*encoder_plugin, param, error); - if (encoder == nullptr) - return false; - - /* determine content type */ - content_type = encoder_get_mime_type(encoder); - if (content_type == nullptr) - content_type = "application/octet-stream"; - - return true; -} - -inline bool -HttpdOutput::Init(const config_param ¶m, Error &error) -{ - return base.Configure(param, error); -} - static AudioOutput * -httpd_output_init(const config_param ¶m, Error &error) +httpd_output_init(const ConfigBlock &block) { - HttpdOutput *httpd = new HttpdOutput(io_thread_get()); - - AudioOutput *result = httpd->InitAndConfigure(param, error); - if (result == nullptr) - delete httpd; - - return result; + return *new HttpdOutput(io_thread_get(), block); } static void @@ -167,9 +138,9 @@ inline void HttpdOutput::AddClient(int fd) { - clients.emplace_front(*this, fd, GetEventLoop(), - encoder->plugin.tag == nullptr); - ++clients_cnt; + auto *client = new HttpdClient(*this, fd, GetEventLoop(), + !encoder->ImplementsTag()); + clients.push_front(*client); /* pass metadata to client */ if (metadata != nullptr) @@ -182,7 +153,7 @@ /* this method runs in the IOThread; it broadcasts pages from our own queue to all clients */ - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); while (!pages.empty()) { Page *page = pages.front(); @@ -200,16 +171,14 @@ } void -HttpdOutput::OnAccept(int fd, const sockaddr &address, - size_t address_length, gcc_unused int uid) +HttpdOutput::OnAccept(int fd, SocketAddress address, gcc_unused int uid) { /* the listener socket has become readable - a client has connected */ #ifdef HAVE_LIBWRAP - if (address.sa_family != AF_UNIX) { - const auto hostaddr = sockaddr_to_string(&address, - address_length); + if (address.GetFamily() != AF_UNIX) { + const auto hostaddr = ToString(address); // TODO: shall we obtain the program name from argv[0]? const char *progname = "mpd"; @@ -229,14 +198,13 @@ } #else (void)address; - (void)address_length; #endif /* HAVE_WRAP */ - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (fd >= 0) { /* can we allow additional client */ - if (open && (clients_max == 0 || clients_cnt < clients_max)) + if (open && (clients_max == 0 || clients.size() < clients_max)) AddClient(fd); else close_socket(fd); @@ -252,15 +220,19 @@ /* we have fed a lot of input into the encoder, but it didn't give anything back yet - flush now to avoid buffer underruns */ - encoder_flush(encoder, IgnoreError()); + try { + encoder->Flush(); + } catch (const std::runtime_error &) { + /* ignore */ + } + unflushed_input = 0; } size_t size = 0; do { - size_t nbytes = encoder_read(encoder, - buffer + size, - sizeof(buffer) - size); + size_t nbytes = encoder->Read(buffer + size, + sizeof(buffer) - size); if (nbytes == 0) break; @@ -275,12 +247,12 @@ return Page::Copy(buffer, size); } -static bool -httpd_output_enable(AudioOutput *ao, Error &error) +static void +httpd_output_enable(AudioOutput *ao) { HttpdOutput *httpd = HttpdOutput::Cast(ao); - return httpd->Bind(error); + httpd->Bind(); } static void @@ -291,11 +263,10 @@ httpd->Unbind(); } -inline bool -HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error) +inline void +HttpdOutput::OpenEncoder(AudioFormat &audio_format) { - if (!encoder_open(encoder, audio_format, error)) - return false; + encoder = prepared_encoder->Open(audio_format); /* we have to remember the encoder header, i.e. the first bytes of encoder output after opening it, because it has to @@ -303,39 +274,30 @@ header = ReadPage(); unflushed_input = 0; - - return true; } -inline bool -HttpdOutput::Open(AudioFormat &audio_format, Error &error) +inline void +HttpdOutput::Open(AudioFormat &audio_format) { assert(!open); assert(clients.empty()); - /* open the encoder */ - - if (!OpenEncoder(audio_format, error)) - return false; + OpenEncoder(audio_format); /* initialize other attributes */ - clients_cnt = 0; timer = new Timer(audio_format); open = true; - - return true; } -static bool -httpd_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +static void +httpd_output_open(AudioOutput *ao, AudioFormat &audio_format) { HttpdOutput *httpd = HttpdOutput::Cast(ao); - const ScopeLock protect(httpd->mutex); - return httpd->Open(audio_format, error); + const std::lock_guard protect(httpd->mutex); + httpd->Open(audio_format); } inline void @@ -348,13 +310,13 @@ delete timer; BlockingCall(GetEventLoop(), [this](){ - clients.clear(); + clients.clear_and_dispose(DeleteDisposer()); }); if (header != nullptr) header->Unref(); - encoder_close(encoder); + delete encoder; } static void @@ -362,24 +324,17 @@ { HttpdOutput *httpd = HttpdOutput::Cast(ao); - const ScopeLock protect(httpd->mutex); + const std::lock_guard protect(httpd->mutex); httpd->Close(); } void HttpdOutput::RemoveClient(HttpdClient &client) { - assert(clients_cnt > 0); + assert(!clients.empty()); - for (auto prev = clients.before_begin(), i = std::next(prev);; - prev = i, i = std::next(prev)) { - assert(i != clients.end()); - if (&*i == &client) { - clients.erase_after(prev); - clients_cnt--; - break; - } - } + clients.erase_and_dispose(clients.iterator_to(client), + DeleteDisposer()); } void @@ -389,8 +344,8 @@ client.PushPage(header); } -inline unsigned -HttpdOutput::Delay() const +inline std::chrono::steady_clock::duration +HttpdOutput::Delay() const noexcept { if (!LockHasClients() && base.pause) { /* if there's no client and this output is paused, @@ -402,16 +357,16 @@ /* some arbitrary delay that is long enough to avoid consuming too much CPU, and short enough to notice new clients quickly enough */ - return 1000; + return std::chrono::seconds(1); } return timer->IsStarted() ? timer->GetDelay() - : 0; + : std::chrono::steady_clock::duration::zero(); } -static unsigned -httpd_output_delay(AudioOutput *ao) +static std::chrono::steady_clock::duration +httpd_output_delay(AudioOutput *ao) noexcept { HttpdOutput *httpd = HttpdOutput::Cast(ao); @@ -448,25 +403,21 @@ DeferredMonitor::Schedule(); } -inline bool -HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, Error &error) +inline void +HttpdOutput::EncodeAndPlay(const void *chunk, size_t size) { - if (!encoder_write(encoder, chunk, size, error)) - return false; + encoder->Write(chunk, size); unflushed_input += size; BroadcastFromEncoder(); - return true; } inline size_t -HttpdOutput::Play(const void *chunk, size_t size, Error &error) +HttpdOutput::Play(const void *chunk, size_t size) { - if (LockHasClients()) { - if (!EncodeAndPlay(chunk, size, error)) - return 0; - } + if (LockHasClients()) + EncodeAndPlay(chunk, size); if (!timer->IsStarted()) timer->Start(); @@ -476,12 +427,11 @@ } static size_t -httpd_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +httpd_output_play(AudioOutput *ao, const void *chunk, size_t size) { HttpdOutput *httpd = HttpdOutput::Cast(ao); - return httpd->Play(chunk, size, error); + return httpd->Play(chunk, size); } static bool @@ -491,30 +441,36 @@ if (httpd->LockHasClients()) { static const char silence[1020] = { 0 }; - return httpd_output_play(ao, silence, sizeof(silence), - IgnoreError()) > 0; - } else { - return true; + httpd->Play(silence, sizeof(silence)); } + + return true; } inline void -HttpdOutput::SendTag(const Tag *tag) +HttpdOutput::SendTag(const Tag &tag) { - assert(tag != nullptr); - - if (encoder->plugin.tag != nullptr) { + if (encoder->ImplementsTag()) { /* embed encoder tags */ /* flush the current stream, and end it */ - encoder_pre_tag(encoder, IgnoreError()); + try { + encoder->PreTag(); + } catch (const std::runtime_error &) { + /* ignore */ + } + BroadcastFromEncoder(); /* send the tag to the encoder - which starts a new stream now */ - encoder_tag(encoder, tag, IgnoreError()); + try { + encoder->SendTag(tag); + } catch (const std::runtime_error &) { + /* ignore */ + } /* the first page generated by the encoder will now be used as the new "header" page, which is sent to all @@ -538,9 +494,9 @@ TAG_NUM_OF_ITEM_TYPES }; - metadata = icy_server_metadata_page(*tag, &types[0]); + metadata = icy_server_metadata_page(tag, &types[0]); if (metadata != nullptr) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); for (auto &client : clients) client.PushMetaData(metadata); } @@ -548,7 +504,7 @@ } static void -httpd_output_tag(AudioOutput *ao, const Tag *tag) +httpd_output_tag(AudioOutput *ao, const Tag &tag) { HttpdOutput *httpd = HttpdOutput::Cast(ao); @@ -558,7 +514,7 @@ inline void HttpdOutput::CancelAllClients() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); while (!pages.empty()) { Page *page = pages.front(); diff -Nru mpd-0.19.21/src/output/plugins/httpd/HttpdOutputPlugin.hxx mpd-0.20.9/src/output/plugins/httpd/HttpdOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/httpd/HttpdOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/HttpdOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/httpd/IcyMetaDataServer.cxx mpd-0.20.9/src/output/plugins/httpd/IcyMetaDataServer.cxx --- mpd-0.19.21/src/output/plugins/httpd/IcyMetaDataServer.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/IcyMetaDataServer.cxx 2017-05-08 12:48:25.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,62 +22,62 @@ #include "Page.hxx" #include "tag/Tag.hxx" #include "util/FormatString.hxx" - -#include +#include "util/AllocatedString.hxx" +#include "util/StringUtil.hxx" +#include "util/Macros.hxx" #include -char* +AllocatedString<> icy_server_metadata_header(const char *name, const char *genre, const char *url, const char *content_type, int metaint) { - return FormatNew("ICY 200 OK\r\n" - "icy-notice1:
This stream requires an audio player!
\r\n" /* TODO */ - "icy-notice2:MPD - The music player daemon
\r\n" - "icy-name: %s\r\n" /* TODO */ - "icy-genre: %s\r\n" /* TODO */ - "icy-url: %s\r\n" /* TODO */ - "icy-pub:1\r\n" - "icy-metaint:%d\r\n" - /* TODO "icy-br:%d\r\n" */ - "Content-Type: %s\r\n" - "Connection: close\r\n" - "Pragma: no-cache\r\n" - "Cache-Control: no-cache, no-store\r\n" - "\r\n", - name, - genre, - url, - metaint, - /* bitrate, */ - content_type); + return FormatString("ICY 200 OK\r\n" + "icy-notice1:
This stream requires an audio player!
\r\n" /* TODO */ + "icy-notice2:MPD - The music player daemon
\r\n" + "icy-name: %s\r\n" /* TODO */ + "icy-genre: %s\r\n" /* TODO */ + "icy-url: %s\r\n" /* TODO */ + "icy-pub:1\r\n" + "icy-metaint:%d\r\n" + /* TODO "icy-br:%d\r\n" */ + "Content-Type: %s\r\n" + "Connection: close\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache, no-store\r\n" + "\r\n", + name, + genre, + url, + metaint, + /* bitrate, */ + content_type); } -static char * +static AllocatedString<> icy_server_metadata_string(const char *stream_title, const char* stream_url) { - gchar *icy_metadata; - guint meta_length; - // The leading n is a placeholder for the length information - icy_metadata = FormatNew("nStreamTitle='%s';" - "StreamUrl='%s';", - stream_title, - stream_url); + auto icy_metadata = FormatString("nStreamTitle='%s';" + "StreamUrl='%s';" + /* pad 15 spaces just in case + the length needs to be + rounded up */ + " ", + stream_title, + stream_url); - meta_length = strlen(icy_metadata); + size_t meta_length = strlen(icy_metadata.c_str()); meta_length--; // subtract placeholder - meta_length = ((int)meta_length / 16) + 1; + meta_length = meta_length / 16; icy_metadata[0] = meta_length; - if (meta_length > 255) { - delete[] icy_metadata; + if (meta_length > 255) return nullptr; - } return icy_metadata; } @@ -85,50 +85,33 @@ Page * icy_server_metadata_page(const Tag &tag, const TagType *types) { - const gchar *tag_items[TAG_NUM_OF_ITEM_TYPES]; - gint last_item, item; - guint position; - gchar *icy_string; - gchar stream_title[(1 + 255 - 28) * 16]; // Length + Metadata - - // "StreamTitle='';StreamUrl='';" - // = 4081 - 28 - stream_title[0] = '\0'; - - last_item = -1; + const char *tag_items[TAG_NUM_OF_ITEM_TYPES]; + int last_item = -1; while (*types != TAG_NUM_OF_ITEM_TYPES) { - const gchar *tag_item = tag.GetValue(*types++); + const char *tag_item = tag.GetValue(*types++); if (tag_item) tag_items[++last_item] = tag_item; } - position = item = 0; - while (position < sizeof(stream_title) && item <= last_item) { - gint length = 0; - - length = g_strlcpy(stream_title + position, - tag_items[item++], - sizeof(stream_title) - position); - - position += length; - - if (item <= last_item) { - length = g_strlcpy(stream_title + position, - " - ", - sizeof(stream_title) - position); + int item = 0; - position += length; - } - } + // Length + Metadata - "StreamTitle='';StreamUrl='';" = 4081 - 28 + char stream_title[(1 + 255 - 28) * 16]; + char *p = stream_title, *const end = stream_title + ARRAY_SIZE(stream_title); + stream_title[0] = '\0'; - icy_string = icy_server_metadata_string(stream_title, ""); + while (p < end && item <= last_item) { + p = CopyString(p, tag_items[item++], end - p); - if (icy_string == nullptr) - return nullptr; + if (item <= last_item) + p = CopyString(p, " - ", end - p); + } - Page *icy_metadata = Page::Copy(icy_string, (icy_string[0] * 16) + 1); + const auto icy_string = icy_server_metadata_string(stream_title, ""); - delete[] icy_string; + if (icy_string.IsNull()) + return nullptr; - return icy_metadata; + return Page::Copy(icy_string.c_str(), uint8_t(icy_string[0]) * 16 + 1); } diff -Nru mpd-0.19.21/src/output/plugins/httpd/IcyMetaDataServer.hxx mpd-0.20.9/src/output/plugins/httpd/IcyMetaDataServer.hxx --- mpd-0.19.21/src/output/plugins/httpd/IcyMetaDataServer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/IcyMetaDataServer.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,11 +24,9 @@ struct Tag; class Page; +template class AllocatedString; -/** - * Free the return value with delete[]. - */ -char* +AllocatedString icy_server_metadata_header(const char *name, const char *genre, const char *url, const char *content_type, int metaint); diff -Nru mpd-0.19.21/src/output/plugins/httpd/Page.cxx mpd-0.20.9/src/output/plugins/httpd/Page.cxx --- mpd-0.19.21/src/output/plugins/httpd/Page.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/Page.cxx 2017-02-19 17:59:36.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/httpd/Page.hxx mpd-0.20.9/src/output/plugins/httpd/Page.hxx --- mpd-0.19.21/src/output/plugins/httpd/Page.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/httpd/Page.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/JackOutputPlugin.cxx mpd-0.20.9/src/output/plugins/JackOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/JackOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/JackOutputPlugin.cxx 2017-05-08 15:10:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,26 +20,27 @@ #include "config.h" #include "JackOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "util/ScopeExit.hxx" +#include "util/ConstBuffer.hxx" +#include "util/IterableSplitString.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include -#include #include #include #include +#include /* for usleep() */ #include -#include -enum { - MAX_PORTS = 16, -}; +static constexpr unsigned MAX_PORTS = 16; -static const size_t jack_sample_size = sizeof(jack_default_audio_sample_t); +static constexpr size_t jack_sample_size = sizeof(jack_default_audio_sample_t); struct JackOutput { AudioOutput base; @@ -47,18 +48,18 @@ /** * libjack options passed to jack_client_open(). */ - jack_options_t options; + jack_options_t options = JackNullOption; const char *name; - const char *server_name; + const char *const server_name; /* configuration */ - char *source_ports[MAX_PORTS]; + std::string source_ports[MAX_PORTS]; unsigned num_source_ports; - char *destination_ports[MAX_PORTS]; + std::string destination_ports[MAX_PORTS]; unsigned num_destination_ports; size_t ringbuffer_size; @@ -79,27 +80,147 @@ */ bool pause; - JackOutput() - :base(jack_output_plugin) {} + explicit JackOutput(const ConfigBlock &block); + + /** + * Connect the JACK client and performs some basic setup + * (e.g. register callbacks). + * + * Throws #std::runtime_error on error. + */ + void Connect(); + + /** + * Disconnect the JACK client. + */ + void Disconnect(); + + void Shutdown() { + shutdown = true; + } + + void Enable(); + void Disable(); + + void Open(AudioFormat &new_audio_format); + + void Close() { + Stop(); + } + + /** + * Throws #std::runtime_error on error. + */ + void Start(); + void Stop(); + + /** + * Determine the number of frames guaranteed to be available + * on all channels. + */ + gcc_pure + jack_nframes_t GetAvailable() const noexcept; + + void Process(jack_nframes_t nframes); - bool Initialize(const config_param ¶m, Error &error_r) { - return base.Configure(param, error_r); + /** + * @return the number of frames that were written + */ + size_t WriteSamples(const float *src, size_t n_frames); + + std::chrono::steady_clock::duration Delay() const noexcept { + return base.pause && pause && !shutdown + ? std::chrono::seconds(1) + : std::chrono::steady_clock::duration::zero(); } + + size_t Play(const void *chunk, size_t size); + + bool Pause(); }; static constexpr Domain jack_output_domain("jack_output"); /** - * Determine the number of frames guaranteed to be available on all - * channels. + * Throws #std::runtime_error on error. */ -static jack_nframes_t -mpd_jack_available(const JackOutput *jd) +static unsigned +parse_port_list(const char *source, std::string dest[]) { - size_t min = jack_ringbuffer_read_space(jd->ringbuffer[0]); + unsigned n = 0; + for (auto i : IterableSplitString(source, ',')) { + if (n >= MAX_PORTS) + throw std::runtime_error("too many port names"); + + dest[n++] = std::string(i.data, i.size); + } + + if (n == 0) + throw std::runtime_error("at least one port name expected"); - for (unsigned i = 1; i < jd->audio_format.channels; ++i) { - size_t current = jack_ringbuffer_read_space(jd->ringbuffer[i]); + return n; +} + +JackOutput::JackOutput(const ConfigBlock &block) + :base(jack_output_plugin, block), + name(block.GetBlockValue("client_name", nullptr)), + server_name(block.GetBlockValue("server_name", nullptr)) +{ + if (name != nullptr) + options = jack_options_t(options | JackUseExactName); + else + /* if there's a no configured client name, we don't + care about the JackUseExactName option */ + name = "Music Player Daemon"; + + if (server_name != nullptr) + options = jack_options_t(options | JackServerName); + + if (!block.GetBlockValue("autostart", false)) + options = jack_options_t(options | JackNoStartServer); + + /* configure the source ports */ + + const char *value = block.GetBlockValue("source_ports", "left,right"); + num_source_ports = parse_port_list(value, source_ports); + + /* configure the destination ports */ + + value = block.GetBlockValue("destination_ports", nullptr); + if (value == nullptr) { + /* compatibility with MPD < 0.16 */ + value = block.GetBlockValue("ports", nullptr); + if (value != nullptr) + FormatWarning(jack_output_domain, + "deprecated option 'ports' in line %d", + block.line); + } + + if (value != nullptr) { + num_destination_ports = + parse_port_list(value, destination_ports); + } else { + num_destination_ports = 0; + } + + if (num_destination_ports > 0 && + num_destination_ports != num_source_ports) + FormatWarning(jack_output_domain, + "number of source ports (%u) mismatches the " + "number of destination ports (%u) in line %d", + num_source_ports, num_destination_ports, + block.line); + + ringbuffer_size = block.GetBlockValue("ringbuffer_size", 32768u); +} + +inline jack_nframes_t +JackOutput::GetAvailable() const noexcept +{ + size_t min = jack_ringbuffer_read_space(ringbuffer[0]); + + for (unsigned i = 1; i < audio_format.channels; ++i) { + size_t current = jack_ringbuffer_read_space(ringbuffer[i]); if (current < min) min = current; } @@ -109,85 +230,121 @@ return min / jack_sample_size; } -static int -mpd_jack_process(jack_nframes_t nframes, void *arg) +/** + * Call jack_ringbuffer_read_advance() on all buffers in the list. + */ +static void +MultiReadAdvance(ConstBuffer buffers, + size_t size) +{ + for (auto *i : buffers) + jack_ringbuffer_read_advance(i, size); +} + +/** + * Write a specific amount of "silence" to the given port. + */ +static void +WriteSilence(jack_port_t &port, jack_nframes_t nframes) { - JackOutput *jd = (JackOutput *) arg; + jack_default_audio_sample_t *out = + (jack_default_audio_sample_t *) + jack_port_get_buffer(&port, nframes); + if (out == nullptr) + /* workaround for libjack1 bug: if the server + connection fails, the process callback is invoked + anyway, but unable to get a buffer */ + return; + std::fill_n(out, nframes, 0.0); +} + +/** + * Write a specific amount of "silence" to all ports in the list. + */ +static void +MultiWriteSilence(ConstBuffer ports, jack_nframes_t nframes) +{ + for (auto *i : ports) + WriteSilence(*i, nframes); +} + +/** + * Copy data from the buffer to the port. If the buffer underruns, + * fill with silence. + */ +static void +Copy(jack_port_t &dest, jack_nframes_t nframes, + jack_ringbuffer_t &src, jack_nframes_t available) +{ + jack_default_audio_sample_t *out = + (jack_default_audio_sample_t *) + jack_port_get_buffer(&dest, nframes); + if (out == nullptr) + /* workaround for libjack1 bug: if the server + connection fails, the process callback is + invoked anyway, but unable to get a + buffer */ + return; + + /* copy from buffer to port */ + jack_ringbuffer_read(&src, (char *)out, + available * jack_sample_size); + + /* ringbuffer underrun, fill with silence */ + std::fill(out + available, out + nframes, 0.0); +} + +inline void +JackOutput::Process(jack_nframes_t nframes) +{ if (nframes <= 0) - return 0; + return; + + jack_nframes_t available = GetAvailable(); - if (jd->pause) { + const unsigned n_channels = audio_format.channels; + + if (pause) { /* empty the ring buffers */ - const jack_nframes_t available = mpd_jack_available(jd); - for (unsigned i = 0; i < jd->audio_format.channels; ++i) - jack_ringbuffer_read_advance(jd->ringbuffer[i], - available * jack_sample_size); + MultiReadAdvance({ringbuffer, n_channels}, + available * jack_sample_size); /* generate silence while MPD is paused */ - for (unsigned i = 0; i < jd->audio_format.channels; ++i) { - jack_default_audio_sample_t *out = - (jack_default_audio_sample_t *) - jack_port_get_buffer(jd->ports[i], nframes); - - for (jack_nframes_t f = 0; f < nframes; ++f) - out[f] = 0.0; - } + MultiWriteSilence({ports, n_channels}, nframes); - return 0; + return; } - jack_nframes_t available = mpd_jack_available(jd); if (available > nframes) available = nframes; - for (unsigned i = 0; i < jd->audio_format.channels; ++i) { - jack_default_audio_sample_t *out = - (jack_default_audio_sample_t *) - jack_port_get_buffer(jd->ports[i], nframes); - if (out == nullptr) - /* workaround for libjack1 bug: if the server - connection fails, the process callback is - invoked anyway, but unable to get a - buffer */ - continue; - - jack_ringbuffer_read(jd->ringbuffer[i], - (char *)out, available * jack_sample_size); - - for (jack_nframes_t f = available; f < nframes; ++f) - /* ringbuffer underrun, fill with silence */ - out[f] = 0.0; - } + for (unsigned i = 0; i < n_channels; ++i) + Copy(*ports[i], nframes, *ringbuffer[i], available); /* generate silence for the unused source ports */ - for (unsigned i = jd->audio_format.channels; - i < jd->num_source_ports; ++i) { - jack_default_audio_sample_t *out = - (jack_default_audio_sample_t *) - jack_port_get_buffer(jd->ports[i], nframes); - if (out == nullptr) - /* workaround for libjack1 bug: if the server - connection fails, the process callback is - invoked anyway, but unable to get a - buffer */ - continue; + MultiWriteSilence({ports + n_channels, num_source_ports - n_channels}, + nframes); +} - for (jack_nframes_t f = 0; f < nframes; ++f) - out[f] = 0.0; - } +static int +mpd_jack_process(jack_nframes_t nframes, void *arg) +{ + JackOutput &jo = *(JackOutput *) arg; + jo.Process(nframes); return 0; } static void mpd_jack_shutdown(void *arg) { - JackOutput *jd = (JackOutput *) arg; - jd->shutdown = true; + JackOutput &jo = *(JackOutput *) arg; + + jo.Shutdown(); } static void @@ -200,9 +357,10 @@ else if (audio_format.channels > jd->num_source_ports) audio_format.channels = 2; - if (audio_format.format != SampleFormat::S16 && - audio_format.format != SampleFormat::S24_P32) - audio_format.format = SampleFormat::S24_P32; + /* JACK uses 32 bit float in the range [-1 .. 1] - just like + MPD's SampleFormat::FLOAT*/ + static_assert(jack_sample_size == sizeof(float), "Expected float32"); + audio_format.format = SampleFormat::FLOAT; } static void @@ -219,60 +377,41 @@ } #endif -/** - * Disconnect the JACK client. - */ -static void -mpd_jack_disconnect(JackOutput *jd) +void +JackOutput::Disconnect() { - assert(jd != nullptr); - assert(jd->client != nullptr); + assert(client != nullptr); - jack_deactivate(jd->client); - jack_client_close(jd->client); - jd->client = nullptr; + jack_deactivate(client); + jack_client_close(client); + client = nullptr; } -/** - * Connect the JACK client and performs some basic setup - * (e.g. register callbacks). - */ -static bool -mpd_jack_connect(JackOutput *jd, Error &error) +void +JackOutput::Connect() { - jack_status_t status; - - assert(jd != nullptr); + shutdown = false; - jd->shutdown = false; - - jd->client = jack_client_open(jd->name, jd->options, &status, - jd->server_name); - if (jd->client == nullptr) { - error.Format(jack_output_domain, status, - "Failed to connect to JACK server, status=%d", - status); - return false; - } - - jack_set_process_callback(jd->client, mpd_jack_process, jd); - jack_on_shutdown(jd->client, mpd_jack_shutdown, jd); - - for (unsigned i = 0; i < jd->num_source_ports; ++i) { - jd->ports[i] = jack_port_register(jd->client, - jd->source_ports[i], - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); - if (jd->ports[i] == nullptr) { - error.Format(jack_output_domain, - "Cannot register output port \"%s\"", - jd->source_ports[i]); - mpd_jack_disconnect(jd); - return false; + jack_status_t status; + client = jack_client_open(name, options, &status, server_name); + if (client == nullptr) + throw FormatRuntimeError("Failed to connect to JACK server, status=%d", + status); + + jack_set_process_callback(client, mpd_jack_process, this); + jack_on_shutdown(client, mpd_jack_shutdown, this); + + for (unsigned i = 0; i < num_source_ports; ++i) { + ports[i] = jack_port_register(client, + source_ports[i].c_str(), + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); + if (ports[i] == nullptr) { + Disconnect(); + throw FormatRuntimeError("Cannot register output port \"%s\"", + source_ports[i].c_str()); } } - - return true; } static bool @@ -281,271 +420,147 @@ return true; } -static unsigned -parse_port_list(const char *source, char **dest, Error &error) +inline void +JackOutput::Enable() { - char **list = g_strsplit(source, ",", 0); - unsigned n = 0; - - for (n = 0; list[n] != nullptr; ++n) { - if (n >= MAX_PORTS) { - error.Set(config_domain, - "too many port names"); - return 0; - } + for (unsigned i = 0; i < num_source_ports; ++i) + ringbuffer[i] = nullptr; - dest[n] = list[n]; - } + Connect(); +} - g_free(list); +inline void +JackOutput::Disable() +{ + if (client != nullptr) + Disconnect(); - if (n == 0) { - error.Format(config_domain, - "at least one port name expected"); - return 0; + for (unsigned i = 0; i < num_source_ports; ++i) { + if (ringbuffer[i] != nullptr) { + jack_ringbuffer_free(ringbuffer[i]); + ringbuffer[i] = nullptr; + } } - - return n; } static AudioOutput * -mpd_jack_init(const config_param ¶m, Error &error) +mpd_jack_init(const ConfigBlock &block) { - JackOutput *jd = new JackOutput(); - - if (!jd->Initialize(param, error)) { - delete jd; - return nullptr; - } - - const char *value; - - jd->options = JackNullOption; - - jd->name = param.GetBlockValue("client_name", nullptr); - if (jd->name != nullptr) - jd->options = jack_options_t(jd->options | JackUseExactName); - else - /* if there's a no configured client name, we don't - care about the JackUseExactName option */ - jd->name = "Music Player Daemon"; - - jd->server_name = param.GetBlockValue("server_name", nullptr); - if (jd->server_name != nullptr) - jd->options = jack_options_t(jd->options | JackServerName); - - if (!param.GetBlockValue("autostart", false)) - jd->options = jack_options_t(jd->options | JackNoStartServer); - - /* configure the source ports */ - - value = param.GetBlockValue("source_ports", "left,right"); - jd->num_source_ports = parse_port_list(value, - jd->source_ports, error); - if (jd->num_source_ports == 0) - return nullptr; - - /* configure the destination ports */ - - value = param.GetBlockValue("destination_ports", nullptr); - if (value == nullptr) { - /* compatibility with MPD < 0.16 */ - value = param.GetBlockValue("ports", nullptr); - if (value != nullptr) - FormatWarning(jack_output_domain, - "deprecated option 'ports' in line %d", - param.line); - } - - if (value != nullptr) { - jd->num_destination_ports = - parse_port_list(value, - jd->destination_ports, error); - if (jd->num_destination_ports == 0) - return nullptr; - } else { - jd->num_destination_ports = 0; - } - - if (jd->num_destination_ports > 0 && - jd->num_destination_ports != jd->num_source_ports) - FormatWarning(jack_output_domain, - "number of source ports (%u) mismatches the " - "number of destination ports (%u) in line %d", - jd->num_source_ports, jd->num_destination_ports, - param.line); - - jd->ringbuffer_size = param.GetBlockValue("ringbuffer_size", 32768u); - jack_set_error_function(mpd_jack_error); #ifdef HAVE_JACK_SET_INFO_FUNCTION jack_set_info_function(mpd_jack_info); #endif + auto *jd = new JackOutput(block); return &jd->base; } -static void -mpd_jack_finish(AudioOutput *ao) -{ - JackOutput *jd = (JackOutput *)ao; - - for (unsigned i = 0; i < jd->num_source_ports; ++i) - g_free(jd->source_ports[i]); - - for (unsigned i = 0; i < jd->num_destination_ports; ++i) - g_free(jd->destination_ports[i]); - - delete jd; -} - -static bool -mpd_jack_enable(AudioOutput *ao, Error &error) -{ - JackOutput *jd = (JackOutput *)ao; - - for (unsigned i = 0; i < jd->num_source_ports; ++i) - jd->ringbuffer[i] = nullptr; - - return mpd_jack_connect(jd, error); -} - -static void -mpd_jack_disable(AudioOutput *ao) -{ - JackOutput *jd = (JackOutput *)ao; - - if (jd->client != nullptr) - mpd_jack_disconnect(jd); - - for (unsigned i = 0; i < jd->num_source_ports; ++i) { - if (jd->ringbuffer[i] != nullptr) { - jack_ringbuffer_free(jd->ringbuffer[i]); - jd->ringbuffer[i] = nullptr; - } - } -} - /** * Stops the playback on the JACK connection. */ -static void -mpd_jack_stop(JackOutput *jd) +void +JackOutput::Stop() { - assert(jd != nullptr); - - if (jd->client == nullptr) + if (client == nullptr) return; - if (jd->shutdown) + if (shutdown) /* the connection has failed; close it */ - mpd_jack_disconnect(jd); + Disconnect(); else /* the connection is alive: just stop playback */ - jack_deactivate(jd->client); + jack_deactivate(client); } -static bool -mpd_jack_start(JackOutput *jd, Error &error) +inline void +JackOutput::Start() { - const char *destination_ports[MAX_PORTS], **jports; - const char *duplicate_port = nullptr; - unsigned num_destination_ports; - - assert(jd->client != nullptr); - assert(jd->audio_format.channels <= jd->num_source_ports); + assert(client != nullptr); + assert(audio_format.channels <= num_source_ports); /* allocate the ring buffers on the first open(); these persist until MPD exits. It's too unsafe to delete them because we can never know when mpd_jack_process() gets called */ - for (unsigned i = 0; i < jd->num_source_ports; ++i) { - if (jd->ringbuffer[i] == nullptr) - jd->ringbuffer[i] = - jack_ringbuffer_create(jd->ringbuffer_size); + for (unsigned i = 0; i < num_source_ports; ++i) { + if (ringbuffer[i] == nullptr) + ringbuffer[i] = + jack_ringbuffer_create(ringbuffer_size); /* clear the ring buffer to be sure that data from previous playbacks are gone */ - jack_ringbuffer_reset(jd->ringbuffer[i]); + jack_ringbuffer_reset(ringbuffer[i]); } - if ( jack_activate(jd->client) ) { - error.Set(jack_output_domain, "cannot activate client"); - mpd_jack_stop(jd); - return false; + if ( jack_activate(client) ) { + Stop(); + throw std::runtime_error("cannot activate client"); } - if (jd->num_destination_ports == 0) { + const char *dports[MAX_PORTS], **jports; + unsigned num_dports; + if (num_destination_ports == 0) { /* no output ports were configured - ask libjack for defaults */ - jports = jack_get_ports(jd->client, nullptr, nullptr, + jports = jack_get_ports(client, nullptr, nullptr, JackPortIsPhysical | JackPortIsInput); if (jports == nullptr) { - error.Set(jack_output_domain, "no ports found"); - mpd_jack_stop(jd); - return false; + Stop(); + throw std::runtime_error("no ports found"); } assert(*jports != nullptr); - for (num_destination_ports = 0; - num_destination_ports < MAX_PORTS && - jports[num_destination_ports] != nullptr; - ++num_destination_ports) { + for (num_dports = 0; num_dports < MAX_PORTS && + jports[num_dports] != nullptr; + ++num_dports) { FormatDebug(jack_output_domain, "destination_port[%u] = '%s'\n", - num_destination_ports, - jports[num_destination_ports]); - destination_ports[num_destination_ports] = - jports[num_destination_ports]; + num_dports, + jports[num_dports]); + dports[num_dports] = jports[num_dports]; } } else { /* use the configured output ports */ - num_destination_ports = jd->num_destination_ports; - memcpy(destination_ports, jd->destination_ports, - num_destination_ports * sizeof(*destination_ports)); + num_dports = num_destination_ports; + for (unsigned i = 0; i < num_dports; ++i) + dports[i] = destination_ports[i].c_str(); jports = nullptr; } - assert(num_destination_ports > 0); + AtScopeExit(jports) { free(jports); }; - if (jd->audio_format.channels >= 2 && num_destination_ports == 1) { + assert(num_dports > 0); + + const char *duplicate_port = nullptr; + if (audio_format.channels >= 2 && num_dports == 1) { /* mix stereo signal on one speaker */ - while (num_destination_ports < jd->audio_format.channels) - destination_ports[num_destination_ports++] = - destination_ports[0]; - } else if (num_destination_ports > jd->audio_format.channels) { - if (jd->audio_format.channels == 1 && num_destination_ports > 2) { + std::fill(dports + num_dports, dports + audio_format.channels, + dports[0]); + } else if (num_dports > audio_format.channels) { + if (audio_format.channels == 1 && num_dports > 2) { /* mono input file: connect the one source channel to the both destination channels */ - duplicate_port = destination_ports[1]; - num_destination_ports = 1; + duplicate_port = dports[1]; + num_dports = 1; } else /* connect only as many ports as we need */ - num_destination_ports = jd->audio_format.channels; + num_dports = audio_format.channels; } - assert(num_destination_ports <= jd->num_source_ports); - - for (unsigned i = 0; i < num_destination_ports; ++i) { - int ret; + assert(num_dports <= num_source_ports); - ret = jack_connect(jd->client, jack_port_name(jd->ports[i]), - destination_ports[i]); + for (unsigned i = 0; i < num_dports; ++i) { + int ret = jack_connect(client, jack_port_name(ports[i]), + dports[i]); if (ret != 0) { - error.Format(jack_output_domain, - "Not a valid JACK port: %s", - destination_ports[i]); - - if (jports != nullptr) - free(jports); - - mpd_jack_stop(jd); - return false; + Stop(); + throw FormatRuntimeError("Not a valid JACK port: %s", + dports[i]); } } @@ -554,209 +569,126 @@ the both destination channels */ int ret; - ret = jack_connect(jd->client, jack_port_name(jd->ports[0]), + ret = jack_connect(client, jack_port_name(ports[0]), duplicate_port); if (ret != 0) { - error.Format(jack_output_domain, - "Not a valid JACK port: %s", - duplicate_port); - - if (jports != nullptr) - free(jports); - - mpd_jack_stop(jd); - return false; + Stop(); + throw FormatRuntimeError("Not a valid JACK port: %s", + duplicate_port); } } - - if (jports != nullptr) - free(jports); - - return true; } -static bool -mpd_jack_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +inline void +JackOutput::Open(AudioFormat &new_audio_format) { - JackOutput *jd = (JackOutput *)ao; + pause = false; - assert(jd != nullptr); + if (client != nullptr && shutdown) + Disconnect(); - jd->pause = false; + if (client == nullptr) + Connect(); - if (jd->client != nullptr && jd->shutdown) - mpd_jack_disconnect(jd); + set_audioformat(this, new_audio_format); + audio_format = new_audio_format; - if (jd->client == nullptr && !mpd_jack_connect(jd, error)) - return false; - - set_audioformat(jd, audio_format); - jd->audio_format = audio_format; - - if (!mpd_jack_start(jd, error)) - return false; - - return true; + Start(); } -static void -mpd_jack_close(gcc_unused AudioOutput *ao) +inline size_t +JackOutput::WriteSamples(const float *src, size_t n_frames) { - JackOutput *jd = (JackOutput *)ao; + assert(n_frames > 0); - mpd_jack_stop(jd); -} - -static unsigned -mpd_jack_delay(AudioOutput *ao) -{ - JackOutput *jd = (JackOutput *)ao; + const unsigned n_channels = audio_format.channels; - return jd->base.pause && jd->pause && !jd->shutdown - ? 1000 - : 0; -} + float *dest[MAX_CHANNELS]; + size_t space = -1; + for (unsigned i = 0; i < n_channels; ++i) { + jack_ringbuffer_data_t d[2]; + jack_ringbuffer_get_write_vector(ringbuffer[i], d); -static inline jack_default_audio_sample_t -sample_16_to_jack(int16_t sample) -{ - return sample / (jack_default_audio_sample_t)(1 << (16 - 1)); -} + /* choose the first non-empty writable area */ + const jack_ringbuffer_data_t &e = d[d[0].len == 0]; -static void -mpd_jack_write_samples_16(JackOutput *jd, const int16_t *src, - unsigned num_samples) -{ - jack_default_audio_sample_t sample; - unsigned i; + if (e.len < space) + /* send data symmetrically */ + space = e.len; - while (num_samples-- > 0) { - for (i = 0; i < jd->audio_format.channels; ++i) { - sample = sample_16_to_jack(*src++); - jack_ringbuffer_write(jd->ringbuffer[i], - (const char *)&sample, - sizeof(sample)); - } + dest[i] = (float *)e.buf; } -} -static inline jack_default_audio_sample_t -sample_24_to_jack(int32_t sample) -{ - return sample / (jack_default_audio_sample_t)(1 << (24 - 1)); -} + space /= jack_sample_size; + if (space == 0) + return 0; -static void -mpd_jack_write_samples_24(JackOutput *jd, const int32_t *src, - unsigned num_samples) -{ - jack_default_audio_sample_t sample; - unsigned i; + const size_t result = n_frames = std::min(space, n_frames); - while (num_samples-- > 0) { - for (i = 0; i < jd->audio_format.channels; ++i) { - sample = sample_24_to_jack(*src++); - jack_ringbuffer_write(jd->ringbuffer[i], - (const char *)&sample, - sizeof(sample)); - } - } -} + while (n_frames-- > 0) + for (unsigned i = 0; i < n_channels; ++i) + *dest[i]++ = *src++; -static void -mpd_jack_write_samples(JackOutput *jd, const void *src, - unsigned num_samples) -{ - switch (jd->audio_format.format) { - case SampleFormat::S16: - mpd_jack_write_samples_16(jd, (const int16_t*)src, - num_samples); - break; + const size_t per_channel_advance = result * jack_sample_size; + for (unsigned i = 0; i < n_channels; ++i) + jack_ringbuffer_write_advance(ringbuffer[i], + per_channel_advance); - case SampleFormat::S24_P32: - mpd_jack_write_samples_24(jd, (const int32_t*)src, - num_samples); - break; - - default: - assert(false); - gcc_unreachable(); - } + return result; } -static size_t -mpd_jack_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +JackOutput::Play(const void *chunk, size_t size) { - JackOutput *jd = (JackOutput *)ao; - const size_t frame_size = jd->audio_format.GetFrameSize(); - size_t space = 0, space1; - - jd->pause = false; + pause = false; + const size_t frame_size = audio_format.GetFrameSize(); assert(size % frame_size == 0); size /= frame_size; while (true) { - if (jd->shutdown) { - error.Set(jack_output_domain, - "Refusing to play, because " - "there is no client thread"); - return 0; - } - - space = jack_ringbuffer_write_space(jd->ringbuffer[0]); - for (unsigned i = 1; i < jd->audio_format.channels; ++i) { - space1 = jack_ringbuffer_write_space(jd->ringbuffer[i]); - if (space > space1) - /* send data symmetrically */ - space = space1; - } - - if (space >= jack_sample_size) - break; + if (shutdown) + throw std::runtime_error("Refusing to play, because " + "there is no client thread"); + + size_t frames_written = + WriteSamples((const float *)chunk, size); + if (frames_written > 0) + return frames_written * frame_size; /* XXX do something more intelligent to synchronize */ - g_usleep(1000); + usleep(1000); } - - space /= jack_sample_size; - if (space < size) - size = space; - - mpd_jack_write_samples(jd, chunk, size); - return size * frame_size; } -static bool -mpd_jack_pause(AudioOutput *ao) +inline bool +JackOutput::Pause() { - JackOutput *jd = (JackOutput *)ao; - - if (jd->shutdown) + if (shutdown) return false; - jd->pause = true; + pause = true; return true; } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin jack_output_plugin = { "jack", mpd_jack_test_default_device, mpd_jack_init, - mpd_jack_finish, - mpd_jack_enable, - mpd_jack_disable, - mpd_jack_open, - mpd_jack_close, - mpd_jack_delay, + &Wrapper::Finish, + &Wrapper::Enable, + &Wrapper::Disable, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - mpd_jack_play, + &Wrapper::Play, nullptr, nullptr, - mpd_jack_pause, + &Wrapper::Pause, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/JackOutputPlugin.hxx mpd-0.20.9/src/output/plugins/JackOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/JackOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/JackOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/NullOutputPlugin.cxx mpd-0.20.9/src/output/plugins/NullOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/NullOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/NullOutputPlugin.cxx 2017-05-08 15:00:34.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,119 +20,79 @@ #include "config.h" #include "NullOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "../Timer.hxx" -struct NullOutput { +class NullOutput { + friend struct AudioOutputWrapper; + AudioOutput base; - bool sync; + const bool sync; Timer *timer; - NullOutput() - :base(null_output_plugin) {} - - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); +public: + NullOutput(const ConfigBlock &block) + :base(null_output_plugin, block), + sync(block.GetBlockValue("sync", true)) {} + + static NullOutput *Create(const ConfigBlock &block); + + void Open(AudioFormat &audio_format) { + if (sync) + timer = new Timer(audio_format); } -}; - -static AudioOutput * -null_init(const config_param ¶m, Error &error) -{ - NullOutput *nd = new NullOutput(); - if (!nd->Initialize(param, error)) { - delete nd; - return nullptr; + void Close() { + if (sync) + delete timer; } - nd->sync = param.GetBlockValue("sync", true); - - return &nd->base; -} - -static void -null_finish(AudioOutput *ao) -{ - NullOutput *nd = (NullOutput *)ao; - - delete nd; -} - -static bool -null_open(AudioOutput *ao, AudioFormat &audio_format, - gcc_unused Error &error) -{ - NullOutput *nd = (NullOutput *)ao; - - if (nd->sync) - nd->timer = new Timer(audio_format); - - return true; -} - -static void -null_close(AudioOutput *ao) -{ - NullOutput *nd = (NullOutput *)ao; - - if (nd->sync) - delete nd->timer; -} - -static unsigned -null_delay(AudioOutput *ao) -{ - NullOutput *nd = (NullOutput *)ao; - - return nd->sync && nd->timer->IsStarted() - ? nd->timer->GetDelay() - : 0; -} + std::chrono::steady_clock::duration Delay() const noexcept { + return sync && timer->IsStarted() + ? timer->GetDelay() + : std::chrono::steady_clock::duration::zero(); + } -static size_t -null_play(AudioOutput *ao, gcc_unused const void *chunk, size_t size, - gcc_unused Error &error) -{ - NullOutput *nd = (NullOutput *)ao; - Timer *timer = nd->timer; + size_t Play(gcc_unused const void *chunk, size_t size) { + if (sync) { + if (!timer->IsStarted()) + timer->Start(); + timer->Add(size); + } - if (!nd->sync) return size; + } - if (!timer->IsStarted()) - timer->Start(); - timer->Add(size); - - return size; -} + void Cancel() { + if (sync) + timer->Reset(); + } +}; -static void -null_cancel(AudioOutput *ao) +inline NullOutput * +NullOutput::Create(const ConfigBlock &block) { - NullOutput *nd = (NullOutput *)ao; - - if (!nd->sync) - return; - - nd->timer->Reset(); + return new NullOutput(block); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin null_output_plugin = { "null", nullptr, - null_init, - null_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - null_open, - null_close, - null_delay, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - null_play, + &Wrapper::Play, nullptr, - null_cancel, + &Wrapper::Cancel, nullptr, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/NullOutputPlugin.hxx mpd-0.20.9/src/output/plugins/NullOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/NullOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/NullOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/OpenALOutputPlugin.cxx mpd-0.20.9/src/output/plugins/OpenALOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/OpenALOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OpenALOutputPlugin.cxx 2017-06-04 10:38:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,8 @@ #include "config.h" #include "OpenALOutputPlugin.hxx" #include "../OutputAPI.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "../Wrapper.hxx" +#include "util/RuntimeError.hxx" #include @@ -33,10 +33,12 @@ #include #endif -/* should be enough for buffer size = 2048 */ -#define NUM_BUFFERS 16 +class OpenALOutput { + friend struct AudioOutputWrapper; + + /* should be enough for buffer size = 2048 */ + static constexpr unsigned NUM_BUFFERS = 16; -struct OpenALOutput { AudioOutput base; const char *device_name; @@ -48,15 +50,50 @@ ALenum format; ALuint frequency; - OpenALOutput() - :base(openal_output_plugin) {} + OpenALOutput(const ConfigBlock &block); + + static OpenALOutput *Create(const ConfigBlock &block); + + void Open(AudioFormat &audio_format); + void Close(); - bool Initialize(const config_param ¶m, Error &error_r) { - return base.Configure(param, error_r); + gcc_pure + std::chrono::steady_clock::duration Delay() const noexcept { + return filled < NUM_BUFFERS || HasProcessed() + ? std::chrono::steady_clock::duration::zero() + /* we don't know exactly how long we must wait + for the next buffer to finish, so this is a + random guess: */ + : std::chrono::milliseconds(50); } -}; -static constexpr Domain openal_output_domain("openal_output"); + size_t Play(const void *chunk, size_t size); + + void Cancel(); + +private: + gcc_pure + ALint GetSourceI(ALenum param) const noexcept { + ALint value; + alGetSourcei(source, param, &value); + return value; + } + + gcc_pure + bool HasProcessed() const noexcept { + return GetSourceI(AL_BUFFERS_PROCESSED) > 0; + } + + gcc_pure + bool IsPlaying() const noexcept { + return GetSourceI(AL_SOURCE_STATE) == AL_PLAYING; + } + + /** + * Throws #std::runtime_error on error. + */ + void SetupContext(); +}; static ALenum openal_audio_format(AudioFormat &audio_format) @@ -83,200 +120,127 @@ } } -gcc_pure -static inline ALint -openal_get_source_i(const OpenALOutput *od, ALenum param) -{ - ALint value; - alGetSourcei(od->source, param, &value); - return value; -} - -gcc_pure -static inline bool -openal_has_processed(const OpenALOutput *od) +inline void +OpenALOutput::SetupContext() { - return openal_get_source_i(od, AL_BUFFERS_PROCESSED) > 0; -} - -gcc_pure -static inline ALint -openal_is_playing(const OpenALOutput *od) -{ - return openal_get_source_i(od, AL_SOURCE_STATE) == AL_PLAYING; -} - -static bool -openal_setup_context(OpenALOutput *od, Error &error) -{ - od->device = alcOpenDevice(od->device_name); - - if (od->device == nullptr) { - error.Format(openal_output_domain, - "Error opening OpenAL device \"%s\"", - od->device_name); - return false; - } - - od->context = alcCreateContext(od->device, nullptr); + device = alcOpenDevice(device_name); + if (device == nullptr) + throw FormatRuntimeError("Error opening OpenAL device \"%s\"", + device_name); - if (od->context == nullptr) { - error.Format(openal_output_domain, - "Error creating context for \"%s\"", - od->device_name); - alcCloseDevice(od->device); - return false; + context = alcCreateContext(device, nullptr); + if (context == nullptr) { + alcCloseDevice(device); + throw FormatRuntimeError("Error creating context for \"%s\"", + device_name); } - - return true; } -static AudioOutput * -openal_init(const config_param ¶m, Error &error) +OpenALOutput::OpenALOutput(const ConfigBlock &block) + :base(openal_output_plugin, block), + device_name(block.GetBlockValue("device")) { - const char *device_name = param.GetBlockValue("device"); - if (device_name == nullptr) { - device_name = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER); - } - - OpenALOutput *od = new OpenALOutput(); - if (!od->Initialize(param, error)) { - delete od; - return nullptr; - } - - od->device_name = device_name; - - return &od->base; + if (device_name == nullptr) + device_name = alcGetString(nullptr, + ALC_DEFAULT_DEVICE_SPECIFIER); } -static void -openal_finish(AudioOutput *ao) +inline OpenALOutput * +OpenALOutput::Create(const ConfigBlock &block) { - OpenALOutput *od = (OpenALOutput *)ao; - - delete od; + return new OpenALOutput(block); } -static bool -openal_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +inline void +OpenALOutput::Open(AudioFormat &audio_format) { - OpenALOutput *od = (OpenALOutput *)ao; + format = openal_audio_format(audio_format); - od->format = openal_audio_format(audio_format); + SetupContext(); - if (!openal_setup_context(od, error)) { - return false; - } + alcMakeContextCurrent(context); + alGenBuffers(NUM_BUFFERS, buffers); - alcMakeContextCurrent(od->context); - alGenBuffers(NUM_BUFFERS, od->buffers); + if (alGetError() != AL_NO_ERROR) + throw std::runtime_error("Failed to generate buffers"); - if (alGetError() != AL_NO_ERROR) { - error.Set(openal_output_domain, "Failed to generate buffers"); - return false; - } - - alGenSources(1, &od->source); + alGenSources(1, &source); if (alGetError() != AL_NO_ERROR) { - error.Set(openal_output_domain, "Failed to generate source"); - alDeleteBuffers(NUM_BUFFERS, od->buffers); - return false; + alDeleteBuffers(NUM_BUFFERS, buffers); + throw std::runtime_error("Failed to generate source"); } - od->filled = 0; - od->frequency = audio_format.sample_rate; - - return true; + filled = 0; + frequency = audio_format.sample_rate; } -static void -openal_close(AudioOutput *ao) +inline void +OpenALOutput::Close() { - OpenALOutput *od = (OpenALOutput *)ao; - - alcMakeContextCurrent(od->context); - alDeleteSources(1, &od->source); - alDeleteBuffers(NUM_BUFFERS, od->buffers); - alcDestroyContext(od->context); - alcCloseDevice(od->device); + alcMakeContextCurrent(context); + alDeleteSources(1, &source); + alDeleteBuffers(NUM_BUFFERS, buffers); + alcDestroyContext(context); + alcCloseDevice(device); } -static unsigned -openal_delay(AudioOutput *ao) +inline size_t +OpenALOutput::Play(const void *chunk, size_t size) { - OpenALOutput *od = (OpenALOutput *)ao; + if (alcGetCurrentContext() != context) + alcMakeContextCurrent(context); - return od->filled < NUM_BUFFERS || openal_has_processed(od) - ? 0 - /* we don't know exactly how long we must wait for the - next buffer to finish, so this is a random - guess: */ - : 50; -} - -static size_t -openal_play(AudioOutput *ao, const void *chunk, size_t size, - gcc_unused Error &error) -{ - OpenALOutput *od = (OpenALOutput *)ao; ALuint buffer; - - if (alcGetCurrentContext() != od->context) { - alcMakeContextCurrent(od->context); - } - - if (od->filled < NUM_BUFFERS) { + if (filled < NUM_BUFFERS) { /* fill all buffers */ - buffer = od->buffers[od->filled]; - od->filled++; + buffer = buffers[filled]; + filled++; } else { /* wait for processed buffer */ - while (!openal_has_processed(od)) + while (!HasProcessed()) usleep(10); - alSourceUnqueueBuffers(od->source, 1, &buffer); + alSourceUnqueueBuffers(source, 1, &buffer); } - alBufferData(buffer, od->format, chunk, size, od->frequency); - alSourceQueueBuffers(od->source, 1, &buffer); + alBufferData(buffer, format, chunk, size, frequency); + alSourceQueueBuffers(source, 1, &buffer); - if (!openal_is_playing(od)) - alSourcePlay(od->source); + if (!IsPlaying()) + alSourcePlay(source); return size; } -static void -openal_cancel(AudioOutput *ao) +inline void +OpenALOutput::Cancel() { - OpenALOutput *od = (OpenALOutput *)ao; - - od->filled = 0; - alcMakeContextCurrent(od->context); - alSourceStop(od->source); + filled = 0; + alcMakeContextCurrent(context); + alSourceStop(source); /* force-unqueue all buffers */ - alSourcei(od->source, AL_BUFFER, 0); - od->filled = 0; + alSourcei(source, AL_BUFFER, 0); + filled = 0; } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin openal_output_plugin = { "openal", nullptr, - openal_init, - openal_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - openal_open, - openal_close, - openal_delay, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - openal_play, + &Wrapper::Play, nullptr, - openal_cancel, + &Wrapper::Cancel, nullptr, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/OpenALOutputPlugin.hxx mpd-0.20.9/src/output/plugins/OpenALOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/OpenALOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OpenALOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/OssOutputPlugin.cxx mpd-0.20.9/src/output/plugins/OssOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/OssOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OssOutputPlugin.cxx 2017-05-08 15:01:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,15 +20,18 @@ #include "config.h" #include "OssOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "mixer/MixerList.hxx" #include "system/fd_util.h" +#include "system/Error.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "util/Macros.hxx" #include "system/ByteOrder.hxx" #include "Log.hxx" +#include + #include #include #include @@ -57,7 +60,9 @@ #include "util/Manual.hxx" #endif -struct OssOutput { +class OssOutput { + friend struct AudioOutputWrapper; + AudioOutput base; #ifdef AFMT_S24_PACKED @@ -79,13 +84,46 @@ */ int oss_format; - OssOutput() - :base(oss_output_plugin), - fd(-1), device(nullptr) {} +public: + OssOutput(const ConfigBlock &block, const char *_device=nullptr) + :base(oss_output_plugin, block), + fd(-1), device(_device) {} + + static OssOutput *Create(const ConfigBlock &block); + +#ifdef AFMT_S24_PACKED + void Enable() { + pcm_export.Construct(); + } + + void Disable() { + pcm_export.Destruct(); + } +#endif + + void Open(AudioFormat &audio_format); - bool Initialize(const config_param ¶m, Error &error_r) { - return base.Configure(param, error_r); + void Close() { + DoClose(); } + + size_t Play(const void *chunk, size_t size); + void Cancel(); + +private: + /** + * Sets up the OSS device which was opened before. + */ + void Setup(AudioFormat &audio_format); + + /** + * Reopen the device with the saved audio_format, without any probing. + * + * Throws #std::runtime_error on error. + */ + void Reopen(); + + void DoClose(); }; static constexpr Domain oss_output_domain("oss_output"); @@ -124,7 +162,7 @@ return OSS_STAT_NO_ERROR; } -static const char *default_devices[] = { "/dev/sound/dsp", "/dev/dsp" }; +static const char *const default_devices[] = { "/dev/sound/dsp", "/dev/dsp" }; static bool oss_output_test_default_device(void) @@ -147,25 +185,17 @@ return false; } -static AudioOutput * -oss_open_default(Error &error) +static OssOutput * +oss_open_default() { int err[ARRAY_SIZE(default_devices)]; enum oss_stat ret[ARRAY_SIZE(default_devices)]; - const config_param empty; + const ConfigBlock empty; for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) { ret[i] = oss_stat_device(default_devices[i], &err[i]); - if (ret[i] == OSS_STAT_NO_ERROR) { - OssOutput *od = new OssOutput(); - if (!od->Initialize(empty, error)) { - delete od; - return NULL; - } - - od->device = default_devices[i]; - return &od->base; - } + if (ret[i] == OSS_STAT_NO_ERROR) + return new OssOutput(empty, default_devices[i]); } for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) { @@ -192,64 +222,25 @@ } } - error.Set(oss_output_domain, - "error trying to open default OSS device"); - return NULL; + throw std::runtime_error("error trying to open default OSS device"); } -static AudioOutput * -oss_output_init(const config_param ¶m, Error &error) -{ - const char *device = param.GetBlockValue("device"); - if (device != NULL) { - OssOutput *od = new OssOutput(); - if (!od->Initialize(param, error)) { - delete od; - return NULL; - } - - od->device = device; - return &od->base; - } - - return oss_open_default(error); -} - -static void -oss_output_finish(AudioOutput *ao) -{ - OssOutput *od = (OssOutput *)ao; - - delete od; -} - -#ifdef AFMT_S24_PACKED - -static bool -oss_output_enable(AudioOutput *ao, gcc_unused Error &error) +inline OssOutput * +OssOutput::Create(const ConfigBlock &block) { - OssOutput *od = (OssOutput *)ao; + const char *device = block.GetBlockValue("device"); + if (device != nullptr) + return new OssOutput(block, device); - od->pcm_export.Construct(); - return true; + return oss_open_default(); } -static void -oss_output_disable(AudioOutput *ao) +void +OssOutput::DoClose() { - OssOutput *od = (OssOutput *)ao; - - od->pcm_export.Destruct(); -} - -#endif - -static void -oss_close(OssOutput *od) -{ - if (od->fd >= 0) - close(od->fd); - od->fd = -1; + if (fd >= 0) + close(fd); + fd = -1; } /** @@ -257,23 +248,21 @@ */ enum oss_setup_result { SUCCESS, - ERROR, UNSUPPORTED, }; /** * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * returned. If the parameter is not supported, UNSUPPORTED is - * returned. Any other failure returns ERROR and allocates an #Error. + * returned. Any other failure throws std::runtime_error. */ static enum oss_setup_result oss_try_ioctl_r(int fd, unsigned long request, int *value_r, - const char *msg, Error &error) + const char *msg) { assert(fd >= 0); - assert(value_r != NULL); - assert(msg != NULL); - assert(!error.IsDefined()); + assert(value_r != nullptr); + assert(msg != nullptr); int ret = ioctl(fd, request, value_r); if (ret >= 0) @@ -282,43 +271,41 @@ if (errno == EINVAL) return UNSUPPORTED; - error.SetErrno(msg); - return ERROR; + throw MakeErrno(msg); } /** * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * returned. If the parameter is not supported, UNSUPPORTED is - * returned. Any other failure returns ERROR and allocates an #Error. + * returned. Any other failure throws std::runtime_error. */ static enum oss_setup_result oss_try_ioctl(int fd, unsigned long request, int value, - const char *msg, Error &error_r) + const char *msg) { - return oss_try_ioctl_r(fd, request, &value, msg, error_r); + return oss_try_ioctl_r(fd, request, &value, msg); } /** * Set up the channel number, and attempts to find alternatives if the * specified number is not supported. + * + * Throws #std::runtime_error on error. */ -static bool -oss_setup_channels(int fd, AudioFormat &audio_format, Error &error) +static void +oss_setup_channels(int fd, AudioFormat &audio_format) { const char *const msg = "Failed to set channel count"; int channels = audio_format.channels; enum oss_setup_result result = - oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error); + oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg); switch (result) { case SUCCESS: if (!audio_valid_channel_count(channels)) break; audio_format.channels = channels; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; @@ -331,89 +318,80 @@ channels = i; result = oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, - msg, error); + msg); switch (result) { case SUCCESS: if (!audio_valid_channel_count(channels)) break; audio_format.channels = channels; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; } } - error.Set(oss_output_domain, msg); - return false; + throw std::runtime_error(msg); } /** * Set up the sample rate, and attempts to find alternatives if the * specified sample rate is not supported. + * + * Throws #std::runtime_error on error. */ -static bool -oss_setup_sample_rate(int fd, AudioFormat &audio_format, - Error &error) +static void +oss_setup_sample_rate(int fd, AudioFormat &audio_format) { const char *const msg = "Failed to set sample rate"; int sample_rate = audio_format.sample_rate; enum oss_setup_result result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, - msg, error); + msg); switch (result) { case SUCCESS: if (!audio_valid_sample_rate(sample_rate)) break; audio_format.sample_rate = sample_rate; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; } - static const int sample_rates[] = { 48000, 44100, 0 }; + static constexpr int sample_rates[] = { 48000, 44100, 0 }; for (unsigned i = 0; sample_rates[i] != 0; ++i) { sample_rate = sample_rates[i]; if (sample_rate == (int)audio_format.sample_rate) continue; result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, - msg, error); + msg); switch (result) { case SUCCESS: if (!audio_valid_sample_rate(sample_rate)) break; audio_format.sample_rate = sample_rate; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; } } - error.Set(oss_output_domain, msg); - return false; + throw std::runtime_error(msg); } /** * Convert a MPD sample format to its OSS counterpart. Returns * AFMT_QUERY if there is no direct counterpart. */ +gcc_const static int -sample_format_to_oss(SampleFormat format) +sample_format_to_oss(SampleFormat format) noexcept { switch (format) { case SampleFormat::UNDEFINED: @@ -442,15 +420,17 @@ #endif } - return AFMT_QUERY; + assert(false); + gcc_unreachable(); } /** * Convert an OSS sample format to its MPD counterpart. Returns * SampleFormat::UNDEFINED if there is no direct counterpart. */ +gcc_const static SampleFormat -sample_format_from_oss(int format) +sample_format_from_oss(int format) noexcept { switch (format) { case AFMT_S8: @@ -488,11 +468,11 @@ static enum oss_setup_result oss_probe_sample_format(int fd, SampleFormat sample_format, SampleFormat *sample_format_r, - int *oss_format_r, + int *oss_format_r #ifdef AFMT_S24_PACKED - PcmExport &pcm_export, + , PcmExport &pcm_export #endif - Error &error) + ) { int oss_format = sample_format_to_oss(sample_format); if (oss_format == AFMT_QUERY) @@ -501,7 +481,7 @@ enum oss_setup_result result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, &oss_format, - "Failed to set sample format", error); + "Failed to set sample format"); #ifdef AFMT_S24_PACKED if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) { @@ -510,7 +490,7 @@ oss_format = AFMT_S24_PACKED; result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, &oss_format, - "Failed to set sample format", error); + "Failed to set sample format"); } #endif @@ -525,10 +505,13 @@ *oss_format_r = oss_format; #ifdef AFMT_S24_PACKED - pcm_export.Open(sample_format, 0, false, false, - oss_format == AFMT_S24_PACKED, - oss_format == AFMT_S24_PACKED && - !IsLittleEndian()); + PcmExport::Params params; + params.alsa_channel_order = true; + params.pack24 = oss_format == AFMT_S24_PACKED; + params.reverse_endian = oss_format == AFMT_S24_PACKED && + !IsLittleEndian(); + + pcm_export.Open(sample_format, 0, params); #endif return SUCCESS; @@ -538,41 +521,35 @@ * Set up the sample format, and attempts to find alternatives if the * specified format is not supported. */ -static bool +static void oss_setup_sample_format(int fd, AudioFormat &audio_format, - int *oss_format_r, + int *oss_format_r #ifdef AFMT_S24_PACKED - PcmExport &pcm_export, + , PcmExport &pcm_export #endif - Error &error) + ) { SampleFormat mpd_format; enum oss_setup_result result = oss_probe_sample_format(fd, audio_format.format, - &mpd_format, oss_format_r, + &mpd_format, oss_format_r #ifdef AFMT_S24_PACKED - pcm_export, + , pcm_export #endif - error); + ); switch (result) { case SUCCESS: audio_format.format = mpd_format; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; } - if (result != UNSUPPORTED) - return result == SUCCESS; - /* the requested sample format is not available - probe for other formats supported by MPD */ - static const SampleFormat sample_formats[] = { + static constexpr SampleFormat sample_formats[] = { SampleFormat::S24_P32, SampleFormat::S32, SampleFormat::S16, @@ -587,151 +564,120 @@ continue; result = oss_probe_sample_format(fd, mpd_format, - &mpd_format, oss_format_r, + &mpd_format, oss_format_r #ifdef AFMT_S24_PACKED - pcm_export, + , pcm_export #endif - error); + ); switch (result) { case SUCCESS: audio_format.format = mpd_format; - return true; - - case ERROR: - return false; + return; case UNSUPPORTED: break; } } - error.Set(oss_output_domain, "Failed to set sample format"); - return false; + throw std::runtime_error("Failed to set sample format"); } -/** - * Sets up the OSS device which was opened before. - */ -static bool -oss_setup(OssOutput *od, AudioFormat &audio_format, - Error &error) +inline void +OssOutput::Setup(AudioFormat &_audio_format) { - return oss_setup_channels(od->fd, audio_format, error) && - oss_setup_sample_rate(od->fd, audio_format, error) && - oss_setup_sample_format(od->fd, audio_format, &od->oss_format, + oss_setup_channels(fd, _audio_format); + oss_setup_sample_rate(fd, _audio_format); + oss_setup_sample_format(fd, _audio_format, &oss_format #ifdef AFMT_S24_PACKED - od->pcm_export, + , pcm_export #endif - error); + ); } /** * Reopen the device with the saved audio_format, without any probing. */ -static bool -oss_reopen(OssOutput *od, Error &error) -{ - assert(od->fd < 0); - - od->fd = open_cloexec(od->device, O_WRONLY, 0); - if (od->fd < 0) { - error.FormatErrno("Error opening OSS device \"%s\"", - od->device); - return false; - } +inline void +OssOutput::Reopen() +try { + assert(fd < 0); + + fd = open_cloexec(device, O_WRONLY, 0); + if (fd < 0) + throw FormatErrno("Error opening OSS device \"%s\"", device); enum oss_setup_result result; const char *const msg1 = "Failed to set channel count"; - result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS, - od->audio_format.channels, msg1, error); + result = oss_try_ioctl(fd, SNDCTL_DSP_CHANNELS, + audio_format.channels, msg1); if (result != SUCCESS) { - oss_close(od); - if (result == UNSUPPORTED) - error.Set(oss_output_domain, msg1); - return false; + DoClose(); + throw std::runtime_error(msg1); } const char *const msg2 = "Failed to set sample rate"; - result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED, - od->audio_format.sample_rate, msg2, error); + result = oss_try_ioctl(fd, SNDCTL_DSP_SPEED, + audio_format.sample_rate, msg2); if (result != SUCCESS) { - oss_close(od); - if (result == UNSUPPORTED) - error.Set(oss_output_domain, msg2); - return false; + DoClose(); + throw std::runtime_error(msg2); } const char *const msg3 = "Failed to set sample format"; - result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, - od->oss_format, - msg3, error); + result = oss_try_ioctl(fd, SNDCTL_DSP_SAMPLESIZE, + oss_format, + msg3); if (result != SUCCESS) { - oss_close(od); - if (result == UNSUPPORTED) - error.Set(oss_output_domain, msg3); - return false; + DoClose(); + throw std::runtime_error(msg3); } - - return true; +} catch (...) { + DoClose(); + throw; } -static bool -oss_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) -{ - OssOutput *od = (OssOutput *)ao; - - od->fd = open_cloexec(od->device, O_WRONLY, 0); - if (od->fd < 0) { - error.FormatErrno("Error opening OSS device \"%s\"", - od->device); - return false; - } - - if (!oss_setup(od, audio_format, error)) { - oss_close(od); - return false; - } - - od->audio_format = audio_format; - return true; -} +inline void +OssOutput::Open(AudioFormat &_audio_format) +try { + fd = open_cloexec(device, O_WRONLY, 0); + if (fd < 0) + throw FormatErrno("Error opening OSS device \"%s\"", device); -static void -oss_output_close(AudioOutput *ao) -{ - OssOutput *od = (OssOutput *)ao; + Setup(_audio_format); - oss_close(od); + audio_format = _audio_format; +} catch (...) { + DoClose(); + throw; } -static void -oss_output_cancel(AudioOutput *ao) +inline void +OssOutput::Cancel() { - OssOutput *od = (OssOutput *)ao; - - if (od->fd >= 0) { - ioctl(od->fd, SNDCTL_DSP_RESET, 0); - oss_close(od); + if (fd >= 0) { + ioctl(fd, SNDCTL_DSP_RESET, 0); + DoClose(); } + +#ifdef AFMT_S24_PACKED + pcm_export->Reset(); +#endif } -static size_t -oss_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +OssOutput::Play(const void *chunk, size_t size) { - OssOutput *od = (OssOutput *)ao; ssize_t ret; assert(size > 0); /* reopen the device since it was closed by dropBufferedAudio */ - if (od->fd < 0 && !oss_reopen(od, error)) - return 0; + if (fd < 0) + Reopen(); #ifdef AFMT_S24_PACKED - const auto e = od->pcm_export->Export({chunk, size}); + const auto e = pcm_export->Export({chunk, size}); chunk = e.data; size = e.size; #endif @@ -739,40 +685,40 @@ assert(size > 0); while (true) { - ret = write(od->fd, chunk, size); + ret = write(fd, chunk, size); if (ret > 0) { #ifdef AFMT_S24_PACKED - ret = od->pcm_export->CalcSourceSize(ret); + ret = pcm_export->CalcSourceSize(ret); #endif return ret; } - if (ret < 0 && errno != EINTR) { - error.FormatErrno("Write error on %s", od->device); - return 0; - } + if (ret < 0 && errno != EINTR) + throw FormatErrno("Write error on %s", device); } } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin oss_output_plugin = { "oss", oss_output_test_default_device, - oss_output_init, - oss_output_finish, + &Wrapper::Init, + &Wrapper::Finish, #ifdef AFMT_S24_PACKED - oss_output_enable, - oss_output_disable, + &Wrapper::Enable, + &Wrapper::Disable, #else nullptr, nullptr, #endif - oss_output_open, - oss_output_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, nullptr, - oss_output_play, + &Wrapper::Play, nullptr, - oss_output_cancel, + &Wrapper::Cancel, nullptr, &oss_mixer_plugin, diff -Nru mpd-0.19.21/src/output/plugins/OssOutputPlugin.hxx mpd-0.20.9/src/output/plugins/OssOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/OssOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OssOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/OSXOutputPlugin.cxx mpd-0.20.9/src/output/plugins/OSXOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/OSXOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OSXOutputPlugin.cxx 2017-05-16 05:10:59.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,17 +20,20 @@ #include "config.h" #include "OSXOutputPlugin.hxx" #include "../OutputAPI.hxx" -#include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" +#include "util/ScopeExit.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "system/ByteOrder.hxx" #include "Log.hxx" -#include +#include #include #include +#include + +#include struct OSXOutput { AudioOutput base; @@ -39,19 +42,35 @@ OSType component_subtype; /* only applicable with kAudioUnitSubType_HALOutput */ const char *device_name; + const char *channel_map; + bool hog_device; + bool sync_sample_rate; - AudioUnit au; - Mutex mutex; - Cond condition; + AudioDeviceID dev_id; + AudioComponentInstance au; + AudioStreamBasicDescription asbd; - DynamicFifoBuffer *buffer; + boost::lockfree::spsc_queue *ring_buffer; - OSXOutput() - :base(osx_output_plugin) {} + OSXOutput(const ConfigBlock &block); }; static constexpr Domain osx_output_domain("osx_output"); +static void +osx_os_status_to_cstring(OSStatus status, char *str, size_t size) { + CFErrorRef cferr = CFErrorCreate(nullptr, kCFErrorDomainOSStatus, status, nullptr); + CFStringRef cfstr = CFErrorCopyDescription(cferr); + if (!CFStringGetCString(cfstr, str, size, kCFStringEncodingUTF8)) { + /* conversion failed, return empty string */ + *str = '\0'; + } + if (cferr) + CFRelease(cferr); + if (cfstr) + CFRelease(cfstr); +} + static bool osx_output_test_default_device(void) { @@ -60,36 +79,50 @@ return true; } -static void -osx_output_configure(OSXOutput *oo, const config_param ¶m) +OSXOutput::OSXOutput(const ConfigBlock &block) + :base(osx_output_plugin, block) { - const char *device = param.GetBlockValue("device"); + const char *device = block.GetBlockValue("device"); - if (device == NULL || 0 == strcmp(device, "default")) { - oo->component_subtype = kAudioUnitSubType_DefaultOutput; - oo->device_name = NULL; + if (device == nullptr || 0 == strcmp(device, "default")) { + component_subtype = kAudioUnitSubType_DefaultOutput; + device_name = nullptr; } else if (0 == strcmp(device, "system")) { - oo->component_subtype = kAudioUnitSubType_SystemOutput; - oo->device_name = NULL; + component_subtype = kAudioUnitSubType_SystemOutput; + device_name = nullptr; } else { - oo->component_subtype = kAudioUnitSubType_HALOutput; + component_subtype = kAudioUnitSubType_HALOutput; /* XXX am I supposed to strdup() this? */ - oo->device_name = device; + device_name = device; } + + channel_map = block.GetBlockValue("channel_map"); + hog_device = block.GetBlockValue("hog_device", false); + sync_sample_rate = block.GetBlockValue("sync_sample_rate", false); } static AudioOutput * -osx_output_init(const config_param ¶m, Error &error) +osx_output_init(const ConfigBlock &block) { - OSXOutput *oo = new OSXOutput(); - if (!oo->base.Configure(param, error)) { - delete oo; - return NULL; - } + OSXOutput *oo = new OSXOutput(block); - osx_output_configure(oo, param); + AudioObjectPropertyAddress aopa = { + kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMaster + }; + + AudioDeviceID dev_id = kAudioDeviceUnknown; + UInt32 dev_id_size = sizeof(dev_id); + AudioObjectGetPropertyData(kAudioObjectSystemObject, + &aopa, + 0, + NULL, + &dev_id_size, + &dev_id); + oo->dev_id = dev_id; return &oo->base; } @@ -102,60 +135,323 @@ delete oo; } -static bool -osx_output_set_device(OSXOutput *oo, Error &error) +static void +osx_output_parse_channel_map( + const char *device_name, + const char *channel_map_str, + SInt32 channel_map[], + UInt32 num_channels) +{ + char *endptr; + unsigned int inserted_channels = 0; + bool want_number = true; + + while (*channel_map_str) { + if (inserted_channels >= num_channels) + throw FormatRuntimeError("%s: channel map contains more than %u entries or trailing garbage", + device_name, num_channels); + + if (!want_number && *channel_map_str == ',') { + ++channel_map_str; + want_number = true; + continue; + } + + if (want_number && + (isdigit(*channel_map_str) || *channel_map_str == '-') + ) { + channel_map[inserted_channels] = strtol(channel_map_str, &endptr, 10); + if (channel_map[inserted_channels] < -1) + throw FormatRuntimeError("%s: channel map value %d not allowed (must be -1 or greater)", + device_name, channel_map[inserted_channels]); + + channel_map_str = endptr; + want_number = false; + FormatDebug(osx_output_domain, + "%s: channel_map[%u] = %d", + device_name, inserted_channels, channel_map[inserted_channels]); + ++inserted_channels; + continue; + } + + throw FormatRuntimeError("%s: invalid character '%c' in channel map", + device_name, *channel_map_str); + } + + if (inserted_channels < num_channels) + throw FormatRuntimeError("%s: channel map contains less than %u entries", + device_name, num_channels); +} + +static void +osx_output_set_channel_map(OSXOutput *oo) +{ + AudioStreamBasicDescription desc; + OSStatus status; + UInt32 size, num_channels; + char errormsg[1024]; + + size = sizeof(desc); + memset(&desc, 0, size); + status = AudioUnitGetProperty(oo->au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 0, + &desc, + &size); + if (status != noErr) { + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("%s: unable to get number of output device channels: %s", + oo->device_name, errormsg); + } + + num_channels = desc.mChannelsPerFrame; + std::unique_ptr channel_map(new SInt32[num_channels]); + osx_output_parse_channel_map(oo->device_name, + oo->channel_map, + channel_map.get(), + num_channels); + + size = num_channels * sizeof(SInt32); + status = AudioUnitSetProperty(oo->au, + kAudioOutputUnitProperty_ChannelMap, + kAudioUnitScope_Input, + 0, + channel_map.get(), + size); + if (status != noErr) { + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("%s: unable to set channel map: %s", oo->device_name, errormsg); + } +} + +static void +osx_output_sync_device_sample_rate(AudioDeviceID dev_id, AudioStreamBasicDescription desc) +{ + FormatDebug(osx_output_domain, "Syncing sample rate."); + AudioObjectPropertyAddress aopa = { + kAudioDevicePropertyAvailableNominalSampleRates, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMaster + }; + + UInt32 property_size; + OSStatus err = AudioObjectGetPropertyDataSize(dev_id, + &aopa, + 0, + NULL, + &property_size); + + int count = property_size/sizeof(AudioValueRange); + AudioValueRange ranges[count]; + property_size = sizeof(ranges); + err = AudioObjectGetPropertyData(dev_id, + &aopa, + 0, + NULL, + &property_size, + &ranges); + // Get the maximum sample rate as fallback. + Float64 sample_rate = .0; + for (int i = 0; i < count; i++) { + if (ranges[i].mMaximum > sample_rate) + sample_rate = ranges[i].mMaximum; + } + + // Now try to see if the device support our format sample rate. + // For some high quality media samples, the frame rate may exceed + // device capability. In this case, we let CoreAudio downsample + // by decimation with an integer factor ranging from 1 to 4. + for (int f = 4; f > 0; f--) { + Float64 rate = desc.mSampleRate / f; + for (int i = 0; i < count; i++) { + if (ranges[i].mMinimum <= rate + && rate <= ranges[i].mMaximum) { + sample_rate = rate; + break; + } + } + } + + aopa.mSelector = kAudioDevicePropertyNominalSampleRate, + + err = AudioObjectSetPropertyData(dev_id, + &aopa, + 0, + NULL, + sizeof(&desc.mSampleRate), + &sample_rate); + if (err != noErr) { + FormatWarning(osx_output_domain, + "Failed to synchronize the sample rate: %d", + err); + } else { + FormatDebug(osx_output_domain, + "Sample rate synced to %f Hz.", + sample_rate); + } +} + +static OSStatus +osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt32 *frame_size) +{ + AudioValueRange value_range = {0, 0}; + UInt32 property_size = sizeof(AudioValueRange); + OSStatus err = AudioUnitGetProperty(au, + kAudioDevicePropertyBufferFrameSizeRange, + kAudioUnitScope_Global, + 0, + &value_range, + &property_size); + if (err != noErr) + return err; + + UInt32 buffer_frame_size = value_range.mMaximum; + err = AudioUnitSetProperty(au, + kAudioDevicePropertyBufferFrameSize, + kAudioUnitScope_Global, + 0, + &buffer_frame_size, + sizeof(buffer_frame_size)); + if (err != noErr) + FormatWarning(osx_output_domain, + "Failed to set maximum buffer size: %d", + err); + + property_size = sizeof(buffer_frame_size); + err = AudioUnitGetProperty(au, + kAudioDevicePropertyBufferFrameSize, + kAudioUnitScope_Global, + 0, + &buffer_frame_size, + &property_size); + if (err != noErr) { + FormatWarning(osx_output_domain, + "Cannot get the buffer frame size: %d", + err); + return err; + } + + buffer_frame_size *= desc.mBytesPerFrame; + + // We set the frame size to a power of two integer that + // is larger than buffer_frame_size. + while (*frame_size < buffer_frame_size + 1) { + *frame_size <<= 1; + } + + return noErr; +} + +static void +osx_output_hog_device(AudioDeviceID dev_id, bool hog) +{ + pid_t hog_pid; + AudioObjectPropertyAddress aopa = { + kAudioDevicePropertyHogMode, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMaster + }; + UInt32 size = sizeof(hog_pid); + OSStatus err = AudioObjectGetPropertyData(dev_id, + &aopa, + 0, + NULL, + &size, + &hog_pid); + if (err != noErr) { + FormatDebug(osx_output_domain, + "Cannot get hog information: %d", + err); + return; + } + if (hog) { + if (hog_pid != -1) { + FormatDebug(osx_output_domain, + "Device is already hogged."); + return; + } + } else { + if (hog_pid != getpid()) { + FormatDebug(osx_output_domain, + "Device is not owned by this process."); + return; + } + } + hog_pid = hog ? getpid() : -1; + size = sizeof(hog_pid); + err = AudioObjectSetPropertyData(dev_id, + &aopa, + 0, + NULL, + size, + &hog_pid); + if (err != noErr) { + FormatDebug(osx_output_domain, + "Cannot hog the device: %d", + err); + } else { + FormatDebug(osx_output_domain, + hog_pid == -1 ? "Device is unhogged" + : "Device is hogged"); + } +} + + +static void +osx_output_set_device(OSXOutput *oo) { - bool ret = true; OSStatus status; UInt32 size, numdevices; - AudioDeviceID *deviceids = NULL; + AudioObjectPropertyAddress propaddr; + CFStringRef cfname = nullptr; + char errormsg[1024]; char name[256]; unsigned int i; + AtScopeExit(&cfname) { + if (cfname) + CFRelease(cfname); + }; + if (oo->component_subtype != kAudioUnitSubType_HALOutput) - goto done; + return; /* how many audio devices are there? */ - status = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, - &size, - NULL); + propaddr = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to determine number of OS X audio devices: %s", - GetMacOSStatusCommentString(status)); - ret = false; - goto done; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to determine number of OS X audio devices: %s", + errormsg); } /* what are the available audio device IDs? */ numdevices = size / sizeof(AudioDeviceID); - deviceids = new AudioDeviceID[numdevices]; - status = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, - &size, - deviceids); + std::unique_ptr deviceids(new AudioDeviceID[numdevices]); + status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size, deviceids.get()); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to determine OS X audio device IDs: %s", - GetMacOSStatusCommentString(status)); - ret = false; - goto done; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to determine OS X audio device IDs: %s", + errormsg); } /* which audio device matches oo->device_name? */ + propaddr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + size = sizeof(CFStringRef); for (i = 0; i < numdevices; i++) { - size = sizeof(name); - status = AudioDeviceGetProperty(deviceids[i], 0, false, - kAudioDevicePropertyDeviceName, - &size, name); + status = AudioObjectGetPropertyData(deviceids[i], &propaddr, 0, nullptr, &size, &cfname); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to determine OS X device name " - "(device %u): %s", - (unsigned int) deviceids[i], - GetMacOSStatusCommentString(status)); - ret = false; - goto done; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to determine OS X device name " + "(device %u): %s", + (unsigned int) deviceids[i], + errormsg); } + + if (!CFStringGetCString(cfname, name, sizeof(name), kCFStringEncodingUTF8)) + throw std::runtime_error("Unable to convert device name from CFStringRef to char*"); + if (strcmp(oo->device_name, name) == 0) { FormatDebug(osx_output_domain, "found matching device: ID=%u, name=%s", @@ -168,7 +464,7 @@ "Found no audio device with name '%s' " "(will use default audio device)", oo->device_name); - goto done; + return; } status = AudioUnitSetProperty(oo->au, @@ -178,110 +474,79 @@ &(deviceids[i]), sizeof(AudioDeviceID)); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to set OS X audio output device: %s", - GetMacOSStatusCommentString(status)); - ret = false; - goto done; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to set OS X audio output device: %s", + errormsg); } + oo->dev_id = deviceids[i]; FormatDebug(osx_output_domain, "set OS X audio output device ID=%u, name=%s", (unsigned)deviceids[i], name); -done: - delete[] deviceids; - return ret; + if (oo->channel_map) + osx_output_set_channel_map(oo); } + +/* + This function (the 'render callback' osx_render) is called by the + OS X audio subsystem (CoreAudio) to request audio data that will be + played by the audio hardware. This function has hard time constraints + so it cannot do IO (debug statements) or memory allocations. +*/ + static OSStatus osx_render(void *vdata, gcc_unused AudioUnitRenderActionFlags *io_action_flags, gcc_unused const AudioTimeStamp *in_timestamp, gcc_unused UInt32 in_bus_number, - gcc_unused UInt32 in_number_frames, + UInt32 in_number_frames, AudioBufferList *buffer_list) { OSXOutput *od = (OSXOutput *) vdata; - AudioBuffer *buffer = &buffer_list->mBuffers[0]; - size_t buffer_size = buffer->mDataByteSize; - assert(od->buffer != NULL); - - od->mutex.lock(); - - auto src = od->buffer->Read(); - if (!src.IsEmpty()) { - if (src.size > buffer_size) - src.size = buffer_size; - - memcpy(buffer->mData, src.data, src.size); - od->buffer->Consume(src.size); - } - - od->condition.signal(); - od->mutex.unlock(); - - buffer->mDataByteSize = src.size; - - unsigned i; - for (i = 1; i < buffer_list->mNumberBuffers; ++i) { - buffer = &buffer_list->mBuffers[i]; - buffer->mDataByteSize = 0; - } - - return 0; + int count = in_number_frames * od->asbd.mBytesPerFrame; + buffer_list->mBuffers[0].mDataByteSize = + od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData, + count); + return noErr; } -static bool -osx_output_enable(AudioOutput *ao, Error &error) +static void +osx_output_enable(AudioOutput *ao) { + char errormsg[1024]; OSXOutput *oo = (OSXOutput *)ao; - ComponentDescription desc; + AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = oo->component_subtype; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; - Component comp = FindNextComponent(NULL, &desc); - if (comp == 0) { - error.Set(osx_output_domain, - "Error finding OS X component"); - return false; - } + AudioComponent comp = AudioComponentFindNext(nullptr, &desc); + if (comp == 0) + throw std::runtime_error("Error finding OS X component"); - OSStatus status = OpenAComponent(comp, &oo->au); + OSStatus status = AudioComponentInstanceNew(comp, &oo->au); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to open OS X component: %s", - GetMacOSStatusCommentString(status)); - return false; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to open OS X component: %s", + errormsg); } - if (!osx_output_set_device(oo, error)) { - CloseComponent(oo->au); - return false; + try { + osx_output_set_device(oo); + } catch (...) { + AudioComponentInstanceDispose(oo->au); + throw; } - AURenderCallbackStruct callback; - callback.inputProc = osx_render; - callback.inputProcRefCon = oo; - - ComponentResult result = - AudioUnitSetProperty(oo->au, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, 0, - &callback, sizeof(callback)); - if (result != noErr) { - CloseComponent(oo->au); - error.Set(osx_output_domain, result, - "unable to set callback for OS X audio unit"); - return false; + if (oo->hog_device) { + osx_output_hog_device(oo->dev_id, true); } - - return true; } static void @@ -289,16 +554,11 @@ { OSXOutput *oo = (OSXOutput *)ao; - CloseComponent(oo->au); -} + AudioComponentInstanceDispose(oo->au); -static void -osx_output_cancel(AudioOutput *ao) -{ - OSXOutput *od = (OSXOutput *)ao; - - const ScopeLock protect(od->mutex); - od->buffer->Clear(); + if (oo->hog_device) { + osx_output_hog_device(oo->dev_id, false); + } } static void @@ -309,107 +569,113 @@ AudioOutputUnitStop(od->au); AudioUnitUninitialize(od->au); - delete od->buffer; + delete od->ring_buffer; } -static bool -osx_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +static void +osx_output_open(AudioOutput *ao, AudioFormat &audio_format) { + char errormsg[1024]; OSXOutput *od = (OSXOutput *)ao; - AudioStreamBasicDescription stream_description; - stream_description.mSampleRate = audio_format.sample_rate; - stream_description.mFormatID = kAudioFormatLinearPCM; - stream_description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + memset(&od->asbd, 0, sizeof(od->asbd)); + od->asbd.mSampleRate = audio_format.sample_rate; + od->asbd.mFormatID = kAudioFormatLinearPCM; + od->asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; switch (audio_format.format) { case SampleFormat::S8: - stream_description.mBitsPerChannel = 8; + od->asbd.mBitsPerChannel = 8; break; case SampleFormat::S16: - stream_description.mBitsPerChannel = 16; + od->asbd.mBitsPerChannel = 16; break; case SampleFormat::S32: - stream_description.mBitsPerChannel = 32; + od->asbd.mBitsPerChannel = 32; break; default: audio_format.format = SampleFormat::S32; - stream_description.mBitsPerChannel = 32; + od->asbd.mBitsPerChannel = 32; break; } if (IsBigEndian()) - stream_description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; + od->asbd.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; - stream_description.mBytesPerPacket = audio_format.GetFrameSize(); - stream_description.mFramesPerPacket = 1; - stream_description.mBytesPerFrame = stream_description.mBytesPerPacket; - stream_description.mChannelsPerFrame = audio_format.channels; + od->asbd.mBytesPerPacket = audio_format.GetFrameSize(); + od->asbd.mFramesPerPacket = 1; + od->asbd.mBytesPerFrame = od->asbd.mBytesPerPacket; + od->asbd.mChannelsPerFrame = audio_format.channels; + + if (od->sync_sample_rate) { + osx_output_sync_device_sample_rate(od->dev_id, od->asbd); + } - ComponentResult result = + OSStatus status = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, - &stream_description, - sizeof(stream_description)); - if (result != noErr) { - error.Set(osx_output_domain, result, - "Unable to set format on OS X device"); - return false; + &od->asbd, + sizeof(od->asbd)); + if (status != noErr) + throw std::runtime_error("Unable to set format on OS X device"); + + AURenderCallbackStruct callback; + callback.inputProc = osx_render; + callback.inputProcRefCon = od; + + status = + AudioUnitSetProperty(od->au, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, 0, + &callback, sizeof(callback)); + if (status != noErr) { + AudioComponentInstanceDispose(od->au); + throw std::runtime_error("unable to set callback for OS X audio unit"); + } + + status = AudioUnitInitialize(od->au); + if (status != noErr) { + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to initialize OS X audio unit: %s", + errormsg); } - OSStatus status = AudioUnitInitialize(od->au); + UInt32 buffer_frame_size = 1; + status = osx_output_set_buffer_size(od->au, od->asbd, &buffer_frame_size); if (status != noErr) { - error.Format(osx_output_domain, status, - "Unable to initialize OS X audio unit: %s", - GetMacOSStatusCommentString(status)); - return false; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("Unable to set frame size: %s", + errormsg); } - /* create a buffer of 1s */ - od->buffer = new DynamicFifoBuffer(audio_format.sample_rate * - audio_format.GetFrameSize()); + od->ring_buffer = new boost::lockfree::spsc_queue(buffer_frame_size); status = AudioOutputUnitStart(od->au); if (status != 0) { AudioUnitUninitialize(od->au); - error.Format(osx_output_domain, status, - "unable to start audio output: %s", - GetMacOSStatusCommentString(status)); - return false; + osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); + throw FormatRuntimeError("unable to start audio output: %s", + errormsg); } - - return true; } static size_t -osx_output_play(AudioOutput *ao, const void *chunk, size_t size, - gcc_unused Error &error) +osx_output_play(AudioOutput *ao, const void *chunk, size_t size) { OSXOutput *od = (OSXOutput *)ao; + return od->ring_buffer->push((uint8_t *)chunk, size); +} - const ScopeLock protect(od->mutex); - - DynamicFifoBuffer::Range dest; - while (true) { - dest = od->buffer->Write(); - if (!dest.IsEmpty()) - break; - - /* wait for some free space in the buffer */ - od->condition.wait(od->mutex); - } - - if (size > dest.size) - size = dest.size; - - memcpy(dest.data, chunk, size); - od->buffer->Append(size); - - return size; +static std::chrono::steady_clock::duration +osx_output_delay(AudioOutput *ao) noexcept +{ + OSXOutput *od = (OSXOutput *)ao; + return od->ring_buffer->write_available() + ? std::chrono::steady_clock::duration::zero() + : std::chrono::milliseconds(25); } const struct AudioOutputPlugin osx_output_plugin = { @@ -421,11 +687,11 @@ osx_output_disable, osx_output_open, osx_output_close, - nullptr, + osx_output_delay, nullptr, osx_output_play, nullptr, - osx_output_cancel, + nullptr, nullptr, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/OSXOutputPlugin.hxx mpd-0.20.9/src/output/plugins/OSXOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/OSXOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/OSXOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/PipeOutputPlugin.cxx mpd-0.20.9/src/output/plugins/PipeOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/PipeOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/PipeOutputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,119 +20,82 @@ #include "config.h" #include "PipeOutputPlugin.hxx" #include "../OutputAPI.hxx" -#include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "../Wrapper.hxx" +#include "system/Error.hxx" #include +#include #include -struct PipeOutput { +class PipeOutput { + friend struct AudioOutputWrapper; + AudioOutput base; - std::string cmd; + const std::string cmd; FILE *fh; - PipeOutput() - :base(pipe_output_plugin) {} + PipeOutput(const ConfigBlock &block); - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); - } +public: + static PipeOutput *Create(const ConfigBlock &block); - bool Configure(const config_param ¶m, Error &error); -}; + void Open(AudioFormat &audio_format); -inline bool -PipeOutput::Configure(const config_param ¶m, Error &error) -{ - cmd = param.GetBlockValue("command", ""); - if (cmd.empty()) { - error.Set(config_domain, - "No \"command\" parameter specified"); - return false; + void Close() { + pclose(fh); } - return true; -} + size_t Play(const void *chunk, size_t size); +}; -static AudioOutput * -pipe_output_init(const config_param ¶m, Error &error) +PipeOutput::PipeOutput(const ConfigBlock &block) + :base(pipe_output_plugin, block), + cmd(block.GetBlockValue("command", "")) { - PipeOutput *pd = new PipeOutput(); - - if (!pd->Initialize(param, error)) { - delete pd; - return nullptr; - } - - if (!pd->Configure(param, error)) { - delete pd; - return nullptr; - } - - return &pd->base; + if (cmd.empty()) + throw std::runtime_error("No \"command\" parameter specified"); } -static void -pipe_output_finish(AudioOutput *ao) +inline PipeOutput * +PipeOutput::Create(const ConfigBlock &block) { - PipeOutput *pd = (PipeOutput *)ao; - - delete pd; + return new PipeOutput(block); } -static bool -pipe_output_open(AudioOutput *ao, - gcc_unused AudioFormat &audio_format, - Error &error) +inline void +PipeOutput::Open(gcc_unused AudioFormat &audio_format) { - PipeOutput *pd = (PipeOutput *)ao; - - pd->fh = popen(pd->cmd.c_str(), "w"); - if (pd->fh == nullptr) { - error.FormatErrno("Error opening pipe \"%s\"", - pd->cmd.c_str()); - return false; - } - - return true; + fh = popen(cmd.c_str(), "w"); + if (fh == nullptr) + throw FormatErrno("Error opening pipe \"%s\"", cmd.c_str()); } -static void -pipe_output_close(AudioOutput *ao) +inline size_t +PipeOutput::Play(const void *chunk, size_t size) { - PipeOutput *pd = (PipeOutput *)ao; + size_t nbytes = fwrite(chunk, 1, size, fh); + if (nbytes == 0) + throw MakeErrno("Write error on pipe"); - pclose(pd->fh); + return nbytes; } -static size_t -pipe_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - PipeOutput *pd = (PipeOutput *)ao; - size_t ret; - - ret = fwrite(chunk, 1, size, pd->fh); - if (ret == 0) - error.SetErrno("Write error on pipe"); - - return ret; -} +typedef AudioOutputWrapper Wrapper; const struct AudioOutputPlugin pipe_output_plugin = { "pipe", nullptr, - pipe_output_init, - pipe_output_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - pipe_output_open, - pipe_output_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, nullptr, - pipe_output_play, + &Wrapper::Play, nullptr, nullptr, nullptr, diff -Nru mpd-0.19.21/src/output/plugins/PipeOutputPlugin.hxx mpd-0.20.9/src/output/plugins/PipeOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/PipeOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/PipeOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/PulseOutputPlugin.cxx mpd-0.20.9/src/output/plugins/PulseOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/PulseOutputPlugin.cxx 2016-08-15 08:02:29.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/PulseOutputPlugin.cxx 2017-05-16 05:11:42.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,14 @@ #include "config.h" #include "PulseOutputPlugin.hxx" +#include "lib/pulse/Domain.hxx" +#include "lib/pulse/Error.hxx" +#include "lib/pulse/LogError.hxx" +#include "lib/pulse/LockGuard.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "mixer/MixerList.hxx" #include "mixer/plugins/PulseMixerPlugin.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include "Log.hxx" #include @@ -31,110 +34,218 @@ #include #include #include -#include #include +#include + #include #include #include #define MPD_PULSE_NAME "Music Player Daemon" -struct PulseOutput { +class PulseOutput { + friend struct AudioOutputWrapper; + AudioOutput base; const char *name; const char *server; const char *sink; - PulseMixer *mixer; + PulseMixer *mixer = nullptr; - struct pa_threaded_mainloop *mainloop; + struct pa_threaded_mainloop *mainloop = nullptr; struct pa_context *context; - struct pa_stream *stream; + struct pa_stream *stream = nullptr; size_t writable; - PulseOutput() - :base(pulse_output_plugin) {} -}; + explicit PulseOutput(const ConfigBlock &block); -static constexpr Domain pulse_output_domain("pulse_output"); +public: + void SetMixer(PulseMixer &_mixer); -static void -SetError(Error &error, pa_context *context, const char *msg) -{ - const int e = pa_context_errno(context); - error.Format(pulse_output_domain, e, "%s: %s", msg, pa_strerror(e)); -} + void ClearMixer(gcc_unused PulseMixer &old_mixer) { + assert(mixer == &old_mixer); -void -pulse_output_lock(PulseOutput &po) + mixer = nullptr; + } + + void SetVolume(const pa_cvolume &volume); + + struct pa_threaded_mainloop *GetMainloop() { + return mainloop; + } + + void OnContextStateChanged(pa_context_state_t new_state); + void OnServerLayoutChanged(pa_subscription_event_type_t t, + uint32_t idx); + void OnStreamSuspended(pa_stream *_stream); + void OnStreamStateChanged(pa_stream *_stream, + pa_stream_state_t new_state); + void OnStreamWrite(size_t nbytes); + + void OnStreamSuccess() { + Signal(); + } + + static bool TestDefaultDevice(); + + static PulseOutput *Create(const ConfigBlock &block); + + void Enable(); + void Disable(); + + void Open(AudioFormat &audio_format); + void Close(); + + std::chrono::steady_clock::duration Delay() noexcept; + size_t Play(const void *chunk, size_t size); + void Cancel(); + bool Pause(); + +private: + /** + * Attempt to connect asynchronously to the PulseAudio server. + * + * Throws #std::runtime_error on error. + */ + void Connect(); + + /** + * Create, set up and connect a context. + * + * Caller must lock the main loop. + * + * Throws #std::runtime_error on error. + */ + void SetupContext(); + + /** + * Frees and clears the context. + * + * Caller must lock the main loop. + */ + void DeleteContext(); + + void Signal() { + pa_threaded_mainloop_signal(mainloop, 0); + } + + /** + * Check if the context is (already) connected, and waits if + * not. If the context has been disconnected, retry to + * connect. + * + * Caller must lock the main loop. + * + * Throws #std::runtime_error on error. + */ + void WaitConnection(); + + /** + * Create, set up and connect a context. + * + * Caller must lock the main loop. + * + * Throws #std::runtime_error on error. + */ + void SetupStream(const pa_sample_spec &ss); + + /** + * Frees and clears the stream. + */ + void DeleteStream(); + + /** + * Check if the stream is (already) connected, and waits if + * not. The mainloop must be locked before calling this + * function. + * + * Throws #std::runtime_error on error. + */ + void WaitStream(); + + /** + * Sets cork mode on the stream. + * + * Throws #std::runtime_error on error. + */ + void StreamPause(bool pause); +}; + +PulseOutput::PulseOutput(const ConfigBlock &block) + :base(pulse_output_plugin, block), + name(block.GetBlockValue("name", "mpd_pulse")), + server(block.GetBlockValue("server")), + sink(block.GetBlockValue("sink")) { - pa_threaded_mainloop_lock(po.mainloop); + setenv("PULSE_PROP_media.role", "music", true); + setenv("PULSE_PROP_application.icon_name", "mpd", true); } -void -pulse_output_unlock(PulseOutput &po) +struct pa_threaded_mainloop * +pulse_output_get_mainloop(PulseOutput &po) { - pa_threaded_mainloop_unlock(po.mainloop); + return po.GetMainloop(); } -void -pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm) +inline void +PulseOutput::SetMixer(PulseMixer &_mixer) { - assert(po.mixer == nullptr); + assert(mixer == nullptr); - po.mixer = ± + mixer = &_mixer; - if (po.mainloop == nullptr) + if (mainloop == nullptr) return; - pa_threaded_mainloop_lock(po.mainloop); + Pulse::LockGuard lock(mainloop); - if (po.context != nullptr && - pa_context_get_state(po.context) == PA_CONTEXT_READY) { - pulse_mixer_on_connect(pm, po.context); - - if (po.stream != nullptr && - pa_stream_get_state(po.stream) == PA_STREAM_READY) - pulse_mixer_on_change(pm, po.context, po.stream); + if (context != nullptr && + pa_context_get_state(context) == PA_CONTEXT_READY) { + pulse_mixer_on_connect(_mixer, context); + + if (stream != nullptr && + pa_stream_get_state(stream) == PA_STREAM_READY) + pulse_mixer_on_change(_mixer, context, stream); } - - pa_threaded_mainloop_unlock(po.mainloop); } void -pulse_output_clear_mixer(PulseOutput &po, gcc_unused PulseMixer &pm) +pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm) { - assert(po.mixer == &pm); + po.SetMixer(pm); +} - po.mixer = nullptr; +void +pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm) +{ + po.ClearMixer(pm); } -bool -pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume, - Error &error) +inline void +PulseOutput::SetVolume(const pa_cvolume &volume) { - pa_operation *o; + if (context == nullptr || stream == nullptr || + pa_stream_get_state(stream) != PA_STREAM_READY) + throw std::runtime_error("disconnected"); - if (po.context == nullptr || po.stream == nullptr || - pa_stream_get_state(po.stream) != PA_STREAM_READY) { - error.Set(pulse_output_domain, "disconnected"); - return false; - } - - o = pa_context_set_sink_input_volume(po.context, - pa_stream_get_index(po.stream), - volume, nullptr, nullptr); - if (o == nullptr) { - SetError(error, po.context, - "failed to set PulseAudio volume"); - return false; - } + pa_operation *o = + pa_context_set_sink_input_volume(context, + pa_stream_get_index(stream), + &volume, nullptr, nullptr); + if (o == nullptr) + throw std::runtime_error("failed to set PulseAudio volume"); pa_operation_unref(o); - return true; +} + +void +pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume) +{ + return po.SetVolume(*volume); } /** @@ -169,32 +280,30 @@ pulse_output_stream_success_cb(gcc_unused pa_stream *s, gcc_unused int success, void *userdata) { - PulseOutput *po = (PulseOutput *)userdata; + PulseOutput &po = *(PulseOutput *)userdata; - pa_threaded_mainloop_signal(po->mainloop, 0); + po.OnStreamSuccess(); } -static void -pulse_output_context_state_cb(struct pa_context *context, void *userdata) +inline void +PulseOutput::OnContextStateChanged(pa_context_state_t new_state) { - PulseOutput *po = (PulseOutput *)userdata; - - switch (pa_context_get_state(context)) { + switch (new_state) { case PA_CONTEXT_READY: - if (po->mixer != nullptr) - pulse_mixer_on_connect(*po->mixer, context); + if (mixer != nullptr) + pulse_mixer_on_connect(*mixer, context); - pa_threaded_mainloop_signal(po->mainloop, 0); + Signal(); break; case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: - if (po->mixer != nullptr) - pulse_mixer_on_disconnect(*po->mixer); + if (mixer != nullptr) + pulse_mixer_on_disconnect(*mixer); /* the caller thread might be waiting for these states */ - pa_threaded_mainloop_signal(po->mainloop, 0); + Signal(); break; case PA_CONTEXT_UNCONNECTED: @@ -206,289 +315,237 @@ } static void -pulse_output_subscribe_cb(pa_context *context, - pa_subscription_event_type_t t, - uint32_t idx, void *userdata) +pulse_output_context_state_cb(struct pa_context *context, void *userdata) +{ + PulseOutput &po = *(PulseOutput *)userdata; + + po.OnContextStateChanged(pa_context_get_state(context)); +} + +inline void +PulseOutput::OnServerLayoutChanged(pa_subscription_event_type_t t, + uint32_t idx) { - PulseOutput *po = (PulseOutput *)userdata; pa_subscription_event_type_t facility = pa_subscription_event_type_t(t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK); pa_subscription_event_type_t type = pa_subscription_event_type_t(t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); - if (po->mixer != nullptr && + if (mixer != nullptr && facility == PA_SUBSCRIPTION_EVENT_SINK_INPUT && - po->stream != nullptr && - pa_stream_get_state(po->stream) == PA_STREAM_READY && - idx == pa_stream_get_index(po->stream) && + stream != nullptr && + pa_stream_get_state(stream) == PA_STREAM_READY && + idx == pa_stream_get_index(stream) && (type == PA_SUBSCRIPTION_EVENT_NEW || type == PA_SUBSCRIPTION_EVENT_CHANGE)) - pulse_mixer_on_change(*po->mixer, context, po->stream); + pulse_mixer_on_change(*mixer, context, stream); } -/** - * Attempt to connect asynchronously to the PulseAudio server. - * - * @return true on success, false on error - */ -static bool -pulse_output_connect(PulseOutput *po, Error &error) +static void +pulse_output_subscribe_cb(gcc_unused pa_context *context, + pa_subscription_event_type_t t, + uint32_t idx, void *userdata) { - assert(po != nullptr); - assert(po->context != nullptr); + PulseOutput &po = *(PulseOutput *)userdata; - if (pa_context_connect(po->context, po->server, - (pa_context_flags_t)0, nullptr) < 0) { - SetError(error, po->context, - "pa_context_connect() has failed"); - return false; - } - - return true; + po.OnServerLayoutChanged(t, idx); } -/** - * Frees and clears the stream. - */ -static void -pulse_output_delete_stream(PulseOutput *po) +inline void +PulseOutput::Connect() { - assert(po != nullptr); - assert(po->stream != nullptr); - - pa_stream_set_suspended_callback(po->stream, nullptr, nullptr); - - pa_stream_set_state_callback(po->stream, nullptr, nullptr); - pa_stream_set_write_callback(po->stream, nullptr, nullptr); + assert(context != nullptr); - pa_stream_disconnect(po->stream); - pa_stream_unref(po->stream); - po->stream = nullptr; + if (pa_context_connect(context, server, + (pa_context_flags_t)0, nullptr) < 0) + throw MakePulseError(context, + "pa_context_connect() has failed"); } -/** - * Frees and clears the context. - * - * Caller must lock the main loop. - */ -static void -pulse_output_delete_context(PulseOutput *po) +void +PulseOutput::DeleteStream() { - assert(po != nullptr); - assert(po->context != nullptr); + assert(stream != nullptr); - pa_context_set_state_callback(po->context, nullptr, nullptr); - pa_context_set_subscribe_callback(po->context, nullptr, nullptr); + pa_stream_set_suspended_callback(stream, nullptr, nullptr); - pa_context_disconnect(po->context); - pa_context_unref(po->context); - po->context = nullptr; + pa_stream_set_state_callback(stream, nullptr, nullptr); + pa_stream_set_write_callback(stream, nullptr, nullptr); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = nullptr; } -/** - * Create, set up and connect a context. - * - * Caller must lock the main loop. - * - * @return true on success, false on error - */ -static bool -pulse_output_setup_context(PulseOutput *po, Error &error) +void +PulseOutput::DeleteContext() { - assert(po != nullptr); - assert(po->mainloop != nullptr); + assert(context != nullptr); - po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop), - MPD_PULSE_NAME); - if (po->context == nullptr) { - error.Set(pulse_output_domain, "pa_context_new() has failed"); - return false; - } - - pa_context_set_state_callback(po->context, - pulse_output_context_state_cb, po); - pa_context_set_subscribe_callback(po->context, - pulse_output_subscribe_cb, po); - - if (!pulse_output_connect(po, error)) { - pulse_output_delete_context(po); - return false; - } + pa_context_set_state_callback(context, nullptr, nullptr); + pa_context_set_subscribe_callback(context, nullptr, nullptr); - return true; + pa_context_disconnect(context); + pa_context_unref(context); + context = nullptr; } -static AudioOutput * -pulse_output_init(const config_param ¶m, Error &error) +void +PulseOutput::SetupContext() { - PulseOutput *po; + assert(mainloop != nullptr); - setenv("PULSE_PROP_media.role", "music", true); - setenv("PULSE_PROP_application.icon_name", "mpd", true); + context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), + MPD_PULSE_NAME); + if (context == nullptr) + throw std::runtime_error("pa_context_new() has failed"); - po = new PulseOutput(); - if (!po->base.Configure(param, error)) { - delete po; - return nullptr; - } - - po->name = param.GetBlockValue("name", "mpd_pulse"); - po->server = param.GetBlockValue("server"); - po->sink = param.GetBlockValue("sink"); - - po->mixer = nullptr; - po->mainloop = nullptr; - po->context = nullptr; - po->stream = nullptr; + pa_context_set_state_callback(context, + pulse_output_context_state_cb, this); + pa_context_set_subscribe_callback(context, + pulse_output_subscribe_cb, this); - return &po->base; + try { + Connect(); + } catch (...) { + DeleteContext(); + throw; + } } -static void -pulse_output_finish(AudioOutput *ao) +PulseOutput * +PulseOutput::Create(const ConfigBlock &block) { - PulseOutput *po = (PulseOutput *)ao; - - delete po; + return new PulseOutput(block); } -static bool -pulse_output_enable(AudioOutput *ao, Error &error) +inline void +PulseOutput::Enable() { - PulseOutput *po = (PulseOutput *)ao; - - assert(po->mainloop == nullptr); - assert(po->context == nullptr); + assert(mainloop == nullptr); /* create the libpulse mainloop and start the thread */ - po->mainloop = pa_threaded_mainloop_new(); - if (po->mainloop == nullptr) { - error.Set(pulse_output_domain, - "pa_threaded_mainloop_new() has failed"); - return false; - } - - pa_threaded_mainloop_lock(po->mainloop); - - if (pa_threaded_mainloop_start(po->mainloop) < 0) { - pa_threaded_mainloop_unlock(po->mainloop); - pa_threaded_mainloop_free(po->mainloop); - po->mainloop = nullptr; - - error.Set(pulse_output_domain, - "pa_threaded_mainloop_start() has failed"); - return false; + mainloop = pa_threaded_mainloop_new(); + if (mainloop == nullptr) + throw std::runtime_error("pa_threaded_mainloop_new() has failed"); + + pa_threaded_mainloop_lock(mainloop); + + if (pa_threaded_mainloop_start(mainloop) < 0) { + pa_threaded_mainloop_unlock(mainloop); + pa_threaded_mainloop_free(mainloop); + mainloop = nullptr; + + throw std::runtime_error("pa_threaded_mainloop_start() has failed"); } /* create the libpulse context and connect it */ - if (!pulse_output_setup_context(po, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - pa_threaded_mainloop_stop(po->mainloop); - pa_threaded_mainloop_free(po->mainloop); - po->mainloop = nullptr; - return false; + try { + SetupContext(); + } catch (...) { + pa_threaded_mainloop_unlock(mainloop); + pa_threaded_mainloop_stop(mainloop); + pa_threaded_mainloop_free(mainloop); + mainloop = nullptr; + throw; } - pa_threaded_mainloop_unlock(po->mainloop); - - return true; + pa_threaded_mainloop_unlock(mainloop); } -static void -pulse_output_disable(AudioOutput *ao) +inline void +PulseOutput::Disable() { - PulseOutput *po = (PulseOutput *)ao; - - assert(po->mainloop != nullptr); + assert(mainloop != nullptr); - pa_threaded_mainloop_stop(po->mainloop); - if (po->context != nullptr) - pulse_output_delete_context(po); - pa_threaded_mainloop_free(po->mainloop); - po->mainloop = nullptr; + pa_threaded_mainloop_stop(mainloop); + if (context != nullptr) + DeleteContext(); + pa_threaded_mainloop_free(mainloop); + mainloop = nullptr; } -/** - * Check if the context is (already) connected, and waits if not. If - * the context has been disconnected, retry to connect. - * - * Caller must lock the main loop. - * - * @return true on success, false on error - */ -static bool -pulse_output_wait_connection(PulseOutput *po, Error &error) +void +PulseOutput::WaitConnection() { - assert(po->mainloop != nullptr); + assert(mainloop != nullptr); pa_context_state_t state; - if (po->context == nullptr && !pulse_output_setup_context(po, error)) - return false; + if (context == nullptr) + SetupContext(); while (true) { - state = pa_context_get_state(po->context); + state = pa_context_get_state(context); switch (state) { case PA_CONTEXT_READY: /* nothing to do */ - return true; + return; case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: /* failure */ - SetError(error, po->context, "failed to connect"); - pulse_output_delete_context(po); - return false; + { + auto e = MakePulseError(context, + "failed to connect"); + DeleteContext(); + throw e; + } case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: /* wait some more */ - pa_threaded_mainloop_wait(po->mainloop); + pa_threaded_mainloop_wait(mainloop); break; } } } -static void -pulse_output_stream_suspended_cb(gcc_unused pa_stream *stream, void *userdata) +inline void +PulseOutput::OnStreamSuspended(gcc_unused pa_stream *_stream) { - PulseOutput *po = (PulseOutput *)userdata; - - assert(stream == po->stream || po->stream == nullptr); - assert(po->mainloop != nullptr); + assert(_stream == stream || stream == nullptr); + assert(mainloop != nullptr); /* wake up the main loop to break out of the loop in pulse_output_play() */ - pa_threaded_mainloop_signal(po->mainloop, 0); + Signal(); } static void -pulse_output_stream_state_cb(pa_stream *stream, void *userdata) +pulse_output_stream_suspended_cb(pa_stream *stream, void *userdata) { - PulseOutput *po = (PulseOutput *)userdata; + PulseOutput &po = *(PulseOutput *)userdata; + + po.OnStreamSuspended(stream); +} - assert(stream == po->stream || po->stream == nullptr); - assert(po->mainloop != nullptr); - assert(po->context != nullptr); +inline void +PulseOutput::OnStreamStateChanged(pa_stream *_stream, + pa_stream_state_t new_state) +{ + assert(_stream == stream || stream == nullptr); + assert(mainloop != nullptr); + assert(context != nullptr); - switch (pa_stream_get_state(stream)) { + switch (new_state) { case PA_STREAM_READY: - if (po->mixer != nullptr) - pulse_mixer_on_change(*po->mixer, po->context, stream); + if (mixer != nullptr) + pulse_mixer_on_change(*mixer, context, _stream); - pa_threaded_mainloop_signal(po->mainloop, 0); + Signal(); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: - if (po->mixer != nullptr) - pulse_mixer_on_disconnect(*po->mixer); + if (mixer != nullptr) + pulse_mixer_on_disconnect(*mixer); - pa_threaded_mainloop_signal(po->mainloop, 0); + Signal(); break; case PA_STREAM_UNCONNECTED: @@ -498,67 +555,71 @@ } static void -pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes, - void *userdata) +pulse_output_stream_state_cb(pa_stream *stream, void *userdata) { - PulseOutput *po = (PulseOutput *)userdata; + PulseOutput &po = *(PulseOutput *)userdata; - assert(po->mainloop != nullptr); + return po.OnStreamStateChanged(stream, pa_stream_get_state(stream)); +} - po->writable = nbytes; - pa_threaded_mainloop_signal(po->mainloop, 0); +inline void +PulseOutput::OnStreamWrite(size_t nbytes) +{ + assert(mainloop != nullptr); + + writable = nbytes; + Signal(); } -/** - * Create, set up and connect a context. - * - * Caller must lock the main loop. - * - * @return true on success, false on error - */ -static bool -pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss, - Error &error) +static void +pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes, + void *userdata) { - assert(po != nullptr); - assert(po->context != nullptr); + PulseOutput &po = *(PulseOutput *)userdata; - po->stream = pa_stream_new(po->context, po->name, ss, nullptr); - if (po->stream == nullptr) { - SetError(error, po->context, "pa_stream_new() has failed"); - return false; - } + return po.OnStreamWrite(nbytes); +} - pa_stream_set_suspended_callback(po->stream, - pulse_output_stream_suspended_cb, po); +inline void +PulseOutput::SetupStream(const pa_sample_spec &ss) +{ + assert(context != nullptr); - pa_stream_set_state_callback(po->stream, - pulse_output_stream_state_cb, po); - pa_stream_set_write_callback(po->stream, - pulse_output_stream_write_cb, po); + /* WAVE-EX is been adopted as the speaker map for most media files */ + pa_channel_map chan_map; + pa_channel_map_init_auto(&chan_map, ss.channels, + PA_CHANNEL_MAP_WAVEEX); + stream = pa_stream_new(context, name, &ss, &chan_map); + if (stream == nullptr) + throw MakePulseError(context, + "pa_stream_new() has failed"); - return true; + pa_stream_set_suspended_callback(stream, + pulse_output_stream_suspended_cb, + this); + + pa_stream_set_state_callback(stream, + pulse_output_stream_state_cb, this); + pa_stream_set_write_callback(stream, + pulse_output_stream_write_cb, this); } -static bool -pulse_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +inline void +PulseOutput::Open(AudioFormat &audio_format) { - PulseOutput *po = (PulseOutput *)ao; - - assert(po->mainloop != nullptr); + assert(mainloop != nullptr); - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); - if (po->context != nullptr) { - switch (pa_context_get_state(po->context)) { + if (context != nullptr) { + switch (pa_context_get_state(context)) { case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: /* the connection was closed meanwhile; delete it, and pulse_output_wait_connection() will reopen it */ - pulse_output_delete_context(po); + DeleteContext(); break; case PA_CONTEXT_READY: @@ -569,10 +630,7 @@ } } - if (!pulse_output_wait_connection(po, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - return false; - } + WaitConnection(); /* Use the sample formats that our version of PulseAudio and MPD have in common, otherwise force MPD to send 16 bit */ @@ -603,298 +661,228 @@ /* create a stream .. */ - if (!pulse_output_setup_stream(po, &ss, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - return false; - } + SetupStream(ss); /* .. and connect it (asynchronously) */ - if (pa_stream_connect_playback(po->stream, po->sink, + if (pa_stream_connect_playback(stream, sink, nullptr, pa_stream_flags_t(0), nullptr, nullptr) < 0) { - pulse_output_delete_stream(po); + DeleteStream(); - SetError(error, po->context, - "pa_stream_connect_playback() has failed"); - pa_threaded_mainloop_unlock(po->mainloop); - return false; + throw MakePulseError(context, + "pa_stream_connect_playback() has failed"); } - - pa_threaded_mainloop_unlock(po->mainloop); - - return true; } -static void -pulse_output_close(AudioOutput *ao) +inline void +PulseOutput::Close() { - PulseOutput *po = (PulseOutput *)ao; - pa_operation *o; - - assert(po->mainloop != nullptr); + assert(mainloop != nullptr); - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); - if (pa_stream_get_state(po->stream) == PA_STREAM_READY) { - o = pa_stream_drain(po->stream, - pulse_output_stream_success_cb, po); + if (pa_stream_get_state(stream) == PA_STREAM_READY) { + pa_operation *o = + pa_stream_drain(stream, + pulse_output_stream_success_cb, this); if (o == nullptr) { - FormatWarning(pulse_output_domain, - "pa_stream_drain() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + LogPulseError(context, + "pa_stream_drain() has failed"); } else - pulse_wait_for_operation(po->mainloop, o); + pulse_wait_for_operation(mainloop, o); } - pulse_output_delete_stream(po); - - if (po->context != nullptr && - pa_context_get_state(po->context) != PA_CONTEXT_READY) - pulse_output_delete_context(po); + DeleteStream(); - pa_threaded_mainloop_unlock(po->mainloop); + if (context != nullptr && + pa_context_get_state(context) != PA_CONTEXT_READY) + DeleteContext(); } -/** - * Check if the stream is (already) connected, and waits if not. The - * mainloop must be locked before calling this function. - * - * @return true on success, false on error - */ -static bool -pulse_output_wait_stream(PulseOutput *po, Error &error) +void +PulseOutput::WaitStream() { while (true) { - switch (pa_stream_get_state(po->stream)) { + switch (pa_stream_get_state(stream)) { case PA_STREAM_READY: - return true; + return; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: case PA_STREAM_UNCONNECTED: - SetError(error, po->context, - "failed to connect the stream"); - return false; + throw MakePulseError(context, + "failed to connect the stream"); case PA_STREAM_CREATING: - pa_threaded_mainloop_wait(po->mainloop); + pa_threaded_mainloop_wait(mainloop); break; } } } -/** - * Sets cork mode on the stream. - */ -static bool -pulse_output_stream_pause(PulseOutput *po, bool pause, - Error &error) +void +PulseOutput::StreamPause(bool pause) { - pa_operation *o; - - assert(po->mainloop != nullptr); - assert(po->context != nullptr); - assert(po->stream != nullptr); - - o = pa_stream_cork(po->stream, pause, - pulse_output_stream_success_cb, po); - if (o == nullptr) { - SetError(error, po->context, "pa_stream_cork() has failed"); - return false; - } + assert(mainloop != nullptr); + assert(context != nullptr); + assert(stream != nullptr); - if (!pulse_wait_for_operation(po->mainloop, o)) { - SetError(error, po->context, "pa_stream_cork() has failed"); - return false; - } + pa_operation *o = pa_stream_cork(stream, pause, + pulse_output_stream_success_cb, this); + if (o == nullptr) + throw MakePulseError(context, + "pa_stream_cork() has failed"); - return true; + if (!pulse_wait_for_operation(mainloop, o)) + throw MakePulseError(context, + "pa_stream_cork() has failed"); } -static unsigned -pulse_output_delay(AudioOutput *ao) +inline std::chrono::steady_clock::duration +PulseOutput::Delay() noexcept { - PulseOutput *po = (PulseOutput *)ao; - unsigned result = 0; - - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); - if (po->base.pause && pa_stream_is_corked(po->stream) && - pa_stream_get_state(po->stream) == PA_STREAM_READY) + auto result = std::chrono::steady_clock::duration::zero(); + if (base.pause && pa_stream_is_corked(stream) && + pa_stream_get_state(stream) == PA_STREAM_READY) /* idle while paused */ - result = 1000; - - pa_threaded_mainloop_unlock(po->mainloop); + result = std::chrono::seconds(1); return result; } -static size_t -pulse_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +PulseOutput::Play(const void *chunk, size_t size) { - PulseOutput *po = (PulseOutput *)ao; - - assert(po->mainloop != nullptr); - assert(po->stream != nullptr); + assert(mainloop != nullptr); + assert(stream != nullptr); - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); /* check if the stream is (already) connected */ - if (!pulse_output_wait_stream(po, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - return 0; - } + WaitStream(); - assert(po->context != nullptr); + assert(context != nullptr); /* unpause if previously paused */ - if (pa_stream_is_corked(po->stream) && - !pulse_output_stream_pause(po, false, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - return 0; - } + if (pa_stream_is_corked(stream)) + StreamPause(false); /* wait until the server allows us to write */ - while (po->writable == 0) { - if (pa_stream_is_suspended(po->stream)) { - pa_threaded_mainloop_unlock(po->mainloop); - error.Set(pulse_output_domain, "suspended"); - return 0; - } + while (writable == 0) { + if (pa_stream_is_suspended(stream)) + throw std::runtime_error("suspended"); - pa_threaded_mainloop_wait(po->mainloop); + pa_threaded_mainloop_wait(mainloop); - if (pa_stream_get_state(po->stream) != PA_STREAM_READY) { - pa_threaded_mainloop_unlock(po->mainloop); - error.Set(pulse_output_domain, "disconnected"); - return 0; - } + if (pa_stream_get_state(stream) != PA_STREAM_READY) + throw std::runtime_error("disconnected"); } /* now write */ - if (size > po->writable) + if (size > writable) /* don't send more than possible */ - size = po->writable; + size = writable; - po->writable -= size; + writable -= size; - int result = pa_stream_write(po->stream, chunk, size, nullptr, + int result = pa_stream_write(stream, chunk, size, nullptr, 0, PA_SEEK_RELATIVE); - pa_threaded_mainloop_unlock(po->mainloop); - if (result < 0) { - SetError(error, po->context, "pa_stream_write() failed"); - return 0; - } + if (result < 0) + throw MakePulseError(context, "pa_stream_write() failed"); return size; } -static void -pulse_output_cancel(AudioOutput *ao) +inline void +PulseOutput::Cancel() { - PulseOutput *po = (PulseOutput *)ao; - pa_operation *o; - - assert(po->mainloop != nullptr); - assert(po->stream != nullptr); + assert(mainloop != nullptr); + assert(stream != nullptr); - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); - if (pa_stream_get_state(po->stream) != PA_STREAM_READY) { + if (pa_stream_get_state(stream) != PA_STREAM_READY) { /* no need to flush when the stream isn't connected yet */ - pa_threaded_mainloop_unlock(po->mainloop); return; } - assert(po->context != nullptr); + assert(context != nullptr); - o = pa_stream_flush(po->stream, pulse_output_stream_success_cb, po); + pa_operation *o = pa_stream_flush(stream, + pulse_output_stream_success_cb, + this); if (o == nullptr) { - FormatWarning(pulse_output_domain, - "pa_stream_flush() has failed: %s", - pa_strerror(pa_context_errno(po->context))); - pa_threaded_mainloop_unlock(po->mainloop); + LogPulseError(context, "pa_stream_flush() has failed"); return; } - pulse_wait_for_operation(po->mainloop, o); - pa_threaded_mainloop_unlock(po->mainloop); + pulse_wait_for_operation(mainloop, o); } -static bool -pulse_output_pause(AudioOutput *ao) +inline bool +PulseOutput::Pause() { - PulseOutput *po = (PulseOutput *)ao; - - assert(po->mainloop != nullptr); - assert(po->stream != nullptr); + assert(mainloop != nullptr); + assert(stream != nullptr); - pa_threaded_mainloop_lock(po->mainloop); + Pulse::LockGuard lock(mainloop); /* check if the stream is (already/still) connected */ - Error error; - if (!pulse_output_wait_stream(po, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - LogError(error); - return false; - } + WaitStream(); - assert(po->context != nullptr); + assert(context != nullptr); /* cork the stream */ - if (!pa_stream_is_corked(po->stream) && - !pulse_output_stream_pause(po, true, error)) { - pa_threaded_mainloop_unlock(po->mainloop); - LogError(error); - return false; - } + if (!pa_stream_is_corked(stream)) + StreamPause(true); - pa_threaded_mainloop_unlock(po->mainloop); + return true; +} +inline bool +PulseOutput::TestDefaultDevice() +try { + const ConfigBlock empty; + PulseOutput po(empty); + po.WaitConnection(); return true; +} catch (const std::runtime_error &e) { + return false; } static bool pulse_output_test_default_device(void) { - bool success; - - const config_param empty; - PulseOutput *po = (PulseOutput *) - pulse_output_init(empty, IgnoreError()); - if (po == nullptr) - return false; - - success = pulse_output_wait_connection(po, IgnoreError()); - pulse_output_finish(&po->base); - - return success; + return PulseOutput::TestDefaultDevice(); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin pulse_output_plugin = { "pulse", pulse_output_test_default_device, - pulse_output_init, - pulse_output_finish, - pulse_output_enable, - pulse_output_disable, - pulse_output_open, - pulse_output_close, - pulse_output_delay, + &Wrapper::Init, + &Wrapper::Finish, + &Wrapper::Enable, + &Wrapper::Disable, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - pulse_output_play, + &Wrapper::Play, nullptr, - pulse_output_cancel, - pulse_output_pause, + &Wrapper::Cancel, + &Wrapper::Pause, &pulse_mixer_plugin, }; diff -Nru mpd-0.19.21/src/output/plugins/PulseOutputPlugin.hxx mpd-0.20.9/src/output/plugins/PulseOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/PulseOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/PulseOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,18 +20,14 @@ #ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX #define MPD_PULSE_OUTPUT_PLUGIN_HXX -struct PulseOutput; +class PulseOutput; class PulseMixer; struct pa_cvolume; -class Error; extern const struct AudioOutputPlugin pulse_output_plugin; -void -pulse_output_lock(PulseOutput &po); - -void -pulse_output_unlock(PulseOutput &po); +struct pa_threaded_mainloop * +pulse_output_get_mainloop(PulseOutput &po); void pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm); @@ -39,8 +35,7 @@ void pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm); -bool -pulse_output_set_volume(PulseOutput &po, - const pa_cvolume *volume, Error &error); +void +pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume); #endif diff -Nru mpd-0.19.21/src/output/plugins/RecorderOutputPlugin.cxx mpd-0.20.9/src/output/plugins/RecorderOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/RecorderOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/RecorderOutputPlugin.cxx 2017-06-04 10:38:35.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,237 +20,364 @@ #include "config.h" #include "RecorderOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" +#include "tag/Format.hxx" +#include "encoder/ToOutputStream.hxx" +#include "encoder/EncoderInterface.hxx" #include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderList.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "config/ConfigPath.hxx" +#include "Log.hxx" +#include "fs/AllocatedPath.hxx" +#include "fs/io/FileOutputStream.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" -#include "system/fd_util.h" -#include "open.h" +#include "util/ScopeExit.hxx" + +#include #include -#include -#include -#include -#include +#include + +static constexpr Domain recorder_domain("recorder"); + +class RecorderOutput { + friend struct AudioOutputWrapper; -struct RecorderOutput { AudioOutput base; /** * The configured encoder plugin. */ + PreparedEncoder *prepared_encoder = nullptr; Encoder *encoder; /** * The destination file name. */ - const char *path; + AllocatedPath path = AllocatedPath::Null(); + + /** + * A string that will be used with FormatTag() to build the + * destination path. + */ + std::string format_path; /** - * The destination file descriptor. + * The #AudioFormat that is currently active. This is used + * for switching to another file. */ - int fd; + AudioFormat effective_audio_format; /** - * The buffer for encoder_read(). + * The destination file. */ - char buffer[32768]; + FileOutputStream *file; - RecorderOutput() - :base(recorder_output_plugin) {} + RecorderOutput(const ConfigBlock &block); - bool Initialize(const config_param ¶m, Error &error_r) { - return base.Configure(param, error_r); + ~RecorderOutput() { + delete prepared_encoder; } - bool Configure(const config_param ¶m, Error &error); + static RecorderOutput *Create(const ConfigBlock &block); - bool WriteToFile(const void *data, size_t length, Error &error); + void Open(AudioFormat &audio_format); + void Close(); /** * Writes pending data from the encoder to the output file. */ - bool EncoderToFile(Error &error); -}; + void EncoderToFile(); + + void SendTag(const Tag &tag); -static constexpr Domain recorder_output_domain("recorder_output"); + size_t Play(const void *chunk, size_t size); -inline bool -RecorderOutput::Configure(const config_param ¶m, Error &error) +private: + gcc_pure + bool HasDynamicPath() const noexcept { + return !format_path.empty(); + } + + /** + * Finish the encoder and commit the file. + * + * Throws #std::runtime_error on error. + */ + void Commit(); + + void FinishFormat(); + void ReopenFormat(AllocatedPath &&new_path); +}; + +RecorderOutput::RecorderOutput(const ConfigBlock &block) + :base(recorder_output_plugin, block) { /* read configuration */ const char *encoder_name = - param.GetBlockValue("encoder", "vorbis"); + block.GetBlockValue("encoder", "vorbis"); const auto encoder_plugin = encoder_plugin_get(encoder_name); - if (encoder_plugin == nullptr) { - error.Format(config_domain, - "No such encoder: %s", encoder_name); - return false; - } + if (encoder_plugin == nullptr) + throw FormatRuntimeError("No such encoder: %s", encoder_name); - path = param.GetBlockValue("path"); - if (path == nullptr) { - error.Set(config_domain, "'path' not configured"); - return false; - } + path = block.GetPath("path"); + + const char *fmt = block.GetBlockValue("format_path", nullptr); + if (fmt != nullptr) + format_path = fmt; + + if (path.IsNull() && fmt == nullptr) + throw std::runtime_error("'path' not configured"); + + if (!path.IsNull() && fmt != nullptr) + throw std::runtime_error("Cannot have both 'path' and 'format_path'"); /* initialize encoder */ - encoder = encoder_init(*encoder_plugin, param, error); - if (encoder == nullptr) - return false; + prepared_encoder = encoder_init(*encoder_plugin, block); +} - return true; +RecorderOutput * +RecorderOutput::Create(const ConfigBlock &block) +{ + return new RecorderOutput(block); } -static AudioOutput * -recorder_output_init(const config_param ¶m, Error &error) +inline void +RecorderOutput::EncoderToFile() { - RecorderOutput *recorder = new RecorderOutput(); + assert(file != nullptr); + + EncoderToOutputStream(*file, *encoder); +} - if (!recorder->Initialize(param, error)) { - delete recorder; - return nullptr; +inline void +RecorderOutput::Open(AudioFormat &audio_format) +{ + /* create the output file */ + + if (!HasDynamicPath()) { + assert(!path.IsNull()); + + file = new FileOutputStream(path); + } else { + /* don't open the file just yet; wait until we have + a tag that we can use to build the path */ + assert(path.IsNull()); + + file = nullptr; } - if (!recorder->Configure(param, error)) { - delete recorder; - return nullptr; + /* open the encoder */ + + try { + encoder = prepared_encoder->Open(audio_format); + } catch (const std::runtime_error &) { + delete file; + throw; } - return &recorder->base; + if (!HasDynamicPath()) { + try { + EncoderToFile(); + } catch (const std::runtime_error &) { + delete encoder; + throw; + } + } else { + /* remember the AudioFormat for ReopenFormat() */ + effective_audio_format = audio_format; + + /* close the encoder for now; it will be opened as + soon as we have received a tag */ + delete encoder; + } } -static void -recorder_output_finish(AudioOutput *ao) +inline void +RecorderOutput::Commit() { - RecorderOutput *recorder = (RecorderOutput *)ao; + assert(!path.IsNull()); - encoder_finish(recorder->encoder); - delete recorder; -} + /* flush the encoder and write the rest to the file */ -inline bool -RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error) -{ - assert(length > 0); + try { + encoder->End(); + EncoderToFile(); + } catch (...) { + delete encoder; + throw; + } - const uint8_t *data = (const uint8_t *)_data, *end = data + length; + /* now really close everything */ - while (true) { - ssize_t nbytes = write(fd, data, end - data); - if (nbytes > 0) { - data += nbytes; - if (data == end) - return true; - } else if (nbytes == 0) { - /* shouldn't happen for files */ - error.Set(recorder_output_domain, - "write() returned 0"); - return false; - } else if (errno != EINTR) { - error.FormatErrno("Failed to write to '%s'", path); - return false; - } + delete encoder; + + try { + file->Commit(); + } catch (...) { + delete file; + throw; } + + delete file; } -inline bool -RecorderOutput::EncoderToFile(Error &error) +inline void +RecorderOutput::Close() { - assert(fd >= 0); - - while (true) { - /* read from the encoder */ - - size_t size = encoder_read(encoder, buffer, sizeof(buffer)); - if (size == 0) - return true; + if (file == nullptr) { + /* not currently encoding to a file; nothing needs to + be done now */ + assert(HasDynamicPath()); + assert(path.IsNull()); + return; + } - /* write everything into the file */ + try { + Commit(); + } catch (const std::exception &e) { + LogError(e); + } - if (!WriteToFile(buffer, size, error)) - return false; + if (HasDynamicPath()) { + assert(!path.IsNull()); + path.SetNull(); } } -static bool -recorder_output_open(AudioOutput *ao, - AudioFormat &audio_format, - Error &error) +void +RecorderOutput::FinishFormat() { - RecorderOutput *recorder = (RecorderOutput *)ao; + assert(HasDynamicPath()); - /* create the output file */ + if (file == nullptr) + return; - recorder->fd = open_cloexec(recorder->path, - O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, - 0666); - if (recorder->fd < 0) { - error.FormatErrno("Failed to create '%s'", recorder->path); - return false; + try { + Commit(); + } catch (const std::exception &e) { + LogError(e); } - /* open the encoder */ + file = nullptr; + path.SetNull(); +} - if (!encoder_open(recorder->encoder, audio_format, error)) { - close(recorder->fd); - unlink(recorder->path); - return false; +inline void +RecorderOutput::ReopenFormat(AllocatedPath &&new_path) +{ + assert(HasDynamicPath()); + assert(path.IsNull()); + assert(file == nullptr); + + FileOutputStream *new_file = new FileOutputStream(new_path); + + AudioFormat new_audio_format = effective_audio_format; + + try { + encoder = prepared_encoder->Open(new_audio_format); + } catch (...) { + delete new_file; + throw; } - if (!recorder->EncoderToFile(error)) { - encoder_close(recorder->encoder); - close(recorder->fd); - unlink(recorder->path); - return false; + /* reopening the encoder must always result in the same + AudioFormat as before */ + assert(new_audio_format == effective_audio_format); + + try { + EncoderToOutputStream(*new_file, *encoder); + } catch (const std::exception &e) { + delete encoder; + delete new_file; + throw; } - return true; + path = std::move(new_path); + file = new_file; + + FormatDebug(recorder_domain, "Recording to \"%s\"", + path.ToUTF8().c_str()); } -static void -recorder_output_close(AudioOutput *ao) +inline void +RecorderOutput::SendTag(const Tag &tag) { - RecorderOutput *recorder = (RecorderOutput *)ao; + if (HasDynamicPath()) { + char *p = FormatTag(tag, format_path.c_str()); + if (p == nullptr || *p == 0) { + /* no path could be composed with this tag: + don't write a file */ + free(p); + FinishFormat(); + return; + } - /* flush the encoder and write the rest to the file */ + AtScopeExit(p) { free(p); }; - if (encoder_end(recorder->encoder, IgnoreError())) - recorder->EncoderToFile(IgnoreError()); + AllocatedPath new_path = AllocatedPath::Null(); - /* now really close everything */ + try { + new_path = ParsePath(p); + } catch (const std::runtime_error &e) { + LogError(e); + FinishFormat(); + return; + } - encoder_close(recorder->encoder); + if (new_path != path) { + FinishFormat(); - close(recorder->fd); + try { + ReopenFormat(std::move(new_path)); + } catch (const std::runtime_error &e) { + LogError(e); + return; + } + } + } + + encoder->PreTag(); + EncoderToFile(); + encoder->SendTag(tag); } -static size_t -recorder_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +inline size_t +RecorderOutput::Play(const void *chunk, size_t size) { - RecorderOutput *recorder = (RecorderOutput *)ao; + if (file == nullptr) { + /* not currently encoding to a file; discard incoming + data */ + assert(HasDynamicPath()); + assert(path.IsNull()); + return size; + } + + encoder->Write(chunk, size); - return encoder_write(recorder->encoder, chunk, size, error) && - recorder->EncoderToFile(error) - ? size : 0; + EncoderToFile(); + + return size; } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin recorder_output_plugin = { "recorder", nullptr, - recorder_output_init, - recorder_output_finish, - nullptr, + &Wrapper::Init, + &Wrapper::Finish, nullptr, - recorder_output_open, - recorder_output_close, nullptr, + &Wrapper::Open, + &Wrapper::Close, nullptr, - recorder_output_play, + &Wrapper::SendTag, + &Wrapper::Play, nullptr, nullptr, nullptr, diff -Nru mpd-0.19.21/src/output/plugins/RecorderOutputPlugin.hxx mpd-0.20.9/src/output/plugins/RecorderOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/RecorderOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/RecorderOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/RoarOutputPlugin.cxx mpd-0.20.9/src/output/plugins/RoarOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/RoarOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/RoarOutputPlugin.cxx 2017-05-08 15:01:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft * Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen * @@ -21,13 +21,14 @@ #include "config.h" #include "RoarOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "mixer/MixerList.hxx" #include "thread/Mutex.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" #include +#include /* libroar/services.h declares roar_service_stream::new - work around this C++ problem */ @@ -36,50 +37,62 @@ #undef new class RoarOutput { + friend struct AudioOutputWrapper; + AudioOutput base; - std::string host, name; + const std::string host, name; roar_vs_t * vss; - int err; - int role; + int err = ROAR_ERROR_NONE; + const int role; struct roar_connection con; struct roar_audio_info info; mutable Mutex mutex; bool alive; public: - RoarOutput() - :base(roar_output_plugin), - err(ROAR_ERROR_NONE) {} + RoarOutput(const ConfigBlock &block); operator AudioOutput *() { return &base; } - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); - } - - void Configure(const config_param ¶m); - - bool Open(AudioFormat &audio_format, Error &error); + void Open(AudioFormat &audio_format); void Close(); void SendTag(const Tag &tag); - size_t Play(const void *chunk, size_t size, Error &error); + size_t Play(const void *chunk, size_t size); void Cancel(); int GetVolume() const; - bool SetVolume(unsigned volume); + void SetVolume(unsigned volume); }; static constexpr Domain roar_output_domain("roar_output"); +gcc_pure +static int +GetConfiguredRole(const ConfigBlock &block) noexcept +{ + const char *role = block.GetBlockValue("role"); + return role != nullptr + ? roar_str2role(role) + : ROAR_ROLE_MUSIC; +} + +RoarOutput::RoarOutput(const ConfigBlock &block) + :base(roar_output_plugin, block), + host(block.GetBlockValue("server", "")), + name(block.GetBlockValue("name", "MPD")), + role(GetConfiguredRole(block)) +{ +} + inline int RoarOutput::GetVolume() const { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (vss == nullptr || !alive) return -1; @@ -87,7 +100,7 @@ float l, r; int error; if (roar_vs_volume_get(vss, &l, &r, &error) < 0) - return -1; + throw std::runtime_error(roar_vs_strerr(error)); return (l + r) * 50; } @@ -98,60 +111,32 @@ return roar.GetVolume(); } -bool +inline void RoarOutput::SetVolume(unsigned volume) { assert(volume <= 100); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (vss == nullptr || !alive) - return false; + throw std::runtime_error("closed"); int error; float level = volume / 100.0; - roar_vs_volume_mono(vss, level, &error); - return true; + if (roar_vs_volume_mono(vss, level, &error) < 0) + throw std::runtime_error(roar_vs_strerr(error)); } -bool +void roar_output_set_volume(RoarOutput &roar, unsigned volume) { - return roar.SetVolume(volume); -} - -inline void -RoarOutput::Configure(const config_param ¶m) -{ - host = param.GetBlockValue("server", ""); - name = param.GetBlockValue("name", "MPD"); - - const char *_role = param.GetBlockValue("role", "music"); - role = _role != nullptr - ? roar_str2role(_role) - : ROAR_ROLE_MUSIC; + roar.SetVolume(volume); } static AudioOutput * -roar_init(const config_param ¶m, Error &error) -{ - RoarOutput *self = new RoarOutput(); - - if (!self->Initialize(param, error)) { - delete self; - return nullptr; - } - - self->Configure(param); - return *self; -} - -static void -roar_finish(AudioOutput *ao) +roar_init(const ConfigBlock &block) { - RoarOutput *self = (RoarOutput *)ao; - - delete self; + return *new RoarOutput(block); } static void @@ -189,50 +174,34 @@ } } -inline bool -RoarOutput::Open(AudioFormat &audio_format, Error &error) +inline void +RoarOutput::Open(AudioFormat &audio_format) { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (roar_simple_connect(&con, host.empty() ? nullptr : host.c_str(), - name.c_str()) < 0) { - error.Set(roar_output_domain, - "Failed to connect to Roar server"); - return false; - } + name.c_str()) < 0) + throw std::runtime_error("Failed to connect to Roar server"); vss = roar_vs_new_from_con(&con, &err); - if (vss == nullptr || err != ROAR_ERROR_NONE) { - error.Set(roar_output_domain, "Failed to connect to server"); - return false; - } + if (vss == nullptr || err != ROAR_ERROR_NONE) + throw std::runtime_error("Failed to connect to server"); roar_use_audio_format(&info, audio_format); - if (roar_vs_stream(vss, &info, ROAR_DIR_PLAY, &err) < 0) { - error.Set(roar_output_domain, "Failed to start stream"); - return false; - } + if (roar_vs_stream(vss, &info, ROAR_DIR_PLAY, &err) < 0) + throw std::runtime_error("Failed to start stream"); roar_vs_role(vss, role, &err); alive = true; - return true; -} - -static bool -roar_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) -{ - RoarOutput *self = (RoarOutput *)ao; - - return self->Open(audio_format, error); } inline void RoarOutput::Close() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); alive = false; @@ -242,17 +211,10 @@ roar_disconnect(&con); } -static void -roar_close(AudioOutput *ao) -{ - RoarOutput *self = (RoarOutput *)ao; - self->Close(); -} - inline void RoarOutput::Cancel() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); if (vss == nullptr) return; @@ -277,39 +239,19 @@ alive = true; } -static void -roar_cancel(AudioOutput *ao) -{ - RoarOutput *self = (RoarOutput *)ao; - - self->Cancel(); -} - inline size_t -RoarOutput::Play(const void *chunk, size_t size, Error &error) +RoarOutput::Play(const void *chunk, size_t size) { - if (vss == nullptr) { - error.Set(roar_output_domain, "Connection is invalid"); - return 0; - } + if (vss == nullptr) + throw std::runtime_error("Connection is invalid"); ssize_t nbytes = roar_vs_write(vss, chunk, size, &err); - if (nbytes <= 0) { - error.Set(roar_output_domain, "Failed to play data"); - return 0; - } + if (nbytes <= 0) + throw std::runtime_error("Failed to play data"); return nbytes; } -static size_t -roar_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - RoarOutput *self = (RoarOutput *)ao; - return self->Play(chunk, size, error); -} - static const char* roar_tag_convert(TagType type, bool *is_uuid) { @@ -347,8 +289,6 @@ case TAG_MUSICBRAINZ_ALBUMID: case TAG_MUSICBRAINZ_ALBUMARTISTID: case TAG_MUSICBRAINZ_TRACKID: - *is_uuid = true; - return "HASH"; case TAG_MUSICBRAINZ_RELEASETRACKID: *is_uuid = true; return "HASH"; @@ -364,7 +304,7 @@ if (vss == nullptr) return; - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); size_t cnt = 0; struct roar_keyval vals[32]; @@ -407,26 +347,28 @@ } static void -roar_send_tag(AudioOutput *ao, const Tag *meta) +roar_send_tag(AudioOutput *ao, const Tag &meta) { RoarOutput *self = (RoarOutput *)ao; - self->SendTag(*meta); + self->SendTag(meta); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin roar_output_plugin = { "roar", nullptr, roar_init, - roar_finish, + &Wrapper::Finish, nullptr, nullptr, - roar_open, - roar_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, roar_send_tag, - roar_play, + &Wrapper::Play, nullptr, - roar_cancel, + &Wrapper::Cancel, nullptr, &roar_mixer_plugin, }; diff -Nru mpd-0.19.21/src/output/plugins/RoarOutputPlugin.hxx mpd-0.20.9/src/output/plugins/RoarOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/RoarOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/RoarOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -27,7 +27,7 @@ int roar_output_get_volume(RoarOutput &roar); -bool +void roar_output_set_volume(RoarOutput &roar, unsigned volume); #endif diff -Nru mpd-0.19.21/src/output/plugins/ShoutOutputPlugin.cxx mpd-0.20.9/src/output/plugins/ShoutOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/ShoutOutputPlugin.cxx 2016-07-29 08:50:27.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/ShoutOutputPlugin.cxx 2017-05-08 15:11:37.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,16 +20,18 @@ #include "config.h" #include "ShoutOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" +#include "encoder/EncoderInterface.hxx" #include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderList.hxx" -#include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" -#include "system/FatalError.hxx" #include "Log.hxx" #include +#include + #include #include #include @@ -43,41 +45,46 @@ shout_t *shout_conn; shout_metadata_t *shout_meta; + PreparedEncoder *prepared_encoder = nullptr; Encoder *encoder; - float quality; - int bitrate; + float quality = -2.0; + int bitrate = -1; - int timeout; + int timeout = DEFAULT_CONN_TIMEOUT; uint8_t buffer[32768]; - ShoutOutput() - :base(shout_output_plugin), - shout_conn(shout_new()), - shout_meta(shout_metadata_new()), - quality(-2.0), - bitrate(-1), - timeout(DEFAULT_CONN_TIMEOUT) {} - - ~ShoutOutput() { - if (shout_meta != nullptr) - shout_metadata_free(shout_meta); - if (shout_conn != nullptr) - shout_free(shout_conn); - } + explicit ShoutOutput(const ConfigBlock &block); + ~ShoutOutput(); - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); - } + static ShoutOutput *Create(const ConfigBlock &block); + + void Open(AudioFormat &audio_format); + void Close(); - bool Configure(const config_param ¶m, Error &error); + std::chrono::steady_clock::duration Delay() const noexcept; + void SendTag(const Tag &tag); + size_t Play(const void *chunk, size_t size); + void Cancel(); + bool Pause(); }; static int shout_init_count; static constexpr Domain shout_output_domain("shout_output"); +static const char * +require_block_string(const ConfigBlock &block, const char *name) +{ + const char *value = block.GetBlockValue(name); + if (value == nullptr) + throw FormatRuntimeError("no \"%s\" defined for shout device defined " + "at line %d\n", name, block.line); + + return value; +} + static const EncoderPlugin * shout_encoder_plugin_get(const char *name) { @@ -89,95 +96,62 @@ return encoder_plugin_get(name); } -gcc_pure -static const char * -require_block_string(const config_param ¶m, const char *name) +ShoutOutput::ShoutOutput(const ConfigBlock &block) + :base(shout_output_plugin, block), + shout_conn(shout_new()), + shout_meta(shout_metadata_new()) { - const char *value = param.GetBlockValue(name); - if (value == nullptr) - FormatFatalError("no \"%s\" defined for shout device defined " - "at line %u\n", name, param.line); - - return value; -} - -inline bool -ShoutOutput::Configure(const config_param ¶m, Error &error) -{ - const AudioFormat audio_format = base.config_audio_format; - if (!audio_format.IsFullyDefined()) { - error.Set(config_domain, - "Need full audio format specification"); - return false; - } + if (!audio_format.IsFullyDefined()) + throw std::runtime_error("Need full audio format specification"); - const char *host = require_block_string(param, "host"); - const char *mount = require_block_string(param, "mount"); - unsigned port = param.GetBlockValue("port", 0u); - if (port == 0) { - error.Set(config_domain, "shout port must be configured"); - return false; - } + const char *host = require_block_string(block, "host"); + const char *mount = require_block_string(block, "mount"); + unsigned port = block.GetBlockValue("port", 0u); + if (port == 0) + throw std::runtime_error("shout port must be configured"); - const char *passwd = require_block_string(param, "password"); - const char *name = require_block_string(param, "name"); + const char *passwd = require_block_string(block, "password"); + const char *name = require_block_string(block, "name"); - bool is_public = param.GetBlockValue("public", false); + bool is_public = block.GetBlockValue("public", false); - const char *user = param.GetBlockValue("user", "source"); + const char *user = block.GetBlockValue("user", "source"); - const char *value = param.GetBlockValue("quality"); + const char *value = block.GetBlockValue("quality"); if (value != nullptr) { char *test; quality = strtod(value, &test); - if (*test != '\0' || quality < -1.0 || quality > 10.0) { - error.Format(config_domain, - "shout quality \"%s\" is not a number in the " - "range -1 to 10", - value); - return false; - } - - if (param.GetBlockValue("bitrate") != nullptr) { - error.Set(config_domain, - "quality and bitrate are " - "both defined"); - return false; - } + if (*test != '\0' || quality < -1.0 || quality > 10.0) + throw FormatRuntimeError("shout quality \"%s\" is not a number in the " + "range -1 to 10", + value); + + if (block.GetBlockValue("bitrate") != nullptr) + throw std::runtime_error("quality and bitrate are " + "both defined"); } else { - value = param.GetBlockValue("bitrate"); - if (value == nullptr) { - error.Set(config_domain, - "neither bitrate nor quality defined"); - return false; - } + value = block.GetBlockValue("bitrate"); + if (value == nullptr) + throw std::runtime_error("neither bitrate nor quality defined"); char *test; bitrate = strtol(value, &test, 10); - if (*test != '\0' || bitrate <= 0) { - error.Set(config_domain, - "bitrate must be a positive integer"); - return false; - } + if (*test != '\0' || bitrate <= 0) + throw std::runtime_error("bitrate must be a positive integer"); } - const char *encoding = param.GetBlockValue("encoder", nullptr); + const char *encoding = block.GetBlockValue("encoder", nullptr); if (encoding == nullptr) - encoding = param.GetBlockValue("encoding", "vorbis"); + encoding = block.GetBlockValue("encoding", "vorbis"); const auto encoder_plugin = shout_encoder_plugin_get(encoding); - if (encoder_plugin == nullptr) { - error.Format(config_domain, - "couldn't find shout encoder plugin \"%s\"", - encoding); - return false; - } + if (encoder_plugin == nullptr) + throw FormatRuntimeError("couldn't find shout encoder plugin \"%s\"", + encoding); - encoder = encoder_init(*encoder_plugin, param, error); - if (encoder == nullptr) - return false; + prepared_encoder = encoder_init(*encoder_plugin, block); unsigned shout_format; if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0) @@ -186,27 +160,22 @@ shout_format = SHOUT_FORMAT_OGG; unsigned protocol; - value = param.GetBlockValue("protocol"); + value = block.GetBlockValue("protocol"); if (value != nullptr) { if (0 == strcmp(value, "shoutcast") && - 0 != strcmp(encoding, "mp3")) { - error.Format(config_domain, - "you cannot stream \"%s\" to shoutcast, use mp3", - encoding); - return false; - } else if (0 == strcmp(value, "shoutcast")) + 0 != strcmp(encoding, "mp3")) + throw FormatRuntimeError("you cannot stream \"%s\" to shoutcast, use mp3", + encoding); + else if (0 == strcmp(value, "shoutcast")) protocol = SHOUT_PROTOCOL_ICY; else if (0 == strcmp(value, "icecast1")) protocol = SHOUT_PROTOCOL_XAUDIOCAST; else if (0 == strcmp(value, "icecast2")) protocol = SHOUT_PROTOCOL_HTTP; - else { - error.Format(config_domain, - "shout protocol \"%s\" is not \"shoutcast\" or " - "\"icecast1\"or \"icecast2\"", - value); - return false; - } + else + throw FormatRuntimeError("shout protocol \"%s\" is not \"shoutcast\" or " + "\"icecast1\"or \"icecast2\"", + value); } else { protocol = SHOUT_PROTOCOL_HTTP; } @@ -221,31 +190,23 @@ shout_set_format(shout_conn, shout_format) != SHOUTERR_SUCCESS || shout_set_protocol(shout_conn, protocol) != SHOUTERR_SUCCESS || - shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) { - error.Set(shout_output_domain, shout_get_error(shout_conn)); - return false; - } + shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) + throw std::runtime_error(shout_get_error(shout_conn)); /* optional paramters */ - timeout = param.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT); - - value = param.GetBlockValue("genre"); - if (value != nullptr && shout_set_genre(shout_conn, value)) { - error.Set(shout_output_domain, shout_get_error(shout_conn)); - return false; - } + timeout = block.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT); - value = param.GetBlockValue("description"); - if (value != nullptr && shout_set_description(shout_conn, value)) { - error.Set(shout_output_domain, shout_get_error(shout_conn)); - return false; - } - - value = param.GetBlockValue("url"); - if (value != nullptr && shout_set_url(shout_conn, value)) { - error.Set(shout_output_domain, shout_get_error(shout_conn)); - return false; - } + value = block.GetBlockValue("genre"); + if (value != nullptr && shout_set_genre(shout_conn, value)) + throw std::runtime_error(shout_get_error(shout_conn)); + + value = block.GetBlockValue("description"); + if (value != nullptr && shout_set_description(shout_conn, value)) + throw std::runtime_error(shout_get_error(shout_conn)); + + value = block.GetBlockValue("url"); + if (value != nullptr && shout_set_url(shout_conn, value)) + throw std::runtime_error(shout_get_error(shout_conn)); { char temp[11]; @@ -267,34 +228,35 @@ temp); } } - - return true; } -static AudioOutput * -my_shout_init_driver(const config_param ¶m, Error &error) +ShoutOutput::~ShoutOutput() { - ShoutOutput *sd = new ShoutOutput(); - if (!sd->Initialize(param, error)) { - delete sd; - return nullptr; - } + if (shout_meta != nullptr) + shout_metadata_free(shout_meta); + if (shout_conn != nullptr) + shout_free(shout_conn); - if (!sd->Configure(param, error)) { - delete sd; - return nullptr; - } + shout_init_count--; + if (shout_init_count == 0) + shout_shutdown(); + delete prepared_encoder; +} + +ShoutOutput * +ShoutOutput::Create(const ConfigBlock &block) +{ if (shout_init_count == 0) shout_init(); shout_init_count++; - return &sd->base; + return new ShoutOutput(block); } -static bool -handle_shout_error(ShoutOutput *sd, int err, Error &error) +static void +handle_shout_error(ShoutOutput *sd, int err) { switch (err) { case SHOUTERR_SUCCESS: @@ -302,168 +264,136 @@ case SHOUTERR_UNCONNECTED: case SHOUTERR_SOCKET: - error.Format(shout_output_domain, err, - "Lost shout connection to %s:%i: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); - return false; + throw FormatRuntimeError("Lost shout connection to %s:%i: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); default: - error.Format(shout_output_domain, err, - "connection to %s:%i error: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); - return false; + throw FormatRuntimeError("connection to %s:%i error: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); } - - return true; } static bool -write_page(ShoutOutput *sd, Error &error) +write_page(ShoutOutput *sd) { assert(sd->encoder != nullptr); while (true) { - size_t nbytes = encoder_read(sd->encoder, - sd->buffer, sizeof(sd->buffer)); + size_t nbytes = sd->encoder->Read(sd->buffer, + sizeof(sd->buffer)); if (nbytes == 0) return true; int err = shout_send(sd->shout_conn, sd->buffer, nbytes); - if (!handle_shout_error(sd, err, error)) - return false; + handle_shout_error(sd, err); } return true; } -static void close_shout_conn(ShoutOutput * sd) +void +ShoutOutput::Close() { - if (sd->encoder != nullptr) { - if (encoder_end(sd->encoder, IgnoreError())) - write_page(sd, IgnoreError()); + if (encoder != nullptr) { + try { + encoder->End(); + write_page(this); + } catch (const std::runtime_error &) { + /* ignore */ + } - encoder_close(sd->encoder); + delete encoder; } - if (shout_get_connected(sd->shout_conn) != SHOUTERR_UNCONNECTED && - shout_close(sd->shout_conn) != SHOUTERR_SUCCESS) { + if (shout_get_connected(shout_conn) != SHOUTERR_UNCONNECTED && + shout_close(shout_conn) != SHOUTERR_SUCCESS) { FormatWarning(shout_output_domain, "problem closing connection to shout server: %s", - shout_get_error(sd->shout_conn)); + shout_get_error(shout_conn)); } } -static void -my_shout_finish_driver(AudioOutput *ao) +void +ShoutOutput::Cancel() { - ShoutOutput *sd = (ShoutOutput *)ao; - - encoder_finish(sd->encoder); - - delete sd; - - shout_init_count--; - - if (shout_init_count == 0) - shout_shutdown(); -} - -static void -my_shout_drop_buffered_audio(AudioOutput *ao) -{ - gcc_unused - ShoutOutput *sd = (ShoutOutput *)ao; - /* needs to be implemented for shout */ } static void -my_shout_close_device(AudioOutput *ao) -{ - ShoutOutput *sd = (ShoutOutput *)ao; - - close_shout_conn(sd); -} - -static bool -shout_connect(ShoutOutput *sd, Error &error) +shout_connect(ShoutOutput *sd) { switch (shout_open(sd->shout_conn)) { case SHOUTERR_SUCCESS: case SHOUTERR_CONNECTED: - return true; + break; default: - error.Format(shout_output_domain, - "problem opening connection to shout server %s:%i: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); - return false; + throw FormatRuntimeError("problem opening connection to shout server %s:%i: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); } } -static bool -my_shout_open_device(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +void +ShoutOutput::Open(AudioFormat &audio_format) { - ShoutOutput *sd = (ShoutOutput *)ao; + shout_connect(this); - if (!shout_connect(sd, error)) - return false; - - if (!encoder_open(sd->encoder, audio_format, error)) { - shout_close(sd->shout_conn); - return false; - } + try { + encoder = prepared_encoder->Open(audio_format); - if (!write_page(sd, error)) { - encoder_close(sd->encoder); - shout_close(sd->shout_conn); - return false; + try { + write_page(this); + } catch (const std::runtime_error &) { + delete encoder; + throw; + } + } catch (const std::runtime_error &) { + shout_close(shout_conn); + throw; } - - return true; } -static unsigned -my_shout_delay(AudioOutput *ao) +std::chrono::steady_clock::duration +ShoutOutput::Delay() const noexcept { - ShoutOutput *sd = (ShoutOutput *)ao; - - int delay = shout_delay(sd->shout_conn); + int delay = shout_delay(shout_conn); if (delay < 0) delay = 0; - return delay; + return std::chrono::milliseconds(delay); } -static size_t -my_shout_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +size_t +ShoutOutput::Play(const void *chunk, size_t size) { - ShoutOutput *sd = (ShoutOutput *)ao; - - return encoder_write(sd->encoder, chunk, size, error) && - write_page(sd, error) - ? size - : 0; + encoder->Write(chunk, size); + write_page(this); + return size; } -static bool -my_shout_pause(AudioOutput *ao) +bool +ShoutOutput::Pause() { static char silence[1020]; - return my_shout_play(ao, silence, sizeof(silence), IgnoreError()); + try { + encoder->Write(silence, sizeof(silence)); + write_page(this); + } catch (const std::runtime_error &) { + return false; + } + + return true; } static void -shout_tag_to_metadata(const Tag *tag, char *dest, size_t size) +shout_tag_to_metadata(const Tag &tag, char *dest, size_t size) { char artist[size]; char title[size]; @@ -471,7 +401,7 @@ artist[0] = 0; title[0] = 0; - for (const auto &item : *tag) { + for (const auto &item : tag) { switch (item.type) { case TAG_ARTIST: strncpy(artist, item.value, size); @@ -488,51 +418,47 @@ snprintf(dest, size, "%s - %s", artist, title); } -static void my_shout_set_tag(AudioOutput *ao, - const Tag *tag) +void +ShoutOutput::SendTag(const Tag &tag) { - ShoutOutput *sd = (ShoutOutput *)ao; - - if (sd->encoder->plugin.tag != nullptr) { + if (encoder->ImplementsTag()) { /* encoder plugin supports stream tags */ - Error error; - if (!encoder_pre_tag(sd->encoder, error) || - !write_page(sd, error) || - !encoder_tag(sd->encoder, tag, error)) { - LogError(error); - return; - } + encoder->PreTag(); + write_page(this); + encoder->SendTag(tag); } else { /* no stream tag support: fall back to icy-metadata */ char song[1024]; shout_tag_to_metadata(tag, song, sizeof(song)); - shout_metadata_add(sd->shout_meta, "song", song); - if (SHOUTERR_SUCCESS != shout_set_metadata(sd->shout_conn, - sd->shout_meta)) { + shout_metadata_add(shout_meta, "song", song); + if (SHOUTERR_SUCCESS != shout_set_metadata(shout_conn, + shout_meta)) { LogWarning(shout_output_domain, "error setting shout metadata"); } } - write_page(sd, IgnoreError()); + write_page(this); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin shout_output_plugin = { "shout", nullptr, - my_shout_init_driver, - my_shout_finish_driver, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - my_shout_open_device, - my_shout_close_device, - my_shout_delay, - my_shout_set_tag, - my_shout_play, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, + &Wrapper::SendTag, + &Wrapper::Play, nullptr, - my_shout_drop_buffered_audio, - my_shout_pause, + &Wrapper::Cancel, + &Wrapper::Pause, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/ShoutOutputPlugin.hxx mpd-0.20.9/src/output/plugins/ShoutOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/ShoutOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/ShoutOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/sles/AndroidSimpleBufferQueue.hxx mpd-0.20.9/src/output/plugins/sles/AndroidSimpleBufferQueue.hxx --- mpd-0.19.21/src/output/plugins/sles/AndroidSimpleBufferQueue.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/AndroidSimpleBufferQueue.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Max Kellermann + * Copyright (C) 2011-2012 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/output/plugins/sles/Engine.hxx mpd-0.20.9/src/output/plugins/sles/Engine.hxx --- mpd-0.19.21/src/output/plugins/sles/Engine.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/Engine.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Max Kellermann + * Copyright (C) 2011-2012 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/output/plugins/sles/Object.hxx mpd-0.20.9/src/output/plugins/sles/Object.hxx --- mpd-0.19.21/src/output/plugins/sles/Object.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/Object.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Max Kellermann + * Copyright (C) 2011-2012 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/output/plugins/sles/Play.hxx mpd-0.20.9/src/output/plugins/sles/Play.hxx --- mpd-0.19.21/src/output/plugins/sles/Play.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/Play.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Max Kellermann + * Copyright (C) 2011-2012 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff -Nru mpd-0.19.21/src/output/plugins/sles/SlesOutputPlugin.cxx mpd-0.20.9/src/output/plugins/sles/SlesOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/sles/SlesOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/SlesOutputPlugin.cxx 2017-05-16 05:11:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,8 +24,8 @@ #include "Play.hxx" #include "AndroidSimpleBufferQueue.hxx" #include "../../OutputAPI.hxx" +#include "../../Wrapper.hxx" #include "util/Macros.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" #include "system/ByteOrder.hxx" #include "Log.hxx" @@ -33,7 +33,11 @@ #include #include +#include + class SlesOutput { + friend struct AudioOutputWrapper; + static constexpr unsigned N_BUFFERS = 3; static constexpr size_t BUFFER_SIZE = 65536; @@ -81,27 +85,24 @@ uint8_t buffers[N_BUFFERS][BUFFER_SIZE]; public: - SlesOutput() - :base(sles_output_plugin) {} + SlesOutput(const ConfigBlock &block); operator AudioOutput *() { return &base; } - bool Initialize(const config_param ¶m, Error &error) { - return base.Configure(param, error); - } - - bool Configure(const config_param ¶m, Error &error); + static SlesOutput *Create(const ConfigBlock &block); - bool Open(AudioFormat &audio_format, Error &error); + void Open(AudioFormat &audio_format); void Close(); - unsigned Delay() { - return pause && !cancel ? 100 : 0; + std::chrono::steady_clock::duration Delay() noexcept { + return pause && !cancel + ? std::chrono::milliseconds(100) + : std::chrono::steady_clock::duration::zero(); } - size_t Play(const void *chunk, size_t size, Error &error); + size_t Play(const void *chunk, size_t size); void Drain(); void Cancel(); @@ -125,62 +126,52 @@ static constexpr Domain sles_domain("sles"); -inline bool -SlesOutput::Configure(const config_param &, Error &) +SlesOutput::SlesOutput(const ConfigBlock &block) + :base(sles_output_plugin, block) { - return true; } -inline bool -SlesOutput::Open(AudioFormat &audio_format, Error &error) +inline void +SlesOutput::Open(AudioFormat &audio_format) { SLresult result; SLObjectItf _object; result = slCreateEngine(&_object, 0, nullptr, 0, nullptr, nullptr); - if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), "slCreateEngine() failed"); - return false; - } + if (result != SL_RESULT_SUCCESS) + throw std::runtime_error("slCreateEngine() failed"); engine_object = SLES::Object(_object); result = engine_object.Realize(false); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), "Engine.Realize() failed"); engine_object.Destroy(); - return false; + throw std::runtime_error("Engine.Realize() failed"); } SLEngineItf _engine; result = engine_object.GetInterface(SL_IID_ENGINE, &_engine); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Engine.GetInterface(IID_ENGINE) failed"); engine_object.Destroy(); - return false; + throw std::runtime_error("Engine.GetInterface(IID_ENGINE) failed"); } SLES::Engine engine(_engine); result = engine.CreateOutputMix(&_object, 0, nullptr, nullptr); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Engine.CreateOutputMix() failed"); engine_object.Destroy(); - return false; + throw std::runtime_error("Engine.CreateOutputMix() failed"); } mix_object = SLES::Object(_object); result = mix_object.Realize(false); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Mix.Realize() failed"); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Mix.Realize() failed"); } SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { @@ -233,11 +224,9 @@ result = engine.CreateAudioPlayer(&_object, &audioSrc, &audioSnk, ARRAY_SIZE(ids2), ids2, req2); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Engine.CreateAudioPlayer() failed"); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Engine.CreateAudioPlayer() failed"); } play_object = SLES::Object(_object); @@ -255,23 +244,19 @@ result = play_object.Realize(false); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.Realize() failed"); play_object.Destroy(); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Play.Realize() failed"); } SLPlayItf _play; result = play_object.GetInterface(SL_IID_PLAY, &_play); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.GetInterface(IID_PLAY) failed"); play_object.Destroy(); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Play.GetInterface(IID_PLAY) failed"); } play = SLES::Play(_play); @@ -280,33 +265,27 @@ result = play_object.GetInterface(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &_queue); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.GetInterface(IID_ANDROIDSIMPLEBUFFERQUEUE) failed"); play_object.Destroy(); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Play.GetInterface(IID_ANDROIDSIMPLEBUFFERQUEUE) failed"); } queue = SLES::AndroidSimpleBufferQueue(_queue); result = queue.RegisterCallback(PlayedCallback, (void *)this); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.RegisterCallback() failed"); play_object.Destroy(); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Play.RegisterCallback() failed"); } result = play.SetPlayState(SL_PLAYSTATE_PLAYING); if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.SetPlayState(PLAYING) failed"); play_object.Destroy(); mix_object.Destroy(); engine_object.Destroy(); - return false; + throw std::runtime_error("Play.SetPlayState(PLAYING) failed"); } pause = cancel = false; @@ -316,8 +295,6 @@ // TODO: support other sample formats audio_format.format = SampleFormat::S16; - - return true; } inline void @@ -330,22 +307,19 @@ } inline size_t -SlesOutput::Play(const void *chunk, size_t size, Error &error) +SlesOutput::Play(const void *chunk, size_t size) { cancel = false; if (pause) { SLresult result = play.SetPlayState(SL_PLAYSTATE_PLAYING); - if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "Play.SetPlayState(PLAYING) failed"); - return false; - } + if (result != SL_RESULT_SUCCESS) + throw std::runtime_error("Play.SetPlayState(PLAYING) failed"); pause = false; } - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(filled < BUFFER_SIZE); @@ -361,11 +335,8 @@ return nbytes; SLresult result = queue.Enqueue(buffers[next], BUFFER_SIZE); - if (result != SL_RESULT_SUCCESS) { - error.Set(sles_domain, int(result), - "AndroidSimpleBufferQueue.Enqueue() failed"); - return 0; - } + if (result != SL_RESULT_SUCCESS) + throw std::runtime_error("AndroidSimpleBufferQueue.Enqueue() failed"); ++n_queued; next = (next + 1) % N_BUFFERS; @@ -377,7 +348,7 @@ inline void SlesOutput::Drain() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(filled < BUFFER_SIZE); @@ -400,7 +371,7 @@ FormatWarning(sles_domain, "AndroidSimpleBufferQueue.Clear() failed"); - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); n_queued = 0; filled = 0; } @@ -427,7 +398,7 @@ inline void SlesOutput::PlayedCallback() { - const ScopeLock protect(mutex); + const std::lock_guard protect(mutex); assert(n_queued > 0); --n_queued; cond.signal(); @@ -441,99 +412,28 @@ return true; } -static AudioOutput * -sles_output_init(const config_param ¶m, Error &error) +inline SlesOutput * +SlesOutput::Create(const ConfigBlock &block) { - SlesOutput *sles = new SlesOutput(); - - if (!sles->Initialize(param, error) || - !sles->Configure(param, error)) { - delete sles; - return nullptr; - } - - return *sles; + return new SlesOutput(block); } -static void -sles_output_finish(AudioOutput *ao) -{ - SlesOutput *sles = (SlesOutput *)ao; - - delete sles; -} - -static bool -sles_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Open(audio_format, error); -} - -static void -sles_output_close(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Close(); -} - -static unsigned -sles_output_delay(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Delay(); -} - -static size_t -sles_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Play(chunk, size, error); -} - -static void -sles_output_drain(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Drain(); -} - -static void -sles_output_cancel(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Cancel(); -} - -static bool -sles_output_pause(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Pause(); -} +typedef AudioOutputWrapper Wrapper; const struct AudioOutputPlugin sles_output_plugin = { "sles", sles_test_default_device, - sles_output_init, - sles_output_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - sles_output_open, - sles_output_close, - sles_output_delay, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - sles_output_play, - sles_output_drain, - sles_output_cancel, - sles_output_pause, + &Wrapper::Play, + &Wrapper::Drain, + &Wrapper::Cancel, + &Wrapper::Pause, nullptr, }; diff -Nru mpd-0.19.21/src/output/plugins/sles/SlesOutputPlugin.hxx mpd-0.20.9/src/output/plugins/sles/SlesOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/sles/SlesOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/sles/SlesOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/SndioOutputPlugin.cxx mpd-0.20.9/src/output/plugins/SndioOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/SndioOutputPlugin.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/SndioOutputPlugin.cxx 2017-02-01 20:58:30.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SndioOutputPlugin.hxx" +#include "../OutputAPI.hxx" +#include "../Wrapper.hxx" +#include "util/Domain.hxx" +#include "Log.hxx" + +/* work around a C++ incompatibility if the sndio API is emulated by + libroar: libroar's "struct roar_service_stream" has a member named + "new", which is an illegal identifier in C++ */ +#define new new_ + +#include + +/* undo the libroar workaround */ +#undef new + +#include + +#ifndef SIO_DEVANY +/* this macro is missing in libroar-dev 1.0~beta2-3 (Debian Wheezy) */ +#define SIO_DEVANY "default" +#endif + +static constexpr unsigned MPD_SNDIO_BUFFER_TIME_MS = 250; + +static constexpr Domain sndio_output_domain("sndio_output"); + +class SndioOutput { + friend struct AudioOutputWrapper; + AudioOutput base; + const char *const device; + const unsigned buffer_time; /* in ms */ + struct sio_hdl *sio_hdl; + +public: + SndioOutput(const ConfigBlock &block); + + static SndioOutput *Create(const ConfigBlock &block); + + void Open(AudioFormat &audio_format); + void Close(); + size_t Play(const void *chunk, size_t size); + void Cancel(); +}; + +SndioOutput::SndioOutput(const ConfigBlock &block) + :base(sndio_output_plugin, block), + device(block.GetBlockValue("device", SIO_DEVANY)), + buffer_time(block.GetBlockValue("buffer_time", + MPD_SNDIO_BUFFER_TIME_MS)) +{ +} + +SndioOutput * +SndioOutput::Create(const ConfigBlock &block) +{ + return new SndioOutput(block); +} + +static bool +sndio_test_default_device() +{ + struct sio_hdl *sio_hdl; + + sio_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0); + if (!sio_hdl) { + FormatError(sndio_output_domain, + "Error opening default sndio device"); + return false; + } + + sio_close(sio_hdl); + return true; +} + +void +SndioOutput::Open(AudioFormat &audio_format) +{ + struct sio_par par; + unsigned bits, rate, chans; + + sio_hdl = sio_open(device, SIO_PLAY, 0); + if (!sio_hdl) + throw std::runtime_error("Failed to open default sndio device"); + + switch (audio_format.format) { + case SampleFormat::S16: + bits = 16; + break; + case SampleFormat::S24_P32: + bits = 24; + break; + case SampleFormat::S32: + bits = 32; + break; + default: + audio_format.format = SampleFormat::S16; + bits = 16; + break; + } + + rate = audio_format.sample_rate; + chans = audio_format.channels; + + sio_initpar(&par); + par.bits = bits; + par.rate = rate; + par.pchan = chans; + par.sig = 1; + par.le = SIO_LE_NATIVE; + par.appbufsz = rate * buffer_time / 1000; + + if (!sio_setpar(sio_hdl, &par) || + !sio_getpar(sio_hdl, &par)) { + sio_close(sio_hdl); + throw std::runtime_error("Failed to set/get audio params"); + } + + if (par.bits != bits || + par.rate < rate * 995 / 1000 || + par.rate > rate * 1005 / 1000 || + par.pchan != chans || + par.sig != 1 || + par.le != SIO_LE_NATIVE) { + sio_close(sio_hdl); + throw std::runtime_error("Requested audio params cannot be satisfied"); + } + + if (!sio_start(sio_hdl)) { + sio_close(sio_hdl); + throw std::runtime_error("Failed to start audio device"); + } +} + +void +SndioOutput::Close() +{ + sio_close(sio_hdl); +} + +size_t +SndioOutput::Play(const void *chunk, size_t size) +{ + size_t n; + + n = sio_write(sio_hdl, chunk, size); + if (n == 0 && sio_eof(sio_hdl) != 0) + throw std::runtime_error("sndio write failed"); + return n; +} + +typedef AudioOutputWrapper Wrapper; + +const struct AudioOutputPlugin sndio_output_plugin = { + "sndio", + sndio_test_default_device, + &Wrapper::Init, + &Wrapper::Finish, + nullptr, + nullptr, + &Wrapper::Open, + &Wrapper::Close, + nullptr, + nullptr, + &Wrapper::Play, + nullptr, + nullptr, + nullptr, + nullptr, +}; diff -Nru mpd-0.19.21/src/output/plugins/SndioOutputPlugin.hxx mpd-0.20.9/src/output/plugins/SndioOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/SndioOutputPlugin.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/SndioOutputPlugin.hxx 2017-02-01 20:58:30.000000000 +0000 @@ -0,0 +1,25 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SNDIO_OUTPUT_PLUGIN_HXX +#define MPD_SNDIO_OUTPUT_PLUGIN_HXX + +extern const struct AudioOutputPlugin sndio_output_plugin; + +#endif diff -Nru mpd-0.19.21/src/output/plugins/SolarisOutputPlugin.cxx mpd-0.20.9/src/output/plugins/SolarisOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/SolarisOutputPlugin.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/SolarisOutputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "SolarisOutputPlugin.hxx" #include "../OutputAPI.hxx" #include "system/fd_util.h" -#include "util/Error.hxx" +#include "system/Error.hxx" #include #include @@ -53,16 +53,13 @@ AudioOutput base; /* configuration */ - const char *device; + const char *const device; int fd; - SolarisOutput() - :base(solaris_output_plugin) {} - - bool Initialize(const config_param ¶m, Error &error_r) { - return base.Configure(param, error_r); - } + explicit SolarisOutput(const ConfigBlock &block) + :base(solaris_output_plugin, block), + device(block.GetBlockValue("device", "/dev/audio")) {} }; static bool @@ -75,16 +72,9 @@ } static AudioOutput * -solaris_output_init(const config_param ¶m, Error &error_r) +solaris_output_init(const ConfigBlock &block) { - SolarisOutput *so = new SolarisOutput(); - if (!so->Initialize(param, error_r)) { - delete so; - return nullptr; - } - - so->device = param.GetBlockValue("device", "/dev/audio"); - + SolarisOutput *so = new SolarisOutput(block); return &so->base; } @@ -96,9 +86,8 @@ delete so; } -static bool -solaris_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +static void +solaris_output_open(AudioOutput *ao, AudioFormat &audio_format) { SolarisOutput *so = (SolarisOutput *)ao; struct audio_info info; @@ -111,11 +100,9 @@ /* open the device in non-blocking mode */ so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0); - if (so->fd < 0) { - error.FormatErrno("Failed to open %s", + if (so->fd < 0) + throw FormatErrno("Failed to open %s", so->device); - return false; - } /* restore blocking mode */ @@ -127,9 +114,9 @@ ret = ioctl(so->fd, AUDIO_GETINFO, &info); if (ret < 0) { - error.SetErrno("AUDIO_GETINFO failed"); + const int e = errno; close(so->fd); - return false; + throw MakeErrno(e, "AUDIO_GETINFO failed"); } info.play.sample_rate = audio_format.sample_rate; @@ -139,12 +126,10 @@ ret = ioctl(so->fd, AUDIO_SETINFO, &info); if (ret < 0) { - error.SetErrno("AUDIO_SETINFO failed"); + const int e = errno; close(so->fd); - return false; + throw MakeErrno(e, "AUDIO_SETINFO failed"); } - - return true; } static void @@ -156,17 +141,14 @@ } static size_t -solaris_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) +solaris_output_play(AudioOutput *ao, const void *chunk, size_t size) { SolarisOutput *so = (SolarisOutput *)ao; ssize_t nbytes; nbytes = write(so->fd, chunk, size); - if (nbytes <= 0) { - error.SetErrno("Write failed"); - return 0; - } + if (nbytes <= 0) + throw MakeErrno("Write failed"); return nbytes; } diff -Nru mpd-0.19.21/src/output/plugins/SolarisOutputPlugin.hxx mpd-0.20.9/src/output/plugins/SolarisOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/SolarisOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/SolarisOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/plugins/WinmmOutputPlugin.cxx mpd-0.20.9/src/output/plugins/WinmmOutputPlugin.cxx --- mpd-0.19.21/src/output/plugins/WinmmOutputPlugin.cxx 2016-11-07 07:53:39.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/WinmmOutputPlugin.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,11 +20,15 @@ #include "config.h" #include "WinmmOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "pcm/PcmBuffer.hxx" #include "mixer/MixerList.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" +#include "fs/AllocatedPath.hxx" +#include "util/RuntimeError.hxx" #include "util/Macros.hxx" +#include "util/StringCompare.hxx" + +#include #include #include @@ -35,10 +39,12 @@ WAVEHDR hdr; }; -struct WinmmOutput { +class WinmmOutput { + friend struct AudioOutputWrapper; + AudioOutput base; - UINT device_id; + const UINT device_id; HWAVEOUT handle; /** @@ -47,19 +53,54 @@ */ HANDLE event; - WinmmBuffer buffers[8]; + std::array buffers; unsigned next_buffer; - WinmmOutput() - :base(winmm_output_plugin) {} +public: + WinmmOutput(const ConfigBlock &block); + + HWAVEOUT GetHandle() { + return handle; + } + + static WinmmOutput *Create(const ConfigBlock &block) { + return new WinmmOutput(block); + } + + void Open(AudioFormat &audio_format); + void Close(); + + size_t Play(const void *chunk, size_t size); + void Drain(); + void Cancel(); + +private: + /** + * Wait until the buffer is finished. + */ + void DrainBuffer(WinmmBuffer &buffer); + + void DrainAllBuffers(); + + void Stop(); + }; -static constexpr Domain winmm_output_domain("winmm_output"); +static std::runtime_error +MakeWaveOutError(MMRESULT result, const char *prefix) +{ + char buffer[256]; + if (waveOutGetErrorTextA(result, buffer, + ARRAY_SIZE(buffer)) == MMSYSERR_NOERROR) + return FormatRuntimeError("%s: %s", prefix, buffer); + else + return std::runtime_error(prefix); +} HWAVEOUT winmm_output_get_handle(WinmmOutput &output) { - return output.handle; + return output.GetHandle(); } static bool @@ -68,14 +109,12 @@ return waveOutGetNumDevs() > 0; } -static bool -get_device_id(const char *device_name, UINT *device_id, Error &error) +static UINT +get_device_id(const char *device_name) { /* if device is not specified use wave mapper */ - if (device_name == nullptr) { - *device_id = WAVE_MAPPER; - return true; - } + if (device_name == nullptr) + return WAVE_MAPPER; UINT numdevs = waveOutGetNumDevs(); @@ -84,12 +123,16 @@ UINT id = strtoul(device_name, &endptr, 0); if (endptr > device_name && *endptr == 0) { if (id >= numdevs) - goto fail; - *device_id = id; - return true; + throw FormatRuntimeError("device \"%s\" is not found", + device_name); + + return id; } /* check for device name */ + const AllocatedPath device_name_fs = + AllocatedPath::FromUTF8Throw(device_name); + for (UINT i = 0; i < numdevs; i++) { WAVEOUTCAPS caps; MMRESULT result = waveOutGetDevCaps(i, &caps, sizeof(caps)); @@ -97,55 +140,25 @@ continue; /* szPname is only 32 chars long, so it is often truncated. Use partial match to work around this. */ - if (strstr(device_name, caps.szPname) == device_name) { - *device_id = i; - return true; - } - } - -fail: - error.Format(winmm_output_domain, - "device \"%s\" is not found", device_name); - return false; -} - -static AudioOutput * -winmm_output_init(const config_param ¶m, Error &error) -{ - WinmmOutput *wo = new WinmmOutput(); - if (!wo->base.Configure(param, error)) { - delete wo; - return nullptr; + if (StringStartsWith(device_name_fs.c_str(), caps.szPname)) + return i; } - const char *device = param.GetBlockValue("device"); - if (!get_device_id(device, &wo->device_id, error)) { - delete wo; - return nullptr; - } - - return &wo->base; + throw FormatRuntimeError("device \"%s\" is not found", device_name); } -static void -winmm_output_finish(AudioOutput *ao) +WinmmOutput::WinmmOutput(const ConfigBlock &block) + :base(winmm_output_plugin, block), + device_id(get_device_id(block.GetBlockValue("device"))) { - WinmmOutput *wo = (WinmmOutput *)ao; - - delete wo; } -static bool -winmm_output_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) +void +WinmmOutput::Open(AudioFormat &audio_format) { - WinmmOutput *wo = (WinmmOutput *)ao; - - wo->event = CreateEvent(nullptr, false, false, nullptr); - if (wo->event == nullptr) { - error.Set(winmm_output_domain, "CreateEvent() failed"); - return false; - } + event = CreateEvent(nullptr, false, false, nullptr); + if (event == nullptr) + throw std::runtime_error("CreateEvent() failed"); switch (audio_format.format) { case SampleFormat::S16: @@ -175,43 +188,36 @@ format.wBitsPerSample = audio_format.GetSampleSize() * 8; format.cbSize = 0; - MMRESULT result = waveOutOpen(&wo->handle, wo->device_id, &format, - (DWORD_PTR)wo->event, 0, CALLBACK_EVENT); + MMRESULT result = waveOutOpen(&handle, device_id, &format, + (DWORD_PTR)event, 0, CALLBACK_EVENT); if (result != MMSYSERR_NOERROR) { - CloseHandle(wo->event); - error.Set(winmm_output_domain, "waveOutOpen() failed"); - return false; + CloseHandle(event); + throw MakeWaveOutError(result, "waveOutOpen() failed"); } - for (unsigned i = 0; i < ARRAY_SIZE(wo->buffers); ++i) { - memset(&wo->buffers[i].hdr, 0, sizeof(wo->buffers[i].hdr)); - } + for (auto &i : buffers) + memset(&i.hdr, 0, sizeof(i.hdr)); - wo->next_buffer = 0; - - return true; + next_buffer = 0; } -static void -winmm_output_close(AudioOutput *ao) +void +WinmmOutput::Close() { - WinmmOutput *wo = (WinmmOutput *)ao; - - for (unsigned i = 0; i < ARRAY_SIZE(wo->buffers); ++i) - wo->buffers[i].buffer.Clear(); + for (auto &i : buffers) + i.buffer.Clear(); - waveOutClose(wo->handle); + waveOutClose(handle); - CloseHandle(wo->event); + CloseHandle(event); } /** * Copy data into a buffer, and prepare the wave header. */ -static bool -winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, - const void *data, size_t size, - Error &error) +static void +winmm_set_buffer(HWAVEOUT handle, WinmmBuffer *buffer, + const void *data, size_t size) { void *dest = buffer->buffer.Get(size); assert(dest != nullptr); @@ -222,131 +228,110 @@ buffer->hdr.lpData = (LPSTR)dest; buffer->hdr.dwBufferLength = size; - MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr, + MMRESULT result = waveOutPrepareHeader(handle, &buffer->hdr, sizeof(buffer->hdr)); - if (result != MMSYSERR_NOERROR) { - error.Set(winmm_output_domain, result, - "waveOutPrepareHeader() failed"); - return false; - } - - return true; + if (result != MMSYSERR_NOERROR) + throw MakeWaveOutError(result, + "waveOutPrepareHeader() failed"); } -/** - * Wait until the buffer is finished. - */ -static bool -winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, - Error &error) +void +WinmmOutput::DrainBuffer(WinmmBuffer &buffer) { - if ((buffer->hdr.dwFlags & WHDR_DONE) == WHDR_DONE) + if ((buffer.hdr.dwFlags & WHDR_DONE) == WHDR_DONE) /* already finished */ - return true; + return; while (true) { - MMRESULT result = waveOutUnprepareHeader(wo->handle, - &buffer->hdr, - sizeof(buffer->hdr)); + MMRESULT result = waveOutUnprepareHeader(handle, + &buffer.hdr, + sizeof(buffer.hdr)); if (result == MMSYSERR_NOERROR) - return true; - else if (result != WAVERR_STILLPLAYING) { - error.Set(winmm_output_domain, result, - "waveOutUnprepareHeader() failed"); - return false; - } + return; + else if (result != WAVERR_STILLPLAYING) + throw MakeWaveOutError(result, + "waveOutUnprepareHeader() failed"); /* wait some more */ - WaitForSingleObject(wo->event, INFINITE); + WaitForSingleObject(event, INFINITE); } } -static size_t -winmm_output_play(AudioOutput *ao, const void *chunk, size_t size, Error &error) +size_t +WinmmOutput::Play(const void *chunk, size_t size) { - WinmmOutput *wo = (WinmmOutput *)ao; - /* get the next buffer from the ring and prepare it */ - WinmmBuffer *buffer = &wo->buffers[wo->next_buffer]; - if (!winmm_drain_buffer(wo, buffer, error) || - !winmm_set_buffer(wo, buffer, chunk, size, error)) - return 0; + WinmmBuffer *buffer = &buffers[next_buffer]; + DrainBuffer(*buffer); + winmm_set_buffer(handle, buffer, chunk, size); /* enqueue the buffer */ - MMRESULT result = waveOutWrite(wo->handle, &buffer->hdr, + MMRESULT result = waveOutWrite(handle, &buffer->hdr, sizeof(buffer->hdr)); if (result != MMSYSERR_NOERROR) { - waveOutUnprepareHeader(wo->handle, &buffer->hdr, + waveOutUnprepareHeader(handle, &buffer->hdr, sizeof(buffer->hdr)); - error.Set(winmm_output_domain, result, - "waveOutWrite() failed"); - return 0; + throw MakeWaveOutError(result, "waveOutWrite() failed"); } /* mark our buffer as "used" */ - wo->next_buffer = (wo->next_buffer + 1) % - ARRAY_SIZE(wo->buffers); + next_buffer = (next_buffer + 1) % buffers.size(); return size; } -static bool -winmm_drain_all_buffers(WinmmOutput *wo, Error &error) +void +WinmmOutput::DrainAllBuffers() { - for (unsigned i = wo->next_buffer; i < ARRAY_SIZE(wo->buffers); ++i) - if (!winmm_drain_buffer(wo, &wo->buffers[i], error)) - return false; - - for (unsigned i = 0; i < wo->next_buffer; ++i) - if (!winmm_drain_buffer(wo, &wo->buffers[i], error)) - return false; + for (unsigned i = next_buffer; i < buffers.size(); ++i) + DrainBuffer(buffers[i]); - return true; + for (unsigned i = 0; i < next_buffer; ++i) + DrainBuffer(buffers[i]); } -static void -winmm_stop(WinmmOutput *wo) +void +WinmmOutput::Stop() { - waveOutReset(wo->handle); + waveOutReset(handle); - for (unsigned i = 0; i < ARRAY_SIZE(wo->buffers); ++i) { - WinmmBuffer *buffer = &wo->buffers[i]; - waveOutUnprepareHeader(wo->handle, &buffer->hdr, - sizeof(buffer->hdr)); - } + for (auto &i : buffers) + waveOutUnprepareHeader(handle, &i.hdr, sizeof(i.hdr)); } -static void -winmm_output_drain(AudioOutput *ao) +void +WinmmOutput::Drain() { - WinmmOutput *wo = (WinmmOutput *)ao; - - if (!winmm_drain_all_buffers(wo, IgnoreError())) - winmm_stop(wo); + try { + DrainAllBuffers(); + } catch (...) { + Stop(); + throw; + } } -static void -winmm_output_cancel(AudioOutput *ao) +void +WinmmOutput::Cancel() { - WinmmOutput *wo = (WinmmOutput *)ao; - - winmm_stop(wo); + Stop(); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin winmm_output_plugin = { "winmm", winmm_output_test_default_device, - winmm_output_init, - winmm_output_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - winmm_output_open, - winmm_output_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, nullptr, - winmm_output_play, - winmm_output_drain, - winmm_output_cancel, + &Wrapper::Play, + &Wrapper::Drain, + &Wrapper::Cancel, nullptr, &winmm_mixer_plugin, }; diff -Nru mpd-0.19.21/src/output/plugins/WinmmOutputPlugin.hxx mpd-0.20.9/src/output/plugins/WinmmOutputPlugin.hxx --- mpd-0.19.21/src/output/plugins/WinmmOutputPlugin.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/plugins/WinmmOutputPlugin.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/Registry.cxx mpd-0.20.9/src/output/Registry.cxx --- mpd-0.19.21/src/output/Registry.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Registry.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,13 @@ #include "config.h" #include "Registry.hxx" -#include "OutputAPI.hxx" +#include "OutputPlugin.hxx" #include "plugins/AlsaOutputPlugin.hxx" #include "plugins/AoOutputPlugin.hxx" #include "plugins/FifoOutputPlugin.hxx" +#include "plugins/SndioOutputPlugin.hxx" #include "plugins/httpd/HttpdOutputPlugin.hxx" +#include "plugins/HaikuOutputPlugin.hxx" #include "plugins/JackOutputPlugin.hxx" #include "plugins/NullOutputPlugin.hxx" #include "plugins/OpenALOutputPlugin.hxx" @@ -51,16 +53,22 @@ #ifdef HAVE_FIFO &fifo_output_plugin, #endif +#ifdef ENABLE_SNDIO + &sndio_output_plugin, +#endif +#ifdef ENABLE_HAIKU + &haiku_output_plugin, +#endif #ifdef ENABLE_PIPE_OUTPUT &pipe_output_plugin, #endif -#ifdef HAVE_ALSA +#ifdef ENABLE_ALSA &alsa_output_plugin, #endif -#ifdef HAVE_ROAR +#ifdef ENABLE_ROAR &roar_output_plugin, #endif -#ifdef HAVE_AO +#ifdef ENABLE_AO &ao_output_plugin, #endif #ifdef HAVE_OSS @@ -75,10 +83,10 @@ #ifdef ENABLE_SOLARIS_OUTPUT &solaris_output_plugin, #endif -#ifdef HAVE_PULSE +#ifdef ENABLE_PULSE &pulse_output_plugin, #endif -#ifdef HAVE_JACK +#ifdef ENABLE_JACK &jack_output_plugin, #endif #ifdef ENABLE_HTTPD_OUTPUT diff -Nru mpd-0.19.21/src/output/Registry.hxx mpd-0.20.9/src/output/Registry.hxx --- mpd-0.19.21/src/output/Registry.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Registry.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff -Nru mpd-0.19.21/src/output/SharedPipeConsumer.cxx mpd-0.20.9/src/output/SharedPipeConsumer.cxx --- mpd-0.19.21/src/output/SharedPipeConsumer.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/SharedPipeConsumer.cxx 2017-05-08 12:53:49.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SharedPipeConsumer.hxx" +#include "MusicChunk.hxx" +#include "MusicPipe.hxx" + +const MusicChunk * +SharedPipeConsumer::Get() noexcept +{ + if (chunk != nullptr) { + if (!consumed) + return chunk; + + if (chunk->next == nullptr) + return nullptr; + + consumed = false; + return chunk = chunk->next; + } else { + /* get the first chunk from the pipe */ + consumed = false; + return chunk = pipe->Peek(); + } +} + +bool +SharedPipeConsumer::IsConsumed(const MusicChunk &_chunk) const noexcept +{ + if (chunk == nullptr) + return false; + + assert(&_chunk == chunk || pipe->Contains(chunk)); + + if (&_chunk != chunk) { + assert(_chunk.next != nullptr); + return true; + } + + return consumed && _chunk.next == nullptr; +} diff -Nru mpd-0.19.21/src/output/SharedPipeConsumer.hxx mpd-0.20.9/src/output/SharedPipeConsumer.hxx --- mpd-0.19.21/src/output/SharedPipeConsumer.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/SharedPipeConsumer.hxx 2017-05-08 12:52:19.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef SHARED_PIPE_CONSUMER_HXX +#define SHARED_PIPE_CONSUMER_HXX + +#include "check.h" +#include "Compiler.h" + +#include + +struct MusicChunk; +class MusicPipe; + +/** + * A utility class which helps with consuming data from a #MusicPipe. + * + * This class is intentionally not thread-safe. Since it is designed + * to be called from two distinct threads (PlayerThread=feeder and + * OutputThread=consumer), all methods must be called with a mutex + * locked to serialize access. Usually, this is #AudioOutput::mutex. + */ +class SharedPipeConsumer { + /** + * The music pipe which provides music chunks to be played. + */ + const MusicPipe *pipe = nullptr; + + /** + * The #MusicChunk which is currently being played. All + * chunks before this one may be returned to the #MusicBuffer, + * because they are not going to be used by this output + * anymore. + */ + const MusicChunk *chunk; + + /** + * Has the output finished playing #chunk? + */ + bool consumed; + +public: + void Init(const MusicPipe &_pipe) { + pipe = &_pipe; + chunk = nullptr; + } + + const MusicPipe &GetPipe() { + assert(pipe != nullptr); + + return *pipe; + } + + bool IsInitial() { + return chunk == nullptr; + } + + void Cancel() { + chunk = nullptr; + } + + const MusicChunk *Get() noexcept; + + void Consume(gcc_unused const MusicChunk &_chunk) { + assert(chunk != nullptr); + assert(chunk == &_chunk); + + consumed = true; + } + + gcc_pure + bool IsConsumed(const MusicChunk &_chunk) const noexcept; + + void ClearTail(gcc_unused const MusicChunk &_chunk) noexcept { + assert(chunk == &_chunk); + assert(consumed); + chunk = nullptr; + } +}; + +#endif diff -Nru mpd-0.19.21/src/output/Source.cxx mpd-0.20.9/src/output/Source.cxx --- mpd-0.19.21/src/output/Source.cxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/Source.cxx 2017-05-08 12:51:30.000000000 +0000 @@ -0,0 +1,247 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Source.hxx" +#include "MusicChunk.hxx" +#include "filter/FilterInternal.hxx" +#include "filter/plugins/ReplayGainFilterPlugin.hxx" +#include "pcm/PcmMix.hxx" +#include "thread/Mutex.hxx" +#include "util/ConstBuffer.hxx" +#include "util/RuntimeError.hxx" + +#include + +AudioFormat +AudioOutputSource::Open(AudioFormat audio_format, const MusicPipe &_pipe, + PreparedFilter *prepared_replay_gain_filter, + PreparedFilter *prepared_other_replay_gain_filter, + PreparedFilter *prepared_filter) +{ + assert(audio_format.IsValid()); + + if (!IsOpen() || &_pipe != &pipe.GetPipe()) + pipe.Init(_pipe); + + /* (re)open the filter */ + + if (filter_instance != nullptr && + audio_format != in_audio_format) + /* the filter must be reopened on all input format + changes */ + CloseFilter(); + + if (filter_instance == nullptr) + /* open the filter */ + OpenFilter(audio_format, + prepared_replay_gain_filter, + prepared_other_replay_gain_filter, + prepared_filter); + + in_audio_format = audio_format; + return filter_instance->GetOutAudioFormat(); +} + +void +AudioOutputSource::Close() noexcept +{ + assert(in_audio_format.IsValid()); + in_audio_format.Clear(); + + Cancel(); + + CloseFilter(); +} + +void +AudioOutputSource::Cancel() noexcept +{ + current_chunk = nullptr; + pipe.Cancel(); + + if (replay_gain_filter_instance != nullptr) + replay_gain_filter_instance->Reset(); + + if (other_replay_gain_filter_instance != nullptr) + other_replay_gain_filter_instance->Reset(); + + if (filter_instance != nullptr) + filter_instance->Reset(); +} + +void +AudioOutputSource::OpenFilter(AudioFormat audio_format, + PreparedFilter *prepared_replay_gain_filter, + PreparedFilter *prepared_other_replay_gain_filter, + PreparedFilter *prepared_filter) +try { + assert(audio_format.IsValid()); + + /* the replay_gain filter cannot fail here */ + if (prepared_replay_gain_filter != nullptr) { + replay_gain_serial = 0; + replay_gain_filter_instance = + prepared_replay_gain_filter->Open(audio_format); + } + + if (prepared_other_replay_gain_filter != nullptr) { + other_replay_gain_serial = 0; + other_replay_gain_filter_instance = + prepared_other_replay_gain_filter->Open(audio_format); + } + + filter_instance = prepared_filter->Open(audio_format); +} catch (...) { + CloseFilter(); + throw; +} + +void +AudioOutputSource::CloseFilter() noexcept +{ + delete replay_gain_filter_instance; + replay_gain_filter_instance = nullptr; + + delete other_replay_gain_filter_instance; + other_replay_gain_filter_instance = nullptr; + + delete filter_instance; + filter_instance = nullptr; +} + +ConstBuffer +AudioOutputSource::GetChunkData(const MusicChunk &chunk, + Filter *replay_gain_filter, + unsigned *replay_gain_serial_p) +{ + assert(!chunk.IsEmpty()); + assert(chunk.CheckFormat(in_audio_format)); + + ConstBuffer data(chunk.data, chunk.length); + + assert(data.size % in_audio_format.GetFrameSize() == 0); + + if (!data.IsEmpty() && replay_gain_filter != nullptr) { + replay_gain_filter_set_mode(*replay_gain_filter, + replay_gain_mode); + + if (chunk.replay_gain_serial != *replay_gain_serial_p) { + replay_gain_filter_set_info(*replay_gain_filter, + chunk.replay_gain_serial != 0 + ? &chunk.replay_gain_info + : nullptr); + *replay_gain_serial_p = chunk.replay_gain_serial; + } + + data = replay_gain_filter->FilterPCM(data); + } + + return data; +} + +ConstBuffer +AudioOutputSource::FilterChunk(const MusicChunk &chunk) +{ + auto data = GetChunkData(chunk, replay_gain_filter_instance, + &replay_gain_serial); + if (data.IsEmpty()) + return data; + + /* cross-fade */ + + if (chunk.other != nullptr) { + auto other_data = GetChunkData(*chunk.other, + other_replay_gain_filter_instance, + &other_replay_gain_serial); + if (other_data.IsEmpty()) + return data; + + /* if the "other" chunk is longer, then that trailer + is used as-is, without mixing; it is part of the + "next" song being faded in, and if there's a rest, + it means cross-fading ends here */ + + if (data.size > other_data.size) + data.size = other_data.size; + + float mix_ratio = chunk.mix_ratio; + if (mix_ratio >= 0) + /* reverse the mix ratio (because the + arguments to pcm_mix() are reversed), but + only if the mix ratio is non-negative; a + negative mix ratio is a MixRamp special + case */ + mix_ratio = 1.0 - mix_ratio; + + void *dest = cross_fade_buffer.Get(other_data.size); + memcpy(dest, other_data.data, other_data.size); + if (!pcm_mix(cross_fade_dither, dest, data.data, data.size, + in_audio_format.format, + mix_ratio)) + throw FormatRuntimeError("Cannot cross-fade format %s", + sample_format_to_string(in_audio_format.format)); + + data.data = dest; + data.size = other_data.size; + } + + /* apply filter chain */ + + return filter_instance->FilterPCM(data); +} + +bool +AudioOutputSource::Fill(Mutex &mutex) +{ + if (current_chunk != nullptr && pending_tag == nullptr && + pending_data.IsEmpty()) + pipe.Consume(*std::exchange(current_chunk, nullptr)); + + if (current_chunk != nullptr) + return true; + + current_chunk = pipe.Get(); + if (current_chunk == nullptr) + return false; + + pending_tag = current_chunk->tag; + + try { + /* release the mutex while the filter runs, because + that may take a while */ + const ScopeUnlock unlock(mutex); + + pending_data = pending_data.FromVoid(FilterChunk(*current_chunk)); + } catch (...) { + current_chunk = nullptr; + throw; + } + + return true; +} + +void +AudioOutputSource::ConsumeData(size_t nbytes) noexcept +{ + pending_data.skip_front(nbytes); + + if (pending_data.IsEmpty()) + pipe.Consume(*std::exchange(current_chunk, nullptr)); +} diff -Nru mpd-0.19.21/src/output/Source.hxx mpd-0.20.9/src/output/Source.hxx --- mpd-0.19.21/src/output/Source.hxx 1970-01-01 00:00:00.000000000 +0000 +++ mpd-0.20.9/src/output/Source.hxx 2017-05-08 12:52:26.000000000 +0000 @@ -0,0 +1,209 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef AUDIO_OUTPUT_SOURCE_HXX +#define AUDIO_OUTPUT_SOURCE_HXX + +#include "check.h" +#include "Compiler.h" +#include "SharedPipeConsumer.hxx" +#include "AudioFormat.hxx" +#include "ReplayGainMode.hxx" +#include "pcm/PcmBuffer.hxx" +#include "pcm/PcmDither.hxx" +#include "util/ConstBuffer.hxx" + +#include + +#include +#include + +struct MusicChunk; +struct Tag; +class Mutex; +class Filter; +class PreparedFilter; + +/** + * Source of audio data to be played by an #AudioOutput. It receives + * #MusicChunk instances from a #MusicPipe (via #SharedPipeConsumer). + * It applies configured filters, ReplayGain and returns plain PCM + * data. + */ +class AudioOutputSource { + /** + * The audio_format in which audio data is received from the + * player thread (which in turn receives it from the decoder). + */ + AudioFormat in_audio_format = AudioFormat::Undefined(); + + ReplayGainMode replay_gain_mode = ReplayGainMode::OFF; + + /** + * A reference to the #MusicPipe and the current position. + */ + SharedPipeConsumer pipe; + + /** + * The serial number of the last replay gain info. 0 means no + * replay gain info was available. + */ + unsigned replay_gain_serial; + + /** + * The serial number of the last replay gain info by the + * "other" chunk during cross-fading. + */ + unsigned other_replay_gain_serial; + + /** + * The replay_gain_filter_plugin instance of this audio + * output. + */ + Filter *replay_gain_filter_instance = nullptr; + + /** + * The replay_gain_filter_plugin instance of this audio + * output, to be applied to the second chunk during + * cross-fading. + */ + Filter *other_replay_gain_filter_instance = nullptr; + + /** + * The buffer used to allocate the cross-fading result. + */ + PcmBuffer cross_fade_buffer; + + /** + * The dithering state for cross-fading two streams. + */ + PcmDither cross_fade_dither; + + /** + * The filter object of this audio output. This is an + * instance of chain_filter_plugin. + */ + Filter *filter_instance = nullptr; + + /** + * The #MusicChunk currently being processed (see + * #pending_tag, #pending_data). + */ + const MusicChunk *current_chunk = nullptr; + + /** + * The #Tag to be processed by the #AudioOutput. + */ + const Tag *pending_tag; + + /** + * Filtered #MusicChunk PCM data to be processed by the + * #AudioOutput. + */ + ConstBuffer pending_data; + +public: + void SetReplayGainMode(ReplayGainMode _mode) { + replay_gain_mode = _mode; + } + + bool IsOpen() const { + return in_audio_format.IsDefined(); + } + + const AudioFormat &GetInputAudioFormat() const { + assert(IsOpen()); + + return in_audio_format; + } + + AudioFormat Open(AudioFormat audio_format, const MusicPipe &_pipe, + PreparedFilter *prepared_replay_gain_filter, + PreparedFilter *prepared_other_replay_gain_filter, + PreparedFilter *prepared_filter); + + void Close() noexcept; + void Cancel() noexcept; + + /** + * Ensure that ReadTag() or PeekData() return any input. + * + * Throws std::runtime_error on error + * + * @param mutex the #Mutex which protects the + * #SharedPipeConsumer; it is locked by the caller, and may be + * unlocked temporarily by this method + * @return true if any input is available, false if the source + * has (temporarily?) run empty + */ + bool Fill(Mutex &mutex); + + /** + * Reads the #Tag to be processed. Be sure to call Fill() + * successfully before calling this metohd. + */ + const Tag *ReadTag() noexcept { + assert(current_chunk != nullptr); + + return std::exchange(pending_tag, nullptr); + } + + /** + * Returns the remaining filtered PCM data be played. The + * caller shall use ConsumeData() to mark portions of the + * return value as "consumed". + * + * Be sure to call Fill() successfully before calling this + * metohd. + */ + ConstBuffer PeekData() const noexcept { + return pending_data.ToVoid(); + } + + /** + * Mark portions of the PeekData() return value as "consumed". + */ + void ConsumeData(size_t nbytes) noexcept; + + bool IsChunkConsumed(const MusicChunk &chunk) const noexcept { + assert(IsOpen()); + + return pipe.IsConsumed(chunk); + } + + void ClearTailChunk(const MusicChunk &chunk) noexcept { + pipe.ClearTail(chunk); + } + +private: + void OpenFilter(AudioFormat audio_format, + PreparedFilter *prepared_replay_gain_filter, + PreparedFilter *prepared_other_replay_gain_filter, + PreparedFilter *prepared_filter); + + void CloseFilter() noexcept; + + ConstBuffer GetChunkData(const MusicChunk &chunk, + Filter *replay_gain_filter, + unsigned *replay_gain_serial_p); + + ConstBuffer FilterChunk(const MusicChunk &chunk); +}; + +#endif diff -Nru mpd-0.19.21/src/output/Timer.cxx mpd-0.20.9/src/output/Timer.cxx --- mpd-0.19.21/src/output/Timer.cxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Timer.cxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,48 +20,45 @@ #include "config.h" #include "Timer.hxx" #include "AudioFormat.hxx" -#include "system/Clock.hxx" #include #include Timer::Timer(const AudioFormat af) - : time(0), - started(false), - rate(af.sample_rate * af.GetFrameSize()) + :rate(af.sample_rate * af.GetFrameSize()) { } void Timer::Start() { - time = MonotonicClockUS(); + time = Now(); started = true; } void Timer::Reset() { - time = 0; started = false; } -void Timer::Add(int size) +void +Timer::Add(size_t size) { assert(started); // (size samples) / (rate samples per second) = duration seconds // duration seconds * 1000000 = duration us - time += ((uint64_t)size * 1000000) / rate; + time += Time(((uint64_t)size * Time::period::den) / (Time::period::num * rate)); } -unsigned Timer::GetDelay() const +std::chrono::steady_clock::duration +Timer::GetDelay() const { - int64_t delay = (int64_t)(time - MonotonicClockUS()) / 1000; - if (delay < 0) - return 0; + assert(started); - if (delay > std::numeric_limits::max()) - delay = std::numeric_limits::max(); + const auto delay = time - Now(); + if (delay < Time::zero()) + return Time::zero(); - return delay; + return std::chrono::duration_cast(delay); } diff -Nru mpd-0.19.21/src/output/Timer.hxx mpd-0.20.9/src/output/Timer.hxx --- mpd-0.19.21/src/output/Timer.hxx 2016-07-29 08:01:52.000000000 +0000 +++ mpd-0.20.9/src/output/Timer.hxx 2017-01-27 07:46:51.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright 2003-2017 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,15 @@ #ifndef MPD_TIMER_HXX #define MPD_TIMER_HXX -#include +#include struct AudioFormat; class Timer { - uint64_t time; - bool started; + typedef std::chrono::microseconds Time; + + Time time; + bool started = false; const int rate; public: explicit Timer(AudioFormat af); @@ -36,12 +38,17 @@ void Start(); void Reset(); - void Add(int size); + void Add(size_t size); /** - * Returns the number of milliseconds to sleep to get back to sync. + * Returns the duration to sleep to get back to sync. */ - unsigned GetDelay() const; + std::chrono::steady_clock::duration GetDelay() const; + +private: + static Time Now() { + return std::chrono::duration_cast