Compare commits

...

64 Commits

Author SHA1 Message Date
Max Kellermann
ed4d0aa909 release v0.20.15 2018-01-05 17:55:25 +01:00
Max Kellermann
023ce4e720 python/build/libs.py: disable even more FFmpeg modules 2018-01-05 17:41:58 +01:00
Max Kellermann
368d9359dd python/build/libs.py: update libogg to 1.3.3 2018-01-05 17:41:58 +01:00
Max Kellermann
d98c19d561 python/build/libs.py: disable more FFmpeg modules 2018-01-05 16:49:28 +01:00
Max Kellermann
cab77e35e0 queue/PlaylistControl: fix crash after seek failure
This completes the bug fix commit
2065e3290452377b2931f3129b230c8cc536cbc8; if we clear "queued" then we
must clear "queued_song" as well, or another variant of the assertion
fails.
2018-01-05 13:00:24 +01:00
Max Kellermann
e3e90b4b93 python/build/libs.py: disable libcurl SMB support
MPD doesn't use this feature anyway.
2018-01-05 12:00:29 +01:00
Max Kellermann
f8c69893e1 python/build/libs.py: disable lots of useless FFmpeg features 2018-01-05 11:11:20 +01:00
Max Kellermann
49678a0893 python/build/libs.py: suppress "visibility default" in libopus build 2018-01-05 10:33:53 +01:00
Max Kellermann
d667b5b48c python/build/libs.py: work around libid3tag CFLAGS bug 2018-01-05 10:25:16 +01:00
Max Kellermann
9cba55b39c python/build/project.py: add "edits" parameter to edit source files 2018-01-05 10:06:22 +01:00
Max Kellermann
c2cbb7b8ce output/haiku: remove unimplemented Cancel() method 2018-01-05 10:05:14 +01:00
Felix Hädicke
8217d75ca1 build/python: refactoring: introduce new class MakeProject
This introduces a the new class MakeProject, which is used as a base
class for all Makefile based thirdparty libraries.
2018-01-05 08:17:17 +01:00
Max Kellermann
1ca70d9759 build/python/autotools: add properties "ldflags", "libs", "install_target" 2018-01-05 08:17:15 +01:00
Felix Hädicke
4303aaa9b8 build/python: use "glibtoolize", not "libtoolize" when compiling on OS X
On OS X, the "libtoolize" command is some Apple tool. The libtoolize
we want is named "glibtoolize" in Homebrew.
2018-01-05 07:55:59 +01:00
Max Kellermann
7b56bae289 python/build/libs.py: pass --disable-debugging to libid3tag and libmad 2018-01-05 07:30:09 +01:00
Max Kellermann
4183416b3e python/build/libs.py: reindent arrays 2018-01-05 07:27:09 +01:00
Max Kellermann
a60dee57ce python/libs: upgrade Boost to 1.66.0 2018-01-05 07:16:38 +01:00
Max Kellermann
5724656acb android/build.py: enable function/data sections in static libraries
.. and make all library symbols hidden by default.

Saves big amounts of .text section size with --gc-sections, because
only this allows discarding unused functions from those (static)
third-party libraries.
2018-01-04 23:33:07 +01:00
Max Kellermann
329f9cd9fe thread/Util: no ioprio_set() on Android due to seccomp/SIGSYS 2018-01-04 19:33:14 +01:00
Felix Hädicke
fbdb8b406e Makefile.am: build Android APK package without Ant
In current Android SDK releases, Ant support was removed. Move the
necessary build steps from the former Ant build system to our Makefile,
and call the required build tools from the Android SDK (aapt and dx),
Java SDK (javac) and Info-ZIP (zip) directly.

[mk: copied from Felix's commit
e52b906dba971a1173f9e8f83d32b52ee9f89af3 in the XCSoar project)
2018-01-04 18:55:54 +01:00
Max Kellermann
85d0bbd957 Makefile.am: add variable ZIPALIGN 2018-01-04 18:55:45 +01:00
Max Kellermann
414f00d6ae Makefile.am: add variable ANDROID_SDK_PLATFORM 2018-01-04 18:47:52 +01:00
Max Kellermann
17b0add058 filter/Observer: pass Reset() to underlying Filter
Wohooooo, the method Filter::Reset() has been broken because no
implementation of it has ever been called for a loooong time.
And nobody ever noticed it.  WTF.
2018-01-02 22:13:14 +01:00
Max Kellermann
c68ed40661 pcm/SoxrResampler: implement method Reset() 2018-01-02 21:53:09 +01:00
Max Kellermann
ff624075a8 storage/State: check if a CompositeStorage exists; fixes nullptr dereference
Fixes another crash bug caused by commit
64d141f71e
2018-01-02 14:13:26 +01:00
Max Kellermann
08db28469d storage/State: make mount errors non-fatal
Fixes crash bug caused by commit
64d141f71e
2018-01-02 14:07:52 +01:00
Max Kellermann
a20b326807 storage/State: fix memory leak after database mount failure
Caused by commit 64d141f71e

This wasn't a serious memory leak, because after a mount failure, MPD
would abort anyway, which is subject to the next commit.
2018-01-02 14:05:07 +01:00
Max Kellermann
4db1b1b250 storage/State: remove useless #ifdef ENABLE_DATABASE
This source file isn't compiled when the database is disabled.
2018-01-02 13:48:16 +01:00
Max Kellermann
ff6b263b48 increment version number to 0.20.15 2018-01-02 13:46:03 +01:00
Max Kellermann
c0bf052fa9 release v0.20.14 2018-01-01 17:55:38 +01:00
loujine
5419cff925 [doc] Fix outdated MusicBrainz URLs (closes ) 2018-01-01 17:30:24 +01:00
Max Kellermann
eee10ad2ed input/curl: add missing mutex locks to OnEnd(), OnError() 2017-12-26 20:01:13 +01:00
Max Kellermann
98472a8104 pcm/SampleFormat: remove wrong "malloc" attribute 2017-12-23 08:38:22 +01:00
Max Kellermann
d094c168aa archive/{iso9660,zzip}: unlock the mutex during I/O
Similar to commit 31ab78ae8e
2017-12-22 16:09:03 +01:00
Max Kellermann
4b18460bc6 archive/bz2: unlock the archive mutex and lock the file mutex
Fixes deadlock because FileInputStream::Read() unlocks the mutex
(which was not locked) and then locks it, keeping it locked.  This can
result in a deadlock.  This happens because the archive and the file
mutex are different.
2017-12-22 16:02:23 +01:00
Max Kellermann
412c0a965c util/WStringAPI: fix indent 2017-12-21 18:45:26 +01:00
Ilya ilyxa Tyshchenko
2becf79223 correct action for compile on Solaris 11.3 X86 2017-12-21 18:42:36 +01:00
Max Kellermann
43ec96d4a0 command/Error: translate std::{length_error,out_of_range} to ACK_ERROR_ARG 2017-12-21 10:22:04 +01:00
Max Kellermann
3d1d779da7 storage/State: use std::set instead of sorting a std::list 2017-12-21 10:22:00 +01:00
Max Kellermann
c88056ba83 db/simple: fix file corruption in the presence of mount points
If a directory is a mount point, omit the "directory: " as well.

This bug is years old, but has become more visible now that mount
points are persistent in the state file.
2017-12-21 10:16:52 +01:00
Max Kellermann
e769751221 increment version number to 0.20.14 2017-12-21 10:15:16 +01:00
Max Kellermann
49b9a90c3f release v0.20.13 2017-12-18 23:41:56 +01:00
FlashSystems
64d141f71e Save and restore mountpoints within the state file.
Signed-off-by: FlashSystems <developer@flashsystems.de>
2017-12-18 23:39:01 +01:00
FlashSystems
c488d3123f Fix lsinfo and add for mounted databases.
If `SimpleDatabase::Visit` is called on a database that contains a mounted directry the URIs of the elements passed to the callbacks are not prefixed by the mountpoint path. This leads to lsinfo and add not working because they use the wrong URI. This pull request is using the `WalkMount` helper function to create prefixed versions of `VisitDirectory`, `VisitSong` and `VisitPlaylist` to add the correct prefix to the parameters of the callback functions.
2017-12-18 23:33:08 +01:00
Stefano Miccoli
967af60327 rounds alsa HW mixer volume towards ±∞ depending on sgn(∆ vol)
This alleviates a problem in which 'volume +1' cannot be undo by
'volume -1' when using alsa hw mixer.

Closes 
2017-12-18 21:29:03 +01:00
Yue Wang
f1ef9f9d31 OSXOutputPlugin: set the buffer time to be 100ms
[mk: the following text was copied from
https://github.com/MusicPlayerDaemon/MPD/pull/167]

For certain format (hi-res files) and normal buffer size hardware, The
hardware may at once consume most of the buffers. However, in Delay()
function, MPD is supposed to wait for 25 ms after the next try. it
will create a hiccup. The negative impact is much major than
increasing the latency.

I understand larger buffers come at a price. That's why in my earlier
commit last year I significantly reduced it. However, the buffer size
in CoreAudio is set according to the hardware, which is super small
latency. For instance, the system audio of 2015 generation of macbook
pro has maximum buffer size of 4096 samples, which is just 0.09s for
44.1k framerate, or 0.04s for 96k frames --- . compare to the 0.5 sec
latency alsa plugin has, even if we quadruple it, it's still super
tiny.
2017-12-12 10:56:42 +01:00
Max Kellermann
dfaf08743c *: check defined(_WIN32) instead of defined(WIN32)
Only _WIN32 is defined by the compiler, and WIN32 is not standardized
and may be missing.

Closes 
2017-12-12 10:22:20 +01:00
Max Kellermann
d9552d8a6d android/build.py: support NDK r16 2017-12-12 10:01:47 +01:00
Max Kellermann
7586a8ab2c python/build/libs.py: disable the FFmpeg HEVC decoder due to clang build failure 2017-12-12 10:01:47 +01:00
Max Kellermann
e1a942250b python/build/libs.py: disable more FFmpeg features 2017-12-12 09:57:40 +01:00
Max Kellermann
72be0185de python/libs: upgrade Boost to 1.65.1 2017-12-12 09:16:40 +01:00
Max Kellermann
7e4cbce06b python/build/libs: upgrade CURL to 7.57.0 2017-12-12 09:15:24 +01:00
Max Kellermann
177d62f431 python/build/libs: upgrade FFmpeg to 3.4.1 2017-12-11 19:00:22 +01:00
Uwe Kleine-König
5a11e03725 lib/upnp: use include path without upnp/ prefix and honor pkg-config CFLAGS
If libupnp is installed in a non-standard location we must rely on the
include path provided by $(pkg-config --cflags libupnp). Relative to the
path given from that command no prefix must be used to find the respective
files.
2017-12-11 18:58:09 +01:00
Max Kellermann
75d068b7cd Makefile.am: include Windows cross-build script in source tarball 2017-12-05 11:24:52 +01:00
FlashSystems
1208503888 Removing gcc_malloc attribute from Directory::CreateChild to fix
assignment of `mnt->mounted_database` in `SimpleDatabase::Mount`.
2017-12-03 12:34:08 +01:00
Max Kellermann
de90d401d2 MusicChunk: add magic value IGNORE_REPLAY_GAIN
This fixes spurious replay gain logs when the player inserts silence
chunks, because those silence chunks had no replay gain attached,
resetting the ReplayGainFilter state, flipping it forth and back.
2017-12-03 11:39:12 +01:00
Max Kellermann
396defaea9 MusicChunk: initialize replay_gain_serial on demand 2017-12-03 11:39:07 +01:00
Max Kellermann
18f350cd04 player/Thread: initialize MusicChunk::bit_rate in SendSilence()
This attribute is not particularly important, but it was
uninitialized.
2017-12-03 10:54:14 +01:00
Max Kellermann
478180ebe4 queue/PlaylistEdit: shuffle appended songs only within its priority group
Fixes .
2017-12-02 17:17:02 +01:00
Max Kellermann
4a3059f509 queue/PlaylistControl: don't skip highest priority song on "play"
When starting playback with a specific song which does not have the
highest priority, the previous highest priority song was skipped
completely because its order was "swapped".  This commit changes to a
more expensive operation which inserts the selected song into the
order list.

This fixes a small part of 
2017-12-02 16:25:32 +01:00
Max Kellermann
78728138a0 lib/upnp/Compat: disable the 1.8 API emulation with libupnp 1.6.24
libupnp 1.6.24 added a few badly designed macros which break the MPD
build:

 8177a4195a/

To work around this, we disable our emulation functions (from
714011c81e) on this libupnp version.

Closes 
2017-12-02 14:47:27 +01:00
FlashSystems
63fc98591d Fix for "Mount-Points are purged from database on update/rescan."
Signed-off-by: FlashSystems <developer@flashsystems.de>
2017-11-27 22:34:49 +01:00
Max Kellermann
53def9a682 increment version number to 0.20.13 2017-11-27 22:32:55 +01:00
136 changed files with 1006 additions and 345 deletions
Makefile.amNEWS
android
configure.ac
doc/include
python/build
src
CommandLine.cxxLocateUri.hxxLogBackend.cxxLogInit.cxxLogLevel.hxxMain.cxxMain.hxxMusicChunk.hxxStateFile.cxxStateFile.hxxStats.cxxTimePrint.cxx
archive
client
command
config
db
decoder
event
filter
fs
input
lib
mixer
net
output
pcm
player
queue
storage
system
tag
thread
unix
util
win32
test

@@ -285,30 +285,62 @@ libmain_a_CPPFLAGS = $(AM_CPPFLAGS) -Iandroid/build/include
src_mpd_LDADD += libandroid.a libjava.a
all-local: android/build/bin/$(APK_NAME)-debug.apk
all-local: android/build/$(APK_NAME)-debug.apk
clean-local:
rm -rf android/build
libmpd.so: $(filter %.a,$(src_mpd_LDADD)) libmain.a
$(AM_V_CXXLD)$(CXXLD) -shared -Wl,--no-undefined,-shared,-Bsymbolic -llog -lz -o $@ $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) src/libmain_a-Main.o $(src_mpd_LDADD) $(LIBS)
android/build/build.xml: android/AndroidManifest.xml
rm -rf android/build
mkdir -p android/build/include android/build/res android/build/src/org
ln -s $(abs_srcdir)/android/AndroidManifest.xml $(abs_srcdir)/android/custom_rules.xml android/build
ln -s $(abs_srcdir)/android/src android/build/src/org/musicpd
ln -s $(abs_srcdir)/android/res/values $(abs_srcdir)/android/res/layout android/build/res
$(ANDROID_SDK)/tools/android update project --path android/build --target android-17 --name $(APK_NAME)
ANDROID_SDK_BUILD_TOOLS_VERSION = 20.0.0
ANDROID_SDK_PLATFORM = android-17
android/build/bin/classes/org/musicpd/Bridge.class: android/src/Bridge.java android/build/build.xml android/build/res/drawable/icon.png
cd android/build && ant compile-jni-classes
ANDROID_BUILD_TOOLS_DIR = $(ANDROID_SDK)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)
ANDROID_SDK_PLATFORM_DIR = $(ANDROID_SDK)/platforms/$(ANDROID_SDK_PLATFORM)
android/build/include/org_musicpd_Bridge.h: android/build/bin/classes/org/musicpd/Bridge.class
javah -classpath $(ANDROID_SDK)/platforms/android-17/android.jar:android/build/bin/classes -d $(@D) org.musicpd.Bridge
JAVAC = javac
AAPT = $(ANDROID_BUILD_TOOLS_DIR)/aapt
DX = $(ANDROID_BUILD_TOOLS_DIR)/dx
ZIPALIGN = $(ANDROID_BUILD_TOOLS_DIR)/zipalign
ANDROID_XML_RES := $(wildcard $(srcdir)/android/res/*/*.xml)
ANDROID_XML_RES_COPIES := $(patsubst $(srcdir)/android/%,android/build/%,$(ANDROID_XML_RES))
JAVA_SOURCE_NAMES = Bridge.java Loader.java Main.java
JAVA_SOURCES = $(addprefix $(srcdir)/android/src/,$(JAVA_SOURCE_NAMES))
JAVA_CLASSFILES_DIR = android/build/classes
$(ANDROID_XML_RES_COPIES): $(ANDROID_XML_RES)
@$(MKDIR_P) $(dir $@)
cp $(patsubst android/build/%,$(srcdir)/android/%,$@) $@
android/build/resources.apk: $(ANDROID_XML_RES_COPIES) android/build/res/drawable/icon.png
@$(MKDIR_P) android/build/gen
$(AAPT) package -f -m --auto-add-overlay \
--custom-package org.musicpd \
-M $(srcdir)/android/AndroidManifest.xml \
-S android/build/res \
-J android/build/gen \
-I $(ANDROID_SDK_PLATFORM_DIR)/android.jar \
-F android/build/resources.apk
# R.java is generated by aapt, when resources.apk is generated
android/build/gen/org/musicpd/R.java: android/build/resources.apk
android/build/classes.dex: $(JAVA_SOURCES) android/build/gen/org/musicpd/R.java
@$(MKDIR_P) $(JAVA_CLASSFILES_DIR)
$(JAVAC) -source 1.5 -target 1.5 -Xlint:-options \
-cp $(ANDROID_SDK_PLATFORM_DIR)/android.jar:$(JAVA_CLASSFILES_DIR) \
-d $(JAVA_CLASSFILES_DIR) $^
$(DX) --dex --output $@ $(JAVA_CLASSFILES_DIR)
android/build/include/org_musicpd_Bridge.h: android/build/classes.dex
javah -classpath $(ANDROID_SDK_PLATFORM_DIR)/android.jar:$(JAVA_CLASSFILES_DIR) -d $(@D) org.musicpd.Bridge
BUILT_SOURCES = android/build/include/org_musicpd_Bridge.h
android/build/libs/armeabi-v7a/libmpd.so: libmpd.so android/build/build.xml
android/build/lib/armeabi-v7a/libmpd.so: libmpd.so
mkdir -p $(@D)
rm -f $@
$(STRIP) -o $@ $<
@@ -317,24 +349,19 @@ android/build/res/drawable/icon.png: mpd.svg
mkdir -p $(@D)
rsvg-convert --width=48 --height=48 $< -o $@
APK_DEPS = android/build/res/drawable/icon.png \
android/build/libs/armeabi-v7a/libmpd.so \
$(wildcard $(srcdir)/android/src/*.java) \
android/build/build.xml
.DELETE_ON_ERROR: android/build/unsigned.apk
android/build/unsigned.apk: android/build/classes.dex android/build/resources.apk android/build/lib/armeabi-v7a/libmpd.so
cp android/build/resources.apk $@
cd $(dir $@) && zip -q -r $(notdir $@) classes.dex lib
android/build/bin/$(APK_NAME)-debug.apk: $(APK_DEPS)
cd android/build && ant nodeps debug
android/build/$(APK_NAME)-debug.apk: android/build/unsigned.apk
jarsigner -keystore $(HOME)/.android/debug.keystore -storepass android -signedjar $@ $< androiddebugkey
android/build/bin/$(APK_NAME)-release-unsigned.apk: $(APK_DEPS)
cd android/build && ant nodeps release
android/build/bin/$(APK_NAME)-release-unaligned.apk: android/build/bin/$(APK_NAME)-release-unsigned.apk
android/build/$(APK_NAME)-release-unaligned.apk: android/build/unsigned.apk
jarsigner -digestalg SHA1 -sigalg MD5withRSA -storepass:env ANDROID_KEYSTORE_PASS -keystore $(ANDROID_KEYSTORE) -signedjar $@ $< $(ANDROID_KEY_ALIAS)
ANDROID_SDK_BUILD_TOOLS_VERSION = 20.0.0
android/build/bin/$(APK_NAME).apk: android/build/bin/$(APK_NAME)-release-unaligned.apk
$(ANDROID_SDK)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/zipalign -f 4 $< $@
android/build/$(APK_NAME).apk: android/build/$(APK_NAME)-release-unaligned.apk
$(ZIPALIGN) -f 4 $< $@
endif
@@ -702,6 +729,7 @@ libstorage_a_SOURCES = \
src/storage/MemoryDirectoryReader.cxx src/storage/MemoryDirectoryReader.hxx \
src/storage/Configured.cxx src/storage/Configured.hxx \
src/storage/plugins/LocalStorage.cxx src/storage/plugins/LocalStorage.hxx \
src/storage/StorageState.cxx src/storage/StorageState.hxx \
src/storage/FileInfo.hxx
libstorage_a_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -754,6 +782,7 @@ libneighbor_a_SOURCES = \
src/neighbor/NeighborPlugin.hxx
libneighbor_a_CPPFLAGS = $(AM_CPPFLAGS) \
$(UPNP_CFLAGS) \
$(SMBCLIENT_CFLAGS)
if ENABLE_SMBCLIENT
@@ -803,6 +832,8 @@ libdb_plugins_a_SOURCES = \
src/db/plugins/simple/PrefixedLightSong.hxx \
src/db/plugins/simple/SimpleDatabasePlugin.cxx \
src/db/plugins/simple/SimpleDatabasePlugin.hxx
libdb_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \
$(UPNP_CFLAGS)
if ENABLE_LIBMPDCLIENT
libdb_plugins_a_SOURCES += \
@@ -2412,6 +2443,7 @@ EXTRA_DIST = $(doc_DATA) autogen.sh \
$(man_MANS) $(DOCBOOK_FILES) doc/mpdconf.example doc/doxygen.conf \
$(wildcard $(srcdir)/doc/include/*.xml) \
systemd/system/mpd.socket \
$(wildcard $(srcdir)/python/build/*.py) \
android/AndroidManifest.xml \
android/build.py \
android/custom_rules.xml \
@@ -2419,5 +2451,6 @@ EXTRA_DIST = $(doc_DATA) autogen.sh \
android/src/Bridge.java \
android/src/Loader.java \
android/src/Main.java \
win32/build.py \
win32/res/mpd.rc.in win32/res/mpd.ico \
src/haiku/App_MusicPD

34
NEWS

@@ -1,3 +1,37 @@
ver 0.20.15 (2018/01/05)
* queue: fix crash after seek failure
* resampler
- soxr: clear internal state after manual song change
* state file
- make mount point restore errors non-fatal
- fix crash when restoring mounts with incompatible database plugin
* Android
- build without Ant
- fix for SIGSYS crash
ver 0.20.14 (2018/01/01)
* database
- simple: fix file corruption in the presence of mount points
* archive
- bz2: fix deadlock
- reduce lock contention, fixing lots of xrun problems
* fix Solaris build failure
ver 0.20.13 (2017/12/18)
* output
- osx: set up ring buffer to hold at least 100ms
* mixer
- alsa: fix rounding errors
* database
- simple: don't purge mount points on update/rescan
- simple: fix "mount" bug caused by bad compiler optimization
- simple: fix "lsinfo" into mount points
- upnp: work around libupnp 1.6.24 API breakage
* queue: fix spuriously misplaced prioritized songs
* save and restore mountpoints within the state file
* include Windows cross-build script in source tarball
* fix Windows build failures
ver 0.20.12 (2017/11/25)
* database
- upnp: adapt to libupnp 1.8 API changes

@@ -46,13 +46,14 @@ class AndroidNdkToolchain:
self.ndk_arch = 'arm'
android_abi = 'armeabi-v7a'
ndk_platform = 'android-14'
ndk_platform = 'android-21'
# select the NDK compiler
gcc_version = '4.9'
ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform)
sysroot = os.path.join(ndk_platform_path, 'arch-' + self.ndk_arch)
sysroot = os.path.join(ndk_path, 'sysroot')
target_root = os.path.join(ndk_platform_path, 'arch-' + self.ndk_arch)
install_prefix = os.path.join(arch_path, 'root')
@@ -72,6 +73,8 @@ class AndroidNdkToolchain:
self.cxx = os.path.join(llvm_bin, 'clang++')
common_flags += ' -target ' + llvm_triple + ' -integrated-as -gcc-toolchain ' + toolchain_path
common_flags += ' -fvisibility=hidden -fdata-sections -ffunction-sections'
self.ar = os.path.join(toolchain_bin, arch + '-ar')
self.ranlib = os.path.join(toolchain_bin, arch + '-ranlib')
self.nm = os.path.join(toolchain_bin, arch + '-nm')
@@ -79,8 +82,15 @@ class AndroidNdkToolchain:
self.cflags = '-Os -g ' + common_flags
self.cxxflags = '-Os -g ' + common_flags
self.cppflags = '--sysroot=' + self.sysroot + ' -isystem ' + os.path.join(install_prefix, 'include')
self.ldflags = '--sysroot=' + self.sysroot + ' ' + common_flags + ' -L' + os.path.join(install_prefix, 'lib')
self.cppflags = '--sysroot=' + sysroot + \
' -isystem ' + os.path.join(install_prefix, 'include') + \
' -isystem ' + os.path.join(sysroot, 'usr', 'include', arch) + \
' -D__ANDROID_API__=21'
self.ldflags = '--sysroot=' + sysroot + \
' -L' + os.path.join(install_prefix, 'lib') + \
' -L' + os.path.join(target_root, 'usr', 'lib') + \
' -B' + os.path.join(target_root, 'usr', 'lib') + \
' ' + common_flags
self.libs = ''
self.is_arm = self.ndk_arch == 'arm'

@@ -1,10 +1,10 @@
AC_PREREQ(2.60)
AC_INIT(mpd, 0.20.12, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.20.15, musicpd-dev-team@lists.sourceforge.net)
VERSION_MAJOR=0
VERSION_MINOR=20
VERSION_REVISION=12
VERSION_REVISION=15
VERSION_EXTRA=0
AC_CONFIG_SRCDIR([src/Main.cxx])
@@ -492,7 +492,7 @@ if test x$enable_ipv6 = xyes; then
AC_EGREP_CPP([AP_maGiC_VALUE],
[
#include <sys/types.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>

@@ -113,7 +113,7 @@
<para>
<varname>musicbrainz_artistid</varname>: the artist id in the
<ulink
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
database.
</para>
</listitem>
@@ -122,7 +122,7 @@
<para>
<varname>musicbrainz_albumid</varname>: the album id in the
<ulink
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
database.
</para>
</listitem>
@@ -131,7 +131,7 @@
<para>
<varname>musicbrainz_albumartistid</varname>: the album artist
id in the <ulink
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
database.
</para>
</listitem>
@@ -140,7 +140,7 @@
<para>
<varname>musicbrainz_trackid</varname>: the track id in the
<ulink
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
database.
</para>
</listitem>
@@ -149,7 +149,7 @@
<para>
<varname>musicbrainz_releasetrackid</varname>: the release track
id in the <ulink
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
database.
</para>
</listitem>

@@ -1,21 +1,28 @@
import os.path, subprocess
import os.path, subprocess, sys
from build.project import Project
from build.makeproject import MakeProject
class AutotoolsProject(Project):
class AutotoolsProject(MakeProject):
def __init__(self, url, md5, installed, configure_args=[],
autogen=False,
cppflags='',
ldflags='',
libs='',
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
MakeProject.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
self.autogen = autogen
self.cppflags = cppflags
self.ldflags = ldflags
self.libs = libs
def build(self, toolchain):
def configure(self, toolchain):
src = self.unpack(toolchain)
if self.autogen:
subprocess.check_call(['libtoolize', '--force'], cwd=src)
if sys.platform == 'darwin':
subprocess.check_call(['glibtoolize', '--force'], cwd=src)
else:
subprocess.check_call(['libtoolize', '--force'], cwd=src)
subprocess.check_call(['aclocal'], cwd=src)
subprocess.check_call(['automake', '--add-missing', '--force-missing', '--foreign'], cwd=src)
subprocess.check_call(['autoconf'], cwd=src)
@@ -29,8 +36,8 @@ class AutotoolsProject(Project):
'CFLAGS=' + toolchain.cflags,
'CXXFLAGS=' + toolchain.cxxflags,
'CPPFLAGS=' + toolchain.cppflags + ' ' + self.cppflags,
'LDFLAGS=' + toolchain.ldflags,
'LIBS=' + toolchain.libs,
'LDFLAGS=' + toolchain.ldflags + ' ' + self.ldflags,
'LIBS=' + toolchain.libs + ' ' + self.libs,
'AR=' + toolchain.ar,
'RANLIB=' + toolchain.ranlib,
'STRIP=' + toolchain.strip,
@@ -40,7 +47,8 @@ class AutotoolsProject(Project):
] + self.configure_args
subprocess.check_call(configure, cwd=build, env=toolchain.env)
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'],
cwd=build, env=toolchain.env)
subprocess.check_call(['/usr/bin/make', '--quiet', 'install'],
cwd=build, env=toolchain.env)
return build
def build(self, toolchain):
build = self.configure(toolchain)
MakeProject.build(self, toolchain, build)

@@ -1,3 +1,4 @@
import re
from build.project import Project
from build.zlib import ZlibProject
from build.autotools import AutotoolsProject
@@ -5,24 +6,33 @@ from build.ffmpeg import FfmpegProject
from build.boost import BoostProject
libogg = AutotoolsProject(
'http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz',
'5c3a34309d8b98640827e5d0991a4015',
'http://downloads.xiph.org/releases/ogg/libogg-1.3.3.tar.xz',
'4f3fc6178a533d392064f14776b23c397ed4b9f48f5de297aba73b643f955c08',
'lib/libogg.a',
['--disable-shared', '--enable-static'],
[
'--disable-shared', '--enable-static',
],
)
libvorbis = AutotoolsProject(
'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz',
'28cb28097c07a735d6af56e598e1c90f',
'lib/libvorbis.a',
['--disable-shared', '--enable-static'],
[
'--disable-shared', '--enable-static',
],
)
opus = AutotoolsProject(
'https://archive.mozilla.org/pub/opus/opus-1.2.1.tar.gz',
'cfafd339ccd9c5ef8d6ab15d7e1a412c054bf4cb4ecbbbcc78c12ef2def70732',
'lib/libopus.a',
['--disable-shared', '--enable-static'],
[
'--disable-shared', '--enable-static',
],
# suppress "visibility default" from opus_defines.h
cppflags='-DOPUS_EXPORT=',
)
flac = AutotoolsProject(
@@ -45,15 +55,30 @@ libid3tag = AutotoolsProject(
'ftp://ftp.mars.org/pub/mpeg/libid3tag-0.15.1b.tar.gz',
'e5808ad997ba32c498803822078748c3',
'lib/libid3tag.a',
['--disable-shared', '--enable-static'],
[
'--disable-shared', '--enable-static',
# without this, libid3tag's configure.ac ignores -O* and -f*
'--disable-debugging',
],
autogen=True,
edits={
# fix bug in libid3tag's configure.ac which discards all but the last optimization flag
'configure.ac': lambda data: re.sub(r'optimize="\$1"', r'optimize="$optimize $1"', data, count=1),
}
)
libmad = AutotoolsProject(
'ftp://ftp.mars.org/pub/mpeg/libmad-0.15.1b.tar.gz',
'1be543bc30c56fb6bea1d7bf6a64e66c',
'lib/libmad.a',
['--disable-shared', '--enable-static'],
[
'--disable-shared', '--enable-static',
# without this, libmad's configure.ac ignores -O* and -f*
'--disable-debugging',
],
autogen=True,
)
@@ -69,8 +94,8 @@ liblame = AutotoolsProject(
)
ffmpeg = FfmpegProject(
'http://ffmpeg.org/releases/ffmpeg-3.3.3.tar.xz',
'd2a9002cdc6b533b59728827186c044ad02ba64841f1b7cd6c21779875453a1e',
'http://ffmpeg.org/releases/ffmpeg-3.4.1.tar.xz',
'5a77278a63741efa74e26bf197b9bb09ac6381b9757391b922407210f0f991c0',
'lib/libavcodec.a',
[
'--disable-shared', '--enable-static',
@@ -84,17 +109,234 @@ ffmpeg = FfmpegProject(
'--disable-swscale',
'--disable-postproc',
'--disable-avfilter',
'--disable-lzo',
'--disable-faan',
'--disable-pixelutils',
'--disable-network',
'--disable-encoders',
'--disable-muxers',
'--disable-protocols',
'--disable-outdevs',
'--disable-devices',
'--disable-filters',
'--disable-filters',
'--disable-v4l2_m2m',
'--disable-parser=bmp',
'--disable-parser=cavsvideo',
'--disable-parser=dvbsub',
'--disable-parser=dvdsub',
'--disable-parser=dvd_nav',
'--disable-parser=flac',
'--disable-parser=g729',
'--disable-parser=gsm',
'--disable-parser=h261',
'--disable-parser=h263',
'--disable-parser=h264',
'--disable-parser=hevc',
'--disable-parser=mjpeg',
'--disable-parser=mlp',
'--disable-parser=mpeg4video',
'--disable-parser=mpegaudio',
'--disable-parser=mpegvideo',
'--disable-parser=opus',
'--disable-parser=vc1',
'--disable-parser=vp3',
'--disable-parser=vp8',
'--disable-parser=vp9',
'--disable-parser=png',
'--disable-parser=pnm',
'--disable-parser=xma',
'--disable-demuxer=aqtitle',
'--disable-demuxer=ass',
'--disable-demuxer=bethsoftvid',
'--disable-demuxer=bink',
'--disable-demuxer=cavsvideo',
'--disable-demuxer=cdxl',
'--disable-demuxer=dvbsub',
'--disable-demuxer=dvbtxt',
'--disable-demuxer=h261',
'--disable-demuxer=h263',
'--disable-demuxer=h264',
'--disable-demuxer=ico',
'--disable-demuxer=image2',
'--disable-demuxer=jacosub',
'--disable-demuxer=lrc',
'--disable-demuxer=microdvd',
'--disable-demuxer=mjpeg',
'--disable-demuxer=mjpeg_2000',
'--disable-demuxer=mpegps',
'--disable-demuxer=mpegvideo',
'--disable-demuxer=mpl2',
'--disable-demuxer=mpsub',
'--disable-demuxer=pjs',
'--disable-demuxer=rawvideo',
'--disable-demuxer=realtext',
'--disable-demuxer=sami',
'--disable-demuxer=scc',
'--disable-demuxer=srt',
'--disable-demuxer=stl',
'--disable-demuxer=subviewer',
'--disable-demuxer=subviewer1',
'--disable-demuxer=swf',
'--disable-demuxer=tedcaptions',
'--disable-demuxer=vobsub',
'--disable-demuxer=vplayer',
'--disable-demuxer=webvtt',
'--disable-demuxer=yuv4mpegpipe',
# we don't need these decoders, because we have the dedicated
# libraries
'--disable-decoder=flac',
'--disable-decoder=mp1',
'--disable-decoder=mp1float',
'--disable-decoder=mp2',
'--disable-decoder=mp2float',
'--disable-decoder=mp3',
'--disable-decoder=mp3adu',
'--disable-decoder=mp3adufloat',
'--disable-decoder=mp3float',
'--disable-decoder=mp3on4',
'--disable-decoder=mp3on4float',
'--disable-decoder=opus',
'--disable-decoder=vorbis',
# audio codecs nobody uses
'--disable-decoder=atrac1',
'--disable-decoder=atrac3',
'--disable-decoder=atrac3al',
'--disable-decoder=atrac3p',
'--disable-decoder=atrac3pal',
'--disable-decoder=binkaudio_dct',
'--disable-decoder=binkaudio_rdft',
'--disable-decoder=bmv_audio',
'--disable-decoder=dsicinaudio',
'--disable-decoder=dvaudio',
'--disable-decoder=metasound',
'--disable-decoder=paf_audio',
'--disable-decoder=ra_144',
'--disable-decoder=ra_288',
'--disable-decoder=ralf',
'--disable-decoder=qdm2',
'--disable-decoder=qdmc',
# disable lots of image and video codecs
'--disable-decoder=ass',
'--disable-decoder=asv1',
'--disable-decoder=asv2',
'--disable-decoder=apng',
'--disable-decoder=avrn',
'--disable-decoder=avrp',
'--disable-decoder=bethsoftvid',
'--disable-decoder=bink',
'--disable-decoder=bmp',
'--disable-decoder=bmv_video',
'--disable-decoder=cavs',
'--disable-decoder=ccaption',
'--disable-decoder=cdgraphics',
'--disable-decoder=clearvideo',
'--disable-decoder=dirac',
'--disable-decoder=dsicinvideo',
'--disable-decoder=dvbsub',
'--disable-decoder=dvdsub',
'--disable-decoder=dvvideo',
'--disable-decoder=exr',
'--disable-decoder=ffv1',
'--disable-decoder=ffvhuff',
'--disable-decoder=ffwavesynth',
'--disable-decoder=flic',
'--disable-decoder=flv',
'--disable-decoder=fraps',
'--disable-decoder=gif',
'--disable-decoder=h261',
'--disable-decoder=h263',
'--disable-decoder=h263i',
'--disable-decoder=h263p',
'--disable-decoder=h264',
'--disable-decoder=hevc',
'--disable-decoder=hnm4_video',
'--disable-decoder=hq_hqa',
'--disable-decoder=hqx',
'--disable-decoder=idcin',
'--disable-decoder=iff_ilbm',
'--disable-decoder=indeo2',
'--disable-decoder=indeo3',
'--disable-decoder=indeo4',
'--disable-decoder=indeo5',
'--disable-decoder=interplay_video',
'--disable-decoder=jacosub',
'--disable-decoder=jpeg2000',
'--disable-decoder=jpegls',
'--disable-decoder=microdvd',
'--disable-decoder=mimic',
'--disable-decoder=mjpeg',
'--disable-decoder=mmvideo',
'--disable-decoder=mpl2',
'--disable-decoder=motionpixels',
'--disable-decoder=mpeg1video',
'--disable-decoder=mpeg2video',
'--disable-decoder=mpeg4',
'--disable-decoder=mpegvideo',
'--disable-decoder=mscc',
'--disable-decoder=msmpeg4_crystalhd',
'--disable-decoder=msmpeg4v1',
'--disable-decoder=msmpeg4v2',
'--disable-decoder=msmpeg4v3',
'--disable-decoder=msvideo1',
'--disable-decoder=mszh',
'--disable-decoder=mvc1',
'--disable-decoder=mvc2',
'--disable-decoder=on2avc',
'--disable-decoder=paf_video',
'--disable-decoder=png',
'--disable-decoder=qdraw',
'--disable-decoder=qpeg',
'--disable-decoder=rawvideo',
'--disable-decoder=realtext',
'--disable-decoder=roq',
'--disable-decoder=roq_dpcm',
'--disable-decoder=rscc',
'--disable-decoder=rv10',
'--disable-decoder=rv20',
'--disable-decoder=rv30',
'--disable-decoder=rv40',
'--disable-decoder=sami',
'--disable-decoder=sheervideo',
'--disable-decoder=snow',
'--disable-decoder=srt',
'--disable-decoder=stl',
'--disable-decoder=subrip',
'--disable-decoder=subviewer',
'--disable-decoder=subviewer1',
'--disable-decoder=svq1',
'--disable-decoder=svq3',
'--disable-decoder=tiff',
'--disable-decoder=mottiertexseqvideo',
'--disable-decoder=truemotion1',
'--disable-decoder=truemotion2',
'--disable-decoder=truemotion2rt',
'--disable-decoder=twinvq',
'--disable-decoder=utvideo',
'--disable-decoder=vc1',
'--disable-decoder=vmdvideo',
'--disable-decoder=vp3',
'--disable-decoder=vp5',
'--disable-decoder=vp6',
'--disable-decoder=vp7',
'--disable-decoder=vp8',
'--disable-decoder=vp9',
'--disable-decoder=vqa',
'--disable-decoder=webvtt',
'--disable-decoder=wmv1',
'--disable-decoder=wmv2',
'--disable-decoder=wmv3',
'--disable-decoder=yuv4',
],
)
curl = AutotoolsProject(
'http://curl.haxx.se/download/curl-7.55.1.tar.xz',
'3eafca6e84ecb4af5f35795dee84e643d5428287e88c041122bb8dac18676bb7',
'http://curl.haxx.se/download/curl-7.57.0.tar.xz',
'f5f6fd3c72b7b8389969f4fb671ed8532fa9b5bb7a5cae7ca89bc1cea45c7878',
'lib/libcurl.a',
[
'--disable-shared', '--enable-static',
@@ -105,6 +347,7 @@ curl = AutotoolsProject(
'--disable-ldap', '--disable-ldaps',
'--disable-rtsp', '--disable-proxy', '--disable-dict', '--disable-telnet',
'--disable-tftp', '--disable-pop3', '--disable-imap', '--disable-smtp',
'--disable-smb',
'--disable-gopher',
'--disable-manual',
'--disable-threaded-resolver', '--disable-verbose', '--disable-sspi',
@@ -114,7 +357,7 @@ curl = AutotoolsProject(
)
boost = BoostProject(
'http://downloads.sourceforge.net/project/boost/boost/1.65.0/boost_1_65_0.tar.bz2',
'ea26712742e2fb079c2a566a31f3266973b76e38222b9f88b387e3c8b2f9902c',
'http://downloads.sourceforge.net/project/boost/boost/1.66.0/boost_1_66_0.tar.bz2',
'5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9',
'include/boost/version.hpp',
)

@@ -0,0 +1,28 @@
import subprocess
from build.project import Project
class MakeProject(Project):
def __init__(self, url, md5, installed,
install_target='install',
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.install_target = install_target
def get_simultaneous_jobs(self):
return 12
def get_make_args(self, toolchain):
return ['--quiet', '-j' + str(self.get_simultaneous_jobs())]
def get_make_install_args(self, toolchain):
return ['--quiet', self.install_target]
def make(self, toolchain, wd, args):
subprocess.check_call(['/usr/bin/make'] + args,
cwd=wd, env=toolchain.env)
def build(self, toolchain, wd, install=True):
self.make(toolchain, wd, self.get_make_args(toolchain))
if install:
self.make(toolchain, wd, self.get_make_install_args(toolchain))

@@ -7,6 +7,7 @@ from build.tar import untar
class Project:
def __init__(self, url, md5, installed, name=None, version=None,
base=None,
edits=None,
use_cxx=False):
if base is None:
basename = os.path.basename(url)
@@ -28,6 +29,7 @@ class Project:
self.md5 = md5
self.installed = installed
self.edits = edits
self.use_cxx = use_cxx
def download(self, toolchain):
@@ -47,7 +49,18 @@ class Project:
parent_path = toolchain.src_path
else:
parent_path = toolchain.build_path
return untar(self.download(toolchain), parent_path, self.base)
path = untar(self.download(toolchain), parent_path, self.base)
if self.edits is not None:
for filename, function in self.edits.items():
with open(os.path.join(path, filename), 'r+t') as f:
old_data = f.read()
new_data = function(old_data)
f.seek(0)
f.truncate(0)
f.write(new_data)
return path
def make_build_path(self, toolchain):
path = os.path.join(toolchain.build_path, self.base)

@@ -67,7 +67,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#ifdef _WIN32
#define CONFIG_FILE_LOCATION PATH_LITERAL("mpd\\mpd.conf")
#define APP_CONFIG_FILE_LOCATION PATH_LITERAL("conf\\mpd.conf")
#else
@@ -389,7 +389,7 @@ ParseCommandLine(int argc, char **argv, struct options *options)
ConfigLoader loader;
bool found =
#ifdef WIN32
#ifdef _WIN32
loader.TryFile(GetUserConfigDir(), CONFIG_FILE_LOCATION) ||
loader.TryFile(GetSystemConfigDir(), CONFIG_FILE_LOCATION) ||
loader.TryFile(GetAppBaseDir(), APP_CONFIG_FILE_LOCATION);

@@ -24,7 +24,7 @@
#include "Compiler.h"
#include "fs/AllocatedPath.hxx"
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ABSOLUTE

@@ -162,7 +162,7 @@ FileLog(const Domain &domain, const char *message)
domain.GetName(),
chomp_length(message), message);
#ifdef WIN32
#ifdef _WIN32
/* force-flush the log file, because setvbuf() does not seem
to have an effect on WIN32 */
fflush(stderr);

@@ -72,7 +72,7 @@ log_init_file(int line)
out_fd = open_log_file();
if (out_fd < 0) {
#ifdef WIN32
#ifdef _WIN32
const std::string out_path_utf8 = out_path.ToUTF8();
throw FormatRuntimeError("failed to open log file \"%s\" (config line %d)",
out_path_utf8.c_str(), line);
@@ -182,7 +182,7 @@ void setup_log_output()
fflush(nullptr);
if (out_fd < 0) {
#ifdef WIN32
#ifdef _WIN32
return;
#else
out_fd = open("/dev/null", O_WRONLY);

@@ -20,7 +20,7 @@
#ifndef MPD_LOG_LEVEL_HXX
#define MPD_LOG_LEVEL_HXX
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ERROR

@@ -106,7 +106,7 @@
#include <locale.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
@@ -289,7 +289,7 @@ glue_state_file_init()
*/
static void winsock_init(void)
{
#ifdef WIN32
#ifdef _WIN32
WSADATA sockinfo;
int retval = WSAStartup(MAKEWORD(2, 2), &sockinfo);
@@ -418,7 +418,7 @@ Instance::OnIdle(unsigned flags)
int main(int argc, char *argv[])
{
#ifdef WIN32
#ifdef _WIN32
return win32_main(argc, argv);
#else
return mpd_main(argc, argv);
@@ -615,7 +615,7 @@ try {
playlist_state_restore() */
instance->partition->pc.LockUpdateAudio();
#ifdef WIN32
#ifdef _WIN32
win32_app_started();
#endif
@@ -630,7 +630,7 @@ try {
/* run the main loop */
instance->event_loop.Run();
#ifdef WIN32
#ifdef _WIN32
win32_app_stopping();
#endif
@@ -702,7 +702,7 @@ try {
daemonize_finish();
#endif
#ifdef WIN32
#ifdef _WIN32
WSACleanup();
#endif

@@ -42,7 +42,7 @@ int mpd_main(int argc, char *argv[]);
#endif
#ifdef WIN32
#ifdef _WIN32
/**
* If program is run as windows service performs nessesary initialization

@@ -79,12 +79,20 @@ struct MusicChunk {
*/
ReplayGainInfo replay_gain_info;
/**
* A magic value for #replay_gain_serial which omits updating
* the #ReplayGainFilter. This is used by "silence" chunks
* (see PlayerThread::SendSilence()) so they don't affect the
* replay gain.
*/
static constexpr unsigned IGNORE_REPLAY_GAIN = ~0u;
/**
* A serial number for checking if replay gain info has
* changed since the last chunk. The magic value 0 indicates
* that there is no replay gain info available.
*/
unsigned replay_gain_serial = 0;
unsigned replay_gain_serial;
/** the data (probably PCM) */
uint8_t data[CHUNK_SIZE];

@@ -24,6 +24,7 @@
#include "fs/io/TextFile.hxx"
#include "fs/io/FileOutputStream.hxx"
#include "fs/io/BufferedOutputStream.hxx"
#include "storage/StorageState.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "mixer/Volume.hxx"
@@ -56,6 +57,9 @@ StateFile::RememberVersions() noexcept
prev_output_version = audio_output_state_get_version();
prev_playlist_version = playlist_state_get_hash(partition.playlist,
partition.pc);
#ifdef ENABLE_DATABASE
prev_storage_version = storage_state_get_hash(partition.instance);
#endif
}
bool
@@ -64,7 +68,11 @@ StateFile::IsModified() const noexcept
return prev_volume_version != sw_volume_state_get_hash() ||
prev_output_version != audio_output_state_get_version() ||
prev_playlist_version != playlist_state_get_hash(partition.playlist,
partition.pc);
partition.pc)
#ifdef ENABLE_DATABASE
|| prev_storage_version != storage_state_get_hash(partition.instance)
#endif
;
}
inline void
@@ -72,6 +80,11 @@ StateFile::Write(BufferedOutputStream &os)
{
save_sw_volume_state(os);
audio_output_state_save(os, partition.outputs);
#ifdef ENABLE_DATABASE
storage_state_save(os, partition.instance);
#endif
playlist_state_save(os, partition.playlist, partition.pc);
}
@@ -123,6 +136,10 @@ try {
playlist_state_restore(line, file, song_loader,
partition.playlist,
partition.pc);
#ifdef ENABLE_DATABASE
success = success || storage_state_restore(line, file, partition.instance);
#endif
if (!success)
FormatError(state_file_domain,
"Unrecognized line in state file: %s",

@@ -46,6 +46,10 @@ class StateFile final : private TimeoutMonitor {
unsigned prev_volume_version = 0, prev_output_version = 0,
prev_playlist_version = 0;
#ifdef ENABLE_DATABASE
unsigned prev_storage_version = 0;
#endif
public:
static constexpr std::chrono::steady_clock::duration DEFAULT_INTERVAL = std::chrono::minutes(2);

@@ -31,7 +31,7 @@
#include <chrono>
#ifndef WIN32
#ifndef _WIN32
/**
* The monotonic time stamp when MPD was started. It is used to
* calculate the uptime.
@@ -114,7 +114,7 @@ stats_print(Response &r, const Partition &partition)
{
r.Format("uptime: %u\n"
"playtime: %lu\n",
#ifdef WIN32
#ifdef _WIN32
GetProcessUptimeS(),
#else
(unsigned)std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start_time).count(),

@@ -24,7 +24,7 @@
void
time_print(Response &r, const char *name, time_t t)
{
#ifdef WIN32
#ifdef _WIN32
const struct tm *tm2 = gmtime(&t);
#else
struct tm tm;
@@ -35,7 +35,7 @@ time_print(Response &r, const char *name, time_t t)
char buffer[32];
strftime(buffer, sizeof(buffer),
#ifdef WIN32
#ifdef _WIN32
"%Y-%m-%dT%H:%M:%SZ",
#else
"%FT%TZ",

@@ -162,7 +162,7 @@ Bzip2InputStream::FillBuffer()
if (bzstream.avail_in > 0)
return true;
size_t count = archive->istream->Read(buffer, sizeof(buffer));
size_t count = archive->istream->LockRead(buffer, sizeof(buffer));
if (count == 0)
return false;
@@ -174,6 +174,8 @@ Bzip2InputStream::FillBuffer()
size_t
Bzip2InputStream::Read(void *ptr, size_t length)
{
const ScopeUnlock unlock(mutex);
int bz_result;
size_t nbytes = 0;
@@ -224,4 +226,3 @@ const ArchivePlugin bz2_archive_plugin = {
bz2_open,
bz2_extensions,
};

@@ -182,6 +182,8 @@ Iso9660ArchiveFile::OpenStream(const char *pathname,
size_t
Iso9660InputStream::Read(void *ptr, size_t read_size)
{
const ScopeUnlock unlock(mutex);
int readed = 0;
int no_blocks, cur_block;
size_t left_bytes = statbuf->size - offset;

@@ -138,6 +138,8 @@ ZzipArchiveFile::OpenStream(const char *pathname,
size_t
ZzipInputStream::Read(void *ptr, size_t read_size)
{
const ScopeUnlock unlock(mutex);
int ret = zzip_file_read(file, ptr, read_size);
if (ret < 0)
throw std::runtime_error("zzip_file_read() has failed");
@@ -155,6 +157,8 @@ ZzipInputStream::IsEOF() noexcept
void
ZzipInputStream::Seek(offset_type new_offset)
{
const ScopeUnlock unlock(mutex);
zzip_off_t ofs = zzip_seek(file, new_offset, SEEK_SET);
if (ofs < 0)
throw std::runtime_error("zzip_seek() has failed");

@@ -28,7 +28,7 @@
void
Client::AllowFile(Path path_fs) const
{
#ifdef WIN32
#ifdef _WIN32
(void)path_fs;
throw ProtocolError(ACK_ERROR_PERMISSION, "Access denied");

@@ -24,7 +24,7 @@
#include <string>
#ifdef WIN32
#ifdef _WIN32
/* fuck WIN32! */
#include <windows.h>
#undef GetMessage

@@ -29,7 +29,7 @@
#include "Log.hxx"
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>

@@ -123,6 +123,10 @@ ToAck(std::exception_ptr ep) noexcept
return ACK_ERROR_SYSTEM;
} catch (const std::invalid_argument &e) {
return ACK_ERROR_ARG;
} catch (const std::length_error &e) {
return ACK_ERROR_ARG;
} catch (const std::out_of_range &e) {
return ACK_ERROR_ARG;
#ifdef GLIBCXX_49X
} catch (const std::exception &e) {
#else

@@ -20,7 +20,7 @@
#ifndef MPD_COMMAND_RESULT_HXX
#define MPD_COMMAND_RESULT_HXX
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ERROR

@@ -58,7 +58,7 @@ skip_path(Path name_fs) noexcept
return name_fs.HasNewline();
}
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
/* PRIu64 causes bogus compiler warning */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
@@ -101,7 +101,7 @@ handle_listfiles_local(Response &r, Path path_fs)
return CommandResult::OK;
}
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic pop
#endif

@@ -50,7 +50,7 @@ skip_path(const char *name_utf8) noexcept
return strchr(name_utf8, '\n') != nullptr;
}
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
/* PRIu64 causes bogus compiler warning */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
@@ -94,7 +94,7 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
}
}
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic pop
#endif

@@ -22,7 +22,7 @@
#include "Compiler.h"
#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7)
#if defined(_WIN32) && CLANG_OR_GCC_VERSION(4,7)
/* "INPUT" is declared by winuser.h */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
@@ -93,7 +93,7 @@ enum class ConfigBlockOption {
MAX
};
#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7)
#if defined(_WIN32) && CLANG_OR_GCC_VERSION(4,7)
#pragma GCC diagnostic pop
#endif

@@ -29,7 +29,7 @@
#include <assert.h>
#include <string.h>
#ifndef WIN32
#ifndef _WIN32
#include <pwd.h>
/**
@@ -79,7 +79,7 @@ ParsePath(const char *path)
{
assert(path != nullptr);
#ifndef WIN32
#ifndef _WIN32
if (path[0] == '~') {
++path;
@@ -119,7 +119,7 @@ ParsePath(const char *path)
} else {
#endif
return AllocatedPath::FromUTF8Throw(path);
#ifndef WIN32
#ifndef _WIN32
}
#endif
}

@@ -109,7 +109,7 @@ Directory::PruneEmpty() noexcept
child != end;) {
child->PruneEmpty();
if (child->IsEmpty())
if (child->IsEmpty() && !child->IsMount())
child = children.erase_and_dispose(child,
DeleteDisposer());
else
@@ -230,7 +230,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
call will lock it again */
const ScopeDatabaseUnlock unlock;
WalkMount(GetPath(), *mounted_database,
recursive, filter,
"", recursive, filter,
visit_directory, visit_song,
visit_playlist);
return;

@@ -127,7 +127,6 @@ public:
*
* @param name_utf8 the UTF-8 encoded name of the new sub directory
*/
gcc_malloc
Directory *CreateChild(const char *name_utf8);
/**

@@ -82,10 +82,11 @@ directory_save(BufferedOutputStream &os, const Directory &directory)
}
for (const auto &child : directory.children) {
os.Format(DIRECTORY_DIR "%s\n", child.GetName());
if (child.IsMount())
continue;
if (!child.IsMount())
directory_save(os, child);
os.Format(DIRECTORY_DIR "%s\n", child.GetName());
directory_save(os, child);
}
for (const auto &song : directory.songs)

@@ -72,7 +72,7 @@ PrefixVisitPlaylist(const char *base, const VisitPlaylist &visit_playlist,
void
WalkMount(const char *base, const Database &db,
bool recursive, const SongFilter *filter,
const char* uri, bool recursive, const SongFilter *filter,
const VisitDirectory &visit_directory, const VisitSong &visit_song,
const VisitPlaylist &visit_playlist)
{
@@ -93,5 +93,5 @@ WalkMount(const char *base, const Database &db,
vp = std::bind(PrefixVisitPlaylist,
base, std::ref(visit_playlist), _1, _2);
db.Visit(DatabaseSelection("", recursive, filter), vd, vs, vp);
db.Visit(DatabaseSelection(uri, recursive, filter), vd, vs, vp);
}

@@ -27,7 +27,7 @@ class SongFilter;
void
WalkMount(const char *base, const Database &db,
bool recursive, const SongFilter *filter,
const char* uri, bool recursive, const SongFilter *filter,
const VisitDirectory &visit_directory, const VisitSong &visit_song,
const VisitPlaylist &visit_playlist);

@@ -20,6 +20,7 @@
#include "config.h"
#include "SimpleDatabasePlugin.hxx"
#include "PrefixedLightSong.hxx"
#include "Mount.hxx"
#include "db/DatabasePlugin.hxx"
#include "db/Selection.hxx"
#include "db/Helpers.hxx"
@@ -115,7 +116,7 @@ SimpleDatabase::Check() const
path_utf8 + "\" because the "
"parent path is not a directory");
#ifndef WIN32
#ifndef _WIN32
/* Check if we can write to the directory */
if (!CheckAccess(dirPath, X_OK | W_OK)) {
const int e = errno;
@@ -134,7 +135,7 @@ SimpleDatabase::Check() const
if (!fi.IsRegular())
throw std::runtime_error("db file \"" + path_utf8 + "\" is not a regular file");
#ifndef WIN32
#ifndef _WIN32
/* And check that we can write to it */
if (!CheckAccess(path, R_OK | W_OK))
throw FormatErrno("Can't open db file \"%s\" for reading/writing",
@@ -270,6 +271,18 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
ScopeDatabaseLock protect;
auto r = root->LookupDirectory(selection.uri.c_str());
if (r.directory->IsMount()) {
/* pass the request and the remaining uri to the mounted database */
protect.unlock();
WalkMount(r.directory->GetPath(), *(r.directory->mounted_database),
(r.uri == nullptr)?"":r.uri, selection.recursive, selection.filter,
visit_directory, visit_song, visit_playlist);
return;
}
if (r.uri == nullptr) {
/* it's a directory */

@@ -91,7 +91,7 @@ bool
directory_child_access(Storage &storage, const Directory &directory,
const char *name, int mode) noexcept
{
#ifdef WIN32
#ifdef _WIN32
/* CheckAccess() is useless on WIN32 */
(void)storage;
(void)directory;

@@ -55,7 +55,7 @@ UpdateWalk::UpdateWalk(EventLoop &_loop, DatabaseListener &_listener,
storage(_storage),
editor(_loop, _listener)
{
#ifndef WIN32
#ifndef _WIN32
follow_inside_symlinks =
config_get_bool(ConfigOption::FOLLOW_INSIDE_SYMLINKS,
DEFAULT_FOLLOW_INSIDE_SYMLINKS);
@@ -104,7 +104,7 @@ inline void
UpdateWalk::PurgeDeletedFromDirectory(Directory &directory)
{
directory.ForEachChildSafe([&](Directory &child){
if (DirectoryExists(storage, child))
if (child.IsMount() || DirectoryExists(storage, child))
return;
editor.LockDeleteDirectory(&child);
@@ -133,7 +133,7 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory)
}
}
#ifndef WIN32
#ifndef _WIN32
static bool
update_directory_stat(Storage &storage, Directory &directory)
{
@@ -156,7 +156,7 @@ static int
FindAncestorLoop(Storage &storage, Directory *parent,
unsigned inode, unsigned device)
{
#ifndef WIN32
#ifndef _WIN32
if (device == 0 && inode == 0)
/* can't detect loops if the Storage does not support
these numbers */
@@ -258,7 +258,7 @@ bool
UpdateWalk::SkipSymlink(const Directory *directory,
const char *utf8_name) const noexcept
{
#ifndef WIN32
#ifndef _WIN32
const auto path_fs = storage.MapChildFS(directory->GetPath(),
utf8_name);
if (path_fs.IsNull())

@@ -36,7 +36,7 @@ class UpdateWalk final {
friend class UpdateArchiveVisitor;
#endif
#ifndef WIN32
#ifndef _WIN32
static constexpr bool DEFAULT_FOLLOW_INSIDE_SYMLINKS = true;
static constexpr bool DEFAULT_FOLLOW_OUTSIDE_SYMLINKS = true;

@@ -46,7 +46,7 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
p += nbytes;
#ifndef WIN32
#ifndef _WIN32
} catch (const std::system_error &e) {
errno = e.code().category() == ErrnoCategory()
? e.code().value()

@@ -23,7 +23,7 @@
#include <algorithm>
#ifndef WIN32
#ifndef _WIN32
#include <poll.h>
#endif
@@ -50,7 +50,7 @@ MultiSocketMonitor::ClearSocketList()
fds.clear();
}
#ifndef WIN32
#ifndef _WIN32
void
MultiSocketMonitor::ReplaceSocketList(pollfd *pfds, unsigned n)

@@ -31,7 +31,7 @@
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
/* ERROR is a WIN32 macro that poisons our namespace; this is a kludge
to allow us to use it anyway */
#ifdef ERROR
@@ -39,7 +39,7 @@
#endif
#endif
#ifndef WIN32
#ifndef _WIN32
struct pollfd;
#endif
@@ -189,7 +189,7 @@ public:
}
}
#ifndef WIN32
#ifndef _WIN32
/**
* Replace the socket list with the given file descriptors.
* The given pollfd array will be modified by this method.

@@ -43,7 +43,7 @@
#include <unistd.h>
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
#include <ws2tcpip.h>
#include <winsock.h>
#else

@@ -20,7 +20,7 @@
#include "config.h"
#include "SignalMonitor.hxx"
#ifndef WIN32
#ifndef _WIN32
#include "SocketMonitor.hxx"
#include "util/Manual.hxx"

@@ -24,7 +24,7 @@
class EventLoop;
#ifndef WIN32
#ifndef _WIN32
#include "util/BindMethod.hxx"

@@ -24,7 +24,7 @@
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>

@@ -28,7 +28,7 @@
#include <assert.h>
#include <stddef.h>
#ifdef WIN32
#ifdef _WIN32
/* ERROR is a WIN32 macro that poisons our namespace; this is a kludge
to allow us to use it anyway */
#ifdef ERROR

@@ -73,6 +73,10 @@ public:
return filter;
}
void Reset() override {
filter->Reset();
}
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override {
return filter->FilterPCM(src);
}

@@ -31,7 +31,7 @@ AllocatedPath::~AllocatedPath() {}
AllocatedPath
AllocatedPath::FromUTF8(const char *path_utf8) noexcept
{
#if defined(HAVE_FS_CHARSET) || defined(WIN32)
#if defined(HAVE_FS_CHARSET) || defined(_WIN32)
try {
return AllocatedPath(::PathFromUTF8(path_utf8));
} catch (const std::runtime_error &) {
@@ -45,7 +45,7 @@ AllocatedPath::FromUTF8(const char *path_utf8) noexcept
AllocatedPath
AllocatedPath::FromUTF8Throw(const char *path_utf8)
{
#if defined(HAVE_FS_CHARSET) || defined(WIN32)
#if defined(HAVE_FS_CHARSET) || defined(_WIN32)
return AllocatedPath(::PathFromUTF8(path_utf8));
#else
return FromFS(path_utf8);

@@ -24,7 +24,7 @@
#include "lib/icu/Converter.hxx"
#include "util/AllocatedString.hxx"
#ifdef WIN32
#ifdef _WIN32
#include "lib/icu/Win32.hxx"
#include <windows.h>
#endif
@@ -70,7 +70,7 @@ GetFSCharset() noexcept
{
#ifdef HAVE_FS_CHARSET
return fs_charset.empty() ? "UTF-8" : fs_charset.c_str();
#elif defined(WIN32)
#elif defined(_WIN32)
return "ACP";
#else
return "UTF-8";
@@ -100,7 +100,7 @@ PathToUTF8(PathTraitsFS::const_pointer_type path_fs)
assert(path_fs != nullptr);
#endif
#ifdef WIN32
#ifdef _WIN32
const auto buffer = WideCharToMultiByte(CP_UTF8, path_fs);
return FixSeparators(PathTraitsUTF8::string(buffer.c_str()));
#else
@@ -116,7 +116,7 @@ PathToUTF8(PathTraitsFS::const_pointer_type path_fs)
#endif
}
#if defined(HAVE_FS_CHARSET) || defined(WIN32)
#if defined(HAVE_FS_CHARSET) || defined(_WIN32)
PathTraitsFS::string
PathFromUTF8(PathTraitsUTF8::const_pointer_type path_utf8)
@@ -126,7 +126,7 @@ PathFromUTF8(PathTraitsUTF8::const_pointer_type path_utf8)
assert(path_utf8 != nullptr);
#endif
#ifdef WIN32
#ifdef _WIN32
const auto buffer = MultiByteToWideChar(CP_UTF8, path_utf8);
return PathTraitsFS::string(buffer.c_str());
#else

@@ -24,7 +24,7 @@
#include "Compiler.h"
#include "Traits.hxx"
#if (defined(HAVE_ICU) || defined(HAVE_ICONV)) && !defined(WIN32)
#if (defined(HAVE_ICU) || defined(HAVE_ICONV)) && !defined(_WIN32)
#define HAVE_FS_CHARSET
#endif

@@ -41,7 +41,7 @@ try {
return;
}
#ifndef WIN32
#ifndef _WIN32
try {
const auto x = AllocatedPath::Build(path_fs,
PathTraitsFS::CURRENT_DIRECTORY);

@@ -21,7 +21,7 @@
#include "DirectoryReader.hxx"
#include "system/Error.hxx"
#ifdef WIN32
#ifdef _WIN32
DirectoryReader::DirectoryReader(Path dir)
:handle(FindFirstFile(MakeWildcardPath(dir.c_str()), &data))

@@ -23,7 +23,7 @@
#include "check.h"
#include "Path.hxx"
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>

@@ -26,13 +26,13 @@
#include <stdint.h>
#ifdef WIN32
#ifdef _WIN32
#include <fileapi.h>
#else
#include <sys/stat.h>
#endif
#ifdef WIN32
#ifdef _WIN32
static inline constexpr uint64_t
ConstructUint64(DWORD lo, DWORD hi)
@@ -54,7 +54,7 @@ class FileInfo {
bool follow_symlinks);
friend class FileReader;
#ifdef WIN32
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA data;
#else
struct stat st;
@@ -65,7 +65,7 @@ public:
FileInfo(Path path, bool follow_symlinks=true) {
if (!GetFileInfo(path, *this, follow_symlinks)) {
#ifdef WIN32
#ifdef _WIN32
throw FormatLastError("Failed to access %s",
path.ToUTF8().c_str());
#else
@@ -76,7 +76,7 @@ public:
}
bool IsRegular() const {
#ifdef WIN32
#ifdef _WIN32
return (data.dwFileAttributes &
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE)) == 0;
#else
@@ -85,7 +85,7 @@ public:
}
bool IsDirectory() const {
#ifdef WIN32
#ifdef _WIN32
return data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
#else
return S_ISDIR(st.st_mode);
@@ -93,7 +93,7 @@ public:
}
uint64_t GetSize() const {
#ifdef WIN32
#ifdef _WIN32
return ConstructUint64(data.nFileSizeLow, data.nFileSizeHigh);
#else
return st.st_size;
@@ -101,14 +101,14 @@ public:
}
time_t GetModificationTime() const {
#ifdef WIN32
#ifdef _WIN32
return FileTimeToTimeT(data.ftLastWriteTime);
#else
return st.st_mtime;
#endif
}
#ifndef WIN32
#ifndef _WIN32
uid_t GetUid() const {
return st.st_uid;
}
@@ -130,7 +130,7 @@ public:
inline bool
GetFileInfo(Path path, FileInfo &info, bool follow_symlinks=true)
{
#ifdef WIN32
#ifdef _WIN32
(void)follow_symlinks;
return GetFileAttributesEx(path.c_str(), GetFileExInfoStandard,
&info.data);

@@ -29,7 +29,7 @@
void
RenameFile(Path oldpath, Path newpath)
{
#ifdef WIN32
#ifdef _WIN32
if (!MoveFileEx(oldpath.c_str(), newpath.c_str(),
MOVEFILE_REPLACE_EXISTING))
throw MakeLastError("Failed to rename file");
@@ -42,7 +42,7 @@ RenameFile(Path oldpath, Path newpath)
AllocatedPath
ReadLink(Path path)
{
#ifdef WIN32
#ifdef _WIN32
(void)path;
errno = EINVAL;
return AllocatedPath::Null();
@@ -63,7 +63,7 @@ ReadLink(Path path)
void
TruncateFile(Path path)
{
#ifdef WIN32
#ifdef _WIN32
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr,
TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr);
@@ -83,7 +83,7 @@ TruncateFile(Path path)
void
RemoveFile(Path path)
{
#ifdef WIN32
#ifdef _WIN32
if (!DeleteFile(path.c_str()))
throw FormatLastError("Failed to delete %s", path.c_str());
#else

@@ -26,7 +26,7 @@
#include "Path.hxx"
#ifdef WIN32
#ifdef _WIN32
#include <fileapi.h>
#endif
@@ -43,7 +43,7 @@ class AllocatedPath;
static inline FILE *
FOpen(Path file, PathTraitsFS::const_pointer_type mode)
{
#ifdef WIN32
#ifdef _WIN32
return _tfopen(file.c_str(), mode);
#else
return fopen(file.c_str(), mode);
@@ -56,7 +56,7 @@ FOpen(Path file, PathTraitsFS::const_pointer_type mode)
static inline int
OpenFile(Path file, int flags, int mode)
{
#ifdef WIN32
#ifdef _WIN32
return _topen(file.c_str(), flags, mode);
#else
return open_cloexec(file.c_str(), flags, mode);
@@ -71,7 +71,7 @@ OpenFile(Path file, int flags, int mode)
void
RenameFile(Path oldpath, Path newpath);
#ifndef WIN32
#ifndef _WIN32
/**
* Wrapper for stat() that uses #Path names.
@@ -107,7 +107,7 @@ RemoveFile(Path path);
AllocatedPath
ReadLink(Path path);
#ifndef WIN32
#ifndef _WIN32
static inline bool
MakeFifo(Path path, mode_t mode)
@@ -132,7 +132,7 @@ CheckAccess(Path path, int mode)
static inline bool
FileExists(Path path, bool follow_symlinks = true)
{
#ifdef WIN32
#ifdef _WIN32
(void)follow_symlinks;
const auto a = GetFileAttributes(path.c_str());
@@ -150,7 +150,7 @@ FileExists(Path path, bool follow_symlinks = true)
static inline bool
DirectoryExists(Path path, bool follow_symlinks = true)
{
#ifdef WIN32
#ifdef _WIN32
(void)follow_symlinks;
const auto a = GetFileAttributes(path.c_str());
@@ -167,7 +167,7 @@ DirectoryExists(Path path, bool follow_symlinks = true)
static inline bool
PathExists(Path path)
{
#ifdef WIN32
#ifdef _WIN32
return GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES;
#else
return CheckAccess(path, F_OK);

@@ -26,7 +26,7 @@
#define HAVE_CLASS_GLOB
#include <string>
#include <fnmatch.h>
#elif defined(WIN32)
#elif defined(_WIN32)
#define HAVE_CLASS_GLOB
#include <string>
#include <shlwapi.h>
@@ -40,12 +40,12 @@
* (asterisk and question mark).
*/
class Glob {
#if defined(HAVE_FNMATCH) || defined(WIN32)
#if defined(HAVE_FNMATCH) || defined(_WIN32)
std::string pattern;
#endif
public:
#if defined(HAVE_FNMATCH) || defined(WIN32)
#if defined(HAVE_FNMATCH) || defined(_WIN32)
explicit Glob(const char *_pattern)
:pattern(_pattern) {}
@@ -57,7 +57,7 @@ public:
bool Check(const char *name_fs) const noexcept {
#ifdef HAVE_FNMATCH
return fnmatch(pattern.c_str(), name_fs, 0) == 0;
#elif defined(WIN32)
#elif defined(_WIN32)
return PathMatchSpecA(name_fs, pattern.c_str());
#endif
}

@@ -25,7 +25,7 @@
#include <stddef.h>
#include <limits.h>
#if defined(WIN32)
#if defined(_WIN32)
static constexpr size_t MPD_PATH_MAX = 260;
#elif defined(MAXPATHLEN)
static constexpr size_t MPD_PATH_MAX = MAXPATHLEN;

@@ -20,7 +20,7 @@
#include "config.h"
// Use X Desktop guidelines where applicable
#if !defined(__APPLE__) && !defined(WIN32) && !defined(ANDROID)
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(ANDROID)
#define USE_XDG
#endif
@@ -29,7 +29,7 @@
#include <array>
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#include <shlobj.h>
#else
@@ -53,7 +53,7 @@
#include "Main.hxx"
#endif
#if !defined(WIN32) && !defined(ANDROID)
#if !defined(_WIN32) && !defined(ANDROID)
class PasswdEntry
{
#if defined(HAVE_GETPWNAM_R) || defined(HAVE_GETPWUID_R)
@@ -113,7 +113,7 @@ SafePathFromFS(PathTraitsFS::const_pointer_type dir)
}
#endif
#ifdef WIN32
#ifdef _WIN32
static AllocatedPath GetStandardDir(int folder_id)
{
std::array<PathTraitsFS::value_type, MAX_PATH> dir;
@@ -226,7 +226,7 @@ try {
AllocatedPath
GetUserConfigDir() noexcept
{
#if defined(WIN32)
#if defined(_WIN32)
return GetStandardDir(CSIDL_LOCAL_APPDATA);
#elif defined(USE_XDG)
// Check for $XDG_CONFIG_HOME
@@ -251,7 +251,7 @@ GetUserConfigDir() noexcept
AllocatedPath
GetUserMusicDir() noexcept
{
#if defined(WIN32)
#if defined(_WIN32)
return GetStandardDir(CSIDL_MYMUSIC);
#elif defined(USE_XDG)
return GetUserDir("XDG_MUSIC_DIR");
@@ -287,7 +287,7 @@ GetUserCacheDir() noexcept
#endif
}
#ifdef WIN32
#ifdef _WIN32
AllocatedPath
GetSystemConfigDir() noexcept

@@ -42,7 +42,7 @@ gcc_pure
AllocatedPath
GetUserCacheDir() noexcept;
#ifdef WIN32
#ifdef _WIN32
/**
* Obtains system configuration directory.

@@ -78,7 +78,7 @@ GetParentPathImpl(typename Traits::const_pointer_type p)
return typename Traits::string(Traits::CURRENT_DIRECTORY);
if (sep == p)
return typename Traits::string(p, p + 1);
#ifdef WIN32
#ifdef _WIN32
if (Traits::IsDrive(p) && sep == p + 2)
return typename Traits::string(p, p + 3);
#endif

@@ -25,7 +25,7 @@
#include "util/StringPointer.hxx"
#include "util/StringAPI.hxx"
#ifdef WIN32
#ifdef _WIN32
#include "util/CharUtil.hxx"
#include <tchar.h>
#endif
@@ -34,7 +34,7 @@
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
#define PATH_LITERAL(s) _T(s)
#else
#define PATH_LITERAL(s) (s)
@@ -44,7 +44,7 @@
* This class describes the nature of a native filesystem path.
*/
struct PathTraitsFS {
#ifdef WIN32
#ifdef _WIN32
typedef std::wstring string;
#else
typedef std::string string;
@@ -55,7 +55,7 @@ struct PathTraitsFS {
typedef Pointer::pointer_type pointer_type;
typedef Pointer::const_pointer_type const_pointer_type;
#ifdef WIN32
#ifdef _WIN32
static constexpr value_type SEPARATOR = '\\';
#else
static constexpr value_type SEPARATOR = '/';
@@ -65,7 +65,7 @@ struct PathTraitsFS {
static constexpr bool IsSeparator(value_type ch) noexcept {
return
#ifdef WIN32
#ifdef _WIN32
ch == '/' ||
#endif
ch == SEPARATOR;
@@ -78,7 +78,7 @@ struct PathTraitsFS {
assert(p != nullptr);
#endif
#ifdef WIN32
#ifdef _WIN32
const_pointer_type pos = p + GetLength(p);
while (p != pos && !IsSeparator(*pos))
--pos;
@@ -88,7 +88,7 @@ struct PathTraitsFS {
#endif
}
#ifdef WIN32
#ifdef _WIN32
gcc_pure gcc_nonnull_all
static constexpr bool IsDrive(const_pointer_type p) noexcept {
return IsAlphaASCII(p[0]) && p[1] == ':';
@@ -102,7 +102,7 @@ struct PathTraitsFS {
assert(p != nullptr);
#endif
#ifdef WIN32
#ifdef _WIN32
if (IsDrive(p) && IsSeparator(p[2]))
return true;
#endif
@@ -188,7 +188,7 @@ struct PathTraitsUTF8 {
return strrchr(p, SEPARATOR);
}
#ifdef WIN32
#ifdef _WIN32
gcc_pure gcc_nonnull_all
static constexpr bool IsDrive(const_pointer_type p) noexcept {
return IsAlphaASCII(p[0]) && p[1] == ':';
@@ -202,7 +202,7 @@ struct PathTraitsUTF8 {
assert(p != nullptr);
#endif
#ifdef WIN32
#ifdef _WIN32
if (IsDrive(p) && IsSeparator(p[2]))
return true;
#endif

@@ -43,7 +43,7 @@ FileOutputStream::FileOutputStream(Path _path, Mode _mode)
}
}
#ifdef WIN32
#ifdef _WIN32
inline void
FileOutputStream::OpenCreate(gcc_unused bool visible)
@@ -223,7 +223,7 @@ FileOutputStream::Commit()
#endif
if (!Close()) {
#ifdef WIN32
#ifdef _WIN32
throw FormatLastError("Failed to commit %s",
path.ToUTF8().c_str());
#else

@@ -25,14 +25,14 @@
#include "fs/AllocatedPath.hxx"
#include "Compiler.h"
#ifndef WIN32
#ifndef _WIN32
#include "system/FileDescriptor.hxx"
#endif
#include <assert.h>
#include <stdint.h>
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#endif
@@ -41,7 +41,7 @@ class Path;
class FileOutputStream final : public OutputStream {
const AllocatedPath path;
#ifdef WIN32
#ifdef _WIN32
HANDLE handle = INVALID_HANDLE_VALUE;
#else
FileDescriptor fd = FileDescriptor::Undefined();
@@ -116,7 +116,7 @@ private:
bool Close() {
assert(IsDefined());
#ifdef WIN32
#ifdef _WIN32
CloseHandle(handle);
handle = INVALID_HANDLE_VALUE;
return true;
@@ -125,7 +125,7 @@ private:
#endif
}
#ifdef WIN32
#ifdef _WIN32
bool SeekEOF() {
return SetFilePointer(handle, 0, nullptr,
FILE_END) != 0xffffffff;
@@ -133,7 +133,7 @@ private:
#endif
bool IsDefined() const {
#ifdef WIN32
#ifdef _WIN32
return handle != INVALID_HANDLE_VALUE;
#else
return fd.IsDefined();

@@ -24,7 +24,7 @@
#include <assert.h>
#ifdef WIN32
#ifdef _WIN32
FileReader::FileReader(Path _path)
:path(_path),

@@ -25,11 +25,11 @@
#include "fs/AllocatedPath.hxx"
#include "Compiler.h"
#ifndef WIN32
#ifndef _WIN32
#include "system/FileDescriptor.hxx"
#endif
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#endif
@@ -39,7 +39,7 @@ class FileInfo;
class FileReader final : public Reader {
AllocatedPath path;
#ifdef WIN32
#ifdef _WIN32
HANDLE handle;
#else
FileDescriptor fd;
@@ -48,7 +48,7 @@ class FileReader final : public Reader {
public:
explicit FileReader(Path _path);
#ifdef WIN32
#ifdef _WIN32
FileReader(FileReader &&other)
:path(std::move(other.path)),
handle(other.handle) {
@@ -70,7 +70,7 @@ public:
protected:
bool IsDefined() const {
#ifdef WIN32
#ifdef _WIN32
return handle != INVALID_HANDLE_VALUE;
#else
return fd.IsDefined();
@@ -78,7 +78,7 @@ protected:
}
public:
#ifndef WIN32
#ifndef _WIN32
FileDescriptor GetFD() const {
return fd;
}
@@ -90,7 +90,7 @@ public:
gcc_pure
uint64_t GetSize() const noexcept {
#ifdef WIN32
#ifdef _WIN32
LARGE_INTEGER size;
return GetFileSizeEx(handle, &size)
? size.QuadPart
@@ -102,7 +102,7 @@ public:
gcc_pure
uint64_t GetPosition() const noexcept {
#ifdef WIN32
#ifdef _WIN32
LARGE_INTEGER zero;
zero.QuadPart = 0;
LARGE_INTEGER position;

@@ -26,7 +26,7 @@
#include <stddef.h>
#include <stdint.h>
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ERROR

@@ -227,7 +227,7 @@ CurlInputStream::OnHeaders(unsigned status,
if (i != headers.end()) {
size_t icy_metaint = ParseUint64(i->second.c_str());
#ifndef WIN32
#ifndef _WIN32
/* Windows doesn't know "%z" */
FormatDebug(curl_domain, "icy-metaint=%zu", icy_metaint);
#endif
@@ -266,6 +266,7 @@ CurlInputStream::OnData(ConstBuffer<void> data)
void
CurlInputStream::OnEnd()
{
const std::lock_guard<Mutex> protect(mutex);
cond.broadcast();
AsyncInputStream::SetClosed();
@@ -274,6 +275,7 @@ CurlInputStream::OnEnd()
void
CurlInputStream::OnError(std::exception_ptr e)
{
const std::lock_guard<Mutex> protect(mutex);
postponed_exception = std::move(e);
if (IsSeekPending())
@@ -414,7 +416,7 @@ CurlInputStream::SeekInternal(offset_type new_offset)
if (offset > 0) {
char range[32];
#ifdef WIN32
#ifdef _WIN32
// TODO: what can we use on Windows to format 64 bit?
sprintf(range, "%lu-", (long)offset);
#else

@@ -36,7 +36,7 @@
#include <ctype.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#include "Win32.hxx"
#include <windows.h>
#endif
@@ -73,7 +73,7 @@ try {
folded.SetSize(folded_length);
return UCharToUTF8({folded.begin(), folded.size()});
#elif defined(WIN32)
#elif defined(_WIN32)
const auto u = MultiByteToWideChar(CP_UTF8, src);
const int size = LCMapStringEx(LOCALE_NAME_INVARIANT,

@@ -32,7 +32,7 @@
#include <ctype.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#include "Win32.hxx"
#include "util/AllocatedString.hxx"
#include <windows.h>
@@ -103,7 +103,7 @@ IcuCollate(const char *a, const char *b) noexcept
}
#endif
#elif defined(WIN32)
#elif defined(_WIN32)
AllocatedString<wchar_t> wa = nullptr, wb = nullptr;
try {

@@ -22,7 +22,7 @@
#include "Compiler.h"
#include <upnp/upnptools.h>
#include <upnptools.h>
static inline constexpr unsigned
CountNameValuePairs()

@@ -20,7 +20,7 @@
#ifndef MPD_UPNP_CALLBACK_HXX
#define MPD_UPNP_CALLBACK_HXX
#include <upnp/upnp.h>
#include <upnp.h>
/**
* A class that is supposed to be used for libupnp asynchronous

@@ -24,7 +24,7 @@
#include "thread/Mutex.hxx"
#include "util/RuntimeError.hxx"
#include <upnp/upnptools.h>
#include <upnptools.h>
#include <assert.h>

@@ -22,7 +22,7 @@
#include "check.h"
#include <upnp/upnp.h>
#include <upnp.h>
void
UpnpClientGlobalInit(UpnpClient_Handle &handle);

@@ -20,15 +20,18 @@
#ifndef MPD_UPNP_COMPAT_HXX
#define MPD_UPNP_COMPAT_HXX
#include <upnp/upnp.h>
#include <upnp.h>
#if UPNP_VERSION < 10800
#include "Compiler.h"
/* emulate the libupnp 1.8 API with older versions */
using UpnpDiscovery = Upnp_Discovery;
#endif
#if UPNP_VERSION < 10624
#include "Compiler.h"
gcc_pure
static inline int
UpnpDiscovery_get_Expires(const UpnpDiscovery *disco) noexcept

@@ -22,7 +22,7 @@
#include "Compiler.h"
#include <upnp/upnp.h>
#include <upnp.h>
#include <string>
#include <list>

@@ -24,7 +24,7 @@
#include "util/ScopeExit.hxx"
#include "util/RuntimeError.hxx"
#include <upnp/upnptools.h>
#include <upnptools.h>
#include <stdlib.h>
#include <string.h>

@@ -27,7 +27,7 @@
#include "thread/Mutex.hxx"
#include "Compiler.h"
#include <upnp/upnp.h>
#include <upnp.h>
#include <list>
#include <vector>

@@ -22,9 +22,9 @@
#include "thread/Mutex.hxx"
#include "util/RuntimeError.hxx"
#include <upnp/upnp.h>
#include <upnp/upnptools.h>
#include <upnp/ixml.h>
#include <upnp.h>
#include <upnptools.h>
#include <ixml.h>
#include <assert.h>

@@ -20,7 +20,7 @@
#ifndef MPD_UPNP_UNIQUE_XML_HXX
#define MPD_UPNP_UNIQUE_XML_HXX
#include <upnp/ixml.h>
#include <ixml.h>
#include <memory>

@@ -17,7 +17,7 @@
#ifndef _IXMLWRAP_H_INCLUDED_
#define _IXMLWRAP_H_INCLUDED_
#include <upnp/ixml.h>
#include <ixml.h>
#include <string>

@@ -292,7 +292,9 @@ AlsaMixer::SetVolume(unsigned volume)
{
assert(handle != nullptr);
int err = set_normalized_playback_volume(elem, 0.01*volume, 1);
double cur = get_normalized_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT);
int delta = volume - lrint(100.*cur);
int err = set_normalized_playback_volume(elem, cur + 0.01*delta, delta);
if (err < 0)
throw FormatRuntimeError("failed to set ALSA volume: %s",
snd_strerror(err));

@@ -23,7 +23,7 @@
#include <string>
#ifdef WIN32
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/types.h>

@@ -34,7 +34,7 @@
#include <cstddef>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
@@ -45,7 +45,7 @@
*/
class SocketAddress {
public:
#ifdef WIN32
#ifdef _WIN32
typedef int size_type;
#else
typedef socklen_t size_type;

@@ -23,7 +23,7 @@
#include <string.h>
#ifdef WIN32
#ifdef _WIN32
SocketErrorMessage::SocketErrorMessage(socket_error_t code) noexcept
{

@@ -23,7 +23,7 @@
#include "Compiler.h"
#include "system/Error.hxx"
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
typedef DWORD socket_error_t;
#else
@@ -35,7 +35,7 @@ gcc_pure
static inline socket_error_t
GetSocketError() noexcept
{
#ifdef WIN32
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
@@ -46,7 +46,7 @@ gcc_const
static inline bool
IsSocketErrorAgain(socket_error_t code) noexcept
{
#ifdef WIN32
#ifdef _WIN32
return code == WSAEINPROGRESS;
#else
return code == EAGAIN;
@@ -57,7 +57,7 @@ gcc_const
static inline bool
IsSocketErrorInterruped(socket_error_t code) noexcept
{
#ifdef WIN32
#ifdef _WIN32
return code == WSAEINTR;
#else
return code == EINTR;
@@ -68,7 +68,7 @@ gcc_const
static inline bool
IsSocketErrorClosed(socket_error_t code) noexcept
{
#ifdef WIN32
#ifdef _WIN32
return code == WSAECONNRESET;
#else
return code == EPIPE || code == ECONNRESET;
@@ -81,7 +81,7 @@ IsSocketErrorClosed(socket_error_t code) noexcept
* and this class hosts the buffer.
*/
class SocketErrorMessage {
#ifdef WIN32
#ifdef _WIN32
char msg[256];
#else
const char *const msg;
@@ -99,7 +99,7 @@ gcc_const
static inline std::system_error
MakeSocketError(socket_error_t code, const char *msg) noexcept
{
#ifdef WIN32
#ifdef _WIN32
return MakeLastError(code, msg);
#else
return MakeErrno(code, msg);

@@ -34,7 +34,7 @@
#include <algorithm>
#ifdef WIN32
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <netdb.h>

@@ -142,7 +142,8 @@ AudioOutputSource::GetChunkData(const MusicChunk &chunk,
replay_gain_filter_set_mode(*replay_gain_filter,
replay_gain_mode);
if (chunk.replay_gain_serial != *replay_gain_serial_p) {
if (chunk.replay_gain_serial != *replay_gain_serial_p &&
chunk.replay_gain_serial != MusicChunk::IGNORE_REPLAY_GAIN) {
replay_gain_filter_set_info(*replay_gain_filter,
chunk.replay_gain_serial != 0
? &chunk.replay_gain_info

@@ -77,7 +77,6 @@ public:
void Close();
size_t Play(const void *chunk, size_t size);
void Cancel();
std::chrono::steady_clock::duration Delay() noexcept;

@@ -36,9 +36,10 @@
#include <memory>
static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100;
struct OSXOutput {
AudioOutput base;
/* configuration settings */
OSType component_subtype;
/* only applicable with kAudioUnitSubType_HALOutput */
@@ -693,7 +694,9 @@ osx_output_open(AudioOutput *ao, AudioFormat &audio_format)
errormsg);
}
od->ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(buffer_frame_size);
size_t ring_buffer_size = std::max<size_t>(buffer_frame_size,
MPD_OSX_BUFFER_TIME_MS * audio_format.GetFrameSize() * audio_format.sample_rate / 1000);
od->ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(ring_buffer_size);
status = AudioOutputUnitStart(od->au);
if (status != 0) {
@@ -717,7 +720,7 @@ osx_output_delay(AudioOutput *ao) noexcept
OSXOutput *od = (OSXOutput *)ao;
return od->ring_buffer->write_available()
? std::chrono::steady_clock::duration::zero()
: std::chrono::milliseconds(25);
: std::chrono::milliseconds(MPD_OSX_BUFFER_TIME_MS / 4);
}
int

@@ -24,7 +24,7 @@
#include <stdint.h>
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
/* on WIN32, "FLOAT" is already defined, and this triggers -Wshadow */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
@@ -57,7 +57,7 @@ enum class SampleFormat : uint8_t {
DSD,
};
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic pop
#endif
@@ -122,7 +122,7 @@ sample_format_size(SampleFormat format)
* @param format a #SampleFormat enum value
* @return the string
*/
gcc_pure gcc_malloc
gcc_pure
const char *
sample_format_to_string(SampleFormat format) noexcept;

@@ -139,6 +139,14 @@ SoxrPcmResampler::Close()
soxr_delete(soxr);
}
void
SoxrPcmResampler::Reset()
{
#if SOXR_THIS_VERSION >= SOXR_VERSION(0,1,2)
soxr_clear(soxr);
#endif
}
ConstBuffer<void>
SoxrPcmResampler::Resample(ConstBuffer<void> src)
{

@@ -41,6 +41,7 @@ class SoxrPcmResampler final : public PcmResampler {
public:
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() override;
void Reset() override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
};

@@ -558,8 +558,10 @@ Player::SendSilence()
partial frames */
unsigned num_frames = sizeof(chunk->data) / frame_size;
chunk->bit_rate = 0;
chunk->time = SignedSongTime::Negative(); /* undefined time stamp */
chunk->length = num_frames * frame_size;
chunk->replay_gain_serial = MusicChunk::IGNORE_REPLAY_GAIN;
PcmSilence({chunk->data, chunk->length}, play_audio_format.format);
try {

@@ -75,8 +75,7 @@ playlist::MoveOrderToCurrent(unsigned old_order)
} else {
/* not playing anything: move the specified song to
the front */
queue.SwapOrders(old_order, 0);
return 0;
return queue.MoveOrderBefore(old_order, 0);
}
}
@@ -213,8 +212,6 @@ playlist::SeekSongOrder(PlayerControl &pc, unsigned i, SongTime seek_time)
{
assert(queue.IsValidOrder(i));
const DetachedSong *queued_song = GetQueuedSong();
pc.LockClearError();
stop_on_error = true;
error_count = 0;
@@ -227,8 +224,6 @@ playlist::SeekSongOrder(PlayerControl &pc, unsigned i, SongTime seek_time)
playing = true;
current = i;
queued_song = nullptr;
}
queued = -1;
@@ -236,7 +231,7 @@ playlist::SeekSongOrder(PlayerControl &pc, unsigned i, SongTime seek_time)
try {
pc.LockSeek(new DetachedSong(queue.GetOrder(i)), seek_time);
} catch (...) {
UpdateQueuedSong(pc, queued_song);
UpdateQueuedSong(pc, nullptr);
throw;
}

@@ -112,7 +112,7 @@ playlist::AppendSong(PlayerControl &pc, DetachedSong &&song)
else
start = current + 1;
if (start < queue.GetLength())
queue.ShuffleOrderLast(start, queue.GetLength());
queue.ShuffleOrderLastWithPriority(start, queue.GetLength());
}
UpdateQueuedSong(pc, queued_song);

Some files were not shown because too many files have changed in this diff Show More