[Pkg-mpd-commits] [pkg-mpd] 01/07: Imported Upstream version 0.19.18
Florian Schlichting
fsfs at moszumanska.debian.org
Thu Aug 18 21:55:27 UTC 2016
This is an automated email from the git hooks/post-receive script.
fsfs pushed a commit to branch master
in repository pkg-mpd.
commit 7be2afa7debb811219abf16d67b5947ba88812aa
Author: Florian Schlichting <fsfs at debian.org>
Date: Thu Aug 18 22:52:40 2016 +0200
Imported Upstream version 0.19.18
---
INSTALL | 2 +-
Makefile.am | 12 +-
Makefile.in | 171 ++++-
NEWS | 15 +
config.h.in | 3 +
configure | 256 +++++---
configure.ac | 35 +-
doc/developer.xml | 2 +-
doc/doxygen.conf | 2 +-
doc/mpdconf.example | 2 +-
src/Compiler.h | 2 +-
src/archive/plugins/Bzip2ArchivePlugin.cxx | 2 +-
src/db/update/ExcludeList.cxx | 2 +
src/decoder/DecoderThread.cxx | 1 +
src/decoder/plugins/FfmpegDecoderPlugin.cxx | 707 +++++++++++----------
src/decoder/plugins/FfmpegIo.cxx | 100 +++
.../plugins/{FfmpegMetaData.hxx => FfmpegIo.hxx} | 34 +-
src/decoder/plugins/FfmpegMetaData.cxx | 32 +-
src/decoder/plugins/FfmpegMetaData.hxx | 4 +-
src/decoder/plugins/SidplayDecoderPlugin.cxx | 382 ++++++-----
src/fs/AllocatedPath.hxx | 2 +-
src/fs/Path.hxx | 20 +-
.../plugins/FfmpegMetaData.hxx => fs/Path2.cxx} | 24 +-
.../FfmpegMetaData.hxx => lib/ffmpeg/Buffer.hxx} | 48 +-
.../FfmpegMetaData.hxx => lib/ffmpeg/Init.cxx} | 26 +-
.../FfmpegMetaData.hxx => lib/ffmpeg/Init.hxx} | 18 +-
src/lib/ffmpeg/LogCallback.cxx | 66 ++
.../ffmpeg/LogCallback.hxx} | 18 +-
.../FfmpegMetaData.hxx => lib/ffmpeg/LogError.cxx} | 33 +-
.../FfmpegMetaData.hxx => lib/ffmpeg/LogError.hxx} | 19 +-
src/lib/ffmpeg/Time.hxx | 104 +++
src/lib/nfs/Manager.cxx | 12 +
src/lib/nfs/Manager.hxx | 4 +
src/output/plugins/ShoutOutputPlugin.cxx | 4 +-
.../FfmpegMetaData.hxx => pcm/Interleave.cxx} | 41 +-
.../FfmpegMetaData.hxx => pcm/Interleave.hxx} | 25 +-
src/util/ScopeExit.hxx | 89 +++
37 files changed, 1534 insertions(+), 785 deletions(-)
diff --git a/INSTALL b/INSTALL
index a45c4fb..97107ba 100644
--- a/INSTALL
+++ b/INSTALL
@@ -12,7 +12,7 @@ install MPD. If more information is desired, read the user manual:
Dependencies
------------
-gcc 4.6 or later - http://gcc.gnu.org/
+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.
diff --git a/Makefile.am b/Makefile.am
index 7cd68f8..744b966 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -359,6 +359,7 @@ libutil_a_SOURCES = \
src/util/Clamp.hxx \
src/util/Alloc.cxx src/util/Alloc.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 \
@@ -462,6 +463,7 @@ ICU_LDADD = libicu.a $(ICU_LIBS)
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 \
@@ -528,7 +530,7 @@ libfs_a_SOURCES = \
src/fs/Traits.cxx 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/Path.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 \
@@ -799,6 +801,11 @@ endif
if HAVE_FFMPEG
noinst_LIBRARIES += libffmpeg.a
libffmpeg_a_SOURCES = \
+ src/lib/ffmpeg/Init.cxx src/lib/ffmpeg/Init.hxx \
+ src/lib/ffmpeg/Time.hxx \
+ src/lib/ffmpeg/Buffer.hxx \
+ src/lib/ffmpeg/LogError.cxx src/lib/ffmpeg/LogError.hxx \
+ src/lib/ffmpeg/LogCallback.cxx 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
libffmpeg_a_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -980,6 +987,8 @@ endif
if HAVE_FFMPEG
libdecoder_a_SOURCES += \
+ src/decoder/plugins/FfmpegIo.cxx \
+ src/decoder/plugins/FfmpegIo.hxx \
src/decoder/plugins/FfmpegMetaData.cxx \
src/decoder/plugins/FfmpegMetaData.hxx \
src/decoder/plugins/FfmpegDecoderPlugin.cxx \
@@ -1867,6 +1876,7 @@ test_run_convert_SOURCES = test/run_convert.cxx \
src/AudioParser.cxx
test_run_convert_LDADD = \
$(PCM_LIBS) \
+ libconf.a \
libutil.a \
$(GLIB_LIBS)
diff --git a/Makefile.in b/Makefile.in
index 840ba0c..7e06e9b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -328,6 +328,8 @@ host_triplet = @host@
@ENABLE_WILDMIDI_TRUE@ src/decoder/plugins/WildmidiDecoderPlugin.hxx
@HAVE_FFMPEG_TRUE at am__append_50 = \
+ at HAVE_FFMPEG_TRUE@ src/decoder/plugins/FfmpegIo.cxx \
+ at 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 \
@@ -784,6 +786,8 @@ am__libdecoder_a_SOURCES_DIST = \
src/decoder/plugins/FluidsynthDecoderPlugin.hxx \
src/decoder/plugins/WildmidiDecoderPlugin.cxx \
src/decoder/plugins/WildmidiDecoderPlugin.hxx \
+ src/decoder/plugins/FfmpegIo.cxx \
+ src/decoder/plugins/FfmpegIo.hxx \
src/decoder/plugins/FfmpegMetaData.cxx \
src/decoder/plugins/FfmpegMetaData.hxx \
src/decoder/plugins/FfmpegDecoderPlugin.cxx \
@@ -824,7 +828,8 @@ am__libdecoder_a_SOURCES_DIST = \
@ENABLE_SIDPLAY_TRUE at am__objects_20 = src/decoder/plugins/libdecoder_a-SidplayDecoderPlugin.$(OBJEXT)
@ENABLE_FLUIDSYNTH_TRUE at am__objects_21 = src/decoder/plugins/libdecoder_a-FluidsynthDecoderPlugin.$(OBJEXT)
@ENABLE_WILDMIDI_TRUE at am__objects_22 = src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.$(OBJEXT)
- at HAVE_FFMPEG_TRUE@am__objects_23 = src/decoder/plugins/libdecoder_a-FfmpegMetaData.$(OBJEXT) \
+ at HAVE_FFMPEG_TRUE@am__objects_23 = src/decoder/plugins/libdecoder_a-FfmpegIo.$(OBJEXT) \
+ at HAVE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegMetaData.$(OBJEXT) \
@HAVE_FFMPEG_TRUE@ src/decoder/plugins/libdecoder_a-FfmpegDecoderPlugin.$(OBJEXT)
@ENABLE_SNDFILE_TRUE at am__objects_24 = src/decoder/plugins/libdecoder_a-SndfileDecoderPlugin.$(OBJEXT)
@HAVE_GME_TRUE at am__objects_25 = src/decoder/plugins/libdecoder_a-GmeDecoderPlugin.$(OBJEXT)
@@ -897,10 +902,17 @@ am_libevent_a_OBJECTS = src/event/PollGroupPoll.$(OBJEXT) \
libevent_a_OBJECTS = $(am_libevent_a_OBJECTS)
libffmpeg_a_AR = $(AR) $(ARFLAGS)
libffmpeg_a_LIBADD =
-am__libffmpeg_a_SOURCES_DIST = src/lib/ffmpeg/Error.cxx \
+am__libffmpeg_a_SOURCES_DIST = src/lib/ffmpeg/Init.cxx \
+ src/lib/ffmpeg/Init.hxx src/lib/ffmpeg/Time.hxx \
+ src/lib/ffmpeg/Buffer.hxx src/lib/ffmpeg/LogError.cxx \
+ src/lib/ffmpeg/LogError.hxx src/lib/ffmpeg/LogCallback.cxx \
+ 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 at am_libffmpeg_a_OBJECTS = \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-Init.$(OBJEXT) \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/libffmpeg_a-LogError.$(OBJEXT) \
+ at 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)
libffmpeg_a_OBJECTS = $(am_libffmpeg_a_OBJECTS)
@@ -930,7 +942,7 @@ am__libfs_a_SOURCES_DIST = src/fs/io/Reader.hxx \
src/fs/Domain.hxx src/fs/Limits.hxx src/fs/Traits.cxx \
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/Path.hxx src/fs/AllocatedPath.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 \
@@ -954,6 +966,7 @@ am_libfs_a_OBJECTS = src/fs/io/libfs_a-PeekReader.$(OBJEXT) \
src/fs/libfs_a-Traits.$(OBJEXT) \
src/fs/libfs_a-Config.$(OBJEXT) \
src/fs/libfs_a-Charset.$(OBJEXT) src/fs/libfs_a-Path.$(OBJEXT) \
+ src/fs/libfs_a-Path2.$(OBJEXT) \
src/fs/libfs_a-AllocatedPath.$(OBJEXT) \
src/fs/libfs_a-FileSystem.$(OBJEXT) \
src/fs/libfs_a-StandardDirectory.$(OBJEXT) \
@@ -1521,14 +1534,15 @@ 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 \
- src/pcm/Traits.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/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 \
@@ -1549,6 +1563,7 @@ am__libpcm_a_SOURCES_DIST = src/pcm/Domain.cxx src/pcm/Domain.hxx \
@HAVE_SOXR_TRUE at am__objects_83 = \
@HAVE_SOXR_TRUE@ src/pcm/libpcm_a-SoxrResampler.$(OBJEXT)
am_libpcm_a_OBJECTS = src/pcm/libpcm_a-Domain.$(OBJEXT) \
+ src/pcm/libpcm_a-Interleave.$(OBJEXT) \
src/pcm/libpcm_a-PcmBuffer.$(OBJEXT) \
src/pcm/libpcm_a-PcmExport.$(OBJEXT) \
src/pcm/libpcm_a-PcmConvert.$(OBJEXT) \
@@ -2008,7 +2023,7 @@ am__test_run_convert_SOURCES_DIST = test/run_convert.cxx src/Log.cxx \
@ENABLE_TEST_TRUE@ src/AudioParser.$(OBJEXT)
test_run_convert_OBJECTS = $(am_test_run_convert_OBJECTS)
@ENABLE_TEST_TRUE at test_run_convert_DEPENDENCIES = \
- at ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_17) libutil.a \
+ at ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_17) libconf.a libutil.a \
@ENABLE_TEST_TRUE@ $(am__DEPENDENCIES_1)
am__test_run_decoder_SOURCES_DIST = test/run_decoder.cxx \
test/FakeDecoderAPI.cxx test/FakeDecoderAPI.hxx \
@@ -3186,6 +3201,7 @@ libutil_a_SOURCES = \
src/util/Clamp.hxx \
src/util/Alloc.cxx src/util/Alloc.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 \
@@ -3279,14 +3295,15 @@ 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/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/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 \
@@ -3321,7 +3338,7 @@ libfs_a_SOURCES = src/fs/io/Reader.hxx src/fs/io/PeekReader.cxx \
src/fs/Domain.hxx src/fs/Limits.hxx src/fs/Traits.cxx \
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/Path.hxx src/fs/AllocatedPath.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 \
@@ -3479,6 +3496,11 @@ libtag_a_SOURCES = src/tag/TagType.h src/tag/Tag.cxx src/tag/Tag.hxx \
src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \
src/tag/ApeTag.cxx src/tag/ApeTag.hxx $(am__append_30)
@HAVE_FFMPEG_TRUE at libffmpeg_a_SOURCES = \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Init.cxx src/lib/ffmpeg/Init.hxx \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Time.hxx \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/Buffer.hxx \
+ at HAVE_FFMPEG_TRUE@ src/lib/ffmpeg/LogError.cxx src/lib/ffmpeg/LogError.hxx \
+ at 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
@@ -4057,6 +4079,7 @@ FILTER_LIBS = \
@ENABLE_TEST_TRUE at test_run_convert_LDADD = \
@ENABLE_TEST_TRUE@ $(PCM_LIBS) \
+ at ENABLE_TEST_TRUE@ libconf.a \
@ENABLE_TEST_TRUE@ libutil.a \
@ENABLE_TEST_TRUE@ $(GLIB_LIBS)
@@ -4676,6 +4699,9 @@ src/decoder/plugins/libdecoder_a-FluidsynthDecoderPlugin.$(OBJEXT): \
src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.$(OBJEXT): \
src/decoder/plugins/$(am__dirstamp) \
src/decoder/plugins/$(DEPDIR)/$(am__dirstamp)
+src/decoder/plugins/libdecoder_a-FfmpegIo.$(OBJEXT): \
+ src/decoder/plugins/$(am__dirstamp) \
+ src/decoder/plugins/$(DEPDIR)/$(am__dirstamp)
src/decoder/plugins/libdecoder_a-FfmpegMetaData.$(OBJEXT): \
src/decoder/plugins/$(am__dirstamp) \
src/decoder/plugins/$(DEPDIR)/$(am__dirstamp)
@@ -4783,6 +4809,15 @@ src/lib/ffmpeg/$(am__dirstamp):
src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/lib/ffmpeg/$(DEPDIR)
@: > src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp)
+src/lib/ffmpeg/libffmpeg_a-Init.$(OBJEXT): \
+ src/lib/ffmpeg/$(am__dirstamp) \
+ src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp)
+src/lib/ffmpeg/libffmpeg_a-LogError.$(OBJEXT): \
+ src/lib/ffmpeg/$(am__dirstamp) \
+ src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp)
+src/lib/ffmpeg/libffmpeg_a-LogCallback.$(OBJEXT): \
+ src/lib/ffmpeg/$(am__dirstamp) \
+ src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp)
src/lib/ffmpeg/libffmpeg_a-Error.$(OBJEXT): \
src/lib/ffmpeg/$(am__dirstamp) \
src/lib/ffmpeg/$(DEPDIR)/$(am__dirstamp)
@@ -4872,6 +4907,8 @@ src/fs/libfs_a-Charset.$(OBJEXT): src/fs/$(am__dirstamp) \
src/fs/$(DEPDIR)/$(am__dirstamp)
src/fs/libfs_a-Path.$(OBJEXT): src/fs/$(am__dirstamp) \
src/fs/$(DEPDIR)/$(am__dirstamp)
+src/fs/libfs_a-Path2.$(OBJEXT): src/fs/$(am__dirstamp) \
+ src/fs/$(DEPDIR)/$(am__dirstamp)
src/fs/libfs_a-AllocatedPath.$(OBJEXT): src/fs/$(am__dirstamp) \
src/fs/$(DEPDIR)/$(am__dirstamp)
src/fs/libfs_a-FileSystem.$(OBJEXT): src/fs/$(am__dirstamp) \
@@ -5678,6 +5715,8 @@ src/pcm/$(DEPDIR)/$(am__dirstamp):
@: > src/pcm/$(DEPDIR)/$(am__dirstamp)
src/pcm/libpcm_a-Domain.$(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)
src/pcm/libpcm_a-PcmBuffer.$(OBJEXT): src/pcm/$(am__dirstamp) \
src/pcm/$(DEPDIR)/$(am__dirstamp)
src/pcm/libpcm_a-PcmExport.$(OBJEXT): src/pcm/$(am__dirstamp) \
@@ -6668,6 +6707,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-DsfDecoderPlugin.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FaadDecoderPlugin.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegDecoderPlugin.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegMetaData.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FlacCommon.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/decoder/plugins/$(DEPDIR)/libdecoder_a-FlacDecoderPlugin.Po at am__quote@
@@ -6743,6 +6783,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-Domain.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-FileSystem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-Path.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-Path2.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-StandardDirectory.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/$(DEPDIR)/libfs_a-Traits.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/fs/io/$(DEPDIR)/libfs_a-AutoGunzipReader.Po at am__quote@
@@ -6783,6 +6824,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/expat/$(DEPDIR)/libplaylist_plugins_a-ExpatParser.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Domain.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Error.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Collate.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Error.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Init.Po at am__quote@
@@ -6885,6 +6929,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-FallbackResampler.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-FormatConverter.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-GlueResampler.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-Interleave.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-LibsamplerateResampler.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-PcmBuffer.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at src/pcm/$(DEPDIR)/libpcm_a-PcmChannels.Po at am__quote@
@@ -7767,6 +7812,20 @@ src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.obj: src/decoder/plugins/
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-WildmidiDecoderPlugin.obj `if test -f 'src/decoder/plugins/WildmidiDecoderPlugin.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/WildmidiDecoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/WildmidiDecoderPlugin.cxx'; fi`
+src/decoder/plugins/libdecoder_a-FfmpegIo.o: src/decoder/plugins/FfmpegIo.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-FfmpegIo.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Tpo -c -o src/decoder/plugins/libdecoder_a-FfmpegIo.o `test -f 'src/decoder/plugins/FfmpegIo.cxx' || echo '$(srcdir)/'`src/decoder/plugins/FfmpegIo.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/FfmpegIo.cxx' object='src/decoder/plugins/libdecoder_a-FfmpegIo.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-FfmpegIo.o `test -f 'src/decoder/plugins/FfmpegIo.cxx' || echo '$(srcdir)/'`src/decoder/plugins/FfmpegIo.cxx
+
+src/decoder/plugins/libdecoder_a-FfmpegIo.obj: src/decoder/plugins/FfmpegIo.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/decoder/plugins/libdecoder_a-FfmpegIo.obj -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Tpo -c -o src/decoder/plugins/libdecoder_a-FfmpegIo.obj `if test -f 'src/decoder/plugins/FfmpegIo.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/FfmpegIo.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/FfmpegIo.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegIo.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/decoder/plugins/FfmpegIo.cxx' object='src/decoder/plugins/libdecoder_a-FfmpegIo.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdecoder_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/decoder/plugins/libdecoder_a-FfmpegIo.obj `if test -f 'src/decoder/plugins/FfmpegIo.cxx'; then $(CYGPATH_W) 'src/decoder/plugins/FfmpegIo.cxx'; else $(CYGPATH_W) '$(srcdir)/src/decoder/plugins/FfmpegIo.cxx'; fi`
+
src/decoder/plugins/libdecoder_a-FfmpegMetaData.o: src/decoder/plugins/FfmpegMetaData.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-FfmpegMetaData.o -MD -MP -MF src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegMetaData.Tpo -c -o src/decoder/plugins/libdecoder_a-FfmpegMetaData.o `test -f 'src/decoder/plugins/FfmpegMetaData.cxx' || echo '$(srcdir)/'`src/decoder/plugins/FfmpegMetaData.cxx
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegMetaData.Tpo src/decoder/plugins/$(DEPDIR)/libdecoder_a-FfmpegMetaData.Po
@@ -7963,6 +8022,48 @@ src/encoder/plugins/libencoder_plugins_a-ShineEncoderPlugin.obj: src/encoder/plu
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libencoder_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/encoder/plugins/libencoder_plugins_a-ShineEncoderPlugin.obj `if test -f 'src/encoder/plugins/ShineEncoderPlugin.cxx'; then $(CYGPATH_W) 'src/encoder/plugins/ShineEncoderPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/encoder/plugins/ShineEncoderPlugin.cxx'; fi`
+src/lib/ffmpeg/libffmpeg_a-Init.o: src/lib/ffmpeg/Init.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-Init.o -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-Init.o `test -f 'src/lib/ffmpeg/Init.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/Init.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/Init.cxx' object='src/lib/ffmpeg/libffmpeg_a-Init.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-Init.o `test -f 'src/lib/ffmpeg/Init.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/Init.cxx
+
+src/lib/ffmpeg/libffmpeg_a-Init.obj: src/lib/ffmpeg/Init.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-Init.obj -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-Init.obj `if test -f 'src/lib/ffmpeg/Init.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/Init.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/Init.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/Init.cxx' object='src/lib/ffmpeg/libffmpeg_a-Init.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-Init.obj `if test -f 'src/lib/ffmpeg/Init.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/Init.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/Init.cxx'; fi`
+
+src/lib/ffmpeg/libffmpeg_a-LogError.o: src/lib/ffmpeg/LogError.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-LogError.o -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-LogError.o `test -f 'src/lib/ffmpeg/LogError.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/LogError.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/LogError.cxx' object='src/lib/ffmpeg/libffmpeg_a-LogError.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-LogError.o `test -f 'src/lib/ffmpeg/LogError.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/LogError.cxx
+
+src/lib/ffmpeg/libffmpeg_a-LogError.obj: src/lib/ffmpeg/LogError.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-LogError.obj -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-LogError.obj `if test -f 'src/lib/ffmpeg/LogError.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/LogError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/LogError.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/LogError.cxx' object='src/lib/ffmpeg/libffmpeg_a-LogError.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-LogError.obj `if test -f 'src/lib/ffmpeg/LogError.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/LogError.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/LogError.cxx'; fi`
+
+src/lib/ffmpeg/libffmpeg_a-LogCallback.o: src/lib/ffmpeg/LogCallback.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-LogCallback.o -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-LogCallback.o `test -f 'src/lib/ffmpeg/LogCallback.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/LogCallback.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/LogCallback.cxx' object='src/lib/ffmpeg/libffmpeg_a-LogCallback.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-LogCallback.o `test -f 'src/lib/ffmpeg/LogCallback.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/LogCallback.cxx
+
+src/lib/ffmpeg/libffmpeg_a-LogCallback.obj: src/lib/ffmpeg/LogCallback.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-LogCallback.obj -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-LogCallback.obj `if test -f 'src/lib/ffmpeg/LogCallback.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/LogCallback.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/LogCallback.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/lib/ffmpeg/LogCallback.cxx' object='src/lib/ffmpeg/libffmpeg_a-LogCallback.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/ffmpeg/libffmpeg_a-LogCallback.obj `if test -f 'src/lib/ffmpeg/LogCallback.cxx'; then $(CYGPATH_W) 'src/lib/ffmpeg/LogCallback.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/ffmpeg/LogCallback.cxx'; fi`
+
src/lib/ffmpeg/libffmpeg_a-Error.o: src/lib/ffmpeg/Error.cxx
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libffmpeg_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/ffmpeg/libffmpeg_a-Error.o -MD -MP -MF src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Error.Tpo -c -o src/lib/ffmpeg/libffmpeg_a-Error.o `test -f 'src/lib/ffmpeg/Error.cxx' || echo '$(srcdir)/'`src/lib/ffmpeg/Error.cxx
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Error.Tpo src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Error.Po
@@ -8145,6 +8246,20 @@ src/fs/libfs_a-Path.obj: src/fs/Path.cxx
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-Path.obj `if test -f 'src/fs/Path.cxx'; then $(CYGPATH_W) 'src/fs/Path.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/Path.cxx'; fi`
+src/fs/libfs_a-Path2.o: src/fs/Path2.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/libfs_a-Path2.o -MD -MP -MF src/fs/$(DEPDIR)/libfs_a-Path2.Tpo -c -o src/fs/libfs_a-Path2.o `test -f 'src/fs/Path2.cxx' || echo '$(srcdir)/'`src/fs/Path2.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/fs/$(DEPDIR)/libfs_a-Path2.Tpo src/fs/$(DEPDIR)/libfs_a-Path2.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fs/Path2.cxx' object='src/fs/libfs_a-Path2.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-Path2.o `test -f 'src/fs/Path2.cxx' || echo '$(srcdir)/'`src/fs/Path2.cxx
+
+src/fs/libfs_a-Path2.obj: src/fs/Path2.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/libfs_a-Path2.obj -MD -MP -MF src/fs/$(DEPDIR)/libfs_a-Path2.Tpo -c -o src/fs/libfs_a-Path2.obj `if test -f 'src/fs/Path2.cxx'; then $(CYGPATH_W) 'src/fs/Path2.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/Path2.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/fs/$(DEPDIR)/libfs_a-Path2.Tpo src/fs/$(DEPDIR)/libfs_a-Path2.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fs/Path2.cxx' object='src/fs/libfs_a-Path2.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/fs/libfs_a-Path2.obj `if test -f 'src/fs/Path2.cxx'; then $(CYGPATH_W) 'src/fs/Path2.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/Path2.cxx'; fi`
+
src/fs/libfs_a-AllocatedPath.o: src/fs/AllocatedPath.cxx
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfs_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/fs/libfs_a-AllocatedPath.o -MD -MP -MF src/fs/$(DEPDIR)/libfs_a-AllocatedPath.Tpo -c -o src/fs/libfs_a-AllocatedPath.o `test -f 'src/fs/AllocatedPath.cxx' || echo '$(srcdir)/'`src/fs/AllocatedPath.cxx
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/fs/$(DEPDIR)/libfs_a-AllocatedPath.Tpo src/fs/$(DEPDIR)/libfs_a-AllocatedPath.Po
@@ -11477,6 +11592,20 @@ src/pcm/libpcm_a-Domain.obj: src/pcm/Domain.cxx
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at 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`
+src/pcm/libpcm_a-Interleave.o: src/pcm/Interleave.cxx
+ at 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
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Interleave.Tpo src/pcm/$(DEPDIR)/libpcm_a-Interleave.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Interleave.cxx' object='src/pcm/libpcm_a-Interleave.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Interleave.o `test -f 'src/pcm/Interleave.cxx' || echo '$(srcdir)/'`src/pcm/Interleave.cxx
+
+src/pcm/libpcm_a-Interleave.obj: src/pcm/Interleave.cxx
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-Interleave.obj -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-Interleave.Tpo -c -o src/pcm/libpcm_a-Interleave.obj `if test -f 'src/pcm/Interleave.cxx'; then $(CYGPATH_W) 'src/pcm/Interleave.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Interleave.cxx'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-Interleave.Tpo src/pcm/$(DEPDIR)/libpcm_a-Interleave.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/pcm/Interleave.cxx' object='src/pcm/libpcm_a-Interleave.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/pcm/libpcm_a-Interleave.obj `if test -f 'src/pcm/Interleave.cxx'; then $(CYGPATH_W) 'src/pcm/Interleave.cxx'; else $(CYGPATH_W) '$(srcdir)/src/pcm/Interleave.cxx'; fi`
+
src/pcm/libpcm_a-PcmBuffer.o: src/pcm/PcmBuffer.cxx
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcm_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/pcm/libpcm_a-PcmBuffer.o -MD -MP -MF src/pcm/$(DEPDIR)/libpcm_a-PcmBuffer.Tpo -c -o src/pcm/libpcm_a-PcmBuffer.o `test -f 'src/pcm/PcmBuffer.cxx' || echo '$(srcdir)/'`src/pcm/PcmBuffer.cxx
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/pcm/$(DEPDIR)/libpcm_a-PcmBuffer.Tpo src/pcm/$(DEPDIR)/libpcm_a-PcmBuffer.Po
diff --git a/NEWS b/NEWS
index df7493f..f490282 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,18 @@
+ver 0.19.18 (2016/08/05)
+* decoder
+ - ffmpeg: fix crash with older FFmpeg versions (< 3.0)
+ - ffmpeg: log detailed error message
+ - ffmpeg: support FFmpeg 3.1
+ - sidplay: detect libsidplay2 with pkg-config
+ - sidplay: log detailed error message
+ - sidplay: read the "date" tag
+ - sidplay: allow building with libsidplayfp instead of libsidplay2
+* output
+ - shout: recognize setting "encoder" instead of "encoding"
+* fix memory leak after stream failure
+* fix build failure with Boost 1.61
+* require gcc 4.7 or newer
+
ver 0.19.17 (2016/07/09)
* decoder
- flac: fix assertion failure while seeking
diff --git a/config.h.in b/config.h.in
index 1acac96..155ad1c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -270,6 +270,9 @@
/* Define to enable the shoutcast output */
#undef HAVE_SHOUT
+/* Define if libsidplayfp is used instead of libsidplay2 */
+#undef HAVE_SIDPLAYFP
+
/* Define to enable libsoxr */
#undef HAVE_SOXR
diff --git a/configure b/configure
index 8389a30..1a22fb8 100755
--- a/configure
+++ b/configure
@@ -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.17.
+# Generated by GNU Autoconf 2.69 for mpd 0.19.18.
#
# Report bugs to <musicpd-dev-team at lists.sourceforge.net>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='mpd'
PACKAGE_TARNAME='mpd'
-PACKAGE_VERSION='0.19.17'
-PACKAGE_STRING='mpd 0.19.17'
+PACKAGE_VERSION='0.19.18'
+PACKAGE_STRING='mpd 0.19.18'
PACKAGE_BUGREPORT='musicpd-dev-team at lists.sourceforge.net'
PACKAGE_URL=''
@@ -712,8 +712,8 @@ WAVPACK_LIBS
WAVPACK_CFLAGS
ENABLE_SIDPLAY_FALSE
ENABLE_SIDPLAY_TRUE
-SIDPLAY_CFLAGS
SIDPLAY_LIBS
+SIDPLAY_CFLAGS
ENABLE_VORBIS_DECODER_FALSE
ENABLE_VORBIS_DECODER_TRUE
VORBIS_LIBS
@@ -1185,6 +1185,8 @@ SNDFILE_CFLAGS
SNDFILE_LIBS
VORBIS_CFLAGS
VORBIS_LIBS
+SIDPLAY_CFLAGS
+SIDPLAY_LIBS
WAVPACK_CFLAGS
WAVPACK_LIBS
SHINE_CFLAGS
@@ -1757,7 +1759,7 @@ if test "$ac_init_help" = "long"; then
# 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.17 to adapt to many kinds of systems.
+\`configure' configures mpd 0.19.18 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1828,7 +1830,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of mpd 0.19.17:";;
+ short | recursive ) echo "Configuration of mpd 0.19.18:";;
esac
cat <<\_ACEOF
@@ -2069,6 +2071,10 @@ Some influential environment variables:
VORBIS_CFLAGS
C compiler flags for VORBIS, overriding pkg-config
VORBIS_LIBS linker flags for VORBIS, overriding pkg-config
+ SIDPLAY_CFLAGS
+ C compiler flags for SIDPLAY, overriding pkg-config
+ SIDPLAY_LIBS
+ linker flags for SIDPLAY, overriding pkg-config
WAVPACK_CFLAGS
C compiler flags for WAVPACK, overriding pkg-config
WAVPACK_LIBS
@@ -2169,7 +2175,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-mpd configure 0.19.17
+mpd configure 0.19.18
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2622,7 +2628,7 @@ 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.17, which was
+It was created by mpd $as_me 0.19.18, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2973,7 +2979,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
VERSION_MAJOR=0
VERSION_MINOR=19
-VERSION_REVISION=17
+VERSION_REVISION=18
VERSION_EXTRA=0
@@ -3492,7 +3498,7 @@ fi
# Define the identity of the package.
PACKAGE='mpd'
- VERSION='0.19.17'
+ VERSION='0.19.18'
cat >>confdefs.h <<_ACEOF
@@ -8158,15 +8164,6 @@ else
fi
- if test x$enable_glib = xno; then
- if test x$enable_sidplay = xauto; then
- enable_sidplay=no
- elif test x$enable_sidplay = xyes; then
- as_fn_error $? "Cannot use --enable-sidplay with --disable-glib" "$LINENO" 5
- fi
- fi
-
-
# Check whether --enable-shine-encoder was given.
if test "${enable_shine_encoder+set}" = set; then :
enableval=$enable_shine_encoder;
@@ -14460,44 +14457,152 @@ fi
if test x$enable_sidplay != xno; then
- # we're not using pkg-config here
- # because libsidplay2's .pc file requires libtool
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsidplay2" >&5
-$as_echo_n "checking for main in -lsidplay2... " >&6; }
-if ${ac_cv_lib_sidplay2_main+:} false; then :
- $as_echo_n "(cached) " >&6
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIDPLAY" >&5
+$as_echo_n "checking for SIDPLAY... " >&6; }
+
+if test -n "$SIDPLAY_CFLAGS"; then
+ 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
+ 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`
+ test "x$?" != "x0" && pkg_failed=yes
else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsidplay2 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$SIDPLAY_LIBS"; then
+ 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
+ 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`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sidplay2_main=yes
+
+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
- ac_cv_lib_sidplay2_main=no
+ _pkg_short_errors_supported=no
fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+ if test $_pkg_short_errors_supported = yes; then
+ SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsidplayfp libsidutils" 2>&1`
+ else
+ SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsidplayfp libsidutils" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$SIDPLAY_PKG_ERRORS" >&5
+
+ found_sidplayfp=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ found_sidplayfp=no
+else
+ SIDPLAY_CFLAGS=$pkg_cv_SIDPLAY_CFLAGS
+ SIDPLAY_LIBS=$pkg_cv_SIDPLAY_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ found_sidplayfp=yes
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sidplay2_main" >&5
-$as_echo "$ac_cv_lib_sidplay2_main" >&6; }
-if test "x$ac_cv_lib_sidplay2_main" = xyes; then :
- found_sidplay=yes
+ found_sidplay=$found_sidplayfp
+fi
+
+if test x$enable_sidplay != xno && test x$found_sidplayfp = xno; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIDPLAY" >&5
+$as_echo_n "checking for SIDPLAY... " >&6; }
+
+if test -n "$SIDPLAY_CFLAGS"; then
+ 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 \"libsidplay2 libsidutils\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsidplay2 libsidutils") 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 "libsidplay2 libsidutils" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
- found_sidplay=no
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$SIDPLAY_LIBS"; then
+ 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 \"libsidplay2 libsidutils\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsidplay2 libsidutils") 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 "libsidplay2 libsidutils" 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
+ SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsidplay2 libsidutils" 2>&1`
+ else
+ SIDPLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsidplay2 libsidutils" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$SIDPLAY_PKG_ERRORS" >&5
+
+ found_sidplay=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ found_sidplay=no
+else
+ SIDPLAY_CFLAGS=$pkg_cv_SIDPLAY_CFLAGS
+ SIDPLAY_LIBS=$pkg_cv_SIDPLAY_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ found_sidplay=yes
+fi
name="sidplay"
@@ -14524,7 +14629,7 @@ $as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
fi
-if test x$enable_sidplay != xno; then
+if test x$enable_sidplay != xno && test x$found_sidplayfp = xno; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lresid-builder" >&5
$as_echo_n "checking for main in -lresid-builder... " >&6; }
if ${ac_cv_lib_resid_builder_main+:} false; then :
@@ -14562,51 +14667,12 @@ else
fi
- if test x$found_sidplay = xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsidutils" >&5
-$as_echo_n "checking for main in -lsidutils... " >&6; }
-if ${ac_cv_lib_sidutils_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsidutils $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sidutils_main=yes
-else
- ac_cv_lib_sidutils_main=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_sidutils_main" >&5
-$as_echo "$ac_cv_lib_sidutils_main" >&6; }
-if test "x$ac_cv_lib_sidutils_main" = xyes; then :
- :
-else
- found_sidplay=no
-fi
-
- fi
-
name="sidplay"
var="enable_sidplay"
found="found_$name"
feature="sidplay decoder plugin"
- msg="libresid-builder or libsidutils not found"
+ msg="libresid-builder not found"
if eval "test x`echo '$'$var` = xno"; then
eval "$found=no"
@@ -14642,13 +14708,15 @@ $as_echo "$as_me: WARNING: $msg -- disabling $feature" >&2;}
fi
if test x$enable_sidplay = xyes; then
- SIDPLAY_LIBS="-lsidplay2 -lresid-builder -lsidutils"
-
+ SIDPLAY_LIBS="$SIDPLAY_LIBS -lresid-builder"
+$as_echo "#define ENABLE_SIDPLAY 1" >>confdefs.h
+ if test x$found_sidplayfp = xyes; then
-$as_echo "#define ENABLE_SIDPLAY 1" >>confdefs.h
+$as_echo "#define HAVE_SIDPLAYFP 1" >>confdefs.h
+ fi
fi
if test x$enable_sidplay = xyes; then
@@ -20895,7 +20963,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# 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.17, which was
+This file was extended by mpd $as_me 0.19.18, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20961,7 +21029,7 @@ _ACEOF
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.17
+mpd config.status 0.19.18
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index b5d59c2..1a3a20c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
AC_PREREQ(2.60)
-AC_INIT(mpd, 0.19.17, musicpd-dev-team at lists.sourceforge.net)
+AC_INIT(mpd, 0.19.18, musicpd-dev-team at lists.sourceforge.net)
VERSION_MAJOR=0
VERSION_MINOR=19
-VERSION_REVISION=17
+VERSION_REVISION=18
VERSION_EXTRA=0
AC_CONFIG_SRCDIR([src/Main.cxx])
@@ -542,8 +542,6 @@ AC_ARG_ENABLE(sidplay,
AS_HELP_STRING([--enable-sidplay],
[enable C64 SID support via libsidplay2]),,
enable_sidplay=auto)
-MPD_DEPENDS([enable_sidplay], [enable_glib],
- [Cannot use --enable-sidplay with --disable-glib])
AC_ARG_ENABLE(shine-encoder,
AS_HELP_STRING([--enable-shine-encoder],
@@ -1335,31 +1333,36 @@ AM_CONDITIONAL(ENABLE_VORBIS_DECODER, test x$enable_vorbis = xyes || test x$enab
dnl --------------------------------- sidplay ---------------------------------
if test x$enable_sidplay != xno; then
- # we're not using pkg-config here
- # because libsidplay2's .pc file requires libtool
- AC_CHECK_LIB([sidplay2],[main],[found_sidplay=yes],[found_sidplay=no],[])
+ dnl Check for libsidplayfp first
+ PKG_CHECK_MODULES([SIDPLAY], [libsidplayfp libsidutils],
+ [found_sidplayfp=yes],
+ [found_sidplayfp=no])
+ found_sidplay=$found_sidplayfp
+fi
+
+if test x$enable_sidplay != xno && test x$found_sidplayfp = xno; then
+ PKG_CHECK_MODULES([SIDPLAY], [libsidplay2 libsidutils],
+ [found_sidplay=yes],
+ [found_sidplay=no])
MPD_AUTO_PRE(sidplay, [sidplay decoder plugin],
[libsidplay2 not found])
fi
-if test x$enable_sidplay != xno; then
+if test x$enable_sidplay != xno && test x$found_sidplayfp = xno; then
AC_CHECK_LIB([resid-builder], [main],
[found_sidplay=yes], [found_sidplay=no])
- if test x$found_sidplay = xyes; then
- AC_CHECK_LIB([sidutils],[main],[:],[found_sidplay=no],[])
- fi
-
MPD_AUTO_RESULT(sidplay, [sidplay decoder plugin],
- [libresid-builder or libsidutils not found])
+ [libresid-builder not found])
fi
if test x$enable_sidplay = xyes; then
- AC_SUBST(SIDPLAY_LIBS,"-lsidplay2 -lresid-builder -lsidutils")
- AC_SUBST(SIDPLAY_CFLAGS,)
-
+ SIDPLAY_LIBS="$SIDPLAY_LIBS -lresid-builder"
AC_DEFINE(ENABLE_SIDPLAY, 1, [Define for libsidplay2 support])
+ if test x$found_sidplayfp = xyes; then
+ AC_DEFINE(HAVE_SIDPLAYFP, 1, [Define if libsidplayfp is used instead of libsidplay2])
+ fi
fi
AM_CONDITIONAL(ENABLE_SIDPLAY, test x$enable_sidplay = xyes)
diff --git a/doc/developer.xml b/doc/developer.xml
index 074c7f3..f07c520 100644
--- a/doc/developer.xml
+++ b/doc/developer.xml
@@ -41,7 +41,7 @@
<listitem>
<para>
the code should be C++11 compliant, and must compile with
- <application>GCC</application> 4.6 and
+ <application>GCC</application> 4.7 and
<application>clang</application> 3.2
</para>
</listitem>
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index ac2bdae..fb9131a 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -31,7 +31,7 @@ PROJECT_NAME = MPD
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 0.19.17
+PROJECT_NUMBER = 0.19.18
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
diff --git a/doc/mpdconf.example b/doc/mpdconf.example
index 6ba0351..21d4b41 100644
--- a/doc/mpdconf.example
+++ b/doc/mpdconf.example
@@ -231,7 +231,7 @@ input {
#
#audio_output {
# type "shout"
-# encoding "ogg" # optional
+# encoder "vorbis" # optional
# name "My Shout Stream"
# host "localhost"
# port "8000"
diff --git a/src/Compiler.h b/src/Compiler.h
index fea9715..5a28c3d 100644
--- a/src/Compiler.h
+++ b/src/Compiler.h
@@ -45,7 +45,7 @@
# error Sorry, your clang version is too old. You need at least version 3.1.
# endif
#elif defined(__GNUC__)
-# if GCC_OLDER_THAN(4,6)
+# if GCC_OLDER_THAN(4,7)
# error Sorry, your gcc version is too old. You need at least version 4.6.
# endif
#else
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx
index 2b92049..8548cb1 100644
--- a/src/archive/plugins/Bzip2ArchivePlugin.cxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx
@@ -53,7 +53,7 @@ public:
Bzip2ArchiveFile(Path path, InputStream *_is)
:ArchiveFile(bz2_archive_plugin),
- name(PathTraitsFS::GetBase(path.c_str())),
+ name(path.GetBase().c_str()),
istream(_is) {
// remove .bz2 suffix
const size_t len = name.length();
diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx
index cf92ac8..029bed9 100644
--- a/src/db/update/ExcludeList.cxx
+++ b/src/db/update/ExcludeList.cxx
@@ -34,7 +34,9 @@
#include <string.h>
#include <errno.h>
+#ifdef HAVE_GLIB
static constexpr Domain exclude_list_domain("exclude_list");
+#endif
bool
ExcludeList::LoadFile(Path path_fs)
diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx
index d5f73c3..2e407e6 100644
--- a/src/decoder/DecoderThread.cxx
+++ b/src/decoder/DecoderThread.cxx
@@ -98,6 +98,7 @@ decoder_input_stream_open(DecoderControl &dc, const char *uri)
if (!is->Check(error)) {
dc.Unlock();
+ delete is;
LogError(error);
return nullptr;
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index 6404450..7695dcb 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -20,16 +20,24 @@
/* necessary because libavutil/common.h uses UINT64_C */
#define __STDC_CONSTANT_MACROS
+#include "lib/ffmpeg/Time.hxx"
#include "config.h"
#include "FfmpegDecoderPlugin.hxx"
#include "lib/ffmpeg/Domain.hxx"
+#include "lib/ffmpeg/Error.hxx"
+#include "lib/ffmpeg/LogError.hxx"
+#include "lib/ffmpeg/Init.hxx"
+#include "lib/ffmpeg/Buffer.hxx"
#include "../DecoderAPI.hxx"
#include "FfmpegMetaData.hxx"
+#include "FfmpegIo.hxx"
+#include "pcm/Interleave.hxx"
#include "tag/TagHandler.hxx"
#include "input/InputStream.hxx"
#include "CheckAudioFormat.hxx"
+#include "util/ScopeExit.hxx"
+#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
-#include "util/Domain.hxx"
#include "LogV.hxx"
extern "C" {
@@ -38,7 +46,6 @@ extern "C" {
#include <libavformat/avio.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
-#include <libavutil/mathematics.h>
#if LIBAVUTIL_VERSION_MAJOR >= 53
#include <libavutil/frame.h>
@@ -48,270 +55,144 @@ extern "C" {
#include <assert.h>
#include <string.h>
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-static LogLevel
-import_ffmpeg_level(int level)
+static AVFormatContext *
+FfmpegOpenInput(AVIOContext *pb,
+ const char *filename,
+ AVInputFormat *fmt,
+ Error &error)
{
- if (level <= AV_LOG_FATAL)
- return LogLevel::ERROR;
+ AVFormatContext *context = avformat_alloc_context();
+ if (context == nullptr) {
+ error.Set(ffmpeg_domain, "Out of memory");
+ return nullptr;
+ }
- if (level <= AV_LOG_WARNING)
- return LogLevel::WARNING;
+ context->pb = pb;
- if (level <= AV_LOG_INFO)
- return LogLevel::INFO;
+ int err = avformat_open_input(&context, filename, fmt, nullptr);
+ if (err < 0) {
+ avformat_free_context(context);
+ SetFfmpegError(error, err, "avformat_open_input() failed");
+ return nullptr;
+ }
- return LogLevel::DEBUG;
+ return context;
}
-static void
-mpd_ffmpeg_log_callback(gcc_unused void *ptr, int level,
- const char *fmt, va_list vl)
+static bool
+ffmpeg_init(gcc_unused const config_param ¶m)
{
- const AVClass * cls = nullptr;
-
- if (ptr != nullptr)
- cls = *(const AVClass *const*)ptr;
-
- if (cls != nullptr) {
- char domain[64];
- snprintf(domain, sizeof(domain), "%s/%s",
- ffmpeg_domain.GetName(), cls->item_name(ptr));
- const Domain d(domain);
- LogFormatV(d, import_ffmpeg_level(level), fmt, vl);
- }
+ FfmpegInit();
+ return true;
}
-struct AvioStream {
- Decoder *const decoder;
- InputStream &input;
-
- AVIOContext *io;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 25, 0) /* FFmpeg 3.1 */
- AvioStream(Decoder *_decoder, InputStream &_input)
- :decoder(_decoder), input(_input), io(nullptr) {}
-
- ~AvioStream() {
- if (io != nullptr) {
- av_free(io->buffer);
- av_free(io);
- }
- }
-
- bool Open();
-};
-
-static int
-mpd_ffmpeg_stream_read(void *opaque, uint8_t *buf, int size)
+gcc_pure
+static const AVCodecParameters &
+GetCodecParameters(const AVStream &stream)
{
- AvioStream *stream = (AvioStream *)opaque;
-
- return decoder_read(stream->decoder, stream->input,
- (void *)buf, size);
+ return *stream.codecpar;
}
-static int64_t
-mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
+gcc_pure
+static AVSampleFormat
+GetSampleFormat(const AVCodecParameters &codec_params)
{
- AvioStream *stream = (AvioStream *)opaque;
-
- switch (whence) {
- case SEEK_SET:
- break;
-
- case SEEK_CUR:
- pos += stream->input.GetOffset();
- break;
-
- case SEEK_END:
- if (!stream->input.KnownSize())
- return -1;
-
- pos += stream->input.GetSize();
- break;
-
- case AVSEEK_SIZE:
- if (!stream->input.KnownSize())
- return -1;
-
- return stream->input.GetSize();
-
- default:
- return -1;
- }
-
- if (!stream->input.LockSeek(pos, IgnoreError()))
- return -1;
-
- return stream->input.GetOffset();
+ return AVSampleFormat(codec_params.format);
}
-bool
-AvioStream::Open()
-{
- constexpr size_t BUFFER_SIZE = 8192;
- auto buffer = (unsigned char *)av_malloc(BUFFER_SIZE);
- if (buffer == nullptr)
- return false;
+#else
- io = avio_alloc_context(buffer, BUFFER_SIZE,
- false, this,
- mpd_ffmpeg_stream_read, nullptr,
- input.IsSeekable()
- ? mpd_ffmpeg_stream_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,
- however no AVIOContext exists in that failure code path. */
- return io != nullptr;
+gcc_pure
+static const AVCodecContext &
+GetCodecParameters(const AVStream &stream)
+{
+ return *stream.codec;
}
-/**
- * API compatibility wrapper for av_open_input_stream() and
- * avformat_open_input().
- */
-static int
-mpd_ffmpeg_open_input(AVFormatContext **ic_ptr,
- AVIOContext *pb,
- const char *filename,
- AVInputFormat *fmt)
+gcc_pure
+static AVSampleFormat
+GetSampleFormat(const AVCodecContext &codec_context)
{
- AVFormatContext *context = avformat_alloc_context();
- if (context == nullptr)
- return AVERROR(ENOMEM);
-
- context->pb = pb;
- *ic_ptr = context;
- return avformat_open_input(ic_ptr, filename, fmt, nullptr);
+ return codec_context.sample_fmt;
}
+#endif
+
+gcc_pure
static bool
-ffmpeg_init(gcc_unused const config_param ¶m)
+IsAudio(const AVStream &stream)
{
- av_log_set_callback(mpd_ffmpeg_log_callback);
-
- av_register_all();
- return true;
+ return GetCodecParameters(stream).codec_type == AVMEDIA_TYPE_AUDIO;
}
+gcc_pure
static int
ffmpeg_find_audio_stream(const AVFormatContext &format_context)
{
for (unsigned i = 0; i < format_context.nb_streams; ++i)
- if (format_context.streams[i]->codec->codec_type ==
- AVMEDIA_TYPE_AUDIO)
+ if (IsAudio(*format_context.streams[i]))
return i;
return -1;
}
-gcc_const
-static double
-time_from_ffmpeg(int64_t t, const AVRational time_base)
-{
- assert(t != (int64_t)AV_NOPTS_VALUE);
-
- return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
- / (double)1024;
-}
-
-template<typename Ratio>
-static constexpr AVRational
-RatioToAVRational()
-{
- return { Ratio::num, Ratio::den };
-}
-
-gcc_const
-static int64_t
-time_to_ffmpeg(SongTime t, const AVRational time_base)
-{
- return av_rescale_q(t.count(),
- RatioToAVRational<SongTime::period>(),
- time_base);
-}
-
-/**
- * Replace #AV_NOPTS_VALUE with the given fallback.
- */
-static constexpr int64_t
-timestamp_fallback(int64_t t, int64_t fallback)
-{
- return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
- ? t
- : fallback;
-}
-
/**
* Accessor for AVStream::start_time that replaces AV_NOPTS_VALUE with
* zero. We can't use AV_NOPTS_VALUE in calculations, and we simply
* assume that the stream's start time is zero, which appears to be
* the best way out of that situation.
*/
-static int64_t
+static constexpr int64_t
start_time_fallback(const AVStream &stream)
{
- return timestamp_fallback(stream.start_time, 0);
-}
-
-static void
-copy_interleave_frame2(uint8_t *dest, uint8_t **src,
- unsigned nframes, unsigned nchannels,
- unsigned sample_size)
-{
- for (unsigned frame = 0; frame < nframes; ++frame) {
- for (unsigned channel = 0; channel < nchannels; ++channel) {
- memcpy(dest, src[channel] + frame * sample_size,
- sample_size);
- dest += sample_size;
- }
- }
+ return FfmpegTimestampFallback(stream.start_time, 0);
}
/**
- * Copy PCM data from a AVFrame to an interleaved buffer.
+ * Copy PCM data from a non-empty AVFrame to an interleaved buffer.
*/
-static int
+static ConstBuffer<void>
copy_interleave_frame(const AVCodecContext &codec_context,
const AVFrame &frame,
- uint8_t **output_buffer,
- uint8_t **global_buffer, int *global_buffer_size)
+ FfmpegBuffer &global_buffer,
+ Error &error)
{
+ assert(frame.nb_samples > 0);
+
int plane_size;
const int data_size =
av_samples_get_buffer_size(&plane_size,
codec_context.channels,
frame.nb_samples,
codec_context.sample_fmt, 1);
- if (data_size <= 0)
- return data_size;
+ assert(data_size != 0);
+ if (data_size < 0) {
+ SetFfmpegError(error, data_size);
+ return 0;
+ }
+ void *output_buffer;
if (av_sample_fmt_is_planar(codec_context.sample_fmt) &&
codec_context.channels > 1) {
- if(*global_buffer_size < data_size) {
- av_freep(global_buffer);
-
- *global_buffer = (uint8_t*)av_malloc(data_size);
-
- if (!*global_buffer)
- /* Not enough memory - shouldn't happen */
- return AVERROR(ENOMEM);
- *global_buffer_size = data_size;
+ output_buffer = global_buffer.GetT<uint8_t>(data_size);
+ if (output_buffer == nullptr) {
+ /* Not enough memory - shouldn't happen */
+ error.SetErrno(ENOMEM);
+ return 0;
}
- *output_buffer = *global_buffer;
- copy_interleave_frame2(*output_buffer, frame.extended_data,
- frame.nb_samples,
- codec_context.channels,
- av_get_bytes_per_sample(codec_context.sample_fmt));
+
+ PcmInterleave(output_buffer,
+ ConstBuffer<const void *>((const void *const*)frame.extended_data,
+ codec_context.channels),
+ frame.nb_samples,
+ av_get_bytes_per_sample(codec_context.sample_fmt));
} else {
- *output_buffer = frame.extended_data[0];
+ output_buffer = frame.extended_data[0];
}
- return data_size;
+ return { output_buffer, (size_t)data_size };
}
/**
@@ -343,6 +224,94 @@ PtsToPcmFrame(uint64_t pts, const AVStream &stream,
}
/**
+ * Invoke decoder_data() with the contents of an #AVFrame.
+ */
+static DecoderCommand
+FfmpegSendFrame(Decoder &decoder, 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()) {
+ /* this must be a serious error, e.g. OOM */
+ LogError(error);
+ return DecoderCommand::STOP;
+ }
+
+ if (skip_bytes > 0) {
+ if (skip_bytes >= output_buffer.size) {
+ skip_bytes -= output_buffer.size;
+ return DecoderCommand::NONE;
+ }
+
+ output_buffer.data =
+ (const uint8_t *)output_buffer.data + skip_bytes;
+ output_buffer.size -= skip_bytes;
+ skip_bytes = 0;
+ }
+
+ return decoder_data(decoder, 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,
+ AVCodecContext &codec_context,
+ AVFrame &frame,
+ size_t &skip_bytes,
+ FfmpegBuffer &buffer,
+ bool &eof)
+{
+ while (true) {
+ DecoderCommand cmd;
+
+ int err = avcodec_receive_frame(&codec_context, &frame);
+ switch (err) {
+ case 0:
+ cmd = FfmpegSendFrame(decoder, is, codec_context,
+ frame, skip_bytes,
+ buffer);
+ if (cmd != DecoderCommand::NONE)
+ return cmd;
+
+ break;
+
+ case AVERROR_EOF:
+ eof = true;
+ return DecoderCommand::NONE;
+
+ case AVERROR(EAGAIN):
+ /* need to call avcodec_send_packet() */
+ return DecoderCommand::NONE;
+
+ default:
+ {
+ char msg[256];
+ av_strerror(err, msg, sizeof(msg));
+ FormatWarning(ffmpeg_domain,
+ "avcodec_send_packet() failed: %s",
+ msg);
+ }
+
+ return DecoderCommand::STOP;
+ }
+ }
+}
+
+#endif
+
+/**
+ * Decode an #AVPacket and send the resulting PCM data to the decoder
+ * API.
+ *
* @param min_frame skip all data before this PCM frame number; this
* is used after seeking to skip data in an AVPacket until the exact
* desired time stamp has been reached
@@ -352,9 +321,9 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
AVPacket &&packet,
AVCodecContext &codec_context,
const AVStream &stream,
- AVFrame *frame,
+ AVFrame &frame,
uint64_t min_frame, size_t pcm_frame_size,
- uint8_t **buffer, int *buffer_size)
+ FfmpegBuffer &buffer)
{
size_t skip_bytes = 0;
@@ -367,59 +336,85 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
skip_bytes = pcm_frame_size * (min_frame - cur_frame);
} else
decoder_timestamp(decoder,
- time_from_ffmpeg(pts, stream.time_base));
+ FfmpegTimeToDouble(pts,
+ stream.time_base));
}
- uint8_t *output_buffer;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0)
+ bool eof = false;
+ int err = avcodec_send_packet(&codec_context, &packet);
+ switch (err) {
+ case 0:
+ break;
+
+ case AVERROR_EOF:
+ eof = true;
+ break;
+
+ default:
+ {
+ char msg[256];
+ av_strerror(err, msg, sizeof(msg));
+ FormatWarning(ffmpeg_domain,
+ "avcodec_send_packet() failed: %s", msg);
+ }
+
+ return DecoderCommand::NONE;
+ }
+
+ auto cmd = FfmpegReceiveFrames(decoder, is, codec_context,
+ frame,
+ skip_bytes, buffer, eof);
+
+ if (eof)
+ cmd = DecoderCommand::STOP;
+#else
DecoderCommand cmd = DecoderCommand::NONE;
while (packet.size > 0 && cmd == DecoderCommand::NONE) {
- int audio_size = 0;
int got_frame = 0;
int len = avcodec_decode_audio4(&codec_context,
- frame, &got_frame,
+ &frame, &got_frame,
&packet);
- if (len >= 0 && got_frame) {
- audio_size = copy_interleave_frame(codec_context,
- *frame,
- &output_buffer,
- buffer, buffer_size);
- if (audio_size < 0)
- len = audio_size;
- }
-
if (len < 0) {
/* if error, we skip the frame */
- LogDefault(ffmpeg_domain,
- "decoding failed, frame skipped");
+ LogFfmpegError(len, "decoding failed, frame skipped");
break;
}
packet.data += len;
packet.size -= len;
- if (audio_size <= 0)
+ if (!got_frame || frame.nb_samples <= 0)
continue;
- const uint8_t *data = output_buffer;
- if (skip_bytes > 0) {
- if (skip_bytes >= size_t(audio_size)) {
- skip_bytes -= audio_size;
- continue;
- }
-
- data += skip_bytes;
- audio_size -= skip_bytes;
- skip_bytes = 0;
- }
-
- cmd = decoder_data(decoder, is,
- data, audio_size,
- codec_context.bit_rate / 1000);
+ cmd = FfmpegSendFrame(decoder, is, codec_context,
+ frame, skip_bytes,
+ buffer);
}
+#endif
+
return cmd;
}
+static DecoderCommand
+ffmpeg_send_packet(Decoder &decoder, InputStream &is,
+ const AVPacket &packet,
+ AVCodecContext &codec_context,
+ const AVStream &stream,
+ AVFrame &frame,
+ uint64_t min_frame, size_t pcm_frame_size,
+ FfmpegBuffer &buffer)
+{
+ return ffmpeg_send_packet(decoder, is,
+ /* copy the AVPacket, because FFmpeg
+ < 3.0 requires this */
+ AVPacket(packet),
+ codec_context, stream,
+ frame, min_frame, pcm_frame_size,
+ buffer);
+}
+
gcc_const
static SampleFormat
ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
@@ -458,10 +453,8 @@ ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
static AVInputFormat *
ffmpeg_probe(Decoder *decoder, InputStream &is)
{
- enum {
- BUFFER_SIZE = 16384,
- PADDING = 16,
- };
+ 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);
@@ -501,52 +494,33 @@ ffmpeg_probe(Decoder *decoder, InputStream &is)
}
static void
-ffmpeg_decode(Decoder &decoder, InputStream &input)
+FfmpegDecode(Decoder &decoder, InputStream &input,
+ AVFormatContext &format_context)
{
- AVInputFormat *input_format = ffmpeg_probe(&decoder, 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);
- if (!stream.Open()) {
- LogError(ffmpeg_domain, "Failed to open stream");
- return;
- }
-
- //ffmpeg works with ours "fileops" helper
- AVFormatContext *format_context = nullptr;
- if (mpd_ffmpeg_open_input(&format_context, stream.io,
- input.GetURI(),
- input_format) != 0) {
- LogError(ffmpeg_domain, "Open failed");
- return;
- }
-
const int find_result =
- avformat_find_stream_info(format_context, nullptr);
+ avformat_find_stream_info(&format_context, nullptr);
if (find_result < 0) {
LogError(ffmpeg_domain, "Couldn't find stream info");
- avformat_close_input(&format_context);
return;
}
- int audio_stream = ffmpeg_find_audio_stream(*format_context);
+ int audio_stream = ffmpeg_find_audio_stream(format_context);
if (audio_stream == -1) {
LogError(ffmpeg_domain, "No audio stream inside");
- avformat_close_input(&format_context);
return;
}
- AVStream *av_stream = format_context->streams[audio_stream];
+ AVStream &av_stream = *format_context.streams[audio_stream];
- AVCodecContext *codec_context = av_stream->codec;
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 5, 0)
+ AVCodecContext *codec_context = av_stream.codec;
+#endif
+
+ const auto &codec_params = GetCodecParameters(av_stream);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0)
const AVCodecDescriptor *codec_descriptor =
- avcodec_descriptor_get(codec_context->codec_id);
+ avcodec_descriptor_get(codec_params.codec_id);
if (codec_descriptor != nullptr)
FormatDebug(ffmpeg_domain, "codec '%s'",
codec_descriptor->name);
@@ -556,30 +530,39 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
codec_context->codec_name);
#endif
- AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);
+ AVCodec *codec = avcodec_find_decoder(codec_params.codec_id);
if (!codec) {
LogError(ffmpeg_domain, "Unsupported audio codec");
- avformat_close_input(&format_context);
return;
}
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 5, 0)
+ AVCodecContext *codec_context = avcodec_alloc_context3(codec);
+ if (codec_context == nullptr) {
+ LogError(ffmpeg_domain, "avcodec_alloc_context3() failed");
+ return;
+ }
+
+ AtScopeExit(&codec_context) {
+ avcodec_free_context(&codec_context);
+ };
+#endif
+
const SampleFormat sample_format =
- ffmpeg_sample_format(codec_context->sample_fmt);
+ ffmpeg_sample_format(GetSampleFormat(codec_params));
if (sample_format == SampleFormat::UNDEFINED) {
// (error message already done by ffmpeg_sample_format())
- avformat_close_input(&format_context);
return;
}
Error error;
AudioFormat audio_format;
if (!audio_format_init_checked(audio_format,
- codec_context->sample_rate,
+ codec_params.sample_rate,
sample_format,
- codec_context->channels, error)) {
+ codec_params.channels, error)) {
LogError(error);
- avformat_close_input(&format_context);
return;
}
@@ -591,15 +574,17 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
const int open_result = avcodec_open2(codec_context, codec, nullptr);
if (open_result < 0) {
LogError(ffmpeg_domain, "Could not open codec");
- avformat_close_input(&format_context);
return;
}
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 5, 0)
+ AtScopeExit(codec_context) {
+ avcodec_close(codec_context);
+ };
+#endif
+
const SignedSongTime total_time =
- format_context->duration != (int64_t)AV_NOPTS_VALUE
- ? SignedSongTime::FromScale<uint64_t>(format_context->duration,
- AV_TIME_BASE)
- : SignedSongTime::Negative();
+ FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
decoder_initialized(decoder, audio_format,
input.IsSeekable(), total_time);
@@ -611,30 +596,57 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
#endif
if (!frame) {
LogError(ffmpeg_domain, "Could not allocate frame");
- avformat_close_input(&format_context);
return;
}
- uint8_t *interleaved_buffer = nullptr;
- int interleaved_buffer_size = 0;
+ AtScopeExit(&frame) {
+#if LIBAVUTIL_VERSION_MAJOR >= 53
+ av_frame_free(&frame);
+#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
+ avcodec_free_frame(&frame);
+#else
+ av_free(frame);
+#endif
+ };
+
+ FfmpegBuffer interleaved_buffer;
uint64_t min_frame = 0;
- DecoderCommand cmd;
- do {
+ DecoderCommand cmd = decoder_get_command(decoder);
+ while (cmd != DecoderCommand::STOP) {
+ if (cmd == DecoderCommand::SEEK) {
+ int64_t where =
+ ToFfmpegTime(decoder_seek_time(decoder),
+ av_stream.time_base) +
+ start_time_fallback(av_stream);
+
+ /* AVSEEK_FLAG_BACKWARD asks FFmpeg to seek to
+ the packet boundary before the seek time
+ stamp, not after */
+ if (av_seek_frame(&format_context, audio_stream, where,
+ AVSEEK_FLAG_ANY|AVSEEK_FLAG_BACKWARD) < 0)
+ decoder_seek_error(decoder);
+ else {
+ avcodec_flush_buffers(codec_context);
+ min_frame = decoder_seek_where_frame(decoder);
+ decoder_command_finished(decoder);
+ }
+ }
+
AVPacket packet;
- if (av_read_frame(format_context, &packet) < 0)
+ if (av_read_frame(&format_context, &packet) < 0)
/* end of file */
break;
if (packet.stream_index == audio_stream) {
cmd = ffmpeg_send_packet(decoder, input,
- std::move(packet),
+ packet,
*codec_context,
- *av_stream,
- frame,
+ av_stream,
+ *frame,
min_frame, audio_format.GetFrameSize(),
- &interleaved_buffer, &interleaved_buffer_size);
+ interleaved_buffer);
min_frame = 0;
} else
cmd = decoder_get_command(decoder);
@@ -644,42 +656,65 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
#else
av_free_packet(&packet);
#endif
+ }
+}
- if (cmd == DecoderCommand::SEEK) {
- int64_t where =
- time_to_ffmpeg(decoder_seek_time(decoder),
- av_stream->time_base) +
- start_time_fallback(*av_stream);
+static void
+ffmpeg_decode(Decoder &decoder, InputStream &input)
+{
+ AVInputFormat *input_format = ffmpeg_probe(&decoder, input);
+ if (input_format == nullptr)
+ return;
- /* AVSEEK_FLAG_BACKWARD asks FFmpeg to seek to
- the packet boundary before the seek time
- stamp, not after */
+ FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)",
+ input_format->name, input_format->long_name);
- if (av_seek_frame(format_context, audio_stream, where,
- AVSEEK_FLAG_ANY|AVSEEK_FLAG_BACKWARD) < 0)
- decoder_seek_error(decoder);
- else {
- avcodec_flush_buffers(codec_context);
- min_frame = decoder_seek_where_frame(decoder);
- decoder_command_finished(decoder);
- }
- }
- } while (cmd != DecoderCommand::STOP);
+ AvioStream stream(&decoder, input);
+ if (!stream.Open()) {
+ LogError(ffmpeg_domain, "Failed to open stream");
+ return;
+ }
-#if LIBAVUTIL_VERSION_MAJOR >= 53
- av_frame_free(&frame);
-#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
- avcodec_free_frame(&frame);
-#else
- av_freep(&frame);
-#endif
- av_freep(&interleaved_buffer);
+ Error error;
+ AVFormatContext *format_context =
+ FfmpegOpenInput(stream.io, input.GetURI(), input_format, error);
+ if (format_context == nullptr) {
+ LogError(error);
+ return;
+ }
+
+ AtScopeExit(&format_context) {
+ avformat_close_input(&format_context);
+ };
+
+ FfmpegDecode(decoder, input, *format_context);
+}
+
+static bool
+FfmpegScanStream(AVFormatContext &format_context,
+ const struct tag_handler &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<uint64_t>(format_context.duration,
+ AV_TIME_BASE);
+ tag_handler_invoke_duration(&handler, handler_ctx, duration);
+ }
- avcodec_close(codec_context);
- avformat_close_input(&format_context);
+ 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);
+
+ return true;
}
-//no tag reading in ffmpeg, check if playable
static bool
ffmpeg_scan_stream(InputStream &is,
const struct tag_handler *handler, void *handler_ctx)
@@ -692,33 +727,17 @@ ffmpeg_scan_stream(InputStream &is,
if (!stream.Open())
return false;
- AVFormatContext *f = nullptr;
- if (mpd_ffmpeg_open_input(&f, stream.io, is.GetURI(),
- input_format) != 0)
+ AVFormatContext *f =
+ FfmpegOpenInput(stream.io, is.GetURI(), input_format,
+ IgnoreError());
+ if (f == nullptr)
return false;
- const int find_result =
- avformat_find_stream_info(f, nullptr);
- if (find_result < 0) {
+ AtScopeExit(&f) {
avformat_close_input(&f);
- return false;
- }
-
- if (f->duration != (int64_t)AV_NOPTS_VALUE) {
- const auto duration =
- SongTime::FromScale<uint64_t>(f->duration,
- AV_TIME_BASE);
- tag_handler_invoke_duration(handler, handler_ctx, duration);
- }
-
- ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
- int idx = ffmpeg_find_audio_stream(*f);
- if (idx >= 0)
- ffmpeg_scan_dictionary(f->streams[idx]->metadata,
- handler, handler_ctx);
+ };
- avformat_close_input(&f);
- return true;
+ return FfmpegScanStream(*f, *handler, handler_ctx);
}
/**
diff --git a/src/decoder/plugins/FfmpegIo.cxx b/src/decoder/plugins/FfmpegIo.cxx
new file mode 100644
index 0000000..5f8452c
--- /dev/null
+++ b/src/decoder/plugins/FfmpegIo.cxx
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2003-2016 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.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "FfmpegIo.hxx"
+#include "../DecoderAPI.hxx"
+#include "input/InputStream.hxx"
+#include "util/Error.hxx"
+
+AvioStream::~AvioStream()
+{
+ if (io != nullptr) {
+ av_free(io->buffer);
+ av_free(io);
+ }
+}
+
+static int
+mpd_ffmpeg_stream_read(void *opaque, uint8_t *buf, int size)
+{
+ AvioStream *stream = (AvioStream *)opaque;
+
+ return decoder_read(stream->decoder, stream->input,
+ (void *)buf, size);
+}
+
+static int64_t
+mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
+{
+ AvioStream *stream = (AvioStream *)opaque;
+
+ switch (whence) {
+ case SEEK_SET:
+ break;
+
+ case SEEK_CUR:
+ pos += stream->input.GetOffset();
+ break;
+
+ case SEEK_END:
+ if (!stream->input.KnownSize())
+ return -1;
+
+ pos += stream->input.GetSize();
+ break;
+
+ case AVSEEK_SIZE:
+ if (!stream->input.KnownSize())
+ return -1;
+
+ return stream->input.GetSize();
+
+ default:
+ return -1;
+ }
+
+ if (!stream->input.LockSeek(pos, IgnoreError()))
+ return -1;
+
+ return stream->input.GetOffset();
+}
+
+bool
+AvioStream::Open()
+{
+ constexpr size_t BUFFER_SIZE = 8192;
+ auto buffer = (unsigned char *)av_malloc(BUFFER_SIZE);
+ if (buffer == nullptr)
+ return false;
+
+ io = avio_alloc_context(buffer, BUFFER_SIZE,
+ false, this,
+ mpd_ffmpeg_stream_read, nullptr,
+ input.IsSeekable()
+ ? mpd_ffmpeg_stream_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,
+ however no AVIOContext exists in that failure code path. */
+ return io != nullptr;
+}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/decoder/plugins/FfmpegIo.hxx
similarity index 63%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/decoder/plugins/FfmpegIo.hxx
index 5eb41db..7c400de 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/decoder/plugins/FfmpegIo.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,22 +17,32 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#ifndef MPD_FFMPEG_IO_HXX
+#define MPD_FFMPEG_IO_HXX
+
+#include "check.h"
extern "C" {
-#include <libavutil/dict.h>
+#include "libavformat/avio.h"
}
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
+#include <stdint.h>
+
+class InputStream;
+struct Decoder;
+
+struct AvioStream {
+ Decoder *const decoder;
+ InputStream &input;
+
+ AVIOContext *io;
+
+ AvioStream(Decoder *_decoder, InputStream &_input)
+ :decoder(_decoder), input(_input), io(nullptr) {}
-struct tag_handler;
+ ~AvioStream();
-void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+ bool Open();
+};
#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.cxx b/src/decoder/plugins/FfmpegMetaData.cxx
index a394669..5a5c9e1 100644
--- a/src/decoder/plugins/FfmpegMetaData.cxx
+++ b/src/decoder/plugins/FfmpegMetaData.cxx
@@ -36,9 +36,9 @@ static const struct tag_table ffmpeg_tags[] = {
};
static void
-ffmpeg_copy_metadata(TagType type,
- AVDictionary *m, const char *name,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanTag(TagType type,
+ AVDictionary *m, const char *name,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVDictionaryEntry *mt = nullptr;
@@ -48,8 +48,8 @@ ffmpeg_copy_metadata(TagType type,
}
static void
-ffmpeg_scan_pairs(AVDictionary *dict,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanPairs(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVDictionaryEntry *i = nullptr;
@@ -59,18 +59,20 @@ ffmpeg_scan_pairs(AVDictionary *dict,
}
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanDictionary(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
{
- for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- ffmpeg_copy_metadata(TagType(i), dict, tag_item_names[i],
- handler, handler_ctx);
+ 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);
- for (const struct tag_table *i = ffmpeg_tags;
- i->name != nullptr; ++i)
- ffmpeg_copy_metadata(i->type, dict, i->name,
- handler, handler_ctx);
+ for (const struct tag_table *i = ffmpeg_tags;
+ i->name != nullptr; ++i)
+ FfmpegScanTag(i->type, dict, i->name,
+ handler, handler_ctx);
+ }
if (handler->pair != nullptr)
- ffmpeg_scan_pairs(dict, handler, handler_ctx);
+ FfmpegScanPairs(dict, handler, handler_ctx);
}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/decoder/plugins/FfmpegMetaData.hxx
index 5eb41db..1f233fb 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/decoder/plugins/FfmpegMetaData.hxx
@@ -32,7 +32,7 @@ extern "C" {
struct tag_handler;
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+FfmpegScanDictionary(AVDictionary *dict,
+ const tag_handler *handler, void *handler_ctx);
#endif
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 8435f09..db4070b 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -22,67 +22,61 @@
#include "../DecoderAPI.hxx"
#include "tag/TagHandler.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 <errno.h>
-#include <stdlib.h>
#include <string.h>
-#include <glib.h>
+#ifdef HAVE_SIDPLAYFP
+#include <sidplayfp/sidplayfp.h>
+#include <sidplayfp/SidInfo.h>
+#include <sidplayfp/SidConfig.h>
+#include <sidplayfp/SidTune.h>
+#include <sidplayfp/SidTuneInfo.h>
+#include <sidplayfp/builders/resid.h>
+#include <sidplayfp/builders/residfp.h>
+#include <sidplayfp/SidDatabase.h>
+#else
#include <sidplay/sidplay2.h>
#include <sidplay/builders/resid.h>
#include <sidplay/utils/SidTuneMod.h>
+#include <sidplay/utils/SidDatabase.h>
+#endif
#define SUBTUNE_PREFIX "tune_"
static constexpr Domain sidplay_domain("sidplay");
-static GPatternSpec *path_with_subtune;
-static const char *songlength_file;
-static GKeyFile *songlength_database;
+static SidDatabase *songlength_database;
static bool all_files_are_containers;
static unsigned default_songlength;
static bool filter_setting;
-static GKeyFile *
-sidplay_load_songlength_db(const char *path)
+static SidDatabase *
+sidplay_load_songlength_db(const Path path)
{
- GError *error = nullptr;
- gchar *data;
- gsize size;
-
- if (!g_file_get_contents(path, &data, &size, &error)) {
+ SidDatabase *db = new SidDatabase();
+#ifdef HAVE_SIDPLAYFP
+ bool error = !db->open(path.c_str());
+#else
+ bool error = db->open(path.c_str()) < 0;
+#endif
+ if (error) {
FormatError(sidplay_domain,
"unable to read songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- return nullptr;
- }
-
- /* replace any ; comment characters with # */
- for (gsize i = 0; i < size; i++)
- if (data[i] == ';')
- data[i] = '#';
-
- GKeyFile *db = g_key_file_new();
- bool success = g_key_file_load_from_data(db, data, size,
- G_KEY_FILE_NONE, &error);
- g_free(data);
- if (!success) {
- FormatError(sidplay_domain,
- "unable to parse songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- g_key_file_free(db);
+ path.c_str(), db->error());
+ delete db;
return nullptr;
}
- g_key_file_set_list_separator(db, ' ');
return db;
}
@@ -90,18 +84,18 @@ static bool
sidplay_init(const config_param ¶m)
{
/* read the songlengths database file */
- songlength_file = param.GetBlockValue("songlength_database");
- if (songlength_file != nullptr)
- songlength_database = sidplay_load_songlength_db(songlength_file);
+ Error error;
+ const auto database_path = param.GetBlockPath("songlength_database", error);
+ 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);
all_files_are_containers =
param.GetBlockValue("all_files_are_containers", true);
- path_with_subtune=g_pattern_spec_new(
- "*/" SUBTUNE_PREFIX "???.sid");
-
filter_setting = param.GetBlockValue("filter", true);
return true;
@@ -110,98 +104,81 @@ sidplay_init(const config_param ¶m)
static void
sidplay_finish()
{
- g_pattern_spec_free(path_with_subtune);
-
- if(songlength_database)
- g_key_file_free(songlength_database);
+ delete songlength_database;
}
-/**
- * returns the file path stripped of any /tune_xxx.sid subtune
- * suffix
- */
-static char *
-get_container_name(Path path_fs)
+struct SidplayContainerPath {
+ AllocatedPath path;
+ unsigned track;
+};
+
+gcc_pure
+static unsigned
+ParseSubtuneName(const char *base)
{
- char *path_container = strdup(path_fs.c_str());
+ if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
+ return 0;
- if(!g_pattern_match(path_with_subtune,
- strlen(path_container), path_container, nullptr))
- return path_container;
+ base += sizeof(SUBTUNE_PREFIX) - 1;
- char *ptr=g_strrstr(path_container, "/" SUBTUNE_PREFIX);
- if(ptr) *ptr='\0';
+ char *endptr;
+ auto track = strtoul(base, &endptr, 10);
+ if (endptr == base || *endptr != '.')
+ return 0;
- return path_container;
+ return track;
}
/**
- * returns tune number from file.sid/tune_xxx.sid style path or 1 if
- * no subtune is appended
+ * returns the file path stripped of any /tune_xxx.* subtune suffix
+ * and the track number (or 1 if no "tune_xxx" suffix is present).
*/
-static unsigned
-get_song_num(const char *path_fs)
+static SidplayContainerPath
+ParseContainerPath(Path path_fs)
{
- if(g_pattern_match(path_with_subtune,
- strlen(path_fs), path_fs, nullptr)) {
- char *sub=g_strrstr(path_fs, "/" SUBTUNE_PREFIX);
- if(!sub) return 1;
-
- sub+=strlen("/" SUBTUNE_PREFIX);
- int song_num=strtol(sub, nullptr, 10);
-
- if (errno == EINVAL)
- return 1;
- else
- return song_num;
- } else
- return 1;
+ const Path base = path_fs.GetBase();
+ unsigned track;
+ if (base.IsNull() ||
+ (track = ParseSubtuneName(base.c_str())) < 1)
+ return { AllocatedPath(path_fs), 1 };
+
+ return { path_fs.GetDirectoryName(), track };
}
-/* get the song length in seconds */
+#ifdef HAVE_SIDPLAYFP
+
static SignedSongTime
-get_song_length(Path path_fs)
+get_song_length(SidTune &tune)
{
if (songlength_database == nullptr)
return SignedSongTime::Negative();
- char *sid_file = get_container_name(path_fs);
- SidTuneMod tune(sid_file);
- free(sid_file);
- if(!tune) {
- LogWarning(sidplay_domain,
- "failed to load file for calculating md5 sum");
+ const auto length = songlength_database->length(tune);
+ if (length < 0)
return SignedSongTime::Negative();
- }
- char md5sum[SIDTUNE_MD5_LENGTH+1];
- tune.createMD5(md5sum);
- const unsigned song_num = get_song_num(path_fs.c_str());
+ return SignedSongTime::FromS(length);
+}
- gsize num_items;
- gchar **values=g_key_file_get_string_list(songlength_database,
- "Database", md5sum, &num_items, nullptr);
- if(!values || song_num>num_items) {
- g_strfreev(values);
- return SignedSongTime::Negative();
- }
+#else
- int minutes=strtol(values[song_num-1], nullptr, 10);
- if(errno==EINVAL) minutes=0;
+static SignedSongTime
+get_song_length(SidTuneMod &tune)
+{
+ assert(tune);
- int seconds;
- char *ptr=strchr(values[song_num-1], ':');
- if(ptr) {
- seconds=strtol(ptr+1, nullptr, 10);
- if(errno==EINVAL) seconds=0;
- } else
- seconds=0;
+ if (songlength_database == nullptr)
+ return SignedSongTime::Negative();
- g_strfreev(values);
+ const auto length = songlength_database->length(tune);
+ if (length < 0)
+ return SignedSongTime::Negative();
- return SignedSongTime::FromS((minutes * 60) + seconds);
+ return SignedSongTime::FromS(length);
}
+#endif
+
static void
sidplay_file_decode(Decoder &decoder, Path path_fs)
{
@@ -209,26 +186,43 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
/* load the tune */
- char *path_container=get_container_name(path_fs);
- SidTune tune(path_container, nullptr, true);
- free(path_container);
- if (!tune) {
- LogWarning(sidplay_domain, "failed to load file");
+ const auto container = ParseContainerPath(path_fs);
+#ifdef HAVE_SIDPLAYFP
+ SidTune tune(container.path.c_str());
+#else
+ SidTuneMod tune(container.path.c_str());
+#endif
+ if (!tune.getStatus()) {
+#ifdef HAVE_SIDPLAYFP
+ const char *error = tune.statusString();
+#else
+ const char *error = tune.getInfo().statusString;
+#endif
+ FormatWarning(sidplay_domain, "failed to load file: %s",
+ error);
return;
}
- const int song_num = get_song_num(path_fs.c_str());
+ const int song_num = container.track;
tune.selectSong(song_num);
- auto duration = get_song_length(path_fs);
+ auto duration = get_song_length(tune);
if (duration.IsNegative() && default_songlength > 0)
duration = SongTime::FromS(default_songlength);
/* initialize the player */
+#ifdef HAVE_SIDPLAYFP
+ sidplayfp player;
+#else
sidplay2 player;
- int iret = player.load(&tune);
- if (iret != 0) {
+#endif
+#ifdef HAVE_SIDPLAYFP
+ bool error = !player.load(&tune);
+#else
+ bool error = player.load(&tune) < 0;
+#endif
+ if (error) {
FormatWarning(sidplay_domain,
"sidplay2.load() failed: %s", player.error());
return;
@@ -236,53 +230,104 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
/* initialize the builder */
- ReSIDBuilder builder("ReSID");
- if (!builder) {
- LogWarning(sidplay_domain,
- "failed to initialize ReSIDBuilder");
+#ifdef HAVE_SIDPLAYFP
+ ReSIDfpBuilder builder("ReSID");
+ if (!builder.getStatus()) {
+ FormatWarning(sidplay_domain,
+ "failed to initialize ReSIDfpBuilder: %s",
+ builder.error());
return;
}
+ builder.create(player.info().maxsids());
+ if (!builder.getStatus()) {
+ FormatWarning(sidplay_domain,
+ "ReSIDfpBuilder.create() failed: %s",
+ builder.error());
+ return;
+ }
+#else
+ ReSIDBuilder builder("ReSID");
builder.create(player.info().maxsids);
if (!builder) {
- LogWarning(sidplay_domain, "ReSIDBuilder.create() failed");
+ FormatWarning(sidplay_domain, "ReSIDBuilder.create() failed: %s",
+ builder.error());
return;
}
+#endif
builder.filter(filter_setting);
+#ifdef HAVE_SIDPLAYFP
+ if (!builder.getStatus()) {
+ FormatWarning(sidplay_domain,
+ "ReSIDfpBuilder.filter() failed: %s",
+ builder.error());
+ return;
+ }
+#else
if (!builder) {
- LogWarning(sidplay_domain, "ReSIDBuilder.filter() failed");
+ FormatWarning(sidplay_domain, "ReSIDBuilder.filter() failed: %s",
+ builder.error());
return;
}
+#endif
/* configure the player */
- sid2_config_t config = player.config();
+ auto config = player.config();
+#ifndef HAVE_SIDPLAYFP
config.clockDefault = SID2_CLOCK_PAL;
config.clockForced = true;
config.clockSpeed = SID2_CLOCK_CORRECT;
+#endif
config.frequency = 48000;
+#ifndef HAVE_SIDPLAYFP
config.optimisation = SID2_DEFAULT_OPTIMISATION;
config.precision = 16;
config.sidDefault = SID2_MOS6581;
+#endif
config.sidEmulation = &builder;
+#ifdef HAVE_SIDPLAYFP
+ config.samplingMethod = SidConfig::INTERPOLATE;
+ config.fastSampling = false;
+#else
config.sidModel = SID2_MODEL_CORRECT;
config.sidSamples = true;
config.sampleFormat = IsLittleEndian()
? SID2_LITTLE_SIGNED
: SID2_BIG_SIGNED;
- if (tune.isStereo()) {
+#endif
+
+#ifdef HAVE_SIDPLAYFP
+ const bool stereo = tune.getInfo()->sidChips() >= 2;
+#else
+ const bool stereo = tune.isStereo();
+#endif
+
+ if (stereo) {
+#ifdef HAVE_SIDPLAYFP
+ config.playback = SidConfig::STEREO;
+#else
config.playback = sid2_stereo;
+#endif
channels = 2;
} else {
+#ifdef HAVE_SIDPLAYFP
+ config.playback = SidConfig::MONO;
+#else
config.playback = sid2_mono;
+#endif
channels = 1;
}
- iret = player.config(config);
- if (iret != 0) {
+#ifdef HAVE_SIDPLAYFP
+ error = !player.config(config);
+#else
+ error = player.config(config) < 0;
+#endif
+ if (error) {
FormatWarning(sidplay_domain,
"sidplay2.config() failed: %s", player.error());
return;
@@ -297,17 +342,21 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
/* .. and play */
+#ifdef HAVE_SIDPLAYFP
+ constexpr unsigned timebase = 1;
+#else
const unsigned timebase = player.timebase();
+#endif
const unsigned end = duration.IsNegative()
? 0u
: duration.ToScale<uint64_t>(timebase);
DecoderCommand cmd;
do {
- char buffer[4096];
+ short buffer[4096];
size_t nbytes;
- nbytes = player.play(buffer, sizeof(buffer));
+ nbytes = player.play(buffer, ARRAY_SIZE(buffer));
if (nbytes == 0)
break;
@@ -328,7 +377,7 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
/* ignore data until target time is reached */
while(data_time<target_time) {
- nbytes=player.play(buffer, sizeof(buffer));
+ nbytes=player.play(buffer, ARRAY_SIZE(buffer));
if(nbytes==0)
break;
data_time = player.time();
@@ -343,41 +392,72 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
} while (cmd != DecoderCommand::STOP);
}
+gcc_pure
+static const char *
+GetInfoString(const SidTuneInfo &info, unsigned i)
+{
+#ifdef HAVE_SIDPLAYFP
+ return info.numberOfInfoStrings() > i
+ ? info.infoString(i)
+ : nullptr;
+#else
+ return info.numberOfInfoStrings > i
+ ? info.infoString[i]
+ : nullptr;
+#endif
+}
+
static bool
sidplay_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
- const int song_num = get_song_num(path_fs.c_str());
- char *path_container=get_container_name(path_fs);
-
- SidTune tune(path_container, nullptr, true);
- free(path_container);
- if (!tune)
+ 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;
- if (info.numberOfInfoStrings > 0 && info.infoString[0] != nullptr)
- title=info.infoString[0];
- else
- title="";
+ const char *title = GetInfoString(info, 0);
+ if (title == nullptr)
+ title = "";
- if(info.songs>1) {
+ if (n_tracks > 1) {
char tag_title[1024];
snprintf(tag_title, sizeof(tag_title),
- "%s (%d/%d)",
- title, song_num, info.songs);
+ "%s (%d/%u)",
+ title, song_num, n_tracks);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
} else
tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, title);
/* artist */
- if (info.numberOfInfoStrings > 1 && info.infoString[1] != nullptr)
+ const char *artist = GetInfoString(info, 1);
+ if (artist != nullptr)
tag_handler_invoke_tag(handler, handler_ctx, TAG_ARTIST,
- info.infoString[1]);
+ artist);
+
+ /* date */
+ const char *date = GetInfoString(info, 2);
+ if (date != nullptr)
+ tag_handler_invoke_tag(handler, handler_ctx, TAG_DATE,
+ date);
/* track */
char track[16];
@@ -385,7 +465,7 @@ sidplay_scan_file(Path path_fs,
tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
/* time */
- const auto duration = get_song_length(path_fs);
+ const auto duration = get_song_length(tune);
if (!duration.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx,
SongTime(duration));
@@ -397,19 +477,25 @@ static char *
sidplay_container_scan(Path path_fs, const unsigned int tnum)
{
SidTune tune(path_fs.c_str(), nullptr, true);
- if (!tune)
+ if (!tune.getStatus())
return nullptr;
- const SidTuneInfo &info=tune.getInfo();
+#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
/* Don't treat sids containing a single tune
as containers */
- if(!all_files_are_containers && info.songs<2)
+ if(!all_files_are_containers && n_tracks < 2)
return nullptr;
/* Construct container/tune path names, eg.
Delta.sid/tune_001.sid */
- if(tnum<=info.songs) {
+ if (tnum <= n_tracks) {
return FormatNew(SUBTUNE_PREFIX "%03u.sid", tnum);
} else
return nullptr;
diff --git a/src/fs/AllocatedPath.hxx b/src/fs/AllocatedPath.hxx
index c345470..e3281b7 100644
--- a/src/fs/AllocatedPath.hxx
+++ b/src/fs/AllocatedPath.hxx
@@ -252,7 +252,7 @@ public:
void ChopSeparators();
gcc_pure
- bool IsAbsolute() {
+ bool IsAbsolute() const {
return PathTraitsFS::IsAbsolute(c_str());
}
};
diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx
index 9e0fa5a..084b7c3 100644
--- a/src/fs/Path.hxx
+++ b/src/fs/Path.hxx
@@ -29,6 +29,8 @@
#include <assert.h>
#include <string.h>
+class AllocatedPath;
+
/**
* A path name in the native file system character set.
*
@@ -129,6 +131,22 @@ public:
std::string ToUTF8() const;
/**
+ * Determine the "base" file name.
+ * The return value points inside this object.
+ */
+ gcc_pure
+ Path GetBase() const {
+ return FromFS(PathTraitsFS::GetBase(value));
+ }
+
+ /**
+ * Gets directory name of this path.
+ * Returns a "nulled" instance on error.
+ */
+ gcc_pure
+ AllocatedPath GetDirectoryName() const;
+
+ /**
* Determine the relative part of the given path to this
* object, not including the directory separator. Returns an
* empty string if the given path equals this object or
@@ -140,7 +158,7 @@ public:
}
gcc_pure
- bool IsAbsolute() {
+ bool IsAbsolute() const {
return PathTraitsFS::IsAbsolute(c_str());
}
};
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/fs/Path2.cxx
similarity index 71%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/fs/Path2.cxx
index 5eb41db..966e34d 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/fs/Path2.cxx
@@ -17,22 +17,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#include "config.h"
+#include "Path.hxx"
+#include "AllocatedPath.hxx"
-extern "C" {
-#include <libavutil/dict.h>
+AllocatedPath
+Path::GetDirectoryName() const
+{
+ return AllocatedPath::FromFS(PathTraitsFS::GetParent(c_str()));
}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
-
-void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
-
-#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/Buffer.hxx
similarity index 53%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/Buffer.hxx
index 5eb41db..50a702f 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/Buffer.hxx
@@ -17,22 +17,56 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#ifndef MPD_FFMPEG_BUFFER_HXX
+#define MPD_FFMPEG_BUFFER_HXX
extern "C" {
-#include <libavutil/dict.h>
+#include <libavutil/mem.h>
+
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0)
+#define HAVE_AV_FAST_MALLOC
+#else
+#include <libavcodec/avcodec.h>
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0)
+#define HAVE_AV_FAST_MALLOC
+#endif
+#endif
}
+#include <stddef.h>
+
/* suppress the ffmpeg compatibility macro */
#ifdef SampleFormat
#undef SampleFormat
#endif
-struct tag_handler;
+class FfmpegBuffer {
+ void *data;
+ unsigned size;
+
+public:
+ FfmpegBuffer():data(nullptr), size(0) {}
+
+ ~FfmpegBuffer() {
+ av_free(data);
+ }
+
+ void *Get(size_t min_size) {
+#ifdef HAVE_AV_FAST_MALLOC
+ av_fast_malloc(&data, &size, min_size);
+#else
+ void *new_data = av_fast_realloc(data, &size, min_size);
+ if (new_data == nullptr)
+ return AVERROR(ENOMEM);
+ data = new_data;
+#endif
+ return data;
+ }
-void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+ template<typename T>
+ T *GetT(size_t n) {
+ return (T *)Get(n * sizeof(T));
+ }
+};
#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/Init.cxx
similarity index 72%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/Init.cxx
index 5eb41db..24f4ab2 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/Init.cxx
@@ -17,22 +17,22 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "Init.hxx"
+#include "LogCallback.hxx"
extern "C" {
-#include <libavutil/dict.h>
+#include <libavformat/avformat.h>
}
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
-
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+FfmpegInit()
+{
+ av_log_set_callback(FfmpegLogCallback);
+
+ av_register_all();
+}
-#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/Init.hxx
similarity index 71%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/Init.hxx
index 5eb41db..bcc4805 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/Init.hxx
@@ -17,22 +17,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
-
-extern "C" {
-#include <libavutil/dict.h>
-}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
+#ifndef MPD_FFMPEG_INIT_HXX
+#define MPD_FFMPEG_INIT_HXX
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+FfmpegInit();
#endif
diff --git a/src/lib/ffmpeg/LogCallback.cxx b/src/lib/ffmpeg/LogCallback.cxx
new file mode 100644
index 0000000..799ba2f
--- /dev/null
+++ b/src/lib/ffmpeg/LogCallback.cxx
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "LogCallback.hxx"
+#include "Domain.hxx"
+#include "LogV.hxx"
+#include "util/Domain.hxx"
+
+extern "C" {
+#include <libavutil/log.h>
+}
+
+#include <stdio.h>
+
+gcc_const
+static LogLevel
+FfmpegImportLogLevel(int level)
+{
+ if (level <= AV_LOG_FATAL)
+ return LogLevel::ERROR;
+
+ if (level <= AV_LOG_WARNING)
+ return LogLevel::WARNING;
+
+ if (level <= AV_LOG_INFO)
+ return LogLevel::INFO;
+
+ return LogLevel::DEBUG;
+}
+
+void
+FfmpegLogCallback(gcc_unused void *ptr, int level, const char *fmt, va_list vl)
+{
+ const AVClass * cls = nullptr;
+
+ if (ptr != nullptr)
+ cls = *(const AVClass *const*)ptr;
+
+ if (cls != nullptr) {
+ char domain[64];
+ snprintf(domain, sizeof(domain), "%s/%s",
+ ffmpeg_domain.GetName(), cls->item_name(ptr));
+ const Domain d(domain);
+ LogFormatV(d, FfmpegImportLogLevel(level), fmt, vl);
+ }
+}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/LogCallback.hxx
similarity index 72%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/LogCallback.hxx
index 5eb41db..cb4b2cc 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/LogCallback.hxx
@@ -17,22 +17,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#ifndef MPD_FFMPEG_LOG_CALLBACK_HXX
+#define MPD_FFMPEG_LOG_CALLBACK_HXX
-extern "C" {
-#include <libavutil/dict.h>
-}
+#include "check.h"
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
+#include <stdarg.h>
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+FfmpegLogCallback(void *ptr, int level, const char *fmt, va_list vl);
#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/LogError.cxx
similarity index 65%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/LogError.cxx
index 5eb41db..da761f3 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/LogError.cxx
@@ -17,22 +17,29 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#include "config.h"
+#include "LogError.hxx"
+#include "Domain.hxx"
+#include "Log.hxx"
+
+#include <cstdint> /* needed due to libavutil bug */
extern "C" {
-#include <libavutil/dict.h>
+#include <libavutil/error.h>
}
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
-
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+LogFfmpegError(int errnum)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ LogError(ffmpeg_domain, msg);
+}
-#endif
+void
+LogFfmpegError(int errnum, const char *prefix)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ FormatError(ffmpeg_domain, "%s: %s", prefix, msg);
+}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/lib/ffmpeg/LogError.hxx
similarity index 72%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/lib/ffmpeg/LogError.hxx
index 5eb41db..ccafc6f 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/lib/ffmpeg/LogError.hxx
@@ -17,22 +17,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#ifndef MPD_FFMPEG_LOG_ERROR_HXX
+#define MPD_FFMPEG_LOG_ERROR_HXX
-extern "C" {
-#include <libavutil/dict.h>
-}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
+void
+LogFfmpegError(int errnum);
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+LogFfmpegError(int errnum, const char *prefix);
#endif
diff --git a/src/lib/ffmpeg/Time.hxx b/src/lib/ffmpeg/Time.hxx
new file mode 100644
index 0000000..9325434
--- /dev/null
+++ b/src/lib/ffmpeg/Time.hxx
@@ -0,0 +1,104 @@
+/*
+ * 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_FFMPEG_TIME_HXX
+#define MPD_FFMPEG_TIME_HXX
+
+#include "Chrono.hxx"
+#include "Compiler.h"
+
+extern "C" {
+#include <libavutil/avutil.h>
+#include <libavutil/mathematics.h>
+}
+
+#include <assert.h>
+#include <stdint.h>
+
+/* suppress the ffmpeg compatibility macro */
+#ifdef SampleFormat
+#undef SampleFormat
+#endif
+
+gcc_const
+static inline double
+FfmpegTimeToDouble(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
+ / (double)1024;
+}
+
+template<typename Ratio>
+static inline constexpr AVRational
+RatioToAVRational()
+{
+ return { Ratio::num, Ratio::den };
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SongTime.
+ */
+gcc_const
+static inline SongTime
+FromFfmpegTime(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return SongTime::FromMS(av_rescale_q(t, time_base,
+ (AVRational){1, 1000}));
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SignedSongTime.
+ */
+gcc_const
+static inline SignedSongTime
+FromFfmpegTimeChecked(int64_t t, const AVRational time_base)
+{
+ return t != (int64_t)AV_NOPTS_VALUE
+ ? SignedSongTime(FromFfmpegTime(t, time_base))
+ : SignedSongTime::Negative();
+}
+
+/**
+ * Convert a #SongTime to a FFmpeg time stamp with the given base.
+ */
+gcc_const
+static inline int64_t
+ToFfmpegTime(SongTime t, const AVRational time_base)
+{
+ return av_rescale_q(t.count(),
+ RatioToAVRational<SongTime::period>(),
+ time_base);
+}
+
+/**
+ * Replace #AV_NOPTS_VALUE with the given fallback.
+ */
+static constexpr int64_t
+FfmpegTimestampFallback(int64_t t, int64_t fallback)
+{
+ return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
+ ? t
+ : fallback;
+}
+
+#endif
diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx
index 6d50cce..2164b1d 100644
--- a/src/lib/nfs/Manager.cxx
+++ b/src/lib/nfs/Manager.cxx
@@ -59,6 +59,18 @@ NfsManager::Compare::operator()(const ManagedConnection &a,
return result < 0;
}
+inline bool
+NfsManager::Compare::operator()(const ManagedConnection &a,
+ const ManagedConnection &b) const
+{
+ int result = strcmp(a.GetServer(), b.GetServer());
+ if (result != 0)
+ return result < 0;
+
+ result = strcmp(a.GetExportName(), b.GetExportName());
+ return result < 0;
+}
+
NfsManager::~NfsManager()
{
assert(GetEventLoop().IsInside());
diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx
index 130c81a..80acbdf 100644
--- a/src/lib/nfs/Manager.hxx
+++ b/src/lib/nfs/Manager.hxx
@@ -64,6 +64,10 @@ class NfsManager final : IdleMonitor {
gcc_pure
bool operator()(const ManagedConnection &a,
const LookupKey b) const;
+
+ gcc_pure
+ bool operator()(const ManagedConnection &a,
+ const ManagedConnection &b) const;
};
/**
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index 406be8d..b0456f5 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -164,7 +164,9 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
}
}
- const char *encoding = param.GetBlockValue("encoding", "ogg");
+ const char *encoding = param.GetBlockValue("encoder", nullptr);
+ if (encoding == nullptr)
+ encoding = param.GetBlockValue("encoding", "vorbis");
const auto encoder_plugin = shout_encoder_plugin_get(encoding);
if (encoder_plugin == nullptr) {
error.Format(config_domain,
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/pcm/Interleave.cxx
similarity index 50%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/pcm/Interleave.cxx
index 5eb41db..8f2b11b 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/pcm/Interleave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,22 +17,31 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#include "config.h"
+#include "Interleave.hxx"
-extern "C" {
-#include <libavutil/dict.h>
-}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
+#include <stdint.h>
+#include <string.h>
-struct tag_handler;
+static void
+GenericPcmInterleave(uint8_t *dest, ConstBuffer<const uint8_t *> src,
+ size_t n_frames, size_t sample_size)
+{
+ for (size_t frame = 0; frame < n_frames; ++frame) {
+ for (size_t channel = 0; channel < src.size; ++channel) {
+ memcpy(dest, src[channel] + frame * sample_size,
+ sample_size);
+ dest += sample_size;
+ }
+ }
+}
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
-
-#endif
+PcmInterleave(void *dest, ConstBuffer<const void *> src,
+ size_t n_frames, size_t sample_size)
+{
+ GenericPcmInterleave((uint8_t *)dest,
+ ConstBuffer<const uint8_t *>((const uint8_t *const*)src.data,
+ src.size),
+ n_frames, sample_size);
+}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/pcm/Interleave.hxx
similarity index 66%
copy from src/decoder/plugins/FfmpegMetaData.hxx
copy to src/pcm/Interleave.hxx
index 5eb41db..c8acbb3 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/pcm/Interleave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,22 +17,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_METADATA_HXX
-#define MPD_FFMPEG_METADATA_HXX
+#ifndef MPD_PCM_INTERLEAVE_HXX
+#define MPD_PCM_INTERLEAVE_HXX
-extern "C" {
-#include <libavutil/dict.h>
-}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-struct tag_handler;
+#include "check.h"
+#include "util/ConstBuffer.hxx"
+/**
+ * Interleave planar PCM samples from #src to #dest.
+ */
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+PcmInterleave(void *dest, ConstBuffer<const void *> src,
+ size_t n_frames, size_t sample_size);
#endif
diff --git a/src/util/ScopeExit.hxx b/src/util/ScopeExit.hxx
new file mode 100644
index 0000000..0ec65cd
--- /dev/null
+++ b/src/util/ScopeExit.hxx
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Max Kellermann <max at duempel.org>
+ *
+ * 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 SCOPE_EXIT_HXX
+#define SCOPE_EXIT_HXX
+
+#include "Compiler.h"
+
+#include <utility>
+
+/**
+ * Internal class. Do not use directly.
+ */
+template<typename F>
+class ScopeExitGuard : F {
+ bool enabled = true;
+
+public:
+ explicit ScopeExitGuard(F &&f):F(std::forward<F>(f)) {}
+
+ ScopeExitGuard(ScopeExitGuard &&src)
+ :F(std::move(src)) {
+ src.enabled = false;
+ }
+
+ ~ScopeExitGuard() {
+ if (enabled)
+ F::operator()();
+ }
+
+ ScopeExitGuard(const ScopeExitGuard &) = delete;
+ ScopeExitGuard &operator=(const ScopeExitGuard &) = delete;
+};
+
+/**
+ * Internal class. Do not use directly.
+ */
+struct ScopeExitTag {
+ /* this operator is a trick so we don't need to close
+ parantheses at the end of the expression AtScopeExit()
+ call */
+ template<typename F>
+ ScopeExitGuard<F> operator+(F &&f) {
+ return ScopeExitGuard<F>(std::forward<F>(f));
+ }
+};
+
+#define ScopeExitCat(a, b) a ## b
+#define ScopeExitName(line) ScopeExitCat(at_scope_exit_, line)
+
+/**
+ * Call the block after this macro at the end of the current scope.
+ * Parameters are lambda captures.
+ *
+ * This is exception-safe, however the given code block must not throw
+ * exceptions.
+ *
+ * This attempts to be a better boost/scope_exit.hpp, without all of
+ * Boost's compile-time and runtime bloat.
+ */
+#define AtScopeExit(...) auto ScopeExitName(__LINE__) = ScopeExitTag() + [__VA_ARGS__]()
+
+#endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mpd/pkg-mpd.git
More information about the Pkg-mpd-commits
mailing list