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:
commit
65bbb0e0aa
9
NEWS
9
NEWS
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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') + \
|
||||||
|
21
doc/user.xml
21
doc/user.xml
@ -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>
|
||||||
|
@ -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(
|
||||||
|
@ -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
9
python/build/quilt.py
Normal 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')
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
20
src/lib/curl/patches/no_netrc.patch
Normal file
20
src/lib/curl/patches/no_netrc.patch
Normal 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;
|
||||||
|
}
|
15
src/lib/curl/patches/only_lib.patch
Normal file
15
src/lib/curl/patches/only_lib.patch
Normal 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 \
|
2
src/lib/curl/patches/series
Normal file
2
src/lib/curl/patches/series
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
only_lib.patch
|
||||||
|
no_netrc.patch
|
@ -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);
|
||||||
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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))) {
|
||||||
|
@ -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;
|
||||||
|
@ -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__
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user