[Pkg-mpd-commits] [pkg-mpd] 01/05: New upstream version 0.20.11

Florian Schlichting fsfs at moszumanska.debian.org
Wed Nov 15 19:55:48 UTC 2017


This is an automated email from the git hooks/post-receive script.

fsfs pushed a commit to branch master
in repository pkg-mpd.

commit 5b328d7d86cfcfc481da3b578ce4285b49f70126
Author: Florian Schlichting <fsfs at debian.org>
Date:   Wed Nov 15 20:22:53 2017 +0100

    New upstream version 0.20.11
---
 AUTHORS                                            |   1 +
 Makefile.am                                        |   5 +
 Makefile.in                                        |  96 ++++++++++++++--
 NEWS                                               |  21 ++++
 android/build.py                                   |   4 +
 config.h.in                                        |   3 +
 configure                                          |  33 ++++--
 configure.ac                                       |   5 +-
 doc/doxygen.conf                                   |   2 +-
 doc/protocol.xml                                   |  13 ++-
 doc/user.xml                                       |  61 +++++++++-
 src/PlaylistFile.cxx                               |  11 +-
 src/PlaylistSave.cxx                               |  18 ++-
 src/SongFilter.cxx                                 |  19 +---
 src/SongFilter.hxx                                 |   8 +-
 src/db/Selection.cxx                               |   1 +
 src/decoder/DecoderThread.cxx                      |   1 +
 src/decoder/plugins/FfmpegDecoderPlugin.cxx        |   8 +-
 src/decoder/plugins/FfmpegMetaData.cxx             |   6 +
 src/decoder/plugins/GmeDecoderPlugin.cxx           |   4 +-
 src/lib/icu/{Collate.cxx => CaseFold.cxx}          | 124 ++-------------------
 src/lib/icu/{Collate.hxx => CaseFold.hxx}          |  25 ++---
 src/lib/icu/Collate.cxx                            |  69 ------------
 src/lib/icu/Collate.hxx                            |   6 -
 src/lib/icu/Compare.cxx                            |  66 +++++++++++
 src/lib/icu/{Collate.hxx => Compare.hxx}           |  40 ++++---
 src/mixer/MixerList.hxx                            |   1 +
 src/mixer/plugins/OSXMixerPlugin.cxx               |  69 ++++++++++++
 src/output/plugins/OSXOutputPlugin.cxx             |  57 +++++++++-
 src/output/plugins/OSXOutputPlugin.hxx             |   8 ++
 src/output/plugins/SndioOutputPlugin.cxx           |  34 +++---
 src/player/Thread.cxx                              |   2 +-
 src/queue/Playlist.cxx                             |   3 +-
 src/queue/Playlist.hxx                             |  12 ++
 src/queue/PlaylistControl.cxx                      |  34 ++++--
 src/queue/Queue.cxx                                |  21 +++-
 src/queue/Queue.hxx                                |  22 +++-
 src/storage/plugins/CurlStorage.cxx                |  20 +++-
 src/tag/Aiff.cxx                                   |   2 +-
 .../icu/Collate.hxx => tag/Id3MusicBrainz.cxx}     |  41 +++----
 .../OSXOutputPlugin.hxx => tag/Id3MusicBrainz.hxx} |   6 +-
 src/tag/TagId3.cxx                                 |  16 +--
 src/util/FormatString.cxx                          |   2 +-
 43 files changed, 647 insertions(+), 353 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index e4582d0..14aa053 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -30,3 +30,4 @@ The following people have contributed code to MPD:
  Jurgen Kramer <gtmkramer at xs4all.nl>
  Jean-Francois Dockes <jf at dockes.org>
  Yue Wang <yuleopen at gmail.com>
+ Matthew Leon Grinshpun <ml at matthewleon.com>
diff --git a/Makefile.am b/Makefile.am
index 898abba..f909647 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -518,6 +518,8 @@ libevent_a_SOURCES = \
 # UTF-8 library
 
 libicu_a_SOURCES = \
+	src/lib/icu/CaseFold.cxx src/lib/icu/CaseFold.hxx \
+	src/lib/icu/Compare.cxx src/lib/icu/Compare.hxx \
 	src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \
 	src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx
 
@@ -923,6 +925,7 @@ libtag_a_SOURCES =\
 	src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \
 	src/tag/MixRamp.cxx src/tag/MixRamp.hxx \
 	src/tag/Generic.cxx src/tag/Generic.hxx \
+	src/tag/Id3MusicBrainz.cxx src/tag/Id3MusicBrainz.hxx \
 	src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \
 	src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \
 	src/tag/ApeTag.cxx src/tag/ApeTag.hxx
@@ -1489,6 +1492,8 @@ liboutput_plugins_a_SOURCES += \
 	src/output/plugins/OSXOutputPlugin.cxx \
 	src/output/plugins/OSXOutputPlugin.hxx
 endif
+libmixer_plugins_a_SOURCES += \
+	src/mixer/plugins/OSXMixerPlugin.cxx
 
 if ENABLE_PULSE
 liboutput_plugins_a_SOURCES += \
diff --git a/Makefile.in b/Makefile.in
index bcd3117..632d921 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1035,7 +1035,9 @@ am_libfs_a_OBJECTS = src/fs/io/libfs_a-PeekReader.$(OBJEXT) \
 libfs_a_OBJECTS = $(am_libfs_a_OBJECTS)
 libicu_a_AR = $(AR) $(ARFLAGS)
 libicu_a_LIBADD =
-am__libicu_a_SOURCES_DIST = src/lib/icu/Collate.cxx \
+am__libicu_a_SOURCES_DIST = src/lib/icu/CaseFold.cxx \
+	src/lib/icu/CaseFold.hxx src/lib/icu/Compare.cxx \
+	src/lib/icu/Compare.hxx src/lib/icu/Collate.cxx \
 	src/lib/icu/Collate.hxx src/lib/icu/Converter.cxx \
 	src/lib/icu/Converter.hxx src/lib/icu/Util.cxx \
 	src/lib/icu/Util.hxx src/lib/icu/Init.cxx src/lib/icu/Init.hxx \
@@ -1044,7 +1046,9 @@ am__libicu_a_SOURCES_DIST = src/lib/icu/Collate.cxx \
 @HAVE_ICU_TRUE@	src/lib/icu/libicu_a-Init.$(OBJEXT)
 @HAVE_WINDOWS_TRUE at am__objects_37 =  \
 @HAVE_WINDOWS_TRUE@	src/lib/icu/libicu_a-Win32.$(OBJEXT)
-am_libicu_a_OBJECTS = src/lib/icu/libicu_a-Collate.$(OBJEXT) \
+am_libicu_a_OBJECTS = src/lib/icu/libicu_a-CaseFold.$(OBJEXT) \
+	src/lib/icu/libicu_a-Compare.$(OBJEXT) \
+	src/lib/icu/libicu_a-Collate.$(OBJEXT) \
 	src/lib/icu/libicu_a-Converter.$(OBJEXT) $(am__objects_36) \
 	$(am__objects_37)
 libicu_a_OBJECTS = $(am_libicu_a_OBJECTS)
@@ -1166,6 +1170,7 @@ am__libmixer_plugins_a_SOURCES_DIST =  \
 	src/mixer/plugins/RoarMixerPlugin.cxx \
 	src/mixer/plugins/HaikuMixerPlugin.cxx \
 	src/mixer/plugins/OssMixerPlugin.cxx \
+	src/mixer/plugins/OSXMixerPlugin.cxx \
 	src/mixer/plugins/PulseMixerPlugin.cxx \
 	src/mixer/plugins/PulseMixerPlugin.hxx \
 	src/mixer/plugins/WinmmMixerPlugin.cxx
@@ -1179,7 +1184,9 @@ am__libmixer_plugins_a_SOURCES_DIST =  \
 am_libmixer_plugins_a_OBJECTS = src/mixer/plugins/libmixer_plugins_a-NullMixerPlugin.$(OBJEXT) \
 	src/mixer/plugins/libmixer_plugins_a-SoftwareMixerPlugin.$(OBJEXT) \
 	$(am__objects_48) $(am__objects_49) $(am__objects_50) \
-	$(am__objects_51) $(am__objects_52) $(am__objects_53)
+	$(am__objects_51) \
+	src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.$(OBJEXT) \
+	$(am__objects_52) $(am__objects_53)
 libmixer_plugins_a_OBJECTS = $(am_libmixer_plugins_a_OBJECTS)
 libmodplug_decoder_plugin_a_AR = $(AR) $(ARFLAGS)
 libmodplug_decoder_plugin_a_LIBADD =
@@ -1829,7 +1836,8 @@ am__libtag_a_SOURCES_DIST = src/tag/TagType.h src/tag/Tag.cxx \
 	src/tag/VorbisComment.cxx src/tag/VorbisComment.hxx \
 	src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \
 	src/tag/MixRamp.cxx src/tag/MixRamp.hxx src/tag/Generic.cxx \
-	src/tag/Generic.hxx src/tag/ApeLoader.cxx \
+	src/tag/Generic.hxx src/tag/Id3MusicBrainz.cxx \
+	src/tag/Id3MusicBrainz.hxx src/tag/ApeLoader.cxx \
 	src/tag/ApeLoader.hxx src/tag/ApeReplayGain.cxx \
 	src/tag/ApeReplayGain.hxx src/tag/ApeTag.cxx \
 	src/tag/ApeTag.hxx src/tag/Id3Load.cxx src/tag/Id3Load.hxx \
@@ -1857,6 +1865,7 @@ am_libtag_a_OBJECTS = src/tag/libtag_a-Tag.$(OBJEXT) \
 	src/tag/libtag_a-ReplayGain.$(OBJEXT) \
 	src/tag/libtag_a-MixRamp.$(OBJEXT) \
 	src/tag/libtag_a-Generic.$(OBJEXT) \
+	src/tag/libtag_a-Id3MusicBrainz.$(OBJEXT) \
 	src/tag/libtag_a-ApeLoader.$(OBJEXT) \
 	src/tag/libtag_a-ApeReplayGain.$(OBJEXT) \
 	src/tag/libtag_a-ApeTag.$(OBJEXT) $(am__objects_100)
@@ -3549,7 +3558,9 @@ libevent_a_SOURCES = \
 
 
 # UTF-8 library
-libicu_a_SOURCES = src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \
+libicu_a_SOURCES = src/lib/icu/CaseFold.cxx src/lib/icu/CaseFold.hxx \
+	src/lib/icu/Compare.cxx src/lib/icu/Compare.hxx \
+	src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \
 	src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx \
 	$(am__append_8) $(am__append_9)
 libicu_a_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -3781,7 +3792,8 @@ libtag_a_SOURCES = src/tag/TagType.h src/tag/Tag.cxx src/tag/Tag.hxx \
 	src/tag/VorbisComment.cxx src/tag/VorbisComment.hxx \
 	src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \
 	src/tag/MixRamp.cxx src/tag/MixRamp.hxx src/tag/Generic.cxx \
-	src/tag/Generic.hxx src/tag/ApeLoader.cxx \
+	src/tag/Generic.hxx src/tag/Id3MusicBrainz.cxx \
+	src/tag/Id3MusicBrainz.hxx src/tag/ApeLoader.cxx \
 	src/tag/ApeLoader.hxx src/tag/ApeReplayGain.cxx \
 	src/tag/ApeReplayGain.hxx src/tag/ApeTag.cxx \
 	src/tag/ApeTag.hxx $(am__append_36)
@@ -3972,7 +3984,8 @@ libmixer_plugins_a_SOURCES = src/mixer/plugins/NullMixerPlugin.cxx \
 	src/mixer/plugins/SoftwareMixerPlugin.cxx \
 	src/mixer/plugins/SoftwareMixerPlugin.hxx $(am__append_81) \
 	$(am__append_85) $(am__append_90) $(am__append_94) \
-	$(am__append_98) $(am__append_106)
+	src/mixer/plugins/OSXMixerPlugin.cxx $(am__append_98) \
+	$(am__append_106)
 libmixer_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \
 	$(ALSA_CFLAGS) \
 	$(PULSE_CFLAGS)
@@ -5310,6 +5323,10 @@ src/lib/icu/$(am__dirstamp):
 src/lib/icu/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/lib/icu/$(DEPDIR)
 	@: > src/lib/icu/$(DEPDIR)/$(am__dirstamp)
+src/lib/icu/libicu_a-CaseFold.$(OBJEXT): src/lib/icu/$(am__dirstamp) \
+	src/lib/icu/$(DEPDIR)/$(am__dirstamp)
+src/lib/icu/libicu_a-Compare.$(OBJEXT): src/lib/icu/$(am__dirstamp) \
+	src/lib/icu/$(DEPDIR)/$(am__dirstamp)
 src/lib/icu/libicu_a-Collate.$(OBJEXT): src/lib/icu/$(am__dirstamp) \
 	src/lib/icu/$(DEPDIR)/$(am__dirstamp)
 src/lib/icu/libicu_a-Converter.$(OBJEXT): src/lib/icu/$(am__dirstamp) \
@@ -5491,6 +5508,9 @@ src/mixer/plugins/libmixer_plugins_a-HaikuMixerPlugin.$(OBJEXT):  \
 src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.$(OBJEXT):  \
 	src/mixer/plugins/$(am__dirstamp) \
 	src/mixer/plugins/$(DEPDIR)/$(am__dirstamp)
+src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.$(OBJEXT):  \
+	src/mixer/plugins/$(am__dirstamp) \
+	src/mixer/plugins/$(DEPDIR)/$(am__dirstamp)
 src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.$(OBJEXT):  \
 	src/mixer/plugins/$(am__dirstamp) \
 	src/mixer/plugins/$(DEPDIR)/$(am__dirstamp)
@@ -6440,6 +6460,8 @@ src/tag/libtag_a-MixRamp.$(OBJEXT): src/tag/$(am__dirstamp) \
 	src/tag/$(DEPDIR)/$(am__dirstamp)
 src/tag/libtag_a-Generic.$(OBJEXT): src/tag/$(am__dirstamp) \
 	src/tag/$(DEPDIR)/$(am__dirstamp)
+src/tag/libtag_a-Id3MusicBrainz.$(OBJEXT): src/tag/$(am__dirstamp) \
+	src/tag/$(DEPDIR)/$(am__dirstamp)
 src/tag/libtag_a-ApeLoader.$(OBJEXT): src/tag/$(am__dirstamp) \
 	src/tag/$(DEPDIR)/$(am__dirstamp)
 src/tag/libtag_a-ApeReplayGain.$(OBJEXT): src/tag/$(am__dirstamp) \
@@ -7391,7 +7413,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-Init.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogCallback.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/ffmpeg/$(DEPDIR)/libffmpeg_a-LogError.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Collate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Compare.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Converter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Init.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/lib/icu/$(DEPDIR)/libicu_a-Util.Po at am__quote@
@@ -7452,6 +7476,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-AlsaMixerPlugin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-HaikuMixerPlugin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-NullMixerPlugin.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OssMixerPlugin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-PulseMixerPlugin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-RoarMixerPlugin.Po at am__quote@
@@ -7604,6 +7629,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-Format.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-Generic.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-Id3Load.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-MixRamp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-ReplayGain.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at src/tag/$(DEPDIR)/libtag_a-Riff.Po at am__quote@
@@ -8983,6 +9009,34 @@ src/fs/io/libfs_a-GzipOutputStream.obj: src/fs/io/GzipOutputStream.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/io/libfs_a-GzipOutputStream.obj `if test -f 'src/fs/io/GzipOutputStream.cxx'; then $(CYGPATH_W) 'src/fs/io/GzipOutputStream.cxx'; else $(CYGPATH_W) '$(srcdir)/src/fs/io/GzipOutputStream.cxx'; fi`
 
+src/lib/icu/libicu_a-CaseFold.o: src/lib/icu/CaseFold.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-CaseFold.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Tpo -c -o src/lib/icu/libicu_a-CaseFold.o `test -f 'src/lib/icu/CaseFold.cxx' || echo '$(srcdir)/'`src/lib/icu/CaseFold.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Tpo src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/lib/icu/CaseFold.cxx' object='src/lib/icu/libicu_a-CaseFold.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) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-CaseFold.o `test -f 'src/lib/icu/CaseFold.cxx' || echo '$(srcdir)/'`src/lib/icu/CaseFold.cxx
+
+src/lib/icu/libicu_a-CaseFold.obj: src/lib/icu/CaseFold.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-CaseFold.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Tpo -c -o src/lib/icu/libicu_a-CaseFold.obj `if test -f 'src/lib/icu/CaseFold.cxx'; then $(CYGPATH_W) 'src/lib/icu/CaseFold.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/CaseFold.cxx'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Tpo src/lib/icu/$(DEPDIR)/libicu_a-CaseFold.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/lib/icu/CaseFold.cxx' object='src/lib/icu/libicu_a-CaseFold.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) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-CaseFold.obj `if test -f 'src/lib/icu/CaseFold.cxx'; then $(CYGPATH_W) 'src/lib/icu/CaseFold.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/CaseFold.cxx'; fi`
+
+src/lib/icu/libicu_a-Compare.o: src/lib/icu/Compare.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Compare.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Compare.Tpo -c -o src/lib/icu/libicu_a-Compare.o `test -f 'src/lib/icu/Compare.cxx' || echo '$(srcdir)/'`src/lib/icu/Compare.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Compare.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Compare.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/lib/icu/Compare.cxx' object='src/lib/icu/libicu_a-Compare.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) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Compare.o `test -f 'src/lib/icu/Compare.cxx' || echo '$(srcdir)/'`src/lib/icu/Compare.cxx
+
+src/lib/icu/libicu_a-Compare.obj: src/lib/icu/Compare.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Compare.obj -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Compare.Tpo -c -o src/lib/icu/libicu_a-Compare.obj `if test -f 'src/lib/icu/Compare.cxx'; then $(CYGPATH_W) 'src/lib/icu/Compare.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Compare.cxx'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Compare.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Compare.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/lib/icu/Compare.cxx' object='src/lib/icu/libicu_a-Compare.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) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/lib/icu/libicu_a-Compare.obj `if test -f 'src/lib/icu/Compare.cxx'; then $(CYGPATH_W) 'src/lib/icu/Compare.cxx'; else $(CYGPATH_W) '$(srcdir)/src/lib/icu/Compare.cxx'; fi`
+
 src/lib/icu/libicu_a-Collate.o: src/lib/icu/Collate.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libicu_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/lib/icu/libicu_a-Collate.o -MD -MP -MF src/lib/icu/$(DEPDIR)/libicu_a-Collate.Tpo -c -o src/lib/icu/libicu_a-Collate.o `test -f 'src/lib/icu/Collate.cxx' || echo '$(srcdir)/'`src/lib/icu/Collate.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/lib/icu/$(DEPDIR)/libicu_a-Collate.Tpo src/lib/icu/$(DEPDIR)/libicu_a-Collate.Po
@@ -9627,6 +9681,20 @@ src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.obj: src/mixer/plugins/OssMi
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-OssMixerPlugin.obj `if test -f 'src/mixer/plugins/OssMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/OssMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/OssMixerPlugin.cxx'; fi`
 
+src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.o: src/mixer/plugins/OSXMixerPlugin.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.o `test -f 'src/mixer/plugins/OSXMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/OSXMixerPlugin.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/mixer/plugins/OSXMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.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) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.o `test -f 'src/mixer/plugins/OSXMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/OSXMixerPlugin.cxx
+
+src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.obj: src/mixer/plugins/OSXMixerPlugin.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.obj -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.obj `if test -f 'src/mixer/plugins/OSXMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/OSXMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-OSXMixerPlugin.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/mixer/plugins/OSXMixerPlugin.cxx' object='src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.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) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mixer/plugins/libmixer_plugins_a-OSXMixerPlugin.obj `if test -f 'src/mixer/plugins/OSXMixerPlugin.cxx'; then $(CYGPATH_W) 'src/mixer/plugins/OSXMixerPlugin.cxx'; else $(CYGPATH_W) '$(srcdir)/src/mixer/plugins/OSXMixerPlugin.cxx'; fi`
+
 src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.o: src/mixer/plugins/PulseMixerPlugin.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmixer_plugins_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.o -MD -MP -MF src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-PulseMixerPlugin.Tpo -c -o src/mixer/plugins/libmixer_plugins_a-PulseMixerPlugin.o `test -f 'src/mixer/plugins/PulseMixerPlugin.cxx' || echo '$(srcdir)/'`src/mixer/plugins/PulseMixerPlugin.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-PulseMixerPlugin.Tpo src/mixer/plugins/$(DEPDIR)/libmixer_plugins_a-PulseMixerPlugin.Po
@@ -13393,6 +13461,20 @@ src/tag/libtag_a-Generic.obj: src/tag/Generic.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) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Generic.obj `if test -f 'src/tag/Generic.cxx'; then $(CYGPATH_W) 'src/tag/Generic.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Generic.cxx'; fi`
 
+src/tag/libtag_a-Id3MusicBrainz.o: src/tag/Id3MusicBrainz.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Id3MusicBrainz.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Tpo -c -o src/tag/libtag_a-Id3MusicBrainz.o `test -f 'src/tag/Id3MusicBrainz.cxx' || echo '$(srcdir)/'`src/tag/Id3MusicBrainz.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Tpo src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/tag/Id3MusicBrainz.cxx' object='src/tag/libtag_a-Id3MusicBrainz.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) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Id3MusicBrainz.o `test -f 'src/tag/Id3MusicBrainz.cxx' || echo '$(srcdir)/'`src/tag/Id3MusicBrainz.cxx
+
+src/tag/libtag_a-Id3MusicBrainz.obj: src/tag/Id3MusicBrainz.cxx
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-Id3MusicBrainz.obj -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Tpo -c -o src/tag/libtag_a-Id3MusicBrainz.obj `if test -f 'src/tag/Id3MusicBrainz.cxx'; then $(CYGPATH_W) 'src/tag/Id3MusicBrainz.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Id3MusicBrainz.cxx'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Tpo src/tag/$(DEPDIR)/libtag_a-Id3MusicBrainz.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='src/tag/Id3MusicBrainz.cxx' object='src/tag/libtag_a-Id3MusicBrainz.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) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tag/libtag_a-Id3MusicBrainz.obj `if test -f 'src/tag/Id3MusicBrainz.cxx'; then $(CYGPATH_W) 'src/tag/Id3MusicBrainz.cxx'; else $(CYGPATH_W) '$(srcdir)/src/tag/Id3MusicBrainz.cxx'; fi`
+
 src/tag/libtag_a-ApeLoader.o: src/tag/ApeLoader.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtag_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tag/libtag_a-ApeLoader.o -MD -MP -MF src/tag/$(DEPDIR)/libtag_a-ApeLoader.Tpo -c -o src/tag/libtag_a-ApeLoader.o `test -f 'src/tag/ApeLoader.cxx' || echo '$(srcdir)/'`src/tag/ApeLoader.cxx
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) src/tag/$(DEPDIR)/libtag_a-ApeLoader.Tpo src/tag/$(DEPDIR)/libtag_a-ApeLoader.Po
diff --git a/NEWS b/NEWS
index b538b11..804d6d7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,24 @@
+ver 0.20.11 (2017/10/18)
+* storage
+  - curl: support Content-Type application/xml
+* decoder
+  - ffmpeg: more reliable song duration
+  - gme: fix track numbering
+* improve random song order when switching songs manually
+* fix case insensitive search without libicu
+* fix Unicode file names in playlists on Windows
+* fix endless loop when accessing malformed file names in ZIP files
+
+ver 0.20.10 (2017/08/24)
+* decoder
+  - ffmpeg: support MusicBrainz ID3v2 tags
+* tags
+  - aiff: fix FORM chunk size endianess (is big-endian)
+* mixer
+  - osx: add a mixer for OSX.
+* fix crash when resuming playback before decoder is ready
+* fix crash on Windows
+
 ver 0.20.9 (2017/06/04)
 * decoder
   - ffmpeg: support *.adx
diff --git a/android/build.py b/android/build.py
index a37432e..3ec3d9b 100755
--- a/android/build.py
+++ b/android/build.py
@@ -154,5 +154,9 @@ configure = [
 
 ] + configure_args
 
+from build.cmdline import concatenate_cmdline_variables
+configure = concatenate_cmdline_variables(configure,
+    set(('CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'LIBS')))
+
 subprocess.check_call(configure, env=toolchain.env)
 subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)
diff --git a/config.h.in b/config.h.in
index 2c09452..7206266 100644
--- a/config.h.in
+++ b/config.h.in
@@ -309,6 +309,9 @@
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
+/* Define to 1 if you have the `strcasestr' function. */
+#undef HAVE_STRCASESTR
+
 /* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
 
diff --git a/configure b/configure
index b87c409..b70a8ca 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.20.9.
+# Generated by GNU Autoconf 2.69 for mpd 0.20.11.
 #
 # 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.20.9'
-PACKAGE_STRING='mpd 0.20.9'
+PACKAGE_VERSION='0.20.11'
+PACKAGE_STRING='mpd 0.20.11'
 PACKAGE_BUGREPORT='musicpd-dev-team at lists.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1785,7 +1785,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.20.9 to adapt to many kinds of systems.
+\`configure' configures mpd 0.20.11 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1856,7 +1856,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of mpd 0.20.9:";;
+     short | recursive ) echo "Configuration of mpd 0.20.11:";;
    esac
   cat <<\_ACEOF
 
@@ -2209,7 +2209,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-mpd configure 0.20.9
+mpd configure 0.20.11
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2616,7 +2616,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.20.9, which was
+It was created by mpd $as_me 0.20.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2967,7 +2967,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 VERSION_MAJOR=0
 VERSION_MINOR=20
-VERSION_REVISION=9
+VERSION_REVISION=11
 VERSION_EXTRA=0
 
 
@@ -3486,7 +3486,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='mpd'
- VERSION='0.20.9'
+ VERSION='0.20.11'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -8366,6 +8366,17 @@ _ACEOF
 fi
 done
 
+for ac_func in strcasestr
+do :
+  ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr"
+if test "x$ac_cv_func_strcasestr" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRCASESTR 1
+_ACEOF
+
+fi
+done
+
 
 if test x$host_is_linux = xyes; then
 
@@ -21691,7 +21702,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.20.9, which was
+This file was extended by mpd $as_me 0.20.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21757,7 +21768,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.20.9
+mpd config.status 0.20.11
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 403254c..ad8b646 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
 AC_PREREQ(2.60)
 
-AC_INIT(mpd, 0.20.9, musicpd-dev-team at lists.sourceforge.net)
+AC_INIT(mpd, 0.20.11, musicpd-dev-team at lists.sourceforge.net)
 
 VERSION_MAJOR=0
 VERSION_MINOR=20
-VERSION_REVISION=9
+VERSION_REVISION=11
 VERSION_EXTRA=0
 
 AC_CONFIG_SRCDIR([src/Main.cxx])
@@ -241,6 +241,7 @@ AC_CHECK_FUNCS(getpwnam_r getpwuid_r)
 AC_CHECK_FUNCS(initgroups)
 AC_CHECK_FUNCS(fnmatch)
 AC_CHECK_FUNCS(strndup)
+AC_CHECK_FUNCS(strcasestr)
 
 if test x$host_is_linux = xyes; then
 	MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index e86dfb6..4dff202 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -38,7 +38,7 @@ PROJECT_NAME           = MPD
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.20.9
+PROJECT_NUMBER         = 0.20.11
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 7996abd..4b9a4c9 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -403,6 +403,15 @@
                 </para>
               </listitem>
             </itemizedlist>
+
+            <para>
+              Change events accumulate, even while the connection is
+              not in "idle" mode; no events gets lost while the client
+              is doing something else with the connection.  If an
+              event had already occurred since the last call, the new
+              <command>idle</command> command will return immediately.
+            </para>
+
             <para>
               While a client is waiting for <command>idle</command>
               results, the server disables timeouts, allowing a client
@@ -436,7 +445,9 @@
               <listitem>
                 <para>
                   <varname>volume</varname>:
-                  <returnvalue>0-100</returnvalue>
+                  <returnvalue>0-100</returnvalue> or
+                  <returnvalue>-1</returnvalue> if the volume cannot
+                  be determined
                 </para>
               </listitem>
               <listitem>
diff --git a/doc/user.xml b/doc/user.xml
index 9a93123..e010d5e 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -113,7 +113,7 @@ cd mpd-version</programlisting>
 
       <para>
         For example, the following installs a fairly complete list of
-        build dependencies on Debian Wheezy:
+        build dependencies on Debian Jessie:
       </para>
 
       <programlisting>
@@ -125,19 +125,20 @@ apt-get install g++ \
   libmpcdec-dev libwavpack-dev libwildmidi-dev \
   libsidplay2-dev libsidutils-dev libresid-builder-dev \
   libavcodec-dev libavformat-dev \
-  libmp3lame-dev \
+  libmp3lame-dev libtwolame-dev libshine-dev \
   libsamplerate0-dev libsoxr-dev \
   libbz2-dev libcdio-paranoia-dev libiso9660-dev libmms-dev \
   libzzip-dev \
   libcurl4-gnutls-dev libyajl-dev libexpat-dev \
   libasound2-dev libao-dev libjack-jackd2-dev libopenal-dev \
   libpulse-dev libroar-dev libshout3-dev \
+  libsndio-dev \
   libmpdclient-dev \
   libnfs-dev libsmbclient-dev \
   libupnp-dev \
   libavahi-client-dev \
   libsqlite3-dev \
-  libsystemd-daemon-dev libwrap0-dev \
+  libsystemd-dev libwrap0-dev \
   libcppunit-dev xmlto \
   libboost-dev \
   libicu-dev
@@ -2990,6 +2991,60 @@ run</programlisting>
         </informaltable>
       </section>
 
+      <section id="opus_encoder">
+        <title><varname>opus</varname></title>
+
+        <para>
+          Encodes into <ulink
+          url="http://www.opus-codec.org/">Ogg Opus</ulink>.
+        </para>
+
+        <informaltable>
+          <tgroup cols="2">
+            <thead>
+              <row>
+                <entry>Setting</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>
+                  <varname>bitrate</varname>
+                </entry>
+                <entry>
+                  Sets the data rate in bit per second.  The special
+                  value "auto" lets <application>libopus</application>
+                  choose a rate (which is the default), and "max" uses
+                  the maximum possible data rate.
+                </entry>
+              </row>
+
+              <row>
+                <entry>
+                  <varname>complexity</varname>
+                </entry>
+                <entry>
+                  Sets the <ulink
+                  url="https://wiki.xiph.org/OpusFAQ#What_is_the_complexity_of_Opus.3F">Opus
+                  complexity</ulink>.
+                </entry>
+              </row>
+
+              <row>
+                <entry>
+                  <varname>signal</varname>
+                </entry>
+                <entry>
+                  Sets the Opus signal type.  Valid values are "auto"
+                  (the default), "voice" and "music".
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </section>
+
       <section id="vorbis_encoder">
         <title><varname>vorbis</varname></title>
 
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx
index 2deae43..c1fcdeb 100644
--- a/src/PlaylistFile.cxx
+++ b/src/PlaylistFile.cxx
@@ -207,13 +207,12 @@ try {
 			continue;
 
 #ifdef _UNICODE
-		wchar_t buffer[MAX_PATH];
-		auto result = MultiByteToWideChar(CP_ACP, 0, s, -1,
-						  buffer, ARRAY_SIZE(buffer));
-		if (result <= 0)
+		/* on Windows, playlists always contain UTF-8, because
+		   its "narrow" charset (i.e. CP_ACP) is incapable of
+		   storing all Unicode paths */
+		const auto path = AllocatedPath::FromUTF8(s);
+		if (path.IsNull())
 			continue;
-
-		const Path path = Path::FromFS(buffer);
 #else
 		const Path path = Path::FromFS(s);
 #endif
diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx
index e64daba..d3ec30b 100644
--- a/src/PlaylistSave.cxx
+++ b/src/PlaylistSave.cxx
@@ -28,13 +28,25 @@
 #include "fs/AllocatedPath.hxx"
 #include "fs/Traits.hxx"
 #include "fs/FileSystem.hxx"
-#include "fs/NarrowPath.hxx"
 #include "fs/io/FileOutputStream.hxx"
 #include "fs/io/BufferedOutputStream.hxx"
 #include "util/UriUtil.hxx"
 
 #include <stdexcept>
 
+static void
+playlist_print_path(BufferedOutputStream &os, const Path path)
+{
+#ifdef _UNICODE
+	/* on Windows, playlists always contain UTF-8, because its
+	   "narrow" charset (i.e. CP_ACP) is incapable of storing all
+	   Unicode paths */
+	os.Format("%s\n", path.ToUTF8().c_str());
+#else
+	os.Format("%s\n", path.c_str());
+#endif
+}
+
 void
 playlist_print_song(BufferedOutputStream &os, const DetachedSong &song)
 {
@@ -44,7 +56,7 @@ playlist_print_song(BufferedOutputStream &os, const DetachedSong &song)
 
 	try {
 		const auto uri_fs = AllocatedPath::FromUTF8Throw(uri_utf8);
-		os.Format("%s\n", NarrowPath(uri_fs).c_str());
+		playlist_print_path(os, uri_fs);
 	} catch (const std::runtime_error &) {
 	}
 }
@@ -63,7 +75,7 @@ playlist_print_uri(BufferedOutputStream &os, const char *uri)
 			AllocatedPath::FromUTF8Throw(uri);
 
 		if (!path.IsNull())
-			os.Format("%s\n", NarrowPath(path).c_str());
+			playlist_print_path(os, path);
 	} catch (const std::runtime_error &) {
 	}
 }
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index ed556ed..4c3e746 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -27,7 +27,7 @@
 #include "util/ASCII.hxx"
 #include "util/TimeParser.hxx"
 #include "util/UriUtil.hxx"
-#include "lib/icu/Collate.hxx"
+#include "lib/icu/CaseFold.hxx"
 
 #include <stdexcept>
 
@@ -57,17 +57,10 @@ locate_parse_type(const char *str) noexcept
 	return tag_name_parse_i(str);
 }
 
-static AllocatedString<>
-ImportString(const char *p, bool fold_case)
-{
-	return fold_case
-		? IcuCaseFold(p)
-		: AllocatedString<>::Duplicate(p);
-}
-
 SongFilter::Item::Item(unsigned _tag, const char *_value, bool _fold_case)
-	:tag(_tag), fold_case(_fold_case),
-	 value(ImportString(_value, _fold_case))
+	:tag(_tag),
+	 value(AllocatedString<>::Duplicate(_value)),
+	 fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare())
 {
 }
 
@@ -87,9 +80,7 @@ SongFilter::Item::StringMatch(const char *s) const noexcept
 	assert(tag != LOCATE_TAG_MODIFIED_SINCE);
 
 	if (fold_case) {
-		const auto folded = IcuCaseFold(s);
-		assert(!folded.IsNull());
-		return StringFind(folded.c_str(), value.c_str()) != nullptr;
+		return fold_case.IsIn(s);
 	} else {
 		return StringIsEqual(s, value.c_str());
 	}
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index a0bb25d..ec83178 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -20,6 +20,7 @@
 #ifndef MPD_SONG_FILTER_HXX
 #define MPD_SONG_FILTER_HXX
 
+#include "lib/icu/Compare.hxx"
 #include "util/AllocatedString.hxx"
 #include "Compiler.h"
 
@@ -48,11 +49,14 @@ public:
 	class Item {
 		uint8_t tag;
 
-		bool fold_case;
-
 		AllocatedString<> value;
 
 		/**
+		 * This value is only set if case folding is enabled.
+		 */
+		IcuCompare fold_case;
+
+		/**
 		 * For #LOCATE_TAG_MODIFIED_SINCE
 		 */
 		time_t time;
diff --git a/src/db/Selection.cxx b/src/db/Selection.cxx
index bab9c9d..c25bf99 100644
--- a/src/db/Selection.cxx
+++ b/src/db/Selection.cxx
@@ -17,6 +17,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include "config.h"
 #include "Selection.hxx"
 #include "SongFilter.hxx"
 
diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx
index e74ee0f..7d4a915 100644
--- a/src/decoder/DecoderThread.cxx
+++ b/src/decoder/DecoderThread.cxx
@@ -508,6 +508,7 @@ try {
 	decoder_run_song(dc, song, uri_utf8, path_fs);
 } catch (...) {
 	dc.state = DecoderState::ERROR;
+	dc.command = DecoderCommand::NONE;
 	dc.error = std::current_exception();
 	dc.client_cond.signal();
 }
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index 75038e6..aba9688 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -712,7 +712,9 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
 #endif
 
 	const SignedSongTime total_time =
-		FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
+		av_stream.duration != (int64_t)AV_NOPTS_VALUE
+		? FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base)
+		: FromFfmpegTimeChecked(format_context.duration, AV_TIME_BASE_Q);
 
 	client.Ready(audio_format, input.IsSeekable(), total_time);
 
@@ -842,6 +844,10 @@ FfmpegScanStream(AVFormatContext &format_context,
 		tag_handler_invoke_duration(handler, handler_ctx,
 					    FromFfmpegTime(stream.duration,
 							   stream.time_base));
+	else if (format_context.duration != (int64_t)AV_NOPTS_VALUE)
+		tag_handler_invoke_duration(handler, handler_ctx,
+					    FromFfmpegTime(format_context.duration,
+							   AV_TIME_BASE_Q));
 
 	FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);
 
diff --git a/src/decoder/plugins/FfmpegMetaData.cxx b/src/decoder/plugins/FfmpegMetaData.cxx
index 24eb0cc..2491dbf 100644
--- a/src/decoder/plugins/FfmpegMetaData.cxx
+++ b/src/decoder/plugins/FfmpegMetaData.cxx
@@ -24,6 +24,7 @@
 #include "FfmpegMetaData.hxx"
 #include "tag/TagTable.hxx"
 #include "tag/TagHandler.hxx"
+#include "tag/Id3MusicBrainz.hxx"
 
 extern "C" {
 #include <libavutil/dict.h>
@@ -75,6 +76,11 @@ FfmpegScanDictionary(AVDictionary *dict,
 		     i->name != nullptr; ++i)
 			FfmpegScanTag(i->type, dict, i->name,
 				      handler, handler_ctx);
+
+		for (const struct tag_table *i = musicbrainz_txxx_tags;
+		     i->name != nullptr; ++i)
+			FfmpegScanTag(i->type, dict, i->name,
+				      handler, handler_ctx);
 	}
 
 	if (handler.pair != nullptr)
diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx
index 403e623..1b9d061 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.cxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.cxx
@@ -293,13 +293,13 @@ gme_container_scan(Path path_fs)
 	TagBuilder tag_builder;
 
 	auto tail = list.before_begin();
-	for (unsigned i = 1; i <= num_songs; ++i) {
+	for (unsigned i = 0; i < num_songs; ++i) {
 		ScanMusicEmu(emu, i,
 			     add_tag_handler, &tag_builder);
 
 		char track_name[64];
 		snprintf(track_name, sizeof(track_name),
-			 SUBTUNE_PREFIX "%03u.%s", i, subtune_suffix);
+			 SUBTUNE_PREFIX "%03u.%s", i+1, subtune_suffix);
 		tail = list.emplace_after(tail, track_name,
 					  tag_builder.Commit());
 	}
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/CaseFold.cxx
similarity index 51%
copy from src/lib/icu/Collate.cxx
copy to src/lib/icu/CaseFold.cxx
index abb4b70..ccdf998 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/CaseFold.cxx
@@ -18,14 +18,16 @@
  */
 
 #include "config.h"
-#include "Collate.hxx"
+#include "CaseFold.hxx"
+
+#ifdef HAVE_ICU_CASE_FOLD
+
 #include "util/AllocatedString.hxx"
 
 #ifdef HAVE_ICU
 #include "Util.hxx"
 #include "util/AllocatedArray.hxx"
 #include "util/ConstBuffer.hxx"
-#include "util/RuntimeError.hxx"
 
 #include <unicode/ucol.h>
 #include <unicode/ustring.h>
@@ -36,7 +38,6 @@
 
 #ifdef WIN32
 #include "Win32.hxx"
-#include "util/AllocatedString.hxx"
 #include <windows.h>
 #endif
 
@@ -46,107 +47,10 @@
 #include <assert.h>
 #include <string.h>
 
-#ifdef HAVE_ICU
-static UCollator *collator;
-#endif
-
-#ifdef HAVE_ICU
-
-void
-IcuCollateInit()
-{
-	assert(collator == nullptr);
-
-	UErrorCode code = U_ZERO_ERROR;
-	collator = ucol_open("", &code);
-	if (collator == nullptr)
-		throw FormatRuntimeError("ucol_open() failed: %s",
-					 u_errorName(code));
-}
-
-void
-IcuCollateFinish() noexcept
-{
-	assert(collator != nullptr);
-
-	ucol_close(collator);
-}
-
-#endif
-
-gcc_pure
-int
-IcuCollate(const char *a, const char *b) noexcept
-{
-#if !CLANG_CHECK_VERSION(3,6)
-	/* disabled on clang due to -Wtautological-pointer-compare */
-	assert(a != nullptr);
-	assert(b != nullptr);
-#endif
-
-#ifdef HAVE_ICU
-	assert(collator != nullptr);
-
-#if U_ICU_VERSION_MAJOR_NUM >= 50
-	UErrorCode code = U_ZERO_ERROR;
-	return (int)ucol_strcollUTF8(collator, a, -1, b, -1, &code);
-#else
-	/* fall back to ucol_strcoll() */
-
-	try {
-		const auto au = UCharFromUTF8(a);
-		const auto bu = UCharFromUTF8(b);
-
-		return ucol_strcoll(collator, au.begin(), au.size(),
-				    bu.begin(), bu.size());
-	} catch (const std::runtime_error &) {
-		/* fall back to plain strcasecmp() */
-		return strcasecmp(a, b);
-	}
-#endif
-
-#elif defined(WIN32)
-	AllocatedString<wchar_t> wa = nullptr, wb = nullptr;
-
-	try {
-		wa = MultiByteToWideChar(CP_UTF8, a);
-	} catch (const std::runtime_error &) {
-		try {
-			wb = MultiByteToWideChar(CP_UTF8, b);
-			return -1;
-		} catch (const std::runtime_error &) {
-			return 0;
-		}
-	}
-
-	try {
-		wb = MultiByteToWideChar(CP_UTF8, b);
-	} catch (const std::runtime_error &) {
-		return 1;
-	}
-
-	auto result = CompareStringEx(LOCALE_NAME_INVARIANT,
-				      LINGUISTIC_IGNORECASE,
-				      wa.c_str(), -1,
-				      wb.c_str(), -1,
-				      nullptr, nullptr, 0);
-	if (result != 0)
-		/* "To maintain the C runtime convention of comparing
-		   strings, the value 2 can be subtracted from a
-		   nonzero return value." */
-		result -= 2;
-
-	return result;
-#else
-	return strcoll(a, b);
-#endif
-}
-
 AllocatedString<>
-IcuCaseFold(const char *src)
+IcuCaseFold(const char *src) noexcept
 try {
 #ifdef HAVE_ICU
-	assert(collator != nullptr);
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
 	assert(src != nullptr);
@@ -189,22 +93,10 @@ try {
 	return WideCharToMultiByte(CP_UTF8, buffer.get());
 
 #else
-	size_t size = strlen(src) + 1;
-	std::unique_ptr<char[]> buffer(new char[size]);
-	size_t nbytes = strxfrm(buffer.get(), src, size);
-	if (nbytes >= size) {
-		/* buffer too small - reallocate and try again */
-		buffer.reset();
-		size = nbytes + 1;
-		buffer.reset(new char[size]);
-		nbytes = strxfrm(buffer.get(), src, size);
-	}
-
-	assert(nbytes < size);
-	assert(buffer[nbytes] == 0);
-
-	return AllocatedString<>::Donate(buffer.release());
+#error not implemented
 #endif
 } catch (const std::runtime_error &) {
 	return AllocatedString<>::Duplicate(src);
 }
+
+#endif /* HAVE_ICU_CASE_FOLD */
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/CaseFold.hxx
similarity index 77%
copy from src/lib/icu/Collate.hxx
copy to src/lib/icu/CaseFold.hxx
index d6cfcb7..eaeaf56 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/CaseFold.hxx
@@ -17,29 +17,22 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef MPD_ICU_COLLATE_HXX
-#define MPD_ICU_COLLATE_HXX
+#ifndef MPD_ICU_CASE_FOLD_HXX
+#define MPD_ICU_CASE_FOLD_HXX
 
 #include "check.h"
-#include "Compiler.h"
-
-template<typename T> class AllocatedString;
 
-/**
- * Throws #std::runtime_error on error.
- */
-void
-IcuCollateInit();
+#if defined(HAVE_ICU) || defined(_WIN32)
+#define HAVE_ICU_CASE_FOLD
 
-void
-IcuCollateFinish() noexcept;
+#include "Compiler.h"
 
-gcc_pure gcc_nonnull_all
-int
-IcuCollate(const char *a, const char *b) noexcept;
+template<typename T> class AllocatedString;
 
 gcc_nonnull_all
 AllocatedString<char>
-IcuCaseFold(const char *src);
+IcuCaseFold(const char *src) noexcept;
+
+#endif
 
 #endif
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx
index abb4b70..f16cba5 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/Collate.cxx
@@ -23,8 +23,6 @@
 
 #ifdef HAVE_ICU
 #include "Util.hxx"
-#include "util/AllocatedArray.hxx"
-#include "util/ConstBuffer.hxx"
 #include "util/RuntimeError.hxx"
 
 #include <unicode/ucol.h>
@@ -141,70 +139,3 @@ IcuCollate(const char *a, const char *b) noexcept
 	return strcoll(a, b);
 #endif
 }
-
-AllocatedString<>
-IcuCaseFold(const char *src)
-try {
-#ifdef HAVE_ICU
-	assert(collator != nullptr);
-#if !CLANG_CHECK_VERSION(3,6)
-	/* disabled on clang due to -Wtautological-pointer-compare */
-	assert(src != nullptr);
-#endif
-
-	const auto u = UCharFromUTF8(src);
-	if (u.IsNull())
-		return AllocatedString<>::Duplicate(src);
-
-	AllocatedArray<UChar> folded(u.size() * 2u);
-
-	UErrorCode error_code = U_ZERO_ERROR;
-	size_t folded_length = u_strFoldCase(folded.begin(), folded.size(),
-					     u.begin(), u.size(),
-					     U_FOLD_CASE_DEFAULT,
-					     &error_code);
-	if (folded_length == 0 || error_code != U_ZERO_ERROR)
-		return AllocatedString<>::Duplicate(src);
-
-	folded.SetSize(folded_length);
-	return UCharToUTF8({folded.begin(), folded.size()});
-
-#elif defined(WIN32)
-	const auto u = MultiByteToWideChar(CP_UTF8, src);
-
-	const int size = LCMapStringEx(LOCALE_NAME_INVARIANT,
-				       LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
-				       u.c_str(), -1, nullptr, 0,
-				       nullptr, nullptr, 0);
-	if (size <= 0)
-		return AllocatedString<>::Duplicate(src);
-
-	std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]);
-	if (LCMapStringEx(LOCALE_NAME_INVARIANT,
-			  LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
-			  u.c_str(), -1, buffer.get(), size,
-			  nullptr, nullptr, 0) <= 0)
-		return AllocatedString<>::Duplicate(src);
-
-	return WideCharToMultiByte(CP_UTF8, buffer.get());
-
-#else
-	size_t size = strlen(src) + 1;
-	std::unique_ptr<char[]> buffer(new char[size]);
-	size_t nbytes = strxfrm(buffer.get(), src, size);
-	if (nbytes >= size) {
-		/* buffer too small - reallocate and try again */
-		buffer.reset();
-		size = nbytes + 1;
-		buffer.reset(new char[size]);
-		nbytes = strxfrm(buffer.get(), src, size);
-	}
-
-	assert(nbytes < size);
-	assert(buffer[nbytes] == 0);
-
-	return AllocatedString<>::Donate(buffer.release());
-#endif
-} catch (const std::runtime_error &) {
-	return AllocatedString<>::Duplicate(src);
-}
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx
index d6cfcb7..d22fa68 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/Collate.hxx
@@ -23,8 +23,6 @@
 #include "check.h"
 #include "Compiler.h"
 
-template<typename T> class AllocatedString;
-
 /**
  * Throws #std::runtime_error on error.
  */
@@ -38,8 +36,4 @@ gcc_pure gcc_nonnull_all
 int
 IcuCollate(const char *a, const char *b) noexcept;
 
-gcc_nonnull_all
-AllocatedString<char>
-IcuCaseFold(const char *src);
-
 #endif
diff --git a/src/lib/icu/Compare.cxx b/src/lib/icu/Compare.cxx
new file mode 100644
index 0000000..21b3230
--- /dev/null
+++ b/src/lib/icu/Compare.cxx
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Compare.hxx"
+#include "CaseFold.hxx"
+#include "util/StringAPI.hxx"
+
+#include <string.h>
+
+#ifdef HAVE_ICU_CASE_FOLD
+
+IcuCompare::IcuCompare(const char *_needle) noexcept
+	:needle(IcuCaseFold(_needle)) {}
+
+#else
+
+IcuCompare::IcuCompare(const char *_needle) noexcept
+	:needle(AllocatedString<>::Duplicate(_needle)) {}
+
+#endif
+
+bool
+IcuCompare::operator==(const char *haystack) const noexcept
+{
+#ifdef HAVE_ICU_CASE_FOLD
+	return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str());
+#else
+	return strcasecmp(haystack, needle.c_str());
+#endif
+}
+
+bool
+IcuCompare::IsIn(const char *haystack) const noexcept
+{
+#ifdef HAVE_ICU_CASE_FOLD
+	return StringFind(IcuCaseFold(haystack).c_str(),
+			  needle.c_str()) != nullptr;
+#elif defined(HAVE_STRCASESTR)
+	return strcasestr(haystack, needle.c_str()) != nullptr;
+#else
+	/* poor man's strcasestr() */
+	for (const size_t length = strlen(needle.c_str());
+	     *haystack != 0; ++haystack)
+		if (strncasecmp(haystack, needle.c_str(), length) == 0)
+			return true;
+
+	return false;
+#endif
+}
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Compare.hxx
similarity index 54%
copy from src/lib/icu/Collate.hxx
copy to src/lib/icu/Compare.hxx
index d6cfcb7..9ee2e68 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/Compare.hxx
@@ -17,29 +17,39 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef MPD_ICU_COLLATE_HXX
-#define MPD_ICU_COLLATE_HXX
+#ifndef MPD_ICU_COMPARE_HXX
+#define MPD_ICU_COMPARE_HXX
 
 #include "check.h"
 #include "Compiler.h"
-
-template<typename T> class AllocatedString;
+#include "util/AllocatedString.hxx"
 
 /**
- * Throws #std::runtime_error on error.
+ * This class can compare one string ("needle") with lots of other
+ * strings ("haystacks") efficiently, ignoring case.  With some
+ * configurations, it can prepare a case-folded version of the needle.
  */
-void
-IcuCollateInit();
+class IcuCompare {
+	AllocatedString<> needle;
+
+public:
+	IcuCompare():needle(nullptr) {}
+
+	explicit IcuCompare(const char *needle) noexcept;
+
+	IcuCompare(IcuCompare &&) = default;
+	IcuCompare &operator=(IcuCompare &&) = default;
 
-void
-IcuCollateFinish() noexcept;
+	gcc_pure
+	operator bool() const noexcept {
+		return !needle.IsNull();
+	}
 
-gcc_pure gcc_nonnull_all
-int
-IcuCollate(const char *a, const char *b) noexcept;
+	gcc_pure
+	bool operator==(const char *haystack) const noexcept;
 
-gcc_nonnull_all
-AllocatedString<char>
-IcuCaseFold(const char *src);
+	gcc_pure
+	bool IsIn(const char *haystack) const noexcept;
+};
 
 #endif
diff --git a/src/mixer/MixerList.hxx b/src/mixer/MixerList.hxx
index b1a8cf1..7c5fe24 100644
--- a/src/mixer/MixerList.hxx
+++ b/src/mixer/MixerList.hxx
@@ -32,6 +32,7 @@ extern const MixerPlugin software_mixer_plugin;
 extern const MixerPlugin alsa_mixer_plugin;
 extern const MixerPlugin haiku_mixer_plugin;
 extern const MixerPlugin oss_mixer_plugin;
+extern const MixerPlugin osx_mixer_plugin;
 extern const MixerPlugin roar_mixer_plugin;
 extern const MixerPlugin pulse_mixer_plugin;
 extern const MixerPlugin winmm_mixer_plugin;
diff --git a/src/mixer/plugins/OSXMixerPlugin.cxx b/src/mixer/plugins/OSXMixerPlugin.cxx
new file mode 100644
index 0000000..566489b
--- /dev/null
+++ b/src/mixer/plugins/OSXMixerPlugin.cxx
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "mixer/MixerInternal.hxx"
+#include "output/plugins/OSXOutputPlugin.hxx"
+
+class OSXMixer final : public Mixer {
+	OSXOutput &output;
+
+public:
+	OSXMixer(OSXOutput &_output, MixerListener &_listener)
+		:Mixer(osx_mixer_plugin, _listener),
+		 output(_output)
+	{
+	}
+
+	/* virtual methods from class Mixer */
+	void Open() override {
+	}
+
+	void Close() override {
+	}
+
+	int GetVolume() override;
+	void SetVolume(unsigned volume) override;
+};
+
+int
+OSXMixer::GetVolume()
+{
+	return osx_output_get_volume(output);
+}
+
+void
+OSXMixer::SetVolume(unsigned new_volume)
+{
+	osx_output_set_volume(output, new_volume);
+}
+
+static Mixer *
+osx_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
+		MixerListener &listener,
+		gcc_unused const ConfigBlock &block)
+{
+	OSXOutput &osxo = (OSXOutput &)ao;
+	return new OSXMixer(osxo, listener);
+}
+
+const MixerPlugin osx_mixer_plugin = {
+	osx_mixer_init,
+	true,
+};
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index 020044a..3a0e6fb 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "OSXOutputPlugin.hxx"
 #include "../OutputAPI.hxx"
+#include "mixer/MixerList.hxx"
 #include "util/ScopeExit.hxx"
 #include "util/RuntimeError.hxx"
 #include "util/Domain.hxx"
@@ -53,6 +54,9 @@ struct OSXOutput {
 	boost::lockfree::spsc_queue<uint8_t> *ring_buffer;
 
 	OSXOutput(const ConfigBlock &block);
+
+	int GetVolume();
+	void SetVolume(unsigned new_volume);
 };
 
 static constexpr Domain osx_output_domain("osx_output");
@@ -103,6 +107,44 @@ OSXOutput::OSXOutput(const ConfigBlock &block)
 	sync_sample_rate = block.GetBlockValue("sync_sample_rate", false);
 }
 
+int
+OSXOutput::GetVolume()
+{
+	AudioUnitParameterValue dvolume;
+	char errormsg[1024];
+
+	OSStatus status = AudioUnitGetParameter(au, kHALOutputParam_Volume,
+			kAudioUnitScope_Global, 0, &dvolume);
+	if (status != noErr) {
+		osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
+		throw FormatRuntimeError("unable to get volume: %s", errormsg);
+	}
+
+	/* see the explanation in SetVolume, below */
+	return static_cast<int>(dvolume * dvolume * 100.0);
+}
+
+void
+OSXOutput::SetVolume(unsigned new_volume) {
+	char errormsg[1024];
+
+	/* The scaling below makes shifts in volume greater at the lower end
+	 * of the scale. This mimics the "feel" of physical volume levers. This is
+	 * generally what users of audio software expect.
+	 */
+
+	AudioUnitParameterValue scaled_volume =
+		sqrt(static_cast<AudioUnitParameterValue>(new_volume) / 100.0);
+
+	OSStatus status = AudioUnitSetParameter(au, kHALOutputParam_Volume,
+			kAudioUnitScope_Global, 0, scaled_volume, 0);
+	if (status != noErr) {
+		osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
+		throw FormatRuntimeError( "unable to set new volume %u: %s",
+				new_volume, errormsg);
+	}
+}
+
 static AudioOutput *
 osx_output_init(const ConfigBlock &block)
 {
@@ -678,6 +720,18 @@ osx_output_delay(AudioOutput *ao) noexcept
 		: std::chrono::milliseconds(25);
 }
 
+int
+osx_output_get_volume(OSXOutput &output)
+{
+	return output.GetVolume();
+}
+
+void
+osx_output_set_volume(OSXOutput &output, unsigned new_volume)
+{
+	return output.SetVolume(new_volume);
+}
+
 const struct AudioOutputPlugin osx_output_plugin = {
 	"osx",
 	osx_output_test_default_device,
@@ -693,5 +747,6 @@ const struct AudioOutputPlugin osx_output_plugin = {
 	nullptr,
 	nullptr,
 	nullptr,
-	nullptr,
+
+	&osx_mixer_plugin,
 };
diff --git a/src/output/plugins/OSXOutputPlugin.hxx b/src/output/plugins/OSXOutputPlugin.hxx
index 440cb8d..9c98424 100644
--- a/src/output/plugins/OSXOutputPlugin.hxx
+++ b/src/output/plugins/OSXOutputPlugin.hxx
@@ -20,6 +20,14 @@
 #ifndef MPD_OSX_OUTPUT_PLUGIN_HXX
 #define MPD_OSX_OUTPUT_PLUGIN_HXX
 
+struct OSXOutput;
+
 extern const struct AudioOutputPlugin osx_output_plugin;
 
+int
+osx_output_get_volume(OSXOutput &output);
+
+void
+osx_output_set_volume(OSXOutput &output, unsigned new_volume);
+
 #endif
diff --git a/src/output/plugins/SndioOutputPlugin.cxx b/src/output/plugins/SndioOutputPlugin.cxx
index b0050d6..699f625 100644
--- a/src/output/plugins/SndioOutputPlugin.cxx
+++ b/src/output/plugins/SndioOutputPlugin.cxx
@@ -50,7 +50,7 @@ class SndioOutput {
 	AudioOutput base;
 	const char *const device;
 	const unsigned buffer_time; /* in ms */
-	struct sio_hdl *sio_hdl;
+	struct sio_hdl *hdl;
 
 public:
 	SndioOutput(const ConfigBlock &block);
@@ -80,16 +80,14 @@ SndioOutput::Create(const ConfigBlock &block)
 static bool
 sndio_test_default_device()
 {
-	struct sio_hdl *sio_hdl;
-
-	sio_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
-	if (!sio_hdl) {
+	auto *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+	if (!hdl) {
 		FormatError(sndio_output_domain,
-		            "Error opening default sndio device");
+			    "Error opening default sndio device");
 		return false;
 	}
 
-	sio_close(sio_hdl);
+	sio_close(hdl);
 	return true;
 }
 
@@ -99,8 +97,8 @@ SndioOutput::Open(AudioFormat &audio_format)
 	struct sio_par par;
 	unsigned bits, rate, chans;
 
-	sio_hdl = sio_open(device, SIO_PLAY, 0);
-	if (!sio_hdl)
+	hdl = sio_open(device, SIO_PLAY, 0);
+	if (!hdl)
 		throw std::runtime_error("Failed to open default sndio device");
 
 	switch (audio_format.format) {
@@ -130,9 +128,9 @@ SndioOutput::Open(AudioFormat &audio_format)
 	par.le = SIO_LE_NATIVE;
 	par.appbufsz = rate * buffer_time / 1000;
 
-	if (!sio_setpar(sio_hdl, &par) ||
-	    !sio_getpar(sio_hdl, &par)) {
-		sio_close(sio_hdl);
+	if (!sio_setpar(hdl, &par) ||
+	    !sio_getpar(hdl, &par)) {
+		sio_close(hdl);
 		throw std::runtime_error("Failed to set/get audio params");
 	}
 
@@ -142,12 +140,12 @@ SndioOutput::Open(AudioFormat &audio_format)
 	    par.pchan != chans ||
 	    par.sig != 1 ||
 	    par.le != SIO_LE_NATIVE) {
-		sio_close(sio_hdl);
+		sio_close(hdl);
 		throw std::runtime_error("Requested audio params cannot be satisfied");
 	}
 
-	if (!sio_start(sio_hdl)) {
-		sio_close(sio_hdl);
+	if (!sio_start(hdl)) {
+		sio_close(hdl);
 		throw std::runtime_error("Failed to start audio device");
 	}
 }
@@ -155,7 +153,7 @@ SndioOutput::Open(AudioFormat &audio_format)
 void
 SndioOutput::Close()
 {
-	sio_close(sio_hdl);
+	sio_close(hdl);
 }
 
 size_t
@@ -163,8 +161,8 @@ SndioOutput::Play(const void *chunk, size_t size)
 {
 	size_t n;
 
-	n = sio_write(sio_hdl, chunk, size);
-	if (n == 0 && sio_eof(sio_hdl) != 0)
+	n = sio_write(hdl, chunk, size);
+	if (n == 0 && sio_eof(hdl) != 0)
 		throw std::runtime_error("sndio write failed");
 	return n;
 }
diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx
index 4cbe165..923e5ee 100644
--- a/src/player/Thread.cxx
+++ b/src/player/Thread.cxx
@@ -135,7 +135,7 @@ class Player {
 	/**
 	 * The current audio format for the audio outputs.
 	 */
-	AudioFormat play_audio_format;
+	AudioFormat play_audio_format = AudioFormat::Undefined();
 
 	/**
 	 * The time stamp of the chunk most recently sent to the
diff --git a/src/queue/Playlist.cxx b/src/queue/Playlist.cxx
index 667e345..dfeb0d1 100644
--- a/src/queue/Playlist.cxx
+++ b/src/queue/Playlist.cxx
@@ -310,8 +310,7 @@ playlist::SetRandom(PlayerControl &pc, bool status)
 			   playlist is played after that */
 			unsigned current_order =
 				queue.PositionToOrder(current_position);
-			queue.MoveOrder(current_order, 0);
-			current = 0;
+			current = queue.MoveOrder(current_order, 0);
 		} else
 			current = -1;
 	} else
diff --git a/src/queue/Playlist.hxx b/src/queue/Playlist.hxx
index 32489e3..c04a091 100644
--- a/src/queue/Playlist.hxx
+++ b/src/queue/Playlist.hxx
@@ -356,6 +356,18 @@ public:
 	}
 
 	void SetConsume(bool new_value);
+
+private:
+	/**
+	 * Prepare a manual song change: move the given song to the
+	 * current playback order.  This is done to avoid skipping
+	 * upcoming songs in the order list.  The newly selected song
+	 * shall be inserted in the order list, and the rest shall be
+	 * played after that as previously planned.
+	 *
+	 * @return the new order number of the given song
+	 */
+	unsigned MoveOrderToCurrent(unsigned old_order);
 };
 
 #endif
diff --git a/src/queue/PlaylistControl.cxx b/src/queue/PlaylistControl.cxx
index 99012ae..4b17386 100644
--- a/src/queue/PlaylistControl.cxx
+++ b/src/queue/PlaylistControl.cxx
@@ -56,6 +56,30 @@ playlist::Stop(PlayerControl &pc)
 	}
 }
 
+unsigned
+playlist::MoveOrderToCurrent(unsigned old_order)
+{
+	if (!queue.random)
+		/* no-op because there is no order list */
+		return old_order;
+
+	if (playing) {
+		/* already playing: move the specified song after the
+		   current one (because the current one has already
+		   been playing and shall not be played again) */
+		return queue.MoveOrderAfter(old_order, current);
+	} else if (current >= 0) {
+		/* not playing: move the specified song before the
+		   current one, so it will be played eventually */
+		return queue.MoveOrderBefore(old_order, current);
+	} else {
+		/* not playing anything: move the specified song to
+		   the front */
+		queue.SwapOrders(old_order, 0);
+		return 0;
+	}
+}
+
 void
 playlist::PlayPosition(PlayerControl &pc, int song)
 {
@@ -90,13 +114,7 @@ playlist::PlayPosition(PlayerControl &pc, int song)
 			   number, because random mode is enabled */
 			i = queue.PositionToOrder(song);
 
-		if (!playing)
-			current = 0;
-
-		/* swap the new song with the previous "current" one,
-		   so playback continues as planned */
-		queue.SwapOrders(i, current);
-		i = current;
+		i = MoveOrderToCurrent(i);
 	}
 
 	stop_on_error = false;
@@ -205,6 +223,8 @@ playlist::SeekSongOrder(PlayerControl &pc, unsigned i, SongTime seek_time)
 		/* seeking is not within the current song - prepare
 		   song change */
 
+		i = MoveOrderToCurrent(i);
+
 		playing = true;
 		current = i;
 
diff --git a/src/queue/Queue.cxx b/src/queue/Queue.cxx
index d248f30..7207780 100644
--- a/src/queue/Queue.cxx
+++ b/src/queue/Queue.cxx
@@ -195,7 +195,7 @@ Queue::MoveRange(unsigned start, unsigned end, unsigned to) noexcept
 	}
 }
 
-void
+unsigned
 Queue::MoveOrder(unsigned from_order, unsigned to_order) noexcept
 {
 	assert(from_order < length);
@@ -212,6 +212,25 @@ Queue::MoveOrder(unsigned from_order, unsigned to_order) noexcept
 	}
 
 	order[to_order] = from_position;
+	return to_order;
+}
+
+unsigned
+Queue::MoveOrderBefore(unsigned from_order, unsigned to_order) noexcept
+{
+	/* if "from_order" comes before "to_order", then the new
+	   position is "to_order-1"; otherwise the "to_order" song is
+	   moved one ahead */
+	return MoveOrder(from_order, to_order - (from_order < to_order));
+}
+
+unsigned
+Queue::MoveOrderAfter(unsigned from_order, unsigned to_order) noexcept
+{
+	/* if "from_order" comes after "to_order", then the new
+	   position is "to_order+1"; otherwise the "to_order" song is
+	   moved one back */
+	return MoveOrder(from_order, to_order + (from_order > to_order));
 }
 
 void
diff --git a/src/queue/Queue.hxx b/src/queue/Queue.hxx
index bd2f95c..06e8004 100644
--- a/src/queue/Queue.hxx
+++ b/src/queue/Queue.hxx
@@ -284,8 +284,28 @@ struct Queue {
 
 	/**
 	 * Moves a song to a new position in the "order" list.
+	 *
+	 * @return to_order
+	 */
+	unsigned MoveOrder(unsigned from_order, unsigned to_order) noexcept;
+
+	/**
+	 * Moves a song to a new position in the "order" list before
+	 * the given one.
+	 *
+	 * @return the new order number of the given "from" song
+	 */
+	unsigned MoveOrderBefore(unsigned from_order,
+				 unsigned to_order) noexcept;
+
+	/**
+	 * Moves a song to a new position in the "order" list after
+	 * the given one.
+	 *
+	 * @return the new order number of the given "from" song
 	 */
-	void MoveOrder(unsigned from_order, unsigned to_order) noexcept;
+	unsigned MoveOrderAfter(unsigned from_order,
+				unsigned to_order) noexcept;
 
 	/**
 	 * Moves a song to a new position.
diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx
index d4177e4..85863cb 100644
--- a/src/storage/plugins/CurlStorage.cxx
+++ b/src/storage/plugins/CurlStorage.cxx
@@ -247,6 +247,22 @@ ParseU64(const char *s, size_t length)
 	return ParseU64(std::string(s, length).c_str());
 }
 
+gcc_pure
+static bool
+IsXmlContentType(const char *content_type) noexcept
+{
+	return StringStartsWith(content_type, "text/xml") ||
+		StringStartsWith(content_type, "application/xml");
+}
+
+gcc_pure
+static bool
+IsXmlContentType(const std::multimap<std::string, std::string> &headers) noexcept
+{
+	auto i = headers.find("content-type");
+	return i != headers.end() && IsXmlContentType(i->second.c_str());
+}
+
 /**
  * A WebDAV PROPFIND request.  Each "response" element will be passed
  * to OnDavResponse() (to be implemented by a derived class).
@@ -308,9 +324,7 @@ private:
 			throw FormatRuntimeError("Status %d from WebDAV server; expected \"207 Multi-Status\"",
 						 status);
 
-		auto i = headers.find("content-type");
-		if (i == headers.end() ||
-		    strncmp(i->second.c_str(), "text/xml", 8) != 0)
+		if (!IsXmlContentType(headers))
 			throw std::runtime_error("Unexpected Content-Type from WebDAV server");
 	}
 
diff --git a/src/tag/Aiff.cxx b/src/tag/Aiff.cxx
index faa47f6..b6a7aa7 100644
--- a/src/tag/Aiff.cxx
+++ b/src/tag/Aiff.cxx
@@ -49,7 +49,7 @@ aiff_seek_id3(InputStream &is)
 	aiff_header header;
 	is.ReadFull(&header, sizeof(header));
 	if (memcmp(header.id, "FORM", 4) != 0 ||
-	    (is.KnownSize() && FromLE32(header.size) > is.GetSize()) ||
+	    (is.KnownSize() && FromBE32(header.size) > is.GetSize()) ||
 	    (memcmp(header.format, "AIFF", 4) != 0 &&
 	     memcmp(header.format, "AIFC", 4) != 0))
 		throw std::runtime_error("Not an AIFF file");
diff --git a/src/lib/icu/Collate.hxx b/src/tag/Id3MusicBrainz.cxx
similarity index 60%
copy from src/lib/icu/Collate.hxx
copy to src/tag/Id3MusicBrainz.cxx
index d6cfcb7..d0de427 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/tag/Id3MusicBrainz.cxx
@@ -17,29 +17,18 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef MPD_ICU_COLLATE_HXX
-#define MPD_ICU_COLLATE_HXX
-
-#include "check.h"
-#include "Compiler.h"
-
-template<typename T> class AllocatedString;
-
-/**
- * Throws #std::runtime_error on error.
- */
-void
-IcuCollateInit();
-
-void
-IcuCollateFinish() noexcept;
-
-gcc_pure gcc_nonnull_all
-int
-IcuCollate(const char *a, const char *b) noexcept;
-
-gcc_nonnull_all
-AllocatedString<char>
-IcuCaseFold(const char *src);
-
-#endif
+#include "Id3MusicBrainz.hxx"
+#include "TagTable.hxx"
+#include "TagType.h"
+
+const struct tag_table musicbrainz_txxx_tags[] = {
+	{ "ALBUMARTISTSORT", TAG_ALBUM_ARTIST_SORT },
+	{ "MusicBrainz Artist Id", TAG_MUSICBRAINZ_ARTISTID },
+	{ "MusicBrainz Album Id", TAG_MUSICBRAINZ_ALBUMID },
+	{ "MusicBrainz Album Artist Id",
+	  TAG_MUSICBRAINZ_ALBUMARTISTID },
+	{ "MusicBrainz Track Id", TAG_MUSICBRAINZ_TRACKID },
+	{ "MusicBrainz Release Track Id",
+	  TAG_MUSICBRAINZ_RELEASETRACKID },
+	{ nullptr, TAG_NUM_OF_ITEM_TYPES }
+};
diff --git a/src/output/plugins/OSXOutputPlugin.hxx b/src/tag/Id3MusicBrainz.hxx
similarity index 86%
copy from src/output/plugins/OSXOutputPlugin.hxx
copy to src/tag/Id3MusicBrainz.hxx
index 440cb8d..bbdfc4b 100644
--- a/src/output/plugins/OSXOutputPlugin.hxx
+++ b/src/tag/Id3MusicBrainz.hxx
@@ -17,9 +17,9 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef MPD_OSX_OUTPUT_PLUGIN_HXX
-#define MPD_OSX_OUTPUT_PLUGIN_HXX
+#ifndef MPD_TAG_ID3MUSICBRAINZ_HXX
+#define MPD_TAG_ID3MUSICBRAINZ_HXX
 
-extern const struct AudioOutputPlugin osx_output_plugin;
+extern const struct tag_table musicbrainz_txxx_tags[];
 
 #endif
diff --git a/src/tag/TagId3.cxx b/src/tag/TagId3.cxx
index 14ce2c3..8326968 100644
--- a/src/tag/TagId3.cxx
+++ b/src/tag/TagId3.cxx
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "TagId3.hxx"
 #include "Id3Load.hxx"
+#include "Id3MusicBrainz.hxx"
 #include "TagHandler.hxx"
 #include "TagTable.hxx"
 #include "TagBuilder.hxx"
@@ -205,19 +206,8 @@ gcc_pure
 static TagType
 tag_id3_parse_txxx_name(const char *name) noexcept
 {
-	static constexpr struct tag_table txxx_tags[] = {
-		{ "ALBUMARTISTSORT", TAG_ALBUM_ARTIST_SORT },
-		{ "MusicBrainz Artist Id", TAG_MUSICBRAINZ_ARTISTID },
-		{ "MusicBrainz Album Id", TAG_MUSICBRAINZ_ALBUMID },
-		{ "MusicBrainz Album Artist Id",
-		  TAG_MUSICBRAINZ_ALBUMARTISTID },
-		{ "MusicBrainz Track Id", TAG_MUSICBRAINZ_TRACKID },
-		{ "MusicBrainz Release Track Id",
-		  TAG_MUSICBRAINZ_RELEASETRACKID },
-		{ nullptr, TAG_NUM_OF_ITEM_TYPES }
-	};
-
-	return tag_table_lookup(txxx_tags, name);
+
+	return tag_table_lookup(musicbrainz_txxx_tags, name);
 }
 
 /**
diff --git a/src/util/FormatString.cxx b/src/util/FormatString.cxx
index 00a2083..b5ea4d0 100644
--- a/src/util/FormatString.cxx
+++ b/src/util/FormatString.cxx
@@ -57,7 +57,7 @@ FormatStringV(const char *fmt, va_list args)
 	const size_t length = strlen(buffer);
 	char *p = new char[length + 1];
 	memcpy(p, buffer, length + 1);
-	return AllocatedString<>::Donate(buffer);
+	return AllocatedString<>::Donate(p);
 #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