release v0.20.17

-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAlqAMO0QHG1heEBtdXNp
 Y3BkLm9yZwAKCRAjbopYxttFEg8eD/49NlFvlNdkamgYvh7MI1Sn67yKAwQt+N51
 W0hVnmXwPoSg76gfWw8J9kVyQy/jEkaCxsPF/UuEbH5jzqAC0y8hwYVRkJaRc9wN
 ZfwHvLHeaUxQweoguEwRSREy4ZC4ImQOK+eAxI1R43mqxxyhko1Akc1NmRVWzYfv
 /FGmAjTi1U6FR/yDpdSFn1NdlPmIgZ4WDuRsDT2NrshX/Bb32FiyZBytvek2P8n/
 QNgXv18E4yWXSb+zBYhPy/eaKhGasyjI3cbht1F0hNW9Yo/BsFxDuwXrX1vNBaOS
 E3Dux4s/nfcJ4RMRjmrkFwXImCvxt7+AGfh8RYBXuwqMExXz2kZjIs4ZVvO7Nu9A
 pFDJQwRIojXMfk73LU/MEpmNNEXhvfQLYkrM7poSqYaOr8SWMszqSgNnnfq6+flB
 sJbstgAStI6lL0jy0HrtMTvPVEiAGh6wCvMy/r2G9XUAyw76ccOg7MaIldn0MHJv
 A51+GfRTi4ILH0ReL1BGAg9nG97uFmRAWGkfkhtyD540xGRk7x5R8/ml4zFogHN6
 SbrV0NPdwk+uFd0y2znQT2gWyjc0id4WEKEoHX+Gl6c5qtPIfrq+PQPyk9kR+u+i
 AxwqMoKQer6Ji5qnsvCiKSkaGGiVNivrZ11jDWNCZaKjmvlKlvj/P5GxbPpORorq
 v4ru/4vNXQ==
 =v4t8
 -----END PGP SIGNATURE-----

Merge tag 'v0.20.17'

release v0.20.17
This commit is contained in:
Max Kellermann 2018-02-11 13:22:43 +01:00
commit 65bbb0e0aa
21 changed files with 150 additions and 24 deletions

9
NEWS
View File

@ -25,6 +25,15 @@ ver 0.21 (not yet released)
- sndio: new mixer plugin - sndio: new mixer plugin
* require GCC 5.0 * require GCC 5.0
ver 0.20.17 (2018/02/11)
* output
- alsa: fix crash bug with 8 channels
* mixer
- alsa: fix rounding error at volume 0
* fix real-time and idle scheduling with Musl
* Android
- fix compatibility with Android 4.0
ver 0.20.16 (2018/02/03) ver 0.20.16 (2018/02/03)
* output * output
- pulse: fix crash during auto-detection - pulse: fix crash during auto-detection

View File

@ -2,10 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.musicpd" package="org.musicpd"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="15" android:versionCode="16"
android:versionName="0.20.16"> android:versionName="0.20.17">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17"/> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17"/>
<application android:icon="@drawable/icon" android:label="@string/app_name"> <application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main" <activity android:name=".Main"

View File

@ -46,7 +46,7 @@ class AndroidNdkToolchain:
self.ndk_arch = 'arm' self.ndk_arch = 'arm'
android_abi = 'armeabi-v7a' android_abi = 'armeabi-v7a'
ndk_platform = 'android-21' ndk_platform = 'android-14'
# select the NDK compiler # select the NDK compiler
gcc_version = '4.9' gcc_version = '4.9'
@ -67,7 +67,7 @@ class AndroidNdkToolchain:
common_flags = '-Os -g' common_flags = '-Os -g'
common_flags += ' -fPIC' common_flags += ' -fPIC'
common_flags += ' -march=armv7-a -mfloat-abi=softfp' common_flags += ' -march=armv7-a -mfpu=vfp -mfloat-abi=softfp'
toolchain_bin = os.path.join(toolchain_path, 'bin') toolchain_bin = os.path.join(toolchain_path, 'bin')
llvm_bin = os.path.join(llvm_path, 'bin') llvm_bin = os.path.join(llvm_path, 'bin')
@ -87,7 +87,7 @@ class AndroidNdkToolchain:
self.cppflags = '--sysroot=' + sysroot + \ self.cppflags = '--sysroot=' + sysroot + \
' -isystem ' + os.path.join(install_prefix, 'include') + \ ' -isystem ' + os.path.join(install_prefix, 'include') + \
' -isystem ' + os.path.join(sysroot, 'usr', 'include', arch) + \ ' -isystem ' + os.path.join(sysroot, 'usr', 'include', arch) + \
' -D__ANDROID_API__=21' ' -D__ANDROID_API__=14'
self.ldflags = '--sysroot=' + sysroot + \ self.ldflags = '--sysroot=' + sysroot + \
' -L' + os.path.join(install_prefix, 'lib') + \ ' -L' + os.path.join(install_prefix, 'lib') + \
' -L' + os.path.join(target_root, 'usr', 'lib') + \ ' -L' + os.path.join(target_root, 'usr', 'lib') + \

View File

@ -66,6 +66,23 @@
</para> </para>
</section> </section>
<section id="install_android">
<title>Installing on Android</title>
<para>
An experimental Android build is available on <ulink
url="https://play.google.com/store/apps/details?id=org.musicpd">Google
Play</ulink>. After installing and launching it, MPD will
scan the music in your <filename>Music</filename> directory
and you can control it as usual with a MPD client.
</para>
<para>
If you need to tweak the configuration, you can create a file
called <filename>mpd.conf</filename> on the data partition.
</para>
</section>
<section id="install_source"> <section id="install_source">
<title>Compiling from source</title> <title>Compiling from source</title>
@ -323,7 +340,9 @@ systemctl start mpd.socket</programlisting>
<application>MPD</application> as a user daemon (and not as a <application>MPD</application> as a user daemon (and not as a
system daemon), the configuration is read from system daemon), the configuration is read from
<filename>$XDG_CONFIG_HOME/mpd/mpd.conf</filename> (usually <filename>$XDG_CONFIG_HOME/mpd/mpd.conf</filename> (usually
<filename>~/.config/mpd/mpd.conf</filename>). <filename>~/.config/mpd/mpd.conf</filename>). On Android,
<filename>mpd.conf</filename> will be loaded from the
top-level directory of the data partition.
</para> </para>
<para> <para>

View File

@ -1,4 +1,6 @@
import re import re
from os.path import abspath
from build.project import Project from build.project import Project
from build.zlib import ZlibProject from build.zlib import ZlibProject
from build.autotools import AutotoolsProject from build.autotools import AutotoolsProject
@ -358,6 +360,8 @@ curl = AutotoolsProject(
'--disable-crypto-auth', '--disable-ntlm-wb', '--disable-tls-srp', '--disable-cookies', '--disable-crypto-auth', '--disable-ntlm-wb', '--disable-tls-srp', '--disable-cookies',
'--without-ssl', '--without-gnutls', '--without-nss', '--without-libssh2', '--without-ssl', '--without-gnutls', '--without-nss', '--without-libssh2',
], ],
patches='src/lib/curl/patches',
) )
boost = BoostProject( boost = BoostProject(

View File

@ -3,10 +3,12 @@ import re
from build.download import download_and_verify from build.download import download_and_verify
from build.tar import untar from build.tar import untar
from build.quilt import push_all
class Project: class Project:
def __init__(self, url, md5, installed, name=None, version=None, def __init__(self, url, md5, installed, name=None, version=None,
base=None, base=None,
patches=None,
edits=None, edits=None,
use_cxx=False): use_cxx=False):
if base is None: if base is None:
@ -18,7 +20,7 @@ class Project:
self.base = base self.base = base
if name is None or version is None: if name is None or version is None:
m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?)$', self.base) m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*)$', self.base)
if name is None: name = m.group(1) if name is None: name = m.group(1)
if version is None: version = m.group(2) if version is None: version = m.group(2)
@ -29,6 +31,10 @@ class Project:
self.md5 = md5 self.md5 = md5
self.installed = installed self.installed = installed
if patches is not None:
srcdir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
patches = os.path.join(srcdir, patches)
self.patches = patches
self.edits = edits self.edits = edits
self.use_cxx = use_cxx self.use_cxx = use_cxx
@ -51,6 +57,9 @@ class Project:
parent_path = toolchain.build_path parent_path = toolchain.build_path
path = untar(self.download(toolchain), parent_path, self.base) path = untar(self.download(toolchain), parent_path, self.base)
if self.patches is not None:
push_all(toolchain, path, self.patches)
if self.edits is not None: if self.edits is not None:
for filename, function in self.edits.items(): for filename, function in self.edits.items():
with open(os.path.join(path, filename), 'r+t') as f: with open(os.path.join(path, filename), 'r+t') as f:

9
python/build/quilt.py Normal file
View File

@ -0,0 +1,9 @@
import subprocess
def run_quilt(toolchain, cwd, patches_path, *args):
env = dict(toolchain.env)
env['QUILT_PATCHES'] = patches_path
subprocess.check_call(['quilt'] + list(args), cwd=cwd, env=env)
def push_all(toolchain, src_path, patches_path):
run_quilt(toolchain, src_path, patches_path, 'push', '-a')

View File

@ -30,6 +30,7 @@
#include "util/ChronoUtil.hxx" #include "util/ChronoUtil.hxx"
#include "util/StringStrip.hxx" #include "util/StringStrip.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "util/NumberParser.hxx"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -98,7 +99,7 @@ song_load(TextFile &file, const char *uri)
if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) { if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) {
tag.AddItem(type, value); tag.AddItem(type, value);
} else if (strcmp(line, "Time") == 0) { } else if (strcmp(line, "Time") == 0) {
tag.SetDuration(SignedSongTime::FromS(atof(value))); tag.SetDuration(SignedSongTime::FromS(ParseDouble(value)));
} else if (strcmp(line, "Playlist") == 0) { } else if (strcmp(line, "Playlist") == 0) {
tag.SetHasPlaylist(strcmp(value, "yes") == 0); tag.SetHasPlaylist(strcmp(value, "yes") == 0);
} else if (strcmp(line, SONG_MTIME) == 0) { } else if (strcmp(line, SONG_MTIME) == 0) {

View File

@ -29,6 +29,7 @@
#include "Idle.hxx" #include "Idle.hxx"
#include "Log.hxx" #include "Log.hxx"
#include "thread/Thread.hxx" #include "thread/Thread.hxx"
#include "thread/Name.hxx"
#include "thread/Util.hxx" #include "thread/Util.hxx"
#ifndef NDEBUG #ifndef NDEBUG
@ -111,6 +112,8 @@ UpdateService::Task()
{ {
assert(walk != nullptr); assert(walk != nullptr);
SetThreadName("update");
if (!next.path_utf8.empty()) if (!next.path_utf8.empty())
FormatDebug(update_domain, "starting: %s", FormatDebug(update_domain, "starting: %s",
next.path_utf8.c_str()); next.path_utf8.c_str());

View File

@ -51,6 +51,7 @@ public:
void Set(const AudioFormat &_out_audio_format); void Set(const AudioFormat &_out_audio_format);
void Reset() noexcept override { void Reset() noexcept override {
if (IsActive())
state.Reset(); state.Reset();
} }

View File

@ -65,9 +65,12 @@ OpenFileInputStream(Path path,
throw FormatRuntimeError("Not a regular file: %s", throw FormatRuntimeError("Not a regular file: %s",
path.c_str()); path.c_str());
#if !defined(__BIONIC__) || __ANDROID_API__ >= 21
/* posix_fadvise() requires Android API 21 */
#ifdef POSIX_FADV_SEQUENTIAL #ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(reader.GetFD().Get(), (off_t)0, info.GetSize(), posix_fadvise(reader.GetFD().Get(), (off_t)0, info.GetSize(),
POSIX_FADV_SEQUENTIAL); POSIX_FADV_SEQUENTIAL);
#endif
#endif #endif
return std::make_unique<FileInputStream>(path.ToUTF8().c_str(), return std::make_unique<FileInputStream>(path.ToUTF8().c_str(),

View File

@ -0,0 +1,20 @@
Index: curl-7.58.0/lib/url.c
===================================================================
--- curl-7.58.0.orig/lib/url.c
+++ curl-7.58.0/lib/url.c
@@ -3503,6 +3503,7 @@ static CURLcode override_login(struct Cu
}
conn->bits.netrc = FALSE;
+#ifndef __BIONIC__
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
int ret = Curl_parsenetrc(conn->host.name,
userp, passwdp,
@@ -3524,6 +3525,7 @@ static CURLcode override_login(struct Cu
conn->bits.user_passwd = TRUE; /* enable user+password */
}
}
+#endif
return CURLE_OK;
}

View File

@ -0,0 +1,15 @@
Index: curl-7.58.0/Makefile.in
===================================================================
--- curl-7.58.0.orig/Makefile.in
+++ curl-7.58.0/Makefile.in
@@ -641,8 +641,8 @@ CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP)
$(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ) $(VC15_LIBVCXPROJ) $(VC15_SRCVCXPROJ)
bin_SCRIPTS = curl-config
-SUBDIRS = lib src
-DIST_SUBDIRS = $(SUBDIRS) tests packages scripts include docs
+SUBDIRS = lib
+DIST_SUBDIRS = $(SUBDIRS) include
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcurl.pc
LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \

View File

@ -0,0 +1,2 @@
only_lib.patch
no_netrc.patch

View File

@ -139,6 +139,13 @@ static int set_normalized_volume(snd_mixer_elem_t *elem,
return set_raw[ctl_dir](elem, value); return set_raw[ctl_dir](elem, value);
} }
/* two special cases to avoid rounding errors at 0% and
100% */
if (volume <= 0)
return set_dB[ctl_dir](elem, min, dir);
else if (volume >= 100)
return set_dB[ctl_dir](elem, max, dir);
if (use_linear_dB_scale(min, max)) { if (use_linear_dB_scale(min, max)) {
value = lrint_dir(volume * (max - min), dir) + min; value = lrint_dir(volume * (max - min), dir) + min;
return set_dB[ctl_dir](elem, value, dir); return set_dB[ctl_dir](elem, value, dir);

View File

@ -88,7 +88,7 @@ static inline ConstBuffer<V>
ToAlsaChannelOrder71(PcmBuffer &buffer, ConstBuffer<V> src) noexcept ToAlsaChannelOrder71(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
{ {
auto dest = buffer.GetT<V>(src.size); auto dest = buffer.GetT<V>(src.size);
ToAlsaChannelOrder71(dest, src.data, src.size / 6); ToAlsaChannelOrder71(dest, src.data, src.size / 8);
return { dest, src.size }; return { dest, src.size };
} }

View File

@ -21,6 +21,7 @@
#include "ArgParser.hxx" #include "ArgParser.hxx"
#include "Ack.hxx" #include "Ack.hxx"
#include "Chrono.hxx" #include "Chrono.hxx"
#include "util/NumberParser.hxx"
#include <stdlib.h> #include <stdlib.h>
@ -151,7 +152,7 @@ float
ParseCommandArgFloat(const char *s) ParseCommandArgFloat(const char *s)
{ {
char *endptr; char *endptr;
auto value = strtof(s, &endptr); auto value = ParseFloat(s, &endptr);
if (endptr == s || *endptr != 0) if (endptr == s || *endptr != 0)
throw FormatProtocolError(ACK_ERROR_ARG, throw FormatProtocolError(ACK_ERROR_ARG,
"Float expected: %s", s); "Float expected: %s", s);

View File

@ -35,6 +35,7 @@
#include "util/CharUtil.hxx" #include "util/CharUtil.hxx"
#include "util/StringAPI.hxx" #include "util/StringAPI.hxx"
#include "util/StringCompare.hxx" #include "util/StringCompare.hxx"
#include "util/NumberParser.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <string.h> #include <string.h>
@ -148,7 +149,7 @@ playlist_state_restore(const char *line, TextFile &file,
while ((line = file.ReadLine()) != nullptr) { while ((line = file.ReadLine()) != nullptr) {
const char *p; const char *p;
if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_TIME))) { if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_TIME))) {
seek_time = SongTime::FromS(atof(p)); seek_time = SongTime::FromS(ParseDouble(p));
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_REPEAT))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_REPEAT))) {
playlist.SetRepeat(pc, StringIsEqual(p, "1")); playlist.SetRepeat(pc, StringIsEqual(p, "1"));
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_SINGLE))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_SINGLE))) {
@ -158,12 +159,12 @@ playlist_state_restore(const char *line, TextFile &file,
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_CROSSFADE))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_CROSSFADE))) {
pc.SetCrossFade(atoi(p)); pc.SetCrossFade(atoi(p));
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_MIXRAMPDB))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_MIXRAMPDB))) {
pc.SetMixRampDb(atof(p)); pc.SetMixRampDb(ParseFloat(p));
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_MIXRAMPDELAY))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_MIXRAMPDELAY))) {
/* this check discards "nan" which was used /* this check discards "nan" which was used
prior to MPD 0.18 */ prior to MPD 0.18 */
if (IsDigitASCII(*p)) if (IsDigitASCII(*p))
pc.SetMixRampDelay(atof(p)); pc.SetMixRampDelay(ParseFloat(p));
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_RANDOM))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_RANDOM))) {
random_mode = StringIsEqual(p, "1"); random_mode = StringIsEqual(p, "1");
} else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_CURRENT))) { } else if ((p = StringAfterPrefix(line, PLAYLIST_STATE_FILE_CURRENT))) {

View File

@ -22,6 +22,7 @@
#include "VorbisComment.hxx" #include "VorbisComment.hxx"
#include "ReplayGainInfo.hxx" #include "ReplayGainInfo.hxx"
#include "util/ASCII.hxx" #include "util/ASCII.hxx"
#include "util/NumberParser.hxx"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
@ -33,16 +34,16 @@ ParseReplayGainTagTemplate(ReplayGainInfo &info, const T t)
const char *value; const char *value;
if ((value = t["replaygain_track_gain"]) != nullptr) { if ((value = t["replaygain_track_gain"]) != nullptr) {
info.track.gain = atof(value); info.track.gain = ParseFloat(value);
return true; return true;
} else if ((value = t["replaygain_album_gain"]) != nullptr) { } else if ((value = t["replaygain_album_gain"]) != nullptr) {
info.album.gain = atof(value); info.album.gain = ParseFloat(value);
return true; return true;
} else if ((value = t["replaygain_track_peak"]) != nullptr) { } else if ((value = t["replaygain_track_peak"]) != nullptr) {
info.track.peak = atof(value); info.track.peak = ParseFloat(value);
return true; return true;
} else if ((value = t["replaygain_album_peak"]) != nullptr) { } else if ((value = t["replaygain_album_peak"]) != nullptr) {
info.album.peak = atof(value); info.album.peak = ParseFloat(value);
return true; return true;
} else } else
return false; return false;

View File

@ -38,10 +38,12 @@
#include <windows.h> #include <windows.h>
#endif #endif
#if defined(__linux__) && !defined(ANDROID) #ifdef __linux__
#ifndef ANDROID
static int static int
ioprio_set(int which, int who, int ioprio) noexcept linux_ioprio_set(int which, int who, int ioprio) noexcept
{ {
return syscall(__NR_ioprio_set, which, who, ioprio); return syscall(__NR_ioprio_set, which, who, ioprio);
} }
@ -55,7 +57,21 @@ ioprio_set_idle() noexcept
static constexpr int _IOPRIO_IDLE = static constexpr int _IOPRIO_IDLE =
(_IOPRIO_CLASS_IDLE << _IOPRIO_CLASS_SHIFT) | 7; (_IOPRIO_CLASS_IDLE << _IOPRIO_CLASS_SHIFT) | 7;
ioprio_set(_IOPRIO_WHO_PROCESS, 0, _IOPRIO_IDLE); linux_ioprio_set(_IOPRIO_WHO_PROCESS, 0, _IOPRIO_IDLE);
}
#endif /* !ANDROID */
/**
* Wrapper for the "sched_setscheduler" system call. We don't use the
* one from the C library because Musl has an intentionally broken
* implementation.
*/
static int
linux_sched_setscheduler(pid_t pid, int sched,
const struct sched_param *param) noexcept
{
return syscall(__NR_sched_setscheduler, pid, sched, param);
} }
#endif #endif
@ -66,7 +82,7 @@ SetThreadIdlePriority() noexcept
#ifdef __linux__ #ifdef __linux__
#ifdef SCHED_IDLE #ifdef SCHED_IDLE
static struct sched_param sched_param; static struct sched_param sched_param;
sched_setscheduler(0, SCHED_IDLE, &sched_param); linux_sched_setscheduler(0, SCHED_IDLE, &sched_param);
#endif #endif
#ifndef ANDROID #ifndef ANDROID
@ -92,7 +108,7 @@ SetThreadRealtime()
policy |= SCHED_RESET_ON_FORK; policy |= SCHED_RESET_ON_FORK;
#endif #endif
if (sched_setscheduler(0, policy, &sched_param) < 0) if (linux_sched_setscheduler(0, policy, &sched_param) < 0)
throw MakeErrno("sched_setscheduler failed"); throw MakeErrno("sched_setscheduler failed");
#endif // __linux__ #endif // __linux__
}; };

View File

@ -78,7 +78,12 @@ ParseDouble(const char *p, char **endptr=nullptr)
static inline float static inline float
ParseFloat(const char *p, char **endptr=nullptr) ParseFloat(const char *p, char **endptr=nullptr)
{ {
#if defined(__BIONIC__) && __ANDROID_API__ < 21
/* strtof() requires API level 21 */
return (float)ParseDouble(p, endptr); return (float)ParseDouble(p, endptr);
#else
return strtof(p, endptr);
#endif
} }
#endif #endif