Compare commits
58 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
df4b6b92f2 | ||
![]() |
1c69913eca | ||
![]() |
cb5c6259fd | ||
![]() |
bf287fefb5 | ||
![]() |
20bf1d68e6 | ||
![]() |
9bc4c168fd | ||
![]() |
3415049d1c | ||
![]() |
a45949b597 | ||
![]() |
6009d4abab | ||
![]() |
16fb843c9b | ||
![]() |
36b333459b | ||
![]() |
4d3320233e | ||
![]() |
933a1a41e6 | ||
![]() |
1ff8626716 | ||
![]() |
c30466b84a | ||
![]() |
868f1a4431 | ||
![]() |
05f529fffd | ||
![]() |
f01388559f | ||
![]() |
27edd4a610 | ||
![]() |
cc421b04cd | ||
![]() |
3f2bc325a1 | ||
![]() |
54686dfd79 | ||
![]() |
f22cf02ed8 | ||
![]() |
5b51d0f733 | ||
![]() |
e03f82636a | ||
![]() |
d53d85bd79 | ||
![]() |
4682ae0898 | ||
![]() |
fd5b195879 | ||
![]() |
bb5df9839d | ||
![]() |
be34d55291 | ||
![]() |
c13911b171 | ||
![]() |
6f83bdd6f3 | ||
![]() |
9bcd425a85 | ||
![]() |
ec917f70d2 | ||
![]() |
40ce4eeb43 | ||
![]() |
29ae84e199 | ||
![]() |
250011f016 | ||
![]() |
e08c85ae2d | ||
![]() |
dcb5ca203c | ||
![]() |
77df5a8f24 | ||
![]() |
d6bebd2507 | ||
![]() |
f74996c02f | ||
![]() |
eea2d35d3a | ||
![]() |
d94e8bd82d | ||
![]() |
b0c92e1a34 | ||
![]() |
ead5bcf048 | ||
![]() |
bdd268a524 | ||
![]() |
e783c2bd2c | ||
![]() |
837fc98638 | ||
![]() |
5deca66fdc | ||
![]() |
cfe2dd4147 | ||
![]() |
00f8d65a17 | ||
![]() |
4e0e4c00bf | ||
![]() |
a8c77a6fba | ||
![]() |
31aa6d0c4f | ||
![]() |
d051c4931d | ||
![]() |
94b0baceb0 | ||
![]() |
16feb261e2 |
.github/workflows
NEWSandroid
doc
meson.buildsrc
LogBackend.cxxMapper.cxxMusicBuffer.cxxMusicBuffer.hxxMusicPipe.cxxMusicPipe.hxxRemoteTagCache.cxx
archive
client
command
db
decoder
event
filter
plugins
fs
input
AsyncInputStream.cxxBufferingInputStream.cxxInputStream.cxxInputStream.hxxThreadInputStream.cxx
cache
plugins
lib
alsa
curl
dbus
icu
nfs
pcre
pipewire
smbclient
upnp
xiph
yajl
mixer
neighbor
net
output
pcm
player
playlist
plugins
protocol
queue
song
sticker
storage
tag
ApeLoader.cxxBuilder.cxxId3Load.cxxId3MixRamp.cxxId3MixRamp.hxxMixRampInfo.hxxMixRampParser.cxxMixRampParser.hxxTag.cxxmeson.build
thread
util
test
132
.github/workflows/build.yml
vendored
Normal file
132
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'android/**'
|
||||
- 'build/**'
|
||||
- 'doc/**'
|
||||
- 'python/**'
|
||||
- 'subprojects/**'
|
||||
- 'systemd/**'
|
||||
- 'win32/**'
|
||||
branches:
|
||||
- master
|
||||
- actions
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'android/**'
|
||||
- 'build/**'
|
||||
- 'doc/**'
|
||||
- 'python/**'
|
||||
- 'subprojects/**'
|
||||
- 'systemd/**'
|
||||
- 'win32/**'
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CC: 'ccache gcc-10'
|
||||
CXX: 'ccache g++-10'
|
||||
steps:
|
||||
- id: checkout
|
||||
uses: actions/checkout@v2
|
||||
- id: cache-ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: linux
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y --no-install-recommends \
|
||||
g++-10 libfmt-dev libboost-dev \
|
||||
libgtest-dev \
|
||||
libpcre2-dev \
|
||||
libsystemd-dev libdbus-1-dev \
|
||||
libicu-dev \
|
||||
libcurl4-gnutls-dev \
|
||||
libpcre2-dev \
|
||||
libavahi-client-dev \
|
||||
libmad0-dev libmpg123-dev libid3tag0-dev \
|
||||
libflac-dev libvorbis-dev libopus-dev libogg-dev \
|
||||
libadplug-dev libaudiofile-dev libsndfile1-dev libfaad-dev \
|
||||
libfluidsynth-dev libgme-dev libmikmod-dev libmodplug-dev \
|
||||
libmpcdec-dev libwavpack-dev libwildmidi-dev \
|
||||
libsidplay2-dev libsidutils-dev libresid-builder-dev \
|
||||
libavcodec-dev libavformat-dev \
|
||||
libmp3lame-dev libtwolame-dev libshine-dev \
|
||||
libsamplerate0-dev libsoxr-dev \
|
||||
libbz2-dev libcdio-paranoia-dev libiso9660-dev libmms-dev \
|
||||
libzzip-dev \
|
||||
libyajl-dev libexpat-dev \
|
||||
libasound2-dev libao-dev libjack-jackd2-dev libopenal-dev \
|
||||
libpulse-dev libshout3-dev \
|
||||
libsndio-dev \
|
||||
libmpdclient-dev \
|
||||
libnfs-dev \
|
||||
libupnp-dev \
|
||||
libsqlite3-dev \
|
||||
libchromaprint-dev \
|
||||
libgcrypt20-dev
|
||||
|
||||
- name: Full Build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: test
|
||||
directory: output/full
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true -Dsystemd=enabled -Dpcre=enabled
|
||||
meson-version: 0.56.0
|
||||
|
||||
- name: Mini Build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: test
|
||||
directory: output/mini
|
||||
setup-options: -Dbuildtype=minsize -Dauto_features=disabled -Dtest=true -Ddaemon=false -Dinotify=false -Depoll=false -Deventfd=false -Dsignalfd=false -Dtcp=false -Ddsd=false -Ddatabase=false -Dneighbor=false -Dcue=false -Dfifo=false -Dhttpd=false -Dpipe=false -Drecorder=false -Dsnapcast=false
|
||||
meson-version: 0.56.0
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- id: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- id: cache-ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: macos
|
||||
|
||||
- uses: actions/setup-python@v1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install \
|
||||
meson ninja \
|
||||
fmt \
|
||||
boost \
|
||||
googletest \
|
||||
icu4c \
|
||||
ffmpeg \
|
||||
libnfs \
|
||||
yajl \
|
||||
libupnp \
|
||||
libid3tag \
|
||||
chromaprint \
|
||||
libsamplerate \
|
||||
libsoxr \
|
||||
flac \
|
||||
opus \
|
||||
libvorbis \
|
||||
faad2 \
|
||||
wavpack \
|
||||
libmpdclient
|
||||
|
||||
- name: Meson Build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: test
|
||||
directory: output
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true
|
||||
meson-version: 0.56.0
|
11
NEWS
11
NEWS
@@ -1,3 +1,14 @@
|
||||
ver 0.23.5 (2021/12/01)
|
||||
* protocol
|
||||
- support relative offsets for "searchadd"
|
||||
- fix "searchaddpl" bug (bogus error "Bad position")
|
||||
* database
|
||||
- upnp: fix crash bug
|
||||
* tags
|
||||
- fix MixRamp support
|
||||
* migrate to PCRE2
|
||||
* GCC 12 build fixes
|
||||
|
||||
ver 0.23.4 (2021/11/11)
|
||||
* protocol
|
||||
- add optional position parameter to "searchaddpl"
|
||||
|
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.musicpd"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="64"
|
||||
android:versionName="0.23.4">
|
||||
android:versionCode="65"
|
||||
android:versionName="0.23.5">
|
||||
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29"/>
|
||||
|
||||
|
@@ -38,7 +38,7 @@ author = 'Max Kellermann'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.23.4'
|
||||
version = '0.23.5'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
#release = version + '~git'
|
||||
|
||||
@@ -107,6 +107,7 @@ html_theme = 'classic'
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
html_theme_options = {"sidebarwidth": "300px"}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
@@ -128,23 +128,6 @@ audio_output
|
||||
no audio_output section is specified, then MPD will scan for a usable audio
|
||||
output.
|
||||
|
||||
replaygain <off or album or track or auto>
|
||||
If specified, mpd will adjust the volume of songs played using ReplayGain
|
||||
tags (see https://wiki.hydrogenaud.io/index.php?title=Replaygain).
|
||||
Setting this to "album" will
|
||||
adjust volume using the album's ReplayGain tags, while setting it to "track"
|
||||
will adjust it using the track ReplayGain tags. "auto" uses the track
|
||||
ReplayGain tags if random play is activated otherwise the album ReplayGain
|
||||
tags. Currently only FLAC, Ogg Vorbis, Musepack, and MP3 (through ID3v2
|
||||
ReplayGain tags, not APEv2) are supported.
|
||||
|
||||
replaygain_preamp <-15 to 15>
|
||||
This is the gain (in dB) applied to songs with ReplayGain tags.
|
||||
|
||||
volume_normalization <yes or no>
|
||||
If yes, mpd will normalize the volume of songs as they play. The default is
|
||||
no.
|
||||
|
||||
filesystem_charset <charset>
|
||||
This specifies the character set used for the filesystem. A list of supported
|
||||
character sets can be obtained by running "iconv -l". The default is
|
||||
|
@@ -1222,6 +1222,8 @@ The music database
|
||||
|
||||
The ``position`` parameter specifies where the songs will be
|
||||
inserted. [#since_0_23]_
|
||||
It can be relative to the current song as in :ref:`addid
|
||||
<command_addid>`. [#since_0_23_5]_
|
||||
|
||||
.. _command_searchaddpl:
|
||||
|
||||
@@ -1659,3 +1661,4 @@ client-to-client messages are local to the current partition.
|
||||
.. [#since_0_23_1] Since :program:`MPD` 0.23.1
|
||||
.. [#since_0_23_3] Since :program:`MPD` 0.23.3
|
||||
.. [#since_0_23_4] Since :program:`MPD` 0.23.4
|
||||
.. [#since_0_23_5] Since :program:`MPD` 0.23.5
|
||||
|
44
doc/user.rst
44
doc/user.rst
@@ -64,13 +64,13 @@ In any case, you need:
|
||||
Each plugin usually needs a codec library, which you also need to
|
||||
install. Check the :doc:`plugins` for details about required libraries
|
||||
|
||||
For example, the following installs a fairly complete list of build dependencies on Debian Buster:
|
||||
For example, the following installs a fairly complete list of build dependencies on Debian Bullseye:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
apt install meson g++ \
|
||||
libfmt-dev \
|
||||
libpcre3-dev \
|
||||
libpcre2-dev \
|
||||
libmad0-dev libmpg123-dev libid3tag0-dev \
|
||||
libflac-dev libvorbis-dev libopus-dev libogg-dev \
|
||||
libadplug-dev libaudiofile-dev libsndfile1-dev libfaad-dev \
|
||||
@@ -465,6 +465,11 @@ The following table lists the audio_output options valid for all plugins:
|
||||
implement an external mixer, see :ref:`external_mixer`) or no mixer
|
||||
(:samp:`none`). By default, the hardware mixer is used for
|
||||
devices which support it, and none for the others.
|
||||
* - **replay_gain_handler software|mixer|none**
|
||||
- Specifies how :ref:`replay_gain` is applied. The default is
|
||||
``software``, which uses an internal software volume control.
|
||||
``mixer`` uses the configured (hardware) mixer control.
|
||||
``none`` disables replay gain on this audio output.
|
||||
* - **filters "name,...**"
|
||||
- The specified configured filters are instantiated in the given
|
||||
order. Each filter name refers to a ``filter`` block, see
|
||||
@@ -583,6 +588,40 @@ Sometimes, music needs to be resampled before it can be played; for example, CDs
|
||||
Check the :ref:`resampler_plugins` reference for a list of resamplers
|
||||
and how to configure them.
|
||||
|
||||
Volume Normalization Settings
|
||||
-----------------------------
|
||||
|
||||
.. _replay_gain:
|
||||
|
||||
Replay Gain
|
||||
^^^^^^^^^^^
|
||||
|
||||
The setting ``replaygain`` specifies whether MPD shall adjust the
|
||||
volume of songs played using `ReplayGain
|
||||
<https://wiki.hydrogenaud.io/index.php?title=Replaygain>`__ tags.
|
||||
Setting this to ``album`` will adjust volume using the album's
|
||||
ReplayGain tags, while setting it to ``track`` will adjust it using
|
||||
the "track" ReplayGain tags. ``auto`` uses the track ReplayGain tags
|
||||
if random play is activated otherwise the album ReplayGain
|
||||
tags.
|
||||
|
||||
If ReplayGain is enabled, then the setting ``replaygain_preamp`` is
|
||||
set to a value (in dB) between ``-15`` and ``15``. This is the gain
|
||||
applied to songs with ReplayGain tags.
|
||||
|
||||
ReplayGain is usually implemented with a software volume filter (which
|
||||
prevents `Bit-perfect playback`_). To use a hardware mixer, set
|
||||
``replay_gain_handler`` to ``mixer`` in the ``audio_output`` section
|
||||
(see :ref:`config_audio_output` for details).
|
||||
|
||||
Simple Volume Normalization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
MPD implements a very simple volume normalization method which can be
|
||||
enabled by setting ``volume_normalization`` to ``yes``. It supports
|
||||
16 bit PCM only.
|
||||
|
||||
|
||||
Client Connections
|
||||
------------------
|
||||
|
||||
@@ -1076,6 +1115,7 @@ Check list for bit-perfect playback:
|
||||
* Disable sound processing inside ALSA by configuring a "hardware"
|
||||
device (:samp:`hw:0,0` or similar).
|
||||
* Don't use software volume (setting :code:`mixer_type`).
|
||||
* Don't use :ref:`replay_gain`.
|
||||
* Don't force :program:`MPD` to use a specific audio format (settings
|
||||
:code:`format`, :ref:`audio_output_format <audio_output_format>`).
|
||||
* Verify that you are really doing bit-perfect playback using :program:`MPD`'s verbose log and :file:`/proc/asound/card*/pcm*p/sub*/hw_params`. Some DACs can also indicate the audio format.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
project(
|
||||
'mpd',
|
||||
['c', 'cpp'],
|
||||
version: '0.23.4',
|
||||
version: '0.23.5',
|
||||
meson_version: '>= 0.56.0',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
@@ -44,7 +44,7 @@ version_conf = configuration_data()
|
||||
version_conf.set_quoted('PACKAGE', meson.project_name())
|
||||
version_conf.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||
version_conf.set_quoted('VERSION', meson.project_version())
|
||||
version_conf.set_quoted('PROTOCOL_VERSION', '0.23.4')
|
||||
version_conf.set_quoted('PROTOCOL_VERSION', '0.23.5')
|
||||
configure_file(output: 'Version.h', configuration: version_conf)
|
||||
|
||||
conf = configuration_data()
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "LogBackend.hxx"
|
||||
#include "Log.hxx"
|
||||
#include "util/Compiler.h"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/StringStrip.hxx"
|
||||
#include "Version.h"
|
||||
@@ -110,7 +111,7 @@ chomp_length(std::string_view p) noexcept
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
|
||||
gcc_const
|
||||
[[gnu::const]]
|
||||
static int
|
||||
ToSysLogLevel(LogLevel log_level) noexcept
|
||||
{
|
||||
|
@@ -85,15 +85,15 @@ map_fs_to_utf8(Path path_fs) noexcept
|
||||
{
|
||||
if (path_fs.IsAbsolute()) {
|
||||
if (global_instance->storage == nullptr)
|
||||
return std::string();
|
||||
return {};
|
||||
|
||||
const auto music_dir_fs = global_instance->storage->MapFS("");
|
||||
if (music_dir_fs.IsNull())
|
||||
return std::string();
|
||||
return {};
|
||||
|
||||
auto relative = music_dir_fs.Relative(path_fs);
|
||||
if (relative == nullptr || StringIsEmpty(relative))
|
||||
return std::string();
|
||||
return {};
|
||||
|
||||
path_fs = Path::FromFS(relative);
|
||||
}
|
||||
|
@@ -29,8 +29,8 @@ MusicBuffer::MusicBuffer(unsigned num_chunks)
|
||||
MusicChunkPtr
|
||||
MusicBuffer::Allocate() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
return MusicChunkPtr(buffer.Allocate(), MusicChunkDeleter(*this));
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return {buffer.Allocate(), MusicChunkDeleter(*this)};
|
||||
}
|
||||
|
||||
void
|
||||
@@ -44,7 +44,7 @@ MusicBuffer::Return(MusicChunk *chunk) noexcept
|
||||
chunk->next.reset();
|
||||
chunk->other.reset();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
assert(!chunk->other || !chunk->other->other);
|
||||
|
||||
|
@@ -54,7 +54,7 @@ public:
|
||||
#endif
|
||||
|
||||
bool IsFull() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return buffer.IsFull();
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@
|
||||
bool
|
||||
MusicPipe::Contains(const MusicChunk *chunk) const noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
for (const MusicChunk *i = head.get(); i != nullptr; i = i->next.get())
|
||||
if (i == chunk)
|
||||
@@ -41,7 +41,7 @@ MusicPipe::Contains(const MusicChunk *chunk) const noexcept
|
||||
MusicChunkPtr
|
||||
MusicPipe::Shift() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
auto chunk = std::move(head);
|
||||
if (chunk != nullptr) {
|
||||
@@ -81,7 +81,7 @@ MusicPipe::Push(MusicChunkPtr chunk) noexcept
|
||||
assert(!chunk->IsEmpty());
|
||||
assert(chunk->length == 0 || chunk->audio_format.IsValid());
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
assert(size > 0 || !audio_format.IsDefined());
|
||||
assert(!audio_format.IsDefined() ||
|
||||
|
@@ -77,7 +77,7 @@ public:
|
||||
*/
|
||||
[[gnu::pure]]
|
||||
const MusicChunk *Peek() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return head.get();
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
*/
|
||||
[[gnu::pure]]
|
||||
unsigned GetSize() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@@ -98,7 +98,7 @@ RemoteTagCache::ItemResolved(Item &item) noexcept
|
||||
void
|
||||
RemoteTagCache::InvokeHandlers() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
|
||||
while (!invoke_list.empty()) {
|
||||
auto &item = invoke_list.front();
|
||||
@@ -125,7 +125,7 @@ RemoteTagCache::Item::OnRemoteTag(Tag &&_tag) noexcept
|
||||
|
||||
scanner.reset();
|
||||
|
||||
const std::lock_guard<Mutex> lock(parent.mutex);
|
||||
const std::scoped_lock<Mutex> lock(parent.mutex);
|
||||
parent.ItemResolved(*this);
|
||||
}
|
||||
|
||||
@@ -137,6 +137,6 @@ RemoteTagCache::Item::OnRemoteTagError(std::exception_ptr e) noexcept
|
||||
|
||||
scanner.reset();
|
||||
|
||||
const std::lock_guard<Mutex> lock(parent.mutex);
|
||||
const std::scoped_lock<Mutex> lock(parent.mutex);
|
||||
parent.ItemResolved(*this);
|
||||
}
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include "plugins/ZzipArchivePlugin.hxx"
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@@ -162,7 +162,7 @@ class Iso9660InputStream final : public InputStream {
|
||||
std::array<uint8_t, ISO_BLOCKSIZE> data;
|
||||
|
||||
public:
|
||||
ConstBuffer<uint8_t> Read() const noexcept {
|
||||
[[nodiscard]] ConstBuffer<uint8_t> Read() const noexcept {
|
||||
assert(fill <= data.size());
|
||||
assert(position <= fill);
|
||||
|
||||
|
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <inttypes.h> /* for PRIoffset (PRIu64) */
|
||||
#include <cinttypes> /* for PRIoffset (PRIu64) */
|
||||
|
||||
struct ZzipDir {
|
||||
ZZIP_DIR *const dir;
|
||||
|
@@ -80,7 +80,7 @@ Response::VFmtError(enum ack code,
|
||||
Fmt(FMT_STRING("ACK [{}@{}] {{{}}} "),
|
||||
(int)code, list_index, command);
|
||||
|
||||
VFmt(format_str, std::move(args));
|
||||
VFmt(format_str, args);
|
||||
|
||||
Write("\n");
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "DatabaseCommands.hxx"
|
||||
#include "PositionArg.hxx"
|
||||
#include "Request.hxx"
|
||||
#include "Partition.hxx"
|
||||
#include "db/DatabaseQueue.hxx"
|
||||
@@ -86,6 +87,20 @@ ParseQueuePosition(Request &args, unsigned queue_length)
|
||||
return queue_length;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
ParseInsertPosition(Request &args, const playlist &playlist)
|
||||
{
|
||||
if (args.size >= 2 && StringIsEqual(args[args.size - 2], "position")) {
|
||||
unsigned position = ParseInsertPosition(args.back(), playlist);
|
||||
args.pop_back();
|
||||
args.pop_back();
|
||||
return position;
|
||||
}
|
||||
|
||||
/* append to the end of the queue by default */
|
||||
return playlist.queue.GetLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert all remaining arguments to a #DatabaseSelection.
|
||||
*
|
||||
@@ -160,7 +175,8 @@ handle_match_add(Client &client, Request args, bool fold_case)
|
||||
{
|
||||
auto &partition = client.GetPartition();
|
||||
const auto queue_length = partition.playlist.queue.GetLength();
|
||||
const unsigned position = ParseQueuePosition(args, queue_length);
|
||||
const unsigned position =
|
||||
ParseInsertPosition(args, partition.playlist);
|
||||
|
||||
SongFilter filter;
|
||||
const auto selection = ParseDatabaseSelection(args, fold_case, filter);
|
||||
|
@@ -213,7 +213,7 @@ read_stream_art(Response &r, const std::string_view art_directory,
|
||||
std::min<offset_type>(art_file_size - offset,
|
||||
r.GetClient().binary_limit);
|
||||
|
||||
std::unique_ptr<std::byte[]> buffer(new std::byte[buffer_size]);
|
||||
auto buffer = std::make_unique<std::byte[]>(buffer_size);
|
||||
|
||||
std::size_t read_size = 0;
|
||||
if (buffer_size > 0) {
|
||||
|
@@ -67,7 +67,7 @@ protected:
|
||||
}
|
||||
|
||||
void CancelThread() noexcept override {
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
cancel = true;
|
||||
cond.notify_one();
|
||||
}
|
||||
@@ -204,7 +204,7 @@ GetChromaprintCommand::DecodeFile(std::string_view suffix, InputStream &is,
|
||||
return false;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (cancel)
|
||||
throw StopDecoder();
|
||||
}
|
||||
|
@@ -53,10 +53,9 @@ SearchInsertIntoPlaylist(const Database &db, const Storage *storage,
|
||||
|
||||
unsigned n = 0;
|
||||
|
||||
db.Visit(selection, [&playlist, &position, &n, storage](const auto &song){
|
||||
db.Visit(selection, [&playlist, position, &n, storage](const auto &song){
|
||||
playlist.Insert(position + n,
|
||||
DatabaseDetachSong(storage, song));
|
||||
++position;
|
||||
++n;
|
||||
});
|
||||
|
||||
|
@@ -35,6 +35,7 @@ db_plugins = static_library(
|
||||
include_directories: inc,
|
||||
dependencies: [
|
||||
upnp_dep,
|
||||
pcre_dep,
|
||||
libmpdclient_dep,
|
||||
log_dep,
|
||||
],
|
||||
|
@@ -278,5 +278,5 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
||||
LightDirectory
|
||||
Directory::Export() const noexcept
|
||||
{
|
||||
return LightDirectory(GetPath(), mtime);
|
||||
return {GetPath(), mtime};
|
||||
}
|
||||
|
@@ -316,7 +316,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
||||
|
||||
if (r.rest.find('/') == std::string_view::npos) {
|
||||
if (visit_song) {
|
||||
Song *song = r.directory->FindSong(r.rest);
|
||||
const Song *song = r.directory->FindSong(r.rest);
|
||||
if (song != nullptr) {
|
||||
const auto song2 = song->Export();
|
||||
if (selection.Match(song2))
|
||||
|
@@ -250,11 +250,11 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
|
||||
{
|
||||
const SongFilter *filter = selection.filter;
|
||||
if (selection.filter == nullptr)
|
||||
return UPnPDirContent();
|
||||
return {};
|
||||
|
||||
const auto searchcaps = server.getSearchCapabilities(handle);
|
||||
if (searchcaps.empty())
|
||||
return UPnPDirContent();
|
||||
return {};
|
||||
|
||||
std::string cond;
|
||||
for (const auto &item : filter->GetItems()) {
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include "util/StringCompare.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <string.h>
|
||||
|
@@ -34,7 +34,7 @@ UpdateQueueItem
|
||||
UpdateQueue::Pop() noexcept
|
||||
{
|
||||
if (update_queue.empty())
|
||||
return UpdateQueueItem();
|
||||
return {};
|
||||
|
||||
auto i = std::move(update_queue.front());
|
||||
update_queue.pop_front();
|
||||
|
@@ -36,7 +36,7 @@ UpdateRemoveService::RunDeferred() noexcept
|
||||
std::forward_list<std::string> copy;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
std::swap(uris, copy);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ UpdateRemoveService::Remove(std::string &&uri)
|
||||
bool was_empty;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
was_empty = uris.empty();
|
||||
uris.emplace_front(std::move(uri));
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ try {
|
||||
}
|
||||
|
||||
bool
|
||||
directory_child_access(Storage &storage, const Directory &directory,
|
||||
directory_child_access(const Storage &storage, const Directory &directory,
|
||||
std::string_view name, int mode) noexcept
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@@ -55,7 +55,7 @@ directory_child_is_regular(Storage &storage, const Directory &directory,
|
||||
*/
|
||||
[[gnu::pure]]
|
||||
bool
|
||||
directory_child_access(Storage &storage, const Directory &directory,
|
||||
directory_child_access(const Storage &storage, const Directory &directory,
|
||||
std::string_view name, int mode) noexcept;
|
||||
|
||||
#endif
|
||||
|
@@ -152,7 +152,7 @@ DecoderBridge::FlushChunk() noexcept
|
||||
if (!chunk->IsEmpty())
|
||||
dc.pipe->Push(std::move(chunk));
|
||||
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
dc.client_cond.notify_one();
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ DecoderBridge::GetVirtualCommand() noexcept
|
||||
DecoderCommand
|
||||
DecoderBridge::LockGetVirtualCommand() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
return GetVirtualCommand();
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ DecoderBridge::Ready(const AudioFormat audio_format,
|
||||
seekable);
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
dc.SetReady(audio_format, seekable, duration);
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ DecoderBridge::GetCommand() noexcept
|
||||
void
|
||||
DecoderBridge::CommandFinished() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
|
||||
assert(dc.command != DecoderCommand::NONE || initial_seek_running);
|
||||
assert(dc.command != DecoderCommand::SEEK ||
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "Command.hxx"
|
||||
#include "pcm/AudioFormat.hxx"
|
||||
#include "MixRampInfo.hxx"
|
||||
#include "tag/MixRampInfo.hxx"
|
||||
#include "input/Handler.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "thread/Cond.hxx"
|
||||
@@ -231,7 +231,7 @@ public:
|
||||
|
||||
[[gnu::pure]]
|
||||
bool LockIsIdle() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return IsIdle();
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
|
||||
[[gnu::pure]]
|
||||
bool LockIsStarting() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return IsStarting();
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
|
||||
[[gnu::pure]]
|
||||
bool LockHasFailed() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return HasFailed();
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
* Like CheckRethrowError(), but locks and unlocks the object.
|
||||
*/
|
||||
void LockCheckRethrowError() const {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
CheckRethrowError();
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ private:
|
||||
}
|
||||
|
||||
void LockAsynchronousCommand(DecoderCommand cmd) noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
command = cmd;
|
||||
Signal();
|
||||
}
|
||||
|
@@ -35,8 +35,8 @@
|
||||
#include "DecoderPlugin.hxx"
|
||||
#include "ReplayGainInfo.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "tag/MixRampInfo.hxx"
|
||||
#include "pcm/AudioFormat.hxx"
|
||||
#include "MixRampInfo.hxx"
|
||||
#include "config/Block.hxx"
|
||||
#include "Chrono.hxx"
|
||||
|
||||
|
@@ -262,7 +262,7 @@ static void
|
||||
MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is)
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(bridge.dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(bridge.dc.mutex);
|
||||
if (bridge.dc.replay_gain_mode == ReplayGainMode::OFF)
|
||||
/* ReplayGain is disabled */
|
||||
return;
|
||||
@@ -337,7 +337,7 @@ TryDecoderFile(DecoderBridge &bridge, Path path_fs, std::string_view suffix,
|
||||
DecoderControl &dc = bridge.dc;
|
||||
|
||||
if (plugin.file_decode != nullptr) {
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
return decoder_file_decode(plugin, bridge, path_fs);
|
||||
} else if (plugin.stream_decode != nullptr) {
|
||||
std::unique_lock<Mutex> lock(dc.mutex);
|
||||
@@ -365,7 +365,7 @@ TryContainerDecoder(DecoderBridge &bridge, Path path_fs,
|
||||
bridge.Reset();
|
||||
|
||||
DecoderControl &dc = bridge.dc;
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
const std::scoped_lock<Mutex> protect(dc.mutex);
|
||||
return decoder_file_decode(plugin, bridge, path_fs);
|
||||
}
|
||||
|
||||
|
@@ -83,8 +83,8 @@ audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length) noexcept
|
||||
static AFfileoffset
|
||||
audiofile_file_length(AFvirtualfile *vfile) noexcept
|
||||
{
|
||||
AudioFileInputStream &afis = *(AudioFileInputStream *)vfile->closure;
|
||||
InputStream &is = afis.is;
|
||||
const AudioFileInputStream &afis = *(AudioFileInputStream *)vfile->closure;
|
||||
const InputStream &is = afis.is;
|
||||
|
||||
return is.GetSize();
|
||||
}
|
||||
@@ -92,8 +92,8 @@ audiofile_file_length(AFvirtualfile *vfile) noexcept
|
||||
static AFfileoffset
|
||||
audiofile_file_tell(AFvirtualfile *vfile) noexcept
|
||||
{
|
||||
AudioFileInputStream &afis = *(AudioFileInputStream *)vfile->closure;
|
||||
InputStream &is = afis.is;
|
||||
const AudioFileInputStream &afis = *(AudioFileInputStream *)vfile->closure;
|
||||
const InputStream &is = afis.is;
|
||||
|
||||
return is.GetOffset();
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#include "tag/Builder.hxx"
|
||||
#include "tag/Handler.hxx"
|
||||
#include "tag/ReplayGain.hxx"
|
||||
#include "tag/MixRamp.hxx"
|
||||
#include "tag/MixRampParser.hxx"
|
||||
#include "input/InputStream.hxx"
|
||||
#include "pcm/CheckAudioFormat.hxx"
|
||||
#include "util/ScopeExit.hxx"
|
||||
|
@@ -78,7 +78,9 @@ FlacDecoder::OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc)
|
||||
if (flac_parse_replay_gain(rgi, vc))
|
||||
GetClient()->SubmitReplayGain(&rgi);
|
||||
|
||||
GetClient()->SubmitMixRamp(flac_parse_mixramp(vc));
|
||||
if (auto mix_ramp = flac_parse_mixramp(vc);
|
||||
mix_ramp.IsDefined())
|
||||
GetClient()->SubmitMixRamp(std::move(mix_ramp));
|
||||
|
||||
tag = flac_vorbis_comments_to_tag(&vc);
|
||||
}
|
||||
|
@@ -23,9 +23,10 @@
|
||||
#include "input/InputStream.hxx"
|
||||
#include "tag/Id3Scan.hxx"
|
||||
#include "tag/Id3ReplayGain.hxx"
|
||||
#include "tag/Id3MixRamp.hxx"
|
||||
#include "tag/Handler.hxx"
|
||||
#include "tag/ReplayGain.hxx"
|
||||
#include "tag/MixRamp.hxx"
|
||||
#include "tag/MixRampParser.hxx"
|
||||
#include "pcm/CheckAudioFormat.hxx"
|
||||
#include "util/Clamp.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
@@ -268,35 +269,6 @@ MadDecoder::FillBuffer() noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ID3TAG
|
||||
gcc_pure
|
||||
static MixRampInfo
|
||||
parse_id3_mixramp(struct id3_tag *tag) noexcept
|
||||
{
|
||||
MixRampInfo result;
|
||||
|
||||
struct id3_frame *frame;
|
||||
for (unsigned i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
|
||||
if (frame->nfields < 3)
|
||||
continue;
|
||||
|
||||
char *const key = (char *)
|
||||
id3_ucs4_latin1duplicate(id3_field_getstring
|
||||
(&frame->fields[1]));
|
||||
char *const value = (char *)
|
||||
id3_ucs4_latin1duplicate(id3_field_getstring
|
||||
(&frame->fields[2]));
|
||||
|
||||
ParseMixRampTag(result, key, value);
|
||||
|
||||
free(key);
|
||||
free(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void
|
||||
MadDecoder::ParseId3(size_t tagsize, Tag *mpd_tag) noexcept
|
||||
{
|
||||
@@ -310,7 +282,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag *mpd_tag) noexcept
|
||||
id3_data = stream.this_frame;
|
||||
mad_stream_skip(&(stream), tagsize);
|
||||
} else {
|
||||
allocated.reset(new id3_byte_t[tagsize]);
|
||||
allocated = std::make_unique<id3_byte_t[]>(tagsize);
|
||||
memcpy(allocated.get(), stream.this_frame, count);
|
||||
mad_stream_skip(&(stream), count);
|
||||
|
||||
@@ -338,7 +310,9 @@ MadDecoder::ParseId3(size_t tagsize, Tag *mpd_tag) noexcept
|
||||
found_replay_gain = true;
|
||||
}
|
||||
|
||||
client->SubmitMixRamp(parse_id3_mixramp(id3_tag.get()));
|
||||
if (auto mix_ramp = Id3ToMixRampInfo(id3_tag.get());
|
||||
mix_ramp.IsDefined())
|
||||
client->SubmitMixRamp(std::move(mix_ramp));
|
||||
}
|
||||
|
||||
#else /* !ENABLE_ID3TAG */
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include "tag/Handler.hxx"
|
||||
#include "tag/Builder.hxx"
|
||||
#include "tag/ReplayGain.hxx"
|
||||
#include "tag/MixRamp.hxx"
|
||||
#include "tag/MixRampParser.hxx"
|
||||
#include "fs/Path.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/ScopeExit.hxx"
|
||||
|
@@ -137,7 +137,7 @@ SidplayGlobal::SidplayGlobal(const ConfigBlock &block)
|
||||
const auto kernal_path = block.GetPath("kernal");
|
||||
if (!kernal_path.IsNull())
|
||||
{
|
||||
kernal.reset(new uint8_t[rom_size]);
|
||||
kernal = std::make_unique<uint8_t[]>(rom_size);
|
||||
loadRom(kernal_path, kernal.get());
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ SidplayGlobal::SidplayGlobal(const ConfigBlock &block)
|
||||
const auto basic_path = block.GetPath("basic");
|
||||
if (!basic_path.IsNull())
|
||||
{
|
||||
basic.reset(new uint8_t[rom_size]);
|
||||
basic = std::make_unique<uint8_t[]>(rom_size);
|
||||
loadRom(basic_path, basic.get());
|
||||
}
|
||||
#endif
|
||||
|
@@ -68,7 +68,7 @@ private:
|
||||
exception = std::current_exception();
|
||||
}
|
||||
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
done = true;
|
||||
cond.notify_one();
|
||||
}
|
||||
|
@@ -323,7 +323,7 @@ EventLoop::Run() noexcept
|
||||
/* try to handle DeferEvents without WakeFD
|
||||
overhead */
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
HandleInject();
|
||||
#endif
|
||||
|
||||
@@ -346,7 +346,7 @@ EventLoop::Run() noexcept
|
||||
|
||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
busy = true;
|
||||
}
|
||||
#endif
|
||||
@@ -378,7 +378,7 @@ EventLoop::AddInject(InjectEvent &d) noexcept
|
||||
bool must_wake;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
if (d.IsPending())
|
||||
return;
|
||||
|
||||
@@ -397,7 +397,7 @@ EventLoop::AddInject(InjectEvent &d) noexcept
|
||||
void
|
||||
EventLoop::RemoveInject(InjectEvent &d) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (d.IsPending())
|
||||
inject.erase(inject.iterator_to(d));
|
||||
@@ -424,7 +424,7 @@ EventLoop::OnSocketReady([[maybe_unused]] unsigned flags) noexcept
|
||||
|
||||
wake_fd.Read();
|
||||
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
HandleInject();
|
||||
}
|
||||
|
||||
|
@@ -91,7 +91,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsDefined() const noexcept {
|
||||
[[nodiscard]] bool IsDefined() const noexcept {
|
||||
return event.IsDefined();
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <csignal>
|
||||
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
auto &GetEventLoop() const noexcept {
|
||||
[[nodiscard]] auto &GetEventLoop() const noexcept {
|
||||
return event.GetEventLoop();
|
||||
}
|
||||
|
||||
@@ -90,12 +91,12 @@ private:
|
||||
/* this should be enough - is it? */
|
||||
static constexpr unsigned MAX_SIGNAL = 64;
|
||||
|
||||
static SignalHandler signal_handlers[MAX_SIGNAL];
|
||||
static std::array<SignalHandler, MAX_SIGNAL> signal_handlers;
|
||||
|
||||
#ifdef USE_SIGNALFD
|
||||
static sigset_t signal_mask;
|
||||
#else
|
||||
static std::atomic_bool signal_pending[MAX_SIGNAL];
|
||||
static std::array<std::atomic_bool, MAX_SIGNAL> signal_pending;
|
||||
#endif
|
||||
|
||||
static Manual<SignalMonitor> monitor;
|
||||
@@ -153,7 +154,7 @@ void
|
||||
SignalMonitorFinish() noexcept
|
||||
{
|
||||
#ifdef USE_SIGNALFD
|
||||
std::fill_n(signal_handlers, MAX_SIGNAL, nullptr);
|
||||
signal_handlers = {};
|
||||
#else
|
||||
struct sigaction sa;
|
||||
sa.sa_flags = 0;
|
||||
@@ -167,7 +168,7 @@ SignalMonitorFinish() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
std::fill_n(signal_pending, MAX_SIGNAL, false);
|
||||
std::fill(signal_pending.begin(), signal_pending.end(), false);
|
||||
#endif
|
||||
|
||||
monitor.Destruct();
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#include "filter/Filter.hxx"
|
||||
#include "filter/Prepared.hxx"
|
||||
#include "pcm/AudioFormat.hxx"
|
||||
#include "util/ConstBuffer.hxx"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
@@ -31,7 +31,7 @@ AllocatedPath::FromUTF8(std::string_view path_utf8) noexcept
|
||||
return FromFS(path_utf8);
|
||||
#else
|
||||
try {
|
||||
return AllocatedPath(::PathFromUTF8(path_utf8));
|
||||
return {::PathFromUTF8(path_utf8)};
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ AllocatedPath::FromUTF8Throw(std::string_view path_utf8)
|
||||
#ifdef FS_CHARSET_ALWAYS_UTF8
|
||||
return FromFS(path_utf8);
|
||||
#else
|
||||
return AllocatedPath(::PathFromUTF8(path_utf8));
|
||||
return {::PathFromUTF8(path_utf8)};
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ Path::ToUTF8() const noexcept
|
||||
try {
|
||||
return ToUTF8Throw();
|
||||
} catch (...) {
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -244,7 +244,7 @@ AsyncInputStream::AppendToBuffer(const void *data, size_t append_size) noexcept
|
||||
void
|
||||
AsyncInputStream::DeferredResume() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
try {
|
||||
Resume();
|
||||
@@ -257,7 +257,7 @@ AsyncInputStream::DeferredResume() noexcept
|
||||
void
|
||||
AsyncInputStream::DeferredSeek() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (seek_state != SeekState::SCHEDULED)
|
||||
return;
|
||||
|
||||
|
@@ -37,7 +37,7 @@ BufferingInputStream::BufferingInputStream(InputStreamPtr _input)
|
||||
BufferingInputStream::~BufferingInputStream() noexcept
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
stop = true;
|
||||
wake_cond.notify_one();
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ InputStream::ReadTag() noexcept
|
||||
std::unique_ptr<Tag>
|
||||
InputStream::LockReadTag() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return ReadTag();
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ InputStream::LockReadFull(void *ptr, size_t _size)
|
||||
bool
|
||||
InputStream::LockIsEOF() const noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return IsEOF();
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
struct Tag;
|
||||
class InputStreamHandler;
|
||||
|
@@ -45,7 +45,7 @@ ThreadInputStream::Stop() noexcept
|
||||
return;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
close = true;
|
||||
wake_cond.notify_one();
|
||||
}
|
||||
|
4
src/input/cache/Item.cxx
vendored
4
src/input/cache/Item.cxx
vendored
@@ -37,14 +37,14 @@ InputCacheItem::~InputCacheItem() noexcept
|
||||
void
|
||||
InputCacheItem::AddLease(InputCacheLease &lease) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
leases.push_back(lease);
|
||||
}
|
||||
|
||||
void
|
||||
InputCacheItem::RemoveLease(InputCacheLease &lease) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
auto i = leases.iterator_to(lease);
|
||||
if (i == next_lease)
|
||||
++next_lease;
|
||||
|
2
src/input/cache/Item.hxx
vendored
2
src/input/cache/Item.hxx
vendored
@@ -63,7 +63,7 @@ public:
|
||||
using BufferingInputStream::size;
|
||||
|
||||
bool IsInUse() const noexcept {
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
return !leases.empty();
|
||||
}
|
||||
|
||||
|
10
src/input/cache/Stream.cxx
vendored
10
src/input/cache/Stream.cxx
vendored
@@ -24,7 +24,7 @@ CacheInputStream::CacheInputStream(InputCacheLease _lease,
|
||||
:InputStream(_lease->GetUri(), _mutex),
|
||||
InputCacheLease(std::move(_lease))
|
||||
{
|
||||
auto &i = GetCacheItem();
|
||||
const auto &i = GetCacheItem();
|
||||
size = i.size();
|
||||
seekable = true;
|
||||
SetReady();
|
||||
@@ -36,7 +36,7 @@ CacheInputStream::Check()
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
auto &i = GetCacheItem();
|
||||
const std::lock_guard<Mutex> protect(i.mutex);
|
||||
const std::scoped_lock<Mutex> protect(i.mutex);
|
||||
|
||||
i.Check();
|
||||
}
|
||||
@@ -60,7 +60,7 @@ CacheInputStream::IsAvailable() const noexcept
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
auto &i = GetCacheItem();
|
||||
const std::lock_guard<Mutex> protect(i.mutex);
|
||||
const std::scoped_lock<Mutex> protect(i.mutex);
|
||||
|
||||
return i.IsAvailable(_offset);
|
||||
}
|
||||
@@ -76,7 +76,7 @@ CacheInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
const std::lock_guard<Mutex> protect(i.mutex);
|
||||
const std::scoped_lock<Mutex> protect(i.mutex);
|
||||
|
||||
nbytes = i.Read(lock, _offset, ptr, read_size);
|
||||
}
|
||||
@@ -91,6 +91,6 @@ CacheInputStream::OnInputCacheAvailable() noexcept
|
||||
auto &i = GetCacheItem();
|
||||
const ScopeUnlock unlock(i.mutex);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
InvokeOnAvailable();
|
||||
}
|
||||
|
@@ -28,12 +28,10 @@
|
||||
#include "lib/alsa/NonBlock.hxx"
|
||||
#include "lib/alsa/Error.hxx"
|
||||
#include "lib/alsa/Format.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "../AsyncInputStream.hxx"
|
||||
#include "event/Call.hxx"
|
||||
#include "config/Block.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
#include "util/ASCII.hxx"
|
||||
#include "util/DivideString.hxx"
|
||||
#include "pcm/AudioParser.hxx"
|
||||
@@ -239,7 +237,7 @@ AlsaInputStream::DispatchSockets() noexcept
|
||||
{
|
||||
non_block.DispatchSockets(*this, capture_handle);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
auto w = PrepareWriteBuffer();
|
||||
const snd_pcm_uframes_t w_frames = w.size / frame_size;
|
||||
|
@@ -238,7 +238,7 @@ CurlInputStream::OnHeaders(unsigned status,
|
||||
StringFormat<40>("got HTTP status %u",
|
||||
status).c_str());
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (IsSeekPending()) {
|
||||
/* don't update metadata while seeking */
|
||||
@@ -301,7 +301,7 @@ CurlInputStream::OnData(ConstBuffer<void> data)
|
||||
{
|
||||
assert(data.size > 0);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (IsSeekPending())
|
||||
SeekDone();
|
||||
@@ -317,7 +317,7 @@ CurlInputStream::OnData(ConstBuffer<void> data)
|
||||
void
|
||||
CurlInputStream::OnEnd()
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
InvokeOnAvailable();
|
||||
|
||||
AsyncInputStream::SetClosed();
|
||||
@@ -326,7 +326,7 @@ CurlInputStream::OnEnd()
|
||||
void
|
||||
CurlInputStream::OnError(std::exception_ptr e) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
postponed_exception = std::move(e);
|
||||
|
||||
if (IsSeekPending())
|
||||
|
@@ -141,7 +141,7 @@ NfsInputStream::DoSeek(offset_type new_offset)
|
||||
void
|
||||
NfsInputStream::OnNfsFileOpen(uint64_t _size) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (reconnecting) {
|
||||
/* reconnect has succeeded */
|
||||
@@ -161,7 +161,7 @@ NfsInputStream::OnNfsFileOpen(uint64_t _size) noexcept
|
||||
void
|
||||
NfsInputStream::OnNfsFileRead(const void *data, size_t data_size) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
assert(!IsBufferFull());
|
||||
assert(IsBufferFull() == (GetBufferSpace() == 0));
|
||||
AppendToBuffer(data, data_size);
|
||||
@@ -174,7 +174,7 @@ NfsInputStream::OnNfsFileRead(const void *data, size_t data_size) noexcept
|
||||
void
|
||||
NfsInputStream::OnNfsFileError(std::exception_ptr &&e) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (IsPaused()) {
|
||||
/* while we're paused, don't report this error to the
|
||||
|
@@ -87,7 +87,7 @@ QobuzClient::StartLogin()
|
||||
void
|
||||
QobuzClient::AddLoginHandler(QobuzSessionHandler &h) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
assert(!h.is_linked());
|
||||
|
||||
const bool was_empty = handlers.empty();
|
||||
@@ -114,7 +114,7 @@ QobuzClient::AddLoginHandler(QobuzSessionHandler &h) noexcept
|
||||
QobuzSession
|
||||
QobuzClient::GetSession() const
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (error)
|
||||
std::rethrow_exception(error);
|
||||
@@ -129,7 +129,7 @@ void
|
||||
QobuzClient::OnQobuzLoginSuccess(QobuzSession &&_session) noexcept
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
session = std::move(_session);
|
||||
login_request.reset();
|
||||
}
|
||||
@@ -141,7 +141,7 @@ void
|
||||
QobuzClient::OnQobuzLoginError(std::exception_ptr _error) noexcept
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
error = std::move(_error);
|
||||
login_request.reset();
|
||||
}
|
||||
@@ -152,7 +152,7 @@ QobuzClient::OnQobuzLoginError(std::exception_ptr _error) noexcept
|
||||
void
|
||||
QobuzClient::InvokeHandlers() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
while (!handlers.empty()) {
|
||||
auto &h = handlers.front();
|
||||
handlers.pop_front();
|
||||
|
@@ -83,7 +83,7 @@ public:
|
||||
void AddLoginHandler(QobuzSessionHandler &h) noexcept;
|
||||
|
||||
void RemoveLoginHandler(QobuzSessionHandler &h) noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (h.is_linked())
|
||||
h.unlink();
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ private:
|
||||
void
|
||||
QobuzInputStream::OnQobuzSession() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
try {
|
||||
const auto session = qobuz_client->GetSession();
|
||||
@@ -103,7 +103,7 @@ QobuzInputStream::OnQobuzSession() noexcept
|
||||
void
|
||||
QobuzInputStream::OnQobuzTrackSuccess(std::string url) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
track_request.reset();
|
||||
|
||||
try {
|
||||
@@ -117,7 +117,7 @@ QobuzInputStream::OnQobuzTrackSuccess(std::string url) noexcept
|
||||
void
|
||||
QobuzInputStream::OnQobuzTrackError(std::exception_ptr e) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
track_request.reset();
|
||||
|
||||
Failed(e);
|
||||
|
@@ -149,7 +149,7 @@ UringInputStream::OnRead(std::unique_ptr<std::byte[]> data,
|
||||
{
|
||||
read_operation.reset();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (nbytes == 0) {
|
||||
postponed_exception = std::make_exception_ptr(std::runtime_error("Premature end of file"));
|
||||
@@ -170,7 +170,7 @@ UringInputStream::OnReadError(int error) noexcept
|
||||
{
|
||||
read_operation.reset();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
postponed_exception = std::make_exception_ptr(MakeErrno(error, "Read failed"));
|
||||
InvokeOnAvailable();
|
||||
|
@@ -41,4 +41,4 @@ ErrorCategory::message(int condition) const
|
||||
return snd_strerror(condition);
|
||||
}
|
||||
|
||||
} // namespace Avahi
|
||||
} // namespace Alsa
|
||||
|
@@ -61,7 +61,7 @@ public:
|
||||
CurlSocket(const CurlSocket &) = delete;
|
||||
CurlSocket &operator=(const CurlSocket &) = delete;
|
||||
|
||||
auto &GetEventLoop() const noexcept {
|
||||
[[nodiscard]] auto &GetEventLoop() const noexcept {
|
||||
return socket_event.GetEventLoop();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
void *userp, void *socketp) noexcept;
|
||||
|
||||
private:
|
||||
SocketDescriptor GetSocket() const noexcept {
|
||||
[[nodiscard]] SocketDescriptor GetSocket() const noexcept {
|
||||
return socket_event.GetSocket();
|
||||
}
|
||||
|
||||
|
@@ -40,7 +40,7 @@ CurlGlobal *CurlInit::instance;
|
||||
|
||||
CurlInit::CurlInit(EventLoop &event_loop)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (++ref > 1) {
|
||||
assert(&event_loop == &instance->GetEventLoop());
|
||||
return;
|
||||
@@ -56,7 +56,7 @@ CurlInit::CurlInit(EventLoop &event_loop)
|
||||
|
||||
CurlInit::~CurlInit() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (--ref > 0)
|
||||
return;
|
||||
|
||||
|
@@ -32,8 +32,8 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* OO wrapper for "struct curl_slist *".
|
||||
|
@@ -35,8 +35,8 @@
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace ODBus {
|
||||
|
||||
|
@@ -44,7 +44,7 @@ try {
|
||||
#ifdef HAVE_ICU
|
||||
const auto u = UCharFromUTF8(src);
|
||||
if (u.IsNull())
|
||||
return AllocatedString(src);
|
||||
return {src};
|
||||
|
||||
AllocatedArray<UChar> folded(u.size() * 2U);
|
||||
|
||||
@@ -54,7 +54,7 @@ try {
|
||||
U_FOLD_CASE_DEFAULT,
|
||||
&error_code);
|
||||
if (folded_length == 0 || error_code != U_ZERO_ERROR)
|
||||
return AllocatedString(src);
|
||||
return {src};
|
||||
|
||||
folded.SetSize(folded_length);
|
||||
return UCharToUTF8({folded.begin(), folded.size()});
|
||||
@@ -63,7 +63,7 @@ try {
|
||||
#error not implemented
|
||||
#endif
|
||||
} catch (...) {
|
||||
return AllocatedString(src);
|
||||
return {src};
|
||||
}
|
||||
|
||||
#endif /* HAVE_ICU_CASE_FOLD */
|
||||
|
@@ -105,7 +105,7 @@ AllocatedString
|
||||
IcuConverter::ToUTF8(std::string_view s) const
|
||||
{
|
||||
#ifdef HAVE_ICU
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
ucnv_resetToUnicode(converter);
|
||||
|
||||
@@ -133,7 +133,7 @@ AllocatedString
|
||||
IcuConverter::FromUTF8(std::string_view s) const
|
||||
{
|
||||
#ifdef HAVE_ICU
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
const auto u = UCharFromUTF8(s);
|
||||
|
||||
@@ -152,7 +152,7 @@ IcuConverter::FromUTF8(std::string_view s) const
|
||||
throw std::runtime_error(fmt::format(FMT_STRING("Failed to convert from Unicode: {}"),
|
||||
u_errorName(code)));
|
||||
|
||||
return AllocatedString({buffer, size_t(target - buffer)});
|
||||
return {{buffer, size_t(target - buffer)}};
|
||||
|
||||
#elif defined(HAVE_ICONV)
|
||||
return DoConvert(from_utf8, s);
|
||||
|
@@ -54,7 +54,7 @@ UCharToUTF8(std::basic_string_view<UChar> src)
|
||||
/* worst-case estimate */
|
||||
size_t dest_capacity = 4 * src.size();
|
||||
|
||||
std::unique_ptr<char[]> dest(new char[dest_capacity + 1]);
|
||||
auto dest = std::make_unique<char[]>(dest_capacity + 1);
|
||||
|
||||
UErrorCode error_code = U_ZERO_ERROR;
|
||||
int32_t dest_length;
|
||||
|
@@ -68,7 +68,7 @@ private:
|
||||
* thread.
|
||||
*/
|
||||
void LockSetFinished() noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
finished = true;
|
||||
cond.notify_one();
|
||||
}
|
||||
|
49
src/lib/pcre/Error.cxx
Normal file
49
src/lib/pcre/Error.cxx
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.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 "Error.hxx"
|
||||
|
||||
#include <pcre2.h>
|
||||
|
||||
namespace Pcre {
|
||||
|
||||
ErrorCategory error_category;
|
||||
|
||||
std::string
|
||||
ErrorCategory::message(int condition) const
|
||||
{
|
||||
PCRE2_UCHAR8 buffer[256];
|
||||
pcre2_get_error_message_8(condition, buffer, std::size(buffer));
|
||||
return std::string{(const char *)buffer};
|
||||
}
|
||||
|
||||
} // namespace Pcre
|
56
src/lib/pcre/Error.hxx
Normal file
56
src/lib/pcre/Error.hxx
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace Pcre {
|
||||
|
||||
class ErrorCategory final : public std::error_category {
|
||||
public:
|
||||
const char *name() const noexcept override {
|
||||
return "pcre2";
|
||||
}
|
||||
|
||||
std::string message(int condition) const override;
|
||||
};
|
||||
|
||||
extern ErrorCategory error_category;
|
||||
|
||||
inline std::system_error
|
||||
MakeError(int error, const char *msg) noexcept
|
||||
{
|
||||
return std::system_error(error, error_category, msg);
|
||||
}
|
||||
|
||||
} // namespace Pcre
|
127
src/lib/pcre/MatchData.hxx
Normal file
127
src/lib/pcre/MatchData.hxx
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pcre2.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
class MatchData {
|
||||
friend class RegexPointer;
|
||||
|
||||
pcre2_match_data_8 *match_data = nullptr;
|
||||
const char *s;
|
||||
PCRE2_SIZE *ovector;
|
||||
std::size_t n;
|
||||
|
||||
explicit MatchData(pcre2_match_data_8 *_md, const char *_s) noexcept
|
||||
:match_data(_md), s(_s),
|
||||
ovector(pcre2_get_ovector_pointer_8(match_data))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
MatchData() = default;
|
||||
|
||||
MatchData(MatchData &&src) noexcept
|
||||
:match_data(std::exchange(src.match_data, nullptr)),
|
||||
s(src.s), ovector(src.ovector), n(src.n) {}
|
||||
|
||||
~MatchData() noexcept {
|
||||
if (match_data != nullptr)
|
||||
pcre2_match_data_free_8(match_data);
|
||||
}
|
||||
|
||||
MatchData &operator=(MatchData &&src) noexcept {
|
||||
using std::swap;
|
||||
swap(match_data, src.match_data);
|
||||
swap(s, src.s);
|
||||
swap(ovector, src.ovector);
|
||||
swap(n, src.n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr operator bool() const noexcept {
|
||||
return match_data != nullptr;
|
||||
}
|
||||
|
||||
constexpr std::size_t size() const noexcept {
|
||||
assert(*this);
|
||||
|
||||
return static_cast<std::size_t>(n);
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
constexpr std::string_view operator[](std::size_t i) const noexcept {
|
||||
assert(*this);
|
||||
assert(i < size());
|
||||
|
||||
int start = ovector[2 * i];
|
||||
if (start < 0)
|
||||
return {};
|
||||
|
||||
int end = ovector[2 * i + 1];
|
||||
assert(end >= start);
|
||||
|
||||
return { s + start, std::size_t(end - start) };
|
||||
}
|
||||
|
||||
static constexpr std::size_t npos = ~std::size_t{};
|
||||
|
||||
[[gnu::pure]]
|
||||
constexpr std::size_t GetCaptureStart(std::size_t i) const noexcept {
|
||||
assert(*this);
|
||||
assert(i < size());
|
||||
|
||||
int start = ovector[2 * i];
|
||||
if (start < 0)
|
||||
return npos;
|
||||
|
||||
return std::size_t(start);
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
constexpr std::size_t GetCaptureEnd(std::size_t i) const noexcept {
|
||||
assert(*this);
|
||||
assert(i < size());
|
||||
|
||||
int end = ovector[2 * i + 1];
|
||||
if (end < 0)
|
||||
return npos;
|
||||
|
||||
return std::size_t(end);
|
||||
}
|
||||
};
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2018 Content Management AG
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.com>
|
||||
@@ -30,27 +30,17 @@
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef REGEX_POINTER_HXX
|
||||
#define REGEX_POINTER_HXX
|
||||
#pragma once
|
||||
|
||||
#include "util/StringView.hxx"
|
||||
#include "util/Compiler.h"
|
||||
#include "MatchData.hxx"
|
||||
|
||||
#include <pcre.h>
|
||||
#include <pcre2.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#if GCC_CHECK_VERSION(11,0)
|
||||
#pragma GCC diagnostic push
|
||||
/* bogus GCC 11 warning "ovector may be used uninitialized" in the
|
||||
ovector.size() call */
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
#include <string_view>
|
||||
|
||||
class RegexPointer {
|
||||
protected:
|
||||
pcre *re = nullptr;
|
||||
pcre_extra *extra = nullptr;
|
||||
pcre2_code_8 *re = nullptr;
|
||||
|
||||
unsigned n_capture = 0;
|
||||
|
||||
@@ -60,18 +50,28 @@ public:
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
bool Match(StringView s) const noexcept {
|
||||
/* we don't need the data written to ovector, but PCRE can
|
||||
omit internal allocations if we pass a buffer to
|
||||
pcre_exec() */
|
||||
std::array<int, 16> ovector;
|
||||
return pcre_exec(re, extra, s.data, s.size,
|
||||
0, 0, &ovector.front(), ovector.size()) >= 0;
|
||||
MatchData Match(std::string_view s) const noexcept {
|
||||
MatchData match_data{
|
||||
pcre2_match_data_create_from_pattern_8(re, nullptr),
|
||||
s.data(),
|
||||
};
|
||||
|
||||
int n = pcre2_match_8(re, (PCRE2_SPTR8)s.data(), s.size(),
|
||||
0, 0,
|
||||
match_data.match_data, nullptr);
|
||||
if (n < 0)
|
||||
/* no match (or error) */
|
||||
return {};
|
||||
|
||||
match_data.n = n;
|
||||
|
||||
if (n_capture >= match_data.n)
|
||||
/* in its return value, PCRE omits mismatching
|
||||
optional captures if (and only if) they are
|
||||
the last capture; this kludge works around
|
||||
this */
|
||||
match_data.n = n_capture + 1;
|
||||
|
||||
return match_data;
|
||||
}
|
||||
};
|
||||
|
||||
#if GCC_CHECK_VERSION(11,0)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2018 Content Management AG
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.com>
|
||||
@@ -31,41 +31,40 @@
|
||||
*/
|
||||
|
||||
#include "UniqueRegex.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
#include "Error.hxx"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
UniqueRegex::Compile(const char *pattern, bool anchored, bool capture,
|
||||
bool caseless)
|
||||
{
|
||||
constexpr int default_options = PCRE_DOTALL|PCRE_NO_AUTO_CAPTURE|PCRE_UTF8;
|
||||
constexpr int default_options = PCRE2_DOTALL|PCRE2_NO_AUTO_CAPTURE;
|
||||
|
||||
int options = default_options;
|
||||
uint32_t options = default_options;
|
||||
if (anchored)
|
||||
options |= PCRE_ANCHORED;
|
||||
options |= PCRE2_ANCHORED;
|
||||
if (capture)
|
||||
options &= ~PCRE_NO_AUTO_CAPTURE;
|
||||
options &= ~PCRE2_NO_AUTO_CAPTURE;
|
||||
if (caseless)
|
||||
options |= PCRE_CASELESS;
|
||||
options |= PCRE2_CASELESS;
|
||||
|
||||
const char *error_string;
|
||||
int error_offset;
|
||||
re = pcre_compile(pattern, options, &error_string, &error_offset, nullptr);
|
||||
if (re == nullptr)
|
||||
throw FormatRuntimeError("Error in regex at offset %d: %s",
|
||||
error_offset, error_string);
|
||||
|
||||
int study_options = 0;
|
||||
#ifdef PCRE_CONFIG_JIT
|
||||
study_options |= PCRE_STUDY_JIT_COMPILE;
|
||||
#endif
|
||||
extra = pcre_study(re, study_options, &error_string);
|
||||
if (extra == nullptr && error_string != nullptr) {
|
||||
pcre_free(re);
|
||||
re = nullptr;
|
||||
throw FormatRuntimeError("Regex study error: %s", error_string);
|
||||
int error_number;
|
||||
PCRE2_SIZE error_offset;
|
||||
re = pcre2_compile_8(PCRE2_SPTR8(pattern),
|
||||
PCRE2_ZERO_TERMINATED, options,
|
||||
&error_number, &error_offset,
|
||||
nullptr);
|
||||
if (re == nullptr) {
|
||||
char msg[256];
|
||||
snprintf(msg, sizeof(msg), "Error in regex at offset %zu",
|
||||
error_offset);
|
||||
throw Pcre::MakeError(error_number, msg);
|
||||
}
|
||||
|
||||
int n;
|
||||
if (capture && pcre_fullinfo(re, extra, PCRE_INFO_CAPTURECOUNT, &n) == 0)
|
||||
pcre2_jit_compile_8(re, PCRE2_JIT_COMPLETE);
|
||||
|
||||
if (int n; capture &&
|
||||
pcre2_pattern_info_8(re, PCRE2_INFO_CAPTURECOUNT, &n) == 0)
|
||||
n_capture = n;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2018 Content Management AG
|
||||
* Copyright 2007-2021 CM4all GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.com>
|
||||
@@ -30,15 +30,12 @@
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UNIQUE_REGEX_HXX
|
||||
#define UNIQUE_REGEX_HXX
|
||||
#pragma once
|
||||
|
||||
#include "RegexPointer.hxx"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
class UniqueRegex : public RegexPointer {
|
||||
public:
|
||||
UniqueRegex() = default;
|
||||
@@ -50,29 +47,22 @@ public:
|
||||
|
||||
UniqueRegex(UniqueRegex &&src) noexcept:RegexPointer(src) {
|
||||
src.re = nullptr;
|
||||
src.extra = nullptr;
|
||||
}
|
||||
|
||||
~UniqueRegex() noexcept {
|
||||
pcre_free(re);
|
||||
#ifdef PCRE_CONFIG_JIT
|
||||
pcre_free_study(extra);
|
||||
#else
|
||||
pcre_free(extra);
|
||||
#endif
|
||||
if (re != nullptr)
|
||||
pcre2_code_free_8(re);
|
||||
}
|
||||
|
||||
UniqueRegex &operator=(UniqueRegex &&src) {
|
||||
UniqueRegex &operator=(UniqueRegex &&src) noexcept {
|
||||
using std::swap;
|
||||
swap<RegexPointer>(*this, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws std::runtime_error on error.
|
||||
* Throws Pcre::Error on error.
|
||||
*/
|
||||
void Compile(const char *pattern, bool anchored, bool capture,
|
||||
bool caseless);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,11 +1,17 @@
|
||||
pcre_dep = dependency('libpcre', required: get_option('pcre'))
|
||||
pcre_dep = dependency('libpcre2-8', required: get_option('pcre'))
|
||||
conf.set('HAVE_PCRE', pcre_dep.found())
|
||||
if not pcre_dep.found()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
pcre_dep = declare_dependency(
|
||||
compile_args: '-DPCRE2_CODE_UNIT_WIDTH=0',
|
||||
dependencies: pcre_dep,
|
||||
)
|
||||
|
||||
pcre = static_library(
|
||||
'pcre',
|
||||
'Error.cxx',
|
||||
'UniqueRegex.cxx',
|
||||
include_directories: inc,
|
||||
dependencies: [
|
||||
|
@@ -31,4 +31,4 @@ ErrorCategory::message(int condition) const
|
||||
return spa_strerror(condition);
|
||||
}
|
||||
|
||||
} // namespace Avahi
|
||||
} // namespace PipeWire
|
||||
|
@@ -45,7 +45,7 @@ SmbclientContext::New()
|
||||
SMBCCTX *ctx;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(global_mutex);
|
||||
const std::scoped_lock<Mutex> protect(global_mutex);
|
||||
ctx = smbc_new_context();
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
~SmbclientContext() noexcept {
|
||||
if (ctx != nullptr) {
|
||||
const std::lock_guard<Mutex> protect(global_mutex);
|
||||
const std::scoped_lock<Mutex> protect(global_mutex);
|
||||
smbc_free_context(ctx, 1);
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ UpnpClientGlobalInit(const char* iface)
|
||||
UpnpGlobalInit(iface);
|
||||
|
||||
try {
|
||||
const std::lock_guard<Mutex> protect(upnp_client_init_mutex);
|
||||
const std::scoped_lock<Mutex> protect(upnp_client_init_mutex);
|
||||
if (upnp_client_ref == 0)
|
||||
DoInit();
|
||||
} catch (...) {
|
||||
@@ -78,7 +78,7 @@ void
|
||||
UpnpClientGlobalFinish() noexcept
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(upnp_client_init_mutex);
|
||||
const std::scoped_lock<Mutex> protect(upnp_client_init_mutex);
|
||||
|
||||
assert(upnp_client_ref > 0);
|
||||
if (--upnp_client_ref == 0)
|
||||
|
@@ -41,14 +41,14 @@ UPnPDeviceDirectory::Downloader::Downloader(UPnPDeviceDirectory &_parent,
|
||||
expires(std::chrono::seconds(UpnpDiscovery_get_Expires(&disco))),
|
||||
request(*parent.curl, url.c_str(), *this)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(parent.mutex);
|
||||
const std::scoped_lock<Mutex> protect(parent.mutex);
|
||||
parent.downloaders.push_back(*this);
|
||||
}
|
||||
|
||||
void
|
||||
UPnPDeviceDirectory::Downloader::Destroy() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(parent.mutex);
|
||||
const std::scoped_lock<Mutex> protect(parent.mutex);
|
||||
unlink();
|
||||
delete this;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ AnnounceLostUPnP(UPnPDiscoveryListener &listener, const UPnPDevice &device)
|
||||
inline void
|
||||
UPnPDeviceDirectory::LockAdd(ContentDirectoryDescriptor &&d)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
for (auto &i : directories) {
|
||||
if (i.id == d.id) {
|
||||
@@ -157,7 +157,7 @@ UPnPDeviceDirectory::LockAdd(ContentDirectoryDescriptor &&d)
|
||||
inline void
|
||||
UPnPDeviceDirectory::LockRemove(const std::string &id)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
for (auto i = directories.begin(), end = directories.end();
|
||||
i != end; ++i) {
|
||||
@@ -265,10 +265,10 @@ UPnPDeviceDirectory::UPnPDeviceDirectory(EventLoop &event_loop,
|
||||
|
||||
UPnPDeviceDirectory::~UPnPDeviceDirectory() noexcept
|
||||
{
|
||||
BlockingCall(GetEventLoop(), [this](){
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
downloaders.clear_and_dispose(DeleteDisposer());
|
||||
});
|
||||
BlockingCall(GetEventLoop(), [this]() {
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
downloaders.clear_and_dispose(DeleteDisposer());
|
||||
});
|
||||
}
|
||||
|
||||
inline EventLoop &
|
||||
@@ -308,7 +308,7 @@ UPnPDeviceDirectory::Search()
|
||||
std::vector<ContentDirectoryService>
|
||||
UPnPDeviceDirectory::GetDirectories()
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
ExpireDevices();
|
||||
|
||||
@@ -327,7 +327,7 @@ UPnPDeviceDirectory::GetDirectories()
|
||||
ContentDirectoryService
|
||||
UPnPDeviceDirectory::GetServer(std::string_view friendly_name)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
ExpireDevices();
|
||||
|
||||
@@ -339,8 +339,7 @@ UPnPDeviceDirectory::GetServer(std::string_view friendly_name)
|
||||
|
||||
for (const auto &service : device.services)
|
||||
if (isCDService(service.serviceType.c_str()))
|
||||
return ContentDirectoryService(device,
|
||||
service);
|
||||
return {device, service};
|
||||
}
|
||||
|
||||
throw std::runtime_error("Server not found");
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "lib/curl/Handler.hxx"
|
||||
#include "lib/curl/Request.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "event/DeferEvent.hxx"
|
||||
#include "event/InjectEvent.hxx"
|
||||
#include "util/IntrusiveList.hxx"
|
||||
|
||||
#include <list>
|
||||
@@ -81,7 +81,7 @@ class UPnPDeviceDirectory final : UpnpCallback {
|
||||
class Downloader final
|
||||
: public IntrusiveListHook, CurlResponseHandler
|
||||
{
|
||||
DeferEvent defer_start_event;
|
||||
InjectEvent defer_start_event;
|
||||
|
||||
UPnPDeviceDirectory &parent;
|
||||
|
||||
|
@@ -56,7 +56,7 @@ DoInit(const char* iface)
|
||||
void
|
||||
UpnpGlobalInit(const char* iface)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(upnp_init_mutex);
|
||||
const std::scoped_lock<Mutex> protect(upnp_init_mutex);
|
||||
|
||||
if (upnp_ref == 0)
|
||||
DoInit(iface);
|
||||
@@ -67,7 +67,7 @@ UpnpGlobalInit(const char* iface)
|
||||
void
|
||||
UpnpGlobalFinish() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(upnp_init_mutex);
|
||||
const std::scoped_lock<Mutex> protect(upnp_init_mutex);
|
||||
|
||||
assert(upnp_ref > 0);
|
||||
|
||||
|
@@ -21,12 +21,12 @@
|
||||
#include "FlacAudioFormat.hxx"
|
||||
#include "ScanVorbisComment.hxx"
|
||||
#include "pcm/CheckAudioFormat.hxx"
|
||||
#include "MixRampInfo.hxx"
|
||||
#include "tag/Handler.hxx"
|
||||
#include "tag/Builder.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "tag/ReplayGain.hxx"
|
||||
#include "tag/MixRamp.hxx"
|
||||
#include "tag/MixRampInfo.hxx"
|
||||
#include "tag/MixRampParser.hxx"
|
||||
#include "ReplayGainInfo.hxx"
|
||||
#include "util/StringView.hxx"
|
||||
|
||||
|
@@ -36,8 +36,7 @@ ScanVorbisPicture(StringView value, TagHandler &handler) noexcept
|
||||
return;
|
||||
|
||||
size_t debase64_size = CalculateBase64OutputSize(value.size);
|
||||
std::unique_ptr<uint8_t[]> debase64_buffer;
|
||||
debase64_buffer.reset(new uint8_t[debase64_size]);
|
||||
auto debase64_buffer = std::make_unique<uint8_t[]>(debase64_size);
|
||||
|
||||
try {
|
||||
debase64_size =
|
||||
|
@@ -32,7 +32,7 @@
|
||||
|
||||
#include <yajl/yajl_parse.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace Yajl {
|
||||
|
||||
|
@@ -52,7 +52,7 @@ mixer_open(Mixer *mixer)
|
||||
{
|
||||
assert(mixer != nullptr);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mixer->mutex);
|
||||
const std::scoped_lock<Mutex> protect(mixer->mutex);
|
||||
|
||||
if (mixer->open)
|
||||
return;
|
||||
@@ -82,7 +82,7 @@ mixer_close(Mixer *mixer)
|
||||
{
|
||||
assert(mixer != nullptr);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mixer->mutex);
|
||||
const std::scoped_lock<Mutex> protect(mixer->mutex);
|
||||
|
||||
if (mixer->open)
|
||||
mixer_close_internal(mixer);
|
||||
@@ -119,7 +119,7 @@ mixer_get_volume(Mixer *mixer)
|
||||
if (mixer->plugin.global && !mixer->failed)
|
||||
mixer_open(mixer);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mixer->mutex);
|
||||
const std::scoped_lock<Mutex> protect(mixer->mutex);
|
||||
|
||||
if (mixer->open) {
|
||||
try {
|
||||
@@ -143,7 +143,7 @@ mixer_set_volume(Mixer *mixer, unsigned volume)
|
||||
if (mixer->plugin.global && !mixer->failed)
|
||||
mixer_open(mixer);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mixer->mutex);
|
||||
const std::scoped_lock<Mutex> protect(mixer->mutex);
|
||||
|
||||
if (mixer->open)
|
||||
mixer->SetVolume(volume);
|
||||
|
@@ -128,13 +128,13 @@ private:
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
double GetNormalizedVolume() const noexcept {
|
||||
[[nodiscard]] double GetNormalizedVolume() const noexcept {
|
||||
return get_normalized_playback_volume(elem,
|
||||
SND_MIXER_SCHN_FRONT_LEFT);
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
unsigned GetPercentVolume() const noexcept {
|
||||
[[nodiscard]] unsigned GetPercentVolume() const noexcept {
|
||||
return NormalizedToPercent(GetNormalizedVolume());
|
||||
}
|
||||
|
||||
|
@@ -99,7 +99,7 @@ void
|
||||
SmbclientNeighborExplorer::Close() noexcept
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
quit = true;
|
||||
cond.notify_one();
|
||||
}
|
||||
@@ -110,7 +110,7 @@ SmbclientNeighborExplorer::Close() noexcept
|
||||
NeighborExplorer::List
|
||||
SmbclientNeighborExplorer::GetList() const noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@@ -175,7 +175,7 @@ UdisksNeighborExplorer::Close() noexcept
|
||||
NeighborExplorer::List
|
||||
UdisksNeighborExplorer::GetList() const noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
|
||||
NeighborExplorer::List result;
|
||||
|
||||
@@ -192,7 +192,7 @@ UdisksNeighborExplorer::Insert(UDisks2::Object &&o) noexcept
|
||||
const NeighborInfo info = ToNeighborInfo(o);
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
auto i = by_uri.emplace(o.GetUri(), info);
|
||||
if (!i.second)
|
||||
i.first->second = info;
|
||||
|
@@ -30,9 +30,10 @@
|
||||
#include "AddressInfo.hxx"
|
||||
#include "Features.hxx"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
|
||||
static constexpr int address_family_ranking[] = {
|
||||
static constexpr auto address_family_ranking = std::array {
|
||||
#ifdef HAVE_UN
|
||||
AF_LOCAL,
|
||||
#endif
|
||||
|
@@ -187,11 +187,18 @@ public:
|
||||
return address.sin_family != AF_UNSPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port number in network byte order
|
||||
*/
|
||||
constexpr uint16_t GetPortBE() const noexcept {
|
||||
return address.sin_port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port number in host byte order
|
||||
*/
|
||||
constexpr uint16_t GetPort() const noexcept {
|
||||
return FromBE16(address.sin_port);
|
||||
return FromBE16(GetPortBE());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "SocketDescriptor.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
class StaticSocketAddress;
|
||||
|
@@ -79,7 +79,7 @@ AudioOutputControl::Steal() noexcept
|
||||
StopThread();
|
||||
|
||||
/* now we can finally remove it */
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return std::exchange(output, nullptr);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ AudioOutputControl::ReplaceDummy(std::unique_ptr<FilteredAudioOutput> new_output
|
||||
assert(new_output);
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
output = std::move(new_output);
|
||||
enabled = _enabled;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ AudioOutputControl::SetAttribute(std::string &&attribute_name,
|
||||
bool
|
||||
AudioOutputControl::LockSetEnabled(bool new_value) noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (new_value == enabled)
|
||||
return false;
|
||||
@@ -158,7 +158,7 @@ AudioOutputControl::LockSetEnabled(bool new_value) noexcept
|
||||
bool
|
||||
AudioOutputControl::LockToggleEnabled() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return enabled = !enabled;
|
||||
}
|
||||
|
||||
@@ -342,14 +342,14 @@ AudioOutputControl::IsChunkConsumed(const MusicChunk &chunk) const noexcept
|
||||
bool
|
||||
AudioOutputControl::LockIsChunkConsumed(const MusicChunk &chunk) const noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return IsChunkConsumed(chunk);
|
||||
}
|
||||
|
||||
void
|
||||
AudioOutputControl::LockPlay() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
assert(allow_play);
|
||||
|
||||
@@ -371,7 +371,7 @@ AudioOutputControl::LockPauseAsync() noexcept
|
||||
if (output)
|
||||
output->Interrupt();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
assert(allow_play);
|
||||
if (IsOpen())
|
||||
@@ -381,7 +381,7 @@ AudioOutputControl::LockPauseAsync() noexcept
|
||||
void
|
||||
AudioOutputControl::LockDrainAsync() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
assert(allow_play);
|
||||
if (IsOpen())
|
||||
@@ -394,7 +394,7 @@ AudioOutputControl::LockCancelAsync() noexcept
|
||||
if (output)
|
||||
output->Interrupt();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
if (IsOpen()) {
|
||||
allow_play = false;
|
||||
@@ -405,7 +405,7 @@ AudioOutputControl::LockCancelAsync() noexcept
|
||||
void
|
||||
AudioOutputControl::LockAllowPlay() noexcept
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
|
||||
allow_play = true;
|
||||
if (IsOpen())
|
||||
@@ -457,7 +457,7 @@ AudioOutputControl::BeginDestroy() noexcept
|
||||
if (output)
|
||||
output->Interrupt();
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
if (!killed) {
|
||||
killed = true;
|
||||
CommandAsync(Command::KILL);
|
||||
|
@@ -405,7 +405,7 @@ public:
|
||||
void EnableDisableAsync();
|
||||
|
||||
void LockEnableDisableAsync() {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
EnableDisableAsync();
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ public:
|
||||
* Locking wrapper for ClearTailChunk().
|
||||
*/
|
||||
void LockClearTailChunk(const MusicChunk &chunk) noexcept {
|
||||
const std::lock_guard<Mutex> lock(mutex);
|
||||
const std::scoped_lock<Mutex> lock(mutex);
|
||||
ClearTailChunk(chunk);
|
||||
}
|
||||
|
||||
|
@@ -229,7 +229,7 @@ MultipleOutputs::Open(const AudioFormat audio_format)
|
||||
std::exception_ptr first_error;
|
||||
|
||||
for (const auto &ao : outputs) {
|
||||
const std::lock_guard<Mutex> lock(ao->mutex);
|
||||
const std::scoped_lock<Mutex> lock(ao->mutex);
|
||||
|
||||
if (ao->IsEnabled())
|
||||
enabled = true;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user