Compare commits
134 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8842650c33 | ||
![]() |
d5bf128cee | ||
![]() |
5cd86e272f | ||
![]() |
740cbe9e02 | ||
![]() |
ed890a273a | ||
![]() |
068cd559e1 | ||
![]() |
dc127f39a7 | ||
![]() |
7a99a7008c | ||
![]() |
70b451db7b | ||
![]() |
2ab03a0914 | ||
![]() |
2fa8c7d2db | ||
![]() |
7c759ba8b0 | ||
![]() |
6d9b452fde | ||
![]() |
f7eb1c9a83 | ||
![]() |
2d22e6dee4 | ||
![]() |
4587bf759d | ||
![]() |
e1e37cfe3c | ||
![]() |
381934985a | ||
![]() |
a8042885ac | ||
![]() |
a71e68db50 | ||
![]() |
1417578b3d | ||
![]() |
96befa138c | ||
![]() |
16a99804de | ||
![]() |
75a39ed279 | ||
![]() |
4d357ab77c | ||
![]() |
d4f3dd49b4 | ||
![]() |
4ec6d0555a | ||
![]() |
a6a1182c4c | ||
![]() |
a59c9c602b | ||
![]() |
0c4d824d64 | ||
![]() |
a5281856c9 | ||
![]() |
0206a46d39 | ||
![]() |
9475ef2202 | ||
![]() |
edae00e719 | ||
![]() |
fb695bc55f | ||
![]() |
23a5b8fd3c | ||
![]() |
273a93cfcf | ||
![]() |
d105985d78 | ||
![]() |
f8cfeb39e9 | ||
![]() |
d5d3982d3c | ||
![]() |
47341107ea | ||
![]() |
90eaa87a4d | ||
![]() |
b09a54b2c2 | ||
![]() |
10aec174d5 | ||
![]() |
d32ed194e8 | ||
![]() |
70d0fbd715 | ||
![]() |
302432e157 | ||
![]() |
4ab8a677dc | ||
![]() |
52e4a4c904 | ||
![]() |
a0f6932ebe | ||
![]() |
6e700dab69 | ||
![]() |
35eaed7206 | ||
![]() |
e7c963f2ce | ||
![]() |
949d72e368 | ||
![]() |
8d2a184658 | ||
![]() |
c877a32d97 | ||
![]() |
541468f0ca | ||
![]() |
d2797effa3 | ||
![]() |
1170fb1e1e | ||
![]() |
65b9b3195c | ||
![]() |
258830e913 | ||
![]() |
d91da96798 | ||
![]() |
b3897df682 | ||
![]() |
3cacb56bb7 | ||
![]() |
15a1973e28 | ||
![]() |
ad7d47a8ba | ||
![]() |
0948c607b6 | ||
![]() |
60d04052c5 | ||
![]() |
c1780ac657 | ||
![]() |
e49cf0ec38 | ||
![]() |
e1d641f684 | ||
![]() |
4efd0a9f77 | ||
![]() |
f6f8751332 | ||
![]() |
abb28593ce | ||
![]() |
115693b046 | ||
![]() |
e4b055eb6d | ||
![]() |
9866adff95 | ||
![]() |
a8b0c55818 | ||
![]() |
cac88e8be5 | ||
![]() |
e9f6a3482c | ||
![]() |
5d2e80f188 | ||
![]() |
cfd4d5b13e | ||
![]() |
06514aec63 | ||
![]() |
4ded1ae67b | ||
![]() |
1da974e3fa | ||
![]() |
94f06f0946 | ||
![]() |
d9eec8a455 | ||
![]() |
eaecbcafb2 | ||
![]() |
73b5d0a9b9 | ||
![]() |
c2d0f35e7a | ||
![]() |
ab99a57997 | ||
![]() |
c8ebaf3521 | ||
![]() |
52d00f7e30 | ||
![]() |
309491a6d8 | ||
![]() |
e7bfd32ccc | ||
![]() |
6f283b52ab | ||
![]() |
32bddfabea | ||
![]() |
1944c826bc | ||
![]() |
619bb60b26 | ||
![]() |
c549e16ed1 | ||
![]() |
01c9c4507f | ||
![]() |
8c9d7bf07e | ||
![]() |
44ef34db88 | ||
![]() |
5781f223f6 | ||
![]() |
e4c8ebe056 | ||
![]() |
76b25a1377 | ||
![]() |
ccc3ee663b | ||
![]() |
0626661764 | ||
![]() |
31db04a3ca | ||
![]() |
0c7163b9db | ||
![]() |
7d78cad8af | ||
![]() |
912530ed20 | ||
![]() |
d3f37199b9 | ||
![]() |
a4748d84b0 | ||
![]() |
8f847ec381 | ||
![]() |
3a70f09dd3 | ||
![]() |
568f63100b | ||
![]() |
3e25916b37 | ||
![]() |
5f9438dae6 | ||
![]() |
99e65c58ce | ||
![]() |
df71b07e9d | ||
![]() |
2694195215 | ||
![]() |
66450d1f3c | ||
![]() |
76efea3aa7 | ||
![]() |
7ab0dfc8ce | ||
![]() |
15ff7c4cad | ||
![]() |
9ab9b97f20 | ||
![]() |
88d92aceab | ||
![]() |
a2ce4352c8 | ||
![]() |
84f43ccde8 | ||
![]() |
38704c9cf3 | ||
![]() |
910d0ec92b | ||
![]() |
3b05c89765 | ||
![]() |
e77b3fa46f |
NEWS
android
doc
meson.buildpython/build
src
CommandLine.cxxCommandLine.hxxLogInit.cxxMain.cxxPlaylistFile.cxxRemoteTagCache.hxxSongPrint.cxxSongSave.cxxSongSave.hxxStateFileConfig.cxxTagPrint.cxxTimePrint.cxx
android
archive
command
db
decoder
encoder
plugins
event
fs
input
io
java
lib
crypto
curl
dbus
ffmpeg
output
storage
system
tag
time
unix
util
subprojects
systemd
test
win32
53
NEWS
53
NEWS
@@ -1,3 +1,56 @@
|
|||||||
|
ver 0.23.13 (2023/05/22)
|
||||||
|
* input
|
||||||
|
- curl: fix busy loop after connection failed
|
||||||
|
- curl: hide "404" log messages for non-existent ".mpdignore" files
|
||||||
|
* archive
|
||||||
|
- zzip: fix crash bug
|
||||||
|
* database
|
||||||
|
- simple: reveal hidden songs after deleting containing CUE
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: reorder to a lower priority than "gme"
|
||||||
|
- gme: require GME 0.6 or later
|
||||||
|
* output
|
||||||
|
- pipewire: fix corruption bug due to missing lock
|
||||||
|
* Linux
|
||||||
|
- shut down if parent process dies in --no-daemon mode
|
||||||
|
- determine systemd unit directories via pkg-config
|
||||||
|
* support libfmt 10
|
||||||
|
|
||||||
|
ver 0.23.12 (2023/01/17)
|
||||||
|
* input
|
||||||
|
- curl: require CURL 7.55.0 or later
|
||||||
|
* decoder
|
||||||
|
- mad: fix integer underflow with very small files
|
||||||
|
* tags
|
||||||
|
- fix crash bug due to race condition
|
||||||
|
* output
|
||||||
|
- pipewire: adjust to PipeWire 0.3.64 API change
|
||||||
|
* fix build failures with GCC 13
|
||||||
|
|
||||||
|
ver 0.23.11 (2022/11/28)
|
||||||
|
* database
|
||||||
|
- simple: move default database to ~/.cache/mpd/db from ~/.cache/mpd.db
|
||||||
|
- simple: default "cache_directory" to ~/.cache/mpd/mounts
|
||||||
|
* macOS: fix build failure "no archive members specified"
|
||||||
|
* Windows
|
||||||
|
- fix crash bug (stack buffer overflow) after I/O errors
|
||||||
|
- fix path traversal bug because backslash was allowed in playlist names
|
||||||
|
* Android/Windows
|
||||||
|
- update OpenSSL to 3.0.7
|
||||||
|
- re-enable CURL's verbose error strings
|
||||||
|
|
||||||
|
ver 0.23.10 (2022/10/14)
|
||||||
|
* storage
|
||||||
|
- curl: fix file time stamps
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: fix libfmt 9 compiler warning
|
||||||
|
* encoder
|
||||||
|
- flac: fix failure when libFLAC is built without Ogg support
|
||||||
|
* output
|
||||||
|
- alsa: fix crash bug
|
||||||
|
* Windows
|
||||||
|
- log to stdout by default, don't require "log_file" setting
|
||||||
|
|
||||||
ver 0.23.9 (2022/08/18)
|
ver 0.23.9 (2022/08/18)
|
||||||
* input
|
* input
|
||||||
- cdio_paranoia: add options "mode" and "skip"
|
- cdio_paranoia: add options "mode" and "skip"
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.musicpd"
|
package="org.musicpd"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:versionCode="68"
|
android:versionCode="71"
|
||||||
android:versionName="0.23.9">
|
android:versionName="0.23.12">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30"/>
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30"/>
|
||||||
|
|
||||||
|
@@ -100,6 +100,7 @@ class AndroidNdkToolchain:
|
|||||||
common_flags += ' -fvisibility=hidden -fdata-sections -ffunction-sections'
|
common_flags += ' -fvisibility=hidden -fdata-sections -ffunction-sections'
|
||||||
|
|
||||||
self.ar = os.path.join(llvm_bin, 'llvm-ar')
|
self.ar = os.path.join(llvm_bin, 'llvm-ar')
|
||||||
|
self.arflags = 'rcs'
|
||||||
self.ranlib = os.path.join(llvm_bin, 'llvm-ranlib')
|
self.ranlib = os.path.join(llvm_bin, 'llvm-ranlib')
|
||||||
self.nm = os.path.join(llvm_bin, 'llvm-nm')
|
self.nm = os.path.join(llvm_bin, 'llvm-nm')
|
||||||
self.strip = os.path.join(llvm_bin, 'llvm-strip')
|
self.strip = os.path.join(llvm_bin, 'llvm-strip')
|
||||||
|
@@ -38,7 +38,10 @@ author = 'Max Kellermann'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.23.9'
|
with open('../meson.build') as f:
|
||||||
|
import re
|
||||||
|
version = re.match(r"project\([^\)]*\bversion:\s*'([^']+)'",
|
||||||
|
f.read(4096)).group(1)
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
#release = version + '~git'
|
#release = version + '~git'
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ version = '0.23.9'
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = None
|
language = "en"
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
|
@@ -11,6 +11,12 @@ Music Player Daemon
|
|||||||
client
|
client
|
||||||
protocol
|
protocol
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: man pages:
|
||||||
|
|
||||||
|
mpd.1
|
||||||
|
mpd.conf.5
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
@@ -181,7 +181,7 @@
|
|||||||
#
|
#
|
||||||
#database {
|
#database {
|
||||||
# plugin "simple"
|
# plugin "simple"
|
||||||
# path "~/.local/share/mpd/db
|
# path "~/.local/share/mpd/db"
|
||||||
# cache_directory "~/.local/share/mpd/cache"
|
# cache_directory "~/.local/share/mpd/cache"
|
||||||
#}
|
#}
|
||||||
#
|
#
|
||||||
|
@@ -219,8 +219,9 @@ Opens remote files or streams over HTTP using libcurl.
|
|||||||
|
|
||||||
Note that unless overridden by the below settings (e.g. by setting
|
Note that unless overridden by the below settings (e.g. by setting
|
||||||
them to a blank value), general curl configuration from environment
|
them to a blank value), general curl configuration from environment
|
||||||
variables such as ``http_proxy`` or specified in :file:`~/.curlrc`
|
variables such as ``http_proxy`` will be in effect.
|
||||||
will be in effect.
|
|
||||||
|
User name and password are read from an optional :file:`~/.netrc`, :file:`~/.curlrc` is not read.
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
:widths: 20 80
|
:widths: 20 80
|
||||||
|
@@ -199,7 +199,7 @@ Compiling for Android
|
|||||||
You need:
|
You need:
|
||||||
|
|
||||||
* Android SDK
|
* Android SDK
|
||||||
* `Android NDK r23 <https://developer.android.com/ndk/downloads>`_
|
* `Android NDK r25b <https://developer.android.com/ndk/downloads>`_
|
||||||
* `Meson 0.56.0 <http://mesonbuild.com/>`__ and `Ninja
|
* `Meson 0.56.0 <http://mesonbuild.com/>`__ and `Ninja
|
||||||
<https://ninja-build.org/>`__
|
<https://ninja-build.org/>`__
|
||||||
* cmake
|
* cmake
|
||||||
@@ -611,6 +611,11 @@ If ReplayGain is enabled, then the setting ``replaygain_preamp`` is
|
|||||||
set to a value (in dB) between ``-15`` and ``15``. This is the gain
|
set to a value (in dB) between ``-15`` and ``15``. This is the gain
|
||||||
applied to songs with ReplayGain tags.
|
applied to songs with ReplayGain tags.
|
||||||
|
|
||||||
|
On songs without ReplayGain tags, the setting
|
||||||
|
``replaygain_missing_preamp`` is used instead. If this setting is not
|
||||||
|
configured, then no ReplayGain is applied to such songs, and they will
|
||||||
|
appear too loud.
|
||||||
|
|
||||||
ReplayGain is usually implemented with a software volume filter (which
|
ReplayGain is usually implemented with a software volume filter (which
|
||||||
prevents `Bit-perfect playback`_). To use a hardware mixer, set
|
prevents `Bit-perfect playback`_). To use a hardware mixer, set
|
||||||
``replay_gain_handler`` to ``mixer`` in the ``audio_output`` section
|
``replay_gain_handler`` to ``mixer`` in the ``audio_output`` section
|
||||||
|
12
meson.build
12
meson.build
@@ -1,7 +1,7 @@
|
|||||||
project(
|
project(
|
||||||
'mpd',
|
'mpd',
|
||||||
['c', 'cpp'],
|
['c', 'cpp'],
|
||||||
version: '0.23.9',
|
version: '0.23.13',
|
||||||
meson_version: '>= 0.56.0',
|
meson_version: '>= 0.56.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=c11',
|
'c_std=c11',
|
||||||
@@ -205,7 +205,6 @@ enable_daemon = not is_windows and not is_android and get_option('daemon')
|
|||||||
conf.set('ENABLE_DAEMON', enable_daemon)
|
conf.set('ENABLE_DAEMON', enable_daemon)
|
||||||
|
|
||||||
conf.set('HAVE_GETPWNAM_R', compiler.has_function('getpwnam_r'))
|
conf.set('HAVE_GETPWNAM_R', compiler.has_function('getpwnam_r'))
|
||||||
conf.set('HAVE_GETPWUID_R', compiler.has_function('getpwuid_r'))
|
|
||||||
conf.set('HAVE_INITGROUPS', compiler.has_function('initgroups'))
|
conf.set('HAVE_INITGROUPS', compiler.has_function('initgroups'))
|
||||||
conf.set('HAVE_FNMATCH', compiler.has_function('fnmatch'))
|
conf.set('HAVE_FNMATCH', compiler.has_function('fnmatch'))
|
||||||
|
|
||||||
@@ -251,6 +250,14 @@ endif
|
|||||||
|
|
||||||
fmt_dep = dependency('fmt', fallback: ['fmt', 'fmt_dep'])
|
fmt_dep = dependency('fmt', fallback: ['fmt', 'fmt_dep'])
|
||||||
|
|
||||||
|
if compiler.get_id() == 'clang' and compiler.version().version_compare('<15')
|
||||||
|
fmt_dep = declare_dependency(
|
||||||
|
dependencies: fmt_dep,
|
||||||
|
# suppress bogus clang 14 warning (the version in Android NDK r25b)
|
||||||
|
compile_args: ['-Wno-unused-local-typedef'],
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
log = static_library(
|
log = static_library(
|
||||||
'log',
|
'log',
|
||||||
'src/Log.cxx',
|
'src/Log.cxx',
|
||||||
@@ -382,6 +389,7 @@ endif
|
|||||||
|
|
||||||
if enable_database
|
if enable_database
|
||||||
sources += [
|
sources += [
|
||||||
|
'src/storage/StorageState.cxx',
|
||||||
'src/queue/PlaylistUpdate.cxx',
|
'src/queue/PlaylistUpdate.cxx',
|
||||||
'src/command/StorageCommands.cxx',
|
'src/command/StorageCommands.cxx',
|
||||||
'src/command/DatabaseCommands.cxx',
|
'src/command/DatabaseCommands.cxx',
|
||||||
|
@@ -45,14 +45,27 @@ class AutotoolsProject(MakeProject):
|
|||||||
'LDFLAGS=' + toolchain.ldflags + ' ' + self.ldflags,
|
'LDFLAGS=' + toolchain.ldflags + ' ' + self.ldflags,
|
||||||
'LIBS=' + toolchain.libs + ' ' + self.libs,
|
'LIBS=' + toolchain.libs + ' ' + self.libs,
|
||||||
'AR=' + toolchain.ar,
|
'AR=' + toolchain.ar,
|
||||||
|
'ARFLAGS=' + toolchain.arflags,
|
||||||
'RANLIB=' + toolchain.ranlib,
|
'RANLIB=' + toolchain.ranlib,
|
||||||
'STRIP=' + toolchain.strip,
|
'STRIP=' + toolchain.strip,
|
||||||
'--host=' + toolchain.arch,
|
'--host=' + toolchain.arch,
|
||||||
'--prefix=' + toolchain.install_prefix,
|
'--prefix=' + toolchain.install_prefix,
|
||||||
'--enable-silent-rules',
|
'--disable-silent-rules',
|
||||||
] + self.configure_args
|
] + self.configure_args
|
||||||
|
|
||||||
subprocess.check_call(configure, cwd=build, env=toolchain.env)
|
try:
|
||||||
|
print(configure)
|
||||||
|
subprocess.check_call(configure, cwd=build, env=toolchain.env)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
# dump config.log after a failed configure run
|
||||||
|
try:
|
||||||
|
with open(os.path.join(build, 'config.log')) as f:
|
||||||
|
sys.stdout.write(f.read())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# re-raise the exception
|
||||||
|
raise
|
||||||
|
|
||||||
return build
|
return build
|
||||||
|
|
||||||
def _build(self, toolchain):
|
def _build(self, toolchain):
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from build.project import Project
|
from build.project import Project
|
||||||
@@ -25,13 +26,33 @@ set(CMAKE_SYSTEM_PROCESSOR {toolchain.actual_arch.split('-', 1)[0]})
|
|||||||
set(CMAKE_C_COMPILER_TARGET {toolchain.actual_arch})
|
set(CMAKE_C_COMPILER_TARGET {toolchain.actual_arch})
|
||||||
set(CMAKE_CXX_COMPILER_TARGET {toolchain.actual_arch})
|
set(CMAKE_CXX_COMPILER_TARGET {toolchain.actual_arch})
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "{toolchain.cflags} {toolchain.cppflags}")
|
set(CMAKE_C_FLAGS_INIT "{toolchain.cflags} {toolchain.cppflags}")
|
||||||
set(CMAKE_CXX_FLAGS "{toolchain.cxxflags} {toolchain.cppflags}")
|
set(CMAKE_CXX_FLAGS_INIT "{toolchain.cxxflags} {toolchain.cppflags}")
|
||||||
""")
|
""")
|
||||||
__write_cmake_compiler(f, 'C', toolchain.cc)
|
__write_cmake_compiler(f, 'C', toolchain.cc)
|
||||||
__write_cmake_compiler(f, 'CXX', toolchain.cxx)
|
__write_cmake_compiler(f, 'CXX', toolchain.cxx)
|
||||||
|
|
||||||
def configure(toolchain, src, build, args=()):
|
if cmake_system_name == 'Darwin':
|
||||||
|
# On macOS, cmake forcibly adds an "-isysroot" flag even if
|
||||||
|
# one is already present in the flags variable; this breaks
|
||||||
|
# cross-compiling for iOS, and can be worked around by setting
|
||||||
|
# the CMAKE_OSX_SYSROOT variable
|
||||||
|
# (https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html).
|
||||||
|
m = re.search(r'-isysroot +(\S+)', toolchain.cflags)
|
||||||
|
if m:
|
||||||
|
sysroot = m.group(1)
|
||||||
|
|
||||||
|
print(f'set(CMAKE_OSX_SYSROOT {sysroot})', file=f)
|
||||||
|
|
||||||
|
# search libraries and headers only in the sysroot, not on
|
||||||
|
# the build host
|
||||||
|
f.write(f"""
|
||||||
|
set(CMAKE_FIND_ROOT_PATH "{toolchain.install_prefix};{sysroot}")
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
""")
|
||||||
|
|
||||||
|
def configure(toolchain, src, build, args=(), env=None):
|
||||||
cross_args = []
|
cross_args = []
|
||||||
|
|
||||||
if toolchain.is_windows:
|
if toolchain.is_windows:
|
||||||
@@ -61,15 +82,23 @@ def configure(toolchain, src, build, args=()):
|
|||||||
'-GNinja',
|
'-GNinja',
|
||||||
] + cross_args + args
|
] + cross_args + args
|
||||||
|
|
||||||
subprocess.check_call(configure, env=toolchain.env, cwd=build)
|
if env is None:
|
||||||
|
env = toolchain.env
|
||||||
|
else:
|
||||||
|
env = {**toolchain.env, **env}
|
||||||
|
|
||||||
|
print(configure)
|
||||||
|
subprocess.check_call(configure, env=env, cwd=build)
|
||||||
|
|
||||||
class CmakeProject(Project):
|
class CmakeProject(Project):
|
||||||
def __init__(self, url, md5, installed, configure_args=[],
|
def __init__(self, url, md5, installed, configure_args=[],
|
||||||
windows_configure_args=[],
|
windows_configure_args=[],
|
||||||
|
env=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
Project.__init__(self, url, md5, installed, **kwargs)
|
Project.__init__(self, url, md5, installed, **kwargs)
|
||||||
self.configure_args = configure_args
|
self.configure_args = configure_args
|
||||||
self.windows_configure_args = windows_configure_args
|
self.windows_configure_args = windows_configure_args
|
||||||
|
self.env = env
|
||||||
|
|
||||||
def configure(self, toolchain):
|
def configure(self, toolchain):
|
||||||
src = self.unpack(toolchain)
|
src = self.unpack(toolchain)
|
||||||
@@ -77,10 +106,10 @@ class CmakeProject(Project):
|
|||||||
configure_args = self.configure_args
|
configure_args = self.configure_args
|
||||||
if toolchain.is_windows:
|
if toolchain.is_windows:
|
||||||
configure_args = configure_args + self.windows_configure_args
|
configure_args = configure_args + self.windows_configure_args
|
||||||
configure(toolchain, src, build, configure_args)
|
configure(toolchain, src, build, configure_args, self.env)
|
||||||
return build
|
return build
|
||||||
|
|
||||||
def _build(self, toolchain):
|
def _build(self, toolchain):
|
||||||
build = self.configure(toolchain)
|
build = self.configure(toolchain)
|
||||||
subprocess.check_call(['ninja', 'install'],
|
subprocess.check_call(['ninja', '-v', 'install'],
|
||||||
cwd=build, env=toolchain.env)
|
cwd=build, env=toolchain.env)
|
||||||
|
@@ -43,20 +43,22 @@ opus = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
flac = AutotoolsProject(
|
flac = AutotoolsProject(
|
||||||
'http://downloads.xiph.org/releases/flac/flac-1.3.4.tar.xz',
|
'http://downloads.xiph.org/releases/flac/flac-1.4.2.tar.xz',
|
||||||
'8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737',
|
'e322d58a1f48d23d9dd38f432672865f6f79e73a6f9cc5a5f57fcaa83eb5a8e4',
|
||||||
'lib/libFLAC.a',
|
'lib/libFLAC.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
'--disable-stack-smash-protection',
|
||||||
'--disable-xmms-plugin', '--disable-cpplibs',
|
'--disable-xmms-plugin', '--disable-cpplibs',
|
||||||
'--disable-doxygen-docs',
|
'--disable-doxygen-docs',
|
||||||
|
'--disable-programs',
|
||||||
],
|
],
|
||||||
subdirs=['include', 'src/libFLAC'],
|
subdirs=['include', 'src/libFLAC'],
|
||||||
)
|
)
|
||||||
|
|
||||||
zlib = ZlibProject(
|
zlib = ZlibProject(
|
||||||
'http://zlib.net/zlib-1.2.12.tar.xz',
|
'http://zlib.net/zlib-1.2.13.tar.xz',
|
||||||
'7db46b8d7726232a621befaab4a1c870f00a90805511c0e0090441dac57def18',
|
'd14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98',
|
||||||
'lib/libz.a',
|
'lib/libz.a',
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -112,30 +114,31 @@ libmodplug = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
libopenmpt = AutotoolsProject(
|
libopenmpt = AutotoolsProject(
|
||||||
'https://lib.openmpt.org/files/libopenmpt/src/libopenmpt-0.5.12+release.autotools.tar.gz',
|
'https://lib.openmpt.org/files/libopenmpt/src/libopenmpt-0.6.6+release.autotools.tar.gz',
|
||||||
'892aea7a599b5d21842bebf463b5aafdad5711be7008dd84401920c6234820af',
|
'6ddb9e26a430620944891796fefb1bbb38bd9148f6cfc558810c0d3f269876c7',
|
||||||
'lib/libopenmpt.a',
|
'lib/libopenmpt.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
'--disable-openmpt123',
|
'--disable-openmpt123',
|
||||||
|
'--disable-examples',
|
||||||
|
'--disable-tests',
|
||||||
|
'--disable-doxygen-doc',
|
||||||
'--without-mpg123', '--without-ogg', '--without-vorbis', '--without-vorbisfile',
|
'--without-mpg123', '--without-ogg', '--without-vorbis', '--without-vorbisfile',
|
||||||
'--without-portaudio', '--without-portaudiocpp', '--without-sndfile',
|
'--without-portaudio', '--without-portaudiocpp', '--without-sndfile',
|
||||||
|
'--without-flac',
|
||||||
],
|
],
|
||||||
base='libopenmpt-0.5.12+release.autotools',
|
base='libopenmpt-0.6.6+release.autotools',
|
||||||
)
|
)
|
||||||
|
|
||||||
wildmidi = CmakeProject(
|
wildmidi = CmakeProject(
|
||||||
'https://codeload.github.com/Mindwerks/wildmidi/tar.gz/wildmidi-0.4.4',
|
'https://github.com/Mindwerks/wildmidi/releases/download/wildmidi-0.4.5/wildmidi-0.4.5.tar.gz',
|
||||||
'6f267c8d331e9859906837e2c197093fddec31829d2ebf7b958cf6b7ae935430',
|
'd5e7bef00a7aa47534a53d43b1265f8d3d27f6a28e7f563c1cdf02ff4fa35b99',
|
||||||
'lib/libWildMidi.a',
|
'lib/libWildMidi.a',
|
||||||
[
|
[
|
||||||
'-DBUILD_SHARED_LIBS=OFF',
|
'-DBUILD_SHARED_LIBS=OFF',
|
||||||
'-DWANT_PLAYER=OFF',
|
'-DWANT_PLAYER=OFF',
|
||||||
'-DWANT_STATIC=ON',
|
'-DWANT_STATIC=ON',
|
||||||
],
|
],
|
||||||
base='wildmidi-wildmidi-0.4.4',
|
|
||||||
name='wildmidi',
|
|
||||||
version='0.4.4',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
gme = CmakeProject(
|
gme = CmakeProject(
|
||||||
@@ -151,8 +154,8 @@ gme = CmakeProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-5.1.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-6.0.tar.xz',
|
||||||
'55eb6aab5ee235550fa54a33eaf8bf1b4ec66c01453182b12f6a993d75698b03',
|
'57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082',
|
||||||
'lib/libavcodec.a',
|
'lib/libavcodec.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
@@ -170,13 +173,16 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-pixelutils',
|
'--disable-pixelutils',
|
||||||
'--disable-network',
|
'--disable-network',
|
||||||
'--disable-encoders',
|
'--disable-encoders',
|
||||||
|
'--disable-hwaccels',
|
||||||
'--disable-muxers',
|
'--disable-muxers',
|
||||||
'--disable-protocols',
|
'--disable-protocols',
|
||||||
'--disable-devices',
|
'--disable-devices',
|
||||||
'--disable-filters',
|
'--disable-filters',
|
||||||
'--disable-v4l2_m2m',
|
'--disable-v4l2_m2m',
|
||||||
|
|
||||||
|
'--disable-sdl2',
|
||||||
'--disable-vulkan',
|
'--disable-vulkan',
|
||||||
|
'--disable-xlib',
|
||||||
|
|
||||||
'--disable-parser=bmp',
|
'--disable-parser=bmp',
|
||||||
'--disable-parser=cavsvideo',
|
'--disable-parser=cavsvideo',
|
||||||
@@ -190,17 +196,22 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-parser=h263',
|
'--disable-parser=h263',
|
||||||
'--disable-parser=h264',
|
'--disable-parser=h264',
|
||||||
'--disable-parser=hevc',
|
'--disable-parser=hevc',
|
||||||
|
'--disable-parser=jpeg2000',
|
||||||
'--disable-parser=mjpeg',
|
'--disable-parser=mjpeg',
|
||||||
'--disable-parser=mlp',
|
'--disable-parser=mlp',
|
||||||
'--disable-parser=mpeg4video',
|
'--disable-parser=mpeg4video',
|
||||||
'--disable-parser=mpegvideo',
|
'--disable-parser=mpegvideo',
|
||||||
'--disable-parser=opus',
|
'--disable-parser=opus',
|
||||||
|
'--disable-parser=qoi',
|
||||||
|
'--disable-parser=rv30',
|
||||||
|
'--disable-parser=rv40',
|
||||||
'--disable-parser=vc1',
|
'--disable-parser=vc1',
|
||||||
'--disable-parser=vp3',
|
'--disable-parser=vp3',
|
||||||
'--disable-parser=vp8',
|
'--disable-parser=vp8',
|
||||||
'--disable-parser=vp9',
|
'--disable-parser=vp9',
|
||||||
'--disable-parser=png',
|
'--disable-parser=png',
|
||||||
'--disable-parser=pnm',
|
'--disable-parser=pnm',
|
||||||
|
'--disable-parser=webp',
|
||||||
'--disable-parser=xma',
|
'--disable-parser=xma',
|
||||||
|
|
||||||
'--disable-demuxer=aqtitle',
|
'--disable-demuxer=aqtitle',
|
||||||
@@ -216,6 +227,42 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-demuxer=h264',
|
'--disable-demuxer=h264',
|
||||||
'--disable-demuxer=ico',
|
'--disable-demuxer=ico',
|
||||||
'--disable-demuxer=image2',
|
'--disable-demuxer=image2',
|
||||||
|
'--disable-demuxer=image2pipe',
|
||||||
|
'--disable-demuxer=image_bmp_pipe',
|
||||||
|
'--disable-demuxer=image_cri_pipe',
|
||||||
|
'--disable-demuxer=image_dds_pipe',
|
||||||
|
'--disable-demuxer=image_dpx_pipe',
|
||||||
|
'--disable-demuxer=image_exr_pipe',
|
||||||
|
'--disable-demuxer=image_gem_pipe',
|
||||||
|
'--disable-demuxer=image_gif_pipe',
|
||||||
|
'--disable-demuxer=image_j2k_pipe',
|
||||||
|
'--disable-demuxer=image_jpeg_pipe',
|
||||||
|
'--disable-demuxer=image_jpegls_pipe',
|
||||||
|
'--disable-demuxer=image_jpegxl_pipe',
|
||||||
|
'--disable-demuxer=image_pam_pipe',
|
||||||
|
'--disable-demuxer=image_pbm_pipe',
|
||||||
|
'--disable-demuxer=image_pcx_pipe',
|
||||||
|
'--disable-demuxer=image_pfm_pipe',
|
||||||
|
'--disable-demuxer=image_pgm_pipe',
|
||||||
|
'--disable-demuxer=image_pgmyuv_pipe',
|
||||||
|
'--disable-demuxer=image_pgx_pipe',
|
||||||
|
'--disable-demuxer=image_phm_pipe',
|
||||||
|
'--disable-demuxer=image_photocd_pipe',
|
||||||
|
'--disable-demuxer=image_pictor_pipe',
|
||||||
|
'--disable-demuxer=image_png_pipe',
|
||||||
|
'--disable-demuxer=image_ppm_pipe',
|
||||||
|
'--disable-demuxer=image_psd_pipe',
|
||||||
|
'--disable-demuxer=image_qdraw_pipe',
|
||||||
|
'--disable-demuxer=image_qoi_pipe',
|
||||||
|
'--disable-demuxer=image_sgi_pipe',
|
||||||
|
'--disable-demuxer=image_sunrast_pipe',
|
||||||
|
'--disable-demuxer=image_svg_pipe',
|
||||||
|
'--disable-demuxer=image_tiff_pipe',
|
||||||
|
'--disable-demuxer=image_vbn_pipe',
|
||||||
|
'--disable-demuxer=image_webp_pipe',
|
||||||
|
'--disable-demuxer=image_xbm_pipe',
|
||||||
|
'--disable-demuxer=image_xpm_pipe',
|
||||||
|
'--disable-demuxer=image_xwd_pipe',
|
||||||
'--disable-demuxer=jacosub',
|
'--disable-demuxer=jacosub',
|
||||||
'--disable-demuxer=lrc',
|
'--disable-demuxer=lrc',
|
||||||
'--disable-demuxer=microdvd',
|
'--disable-demuxer=microdvd',
|
||||||
@@ -238,6 +285,7 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-demuxer=tedcaptions',
|
'--disable-demuxer=tedcaptions',
|
||||||
'--disable-demuxer=vobsub',
|
'--disable-demuxer=vobsub',
|
||||||
'--disable-demuxer=vplayer',
|
'--disable-demuxer=vplayer',
|
||||||
|
'--disable-demuxer=webm_dash_manifest',
|
||||||
'--disable-demuxer=webvtt',
|
'--disable-demuxer=webvtt',
|
||||||
'--disable-demuxer=yuv4mpegpipe',
|
'--disable-demuxer=yuv4mpegpipe',
|
||||||
|
|
||||||
@@ -267,78 +315,179 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-decoder=qdmc',
|
'--disable-decoder=qdmc',
|
||||||
|
|
||||||
# disable lots of image and video codecs
|
# disable lots of image and video codecs
|
||||||
|
'--disable-decoder=acelp_kelvin',
|
||||||
|
'--disable-decoder=agm',
|
||||||
|
'--disable-decoder=aic',
|
||||||
|
'--disable-decoder=alias_pix',
|
||||||
|
'--disable-decoder=ansi',
|
||||||
|
'--disable-decoder=apng',
|
||||||
|
'--disable-decoder=arbc',
|
||||||
|
'--disable-decoder=argo',
|
||||||
'--disable-decoder=ass',
|
'--disable-decoder=ass',
|
||||||
'--disable-decoder=asv1',
|
'--disable-decoder=asv1',
|
||||||
'--disable-decoder=asv2',
|
'--disable-decoder=asv2',
|
||||||
'--disable-decoder=apng',
|
'--disable-decoder=aura',
|
||||||
|
'--disable-decoder=aura2',
|
||||||
'--disable-decoder=avrn',
|
'--disable-decoder=avrn',
|
||||||
'--disable-decoder=avrp',
|
'--disable-decoder=avrp',
|
||||||
|
'--disable-decoder=avui',
|
||||||
|
'--disable-decoder=ayuv',
|
||||||
'--disable-decoder=bethsoftvid',
|
'--disable-decoder=bethsoftvid',
|
||||||
|
'--disable-decoder=bfi',
|
||||||
'--disable-decoder=bink',
|
'--disable-decoder=bink',
|
||||||
|
'--disable-decoder=bintext',
|
||||||
|
'--disable-decoder=bitpacked',
|
||||||
'--disable-decoder=bmp',
|
'--disable-decoder=bmp',
|
||||||
'--disable-decoder=bmv_video',
|
'--disable-decoder=bmv_video',
|
||||||
|
'--disable-decoder=brender_pix',
|
||||||
|
'--disable-decoder=c93',
|
||||||
'--disable-decoder=cavs',
|
'--disable-decoder=cavs',
|
||||||
'--disable-decoder=ccaption',
|
'--disable-decoder=ccaption',
|
||||||
'--disable-decoder=cdgraphics',
|
'--disable-decoder=cdgraphics',
|
||||||
|
'--disable-decoder=cdtoons',
|
||||||
|
'--disable-decoder=cdxl',
|
||||||
|
'--disable-decoder=cfhd',
|
||||||
|
'--disable-decoder=cinepak',
|
||||||
'--disable-decoder=clearvideo',
|
'--disable-decoder=clearvideo',
|
||||||
|
'--disable-decoder=cljr',
|
||||||
|
'--disable-decoder=cllc',
|
||||||
|
'--disable-decoder=cpia',
|
||||||
|
'--disable-decoder=cscd',
|
||||||
|
'--disable-decoder=cyuv',
|
||||||
|
'--disable-decoder=dds',
|
||||||
'--disable-decoder=dirac',
|
'--disable-decoder=dirac',
|
||||||
|
'--disable-decoder=dnxhd',
|
||||||
|
'--disable-decoder=dpx',
|
||||||
'--disable-decoder=dsicinvideo',
|
'--disable-decoder=dsicinvideo',
|
||||||
'--disable-decoder=dvbsub',
|
'--disable-decoder=dvbsub',
|
||||||
'--disable-decoder=dvdsub',
|
'--disable-decoder=dvdsub',
|
||||||
'--disable-decoder=dvvideo',
|
'--disable-decoder=dvvideo',
|
||||||
|
'--disable-decoder=dxa',
|
||||||
|
'--disable-decoder=dxtory',
|
||||||
|
'--disable-decoder=dxv',
|
||||||
|
'--disable-decoder=eacmv',
|
||||||
|
'--disable-decoder=eamad',
|
||||||
|
'--disable-decoder=eatgq',
|
||||||
|
'--disable-decoder=eatgv',
|
||||||
|
'--disable-decoder=eatqi',
|
||||||
|
'--disable-decoder=eightbps',
|
||||||
|
'--disable-decoder=escape124',
|
||||||
|
'--disable-decoder=escape130',
|
||||||
'--disable-decoder=exr',
|
'--disable-decoder=exr',
|
||||||
'--disable-decoder=ffv1',
|
'--disable-decoder=ffv1',
|
||||||
'--disable-decoder=ffvhuff',
|
'--disable-decoder=ffvhuff',
|
||||||
'--disable-decoder=ffwavesynth',
|
'--disable-decoder=ffwavesynth',
|
||||||
|
'--disable-decoder=fic',
|
||||||
|
'--disable-decoder=fits',
|
||||||
|
'--disable-decoder=flashsv',
|
||||||
|
'--disable-decoder=flashsv2',
|
||||||
'--disable-decoder=flic',
|
'--disable-decoder=flic',
|
||||||
'--disable-decoder=flv',
|
'--disable-decoder=flv',
|
||||||
|
'--disable-decoder=fmvc',
|
||||||
'--disable-decoder=fraps',
|
'--disable-decoder=fraps',
|
||||||
|
'--disable-decoder=fourxm',
|
||||||
|
'--disable-decoder=frwu',
|
||||||
|
'--disable-decoder=g2m',
|
||||||
|
'--disable-decoder=gdv',
|
||||||
|
'--disable-decoder=gem',
|
||||||
'--disable-decoder=gif',
|
'--disable-decoder=gif',
|
||||||
'--disable-decoder=h261',
|
'--disable-decoder=h261',
|
||||||
'--disable-decoder=h263',
|
'--disable-decoder=h263',
|
||||||
'--disable-decoder=h263i',
|
'--disable-decoder=h263i',
|
||||||
'--disable-decoder=h263p',
|
'--disable-decoder=h263p',
|
||||||
'--disable-decoder=h264',
|
'--disable-decoder=h264',
|
||||||
|
'--disable-decoder=hap',
|
||||||
'--disable-decoder=hevc',
|
'--disable-decoder=hevc',
|
||||||
'--disable-decoder=hnm4_video',
|
'--disable-decoder=hnm4_video',
|
||||||
'--disable-decoder=hq_hqa',
|
'--disable-decoder=hq_hqa',
|
||||||
'--disable-decoder=hqx',
|
'--disable-decoder=hqx',
|
||||||
|
'--disable-decoder=huffyuv',
|
||||||
|
'--disable-decoder=hymt',
|
||||||
'--disable-decoder=idcin',
|
'--disable-decoder=idcin',
|
||||||
|
'--disable-decoder=idf',
|
||||||
'--disable-decoder=iff_ilbm',
|
'--disable-decoder=iff_ilbm',
|
||||||
|
'--disable-decoder=imm4',
|
||||||
'--disable-decoder=indeo2',
|
'--disable-decoder=indeo2',
|
||||||
'--disable-decoder=indeo3',
|
'--disable-decoder=indeo3',
|
||||||
'--disable-decoder=indeo4',
|
'--disable-decoder=indeo4',
|
||||||
'--disable-decoder=indeo5',
|
'--disable-decoder=indeo5',
|
||||||
'--disable-decoder=interplay_video',
|
'--disable-decoder=interplay_video',
|
||||||
|
'--disable-decoder=ipu',
|
||||||
'--disable-decoder=jacosub',
|
'--disable-decoder=jacosub',
|
||||||
'--disable-decoder=jpeg2000',
|
'--disable-decoder=jpeg2000',
|
||||||
'--disable-decoder=jpegls',
|
'--disable-decoder=jpegls',
|
||||||
|
'--disable-decoder=jv',
|
||||||
|
'--disable-decoder=kgv1',
|
||||||
|
'--disable-decoder=kmvc',
|
||||||
|
'--disable-decoder=lagarith',
|
||||||
|
'--disable-decoder=loco',
|
||||||
|
'--disable-decoder=lscr',
|
||||||
|
'--disable-decoder=m101',
|
||||||
|
'--disable-decoder=magicyuv',
|
||||||
|
'--disable-decoder=mdec',
|
||||||
'--disable-decoder=microdvd',
|
'--disable-decoder=microdvd',
|
||||||
'--disable-decoder=mimic',
|
'--disable-decoder=mimic',
|
||||||
'--disable-decoder=mjpeg',
|
'--disable-decoder=mjpeg',
|
||||||
'--disable-decoder=mmvideo',
|
'--disable-decoder=mmvideo',
|
||||||
'--disable-decoder=mpl2',
|
'--disable-decoder=mpl2',
|
||||||
|
'--disable-decoder=mobiclip',
|
||||||
'--disable-decoder=motionpixels',
|
'--disable-decoder=motionpixels',
|
||||||
|
'--disable-decoder=movtext',
|
||||||
'--disable-decoder=mpeg1video',
|
'--disable-decoder=mpeg1video',
|
||||||
'--disable-decoder=mpeg2video',
|
'--disable-decoder=mpeg2video',
|
||||||
'--disable-decoder=mpeg4',
|
'--disable-decoder=mpeg4',
|
||||||
'--disable-decoder=mpegvideo',
|
'--disable-decoder=mpegvideo',
|
||||||
|
'--disable-decoder=msa1',
|
||||||
'--disable-decoder=mscc',
|
'--disable-decoder=mscc',
|
||||||
'--disable-decoder=msmpeg4_crystalhd',
|
'--disable-decoder=msmpeg4_crystalhd',
|
||||||
'--disable-decoder=msmpeg4v1',
|
'--disable-decoder=msmpeg4v1',
|
||||||
'--disable-decoder=msmpeg4v2',
|
'--disable-decoder=msmpeg4v2',
|
||||||
'--disable-decoder=msmpeg4v3',
|
'--disable-decoder=msmpeg4v3',
|
||||||
|
'--disable-decoder=msp2',
|
||||||
|
'--disable-decoder=msrle',
|
||||||
|
'--disable-decoder=mss1',
|
||||||
'--disable-decoder=msvideo1',
|
'--disable-decoder=msvideo1',
|
||||||
'--disable-decoder=mszh',
|
'--disable-decoder=mszh',
|
||||||
|
'--disable-decoder=mts2',
|
||||||
|
'--disable-decoder=mv30',
|
||||||
'--disable-decoder=mvc1',
|
'--disable-decoder=mvc1',
|
||||||
'--disable-decoder=mvc2',
|
'--disable-decoder=mvc2',
|
||||||
|
'--disable-decoder=mvdv',
|
||||||
|
'--disable-decoder=mvha',
|
||||||
|
'--disable-decoder=mwsc',
|
||||||
|
'--disable-decoder=notchlc',
|
||||||
|
'--disable-decoder=nuv',
|
||||||
'--disable-decoder=on2avc',
|
'--disable-decoder=on2avc',
|
||||||
'--disable-decoder=paf_video',
|
'--disable-decoder=paf_video',
|
||||||
|
'--disable-decoder=pam',
|
||||||
|
'--disable-decoder=pbm',
|
||||||
|
'--disable-decoder=pcx',
|
||||||
|
'--disable-decoder=pgm',
|
||||||
|
'--disable-decoder=pgmyuv',
|
||||||
|
'--disable-decoder=pgssub',
|
||||||
|
'--disable-decoder=pgx',
|
||||||
|
'--disable-decoder=phm',
|
||||||
|
'--disable-decoder=photocd',
|
||||||
'--disable-decoder=png',
|
'--disable-decoder=png',
|
||||||
|
'--disable-decoder=pictor',
|
||||||
|
'--disable-decoder=pixlet',
|
||||||
|
'--disable-decoder=pjs',
|
||||||
|
'--disable-decoder=ppm',
|
||||||
|
'--disable-decoder=prores',
|
||||||
|
'--disable-decoder=prosumer',
|
||||||
|
'--disable-decoder=psd',
|
||||||
|
'--disable-decoder=ptx',
|
||||||
'--disable-decoder=qdraw',
|
'--disable-decoder=qdraw',
|
||||||
|
'--disable-decoder=qoi',
|
||||||
'--disable-decoder=qpeg',
|
'--disable-decoder=qpeg',
|
||||||
|
'--disable-decoder=qtrle',
|
||||||
'--disable-decoder=rawvideo',
|
'--disable-decoder=rawvideo',
|
||||||
|
'--disable-decoder=r10k',
|
||||||
|
'--disable-decoder=r210',
|
||||||
|
'--disable-decoder=rasc',
|
||||||
'--disable-decoder=realtext',
|
'--disable-decoder=realtext',
|
||||||
|
'--disable-decoder=rl2',
|
||||||
|
'--disable-decoder=rpza',
|
||||||
'--disable-decoder=roq',
|
'--disable-decoder=roq',
|
||||||
'--disable-decoder=roq_dpcm',
|
'--disable-decoder=roq_dpcm',
|
||||||
'--disable-decoder=rscc',
|
'--disable-decoder=rscc',
|
||||||
@@ -347,53 +496,120 @@ ffmpeg = FfmpegProject(
|
|||||||
'--disable-decoder=rv30',
|
'--disable-decoder=rv30',
|
||||||
'--disable-decoder=rv40',
|
'--disable-decoder=rv40',
|
||||||
'--disable-decoder=sami',
|
'--disable-decoder=sami',
|
||||||
|
'--disable-decoder=sanm',
|
||||||
|
'--disable-decoder=scpr',
|
||||||
|
'--disable-decoder=screenpresso',
|
||||||
|
'--disable-decoder=sga',
|
||||||
|
'--disable-decoder=sgi',
|
||||||
|
'--disable-decoder=sgirle',
|
||||||
'--disable-decoder=sheervideo',
|
'--disable-decoder=sheervideo',
|
||||||
|
'--disable-decoder=simbiosis_imx',
|
||||||
|
'--disable-decoder=smc',
|
||||||
'--disable-decoder=snow',
|
'--disable-decoder=snow',
|
||||||
|
'--disable-decoder=speedhq',
|
||||||
|
'--disable-decoder=srgc',
|
||||||
'--disable-decoder=srt',
|
'--disable-decoder=srt',
|
||||||
|
'--disable-decoder=ssa',
|
||||||
'--disable-decoder=stl',
|
'--disable-decoder=stl',
|
||||||
'--disable-decoder=subrip',
|
'--disable-decoder=subrip',
|
||||||
'--disable-decoder=subviewer',
|
'--disable-decoder=subviewer',
|
||||||
'--disable-decoder=subviewer1',
|
'--disable-decoder=subviewer1',
|
||||||
|
'--disable-decoder=sunrast',
|
||||||
'--disable-decoder=svq1',
|
'--disable-decoder=svq1',
|
||||||
'--disable-decoder=svq3',
|
'--disable-decoder=svq3',
|
||||||
|
'--disable-decoder=targa',
|
||||||
|
'--disable-decoder=targa_y216',
|
||||||
|
'--disable-decoder=text',
|
||||||
'--disable-decoder=tiff',
|
'--disable-decoder=tiff',
|
||||||
'--disable-decoder=tiertexseqvideo',
|
'--disable-decoder=tiertexseqvideo',
|
||||||
|
'--disable-decoder=tmv',
|
||||||
'--disable-decoder=truemotion1',
|
'--disable-decoder=truemotion1',
|
||||||
'--disable-decoder=truemotion2',
|
'--disable-decoder=truemotion2',
|
||||||
'--disable-decoder=truemotion2rt',
|
'--disable-decoder=truemotion2rt',
|
||||||
|
'--disable-decoder=tscc',
|
||||||
|
'--disable-decoder=tscc2',
|
||||||
'--disable-decoder=twinvq',
|
'--disable-decoder=twinvq',
|
||||||
|
'--disable-decoder=txd',
|
||||||
|
'--disable-decoder=ulti',
|
||||||
'--disable-decoder=utvideo',
|
'--disable-decoder=utvideo',
|
||||||
|
'--disable-decoder=v210',
|
||||||
|
'--disable-decoder=v210x',
|
||||||
|
'--disable-decoder=v308',
|
||||||
|
'--disable-decoder=v408',
|
||||||
|
'--disable-decoder=v410',
|
||||||
|
'--disable-decoder=vb',
|
||||||
|
'--disable-decoder=vble',
|
||||||
|
'--disable-decoder=vbn',
|
||||||
'--disable-decoder=vc1',
|
'--disable-decoder=vc1',
|
||||||
|
'--disable-decoder=vcr1',
|
||||||
'--disable-decoder=vmdvideo',
|
'--disable-decoder=vmdvideo',
|
||||||
|
'--disable-decoder=vmnc',
|
||||||
'--disable-decoder=vp3',
|
'--disable-decoder=vp3',
|
||||||
'--disable-decoder=vp5',
|
'--disable-decoder=vp5',
|
||||||
'--disable-decoder=vp6',
|
'--disable-decoder=vp6',
|
||||||
'--disable-decoder=vp7',
|
'--disable-decoder=vp7',
|
||||||
'--disable-decoder=vp8',
|
'--disable-decoder=vp8',
|
||||||
'--disable-decoder=vp9',
|
'--disable-decoder=vp9',
|
||||||
|
'--disable-decoder=vplayer',
|
||||||
'--disable-decoder=vqa',
|
'--disable-decoder=vqa',
|
||||||
'--disable-decoder=webvtt',
|
'--disable-decoder=webvtt',
|
||||||
|
'--disable-decoder=wcmv',
|
||||||
'--disable-decoder=wmv1',
|
'--disable-decoder=wmv1',
|
||||||
'--disable-decoder=wmv2',
|
'--disable-decoder=wmv2',
|
||||||
'--disable-decoder=wmv3',
|
'--disable-decoder=wmv3',
|
||||||
|
'--disable-decoder=wnv1',
|
||||||
|
'--disable-decoder=wrapped_avframe',
|
||||||
|
'--disable-decoder=xan_wc3',
|
||||||
|
'--disable-decoder=xan_wc4',
|
||||||
|
'--disable-decoder=xbin',
|
||||||
|
'--disable-decoder=xbm',
|
||||||
|
'--disable-decoder=xface',
|
||||||
|
'--disable-decoder=xl',
|
||||||
|
'--disable-decoder=xpm',
|
||||||
|
'--disable-decoder=xsub',
|
||||||
|
'--disable-decoder=xwd',
|
||||||
|
'--disable-decoder=y41p',
|
||||||
|
'--disable-decoder=ylc',
|
||||||
|
'--disable-decoder=yop',
|
||||||
'--disable-decoder=yuv4',
|
'--disable-decoder=yuv4',
|
||||||
|
'--disable-decoder=zero12v',
|
||||||
|
'--disable-decoder=zerocodec',
|
||||||
|
'--disable-decoder=zlib',
|
||||||
|
'--disable-decoder=zmbv',
|
||||||
|
|
||||||
|
'--disable-bsf=av1_frame_merge',
|
||||||
|
'--disable-bsf=av1_frame_split',
|
||||||
|
'--disable-bsf=av1_metadata',
|
||||||
|
'--disable-bsf=dts2pts',
|
||||||
|
'--disable-bsf=h264_metadata',
|
||||||
|
'--disable-bsf=h264_mp4toannexb',
|
||||||
|
'--disable-bsf=h264_redundant_pps',
|
||||||
|
'--disable-bsf=hevc_metadata',
|
||||||
|
'--disable-bsf=hevc_mp4toannexb',
|
||||||
|
'--disable-bsf=mjpeg2jpeg',
|
||||||
|
'--disable-bsf=opus_metadata',
|
||||||
|
'--disable-bsf=pgs_frame_merge',
|
||||||
|
'--disable-bsf=text2movsub',
|
||||||
|
'--disable-bsf=vp9_metadata',
|
||||||
|
'--disable-bsf=vp9_raw_reorder',
|
||||||
|
'--disable-bsf=vp9_superframe',
|
||||||
|
'--disable-bsf=vp9_superframe_split',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
openssl = OpenSSLProject(
|
openssl = OpenSSLProject(
|
||||||
'https://www.openssl.org/source/openssl-3.0.5.tar.gz',
|
'https://www.openssl.org/source/openssl-3.1.0.tar.gz',
|
||||||
'aa7d8d9bef71ad6525c55ba11e5f4397889ce49c2c9349dcea6d3e4f0b024a7a',
|
'aaa925ad9828745c4cad9d9efeb273deca820f2cdcf2c3ac7d7c1212b7c497b4',
|
||||||
'include/openssl/ossl_typ.h',
|
'include/openssl/ossl_typ.h',
|
||||||
)
|
)
|
||||||
|
|
||||||
curl = CmakeProject(
|
curl = CmakeProject(
|
||||||
'https://curl.se/download/curl-7.84.0.tar.xz',
|
'https://curl.se/download/curl-8.0.1.tar.xz',
|
||||||
'2d118b43f547bfe5bae806d8d47b4e596ea5b25a6c1f080aef49fbcd817c5db8',
|
'0a381cd82f4d00a9a334438b8ca239afea5bfefcfa9a1025f2bf118e79e0b5f0',
|
||||||
'lib/libcurl.a',
|
'lib/libcurl.a',
|
||||||
[
|
[
|
||||||
'-DBUILD_CURL_EXE=OFF',
|
'-DBUILD_CURL_EXE=OFF',
|
||||||
'-DBUILD_SHARED_LIBS=OFF',
|
'-DBUILD_SHARED_LIBS=OFF',
|
||||||
'-DCURL_DISABLE_VERBOSE_STRINGS=ON',
|
|
||||||
'-DCURL_DISABLE_LDAP=ON',
|
'-DCURL_DISABLE_LDAP=ON',
|
||||||
'-DCURL_DISABLE_TELNET=ON',
|
'-DCURL_DISABLE_TELNET=ON',
|
||||||
'-DCURL_DISABLE_DICT=ON',
|
'-DCURL_DISABLE_DICT=ON',
|
||||||
@@ -422,8 +638,8 @@ curl = CmakeProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
libnfs = AutotoolsProject(
|
libnfs = AutotoolsProject(
|
||||||
'https://github.com/sahlberg/libnfs/archive/libnfs-5.0.1.tar.gz',
|
'https://github.com/sahlberg/libnfs/archive/libnfs-5.0.2.tar.gz',
|
||||||
'7ef445410b42f36b9bad426608b53ccb9ccca4101e545c383f564c11db672ca8',
|
'637e56643b19da9fba98f06847788c4dad308b723156a64748041035dcdf9bd3',
|
||||||
'lib/libnfs.a',
|
'lib/libnfs.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
@@ -434,7 +650,7 @@ libnfs = AutotoolsProject(
|
|||||||
|
|
||||||
'--disable-utils', '--disable-examples',
|
'--disable-utils', '--disable-examples',
|
||||||
],
|
],
|
||||||
base='libnfs-libnfs-5.0.1',
|
base='libnfs-libnfs-5.0.2',
|
||||||
autoreconf=True,
|
autoreconf=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -445,7 +661,7 @@ jack = JackProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
boost = BoostProject(
|
boost = BoostProject(
|
||||||
'https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2',
|
'https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.bz2',
|
||||||
'475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39',
|
'71feeed900fbccca04a3b4f2f84a7c217186f28a940ed8b7ed4725986baf99fa',
|
||||||
'include/boost/version.hpp',
|
'include/boost/version.hpp',
|
||||||
)
|
)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import subprocess
|
import subprocess, multiprocessing
|
||||||
|
|
||||||
from build.project import Project
|
from build.project import Project
|
||||||
|
|
||||||
@@ -10,7 +10,12 @@ class MakeProject(Project):
|
|||||||
self.install_target = install_target
|
self.install_target = install_target
|
||||||
|
|
||||||
def get_simultaneous_jobs(self):
|
def get_simultaneous_jobs(self):
|
||||||
return 12
|
try:
|
||||||
|
# use twice as many simultaneous jobs as we have CPU cores
|
||||||
|
return multiprocessing.cpu_count() * 2
|
||||||
|
except NotImplementedError:
|
||||||
|
# default to 12, if multiprocessing.cpu_count() is not implemented
|
||||||
|
return 12
|
||||||
|
|
||||||
def get_make_args(self, toolchain):
|
def get_make_args(self, toolchain):
|
||||||
return ['--quiet', '-j' + str(self.get_simultaneous_jobs())]
|
return ['--quiet', '-j' + str(self.get_simultaneous_jobs())]
|
||||||
@@ -19,7 +24,7 @@ class MakeProject(Project):
|
|||||||
return ['--quiet', self.install_target]
|
return ['--quiet', self.install_target]
|
||||||
|
|
||||||
def make(self, toolchain, wd, args):
|
def make(self, toolchain, wd, args):
|
||||||
subprocess.check_call(['/usr/bin/make'] + args,
|
subprocess.check_call(['make'] + args,
|
||||||
cwd=wd, env=toolchain.env)
|
cwd=wd, env=toolchain.env)
|
||||||
|
|
||||||
def build_make(self, toolchain, wd, install=True):
|
def build_make(self, toolchain, wd, install=True):
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import os.path, subprocess, sys
|
import os
|
||||||
|
import subprocess
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
from build.project import Project
|
from build.project import Project
|
||||||
@@ -82,8 +83,8 @@ endian = '{endian}'
|
|||||||
def configure(toolchain, src, build, args=()):
|
def configure(toolchain, src, build, args=()):
|
||||||
cross_file = make_cross_file(toolchain)
|
cross_file = make_cross_file(toolchain)
|
||||||
configure = [
|
configure = [
|
||||||
'meson',
|
'meson', 'setup',
|
||||||
src, build,
|
build, src,
|
||||||
|
|
||||||
'--prefix', toolchain.install_prefix,
|
'--prefix', toolchain.install_prefix,
|
||||||
|
|
||||||
@@ -115,5 +116,5 @@ class MesonProject(Project):
|
|||||||
|
|
||||||
def _build(self, toolchain):
|
def _build(self, toolchain):
|
||||||
build = self.configure(toolchain)
|
build = self.configure(toolchain)
|
||||||
subprocess.check_call(['ninja', 'install'],
|
subprocess.check_call(['ninja', '-v', 'install'],
|
||||||
cwd=build, env=toolchain.env)
|
cwd=build, env=toolchain.env)
|
||||||
|
@@ -14,13 +14,14 @@ class Project:
|
|||||||
if base is None:
|
if base is None:
|
||||||
basename = os.path.basename(url)
|
basename = os.path.basename(url)
|
||||||
m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename)
|
m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename)
|
||||||
if not m: raise
|
if not m: raise RuntimeError('Could not identify tarball name: ' + basename)
|
||||||
self.base = m.group(1)
|
self.base = m.group(1)
|
||||||
else:
|
else:
|
||||||
self.base = base
|
self.base = base
|
||||||
|
|
||||||
if name is None or version is None:
|
if name is None or version is None:
|
||||||
m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*(?:-(?:alpha|beta)\d+)?)(\+.*)?$', self.base)
|
m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*(?:-(?:alpha|beta)\d+)?)(\+.*)?$', self.base)
|
||||||
|
if not m: raise RuntimeError('Could not identify tarball name: ' + self.base)
|
||||||
if name is None: name = m.group(1)
|
if name is None: name = m.group(1)
|
||||||
if version is None: version = m.group(2)
|
if version is None: version = m.group(2)
|
||||||
|
|
||||||
@@ -55,8 +56,8 @@ class Project:
|
|||||||
parent_path = toolchain.src_path
|
parent_path = toolchain.src_path
|
||||||
else:
|
else:
|
||||||
parent_path = toolchain.build_path
|
parent_path = toolchain.build_path
|
||||||
path = untar(self.download(toolchain), parent_path, self.base)
|
path = untar(self.download(toolchain), parent_path, self.base,
|
||||||
|
lazy=out_of_tree and self.patches is None)
|
||||||
if self.patches is not None:
|
if self.patches is not None:
|
||||||
push_all(toolchain, path, self.patches)
|
push_all(toolchain, path, self.patches)
|
||||||
|
|
||||||
@@ -71,8 +72,10 @@ class Project:
|
|||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def make_build_path(self, toolchain):
|
def make_build_path(self, toolchain, lazy=False):
|
||||||
path = os.path.join(toolchain.build_path, self.base)
|
path = os.path.join(toolchain.build_path, self.base)
|
||||||
|
if lazy and os.path.isdir(path):
|
||||||
|
return path
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
import os, shutil, subprocess
|
import os, shutil, subprocess
|
||||||
|
|
||||||
def untar(tarball_path, parent_path, base):
|
def untar(tarball_path, parent_path, base, lazy=False):
|
||||||
path = os.path.join(parent_path, base)
|
path = os.path.join(parent_path, base)
|
||||||
|
if lazy and os.path.isdir(path):
|
||||||
|
return path
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
os.makedirs(parent_path, exist_ok=True)
|
os.makedirs(parent_path, exist_ok=True)
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(['/bin/tar', 'xfC', tarball_path, parent_path])
|
subprocess.check_call(['tar', 'xfC', tarball_path, parent_path])
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
import tarfile
|
import tarfile
|
||||||
tar = tarfile.open(tarball_path)
|
tar = tarfile.open(tarball_path)
|
||||||
|
@@ -1,22 +1,32 @@
|
|||||||
import os.path, subprocess
|
import subprocess
|
||||||
|
|
||||||
from build.project import Project
|
from build.makeproject import MakeProject
|
||||||
|
|
||||||
class ZlibProject(Project):
|
class ZlibProject(MakeProject):
|
||||||
def __init__(self, url, md5, installed,
|
def __init__(self, url, md5, installed,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
Project.__init__(self, url, md5, installed, **kwargs)
|
MakeProject.__init__(self, url, md5, installed, **kwargs)
|
||||||
|
|
||||||
|
def get_make_args(self, toolchain):
|
||||||
|
return MakeProject.get_make_args(self, toolchain) + [
|
||||||
|
'CC=' + toolchain.cc + ' ' + toolchain.cppflags + ' ' + toolchain.cflags,
|
||||||
|
'CPP=' + toolchain.cc + ' -E ' + toolchain.cppflags,
|
||||||
|
'AR=' + toolchain.ar,
|
||||||
|
'ARFLAGS=' + toolchain.arflags,
|
||||||
|
'RANLIB=' + toolchain.ranlib,
|
||||||
|
'LDSHARED=' + toolchain.cc + ' -shared',
|
||||||
|
'libz.a'
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_make_install_args(self, toolchain):
|
||||||
|
return [
|
||||||
|
'RANLIB=' + toolchain.ranlib,
|
||||||
|
self.install_target
|
||||||
|
]
|
||||||
|
|
||||||
def _build(self, toolchain):
|
def _build(self, toolchain):
|
||||||
src = self.unpack(toolchain, out_of_tree=False)
|
src = self.unpack(toolchain, out_of_tree=False)
|
||||||
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet',
|
subprocess.check_call(['./configure', '--prefix=' + toolchain.install_prefix, '--static'],
|
||||||
'-f', 'win32/Makefile.gcc',
|
cwd=src, env=toolchain.env)
|
||||||
'PREFIX=' + toolchain.arch + '-',
|
self.build_make(toolchain, src)
|
||||||
'-j12',
|
|
||||||
'install',
|
|
||||||
'INCLUDE_PATH='+ os.path.join(toolchain.install_prefix, 'include'),
|
|
||||||
'LIBRARY_PATH=' + os.path.join(toolchain.install_prefix, 'lib'),
|
|
||||||
'BINARY_PATH=' + os.path.join(toolchain.install_prefix, 'bin'),
|
|
||||||
],
|
|
||||||
cwd=src, env=toolchain.env)
|
|
||||||
|
@@ -352,12 +352,16 @@ ParseCommandLine(int argc, char **argv, CommandLineOptions &options,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OPTION_NO_DAEMON:
|
case OPTION_NO_DAEMON:
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
options.daemon = false;
|
options.daemon = false;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
case OPTION_SYSTEMD:
|
case OPTION_SYSTEMD:
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
options.daemon = false;
|
options.daemon = false;
|
||||||
|
#endif
|
||||||
options.systemd = true;
|
options.systemd = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,11 +20,18 @@
|
|||||||
#ifndef MPD_COMMAND_LINE_HXX
|
#ifndef MPD_COMMAND_LINE_HXX
|
||||||
#define MPD_COMMAND_LINE_HXX
|
#define MPD_COMMAND_LINE_HXX
|
||||||
|
|
||||||
|
#include "config.h" // for ENABLE_DAEMON
|
||||||
|
|
||||||
struct ConfigData;
|
struct ConfigData;
|
||||||
|
|
||||||
struct CommandLineOptions {
|
struct CommandLineOptions {
|
||||||
bool kill = false;
|
bool kill = false;
|
||||||
|
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
bool daemon = true;
|
bool daemon = true;
|
||||||
|
#else
|
||||||
|
static constexpr bool daemon = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
bool systemd = false;
|
bool systemd = false;
|
||||||
|
@@ -158,12 +158,15 @@ log_init(const ConfigData &config, bool verbose, bool use_stdout)
|
|||||||
getenv("NOTIFY_SOCKET") != nullptr) {
|
getenv("NOTIFY_SOCKET") != nullptr) {
|
||||||
/* if MPD was started as a systemd
|
/* if MPD was started as a systemd
|
||||||
service, default to journal (which
|
service, default to journal (which
|
||||||
is connected to fd=2) */
|
is connected to stdout&stderr) */
|
||||||
out_fd = STDOUT_FILENO;
|
out_fd = STDOUT_FILENO;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef HAVE_SYSLOG
|
#ifdef _WIN32
|
||||||
|
/* default to stdout on Windows */
|
||||||
|
out_fd = STDOUT_FILENO;
|
||||||
|
#elif !defined(HAVE_SYSLOG)
|
||||||
throw std::runtime_error("config parameter 'log_file' not found");
|
throw std::runtime_error("config parameter 'log_file' not found");
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
|
@@ -482,7 +482,10 @@ MainConfigured(const CommandLineOptions &options,
|
|||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
setup_log_output();
|
setup_log_output();
|
||||||
|
|
||||||
const ScopeSignalHandlersInit signal_handlers_init(instance);
|
const ScopeSignalHandlersInit signal_handlers_init{
|
||||||
|
instance,
|
||||||
|
options.daemon,
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instance.io_thread.Start();
|
instance.io_thread.Start();
|
||||||
|
@@ -81,6 +81,9 @@ spl_valid_name(const char *name_utf8)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
return std::strchr(name_utf8, '/') == nullptr &&
|
return std::strchr(name_utf8, '/') == nullptr &&
|
||||||
|
#ifdef _WIN32
|
||||||
|
std::strchr(name_utf8, '\\') == nullptr &&
|
||||||
|
#endif
|
||||||
std::strchr(name_utf8, '\n') == nullptr &&
|
std::strchr(name_utf8, '\n') == nullptr &&
|
||||||
std::strchr(name_utf8, '\r') == nullptr;
|
std::strchr(name_utf8, '\r') == nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,11 @@
|
|||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
#include <boost/intrusive/unordered_set.hpp>
|
#include <boost/intrusive/unordered_set.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
class RemoteTagCacheHandler;
|
class RemoteTagCacheHandler;
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "TagPrint.hxx"
|
#include "TagPrint.hxx"
|
||||||
#include "client/Response.hxx"
|
#include "client/Response.hxx"
|
||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
|
#include "lib/fmt/AudioFormatFormatter.hxx"
|
||||||
#include "time/ChronoUtil.hxx"
|
#include "time/ChronoUtil.hxx"
|
||||||
#include "util/StringBuffer.hxx"
|
#include "util/StringBuffer.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
@@ -93,7 +94,7 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept
|
|||||||
time_print(r, "Last-Modified", song.mtime);
|
time_print(r, "Last-Modified", song.mtime);
|
||||||
|
|
||||||
if (song.audio_format.IsDefined())
|
if (song.audio_format.IsDefined())
|
||||||
r.Fmt(FMT_STRING("Format: {}\n"), ToString(song.audio_format));
|
r.Fmt(FMT_STRING("Format: {}\n"), song.audio_format);
|
||||||
|
|
||||||
tag_print_values(r, song.tag);
|
tag_print_values(r, song.tag);
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept
|
|||||||
time_print(r, "Last-Modified", song.GetLastModified());
|
time_print(r, "Last-Modified", song.GetLastModified());
|
||||||
|
|
||||||
if (const auto &f = song.GetAudioFormat(); f.IsDefined())
|
if (const auto &f = song.GetAudioFormat(); f.IsDefined())
|
||||||
r.Fmt(FMT_STRING("Format: {}\n"), ToString(f));
|
r.Fmt(FMT_STRING("Format: {}\n"), f);
|
||||||
|
|
||||||
tag_print_values(r, song.GetTag());
|
tag_print_values(r, song.GetTag());
|
||||||
|
|
||||||
|
@@ -63,6 +63,9 @@ song_save(BufferedOutputStream &os, const Song &song)
|
|||||||
if (song.audio_format.IsDefined())
|
if (song.audio_format.IsDefined())
|
||||||
os.Format("Format: %s\n", ToString(song.audio_format).c_str());
|
os.Format("Format: %s\n", ToString(song.audio_format).c_str());
|
||||||
|
|
||||||
|
if (song.in_playlist)
|
||||||
|
os.Write("InPlaylist: yes\n");
|
||||||
|
|
||||||
if (!IsNegative(song.mtime))
|
if (!IsNegative(song.mtime))
|
||||||
os.Format(SONG_MTIME ": %li\n",
|
os.Format(SONG_MTIME ": %li\n",
|
||||||
(long)std::chrono::system_clock::to_time_t(song.mtime));
|
(long)std::chrono::system_clock::to_time_t(song.mtime));
|
||||||
@@ -86,7 +89,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
|||||||
|
|
||||||
DetachedSong
|
DetachedSong
|
||||||
song_load(LineReader &file, const char *uri,
|
song_load(LineReader &file, const char *uri,
|
||||||
std::string *target_r)
|
std::string *target_r, bool *in_playlist_r)
|
||||||
{
|
{
|
||||||
DetachedSong song(uri);
|
DetachedSong song(uri);
|
||||||
|
|
||||||
@@ -132,6 +135,9 @@ song_load(LineReader &file, const char *uri,
|
|||||||
|
|
||||||
song.SetStartTime(SongTime::FromMS(start_ms));
|
song.SetStartTime(SongTime::FromMS(start_ms));
|
||||||
song.SetEndTime(SongTime::FromMS(end_ms));
|
song.SetEndTime(SongTime::FromMS(end_ms));
|
||||||
|
} else if (StringIsEqual(line, "InPlaylist")) {
|
||||||
|
if (in_playlist_r != nullptr)
|
||||||
|
*in_playlist_r = StringIsEqual(value, "yes");
|
||||||
} else {
|
} else {
|
||||||
throw FormatRuntimeError("unknown line in db: %s", line);
|
throw FormatRuntimeError("unknown line in db: %s", line);
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,6 @@ song_save(BufferedOutputStream &os, const DetachedSong &song);
|
|||||||
*/
|
*/
|
||||||
DetachedSong
|
DetachedSong
|
||||||
song_load(LineReader &file, const char *uri,
|
song_load(LineReader &file, const char *uri,
|
||||||
std::string *target_r=nullptr);
|
std::string *target_r=nullptr, bool *in_playlist_r=nullptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -32,7 +32,7 @@ StateFileConfig::StateFileConfig(const ConfigData &config)
|
|||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
if (path.IsNull()) {
|
if (path.IsNull()) {
|
||||||
const auto cache_dir = GetUserCacheDir();
|
const auto cache_dir = GetAppCacheDir();
|
||||||
if (cache_dir.IsNull())
|
if (cache_dir.IsNull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -35,8 +35,9 @@ tag_print_types(Response &r) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tag_print(Response &r, TagType type, StringView value) noexcept
|
tag_print(Response &r, TagType type, StringView _value) noexcept
|
||||||
{
|
{
|
||||||
|
const std::string_view value{_value};
|
||||||
r.Fmt(FMT_STRING("{}: {}\n"), tag_item_names[type], value);
|
r.Fmt(FMT_STRING("{}: {}\n"), tag_item_names[type], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,5 +36,5 @@ time_print(Response &r, const char *name,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Fmt(FMT_STRING("{}: {}\n"), name, s);
|
r.Fmt(FMT_STRING("{}: {}\n"), name, s.c_str());
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ Context::Initialise(JNIEnv *env) noexcept
|
|||||||
AllocatedPath
|
AllocatedPath
|
||||||
Context::GetExternalFilesDir(JNIEnv *env, const char *type) noexcept
|
Context::GetExternalFilesDir(JNIEnv *env, const char *type) noexcept
|
||||||
{
|
{
|
||||||
assert(_type != nullptr);
|
assert(type != nullptr);
|
||||||
|
|
||||||
jobject file = env->CallObjectMethod(Get(), getExternalFilesDir_method,
|
jobject file = env->CallObjectMethod(Get(), getExternalFilesDir_method,
|
||||||
Java::String::Optional(env, type).Get());
|
Java::String::Optional(env, type).Get());
|
||||||
|
@@ -166,7 +166,7 @@ class Iso9660InputStream final : public InputStream {
|
|||||||
assert(fill <= data.size());
|
assert(fill <= data.size());
|
||||||
assert(position <= fill);
|
assert(position <= fill);
|
||||||
|
|
||||||
return {&data[position], &data[fill]};
|
return {data.data() + position, data.data() + fill};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Consume(size_t nbytes) noexcept {
|
void Consume(size_t nbytes) noexcept {
|
||||||
|
@@ -22,6 +22,10 @@ if libzzip_dep.found()
|
|||||||
found_archive_plugin = true
|
found_archive_plugin = true
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if not found_archive_plugin
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
archive_plugins = static_library(
|
archive_plugins = static_library(
|
||||||
'archive_plugins',
|
'archive_plugins',
|
||||||
archive_plugins_sources,
|
archive_plugins_sources,
|
||||||
|
@@ -41,6 +41,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <limits.h> // for UINT_MAX
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listfiles_db(Client &client, Response &r, const char *uri)
|
handle_listfiles_db(Client &client, Response &r, const char *uri)
|
||||||
{
|
{
|
||||||
|
@@ -100,10 +100,6 @@ handle_listfiles_local(Response &r, Path path_fs)
|
|||||||
return CommandResult::OK;
|
return CommandResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
IsValidName(const StringView s) noexcept
|
IsValidName(const StringView s) noexcept
|
||||||
@@ -130,7 +126,8 @@ public:
|
|||||||
explicit PrintCommentHandler(Response &_response) noexcept
|
explicit PrintCommentHandler(Response &_response) noexcept
|
||||||
:NullTagHandler(WANT_PAIR), response(_response) {}
|
:NullTagHandler(WANT_PAIR), response(_response) {}
|
||||||
|
|
||||||
void OnPair(StringView key, StringView value) noexcept override {
|
void OnPair(StringView _key, StringView _value) noexcept override {
|
||||||
|
const std::string_view key{_key}, value{_value};
|
||||||
if (IsValidName(key) && IsValidValue(value))
|
if (IsValidName(key) && IsValidValue(value))
|
||||||
response.Fmt(FMT_STRING("{}: {}\n"), key, value);
|
response.Fmt(FMT_STRING("{}: {}\n"), key, value);
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
#include "Instance.hxx"
|
#include "Instance.hxx"
|
||||||
#include "IdleFlags.hxx"
|
#include "IdleFlags.hxx"
|
||||||
|
#include "lib/fmt/AudioFormatFormatter.hxx"
|
||||||
#include "util/StringBuffer.hxx"
|
#include "util/StringBuffer.hxx"
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
#include "util/Exception.hxx"
|
#include "util/Exception.hxx"
|
||||||
@@ -185,7 +186,7 @@ handle_status(Client &client, [[maybe_unused]] Request args, Response &r)
|
|||||||
|
|
||||||
if (player_status.audio_format.IsDefined())
|
if (player_status.audio_format.IsDefined())
|
||||||
r.Fmt(FMT_STRING(COMMAND_STATUS_AUDIO ": {}\n"),
|
r.Fmt(FMT_STRING(COMMAND_STATUS_AUDIO ": {}\n"),
|
||||||
ToString(player_status.audio_format));
|
player_status.audio_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
@@ -83,10 +83,6 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && GCC_CHECK_VERSION(4,6)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listfiles_storage(Response &r, Storage &storage, const char *uri)
|
handle_listfiles_storage(Response &r, Storage &storage, const char *uri)
|
||||||
{
|
{
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "config/Param.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/Block.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
|
#include "fs/FileSystem.hxx"
|
||||||
#include "fs/StandardDirectory.hxx"
|
#include "fs/StandardDirectory.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
|
||||||
@@ -51,17 +52,30 @@ CreateConfiguredDatabase(const ConfigData &config,
|
|||||||
} else {
|
} else {
|
||||||
/* if there is no override, use the cache directory */
|
/* if there is no override, use the cache directory */
|
||||||
|
|
||||||
const AllocatedPath cache_dir = GetUserCacheDir();
|
const AllocatedPath cache_dir = GetAppCacheDir();
|
||||||
if (cache_dir.IsNull())
|
if (cache_dir.IsNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto db_file = cache_dir / Path::FromFS(PATH_LITERAL("mpd.db"));
|
const auto db_file = cache_dir / Path::FromFS(PATH_LITERAL("db"));
|
||||||
auto db_file_utf8 = db_file.ToUTF8();
|
auto db_file_utf8 = db_file.ToUTF8();
|
||||||
if (db_file_utf8.empty())
|
if (db_file_utf8.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
ConfigBlock block;
|
ConfigBlock block;
|
||||||
block.AddBlockParam("path", std::move(db_file_utf8), -1);
|
block.AddBlockParam("path", std::move(db_file_utf8), -1);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto mounts_dir = cache_dir
|
||||||
|
/ Path::FromFS(PATH_LITERAL("mounts"));
|
||||||
|
CreateDirectoryNoThrow(mounts_dir);
|
||||||
|
|
||||||
|
if (auto mounts_dir_utf8 = mounts_dir.ToUTF8();
|
||||||
|
!mounts_dir_utf8.empty())
|
||||||
|
block.AddBlockParam("cache_directory",
|
||||||
|
std::move(mounts_dir_utf8),
|
||||||
|
-1);
|
||||||
|
}
|
||||||
|
|
||||||
return DatabaseGlobalInit(main_event_loop, io_event_loop,
|
return DatabaseGlobalInit(main_event_loop, io_event_loop,
|
||||||
listener, block);
|
listener, block);
|
||||||
}
|
}
|
||||||
|
@@ -126,6 +126,18 @@ Directory::LookupTargetSong(std::string_view _target) noexcept
|
|||||||
return lr.directory->FindSong(lr.rest);
|
return lr.directory->FindSong(lr.rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Directory::ClearInPlaylist() noexcept
|
||||||
|
{
|
||||||
|
assert(holding_db_lock());
|
||||||
|
|
||||||
|
for (auto &child : children)
|
||||||
|
child.ClearInPlaylist();
|
||||||
|
|
||||||
|
for (auto &song : songs)
|
||||||
|
song.in_playlist = false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::PruneEmpty() noexcept
|
Directory::PruneEmpty() noexcept
|
||||||
{
|
{
|
||||||
|
@@ -287,6 +287,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
SongPtr RemoveSong(Song *song) noexcept;
|
SongPtr RemoveSong(Song *song) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively walk through the whole tree and set all
|
||||||
|
* `Song::in_playlist` fields to `false`.
|
||||||
|
*
|
||||||
|
* Caller must lock the #db_mutex.
|
||||||
|
*/
|
||||||
|
void ClearInPlaylist() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
|
@@ -168,12 +168,14 @@ directory_load(LineReader &file, Directory &directory)
|
|||||||
throw FormatRuntimeError("Duplicate song '%s'", name);
|
throw FormatRuntimeError("Duplicate song '%s'", name);
|
||||||
|
|
||||||
std::string target;
|
std::string target;
|
||||||
|
bool in_playlist = false;
|
||||||
auto detached_song = song_load(file, name,
|
auto detached_song = song_load(file, name,
|
||||||
&target);
|
&target, &in_playlist);
|
||||||
|
|
||||||
auto song = std::make_unique<Song>(std::move(detached_song),
|
auto song = std::make_unique<Song>(std::move(detached_song),
|
||||||
directory);
|
directory);
|
||||||
song->target = std::move(target);
|
song->target = std::move(target);
|
||||||
|
song->in_playlist = in_playlist;
|
||||||
|
|
||||||
directory.AddSong(std::move(song));
|
directory.AddSong(std::move(song));
|
||||||
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
||||||
|
@@ -51,6 +51,15 @@ LockFindSong(Directory &directory, std::string_view name) noexcept
|
|||||||
return directory.FindSong(name);
|
return directory.FindSong(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
|
static bool
|
||||||
|
IsAcceptableFilename(std::string_view name) noexcept
|
||||||
|
{
|
||||||
|
return !name.empty() &&
|
||||||
|
/* newlines cannot be represented in MPD's protocol */
|
||||||
|
name.find('\n') == name.npos;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UpdateWalk::UpdateArchiveTree(ArchiveFile &archive, Directory &directory,
|
UpdateWalk::UpdateArchiveTree(ArchiveFile &archive, Directory &directory,
|
||||||
const char *name) noexcept
|
const char *name) noexcept
|
||||||
@@ -58,6 +67,9 @@ UpdateWalk::UpdateArchiveTree(ArchiveFile &archive, Directory &directory,
|
|||||||
const char *tmp = std::strchr(name, '/');
|
const char *tmp = std::strchr(name, '/');
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
const std::string_view child_name(name, tmp - name);
|
const std::string_view child_name(name, tmp - name);
|
||||||
|
if (!IsAcceptableFilename(child_name))
|
||||||
|
return;
|
||||||
|
|
||||||
//add dir is not there already
|
//add dir is not there already
|
||||||
Directory *subdir = LockMakeChild(directory, child_name);
|
Directory *subdir = LockMakeChild(directory, child_name);
|
||||||
subdir->device = DEVICE_INARCHIVE;
|
subdir->device = DEVICE_INARCHIVE;
|
||||||
@@ -65,11 +77,8 @@ UpdateWalk::UpdateArchiveTree(ArchiveFile &archive, Directory &directory,
|
|||||||
//create directories first
|
//create directories first
|
||||||
UpdateArchiveTree(archive, *subdir, tmp + 1);
|
UpdateArchiveTree(archive, *subdir, tmp + 1);
|
||||||
} else {
|
} else {
|
||||||
if (StringIsEmpty(name)) {
|
if (!IsAcceptableFilename(name))
|
||||||
LogWarning(update_domain,
|
|
||||||
"archive returned directory only");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
//add file
|
//add file
|
||||||
Song *song = LockFindSong(directory, name);
|
Song *song = LockFindSong(directory, name);
|
||||||
|
@@ -531,6 +531,7 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) noexcept
|
|||||||
|
|
||||||
{
|
{
|
||||||
const ScopeDatabaseLock protect;
|
const ScopeDatabaseLock protect;
|
||||||
|
root.ClearInPlaylist();
|
||||||
PurgeDanglingFromPlaylists(root);
|
PurgeDanglingFromPlaylists(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -114,11 +114,11 @@ constexpr const struct DecoderPlugin *decoder_plugins[] = {
|
|||||||
#ifdef ENABLE_ADPLUG
|
#ifdef ENABLE_ADPLUG
|
||||||
&adplug_decoder_plugin,
|
&adplug_decoder_plugin,
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_FFMPEG
|
|
||||||
&ffmpeg_decoder_plugin,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_GME
|
#ifdef ENABLE_GME
|
||||||
&gme_decoder_plugin,
|
&gme_decoder_plugin,
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FFMPEG
|
||||||
|
&ffmpeg_decoder_plugin,
|
||||||
#endif
|
#endif
|
||||||
&pcm_decoder_plugin,
|
&pcm_decoder_plugin,
|
||||||
nullptr
|
nullptr
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "lib/ffmpeg/Format.hxx"
|
#include "lib/ffmpeg/Format.hxx"
|
||||||
#include "lib/ffmpeg/Codec.hxx"
|
#include "lib/ffmpeg/Codec.hxx"
|
||||||
#include "lib/ffmpeg/SampleFormat.hxx"
|
#include "lib/ffmpeg/SampleFormat.hxx"
|
||||||
|
#include "lib/ffmpeg/LibFmt.hxx"
|
||||||
#include "../DecoderAPI.hxx"
|
#include "../DecoderAPI.hxx"
|
||||||
#include "FfmpegMetaData.hxx"
|
#include "FfmpegMetaData.hxx"
|
||||||
#include "FfmpegIo.hxx"
|
#include "FfmpegIo.hxx"
|
||||||
|
@@ -56,20 +56,17 @@ struct GmeContainerPath {
|
|||||||
unsigned track;
|
unsigned track;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GME_VERSION >= 0x000600
|
|
||||||
static int gme_accuracy;
|
static int gme_accuracy;
|
||||||
#endif
|
|
||||||
static unsigned gme_default_fade;
|
static unsigned gme_default_fade;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
gme_plugin_init([[maybe_unused]] const ConfigBlock &block)
|
gme_plugin_init([[maybe_unused]] const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
#if GME_VERSION >= 0x000600
|
|
||||||
auto accuracy = block.GetBlockParam("accuracy");
|
auto accuracy = block.GetBlockParam("accuracy");
|
||||||
gme_accuracy = accuracy != nullptr
|
gme_accuracy = accuracy != nullptr
|
||||||
? (int)accuracy->GetBoolValue()
|
? (int)accuracy->GetBoolValue()
|
||||||
: -1;
|
: -1;
|
||||||
#endif
|
|
||||||
auto fade = block.GetBlockParam("default_fade");
|
auto fade = block.GetBlockParam("default_fade");
|
||||||
gme_default_fade = fade != nullptr
|
gme_default_fade = fade != nullptr
|
||||||
? fade->GetUnsignedValue() * 1000
|
? fade->GetUnsignedValue() * 1000
|
||||||
@@ -163,10 +160,8 @@ gme_file_decode(DecoderClient &client, Path path_fs)
|
|||||||
FmtDebug(gme_domain, "emulator type '{}'",
|
FmtDebug(gme_domain, "emulator type '{}'",
|
||||||
gme_type_system(gme_type(emu)));
|
gme_type_system(gme_type(emu)));
|
||||||
|
|
||||||
#if GME_VERSION >= 0x000600
|
|
||||||
if (gme_accuracy >= 0)
|
if (gme_accuracy >= 0)
|
||||||
gme_enable_accuracy(emu, gme_accuracy);
|
gme_enable_accuracy(emu, gme_accuracy);
|
||||||
#endif
|
|
||||||
|
|
||||||
gme_info_t *ti;
|
gme_info_t *ti;
|
||||||
const char *gme_err = gme_track_info(emu, &ti, container.track);
|
const char *gme_err = gme_track_info(emu, &ti, container.track);
|
||||||
|
@@ -798,6 +798,8 @@ MadDecoder::UpdateTimerNextFrame() noexcept
|
|||||||
DecoderCommand
|
DecoderCommand
|
||||||
MadDecoder::SubmitPCM(size_t i, size_t pcm_length) noexcept
|
MadDecoder::SubmitPCM(size_t i, size_t pcm_length) noexcept
|
||||||
{
|
{
|
||||||
|
assert(i <= pcm_length);
|
||||||
|
|
||||||
size_t num_samples = pcm_length - i;
|
size_t num_samples = pcm_length - i;
|
||||||
|
|
||||||
mad_fixed_to_24_buffer(output_buffer, synth.pcm,
|
mad_fixed_to_24_buffer(output_buffer, synth.pcm,
|
||||||
@@ -843,7 +845,7 @@ MadDecoder::SynthAndSubmit() noexcept
|
|||||||
size_t pcm_length = synth.pcm.length;
|
size_t pcm_length = synth.pcm.length;
|
||||||
if (drop_end_samples &&
|
if (drop_end_samples &&
|
||||||
current_frame == max_frames - drop_end_frames - 1) {
|
current_frame == max_frames - drop_end_frames - 1) {
|
||||||
if (drop_end_samples >= pcm_length)
|
if (i + drop_end_samples >= pcm_length)
|
||||||
return DecoderCommand::STOP;
|
return DecoderCommand::STOP;
|
||||||
|
|
||||||
pcm_length -= drop_end_samples;
|
pcm_length -= drop_end_samples;
|
||||||
|
@@ -81,7 +81,7 @@ if libfaad_dep.found()
|
|||||||
decoder_plugins_sources += 'FaadDecoderPlugin.cxx'
|
decoder_plugins_sources += 'FaadDecoderPlugin.cxx'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libgme_dep = c_compiler.find_library('gme', required: get_option('gme'))
|
libgme_dep = dependency('libgme', version: '>= 0.6', required: get_option('gme'))
|
||||||
decoder_features.set('ENABLE_GME', libgme_dep.found())
|
decoder_features.set('ENABLE_GME', libgme_dep.found())
|
||||||
if libgme_dep.found()
|
if libgme_dep.found()
|
||||||
decoder_plugins_sources += 'GmeDecoderPlugin.cxx'
|
decoder_plugins_sources += 'GmeDecoderPlugin.cxx'
|
||||||
|
@@ -38,6 +38,7 @@ class FlacEncoder final : public Encoder {
|
|||||||
|
|
||||||
FLAC__StreamEncoder *const fse;
|
FLAC__StreamEncoder *const fse;
|
||||||
const unsigned compression;
|
const unsigned compression;
|
||||||
|
const bool oggflac;
|
||||||
|
|
||||||
PcmBuffer expand_buffer;
|
PcmBuffer expand_buffer;
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ flac_encoder_init(const ConfigBlock &block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
flac_encoder_setup(FLAC__StreamEncoder *fse, unsigned compression,
|
flac_encoder_setup(FLAC__StreamEncoder *fse, unsigned compression, bool oggflac,
|
||||||
const AudioFormat &audio_format)
|
const AudioFormat &audio_format)
|
||||||
{
|
{
|
||||||
unsigned bits_per_sample;
|
unsigned bits_per_sample;
|
||||||
@@ -157,7 +158,7 @@ flac_encoder_setup(FLAC__StreamEncoder *fse, unsigned compression,
|
|||||||
throw FormatRuntimeError("error setting flac sample rate to %d",
|
throw FormatRuntimeError("error setting flac sample rate to %d",
|
||||||
audio_format.sample_rate);
|
audio_format.sample_rate);
|
||||||
|
|
||||||
if (!FLAC__stream_encoder_set_ogg_serial_number(fse,
|
if (oggflac && !FLAC__stream_encoder_set_ogg_serial_number(fse,
|
||||||
GenerateSerial()))
|
GenerateSerial()))
|
||||||
throw FormatRuntimeError("error setting ogg serial number");
|
throw FormatRuntimeError("error setting ogg serial number");
|
||||||
}
|
}
|
||||||
@@ -166,11 +167,12 @@ FlacEncoder::FlacEncoder(AudioFormat _audio_format, FLAC__StreamEncoder *_fse, u
|
|||||||
:Encoder(_oggchaining),
|
:Encoder(_oggchaining),
|
||||||
audio_format(_audio_format), fse(_fse),
|
audio_format(_audio_format), fse(_fse),
|
||||||
compression(_compression),
|
compression(_compression),
|
||||||
|
oggflac(_oggflac),
|
||||||
output_buffer(8192)
|
output_buffer(8192)
|
||||||
{
|
{
|
||||||
/* this immediately outputs data through callback */
|
/* this immediately outputs data through callback */
|
||||||
|
|
||||||
auto init_status = _oggflac ?
|
auto init_status = oggflac ?
|
||||||
FLAC__stream_encoder_init_ogg_stream(fse,
|
FLAC__stream_encoder_init_ogg_stream(fse,
|
||||||
nullptr, WriteCallback,
|
nullptr, WriteCallback,
|
||||||
nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr,
|
||||||
@@ -209,7 +211,7 @@ PreparedFlacEncoder::Open(AudioFormat &audio_format)
|
|||||||
throw std::runtime_error("FLAC__stream_encoder_new() failed");
|
throw std::runtime_error("FLAC__stream_encoder_new() failed");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
flac_encoder_setup(fse, compression, audio_format);
|
flac_encoder_setup(fse, compression, oggflac, audio_format);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
FLAC__stream_encoder_delete(fse);
|
FLAC__stream_encoder_delete(fse);
|
||||||
throw;
|
throw;
|
||||||
@@ -222,7 +224,7 @@ void
|
|||||||
FlacEncoder::SendTag(const Tag &tag)
|
FlacEncoder::SendTag(const Tag &tag)
|
||||||
{
|
{
|
||||||
/* re-initialize encoder since flac_encoder_finish resets everything */
|
/* re-initialize encoder since flac_encoder_finish resets everything */
|
||||||
flac_encoder_setup(fse, compression, audio_format);
|
flac_encoder_setup(fse, compression, oggflac, audio_format);
|
||||||
|
|
||||||
FLAC__StreamMetadata *metadata = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
FLAC__StreamMetadata *metadata = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||||
FLAC__StreamMetadata_VorbisComment_Entry entry;
|
FLAC__StreamMetadata_VorbisComment_Entry entry;
|
||||||
|
@@ -272,9 +272,8 @@ EventLoop::Run() noexcept
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(IsInside());
|
assert(IsInside());
|
||||||
assert(!quit);
|
|
||||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||||
assert(alive);
|
assert(alive || quit);
|
||||||
assert(busy);
|
assert(busy);
|
||||||
|
|
||||||
wake_event.Schedule(SocketEvent::READ);
|
wake_event.Schedule(SocketEvent::READ);
|
||||||
@@ -299,7 +298,7 @@ EventLoop::Run() noexcept
|
|||||||
|
|
||||||
steady_clock_cache.flush();
|
steady_clock_cache.flush();
|
||||||
|
|
||||||
do {
|
while (!quit) {
|
||||||
again = false;
|
again = false;
|
||||||
|
|
||||||
/* invoke timers */
|
/* invoke timers */
|
||||||
@@ -361,7 +360,7 @@ EventLoop::Run() noexcept
|
|||||||
|
|
||||||
socket_event.Dispatch();
|
socket_event.Dispatch();
|
||||||
}
|
}
|
||||||
} while (!quit);
|
}
|
||||||
|
|
||||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include "Charset.hxx"
|
#include "Charset.hxx"
|
||||||
#include "Features.hxx"
|
#include "Features.hxx"
|
||||||
#include "Domain.hxx"
|
#include "Domain.hxx"
|
||||||
#include "Log.hxx"
|
|
||||||
#include "lib/icu/Converter.hxx"
|
#include "lib/icu/Converter.hxx"
|
||||||
#include "util/AllocatedString.hxx"
|
#include "util/AllocatedString.hxx"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -45,11 +44,9 @@ SetFSCharset(const char *charset)
|
|||||||
assert(charset != nullptr);
|
assert(charset != nullptr);
|
||||||
assert(fs_converter == nullptr);
|
assert(fs_converter == nullptr);
|
||||||
|
|
||||||
|
fs_charset = charset;
|
||||||
fs_converter = IcuConverter::Create(charset);
|
fs_converter = IcuConverter::Create(charset);
|
||||||
assert(fs_converter != nullptr);
|
assert(fs_converter != nullptr);
|
||||||
|
|
||||||
FmtDebug(path_domain,
|
|
||||||
"SetFSCharset: fs charset is {}", fs_charset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -67,6 +67,16 @@ StatFile(Path file, struct stat &buf, bool follow_symlinks = true)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
CreateDirectoryNoThrow(Path path) noexcept
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return CreateDirectory(path.c_str(), nullptr);
|
||||||
|
#else
|
||||||
|
return mkdir(path.c_str(), 0777);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Truncate a file that exists already. Throws std::system_error on
|
* Truncate a file that exists already. Throws std::system_error on
|
||||||
* error.
|
* error.
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#else
|
#else
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -53,6 +52,12 @@
|
|||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_XDG
|
||||||
|
#include "Version.h" // for PACKAGE_NAME
|
||||||
|
#define APP_FILENAME PATH_LITERAL(PACKAGE_NAME)
|
||||||
|
static constexpr Path app_filename = Path::FromFS(APP_FILENAME);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(ANDROID)
|
#if !defined(_WIN32) && !defined(ANDROID)
|
||||||
class PasswdEntry
|
class PasswdEntry
|
||||||
{
|
{
|
||||||
@@ -74,15 +79,6 @@ public:
|
|||||||
return result != nullptr;
|
return result != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadByUid(uid_t uid) {
|
|
||||||
#ifdef HAVE_GETPWUID_R
|
|
||||||
getpwuid_r(uid, &pw, buf.data(), buf.size(), &result);
|
|
||||||
#else
|
|
||||||
result = getpwuid(uid);
|
|
||||||
#endif
|
|
||||||
return result != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const passwd *operator->() {
|
const passwd *operator->() {
|
||||||
assert(result != nullptr);
|
assert(result != nullptr);
|
||||||
return result;
|
return result;
|
||||||
@@ -284,6 +280,24 @@ GetUserCacheDir() noexcept
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AllocatedPath
|
||||||
|
GetAppCacheDir() noexcept
|
||||||
|
{
|
||||||
|
#ifdef USE_XDG
|
||||||
|
if (const auto user_dir = GetUserCacheDir(); !user_dir.IsNull()) {
|
||||||
|
auto dir = user_dir / app_filename;
|
||||||
|
CreateDirectoryNoThrow(dir);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
return context->GetCacheDir(Java::GetEnv());
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
GetUserRuntimeDir() noexcept
|
GetUserRuntimeDir() noexcept
|
||||||
{
|
{
|
||||||
@@ -297,7 +311,7 @@ GetUserRuntimeDir() noexcept
|
|||||||
AllocatedPath
|
AllocatedPath
|
||||||
GetAppRuntimeDir() noexcept
|
GetAppRuntimeDir() noexcept
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#if defined(__linux__) && !defined(ANDROID)
|
||||||
/* systemd specific; see systemd.exec(5) */
|
/* systemd specific; see systemd.exec(5) */
|
||||||
if (const char *runtime_directory = getenv("RUNTIME_DIRECTORY"))
|
if (const char *runtime_directory = getenv("RUNTIME_DIRECTORY"))
|
||||||
if (auto dir = StringView{runtime_directory}.Split(':').first;
|
if (auto dir = StringView{runtime_directory}.Split(':').first;
|
||||||
@@ -307,8 +321,8 @@ GetAppRuntimeDir() noexcept
|
|||||||
|
|
||||||
#ifdef USE_XDG
|
#ifdef USE_XDG
|
||||||
if (const auto user_dir = GetUserRuntimeDir(); !user_dir.IsNull()) {
|
if (const auto user_dir = GetUserRuntimeDir(); !user_dir.IsNull()) {
|
||||||
auto dir = user_dir / Path::FromFS("mpd");
|
auto dir = user_dir / app_filename;
|
||||||
mkdir(dir.c_str(), 0700);
|
CreateDirectoryNoThrow(dir);
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -351,10 +365,8 @@ GetHomeDir() noexcept
|
|||||||
if (const auto home = getenv("HOME");
|
if (const auto home = getenv("HOME");
|
||||||
IsValidPathString(home) && IsValidDir(home))
|
IsValidPathString(home) && IsValidDir(home))
|
||||||
return AllocatedPath::FromFS(home);
|
return AllocatedPath::FromFS(home);
|
||||||
|
|
||||||
if (PasswdEntry pw; pw.ReadByUid(getuid()))
|
|
||||||
return SafePathFromFS(pw->pw_dir);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,13 @@ GetUserMusicDir() noexcept;
|
|||||||
AllocatedPath
|
AllocatedPath
|
||||||
GetUserCacheDir() noexcept;
|
GetUserCacheDir() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains cache directory for this application.
|
||||||
|
*/
|
||||||
|
[[gnu::const]]
|
||||||
|
AllocatedPath
|
||||||
|
GetAppCacheDir() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the runtime directory for the current user.
|
* Obtains the runtime directory for the current user.
|
||||||
*/
|
*/
|
||||||
|
@@ -101,9 +101,17 @@ AsyncInputStream::Seek(std::unique_lock<Mutex> &lock,
|
|||||||
assert(IsReady());
|
assert(IsReady());
|
||||||
assert(seek_state == SeekState::NONE);
|
assert(seek_state == SeekState::NONE);
|
||||||
|
|
||||||
if (new_offset == offset)
|
if (new_offset == offset) {
|
||||||
/* no-op */
|
/* no-op, but if the stream is not open anymore (maybe
|
||||||
|
because it has failed), nothing can be read, so we
|
||||||
|
should check for errors here instead of pretending
|
||||||
|
everything's fine */
|
||||||
|
|
||||||
|
if (!open)
|
||||||
|
Check();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsSeekable())
|
if (!IsSeekable())
|
||||||
throw std::runtime_error("Not seekable");
|
throw std::runtime_error("Not seekable");
|
||||||
|
@@ -417,7 +417,6 @@ CurlInputStream::InitEasy()
|
|||||||
request->SetOption(CURLOPT_HTTP200ALIASES, http_200_aliases);
|
request->SetOption(CURLOPT_HTTP200ALIASES, http_200_aliases);
|
||||||
request->SetOption(CURLOPT_FOLLOWLOCATION, 1L);
|
request->SetOption(CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
request->SetOption(CURLOPT_MAXREDIRS, 5L);
|
request->SetOption(CURLOPT_MAXREDIRS, 5L);
|
||||||
request->SetOption(CURLOPT_FAILONERROR, 1L);
|
|
||||||
|
|
||||||
/* this option eliminates the probe request when
|
/* this option eliminates the probe request when
|
||||||
username/password are specified */
|
username/password are specified */
|
||||||
@@ -439,6 +438,14 @@ CurlInputStream::InitEasy()
|
|||||||
request->SetVerifyPeer(verify_peer);
|
request->SetVerifyPeer(verify_peer);
|
||||||
request->SetVerifyHost(verify_host);
|
request->SetVerifyHost(verify_host);
|
||||||
request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get());
|
request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get());
|
||||||
|
|
||||||
|
try {
|
||||||
|
request->SetProxyVerifyPeer(verify_peer);
|
||||||
|
request->SetProxyVerifyHost(verify_host);
|
||||||
|
} catch (...) {
|
||||||
|
/* these methods fail if libCURL was compiled with
|
||||||
|
CURL_DISABLE_PROXY; ignore silently */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -42,6 +42,8 @@
|
|||||||
#include "io/UniqueFileDescriptor.hxx"
|
#include "io/UniqueFileDescriptor.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
class Path;
|
class Path;
|
||||||
class FileInfo;
|
class FileInfo;
|
||||||
|
|
||||||
|
@@ -49,9 +49,6 @@ Java::File::Initialise(JNIEnv *env) noexcept
|
|||||||
AllocatedPath
|
AllocatedPath
|
||||||
Java::File::ToAbsolutePath(JNIEnv *env, jobject _file) noexcept
|
Java::File::ToAbsolutePath(JNIEnv *env, jobject _file) noexcept
|
||||||
{
|
{
|
||||||
assert(env != nullptr);
|
|
||||||
assert(_file != nullptr);
|
|
||||||
|
|
||||||
LocalObject file(env, _file);
|
LocalObject file(env, _file);
|
||||||
|
|
||||||
const jstring path = GetAbsolutePath(env, file);
|
const jstring path = GetAbsolutePath(env, file);
|
||||||
|
@@ -18,13 +18,13 @@ endif
|
|||||||
|
|
||||||
conf.set('HAVE_MD5', crypto_md5_dep.found())
|
conf.set('HAVE_MD5', crypto_md5_dep.found())
|
||||||
|
|
||||||
if libavutil_dep.found()
|
if ffmpeg_util_dep.found()
|
||||||
crypto_base64 = static_library(
|
crypto_base64 = static_library(
|
||||||
'crypto_base64',
|
'crypto_base64',
|
||||||
'Base64.cxx',
|
'Base64.cxx',
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
libavutil_dep,
|
ffmpeg_util_dep,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -186,10 +186,6 @@ public:
|
|||||||
SetOption(CURLOPT_POSTFIELDSIZE, (long)size);
|
SetOption(CURLOPT_POSTFIELDSIZE, (long)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHttpPost(const struct curl_httppost *post) {
|
|
||||||
SetOption(CURLOPT_HTTPPOST, post);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool GetInfo(CURLINFO info, T value_r) const noexcept {
|
bool GetInfo(CURLINFO info, T value_r) const noexcept {
|
||||||
return ::curl_easy_getinfo(handle, info, value_r) == CURLE_OK;
|
return ::curl_easy_getinfo(handle, info, value_r) == CURLE_OK;
|
||||||
@@ -199,10 +195,10 @@ public:
|
|||||||
* Returns the response body's size, or -1 if that is unknown.
|
* Returns the response body's size, or -1 if that is unknown.
|
||||||
*/
|
*/
|
||||||
[[gnu::pure]]
|
[[gnu::pure]]
|
||||||
int64_t GetContentLength() const noexcept {
|
curl_off_t GetContentLength() const noexcept {
|
||||||
double value;
|
curl_off_t value;
|
||||||
return GetInfo(CURLINFO_CONTENT_LENGTH_DOWNLOAD, &value)
|
return GetInfo(CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &value)
|
||||||
? (int64_t)value
|
? value
|
||||||
: -1;
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -123,6 +123,14 @@ public:
|
|||||||
easy.SetVerifyPeer(value);
|
easy.SetVerifyPeer(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetProxyVerifyHost(bool value) {
|
||||||
|
easy.SetOption(CURLOPT_PROXY_SSL_VERIFYHOST, value ? 2L : 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetProxyVerifyPeer(bool value) {
|
||||||
|
easy.SetOption(CURLOPT_PROXY_SSL_VERIFYPEER, value);
|
||||||
|
}
|
||||||
|
|
||||||
void SetNoBody(bool value=true) {
|
void SetNoBody(bool value=true) {
|
||||||
easy.SetNoBody(value);
|
easy.SetNoBody(value);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
curl_dep = dependency('libcurl', version: '>= 7.33', required: get_option('curl'))
|
curl_dep = dependency('libcurl', version: '>= 7.55', required: get_option('curl'))
|
||||||
conf.set('ENABLE_CURL', curl_dep.found())
|
conf.set('ENABLE_CURL', curl_dep.found())
|
||||||
if not curl_dep.found()
|
if not curl_dep.found()
|
||||||
subdir_done()
|
subdir_done()
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include "Iter.hxx"
|
#include "Iter.hxx"
|
||||||
#include "Values.hxx"
|
#include "Values.hxx"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace ODBus {
|
namespace ODBus {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2021 The Music Player Daemon Project
|
* Copyright 2003-2022 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,26 +17,23 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "LogError.hxx"
|
#pragma once
|
||||||
#include "Domain.hxx"
|
|
||||||
#include "Log.hxx"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavutil/error.h>
|
#include <libavutil/samplefmt.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#include <fmt/format.h>
|
||||||
LogFfmpegError(int errnum)
|
|
||||||
{
|
|
||||||
char msg[256];
|
|
||||||
av_strerror(errnum, msg, sizeof(msg));
|
|
||||||
LogError(ffmpeg_domain, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
template<>
|
||||||
LogFfmpegError(int errnum, const char *prefix)
|
struct fmt::formatter<AVSampleFormat> : formatter<string_view>
|
||||||
{
|
{
|
||||||
char msg[256];
|
template<typename FormatContext>
|
||||||
av_strerror(errnum, msg, sizeof(msg));
|
auto format(const AVSampleFormat format, FormatContext &ctx) {
|
||||||
FmtError(ffmpeg_domain, "{}: {}", prefix, msg);
|
const char *name = av_get_sample_fmt_name(format);
|
||||||
}
|
if (name == nullptr)
|
||||||
|
name = "?";
|
||||||
|
|
||||||
|
return formatter<string_view>::format(name, ctx);
|
||||||
|
}
|
||||||
|
};
|
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2003-2021 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_FFMPEG_LOG_ERROR_HXX
|
|
||||||
#define MPD_FFMPEG_LOG_ERROR_HXX
|
|
||||||
|
|
||||||
void
|
|
||||||
LogFfmpegError(int errnum);
|
|
||||||
|
|
||||||
void
|
|
||||||
LogFfmpegError(int errnum, const char *prefix);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -13,6 +13,29 @@ else
|
|||||||
endif
|
endif
|
||||||
conf.set('HAVE_LIBAVFILTER', libavfilter_dep.found())
|
conf.set('HAVE_LIBAVFILTER', libavfilter_dep.found())
|
||||||
|
|
||||||
|
if not libavutil_dep.found()
|
||||||
|
ffmpeg_util_dep = dependency('', required: false)
|
||||||
|
ffmpeg_dep = dependency('', required: false)
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
ffmpeg_util = static_library(
|
||||||
|
'ffmpeg_util',
|
||||||
|
'Interleave.cxx',
|
||||||
|
'Error.cxx',
|
||||||
|
include_directories: inc,
|
||||||
|
dependencies: [
|
||||||
|
libavutil_dep,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ffmpeg_util_dep = declare_dependency(
|
||||||
|
link_with: ffmpeg_util,
|
||||||
|
dependencies: [
|
||||||
|
libavutil_dep,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
if not enable_ffmpeg
|
if not enable_ffmpeg
|
||||||
ffmpeg_dep = dependency('', required: false)
|
ffmpeg_dep = dependency('', required: false)
|
||||||
subdir_done()
|
subdir_done()
|
||||||
@@ -30,17 +53,16 @@ ffmpeg = static_library(
|
|||||||
'ffmpeg',
|
'ffmpeg',
|
||||||
'Init.cxx',
|
'Init.cxx',
|
||||||
'Interleave.cxx',
|
'Interleave.cxx',
|
||||||
'LogError.cxx',
|
|
||||||
'LogCallback.cxx',
|
'LogCallback.cxx',
|
||||||
'Error.cxx',
|
'Error.cxx',
|
||||||
'Domain.cxx',
|
'Domain.cxx',
|
||||||
ffmpeg_sources,
|
ffmpeg_sources,
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
ffmpeg_util_dep,
|
||||||
libavformat_dep,
|
libavformat_dep,
|
||||||
libavcodec_dep,
|
libavcodec_dep,
|
||||||
libavfilter_dep,
|
libavfilter_dep,
|
||||||
libavutil_dep,
|
|
||||||
log_dep,
|
log_dep,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -48,9 +70,9 @@ ffmpeg = static_library(
|
|||||||
ffmpeg_dep = declare_dependency(
|
ffmpeg_dep = declare_dependency(
|
||||||
link_with: ffmpeg,
|
link_with: ffmpeg,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
ffmpeg_util_dep,
|
||||||
libavformat_dep,
|
libavformat_dep,
|
||||||
libavcodec_dep,
|
libavcodec_dep,
|
||||||
libavfilter_dep,
|
libavfilter_dep,
|
||||||
libavutil_dep,
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -812,8 +812,12 @@ AlsaOutput::Open(AudioFormat &audio_format)
|
|||||||
fmt::format("Failed to open ALSA device \"{}\"",
|
fmt::format("Failed to open ALSA device \"{}\"",
|
||||||
GetDevice()).c_str());
|
GetDevice()).c_str());
|
||||||
|
|
||||||
|
const char *pcm_name = snd_pcm_name(pcm);
|
||||||
|
if (pcm_name == nullptr)
|
||||||
|
pcm_name = "?";
|
||||||
|
|
||||||
FmtDebug(alsa_output_domain, "opened {} type={}",
|
FmtDebug(alsa_output_domain, "opened {} type={}",
|
||||||
snd_pcm_name(pcm),
|
pcm_name,
|
||||||
snd_pcm_type_name(snd_pcm_type(pcm)));
|
snd_pcm_type_name(snd_pcm_type(pcm)));
|
||||||
|
|
||||||
#ifdef ENABLE_DSD
|
#ifdef ENABLE_DSD
|
||||||
|
@@ -627,7 +627,7 @@ osx_render(void *vdata,
|
|||||||
{
|
{
|
||||||
OSXOutput *od = (OSXOutput *) vdata;
|
OSXOutput *od = (OSXOutput *) vdata;
|
||||||
|
|
||||||
int count = in_number_frames * od->asbd.mBytesPerFrame;
|
std::size_t count = in_number_frames * od->asbd.mBytesPerFrame;
|
||||||
buffer_list->mBuffers[0].mDataByteSize =
|
buffer_list->mBuffers[0].mDataByteSize =
|
||||||
od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData,
|
od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData,
|
||||||
count);
|
count);
|
||||||
|
@@ -523,7 +523,13 @@ PipeWireOutput::Open(AudioFormat &audio_format)
|
|||||||
pw_properties_setf(props, PW_KEY_REMOTE_NAME, "%s", remote);
|
pw_properties_setf(props, PW_KEY_REMOTE_NAME, "%s", remote);
|
||||||
|
|
||||||
if (target != nullptr && target_id == PW_ID_ANY)
|
if (target != nullptr && target_id == PW_ID_ANY)
|
||||||
pw_properties_setf(props, PW_KEY_NODE_TARGET, "%s", target);
|
pw_properties_setf(props,
|
||||||
|
#if PW_CHECK_VERSION(0, 3, 64)
|
||||||
|
PW_KEY_TARGET_OBJECT,
|
||||||
|
#else
|
||||||
|
PW_KEY_NODE_TARGET,
|
||||||
|
#endif
|
||||||
|
"%s", target);
|
||||||
|
|
||||||
#ifdef PW_KEY_NODE_RATE
|
#ifdef PW_KEY_NODE_RATE
|
||||||
/* ask PipeWire to change the graph sample rate to ours
|
/* ask PipeWire to change the graph sample rate to ours
|
||||||
@@ -967,6 +973,8 @@ PipeWireOutput::SendTag(const Tag &tag)
|
|||||||
|
|
||||||
struct spa_dict dict = SPA_DICT_INIT(items, n_items);
|
struct spa_dict dict = SPA_DICT_INIT(items, n_items);
|
||||||
|
|
||||||
|
const PipeWire::ThreadLoopLock lock(thread_loop);
|
||||||
|
|
||||||
auto rc = pw_stream_update_properties(stream, &dict);
|
auto rc = pw_stream_update_properties(stream, &dict);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
LogWarning(pipewire_output_domain, "Error updating properties");
|
LogWarning(pipewire_output_domain, "Error updating properties");
|
||||||
|
@@ -17,7 +17,6 @@ storage_glue = static_library(
|
|||||||
'CompositeStorage.cxx',
|
'CompositeStorage.cxx',
|
||||||
'MemoryDirectoryReader.cxx',
|
'MemoryDirectoryReader.cxx',
|
||||||
'Configured.cxx',
|
'Configured.cxx',
|
||||||
'StorageState.cxx',
|
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
boost_dep,
|
boost_dep,
|
||||||
@@ -31,4 +30,3 @@ storage_glue_dep = declare_dependency(
|
|||||||
storage_plugins_dep,
|
storage_plugins_dep,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include "storage/StorageInterface.hxx"
|
#include "storage/StorageInterface.hxx"
|
||||||
#include "storage/FileInfo.hxx"
|
#include "storage/FileInfo.hxx"
|
||||||
#include "storage/MemoryDirectoryReader.hxx"
|
#include "storage/MemoryDirectoryReader.hxx"
|
||||||
|
#include "lib/curl/Error.hxx"
|
||||||
#include "lib/curl/Init.hxx"
|
#include "lib/curl/Init.hxx"
|
||||||
#include "lib/curl/Global.hxx"
|
#include "lib/curl/Global.hxx"
|
||||||
#include "lib/curl/Slist.hxx"
|
#include "lib/curl/Slist.hxx"
|
||||||
@@ -34,7 +35,6 @@
|
|||||||
#include "event/InjectEvent.hxx"
|
#include "event/InjectEvent.hxx"
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "thread/Cond.hxx"
|
#include "thread/Cond.hxx"
|
||||||
#include "time/Parser.hxx"
|
|
||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
@@ -171,8 +171,9 @@ struct DavResponse {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static unsigned
|
static unsigned
|
||||||
ParseStatus(const char *s)
|
ParseStatus(const char *s) noexcept
|
||||||
{
|
{
|
||||||
/* skip the "HTTP/1.1" prefix */
|
/* skip the "HTTP/1.1" prefix */
|
||||||
const char *space = std::strchr(s, ' ');
|
const char *space = std::strchr(s, ' ');
|
||||||
@@ -182,37 +183,37 @@ ParseStatus(const char *s)
|
|||||||
return strtoul(space + 1, nullptr, 10);
|
return strtoul(space + 1, nullptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static unsigned
|
static unsigned
|
||||||
ParseStatus(const char *s, size_t length)
|
ParseStatus(const char *s, size_t length) noexcept
|
||||||
{
|
{
|
||||||
return ParseStatus(std::string(s, length).c_str());
|
return ParseStatus(std::string(s, length).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static std::chrono::system_clock::time_point
|
static std::chrono::system_clock::time_point
|
||||||
ParseTimeStamp(const char *s)
|
ParseTimeStamp(const char *s) noexcept
|
||||||
{
|
{
|
||||||
try {
|
return std::chrono::system_clock::from_time_t(curl_getdate(s, nullptr));
|
||||||
// TODO: make this more robust
|
|
||||||
return ParseTimePoint(s, "%a, %d %b %Y %T");
|
|
||||||
} catch (...) {
|
|
||||||
return std::chrono::system_clock::time_point::min();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static std::chrono::system_clock::time_point
|
static std::chrono::system_clock::time_point
|
||||||
ParseTimeStamp(const char *s, size_t length)
|
ParseTimeStamp(const char *s, size_t length) noexcept
|
||||||
{
|
{
|
||||||
return ParseTimeStamp(std::string(s, length).c_str());
|
return ParseTimeStamp(std::string(s, length).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static uint64_t
|
static uint64_t
|
||||||
ParseU64(const char *s)
|
ParseU64(const char *s) noexcept
|
||||||
{
|
{
|
||||||
return strtoull(s, nullptr, 10);
|
return strtoull(s, nullptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
static uint64_t
|
static uint64_t
|
||||||
ParseU64(const char *s, size_t length)
|
ParseU64(const char *s, size_t length) noexcept
|
||||||
{
|
{
|
||||||
return ParseU64(std::string(s, length).c_str());
|
return ParseU64(std::string(s, length).c_str());
|
||||||
}
|
}
|
||||||
@@ -278,6 +279,7 @@ public:
|
|||||||
"<a:resourcetype/>"
|
"<a:resourcetype/>"
|
||||||
"<a:getcontenttype/>"
|
"<a:getcontenttype/>"
|
||||||
"<a:getcontentlength/>"
|
"<a:getcontentlength/>"
|
||||||
|
"<a:getlastmodified/>"
|
||||||
"</a:prop>"
|
"</a:prop>"
|
||||||
"</a:propfind>");
|
"</a:propfind>");
|
||||||
}
|
}
|
||||||
@@ -299,8 +301,9 @@ private:
|
|||||||
/* virtual methods from CurlResponseHandler */
|
/* virtual methods from CurlResponseHandler */
|
||||||
void OnHeaders(unsigned status, Curl::Headers &&headers) final {
|
void OnHeaders(unsigned status, Curl::Headers &&headers) final {
|
||||||
if (status != 207)
|
if (status != 207)
|
||||||
throw FormatRuntimeError("Status %d from WebDAV server; expected \"207 Multi-Status\"",
|
throw HttpStatusError(status,
|
||||||
status);
|
StringFormat<80>("Status %u from WebDAV server; expected \"207 Multi-Status\"",
|
||||||
|
status).c_str());
|
||||||
|
|
||||||
if (!IsXmlContentType(headers))
|
if (!IsXmlContentType(headers))
|
||||||
throw std::runtime_error("Unexpected Content-Type from WebDAV server");
|
throw std::runtime_error("Unexpected Content-Type from WebDAV server");
|
||||||
|
@@ -70,8 +70,11 @@ FormatLastError(DWORD code, const char *fmt, Args&&... args) noexcept
|
|||||||
{
|
{
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
const auto end = buffer + sizeof(buffer);
|
const auto end = buffer + sizeof(buffer);
|
||||||
size_t length = snprintf(buffer, sizeof(buffer) - 128,
|
constexpr std::size_t max_prefix = sizeof(buffer) - 128;
|
||||||
|
size_t length = snprintf(buffer, max_prefix,
|
||||||
fmt, std::forward<Args>(args)...);
|
fmt, std::forward<Args>(args)...);
|
||||||
|
if (length >= max_prefix)
|
||||||
|
length = max_prefix - 1;
|
||||||
char *p = buffer + length;
|
char *p = buffer + length;
|
||||||
*p++ = ':';
|
*p++ = ':';
|
||||||
*p++ = ' ';
|
*p++ = ' ';
|
||||||
|
@@ -263,8 +263,14 @@ TagBuilder::RemoveAll() noexcept
|
|||||||
void
|
void
|
||||||
TagBuilder::RemoveType(TagType type) noexcept
|
TagBuilder::RemoveType(TagType type) noexcept
|
||||||
{
|
{
|
||||||
|
if (items.empty())
|
||||||
|
/* don't acquire the tag_pool_lock if we're not going
|
||||||
|
to call tag_pool_put_item() anyway */
|
||||||
|
return;
|
||||||
|
|
||||||
const auto begin = items.begin(), end = items.end();
|
const auto begin = items.begin(), end = items.end();
|
||||||
|
|
||||||
|
const std::scoped_lock<Mutex> protect(tag_pool_lock);
|
||||||
items.erase(std::remove_if(begin, end,
|
items.erase(std::remove_if(begin, end,
|
||||||
[type](TagItem *item) {
|
[type](TagItem *item) {
|
||||||
if (item->type != type)
|
if (item->type != type)
|
||||||
|
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2019 Max Kellermann <max.kellermann@gmail.com>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Parser.hxx"
|
|
||||||
#include "Convert.hxx"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
std::chrono::system_clock::time_point
|
|
||||||
ParseTimePoint(const char *s, const char *format)
|
|
||||||
{
|
|
||||||
assert(s != nullptr);
|
|
||||||
assert(format != nullptr);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/* TODO: emulate strptime()? */
|
|
||||||
(void)s;
|
|
||||||
(void)format;
|
|
||||||
throw std::runtime_error("Time parsing not implemented on Windows");
|
|
||||||
#else
|
|
||||||
struct tm tm{};
|
|
||||||
const char *end = strptime(s, format, &tm);
|
|
||||||
if (end == nullptr || *end != 0)
|
|
||||||
throw std::runtime_error("Failed to parse time stamp");
|
|
||||||
|
|
||||||
return TimeGm(tm);
|
|
||||||
#endif /* !_WIN32 */
|
|
||||||
}
|
|
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2019 Max Kellermann <max.kellermann@gmail.com>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TIME_PARSER_HXX
|
|
||||||
#define TIME_PARSER_HXX
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a time stamp.
|
|
||||||
*
|
|
||||||
* Throws std::runtime_error on error.
|
|
||||||
*/
|
|
||||||
std::chrono::system_clock::time_point
|
|
||||||
ParseTimePoint(const char *s, const char *format);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,6 +1,5 @@
|
|||||||
time = static_library(
|
time = static_library(
|
||||||
'time',
|
'time',
|
||||||
'Parser.cxx',
|
|
||||||
'Convert.cxx',
|
'Convert.cxx',
|
||||||
'ISO8601.cxx',
|
'ISO8601.cxx',
|
||||||
'Math.cxx',
|
'Math.cxx',
|
||||||
|
@@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static constexpr Domain signal_handlers_domain("signal_handlers");
|
static constexpr Domain signal_handlers_domain("signal_handlers");
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -60,7 +64,7 @@ handle_reload_event(void *ctx) noexcept
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
SignalHandlersInit(Instance &instance)
|
SignalHandlersInit(Instance &instance, bool daemon)
|
||||||
{
|
{
|
||||||
auto &loop = instance.event_loop;
|
auto &loop = instance.event_loop;
|
||||||
|
|
||||||
@@ -79,6 +83,14 @@ SignalHandlersInit(Instance &instance)
|
|||||||
|
|
||||||
SignalMonitorRegister(SIGHUP, {&instance, handle_reload_event});
|
SignalMonitorRegister(SIGHUP, {&instance, handle_reload_event});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!daemon) {
|
||||||
|
#ifdef __linux__
|
||||||
|
/* if MPD was not daemonized, shut it down when the
|
||||||
|
parent process dies */
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -23,15 +23,15 @@
|
|||||||
struct Instance;
|
struct Instance;
|
||||||
|
|
||||||
void
|
void
|
||||||
SignalHandlersInit(Instance &instance);
|
SignalHandlersInit(Instance &instance, bool daemon);
|
||||||
|
|
||||||
void
|
void
|
||||||
SignalHandlersFinish() noexcept;
|
SignalHandlersFinish() noexcept;
|
||||||
|
|
||||||
class ScopeSignalHandlersInit {
|
class ScopeSignalHandlersInit {
|
||||||
public:
|
public:
|
||||||
ScopeSignalHandlersInit(Instance &instance) {
|
ScopeSignalHandlersInit(Instance &instance, bool daemon) {
|
||||||
SignalHandlersInit(instance);
|
SignalHandlersInit(instance, daemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopeSignalHandlersInit() noexcept {
|
~ScopeSignalHandlersInit() noexcept {
|
||||||
|
@@ -40,14 +40,17 @@ class ScopeExitGuard : F {
|
|||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ScopeExitGuard(F &&f):F(std::forward<F>(f)) {}
|
explicit ScopeExitGuard(F &&f) noexcept:F(std::forward<F>(f)) {}
|
||||||
|
|
||||||
ScopeExitGuard(ScopeExitGuard &&src)
|
ScopeExitGuard(ScopeExitGuard &&src) noexcept
|
||||||
:F(std::move(src)), enabled(src.enabled) {
|
:F(std::move(src)),
|
||||||
src.enabled = false;
|
enabled(std::exchange(src.enabled, false)) {}
|
||||||
}
|
|
||||||
|
|
||||||
~ScopeExitGuard() {
|
/* destructors are "noexcept" by default; this explicit
|
||||||
|
"noexcept" declaration allows the destructor to throw if
|
||||||
|
the function can throw; without this, a throwing function
|
||||||
|
would std::terminate() */
|
||||||
|
~ScopeExitGuard() noexcept(noexcept(std::declval<F>()())) {
|
||||||
if (enabled)
|
if (enabled)
|
||||||
F::operator()();
|
F::operator()();
|
||||||
}
|
}
|
||||||
@@ -64,7 +67,7 @@ struct ScopeExitTag {
|
|||||||
parantheses at the end of the expression AtScopeExit()
|
parantheses at the end of the expression AtScopeExit()
|
||||||
call */
|
call */
|
||||||
template<typename F>
|
template<typename F>
|
||||||
ScopeExitGuard<F> operator+(F &&f) {
|
ScopeExitGuard<F> operator+(F &&f) noexcept {
|
||||||
return ScopeExitGuard<F>(std::forward<F>(f));
|
return ScopeExitGuard<F>(std::forward<F>(f));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = expat-2.4.8
|
directory = expat-2.5.0
|
||||||
source_url = https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.xz
|
source_url = https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.xz
|
||||||
source_filename = expat-2.4.8.tar.bz2
|
source_filename = expat-2.5.0.tar.bz2
|
||||||
source_hash = f79b8f904b749e3e0d20afeadecf8249c55b2e32d4ebb089ae378df479dcaf25
|
source_hash = ef2420f0232c087801abf705e89ae65f6257df6b7931d37846a193ef2e8cdcbe
|
||||||
patch_filename = expat_2.4.8-1_patch.zip
|
patch_filename = expat_2.5.0-2_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.4.8-1/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.5.0-2/get_patch
|
||||||
patch_hash = 9aec253a2c6d1c0feb852c5c6920298d14701eeec7acc6832bb402438b52112a
|
patch_hash = f6cc5ff0d909a2f51a907cc6ca655fb18517a0f58bbe67e4a9c621f1549560c9
|
||||||
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/expat_2.5.0-2/expat-2.5.0.tar.bz2
|
||||||
|
wrapdb_version = 2.5.0-2
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
expat = expat_dep
|
expat = expat_dep
|
||||||
|
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = fmt-8.1.1
|
directory = fmt-9.1.0
|
||||||
source_url = https://github.com/fmtlib/fmt/archive/8.1.1.tar.gz
|
source_url = https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
|
||||||
source_filename = fmt-8.1.1.tar.gz
|
source_filename = fmt-9.1.0.tar.gz
|
||||||
source_hash = 3d794d3cf67633b34b2771eb9f073bde87e846e0d395d254df7b211ef1ec7346
|
source_hash = 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
|
||||||
patch_filename = fmt_8.1.1-2_patch.zip
|
patch_filename = fmt_9.1.0-1_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_8.1.1-2/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_9.1.0-1/get_patch
|
||||||
patch_hash = cd001046281330a8862591780a9ea71a1fa594edd0d015deb24e44680c9ea33b
|
patch_hash = 4557b9ba87b3eb63694ed9b21d1a2117d4a97ca56b91085b10288e9a5294adf8
|
||||||
wrapdb_version = 8.1.1-2
|
wrapdb_version = 9.1.0-1
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
fmt = fmt_dep
|
fmt = fmt_dep
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = sqlite-amalgamation-3380000
|
directory = sqlite-amalgamation-3410200
|
||||||
source_url = https://sqlite.org/2022/sqlite-amalgamation-3380000.zip
|
source_url = https://www.sqlite.org/2023/sqlite-amalgamation-3410200.zip
|
||||||
source_filename = sqlite-amalgamation-3380000.zip
|
source_filename = sqlite-amalgamation-3410200.zip
|
||||||
source_hash = e055f6054e97747a135c89e36520c0a423249e8a91c5fc445163f4a6adb20df6
|
source_hash = 01df06a84803c1ab4d62c64e995b151b2dbcf5dbc93bbc5eee213cb18225d987
|
||||||
patch_filename = sqlite3_3.38.0-1_patch.zip
|
patch_filename = sqlite3_3.41.2-2_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.38.0-1/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.41.2-2/get_patch
|
||||||
patch_hash = 49e30bf010ff63ab772d5417885e6905379025ceac80382e292c6dbd3a9da744
|
patch_hash = 246681dfb731a14bfa61bcde651d5581a7e1c7d14851bfb57a941fac540a6810
|
||||||
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.41.2-2/sqlite-amalgamation-3410200.zip
|
||||||
|
wrapdb_version = 3.41.2-2
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
sqlite3 = sqlite3_dep
|
sqlite3 = sqlite3_dep
|
||||||
|
|
||||||
|
@@ -3,13 +3,12 @@ directory = libvorbis-1.3.7
|
|||||||
source_url = https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz
|
source_url = https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz
|
||||||
source_filename = libvorbis-1.3.7.tar.xz
|
source_filename = libvorbis-1.3.7.tar.xz
|
||||||
source_hash = b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b
|
source_hash = b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b
|
||||||
patch_filename = vorbis_1.3.7-3_patch.zip
|
patch_filename = vorbis_1.3.7-4_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/vorbis_1.3.7-3/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/vorbis_1.3.7-4/get_patch
|
||||||
patch_hash = 6cb90a61ede8c64d3e8e379b96dcc800c9dd69e925122b3d73d8f59a563c3afa
|
patch_hash = 979e22b24b16c927040700dfd8319cd6ba29bf52a14dbc66b1cb4ea60504f14a
|
||||||
wrapdb_version = 1.3.7-3
|
wrapdb_version = 1.3.7-4
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
vorbis = vorbis_dep
|
vorbis = vorbis_dep
|
||||||
vorbisfile = vorbisfile_dep
|
vorbisfile = vorbisfile_dep
|
||||||
vorbisenc = vorbisenc_dep
|
vorbisenc = vorbisenc_dep
|
||||||
|
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
systemd_system_unit_dir = get_option('systemd_system_unit_dir')
|
systemd_system_unit_dir = get_option('systemd_system_unit_dir')
|
||||||
|
if systemd_system_unit_dir == ''
|
||||||
|
systemd = dependency('systemd', required: false)
|
||||||
|
if systemd.found()
|
||||||
|
systemd_system_unit_dir = systemd.get_variable(pkgconfig: 'systemdsystemunitdir')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
if systemd_system_unit_dir == ''
|
if systemd_system_unit_dir == ''
|
||||||
systemd_system_unit_dir = join_paths(get_option('prefix'), 'lib', 'systemd', 'system')
|
systemd_system_unit_dir = join_paths(get_option('prefix'), 'lib', 'systemd', 'system')
|
||||||
endif
|
endif
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
systemd_user_unit_dir = get_option('systemd_user_unit_dir')
|
systemd_user_unit_dir = get_option('systemd_user_unit_dir')
|
||||||
|
if systemd_user_unit_dir == ''
|
||||||
|
systemd = dependency('systemd', required: false)
|
||||||
|
if systemd.found()
|
||||||
|
systemd_user_unit_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
if systemd_user_unit_dir == ''
|
if systemd_user_unit_dir == ''
|
||||||
systemd_user_unit_dir = join_paths(get_option('prefix'), 'lib', 'systemd', 'user')
|
systemd_user_unit_dir = join_paths(get_option('prefix'), 'lib', 'systemd', 'user')
|
||||||
endif
|
endif
|
||||||
|
@@ -288,7 +288,8 @@ if enable_database
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
log_dep,
|
log_dep,
|
||||||
tag_dep,
|
tag_dep,
|
||||||
storage_glue_dep,
|
fs_dep,
|
||||||
|
storage_plugins_dep,
|
||||||
gtest_dep,
|
gtest_dep,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -320,11 +321,6 @@ if curl_dep.found()
|
|||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
curl_dep,
|
curl_dep,
|
||||||
|
|
||||||
# Explicitly linking with zlib here works around a linker
|
|
||||||
# failure on Windows, because our Windows CURL build is
|
|
||||||
# statically linked and thus declares no dependency on zlib
|
|
||||||
zlib_dep,
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ test(
|
|||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
net_dep,
|
net_dep,
|
||||||
|
util_dep,
|
||||||
gtest_dep,
|
gtest_dep,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "ls.hxx"
|
#include "ls.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "db/DatabaseSong.hxx"
|
#include "db/DatabaseSong.hxx"
|
||||||
|
#include "storage/Registry.hxx"
|
||||||
#include "storage/StorageInterface.hxx"
|
#include "storage/StorageInterface.hxx"
|
||||||
#include "storage/plugins/LocalStorage.hxx"
|
#include "storage/plugins/LocalStorage.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
@@ -36,6 +37,13 @@ uri_supported_scheme(const char *uri) noexcept
|
|||||||
return strncmp(uri, "http://", 7) == 0;
|
return strncmp(uri, "http://", 7) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StoragePlugin *
|
||||||
|
GetStoragePluginByUri(const char *) noexcept
|
||||||
|
{
|
||||||
|
// dummy symbol
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr auto music_directory = PATH_LITERAL("/music");
|
static constexpr auto music_directory = PATH_LITERAL("/music");
|
||||||
static Storage *storage;
|
static Storage *storage;
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ class CrossGccToolchain:
|
|||||||
self.cc = os.path.join(toolchain_bin, arch + '-gcc')
|
self.cc = os.path.join(toolchain_bin, arch + '-gcc')
|
||||||
self.cxx = os.path.join(toolchain_bin, arch + '-g++')
|
self.cxx = os.path.join(toolchain_bin, arch + '-g++')
|
||||||
self.ar = os.path.join(toolchain_bin, arch + '-ar')
|
self.ar = os.path.join(toolchain_bin, arch + '-ar')
|
||||||
|
self.arflags = 'rcs'
|
||||||
self.ranlib = os.path.join(toolchain_bin, arch + '-ranlib')
|
self.ranlib = os.path.join(toolchain_bin, arch + '-ranlib')
|
||||||
self.nm = os.path.join(toolchain_bin, arch + '-nm')
|
self.nm = os.path.join(toolchain_bin, arch + '-nm')
|
||||||
self.strip = os.path.join(toolchain_bin, arch + '-strip')
|
self.strip = os.path.join(toolchain_bin, arch + '-strip')
|
||||||
|
Reference in New Issue
Block a user