Compare commits

..

40 Commits

Author SHA1 Message Date
Max Kellermann
24741c5d06 release v0.21.24 2020-06-10 22:48:50 +02:00
Max Kellermann
6b3a282db4 lib/curl/Request: don't enable CURLOPT_NETRC on Windows
Our Windows build is built with `--disable-netrc`, and that makes
CURLOPT_NETRC fail, causing failures with all streams.  D'oh!

Closes https://github.com/MusicPlayerDaemon/MPD/issues/886
2020-06-10 22:46:42 +02:00
Max Kellermann
7583cfe9b7 {android,win32}/build.py: enable the GME decoder plugin
Closes https://github.com/MusicPlayerDaemon/MPD/issues/891
2020-06-10 21:33:29 +02:00
Max Kellermann
aafc9ce75b decoder/gme: use class NarrowPath() for Windows compatibility 2020-06-10 21:22:00 +02:00
Max Kellermann
fea326530b decoder/gme: simplify LoadGmeAndM3u() by moving code to ReplaceSuffix() 2020-06-10 21:20:49 +02:00
Max Kellermann
8925cc17d8 decoder/gme: use StringAfterPrefix() 2020-06-10 21:11:08 +02:00
Max Kellermann
14412c867f add a few IWYU pragmas 2020-06-10 21:10:33 +02:00
Max Kellermann
c5cc256bf2 decoder/gme: use Path::GetSuffix() 2020-06-10 21:02:07 +02:00
Max Kellermann
563c7318f9 fs/AllocatedPath: add method GetSuffix() 2020-06-10 21:00:41 +02:00
Max Kellermann
e92129f449 doc/protocol.rst: clarify the term "UNIX time"
Closes https://github.com/MusicPlayerDaemon/MPD/issues/893
2020-06-10 20:42:42 +02:00
Max Kellermann
374cc51f77 decoder/Bridge: add flag to make initial seek errors fatal
When the client wants to seek, but the decoder has already finished
decoding the current song, the player restarts the decoder with an
initial seek at the new position.  When this initial seek fails, MPD
pretends nothing has happened and plays this song from the start.

With this new flag, a restarted decoder marks the initial seek as
"essential" and fails the decoder if that seek fails.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/895
2020-06-10 17:49:10 +02:00
Rosen Penev
1008d5f67c use cwchar include
Needed for std::wmemchr under libcxx

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-05-30 13:22:04 +02:00
Shen-Ta Hsieh
8e07ea7ad8 src/db: fitting libmpdclient interface 2020-05-29 19:00:16 +02:00
Max Kellermann
d751df0a73 storage/State: disable -Wcomma to work around Boost compiler warning 2020-05-28 14:00:31 +02:00
Max Kellermann
2c084781b0 output/openal: disable -Wdeprecated-declarations on Apple 2020-05-28 13:59:52 +02:00
Max Kellermann
ae7d550a01 meson.build: remove -Wall -Wextra, to be set by Meson 2020-05-28 13:19:34 +02:00
Max Kellermann
30d97fe8a0 meson.build: fix the WildMidi check when the feature is disabled
Fixes regression from commit 69f09648a4
2020-05-27 16:06:49 +02:00
Max Kellermann
5cb0080052 meson.build: default to warning_level=2
This branch isn't yet ready for level 3 (`-Wpedantic`) due to several
C++ violations (e.g. variable length arrays).  These are already
cleaned up in the master branch (0.22).
2020-05-27 15:57:13 +02:00
Max Kellermann
8e4ca23727 lib/ffmpeg/Time: replace C99 compound literal with C++ initializer list 2020-05-27 15:54:34 +02:00
Max Kellermann
bdc861f058 util/TemplateString: remove extra semicolon 2020-05-27 15:46:55 +02:00
Rosen Penev
8925040262 remove some more extra semicolons
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-05-27 15:36:53 +02:00
Max Kellermann
c065950ced .travis.yml: disable zzip on OS X to fix Travis-CI build failure 2020-05-27 15:31:34 +02:00
Max Kellermann
257a77fa35 {android,win32}/build.py: build libmodplug and WildMidi
Closes https://github.com/MusicPlayerDaemon/MPD/issues/866
2020-05-27 15:03:49 +02:00
Max Kellermann
4e5d6e560b decoder/modplug: assume ModPlug is built as static library on Windows 2020-05-27 15:03:46 +02:00
Max Kellermann
d276d8eda2 decoder/wildmidi: assume WildMidi is built as static library on Windows 2020-05-27 15:03:35 +02:00
Max Kellermann
ebcb5e9368 decoder/wildmidi: use NarrowPath, fixing the Windows build 2020-05-27 15:03:33 +02:00
Max Kellermann
69f09648a4 meson.build: attempt to detect WildMidi using pkg-config
The WildMidi project added the pkg-config file in version 0.3.3, but
unfortunately, Debian still doesn't ship it 4 years later:

 https://bugs.debian.org/916631

However, for cross-compiling, the pkg-config file is very helpful.
2020-05-27 15:03:16 +02:00
Max Kellermann
9adda30c38 NEWS: move two lines below Windows/Android 2020-05-27 14:33:43 +02:00
Max Kellermann
d2d4a0251e .gitignore: add emacs lsp-mode files 2020-05-26 21:07:56 +02:00
Max Kellermann
f7b6431b6f meson.build: work around Meson bug detecting strndup() on Windows
Work around Meson bug https://github.com/mesonbuild/meson/issues/3672
2020-05-26 20:50:56 +02:00
Max Kellermann
03b9bd3a9e python/build/libs.py: update FFmpeg to 4.2.3 2020-05-26 18:54:56 +02:00
Max Kellermann
61aed60f6d python/build/libs.py: update CURL to 7.70.0 2020-05-07 14:18:55 +02:00
Max Kellermann
2cc323c9fe python/build/libs.py: update Boost to 1.73.0 2020-05-07 14:18:21 +02:00
Max Kellermann
f24ab120ee android/build.py: use -fpic instead of -fPIC on ARM/Aarch64
Sync with the Android NDK build scripts.
2020-05-07 13:58:36 +02:00
Max Kellermann
68349bc55c android/build.py: use -mfpu=vfpv3-d16 on ARMv7
This flag is used by the Android NDK build scripts as well, and this
fixes a build failure (assembler error) with FFmpeg and NDK r21.
2020-05-07 13:50:33 +02:00
Max Kellermann
209364adf2 db/simple: fix crash when mounting twice
The `db->close()` call was a `nullptr` dereference because the `db`
variable had already been moved.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/839
2020-05-05 18:57:29 +02:00
Max Kellermann
24afdee35c command/all: "tagtypes" requires no permissions
The command is used to configure the client's connection, and this
shouldn't require any permissions.  The client should be able to do
that before sending a password.
2020-04-30 13:08:09 +02:00
Max Kellermann
7aea285361 Revert "Fix unsafe float comparison."
This reverts commit a5273d6992.  It was
wrong and broke the MixRamp unit test.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/844
2020-04-30 06:57:36 +02:00
Rosen Penev
47a7707df1 Math.hxx: fix wrong macro name
_GLIBCXX_USE_C99_MATH_TR1 is the correct one.

_GLIBCXX_USE_C99_MATH is always defined.
2020-04-29 23:20:04 +02:00
Max Kellermann
6fdae1139f increment version number to 0.21.24 2020-04-29 23:20:04 +02:00
40 changed files with 264 additions and 82 deletions

3
.gitignore vendored
View File

@@ -6,3 +6,6 @@
/output/
__pycache__/
/.clangd/
/compile_commands.json

View File

@@ -135,7 +135,8 @@ jobs:
- chromaprint
- libsamplerate
- libsoxr
- libzzip
# libzzip appears to be broken on Homebrew: "ld: library not found for -lzzip"
#- libzzip
- flac
- opus
- libvorbis

20
NEWS
View File

@@ -1,3 +1,23 @@
ver 0.21.24 (2020/06/10)
* protocol
- "tagtypes" requires no permissions
* database
- simple: fix crash when mounting twice
* decoder
- modplug: fix Windows build failure
- wildmidi: attempt to detect WildMidi using pkg-config
- wildmidi: fix Windows build failure
* player
- don't restart current song if seeking beyond end
* Android
- enable the decoder plugins GME, ModPlug and WildMidi
- fix build failure with Android NDK r21
* Windows
- fix stream playback
- enable the decoder plugins GME, ModPlug and WildMidi
- work around Meson bug breaking the Windows build with GCC 10
* fix unit test failure
ver 0.21.23 (2020/04/23)
* protocol
- add tag fallback for AlbumSort

View File

@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.musicpd"
android:installLocation="auto"
android:versionCode="46"
android:versionName="0.21.23">
android:versionCode="47"
android:versionName="0.21.24">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>

View File

@@ -26,7 +26,7 @@ android_abis = {
'ndk_arch': 'arm',
'toolchain_arch': 'arm-linux-androideabi',
'llvm_triple': 'armv7-linux-androideabi',
'cflags': '-march=armv7-a -mfpu=vfp -mfloat-abi=softfp',
'cflags': '-fpic -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp',
},
'arm64-v8a': {
@@ -34,7 +34,7 @@ android_abis = {
'ndk_arch': 'arm64',
'toolchain_arch': 'aarch64-linux-android',
'llvm_triple': 'aarch64-linux-android',
'cflags': '',
'cflags': '-fpic',
},
'x86': {
@@ -42,7 +42,7 @@ android_abis = {
'ndk_arch': 'x86',
'toolchain_arch': 'x86',
'llvm_triple': 'i686-linux-android',
'cflags': '-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32',
'cflags': '-fPIC -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32',
},
'x86_64': {
@@ -50,7 +50,7 @@ android_abis = {
'ndk_arch': 'x86_64',
'toolchain_arch': 'x86_64',
'llvm_triple': 'x86_64-linux-android',
'cflags': '-m64',
'cflags': '-fPIC -m64',
},
}
@@ -97,7 +97,6 @@ class AndroidNdkToolchain:
llvm_triple = abi_info['llvm_triple'] + android_api_level
common_flags = '-Os -g'
common_flags += ' -fPIC'
common_flags += ' ' + abi_info['cflags']
toolchain_bin = os.path.join(toolchain_path, 'bin')
@@ -169,6 +168,9 @@ thirdparty_libs = [
opus,
flac,
libid3tag,
libmodplug,
wildmidi,
gme,
ffmpeg,
curl,
libexpat,

View File

@@ -38,7 +38,7 @@ author = 'Max Kellermann'
# built documents.
#
# The short X.Y version.
version = '0.21.23'
version = '0.21.24'
# The full version, including alpha/beta/rc tags.
release = version

View File

@@ -464,7 +464,8 @@ Querying :program:`MPD`'s status
- ``songs``: number of songs
- ``uptime``: daemon uptime in seconds
- ``db_playtime``: sum of all song times in the database in seconds
- ``db_update``: last db update in UNIX time
- ``db_update``: last db update in UNIX time (seconds since
1970-01-01 UTC)
- ``playtime``: time length of music played
Playback options

View File

@@ -1,11 +1,12 @@
project(
'mpd',
['c', 'cpp'],
version: '0.21.23',
version: '0.21.24',
meson_version: '>= 0.49.0',
default_options: [
'c_std=c99',
'cpp_std=c++14'
'cpp_std=c++14',
'warning_level=2',
],
license: 'GPLv2+',
)
@@ -40,9 +41,6 @@ common_cxxflags = [
]
test_common_flags = [
'-Wall',
'-Wextra',
'-fvisibility=hidden',
'-ffast-math',
@@ -142,7 +140,13 @@ conf.set('HAVE_GETPWNAM_R', compiler.has_function('getpwnam_r'))
conf.set('HAVE_GETPWUID_R', compiler.has_function('getpwuid_r'))
conf.set('HAVE_INITGROUPS', compiler.has_function('initgroups'))
conf.set('HAVE_FNMATCH', compiler.has_function('fnmatch'))
conf.set('HAVE_STRNDUP', compiler.has_function('strndup', prefix: '#define _GNU_SOURCE\n#include <string.h>'))
# Explicitly exclude Windows in this check because
# https://github.com/mesonbuild/meson/issues/3672 (reported in 2018,
# still not fixed in 2020) causes Meson to believe it exists, because
# __builtin_strndup() exists (but strndup() still cannot be used).
conf.set('HAVE_STRNDUP', not is_windows and compiler.has_function('strndup', prefix: '#define _GNU_SOURCE\n#include <string.h>'))
conf.set('HAVE_STRCASESTR', compiler.has_function('strcasestr'))
conf.set('HAVE_PRCTL', is_linux)

45
python/build/cmake.py Normal file
View File

@@ -0,0 +1,45 @@
import subprocess
from build.project import Project
def configure(toolchain, src, build, args=()):
cross_args = []
if toolchain.is_windows:
cross_args.append('-DCMAKE_SYSTEM_NAME=Windows')
cross_args.append('-DCMAKE_RC_COMPILER=' + toolchain.windres)
configure = [
'cmake',
src,
'-DCMAKE_INSTALL_PREFIX=' + toolchain.install_prefix,
'-DCMAKE_BUILD_TYPE=release',
'-DCMAKE_C_COMPILER=' + toolchain.cc,
'-DCMAKE_CXX_COMPILER=' + toolchain.cxx,
'-DCMAKE_C_FLAGS=' + toolchain.cflags + ' ' + toolchain.cppflags,
'-DCMAKE_CXX_FLAGS=' + toolchain.cxxflags + ' ' + toolchain.cppflags,
'-GNinja',
] + cross_args + args
subprocess.check_call(configure, env=toolchain.env, cwd=build)
class CmakeProject(Project):
def __init__(self, url, md5, installed, configure_args=[],
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
def configure(self, toolchain):
src = self.unpack(toolchain)
build = self.make_build_path(toolchain)
configure(toolchain, src, build, self.configure_args)
return build
def build(self, toolchain):
build = self.configure(toolchain)
subprocess.check_call(['ninja', 'install'],
cwd=build, env=toolchain.env)

View File

@@ -4,6 +4,7 @@ from os.path import abspath
from build.project import Project
from build.zlib import ZlibProject
from build.meson import MesonProject
from build.cmake import CmakeProject
from build.autotools import AutotoolsProject
from build.ffmpeg import FfmpegProject
from build.boost import BoostProject
@@ -111,9 +112,44 @@ liblame = AutotoolsProject(
],
)
libmodplug = AutotoolsProject(
'https://downloads.sourceforge.net/modplug-xmms/libmodplug/0.8.9.0/libmodplug-0.8.9.0.tar.gz',
'457ca5a6c179656d66c01505c0d95fafaead4329b9dbaa0f997d00a3508ad9de',
'lib/libmodplug.a',
[
'--disable-shared', '--enable-static',
],
)
wildmidi = CmakeProject(
'https://codeload.github.com/Mindwerks/wildmidi/tar.gz/wildmidi-0.4.3',
'498e5a96455bb4b91b37188ad6dcb070824e92c44f5ed452b90adbaec8eef3c5',
'lib/libWildMidi.a',
[
'-DBUILD_SHARED_LIBS=OFF',
'-DWANT_PLAYER=OFF',
'-DWANT_STATIC=ON',
],
base='wildmidi-wildmidi-0.4.3',
name='wildmidi',
version='0.4.3',
)
gme = CmakeProject(
'https://bitbucket.org/mpyne/game-music-emu/downloads/game-music-emu-0.6.3.tar.xz',
'aba34e53ef0ec6a34b58b84e28bf8cfbccee6585cebca25333604c35db3e051d',
'lib/libgme.a',
[
'-DBUILD_SHARED_LIBS=OFF',
'-DENABLE_UBSAN=OFF',
'-DZLIB_INCLUDE_DIR=OFF',
'-DSDL2_DIR=OFF',
],
)
ffmpeg = FfmpegProject(
'http://ffmpeg.org/releases/ffmpeg-4.2.2.tar.xz',
'cb754255ab0ee2ea5f66f8850e1bd6ad5cac1cd855d0a2f4990fb8c668b0d29c',
'http://ffmpeg.org/releases/ffmpeg-4.2.3.tar.xz',
'9df6c90aed1337634c1fb026fb01c154c29c82a64ea71291ff2da9aacb9aad31',
'lib/libavcodec.a',
[
'--disable-shared', '--enable-static',
@@ -341,8 +377,8 @@ ffmpeg = FfmpegProject(
)
curl = AutotoolsProject(
'http://curl.haxx.se/download/curl-7.69.1.tar.xz',
'03c7d5e6697f7b7e40ada1b2256e565a555657398e6c1fcfa4cb251ccd819d4f',
'http://curl.haxx.se/download/curl-7.70.0.tar.xz',
'032f43f2674008c761af19bf536374128c16241fb234699a55f9fb603fcfbae7',
'lib/libcurl.a',
[
'--disable-shared', '--enable-static',
@@ -397,7 +433,7 @@ libnfs = AutotoolsProject(
)
boost = BoostProject(
'https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.tar.bz2',
'59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722',
'https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.bz2',
'4eb3b8d442b426dc35346235c8733b5ae35ba431690e38c6a8263dce9fcbb402',
'include/boost/version.hpp',
)

View File

@@ -20,7 +20,7 @@
#ifndef MPD_AUDIO_FORMAT_HXX
#define MPD_AUDIO_FORMAT_HXX
#include "pcm/SampleFormat.hxx"
#include "pcm/SampleFormat.hxx" // IWYU pragma: export
#include "util/Compiler.h"
#include <chrono>

View File

@@ -193,7 +193,7 @@ static constexpr struct command commands[] = {
{ "subscribe", PERMISSION_READ, 1, 1, handle_subscribe },
{ "swap", PERMISSION_CONTROL, 2, 2, handle_swap },
{ "swapid", PERMISSION_CONTROL, 2, 2, handle_swapid },
{ "tagtypes", PERMISSION_READ, 0, -1, handle_tagtypes },
{ "tagtypes", PERMISSION_NONE, 0, -1, handle_tagtypes },
{ "toggleoutput", PERMISSION_ADMIN, 1, 1, handle_toggleoutput },
#ifdef ENABLE_DATABASE
{ "unmount", PERMISSION_ADMIN, 1, 1, handle_unmount },

View File

@@ -493,9 +493,13 @@ ProxyDatabase::Connect()
try {
CheckError(connection);
if (mpd_connection_cmp_server_version(connection, 0, 19, 0) < 0)
throw FormatRuntimeError("Connect to MPD %s, but this plugin requires at least version 0.19",
mpd_connection_get_server_version(connection));
if (mpd_connection_cmp_server_version(connection, 0, 19, 0) < 0) {
const unsigned *version =
mpd_connection_get_server_version(connection);
throw FormatRuntimeError("Connect to MPD %u.%u.%u, but this "
"plugin requires at least version 0.19",
version[0], version[1], version[2]);
}
if (!password.empty() &&
!mpd_run_password(connection, password.c_str()))

View File

@@ -449,12 +449,7 @@ SimpleDatabase::Mount(const char *local_uri, const char *storage_uri)
// TODO: update the new database instance?
try {
Mount(local_uri, std::move(db));
} catch (...) {
db->Close();
throw;
}
Mount(local_uri, std::move(db));
}
inline DatabasePtr

View File

@@ -33,6 +33,8 @@
#include "util/ConstBuffer.hxx"
#include "util/StringBuffer.hxx"
#include <stdexcept>
#include <assert.h>
#include <string.h>
#include <math.h>
@@ -344,6 +346,10 @@ DecoderBridge::SeekError()
/* d'oh, we can't seek to the sub-song start position,
what now? - no idea, ignoring the problem for now. */
initial_seek_running = false;
if (initial_seek_essential)
error = std::make_exception_ptr(std::runtime_error("Decoder failed to seek"));
return;
}

View File

@@ -62,6 +62,11 @@ public:
*/
bool initial_seek_pending;
/**
* Are initial seek failures fatal?
*/
const bool initial_seek_essential;
/**
* Is the initial seek currently running? During this time,
* the decoder command is SEEK. This flag is set by
@@ -107,9 +112,11 @@ public:
std::exception_ptr error;
DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
bool _initial_seek_essential,
std::unique_ptr<Tag> _tag)
:dc(_dc),
initial_seek_pending(_initial_seek_pending),
initial_seek_essential(_initial_seek_essential),
song_tag(std::move(_tag)) {}
~DecoderBridge();

View File

@@ -90,6 +90,7 @@ DecoderControl::IsCurrentSong(const DetachedSong &_song) const noexcept
void
DecoderControl::Start(std::unique_ptr<DetachedSong> _song,
SongTime _start_time, SongTime _end_time,
bool _initial_seek_essential,
MusicBuffer &_buffer,
std::shared_ptr<MusicPipe> _pipe) noexcept
{
@@ -99,6 +100,7 @@ DecoderControl::Start(std::unique_ptr<DetachedSong> _song,
song = std::move(_song);
start_time = _start_time;
end_time = _end_time;
initial_seek_essential = _initial_seek_essential;
buffer = &_buffer;
pipe = std::move(_pipe);

View File

@@ -117,6 +117,12 @@ public:
bool seek_error;
bool seekable;
/**
* @see #DecoderBridge::initial_seek_essential
*/
bool initial_seek_essential;
SongTime seek_time;
private:
@@ -398,11 +404,14 @@ public:
* owned and freed by the decoder
* @param start_time see #DecoderControl
* @param end_time see #DecoderControl
* @param initial_seek_essential see
* #DecoderBridge::initial_seek_essential
* @param pipe the pipe which receives the decoded chunks (owned by
* the caller)
*/
void Start(std::unique_ptr<DetachedSong> song,
SongTime start_time, SongTime end_time,
bool initial_seek_essential,
MusicBuffer &buffer,
std::shared_ptr<MusicPipe> pipe) noexcept;

View File

@@ -22,7 +22,7 @@
#include "util/Compiler.h"
#include <forward_list>
#include <forward_list> // IWYU pragma: export
struct ConfigBlock;
class InputStream;

View File

@@ -461,6 +461,7 @@ decoder_run_song(DecoderControl &dc,
dc.start_time = dc.seek_time;
DecoderBridge bridge(dc, dc.start_time.IsPositive(),
dc.initial_seek_essential,
/* pass the song tag only if it's
authoritative, i.e. if it's a local
file - tags on "stream" songs are just

View File

@@ -27,10 +27,10 @@
#include "fs/Path.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/FileSystem.hxx"
#include "fs/NarrowPath.hxx"
#include "util/ScopeExit.hxx"
#include "util/StringCompare.hxx"
#include "util/StringFormat.hxx"
#include "util/UriUtil.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@@ -38,7 +38,6 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define SUBTUNE_PREFIX "tune_"
@@ -76,11 +75,10 @@ gcc_pure
static unsigned
ParseSubtuneName(const char *base) noexcept
{
if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
base = StringAfterPrefix(base, SUBTUNE_PREFIX);
if (base == nullptr)
return 0;
base += sizeof(SUBTUNE_PREFIX) - 1;
char *endptr;
auto track = strtoul(base, &endptr, 10);
if (endptr == base || *endptr != '.')
@@ -99,41 +97,46 @@ ParseContainerPath(Path path_fs)
const Path base = path_fs.GetBase();
unsigned track;
if (base.IsNull() ||
(track = ParseSubtuneName(base.c_str())) < 1)
(track = ParseSubtuneName(NarrowPath(base))) < 1)
return { AllocatedPath(path_fs), 0 };
return { path_fs.GetDirectoryName(), track - 1 };
}
static AllocatedPath
ReplaceSuffix(Path src,
const PathTraitsFS::const_pointer_type new_suffix) noexcept
{
const auto *old_suffix = src.GetSuffix();
if (old_suffix == nullptr)
return nullptr;
PathTraitsFS::string s(src.c_str(), old_suffix);
s += new_suffix;
return AllocatedPath::FromFS(std::move(s));
}
static Music_Emu*
LoadGmeAndM3u(GmeContainerPath container) {
const char *path = container.path.c_str();
const char *suffix = uri_get_suffix(path);
Music_Emu *emu;
const char *gme_err =
gme_open_file(path, &emu, GME_SAMPLE_RATE);
gme_open_file(NarrowPath(container.path), &emu, GME_SAMPLE_RATE);
if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err);
return nullptr;
}
if(suffix == nullptr) {
return emu;
}
std::string m3u_path(path,suffix);
m3u_path += "m3u";
const auto m3u_path = ReplaceSuffix(container.path,
PATH_LITERAL("m3u"));
/*
* Some GME formats lose metadata if you attempt to
* load a non-existant M3U file, so check that one
* exists before loading.
*/
if(FileExists(Path::FromFS(m3u_path.c_str()))) {
gme_load_m3u(emu,m3u_path.c_str());
}
if (!m3u_path.IsNull() && FileExists(m3u_path))
gme_load_m3u(emu, NarrowPath(m3u_path));
return emu;
}
@@ -303,7 +306,7 @@ gme_container_scan(Path path_fs)
if (num_songs < 2)
return list;
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
const auto *subtune_suffix = path_fs.GetSuffix();
TagBuilder tag_builder;

View File

@@ -26,8 +26,13 @@
#include "util/RuntimeError.hxx"
#include "Log.hxx"
#include <libmodplug/modplug.h>
#ifdef _WIN32
/* assume ModPlug is built as static library on Windows; without
this, linking to the static library would fail */
#define MODPLUG_STATIC
#endif
#include <libmodplug/modplug.h>
#include <assert.h>

View File

@@ -25,9 +25,16 @@
#include "fs/AllocatedPath.hxx"
#include "fs/FileSystem.hxx"
#include "fs/Path.hxx"
#include "fs/NarrowPath.hxx"
#include "Log.hxx"
#include "PluginUnavailable.hxx"
#ifdef _WIN32
/* assume WildMidi is built as static library on Windows; without
this, linking to the static library would fail */
#define WILDMIDI_STATIC
#endif
extern "C" {
#include <wildmidi_lib.h>
}
@@ -53,7 +60,8 @@ wildmidi_init(const ConfigBlock &block)
AtScopeExit() { WildMidi_ClearError(); };
#endif
if (WildMidi_Init(path.c_str(), wildmidi_audio_format.sample_rate,
if (WildMidi_Init(NarrowPath(path),
wildmidi_audio_format.sample_rate,
0) != 0) {
#ifdef LIBWILDMIDI_VERSION
/* WildMidi_GetError() requires libwildmidi 0.4 */
@@ -96,7 +104,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
midi *wm;
const struct _WM_Info *info;
wm = WildMidi_Open(path_fs.c_str());
wm = WildMidi_Open(NarrowPath(path_fs));
if (wm == nullptr)
return;
@@ -136,7 +144,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
static bool
wildmidi_scan_file(Path path_fs, TagHandler &handler) noexcept
{
midi *wm = WildMidi_Open(path_fs.c_str());
midi *wm = WildMidi_Open(NarrowPath(path_fs));
if (wm == nullptr)
return false;

View File

@@ -129,7 +129,16 @@ if wavpack_dep.found()
decoder_plugins_sources += 'WavpackDecoderPlugin.cxx'
endif
wildmidi_dep = c_compiler.find_library('WildMidi', required: get_option('wildmidi'))
wildmidi_required = get_option('wildmidi')
if wildmidi_required.enabled()
# if the user has force-enabled WildMidi, allow the pkg-config test
# to fail; after that, the find_library() check must succeed
wildmidi_required = false
endif
wildmidi_dep = dependency('wildmidi', required: wildmidi_required)
if not wildmidi_dep.found()
wildmidi_dep = c_compiler.find_library('WildMidi', required: get_option('wildmidi'))
endif
conf.set('ENABLE_WILDMIDI', wildmidi_dep.found())
if wildmidi_dep.found()
decoder_plugins_sources += 'WildmidiDecoderPlugin.cxx'

View File

@@ -285,6 +285,11 @@ public:
bool IsAbsolute() const noexcept {
return Traits::IsAbsolute(c_str());
}
gcc_pure
const_pointer_type GetSuffix() const noexcept {
return ((Path)*this).GetSuffix();
}
};
#endif

View File

@@ -56,7 +56,7 @@ CurlRequest::CurlRequest(CurlGlobal &_global,
easy.SetUserAgent("Music Player Daemon " VERSION);
easy.SetHeaderFunction(_HeaderFunction, this);
easy.SetWriteFunction(WriteFunction, this);
#ifndef ANDROID
#if !defined(ANDROID) && !defined(_WIN32)
easy.SetOption(CURLOPT_NETRC, 1L);
#endif
easy.SetErrorBuffer(error_buffer);

View File

@@ -86,7 +86,7 @@ struct WrapVariant : BasicValue<T> {
template<typename T>
static WrapVariant<T> Variant(const T &_value) noexcept {
return WrapVariant<T>(_value);
};
}
template<typename T>
struct WrapFixedArray {
@@ -103,7 +103,7 @@ template<typename T>
static WrapFixedArray<T> FixedArray(const T *_data,
size_t _size) noexcept {
return WrapFixedArray<T>(_data, _size);
};
}
template<typename... T>
struct WrapStruct {
@@ -118,7 +118,7 @@ struct WrapStruct {
template<typename... T>
static WrapStruct<T...> Struct(const T&... values) noexcept {
return WrapStruct<T...>(values...);
};
}
} /* namespace ODBus */

View File

@@ -45,7 +45,7 @@ FfmpegTimeToDouble(int64_t t, const AVRational time_base) noexcept
{
assert(t != (int64_t)AV_NOPTS_VALUE);
return FloatDuration(av_rescale_q(t, time_base, (AVRational){1, 1024}))
return FloatDuration(av_rescale_q(t, time_base, {1, 1024}))
/ 1024;
}
@@ -69,7 +69,7 @@ FromFfmpegTime(int64_t t, const AVRational time_base) noexcept
assert(t != (int64_t)AV_NOPTS_VALUE);
return SongTime::FromMS(av_rescale_q(t, time_base,
(AVRational){1, 1000}));
{1, 1000}));
}
/**

View File

@@ -41,6 +41,6 @@ public:
LockGuard &operator=(const LockGuard &) = delete;
};
};
}
#endif

View File

@@ -30,6 +30,6 @@ namespace ixmlwrap {
const char *getFirstElementValue(IXML_Document *doc,
const char *name) noexcept;
};
}
#endif /* _IXMLWRAP_H_INCLUDED_ */

View File

@@ -29,6 +29,9 @@
#else
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
/* on macOS, OpenAL is deprecated, but since the user asked to enable
this plugin, let's ignore the compiler warnings */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
class OpenALOutput final : AudioOutput {

View File

@@ -62,7 +62,7 @@ mixramp_interpolate(const char *ramp_list, float required_db) noexcept
++ramp_list;
/* Check for exact match. */
if (db >= required_db) {
if (db == required_db) {
return duration;
}

View File

@@ -223,7 +223,8 @@ private:
*
* Caller must lock the mutex.
*/
void StartDecoder(std::shared_ptr<MusicPipe> pipe) noexcept;
void StartDecoder(std::shared_ptr<MusicPipe> pipe,
bool initial_seek_essential) noexcept;
/**
* The decoder has acknowledged the "START" command (see
@@ -364,7 +365,8 @@ public:
};
void
Player::StartDecoder(std::shared_ptr<MusicPipe> _pipe) noexcept
Player::StartDecoder(std::shared_ptr<MusicPipe> _pipe,
bool initial_seek_essential) noexcept
{
assert(queued || pc.command == PlayerCommand::SEEK);
assert(pc.next_song != nullptr);
@@ -376,6 +378,7 @@ Player::StartDecoder(std::shared_ptr<MusicPipe> _pipe) noexcept
dc.Start(std::make_unique<DetachedSong>(*pc.next_song),
start_time, pc.next_song->GetEndTime(),
initial_seek_essential,
buffer, std::move(_pipe));
}
@@ -633,7 +636,7 @@ Player::SeekDecoder() noexcept
pipe->Clear();
/* re-start the decoder */
StartDecoder(pipe);
StartDecoder(pipe, true);
ActivateDecoder();
pc.seeking = true;
@@ -711,7 +714,7 @@ Player::ProcessCommand() noexcept
pc.CommandFinished();
if (dc.IsIdle())
StartDecoder(std::make_shared<MusicPipe>());
StartDecoder(std::make_shared<MusicPipe>(), false);
break;
@@ -982,7 +985,7 @@ Player::Run() noexcept
const std::lock_guard<Mutex> lock(pc.mutex);
StartDecoder(pipe);
StartDecoder(pipe, true);
ActivateDecoder();
pc.state = PlayerState::PLAY;
@@ -1022,7 +1025,7 @@ Player::Run() noexcept
assert(dc.pipe == nullptr || dc.pipe == pipe);
StartDecoder(std::make_shared<MusicPipe>());
StartDecoder(std::make_shared<MusicPipe>(), false);
}
if (/* no cross-fading if MPD is going to pause at the

View File

@@ -33,9 +33,16 @@
#include "Instance.hxx"
#include "Log.hxx"
#include <set>
#ifdef __clang__
/* ignore -Wcomma due to strange code in boost/array.hpp (in Boost
1.72) */
#pragma GCC diagnostic ignored "-Wcomma"
#endif
#include <boost/crc.hpp>
#include <set>
#define MOUNT_STATE_BEGIN "mount_begin"
#define MOUNT_STATE_END "mount_end"
#define MOUNT_STATE_STORAGE_URI "uri: "

View File

@@ -94,7 +94,7 @@ SetThreadIdlePriority() noexcept
#elif defined(_WIN32)
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
#endif
};
}
void
SetThreadRealtime()
@@ -111,4 +111,4 @@ SetThreadRealtime()
if (linux_sched_setscheduler(0, policy, &sched_param) < 0)
throw MakeErrno("sched_setscheduler failed");
#endif // __linux__
};
}

View File

@@ -36,7 +36,7 @@
* C99 math can be optionally omitted with gcc's libstdc++.
* Use boost if unavailable.
*/
#if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) && !defined(_GLIBCXX_USE_C99_MATH)
#if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) && !defined(_GLIBCXX_USE_C99_MATH_TR1)
#include <boost/math/special_functions/round.hpp>
using boost::math::lround;
#else

View File

@@ -30,7 +30,7 @@
#ifndef STRING_FORMAT_HXX
#define STRING_FORMAT_HXX
#include "StringBuffer.hxx"
#include "StringBuffer.hxx" // IWYU pragma: export
#include <stdio.h>

View File

@@ -121,6 +121,6 @@ namespace TemplateString {
template<>
struct Concat<> : Empty {};
};
}
#endif

View File

@@ -32,7 +32,7 @@
#include "Compiler.h"
#include <wchar.h>
#include <cwchar>
gcc_pure gcc_nonnull_all
static inline size_t

View File

@@ -96,6 +96,9 @@ thirdparty_libs = [
zlib,
libid3tag,
liblame,
libmodplug,
wildmidi,
gme,
ffmpeg,
curl,
libexpat,