Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
49b9a90c3f | ||
![]() |
64d141f71e | ||
![]() |
c488d3123f | ||
![]() |
967af60327 | ||
![]() |
f1ef9f9d31 | ||
![]() |
dfaf08743c | ||
![]() |
d9552d8a6d | ||
![]() |
7586a8ab2c | ||
![]() |
e1a942250b | ||
![]() |
72be0185de | ||
![]() |
7e4cbce06b | ||
![]() |
177d62f431 | ||
![]() |
5a11e03725 | ||
![]() |
75d068b7cd | ||
![]() |
1208503888 | ||
![]() |
de90d401d2 | ||
![]() |
396defaea9 | ||
![]() |
18f350cd04 | ||
![]() |
478180ebe4 | ||
![]() |
4a3059f509 | ||
![]() |
78728138a0 | ||
![]() |
63fc98591d | ||
![]() |
53def9a682 | ||
![]() |
323231d1dd | ||
![]() |
714011c81e | ||
![]() |
952ff4207b | ||
![]() |
150b16ec2c | ||
![]() |
c98bc4a243 | ||
![]() |
014f8cd693 | ||
![]() |
aea37e46e3 | ||
![]() |
31ab78ae8e | ||
![]() |
f82e1453e4 | ||
![]() |
a2b77c8813 | ||
![]() |
18add29472 | ||
![]() |
b111a8fe8d | ||
![]() |
3b23cf0258 | ||
![]() |
28e864e096 | ||
![]() |
1de19b921a | ||
![]() |
ff162b5a03 | ||
![]() |
d8e4705dd4 | ||
![]() |
338e1f5926 |
Makefile.amNEWS
android
configure.acdoc
python/build
src
CommandLine.cxxLocateUri.hxxLogBackend.cxxLogInit.cxxLogLevel.hxxMain.cxxMain.hxxMusicChunk.hxxStateFile.cxxStateFile.hxxStats.cxxTimePrint.cxx
client
command
config
db
plugins
update
decoder
encoder
plugins
event
MultiSocketMonitor.cxxMultiSocketMonitor.hxxServerSocket.cxxSignalMonitor.cxxSignalMonitor.hxxSocketMonitor.cxxSocketMonitor.hxx
fs
AllocatedPath.cxxCharset.cxxCharset.hxxCheckFile.cxxDirectoryReader.cxxDirectoryReader.hxxFileInfo.hxxFileSystem.cxxFileSystem.hxxGlob.hxxLimits.hxxStandardDirectory.cxxStandardDirectory.hxxTraits.cxxTraits.hxx
io
input
InputPlugin.hxx
plugins
lib
icu
upnp
mixer
plugins
net
output
pcm
player
playlist
queue
storage
system
Clock.cxxClock.hxxEPollFD.cxxError.hxxEventPipe.cxxFatalError.cxxFatalError.hxxFileDescriptor.cxxFileDescriptor.hxxfd_util.cfd_util.h
tag
thread
unix
util
win32
test
@@ -243,6 +243,7 @@ CURL_SOURCES = \
|
||||
src/lib/curl/Slist.hxx
|
||||
|
||||
UPNP_SOURCES = \
|
||||
src/lib/upnp/Compat.hxx \
|
||||
src/lib/upnp/Init.cxx src/lib/upnp/Init.hxx \
|
||||
src/lib/upnp/ClientInit.cxx src/lib/upnp/ClientInit.hxx \
|
||||
src/lib/upnp/Device.cxx src/lib/upnp/Device.hxx \
|
||||
@@ -701,6 +702,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) \
|
||||
@@ -753,6 +755,7 @@ libneighbor_a_SOURCES = \
|
||||
src/neighbor/NeighborPlugin.hxx
|
||||
|
||||
libneighbor_a_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
$(UPNP_CFLAGS) \
|
||||
$(SMBCLIENT_CFLAGS)
|
||||
|
||||
if ENABLE_SMBCLIENT
|
||||
@@ -802,6 +805,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 += \
|
||||
@@ -2411,6 +2416,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 \
|
||||
@@ -2418,5 +2424,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
|
||||
|
33
NEWS
33
NEWS
@@ -1,3 +1,36 @@
|
||||
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
|
||||
* input
|
||||
- cdio_paranoia, ffmpeg, file, smbclient: reduce lock contention,
|
||||
fixing lots of xrun problems
|
||||
- curl: fix seeking
|
||||
* decoder
|
||||
- ffmpeg: fix GCC 8 warning
|
||||
- vorbis: fix Tremor support
|
||||
* player
|
||||
- log message when decoder is too slow
|
||||
* encoder
|
||||
- vorbis: default to quality 3
|
||||
* output
|
||||
- fix hanging playback with soxr resampler
|
||||
- httpd: flush encoder after tag; fixes corrupt Vorbis stream
|
||||
|
||||
ver 0.20.11 (2017/10/18)
|
||||
* storage
|
||||
- curl: support Content-Type application/xml
|
||||
|
@@ -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')
|
||||
|
||||
@@ -79,8 +80,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'
|
||||
|
11
configure.ac
11
configure.ac
@@ -1,10 +1,10 @@
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
AC_INIT(mpd, 0.20.11, musicpd-dev-team@lists.sourceforge.net)
|
||||
AC_INIT(mpd, 0.20.13, musicpd-dev-team@lists.sourceforge.net)
|
||||
|
||||
VERSION_MAJOR=0
|
||||
VERSION_MINOR=20
|
||||
VERSION_REVISION=11
|
||||
VERSION_REVISION=13
|
||||
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>
|
||||
@@ -1385,6 +1385,11 @@ then
|
||||
AX_APPEND_COMPILE_FLAGS([-Wcast-qual])
|
||||
AX_APPEND_COMPILE_FLAGS([-Wwrite-strings])
|
||||
AX_APPEND_COMPILE_FLAGS([-Wsign-compare])
|
||||
|
||||
dnl This GCC8 warning for C++17 ABI compatibility is of no
|
||||
dnl interest for us, because we're not a shared library.
|
||||
AX_APPEND_COMPILE_FLAGS([-Wno-noexcept-type])
|
||||
|
||||
AC_LANG_POP
|
||||
fi
|
||||
|
||||
|
@@ -3068,8 +3068,8 @@ run</programlisting>
|
||||
</entry>
|
||||
<entry>
|
||||
Sets the quality for VBR. -1 is the lowest quality,
|
||||
10 is the highest quality. Cannot be used with
|
||||
<varname>bitrate</varname>.
|
||||
10 is the highest quality. Defaults to 3. Cannot
|
||||
be used with <varname>bitrate</varname>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
@@ -69,8 +69,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 +84,26 @@ ffmpeg = FfmpegProject(
|
||||
'--disable-swscale',
|
||||
'--disable-postproc',
|
||||
'--disable-avfilter',
|
||||
'--disable-lzo',
|
||||
'--disable-faan',
|
||||
'--disable-pixelutils',
|
||||
'--disable-network',
|
||||
'--disable-encoders',
|
||||
'--disable-protocols',
|
||||
'--disable-outdevs',
|
||||
'--disable-devices',
|
||||
'--disable-filters',
|
||||
'--disable-v4l2_m2m',
|
||||
|
||||
# clang misinterprets the "B0" in hevc_mvs.c as binary
|
||||
# literal, which breaks the build; but we don't need that
|
||||
# video codec anyway
|
||||
'--disable-decoder=hevc',
|
||||
],
|
||||
)
|
||||
|
||||
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',
|
||||
@@ -114,7 +123,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.65.1/boost_1_65_1.tar.bz2',
|
||||
'9807a5d16566c57fd74fb522764e0b134a8bbe6b6e8967b83afefd30dcd3be81',
|
||||
'include/boost/version.hpp',
|
||||
)
|
||||
|
@@ -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
|
||||
|
12
src/Main.cxx
12
src/Main.cxx
@@ -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",
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -258,7 +258,7 @@ FfmpegSendFrame(DecoderClient &client, InputStream &is,
|
||||
try {
|
||||
output_buffer = copy_interleave_frame(codec_context, frame,
|
||||
buffer);
|
||||
} catch (const std::exception e) {
|
||||
} catch (const std::exception &e) {
|
||||
/* this must be a serious error, e.g. OOM */
|
||||
LogError(e);
|
||||
return DecoderCommand::STOP;
|
||||
|
@@ -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()
|
||||
|
@@ -178,6 +178,20 @@ VorbisDecoder::SubmitInit()
|
||||
client.Ready(audio_format, eos_granulepos > 0, duration);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TREMOR
|
||||
static inline int16_t tremor_clip_sample(int32_t x)
|
||||
{
|
||||
x >>= 9;
|
||||
|
||||
if (x < INT16_MIN)
|
||||
return INT16_MIN;
|
||||
if (x > INT16_MAX)
|
||||
return INT16_MAX;
|
||||
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
VorbisDecoder::SubmitSomePcm()
|
||||
{
|
||||
@@ -197,7 +211,7 @@ VorbisDecoder::SubmitSomePcm()
|
||||
auto *dest = &buffer[c];
|
||||
|
||||
for (size_t i = 0; i < n_frames; ++i) {
|
||||
*dest = *src++;
|
||||
*dest = tremor_clip_sample(*src++);
|
||||
dest += channels;
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ private:
|
||||
};
|
||||
|
||||
class PreparedVorbisEncoder final : public PreparedEncoder {
|
||||
float quality;
|
||||
float quality = 3;
|
||||
int bitrate;
|
||||
|
||||
public:
|
||||
@@ -97,7 +97,7 @@ PreparedVorbisEncoder::PreparedVorbisEncoder(const ConfigBlock &block)
|
||||
|
||||
value = block.GetBlockValue("bitrate");
|
||||
if (value == nullptr)
|
||||
throw std::runtime_error("neither bitrate nor quality defined");
|
||||
return;
|
||||
|
||||
quality = -2.0;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -270,7 +270,10 @@ CdioParanoiaInputStream::Seek(offset_type new_offset)
|
||||
lsn_relofs = new_offset / CDIO_CD_FRAMESIZE_RAW;
|
||||
offset = new_offset;
|
||||
|
||||
cdio_paranoia_seek(para, lsn_from + lsn_relofs, SEEK_SET);
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
cdio_paranoia_seek(para, lsn_from + lsn_relofs, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -292,6 +295,8 @@ CdioParanoiaInputStream::Read(void *ptr, size_t length)
|
||||
|
||||
//current sector was changed ?
|
||||
if (lsn_relofs != buffer_lsn) {
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
rbuf = cdio_paranoia_read(para, nullptr);
|
||||
|
||||
s_err = cdda_errors(drv);
|
||||
|
@@ -64,7 +64,6 @@ static const size_t CURL_RESUME_AT = 384 * 1024;
|
||||
struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler {
|
||||
/* some buffers which were passed to libcurl, which we have
|
||||
too free */
|
||||
char range[32];
|
||||
CurlSlist request_headers;
|
||||
|
||||
CurlRequest *request = nullptr;
|
||||
@@ -86,8 +85,19 @@ struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler {
|
||||
|
||||
static InputStream *Open(const char *url, Mutex &mutex, Cond &cond);
|
||||
|
||||
/**
|
||||
* Create and initialize a new #CurlRequest instance. After
|
||||
* this, you may add more request headers and set options. To
|
||||
* actually start the request, call StartRequest().
|
||||
*/
|
||||
void InitEasy();
|
||||
|
||||
/**
|
||||
* Start the request after having called InitEasy(). After
|
||||
* this, you must not set any CURL options.
|
||||
*/
|
||||
void StartRequest();
|
||||
|
||||
/**
|
||||
* Frees the current "libcurl easy" handle, and everything
|
||||
* associated with it.
|
||||
@@ -217,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
|
||||
@@ -372,6 +382,11 @@ CurlInputStream::InitEasy()
|
||||
|
||||
request_headers.Clear();
|
||||
request_headers.Append("Icy-Metadata: 1");
|
||||
}
|
||||
|
||||
void
|
||||
CurlInputStream::StartRequest()
|
||||
{
|
||||
request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get());
|
||||
|
||||
request->Start();
|
||||
@@ -398,7 +413,8 @@ CurlInputStream::SeekInternal(offset_type new_offset)
|
||||
/* send the "Range" header */
|
||||
|
||||
if (offset > 0) {
|
||||
#ifdef WIN32
|
||||
char range[32];
|
||||
#ifdef _WIN32
|
||||
// TODO: what can we use on Windows to format 64 bit?
|
||||
sprintf(range, "%lu-", (long)offset);
|
||||
#else
|
||||
@@ -406,6 +422,8 @@ CurlInputStream::SeekInternal(offset_type new_offset)
|
||||
#endif
|
||||
request->SetOption(CURLOPT_RANGE, range);
|
||||
}
|
||||
|
||||
StartRequest();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -428,6 +446,7 @@ CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond)
|
||||
try {
|
||||
BlockingCall(io_thread_get(), [c](){
|
||||
c->InitEasy();
|
||||
c->StartRequest();
|
||||
});
|
||||
} catch (...) {
|
||||
delete c;
|
||||
|
@@ -104,7 +104,13 @@ input_ffmpeg_open(const char *uri,
|
||||
size_t
|
||||
FfmpegInputStream::Read(void *ptr, size_t read_size)
|
||||
{
|
||||
auto result = avio_read(h, (unsigned char *)ptr, read_size);
|
||||
int result;
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
result = avio_read(h, (unsigned char *)ptr, read_size);
|
||||
}
|
||||
|
||||
if (result <= 0) {
|
||||
if (result < 0)
|
||||
throw MakeFfmpegError(result, "avio_read() failed");
|
||||
@@ -126,7 +132,12 @@ FfmpegInputStream::IsEOF() noexcept
|
||||
void
|
||||
FfmpegInputStream::Seek(offset_type new_offset)
|
||||
{
|
||||
auto result = avio_seek(h, new_offset, SEEK_SET);
|
||||
int64_t result;
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
result = avio_seek(h, new_offset, SEEK_SET);
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
throw MakeFfmpegError(result, "avio_seek() failed");
|
||||
|
@@ -87,14 +87,24 @@ input_file_open(gcc_unused const char *filename,
|
||||
void
|
||||
FileInputStream::Seek(offset_type new_offset)
|
||||
{
|
||||
reader.Seek((off_t)new_offset);
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
reader.Seek((off_t)new_offset);
|
||||
}
|
||||
|
||||
offset = new_offset;
|
||||
}
|
||||
|
||||
size_t
|
||||
FileInputStream::Read(void *ptr, size_t read_size)
|
||||
{
|
||||
size_t nbytes = reader.Read(ptr, read_size);
|
||||
size_t nbytes;
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
nbytes = reader.Read(ptr, read_size);
|
||||
}
|
||||
|
||||
offset += nbytes;
|
||||
return nbytes;
|
||||
}
|
||||
|
@@ -125,9 +125,14 @@ input_smbclient_open(const char *uri,
|
||||
size_t
|
||||
SmbclientInputStream::Read(void *ptr, size_t read_size)
|
||||
{
|
||||
smbclient_mutex.lock();
|
||||
ssize_t nbytes = smbc_read(fd, ptr, read_size);
|
||||
smbclient_mutex.unlock();
|
||||
ssize_t nbytes;
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
const std::lock_guard<Mutex> lock(smbclient_mutex);
|
||||
nbytes = smbc_read(fd, ptr, read_size);
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
throw MakeErrno("smbc_read() failed");
|
||||
|
||||
@@ -138,9 +143,14 @@ SmbclientInputStream::Read(void *ptr, size_t read_size)
|
||||
void
|
||||
SmbclientInputStream::Seek(offset_type new_offset)
|
||||
{
|
||||
smbclient_mutex.lock();
|
||||
off_t result = smbc_lseek(fd, new_offset, SEEK_SET);
|
||||
smbclient_mutex.unlock();
|
||||
off_t result;
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
const std::lock_guard<Mutex> lock(smbclient_mutex);
|
||||
result = smbc_lseek(fd, new_offset, SEEK_SET);
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
throw MakeErrno("smbc_lseek() failed");
|
||||
|
||||
|
@@ -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
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
return *(UpnpCallback *)cookie;
|
||||
}
|
||||
|
||||
virtual int Invoke(Upnp_EventType et, void *evp) = 0;
|
||||
virtual int Invoke(Upnp_EventType et, const void *evp) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
|
||||
#include <upnp/upnptools.h>
|
||||
#include <upnptools.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -33,7 +33,12 @@ static unsigned upnp_client_ref;
|
||||
static UpnpClient_Handle upnp_client_handle;
|
||||
|
||||
static int
|
||||
UpnpClientCallback(Upnp_EventType et, void *evp, void *cookie)
|
||||
UpnpClientCallback(Upnp_EventType et,
|
||||
#if UPNP_VERSION >= 10800
|
||||
const
|
||||
#endif
|
||||
void *evp,
|
||||
void *cookie)
|
||||
{
|
||||
if (cookie == nullptr)
|
||||
/* this is the cookie passed to UpnpRegisterClient();
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "check.h"
|
||||
|
||||
#include <upnp/upnp.h>
|
||||
#include <upnp.h>
|
||||
|
||||
void
|
||||
UpnpClientGlobalInit(UpnpClient_Handle &handle);
|
||||
|
72
src/lib/upnp/Compat.hxx
Normal file
72
src/lib/upnp/Compat.hxx
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2003-2017 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_UPNP_COMPAT_HXX
|
||||
#define MPD_UPNP_COMPAT_HXX
|
||||
|
||||
#include <upnp.h>
|
||||
|
||||
#if UPNP_VERSION < 10800
|
||||
/* 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
|
||||
{
|
||||
return disco->Expires;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static inline const char *
|
||||
UpnpDiscovery_get_DeviceID_cstr(const UpnpDiscovery *disco) noexcept
|
||||
{
|
||||
return disco->DeviceId;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static inline const char *
|
||||
UpnpDiscovery_get_DeviceType_cstr(const UpnpDiscovery *disco) noexcept
|
||||
{
|
||||
return disco->DeviceType;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static inline const char *
|
||||
UpnpDiscovery_get_ServiceType_cstr(const UpnpDiscovery *disco) noexcept
|
||||
{
|
||||
return disco->ServiceType;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static inline const char *
|
||||
UpnpDiscovery_get_Location_cstr(const UpnpDiscovery *disco) noexcept
|
||||
{
|
||||
return disco->Location;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -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>
|
||||
@@ -153,10 +153,10 @@ UPnPDeviceDirectory::Explore(void *ctx)
|
||||
}
|
||||
|
||||
inline int
|
||||
UPnPDeviceDirectory::OnAlive(Upnp_Discovery *disco)
|
||||
UPnPDeviceDirectory::OnAlive(const UpnpDiscovery *disco)
|
||||
{
|
||||
if (isMSDevice(disco->DeviceType) ||
|
||||
isCDService(disco->ServiceType)) {
|
||||
if (isMSDevice(UpnpDiscovery_get_DeviceType_cstr(disco)) ||
|
||||
isCDService(UpnpDiscovery_get_ServiceType_cstr(disco))) {
|
||||
DiscoveredTask *tp = new DiscoveredTask(disco);
|
||||
if (queue.put(tp))
|
||||
return UPNP_E_FINISH;
|
||||
@@ -166,12 +166,12 @@ UPnPDeviceDirectory::OnAlive(Upnp_Discovery *disco)
|
||||
}
|
||||
|
||||
inline int
|
||||
UPnPDeviceDirectory::OnByeBye(Upnp_Discovery *disco)
|
||||
UPnPDeviceDirectory::OnByeBye(const UpnpDiscovery *disco)
|
||||
{
|
||||
if (isMSDevice(disco->DeviceType) ||
|
||||
isCDService(disco->ServiceType)) {
|
||||
if (isMSDevice(UpnpDiscovery_get_DeviceType_cstr(disco)) ||
|
||||
isCDService(UpnpDiscovery_get_ServiceType_cstr(disco))) {
|
||||
// Device signals it is going off.
|
||||
LockRemove(disco->DeviceId);
|
||||
LockRemove(UpnpDiscovery_get_DeviceID_cstr(disco));
|
||||
}
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
@@ -182,19 +182,19 @@ UPnPDeviceDirectory::OnByeBye(Upnp_Discovery *disco)
|
||||
// Example: ContentDirectories appearing and disappearing from the network
|
||||
// We queue a task for our worker thread(s)
|
||||
int
|
||||
UPnPDeviceDirectory::Invoke(Upnp_EventType et, void *evp)
|
||||
UPnPDeviceDirectory::Invoke(Upnp_EventType et, const void *evp)
|
||||
{
|
||||
switch (et) {
|
||||
case UPNP_DISCOVERY_SEARCH_RESULT:
|
||||
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
|
||||
{
|
||||
Upnp_Discovery *disco = (Upnp_Discovery *)evp;
|
||||
auto *disco = (const UpnpDiscovery *)evp;
|
||||
return OnAlive(disco);
|
||||
}
|
||||
|
||||
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
|
||||
{
|
||||
Upnp_Discovery *disco = (Upnp_Discovery *)evp;
|
||||
auto *disco = (const UpnpDiscovery *)evp;
|
||||
return OnByeBye(disco);
|
||||
}
|
||||
|
||||
|
@@ -20,13 +20,14 @@
|
||||
#ifndef _UPNPPDISC_H_X_INCLUDED_
|
||||
#define _UPNPPDISC_H_X_INCLUDED_
|
||||
|
||||
#include "Compat.hxx"
|
||||
#include "Callback.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "WorkQueue.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <upnp/upnp.h>
|
||||
#include <upnp.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
@@ -34,6 +35,10 @@
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
#if UPNP_VERSION < 10800
|
||||
#define UpnpDiscovery Upnp_Discovery
|
||||
#endif
|
||||
|
||||
class ContentDirectoryService;
|
||||
|
||||
class UPnPDiscoveryListener {
|
||||
@@ -59,10 +64,10 @@ class UPnPDeviceDirectory final : UpnpCallback {
|
||||
std::string device_id;
|
||||
std::chrono::steady_clock::duration expires;
|
||||
|
||||
DiscoveredTask(const Upnp_Discovery *disco)
|
||||
:url(disco->Location),
|
||||
device_id(disco->DeviceId),
|
||||
expires(std::chrono::seconds(disco->Expires)) {}
|
||||
DiscoveredTask(const UpnpDiscovery *disco)
|
||||
:url(UpnpDiscovery_get_Location_cstr(disco)),
|
||||
device_id(UpnpDiscovery_get_DeviceID_cstr(disco)),
|
||||
expires(std::chrono::seconds(UpnpDiscovery_get_Expires(disco))) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,11 +158,11 @@ private:
|
||||
static void *Explore(void *);
|
||||
void Explore();
|
||||
|
||||
int OnAlive(Upnp_Discovery *disco);
|
||||
int OnByeBye(Upnp_Discovery *disco);
|
||||
int OnAlive(const UpnpDiscovery *disco);
|
||||
int OnByeBye(const UpnpDiscovery *disco);
|
||||
|
||||
/* virtual methods from class UpnpCallback */
|
||||
virtual int Invoke(Upnp_EventType et, void *evp) override;
|
||||
virtual int Invoke(Upnp_EventType et, const void *evp) override;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -271,16 +271,15 @@ try {
|
||||
inline bool
|
||||
AudioOutput::PlayChunk()
|
||||
{
|
||||
if (tags) {
|
||||
const auto *tag = source.ReadTag();
|
||||
if (tag != nullptr) {
|
||||
const ScopeUnlock unlock(mutex);
|
||||
try {
|
||||
ao_plugin_send_tag(this, *tag);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "Failed to send tag to \"%s\" [%s]",
|
||||
name, plugin.name);
|
||||
}
|
||||
// ensure pending tags are flushed in all cases
|
||||
const auto *tag = source.ReadTag();
|
||||
if (tags && tag != nullptr) {
|
||||
const ScopeUnlock unlock(mutex);
|
||||
try {
|
||||
ao_plugin_send_tag(this, *tag);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "Failed to send tag to \"%s\" [%s]",
|
||||
name, plugin.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -468,6 +468,7 @@ HttpdOutput::SendTag(const Tag &tag)
|
||||
|
||||
try {
|
||||
encoder->SendTag(tag);
|
||||
encoder->Flush();
|
||||
} catch (const std::runtime_error &) {
|
||||
/* ignore */
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "output/MultipleOutputs.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "Idle.hxx"
|
||||
#include "system/PeriodClock.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "thread/Name.hxx"
|
||||
#include "Log.hxx"
|
||||
@@ -146,6 +147,8 @@ class Player {
|
||||
*/
|
||||
SongTime elapsed_time;
|
||||
|
||||
PeriodClock throttle_silence_log;
|
||||
|
||||
public:
|
||||
Player(PlayerControl &_pc, DecoderControl &_dc,
|
||||
MusicBuffer &_buffer)
|
||||
@@ -555,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 {
|
||||
@@ -934,6 +939,8 @@ Player::SongBorder()
|
||||
{
|
||||
FormatDefault(player_domain, "played \"%s\"", song->GetURI());
|
||||
|
||||
throttle_silence_log.Reset();
|
||||
|
||||
ReplacePipe(dc.pipe);
|
||||
|
||||
pc.outputs.SongBorder();
|
||||
@@ -1095,6 +1102,10 @@ Player::Run()
|
||||
/* the decoder is too busy and hasn't provided
|
||||
new PCM data in time: send silence (if the
|
||||
output pipe is empty) */
|
||||
|
||||
if (throttle_silence_log.CheckUpdate(std::chrono::seconds(5)))
|
||||
FormatWarning(player_domain, "Decoder is too slow; playing silence to avoid xrun");
|
||||
|
||||
if (!SendSilence())
|
||||
break;
|
||||
}
|
||||
|
@@ -195,7 +195,7 @@ playlist_list_open_stream_mime2(InputStreamPtr &&is, const char *mime)
|
||||
/* rewind the stream, so each plugin gets a
|
||||
fresh start */
|
||||
try {
|
||||
is->Rewind();
|
||||
is->LockRewind();
|
||||
} catch (const std::runtime_error &) {
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ playlist_list_open_stream_suffix(InputStreamPtr &&is, const char *suffix)
|
||||
/* rewind the stream, so each plugin gets a
|
||||
fresh start */
|
||||
try {
|
||||
is->Rewind();
|
||||
is->LockRewind();
|
||||
} catch (const std::runtime_error &) {
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -364,8 +364,20 @@ Queue::ShuffleOrderFirst(unsigned start, unsigned end)
|
||||
}
|
||||
|
||||
void
|
||||
Queue::ShuffleOrderLast(unsigned start, unsigned end)
|
||||
Queue::ShuffleOrderLastWithPriority(unsigned start, unsigned end)
|
||||
{
|
||||
assert(end <= length);
|
||||
assert(start < end);
|
||||
|
||||
/* skip all items at the start which have a higher priority,
|
||||
because the last item shall only be shuffled within its
|
||||
priority group */
|
||||
const auto last_priority = items[OrderToPosition(end - 1)].priority;
|
||||
while (items[OrderToPosition(start)].priority != last_priority) {
|
||||
++start;
|
||||
assert(start < end);
|
||||
}
|
||||
|
||||
rand.AutoCreate();
|
||||
|
||||
std::uniform_int_distribution<unsigned> distribution(start, end - 1);
|
||||
|
@@ -356,11 +356,12 @@ struct Queue {
|
||||
void ShuffleOrderFirst(unsigned start, unsigned end);
|
||||
|
||||
/**
|
||||
* Shuffles the virtual order of the last song in the specified
|
||||
* (order) range. This is used in random mode after a song has been
|
||||
* appended by queue_append().
|
||||
* Shuffles the virtual order of the last song in the
|
||||
* specified (order) range; only songs which match this song's
|
||||
* priority are considered. This is used in random mode after
|
||||
* a song has been appended by Append().
|
||||
*/
|
||||
void ShuffleOrderLast(unsigned start, unsigned end);
|
||||
void ShuffleOrderLastWithPriority(unsigned start, unsigned end);
|
||||
|
||||
/**
|
||||
* Shuffles a (position) range in the queue. The songs are physically
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user