Hello community, here is the log from the commit of package mpd for openSUSE:Factory checked in at 2020-04-27 23:34:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mpd (Old) and /work/SRC/openSUSE:Factory/.mpd.new.2738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mpd" Mon Apr 27 23:34:24 2020 rev:20 rq:797726 version:0.21.23 Changes: -------- --- /work/SRC/openSUSE:Factory/mpd/mpd.changes 2020-04-05 20:55:58.705341844 +0200 +++ /work/SRC/openSUSE:Factory/.mpd.new.2738/mpd.changes 2020-04-27 23:34:41.007090530 +0200 @@ -1,0 +2,16 @@ +Sat Apr 25 18:01:18 UTC 2020 - Илья Индиго <i...@ilya.pp.ua> + +- Update to 0.21.23 + * https://raw.githubusercontent.com/MusicPlayerDaemon/MPD/v0.21.23/NEWS + * protocol: add tag fallback for AlbumSort + * storage + * curl: fix corrupt "href" values in the presence of XML entities + * curl: unescape "href" values + * input + * nfs: fix crash bug + * nfs: fix freeze bug on reconnect + * decoder: gme: adapt to API change in the upcoming version 0.7.0 + * output: alsa: implement channel mapping for 5.0 and 7.0 + * player: drain: outputs at end of song in "single" mode + +------------------------------------------------------------------- Old: ---- mpd-0.21.22.tar.xz New: ---- mpd-0.21.23.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mpd.spec ++++++ --- /var/tmp/diff_new_pack.IpNRmZ/_old 2020-04-27 23:34:42.103092669 +0200 +++ /var/tmp/diff_new_pack.IpNRmZ/_new 2020-04-27 23:34:42.107092678 +0200 @@ -20,7 +20,7 @@ %bcond_with faad %bcond_without mpd_iso9660 Name: mpd -Version: 0.21.22 +Version: 0.21.23 Release: 0 Summary: Music Player Daemon License: GPL-2.0-or-later ++++++ mpd-0.21.22.tar.xz -> mpd-0.21.23.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/NEWS new/mpd-0.21.23/NEWS --- old/mpd-0.21.22/NEWS 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/NEWS 2020-04-23 17:46:20.000000000 +0200 @@ -1,3 +1,21 @@ +ver 0.21.23 (2020/04/23) +* protocol + - add tag fallback for AlbumSort +* storage + - curl: fix corrupt "href" values in the presence of XML entities + - curl: unescape "href" values +* input + - nfs: fix crash bug + - nfs: fix freeze bug on reconnect +* decoder + - gme: adapt to API change in the upcoming version 0.7.0 +* output + - alsa: implement channel mapping for 5.0 and 7.0 +* player + - drain outputs at end of song in "single" mode +* Windows + - fix case insensitive search + ver 0.21.22 (2020/04/02) * database - simple: optimize startup diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/android/AndroidManifest.xml new/mpd-0.21.23/android/AndroidManifest.xml --- old/mpd-0.21.22/android/AndroidManifest.xml 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/android/AndroidManifest.xml 2020-04-23 17:46:20.000000000 +0200 @@ -2,8 +2,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.musicpd" android:installLocation="auto" - android:versionCode="45" - android:versionName="0.21.22"> + android:versionCode="46" + android:versionName="0.21.23"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/doc/conf.py new/mpd-0.21.23/doc/conf.py --- old/mpd-0.21.22/doc/conf.py 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/doc/conf.py 2020-04-23 17:46:20.000000000 +0200 @@ -38,7 +38,7 @@ # built documents. # # The short X.Y version. -version = '0.21.22' +version = '0.21.23' # The full version, including alpha/beta/rc tags. release = version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/meson.build new/mpd-0.21.23/meson.build --- old/mpd-0.21.22/meson.build 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/meson.build 2020-04-23 17:46:20.000000000 +0200 @@ -1,7 +1,7 @@ project( 'mpd', ['c', 'cpp'], - version: '0.21.22', + version: '0.21.23', meson_version: '>= 0.49.0', default_options: [ 'c_std=c99', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/decoder/plugins/GmeDecoderPlugin.cxx new/mpd-0.21.23/src/decoder/plugins/GmeDecoderPlugin.cxx --- old/mpd-0.21.22/src/decoder/plugins/GmeDecoderPlugin.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/decoder/plugins/GmeDecoderPlugin.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -185,7 +185,11 @@ LogWarning(gme_domain, gme_err); if (length > 0) - gme_set_fade(emu, length); + gme_set_fade(emu, length +#if GME_VERSION >= 0x000700 + , 8000 +#endif + ); /* play */ DecoderCommand cmd; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/event/PollGroupWinSelect.cxx new/mpd-0.21.23/src/event/PollGroupWinSelect.cxx --- old/mpd-0.21.22/src/event/PollGroupWinSelect.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/event/PollGroupWinSelect.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -23,8 +23,8 @@ #include "PollGroupWinSelect.hxx" -constexpr int EVENT_READ = 0; -constexpr int EVENT_WRITE = 1; +static constexpr int EVENT_READ = 0; +static constexpr int EVENT_WRITE = 1; static constexpr bool HasEvent(unsigned events, int event_id) noexcept diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/event/SocketMonitor.cxx new/mpd-0.21.23/src/event/SocketMonitor.cxx --- old/mpd-0.21.22/src/event/SocketMonitor.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/event/SocketMonitor.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -20,6 +20,10 @@ #include "SocketMonitor.hxx" #include "Loop.hxx" +#ifdef USE_EPOLL +#include <cerrno> +#endif + #include <assert.h> #ifdef _WIN32 @@ -86,6 +90,21 @@ if (success) scheduled_flags = flags; +#ifdef USE_EPOLL + else if (errno == EBADF || errno == ENOENT) + /* the socket was probably closed by somebody else + (EBADF) or a new file descriptor with the same + number was created but not registered already + (ENOENT) - we can assume that there are no + scheduled events */ + /* note that when this happens, we're actually lucky + that it has failed - imagine another thread may + meanwhile have created something on the same file + descriptor number, and has registered it; the + epoll_ctl() call above would then have succeeded, + but broke the other thread's epoll registration */ + scheduled_flags = 0; +#endif return success; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/event/SocketMonitor.hxx new/mpd-0.21.23/src/event/SocketMonitor.hxx --- old/mpd-0.21.22/src/event/SocketMonitor.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/event/SocketMonitor.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -109,7 +109,7 @@ } bool ScheduleRead() noexcept { - return Schedule(GetScheduledFlags() | READ | HANGUP | ERROR); + return Schedule(GetScheduledFlags() | READ); } bool ScheduleWrite() noexcept { @@ -117,7 +117,7 @@ } void CancelRead() noexcept { - Schedule(GetScheduledFlags() & ~(READ|HANGUP|ERROR)); + Schedule(GetScheduledFlags() & ~READ); } void CancelWrite() noexcept { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/fs/NarrowPath.hxx new/mpd-0.21.23/src/fs/NarrowPath.hxx --- old/mpd-0.21.22/src/fs/NarrowPath.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/fs/NarrowPath.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -90,6 +90,11 @@ constexpr #endif operator Path() const noexcept { +#ifdef _UNICODE + if (value.IsNull()) + return nullptr; +#endif + return value; } }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/icu/CaseFold.cxx new/mpd-0.21.23/src/lib/icu/CaseFold.cxx --- old/mpd-0.21.22/src/lib/icu/CaseFold.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/icu/CaseFold.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -36,11 +36,6 @@ #include <ctype.h> #endif -#ifdef _WIN32 -#include "Win32.hxx" -#include <windows.h> -#endif - #include <memory> #include <assert.h> @@ -72,25 +67,6 @@ 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 #error not implemented #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/icu/CaseFold.hxx new/mpd-0.21.23/src/lib/icu/CaseFold.hxx --- old/mpd-0.21.22/src/lib/icu/CaseFold.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/icu/CaseFold.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -22,7 +22,7 @@ #include "config.h" -#if defined(HAVE_ICU) || defined(_WIN32) +#ifdef HAVE_ICU #define HAVE_ICU_CASE_FOLD #include "util/Compiler.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/icu/Collate.cxx new/mpd-0.21.23/src/lib/icu/Collate.cxx --- old/mpd-0.21.22/src/lib/icu/Collate.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/icu/Collate.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -109,7 +109,7 @@ } auto result = CompareStringEx(LOCALE_NAME_INVARIANT, - LINGUISTIC_IGNORECASE, + NORM_IGNORECASE, wa.c_str(), -1, wb.c_str(), -1, nullptr, nullptr, 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/icu/Compare.cxx new/mpd-0.21.23/src/lib/icu/Compare.cxx --- old/mpd-0.21.22/src/lib/icu/Compare.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/icu/Compare.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -22,6 +22,11 @@ #include "util/StringAPI.hxx" #include "config.h" +#ifdef _WIN32 +#include "Win32.hxx" +#include <windows.h> +#endif + #include <string.h> #ifdef HAVE_ICU_CASE_FOLD @@ -29,6 +34,17 @@ IcuCompare::IcuCompare(const char *_needle) noexcept :needle(IcuCaseFold(_needle)) {} +#elif defined(_WIN32) + +IcuCompare::IcuCompare(const char *_needle) noexcept + :needle(nullptr) +{ + try { + needle = MultiByteToWideChar(CP_UTF8, _needle); + } catch (...) { + } +} + #else IcuCompare::IcuCompare(const char *_needle) noexcept @@ -41,6 +57,22 @@ { #ifdef HAVE_ICU_CASE_FOLD return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str()); +#elif defined(_WIN32) + if (needle.IsNull()) + /* the MultiByteToWideChar() call in the constructor + has failed, so let's always fail the comparison */ + return false; + + try { + auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack); + return CompareStringEx(LOCALE_NAME_INVARIANT, + NORM_IGNORECASE, + w_haystack.c_str(), -1, + needle.c_str(), -1, + nullptr, nullptr, 0) == CSTR_EQUAL; + } catch (...) { + return false; + } #else return strcasecmp(haystack, needle.c_str()); #endif @@ -52,6 +84,24 @@ #ifdef HAVE_ICU_CASE_FOLD return StringFind(IcuCaseFold(haystack).c_str(), needle.c_str()) != nullptr; +#elif defined(_WIN32) + if (needle.IsNull()) + /* the MultiByteToWideChar() call in the constructor + has failed, so let's always fail the comparison */ + return false; + + try { + auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack); + return FindNLSStringEx(LOCALE_NAME_INVARIANT, + FIND_FROMSTART|NORM_IGNORECASE, + w_haystack.c_str(), -1, + needle.c_str(), -1, + nullptr, + nullptr, nullptr, 0) >= 0; + } catch (...) { + /* MultiByteToWideChar() has failed */ + return false; + } #elif defined(HAVE_STRCASESTR) return strcasestr(haystack, needle.c_str()) != nullptr; #else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/icu/Compare.hxx new/mpd-0.21.23/src/lib/icu/Compare.hxx --- old/mpd-0.21.22/src/lib/icu/Compare.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/icu/Compare.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -23,13 +23,23 @@ #include "util/Compiler.h" #include "util/AllocatedString.hxx" +#ifdef _WIN32 +#include <wchar.h> +#endif + /** * 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. */ class IcuCompare { +#ifdef _WIN32 + /* Windows API functions work with wchar_t strings, so let's + cache the MultiByteToWideChar() result for performance */ + AllocatedString<wchar_t> needle; +#else AllocatedString<> needle; +#endif public: IcuCompare():needle(nullptr) {} @@ -38,12 +48,12 @@ IcuCompare(const IcuCompare &src) noexcept :needle(src - ? AllocatedString<>::Duplicate(src.needle.c_str()) + ? src.needle.Clone() : nullptr) {} IcuCompare &operator=(const IcuCompare &src) noexcept { needle = src - ? AllocatedString<>::Duplicate(src.needle.c_str()) + ? src.needle.Clone() : nullptr; return *this; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/nfs/Connection.cxx new/mpd-0.21.23/src/lib/nfs/Connection.cxx --- old/mpd-0.21.22/src/lib/nfs/Connection.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/nfs/Connection.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -191,7 +191,9 @@ events_to_libnfs(unsigned i) noexcept { return ((i & SocketMonitor::READ) ? POLLIN : 0) | - ((i & SocketMonitor::WRITE) ? POLLOUT : 0); + ((i & SocketMonitor::WRITE) ? POLLOUT : 0) | + ((i & SocketMonitor::HANGUP) ? POLLHUP : 0) | + ((i & SocketMonitor::ERROR) ? POLLERR : 0); } NfsConnection::~NfsConnection() noexcept @@ -450,8 +452,7 @@ SocketMonitor::Open(_fd); } - SocketMonitor::Schedule(libnfs_to_events(which_events) - | SocketMonitor::HANGUP); + SocketMonitor::Schedule(libnfs_to_events(which_events)); } inline int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/lib/nfs/FileReader.cxx new/mpd-0.21.23/src/lib/nfs/FileReader.cxx --- old/mpd-0.21.22/src/lib/nfs/FileReader.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/lib/nfs/FileReader.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -180,7 +180,6 @@ inline void NfsFileReader::OpenCallback(nfsfh *_fh) noexcept { - assert(state == State::OPEN); assert(connection != nullptr); assert(_fh != nullptr); @@ -197,27 +196,33 @@ } inline void -NfsFileReader::StatCallback(const struct stat *st) noexcept +NfsFileReader::StatCallback(const struct stat *_st) noexcept { - assert(state == State::STAT); assert(connection != nullptr); assert(fh != nullptr); - assert(st != nullptr); + assert(_st != nullptr); + +#if defined(_WIN32) && !defined(_WIN64) + /* on 32-bit Windows, libnfs enables -D_FILE_OFFSET_BITS=64, + but MPD (Meson) doesn't - to work around this mismatch, we + cast explicitly to "struct stat64" */ + const auto *st = (const struct stat64 *)_st; +#else + const auto *st = _st; +#endif if (!S_ISREG(st->st_mode)) { OnNfsFileError(std::make_exception_ptr(std::runtime_error("Not a regular file"))); return; } - state = State::IDLE; - OnNfsFileOpen(st->st_size); } void NfsFileReader::OnNfsCallback(unsigned status, void *data) noexcept { - switch (state) { + switch (std::exchange(state, State::IDLE)) { case State::INITIAL: case State::DEFER: case State::MOUNT: @@ -234,7 +239,6 @@ break; case State::READ: - state = State::IDLE; OnNfsFileRead(data, status); break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/pcm/Order.cxx new/mpd-0.21.23/src/pcm/Order.cxx --- old/mpd-0.21.22/src/pcm/Order.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/pcm/Order.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -21,6 +21,28 @@ #include "PcmBuffer.hxx" #include "util/ConstBuffer.hxx" + +/* + * According to: + * - https://xiph.org/flac/format.html#frame_header + * - https://github.com/nu774/qaac/wiki/Multichannel--handling + * the source channel order (after decoding, e.g., flac, alac) is for + * - 1ch: mono + * - 2ch: left, right + * - 3ch: left, right, center + * - 4ch: front left, front right, back left, back right + * - 5ch: front left, front right, front center, back/surround left, back/surround right + * - 6ch (aka 5.1): front left, front right, front center, LFE, back/surround left, back/surround right + * - 7ch: front left, front right, front center, LFE, back center, side left, side right + * - 8ch: (aka 7.1): front left, front right, front center, LFE, back left, back right, side left, side right + * + * The ALSA default channel map is (see /usr/share/alsa/pcm/surround71.conf): + * - front left, front right, back left, back right, front center, LFE, side left, side right + * + * Hence, in case of the following source channel orders 3ch, 5ch, 6ch (aka + * 5.1), 7ch and 8ch the channel order has to be adapted + */ + template<typename V> struct TwoPointers { V *dest; @@ -44,11 +66,33 @@ return *this; } + TwoPointers<V> &ToAlsa50() noexcept { + *dest++ = src[0]; // front left + *dest++ = src[1]; // front right + *dest++ = src[3]; // surround left + *dest++ = src[4]; // surround right + *dest++ = src[2]; // front center + src += 5; + return *this; + } + TwoPointers<V> &ToAlsa51() noexcept { return CopyTwo() // left+right .SwapTwoPairs(); // center, LFE, surround left+right } + TwoPointers<V> &ToAlsa70() noexcept { + *dest++ = src[0]; // front left + *dest++ = src[1]; // front right + *dest++ = src[5]; // side left + *dest++ = src[6]; // side right + *dest++ = src[2]; // front center + *dest++ = src[3]; // LFE + *dest++ = src[4]; // back center + src += 7; + return *this; + } + TwoPointers<V> &ToAlsa71() noexcept { return ToAlsa51() .CopyTwo(); // side left+right @@ -57,6 +101,24 @@ template<typename V> static void +ToAlsaChannelOrder50(V *dest, const V *src, size_t n) noexcept +{ + TwoPointers<V> p{dest, src}; + for (size_t i = 0; i != n; ++i) + p.ToAlsa50(); +} + +template<typename V> +static inline ConstBuffer<V> +ToAlsaChannelOrder50(PcmBuffer &buffer, ConstBuffer<V> src) noexcept +{ + auto dest = buffer.GetT<V>(src.size); + ToAlsaChannelOrder50(dest, src.data, src.size / 5); + return { dest, src.size }; +} + +template<typename V> +static void ToAlsaChannelOrder51(V *dest, const V *src, size_t n) noexcept { TwoPointers<V> p{dest, src}; @@ -75,6 +137,24 @@ template<typename V> static void +ToAlsaChannelOrder70(V *dest, const V *src, size_t n) noexcept +{ + TwoPointers<V> p{dest, src}; + for (size_t i = 0; i != n; ++i) + p.ToAlsa70(); +} + +template<typename V> +static inline ConstBuffer<V> +ToAlsaChannelOrder70(PcmBuffer &buffer, ConstBuffer<V> src) noexcept +{ + auto dest = buffer.GetT<V>(src.size); + ToAlsaChannelOrder70(dest, src.data, src.size / 7); + return { dest, src.size }; +} + +template<typename V> +static void ToAlsaChannelOrder71(V *dest, const V *src, size_t n) noexcept { TwoPointers<V> p{dest, src}; @@ -97,9 +177,15 @@ unsigned channels) noexcept { switch (channels) { + case 5: // 5.0 + return ToAlsaChannelOrder50(buffer, src); + case 6: // 5.1 return ToAlsaChannelOrder51(buffer, src); + case 7: // 7.0 + return ToAlsaChannelOrder70(buffer, src); + case 8: // 7.1 return ToAlsaChannelOrder71(buffer, src); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/player/CrossFade.cxx new/mpd-0.21.23/src/player/CrossFade.cxx --- old/mpd-0.21.22/src/player/CrossFade.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/player/CrossFade.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -62,7 +62,7 @@ ++ramp_list; /* Check for exact match. */ - if (db == required_db) { + if (db >= required_db) { return duration; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/player/Thread.cxx new/mpd-0.21.23/src/player/Thread.cxx --- old/mpd-0.21.22/src/player/Thread.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/player/Thread.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -964,6 +964,12 @@ if (border_pause) { paused = true; pc.listener.OnBorderPause(); + + /* drain all outputs to guarantee the current song is + really being played to the end; without this, the + Pause() call would drop all ring buffers */ + pc.outputs.Drain(); + pc.outputs.Pause(); idle_add(IDLE_PLAYER); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/storage/plugins/CurlStorage.cxx new/mpd-0.21.23/src/storage/plugins/CurlStorage.cxx --- old/mpd-0.21.22/src/storage/plugins/CurlStorage.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/storage/plugins/CurlStorage.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -402,7 +402,7 @@ break; case State::HREF: - response.href.assign(s, len); + response.href.append(s, len); break; case State::STATUS: @@ -482,7 +482,7 @@ public: HttpListDirectoryOperation(CurlGlobal &curl, const char *uri) :PropfindOperation(curl, uri, 1), - base_path(UriPathOrSlash(uri)) {} + base_path(CurlUnescape(GetEasy(), UriPathOrSlash(uri))) {} std::unique_ptr<StorageDirectoryReader> Perform() { DeferStart(); @@ -507,8 +507,7 @@ /* kludge: ignoring case in this comparison to avoid false negatives if the web server uses a different - case in hex digits in escaped characters; TODO: - implement properly */ + case */ path = StringAfterPrefixIgnoreCase(path, base_path.c_str()); if (path == nullptr || *path == 0) return nullptr; @@ -531,11 +530,12 @@ if (r.status != 200) return; - const auto escaped_name = HrefToEscapedName(r.href.c_str()); - if (escaped_name.IsNull()) + std::string href = CurlUnescape(GetEasy(), r.href.c_str()); + const auto name = HrefToEscapedName(href.c_str()); + if (name.IsNull()) return; - entries.emplace_front(CurlUnescape(GetEasy(), escaped_name)); + entries.emplace_front(std::string(name.data, name.size)); auto &info = entries.front().info; info = StorageFileInfo(r.collection diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/tag/Fallback.hxx new/mpd-0.21.23/src/tag/Fallback.hxx --- old/mpd-0.21.22/src/tag/Fallback.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/tag/Fallback.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -45,6 +45,10 @@ "AlbumArtist"/"ArtistSort" was found */ return f(TAG_ARTIST); + if (type == TAG_ALBUM_SORT) + /* fall back to "Album" if no "AlbumSort" was found */ + return f(TAG_ALBUM); + return false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/util/Math.hxx new/mpd-0.21.23/src/util/Math.hxx --- old/mpd-0.21.22/src/util/Math.hxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/util/Math.hxx 2020-04-23 17:46:20.000000000 +0200 @@ -30,11 +30,16 @@ #ifndef MATH_HXX #define MATH_HXX +#include <cmath> + +/* + * C99 math can be optionally omitted with gcc's libstdc++. + * Use boost if unavailable. + */ #if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) && !defined(_GLIBCXX_USE_C99_MATH) #include <boost/math/special_functions/round.hpp> using boost::math::lround; #else -#include <cmath> using std::lround; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpd-0.21.22/src/zeroconf/AvahiPoll.cxx new/mpd-0.21.23/src/zeroconf/AvahiPoll.cxx --- old/mpd-0.21.22/src/zeroconf/AvahiPoll.cxx 2020-04-02 17:48:56.000000000 +0200 +++ new/mpd-0.21.23/src/zeroconf/AvahiPoll.cxx 2020-04-23 17:46:20.000000000 +0200 @@ -26,9 +26,7 @@ FromAvahiWatchEvent(AvahiWatchEvent e) { return (e & AVAHI_WATCH_IN ? SocketMonitor::READ : 0) | - (e & AVAHI_WATCH_OUT ? SocketMonitor::WRITE : 0) | - (e & AVAHI_WATCH_ERR ? SocketMonitor::ERROR : 0) | - (e & AVAHI_WATCH_HUP ? SocketMonitor::HANGUP : 0); + (e & AVAHI_WATCH_OUT ? SocketMonitor::WRITE : 0); } static AvahiWatchEvent