Compare commits
214 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1f28790476 | ||
![]() |
c8dae95eff | ||
![]() |
547a084c7e | ||
![]() |
493677ff81 | ||
![]() |
6b430ba271 | ||
![]() |
bc6924d303 | ||
![]() |
02b00f9146 | ||
![]() |
e807ed5870 | ||
![]() |
f08944253b | ||
![]() |
792d6584b9 | ||
![]() |
7b45d01462 | ||
![]() |
5c17b2966a | ||
![]() |
0c54f29446 | ||
![]() |
9c3cf39fdd | ||
![]() |
d2fb229685 | ||
![]() |
f55bc6682f | ||
![]() |
6857286b42 | ||
![]() |
c0d5bd2048 | ||
![]() |
666e5d7904 | ||
![]() |
3613407ac5 | ||
![]() |
c32dceb4d4 | ||
![]() |
5573e78364 | ||
![]() |
807a19889f | ||
![]() |
df7242de91 | ||
![]() |
d62426f168 | ||
![]() |
1714cf3417 | ||
![]() |
1080c917be | ||
![]() |
8eb3164878 | ||
![]() |
915c5442d1 | ||
![]() |
be0360d5e8 | ||
![]() |
4d6ae6ffdd | ||
![]() |
ecee6f415b | ||
![]() |
47680f936b | ||
![]() |
2d7181105d | ||
![]() |
9bdc75524b | ||
![]() |
2f6ceb4949 | ||
![]() |
cd933aa35f | ||
![]() |
138738075b | ||
![]() |
2ee57f9b0d | ||
![]() |
5a5655b790 | ||
![]() |
b88d1e6820 | ||
![]() |
19d2864c34 | ||
![]() |
29e3a17f26 | ||
![]() |
252e9f736f | ||
![]() |
5d08988dda | ||
![]() |
47ca4246aa | ||
![]() |
f8338d4f00 | ||
![]() |
5cf6032c90 | ||
![]() |
8d8b77412d | ||
![]() |
fd9114e7e2 | ||
![]() |
a3fba2f8f7 | ||
![]() |
e2b671f1b2 | ||
![]() |
2a35fbe29e | ||
![]() |
81cde72fd0 | ||
![]() |
bf9ffba4f7 | ||
![]() |
c975d8b943 | ||
![]() |
2730f91872 | ||
![]() |
97ca85e155 | ||
![]() |
39bb4c5871 | ||
![]() |
bdceb90c59 | ||
![]() |
8bd1b5228c | ||
![]() |
a009e95afd | ||
![]() |
32aafb3572 | ||
![]() |
b577783cf0 | ||
![]() |
aa7b872a14 | ||
![]() |
c6f7f57776 | ||
![]() |
106ad08cd2 | ||
![]() |
0341ca1b6a | ||
![]() |
7581ea55db | ||
![]() |
fc9cee38d8 | ||
![]() |
b175e4128d | ||
![]() |
97b07798b0 | ||
![]() |
112fcd206d | ||
![]() |
11d1f56062 | ||
![]() |
bd840d4638 | ||
![]() |
c3d393f214 | ||
![]() |
f88fc0ca1a | ||
![]() |
fb8d8242ab | ||
![]() |
f2a3dfd700 | ||
![]() |
85f9863e0a | ||
![]() |
83572701f4 | ||
![]() |
fa7d7e9187 | ||
![]() |
f818cde32c | ||
![]() |
9da93cd887 | ||
![]() |
026e7ea32a | ||
![]() |
9659d19718 | ||
![]() |
50d35c9677 | ||
![]() |
4260e78861 | ||
![]() |
7342ae2e33 | ||
![]() |
35dbc1a90c | ||
![]() |
c7a4355153 | ||
![]() |
33a84a8ca2 | ||
![]() |
1d04490ed3 | ||
![]() |
4a30c2d79c | ||
![]() |
83072d6b9c | ||
![]() |
c779fc37eb | ||
![]() |
e08c13ad7e | ||
![]() |
2c82a6b2e0 | ||
![]() |
3929f17aef | ||
![]() |
ee39af3419 | ||
![]() |
3882a5a263 | ||
![]() |
ac06088948 | ||
![]() |
a757eebfbb | ||
![]() |
2be4f89555 | ||
![]() |
4a5c7d8261 | ||
![]() |
f591193dda | ||
![]() |
434869900e | ||
![]() |
2aed7378cc | ||
![]() |
71cd6e6248 | ||
![]() |
c83294916a | ||
![]() |
603bbe0afd | ||
![]() |
c361e235eb | ||
![]() |
8a59493d96 | ||
![]() |
7ef86cbf9f | ||
![]() |
c9530118a4 | ||
![]() |
878d9abeb7 | ||
![]() |
2d705efe1c | ||
![]() |
aeaef85507 | ||
![]() |
ebae25d175 | ||
![]() |
5ad1a01d7a | ||
![]() |
8f84e1befd | ||
![]() |
9975905faf | ||
![]() |
233184568c | ||
![]() |
59da778009 | ||
![]() |
108ce95b7c | ||
![]() |
86e9ed5f3a | ||
![]() |
fbecb05bf4 | ||
![]() |
4983703375 | ||
![]() |
3856224df9 | ||
![]() |
6d4bedfc56 | ||
![]() |
bea821f194 | ||
![]() |
4e276256c0 | ||
![]() |
d0f9062b56 | ||
![]() |
b9cc036703 | ||
![]() |
4e9b88559b | ||
![]() |
3452682a42 | ||
![]() |
9262b24504 | ||
![]() |
a5fa43b526 | ||
![]() |
8681a3d74c | ||
![]() |
f9c4d88b12 | ||
![]() |
799032505e | ||
![]() |
c8f174ac92 | ||
![]() |
047e169f3e | ||
![]() |
687327c9e8 | ||
![]() |
26dc37bd76 | ||
![]() |
c693e4aa64 | ||
![]() |
acab731fef | ||
![]() |
7e4ba3cb72 | ||
![]() |
172c4d9c7d | ||
![]() |
bd5f6cbc7b | ||
![]() |
6fcd1c734b | ||
![]() |
eca097dbfb | ||
![]() |
51ffafa011 | ||
![]() |
8dca602346 | ||
![]() |
0ed24f3a05 | ||
![]() |
e25e0030e7 | ||
![]() |
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
NEWSandroid
doc
meson.buildpython/build
src
LocateUri.cxxLog.hxxLogBackend.cxxMapper.cxxMusicBuffer.cxxMusicBuffer.hxxMusicPipe.cxxMusicPipe.hxxPlaylistDatabase.cxxPlaylistDatabase.hxxPlaylistFile.cxxPlaylistSave.cxxRemoteTagCache.cxxSingleMode.hxxSongSave.cxxSongSave.hxxStateFile.cxxTagAny.cxxTagSave.cxx
apple
archive
client
command
config
db
DatabasePlaylist.cxx
plugins
meson.build
simple
DatabaseSave.cxxDatabaseSave.hxxDirectory.cxxDirectorySave.cxxDirectorySave.hxxSimpleDatabasePlugin.cxx
upnp
update
decoder
encoder
event
filter
fs
input
AsyncInputStream.cxxBufferingInputStream.cxxIcyInputStream.cxxInputStream.cxxInputStream.hxxReader.hxxThreadInputStream.cxx
cache
plugins
AlsaInputPlugin.cxxCdioParanoiaInputPlugin.cxxCurlInputPlugin.cxxCurlInputPlugin.hxxFileInputPlugin.cxxNfsInputPlugin.cxxQobuzClient.cxxQobuzClient.hxxQobuzErrorParser.cxxQobuzErrorParser.hxxQobuzInputPlugin.cxxQobuzLoginRequest.cxxQobuzLoginRequest.hxxQobuzTagScanner.cxxQobuzTagScanner.hxxQobuzTrackRequest.cxxQobuzTrackRequest.hxxUringInputPlugin.cxxmeson.build
io
BufferedOutputStream.cxxBufferedOutputStream.hxxBufferedReader.cxxBufferedReader.hxxFileOutputStream.cxxFileOutputStream.hxxFileReader.cxxFileReader.hxxLineReader.hxxOutputStream.hxxPeekReader.cxxPeekReader.hxxReader.hxxStdioOutputStream.hxxmeson.build
uring
lib
alsa
curl
Adapter.cxxAdapter.hxxDelegate.cxxDelegate.hxxEscape.cxxForm.cxxForm.hxxGlobal.cxxHandler.hxxHeaders.hxxInit.cxxRequest.cxxRequest.hxxSetup.cxxSetup.hxxSlist.hxxmeson.build
patches
dbus
icu
nfs
pcre
pipewire
smbclient
upnp
xiph
yajl
zlib
mixer
neighbor
net
output
Control.cxxControl.hxxMultipleOutputs.cxxMultipleOutputs.hxxState.cxx
plugins
pcm
player
playlist
plugins
protocol
queue
song
sticker
storage
tag
ApeLoader.cxxBuilder.cxxIcyMetaDataParser.cxxIcyMetaDataParser.hxxId3Load.cxxId3MixRamp.cxxId3MixRamp.hxxId3Picture.cxxMixRampInfo.hxxMixRampParser.cxxMixRampParser.hxxTag.cxxmeson.build
thread
util
subprojects
test
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
@@ -1,12 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: MaxK
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -18,5 +18,9 @@ about: Create a bug report
|
||||
<!-- Paste the output of "mpd --version" here -->
|
||||
|
||||
|
||||
## Configuration
|
||||
<!-- Paste your MPD configuration here -->
|
||||
|
||||
|
||||
## Log
|
||||
<!-- Paste relevant portions of the log file here (--verbose) -->
|
||||
|
9
.github/ISSUE_TEMPLATE/question.md
vendored
9
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about MPD
|
||||
---
|
||||
|
||||
<!-- Before you ask a question on GitHub, please read MPD's
|
||||
documentation. A copy is available at
|
||||
https://www.musicpd.org/doc/html/ -->
|
||||
## Question
|
155
.github/workflows/build.yml
vendored
Normal file
155
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
---
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'android/**'
|
||||
- 'build/**'
|
||||
- 'doc/**'
|
||||
- 'python/**'
|
||||
- 'subprojects/**'
|
||||
- 'systemd/**'
|
||||
- 'win32/**'
|
||||
branches:
|
||||
- master
|
||||
- v0.23.x
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'android/**'
|
||||
- 'build/**'
|
||||
- 'doc/**'
|
||||
- 'python/**'
|
||||
- 'subprojects/**'
|
||||
- 'systemd/**'
|
||||
- 'win32/**'
|
||||
branches:
|
||||
- master
|
||||
- v0.23.x
|
||||
|
||||
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-get update
|
||||
sudo apt-get 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: build
|
||||
directory: output/full
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true -Dsystemd=enabled -Dpcre=enabled
|
||||
options: --verbose
|
||||
meson-version: 0.56.0
|
||||
|
||||
- name: Unit Tests
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: test
|
||||
directory: output/full
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true -Dsystemd=enabled -Dpcre=enabled
|
||||
options: --verbose
|
||||
meson-version: 0.56.0
|
||||
|
||||
- name: Mini Build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: build
|
||||
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
|
||||
options: --verbose
|
||||
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: Build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: build
|
||||
directory: output
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true
|
||||
options: --verbose
|
||||
meson-version: 0.56.0
|
||||
|
||||
- name: Unit Tests
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
action: test
|
||||
directory: output
|
||||
setup-options: -Ddocumentation=disabled -Dtest=true
|
||||
options: --verbose
|
||||
meson-version: 0.56.0
|
55
NEWS
55
NEWS
@@ -1,3 +1,58 @@
|
||||
ver 0.23.8 (2022/07/09)
|
||||
* storage
|
||||
- curl: fix crash if web server does not understand WebDAV
|
||||
* input
|
||||
- cdio_paranoia: fix crash if no drive was found
|
||||
- cdio_paranoia: faster cancellation
|
||||
- cdio_paranoia: don't scan for replay gain tags
|
||||
- pipewire: fix playback of very short tracks
|
||||
- pipewire: drop all buffers before manual song change
|
||||
- pipewire: fix stuttering after manual song change
|
||||
- snapcast: fix busy loop while paused
|
||||
- snapcast: fix stuttering after resuming playback
|
||||
* mixer
|
||||
- better error messages
|
||||
- alsa: fix setting volume before playback starts
|
||||
- pipewire: fix crash bug
|
||||
- pipewire: fix volume change events with PipeWire 0.3.53
|
||||
- pipewire: don't force initial volume=100%
|
||||
* support libfmt 9
|
||||
|
||||
ver 0.23.7 (2022/05/09)
|
||||
* database
|
||||
- upnp: support pupnp 1.14
|
||||
* decoder
|
||||
- ffmpeg: fix HLS seeking
|
||||
- opus: fix missing song length on high-latency files
|
||||
* output
|
||||
- shout: require at least libshout 2.4.0
|
||||
* mixer
|
||||
- pipewire: fix volume restore
|
||||
- software: update volume of disabled outputs
|
||||
* support libiconv
|
||||
|
||||
ver 0.23.6 (2022/03/14)
|
||||
* protocol
|
||||
- support filename "cover.webp" for "albumart" command
|
||||
- support "readcomments" and "readpicture" on CUE tracks
|
||||
* decoder
|
||||
- ffmpeg: fix end-of-file check (update stuck at empty files)
|
||||
- opus: fix "readpicture" on Opus files
|
||||
* output
|
||||
- pipewire: fix crash bug if setting volume before playback starts
|
||||
- wasapi: fix resume after pause
|
||||
|
||||
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="66"
|
||||
android:versionName="0.23.7">
|
||||
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29"/>
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
|
||||
<application android:allowBackup="true"
|
||||
android:debuggable="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:icon="@drawable/icon"
|
||||
android:banner="@drawable/icon"
|
||||
@@ -43,7 +42,6 @@
|
||||
<receiver android:name=".Receiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.HEADSET_PLUG" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<service android:name=".Main" android:process=":main"/>
|
||||
|
@@ -13,7 +13,7 @@ android_abi = sys.argv[3]
|
||||
configure_args = sys.argv[4:]
|
||||
|
||||
if not os.path.isfile(os.path.join(sdk_path, 'tools', 'android')):
|
||||
print("SDK not found in", ndk_path, file=sys.stderr)
|
||||
print("SDK not found in", sdk_path, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.isdir(ndk_path):
|
||||
|
54
android/gdb.sh
Executable file
54
android/gdb.sh
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script need the following modification in ANDROID_NDK in order to attach
|
||||
# to the good :main pid
|
||||
#--- a/prebuilt/linux-x86_64/bin/ndk-gdb.py
|
||||
#+++ b/prebuilt/linux-x86_64/bin/ndk-gdb.py
|
||||
#@@ -669,7 +669,7 @@
|
||||
# log("Sleeping for {} seconds.".format(args.delay))
|
||||
# time.sleep(args.delay)
|
||||
#
|
||||
#- pids = gdbrunner.get_pids(device, pkg_name)
|
||||
#+ pids = gdbrunner.get_pids(device, pkg_name + ":main")
|
||||
# if len(pids) == 0:
|
||||
# error("Failed to find running process '{}'".format(pkg_name))
|
||||
# if len(pids) > 1:
|
||||
|
||||
SCRIPT_PATH=$(dirname $0)
|
||||
BUILD_PATH="`pwd`"
|
||||
TMP_PATH="$BUILD_PATH/gdb"
|
||||
NDK_GDB_ARGS="--force"
|
||||
ANDROID_NDK=$1
|
||||
|
||||
if [ ! -f $ANDROID_NDK/source.properties ];then
|
||||
echo "usage: $0 ANDROID_NDK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f $BUILD_PATH/libmpd.so ];then
|
||||
echo "This script need to be executed from the android build directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "$TMP_PATH"
|
||||
mkdir -p "$TMP_PATH"
|
||||
|
||||
ANDROID_MANIFEST="$SCRIPT_PATH/AndroidManifest.xml"
|
||||
ABI=`ls "$BUILD_PATH/android/apk/apk/lib" --sort=time | head -n 1`
|
||||
|
||||
if [ ! -f "$ANDROID_MANIFEST" -o "$ABI" = "" ]; then
|
||||
echo "Invalid manifest/ABI, did you try building first ?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$TMP_PATH"/jni
|
||||
touch "$TMP_PATH"/jni/Android.mk
|
||||
echo "APP_ABI := $ABI" > "$TMP_PATH"/jni/Application.mk
|
||||
|
||||
DEST=obj/local/$ABI
|
||||
mkdir -p "$TMP_PATH/$DEST"
|
||||
|
||||
cp "$BUILD_PATH/libmpd.so" "$TMP_PATH/$DEST"
|
||||
cp "$ANDROID_MANIFEST" "$TMP_PATH"
|
||||
|
||||
(cd "$TMP_PATH" && bash $ANDROID_NDK/ndk-gdb $NDK_GDB_ARGS)
|
@@ -24,14 +24,13 @@ import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
@@ -200,24 +199,14 @@ public class Main extends Service implements Runnable {
|
||||
return;
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_HEADSET_PLUG);
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
||||
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
|
||||
registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!mPauseOnHeadphonesDisconnect) {
|
||||
if (!mPauseOnHeadphonesDisconnect)
|
||||
return;
|
||||
}
|
||||
|
||||
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
|
||||
if (intent.hasExtra("state") && intent.getIntExtra("state", 0) == 0)
|
||||
pause();
|
||||
} else {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (device.getBluetoothClass().hasService(BluetoothClass.Service.AUDIO))
|
||||
pause();
|
||||
}
|
||||
if (intent.getAction() == AudioManager.ACTION_AUDIO_BECOMING_NOISY)
|
||||
pause();
|
||||
}
|
||||
}, filter);
|
||||
|
||||
|
@@ -25,16 +25,18 @@ import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class Receiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d("Receiver", "onReceive: " + intent);
|
||||
if (intent.getAction() == "android.intent.action.BOOT_COMPLETED") {
|
||||
if (Settings.Preferences.getBoolean(context,
|
||||
Settings.Preferences.KEY_RUN_ON_BOOT, false)) {
|
||||
final boolean wakelock = Settings.Preferences.getBoolean(context,
|
||||
Settings.Preferences.KEY_WAKELOCK, false);
|
||||
Main.start(context, wakelock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d("Receiver", "onReceive: " + intent);
|
||||
if (intent.getAction() == "android.intent.action.BOOT_COMPLETED") {
|
||||
if (Settings.Preferences.getBoolean(context,
|
||||
Settings.Preferences.KEY_RUN_ON_BOOT,
|
||||
false)) {
|
||||
final boolean wakelock =
|
||||
Settings.Preferences.getBoolean(context,
|
||||
Settings.Preferences.KEY_WAKELOCK, false);
|
||||
Main.start(context, wakelock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ author = 'Max Kellermann'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.23.4'
|
||||
version = '0.23.8'
|
||||
# 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
|
||||
|
@@ -79,7 +79,7 @@
|
||||
# This setting sets the address for the daemon to listen on. Careful attention
|
||||
# should be paid if this is assigned to anything other than the default, any.
|
||||
# This setting can deny access to control of the daemon. Not effective if
|
||||
# systemd socket activiation is in use.
|
||||
# systemd socket activation is in use.
|
||||
#
|
||||
# For network
|
||||
#bind_to_address "any"
|
||||
@@ -185,7 +185,7 @@
|
||||
# cache_directory "~/.local/share/mpd/cache"
|
||||
#}
|
||||
#
|
||||
# An example of database config for a sattelite setup
|
||||
# An example of database config for a satellite setup
|
||||
#
|
||||
#music_directory "nfs://fileserver.local/srv/mp3"
|
||||
#database {
|
||||
|
@@ -479,7 +479,7 @@ Querying :program:`MPD`'s status
|
||||
current song in seconds, but with higher resolution.
|
||||
- ``duration`` [#since_0_20]_: Duration of the current song in seconds.
|
||||
- ``bitrate``: instantaneous bitrate in kbps
|
||||
- ``xfade``: ``crossfade`` in seconds
|
||||
- ``xfade``: ``crossfade`` in seconds (see :ref:`crossfading`)
|
||||
- ``mixrampdb``: ``mixramp`` threshold in dB
|
||||
- ``mixrampdelay``: ``mixrampdelay`` in seconds
|
||||
- ``audio``: The format emitted by the decoder plugin during
|
||||
@@ -519,17 +519,19 @@ Playback options
|
||||
.. _command_crossfade:
|
||||
|
||||
:command:`crossfade {SECONDS}`
|
||||
Sets crossfading between songs.
|
||||
Sets crossfading between songs. See :ref:`crossfading`.
|
||||
|
||||
.. _command_mixrampdb:
|
||||
|
||||
:command:`mixrampdb {deciBels}`
|
||||
Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp
|
||||
Sets the threshold at which songs will be overlapped.
|
||||
See :ref:`mixramp`.
|
||||
|
||||
.. _command_mixrampdelay:
|
||||
|
||||
:command:`mixrampdelay {SECONDS}`
|
||||
Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.
|
||||
See :ref:`mixramp`.
|
||||
|
||||
.. _command_random:
|
||||
|
||||
@@ -543,6 +545,13 @@ Playback options
|
||||
Sets repeat state to ``STATE``,
|
||||
``STATE`` should be 0 or 1.
|
||||
|
||||
If enabled, MPD keeps repeating the whole queue (:ref:`single mode
|
||||
<command_single>` disabled) or the current song (:ref:`single mode
|
||||
<command_single>` enabled).
|
||||
|
||||
If :ref:`random mode <command_random>` is also enabled, the
|
||||
playback order will be shuffled each time the queue gets repeated.
|
||||
|
||||
.. _command_setvol:
|
||||
|
||||
:command:`setvol {VOL}`
|
||||
@@ -771,8 +780,8 @@ Whenever possible, ids should be used.
|
||||
.. _command_playlistfind:
|
||||
|
||||
:command:`playlistfind {FILTER}`
|
||||
Finds songs in the queue with strict
|
||||
matching.
|
||||
Search the queue for songs matching
|
||||
``FILTER`` (see :ref:`Filters <filter_syntax>`).
|
||||
|
||||
.. _command_playlistid:
|
||||
|
||||
@@ -792,8 +801,10 @@ Whenever possible, ids should be used.
|
||||
.. _command_playlistsearch:
|
||||
|
||||
:command:`playlistsearch {FILTER}`
|
||||
Searches case-insensitively for partial matches in the
|
||||
queue.
|
||||
Search the queue for songs matching
|
||||
``FILTER`` (see :ref:`Filters <filter_syntax>`).
|
||||
Parameters have the same meaning as for :ref:`find
|
||||
<command_playlistfind>`, except that search is not case sensitive.
|
||||
|
||||
.. _command_plchanges:
|
||||
|
||||
@@ -1222,6 +1233,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 +1672,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
|
||||
|
116
doc/user.rst
116
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 \
|
||||
@@ -301,7 +301,7 @@ Configuring neighbor plugins
|
||||
----------------------------
|
||||
|
||||
All neighbor plugins are disabled by default to avoid unwanted
|
||||
overhead. To enable (and configure) a plugin, add a :code:`neighbor`
|
||||
overhead. To enable (and configure) a plugin, add a :code:`neighbors`
|
||||
block to :file:`mpd.conf`:
|
||||
|
||||
.. code-block:: none
|
||||
@@ -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
|
||||
@@ -533,7 +538,7 @@ The following table lists the playlist_plugin options valid for all plugins:
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - **plugin**
|
||||
* - **name**
|
||||
- The name of the plugin
|
||||
* - **enabled yes|no**
|
||||
- Allows you to disable a playlist plugin without recompiling. By default, all plugins are enabled.
|
||||
@@ -583,6 +588,85 @@ 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.
|
||||
|
||||
|
||||
.. _crossfading:
|
||||
|
||||
Cross-Fading
|
||||
------------
|
||||
|
||||
If ``crossfade`` is set to a positive number, then adjacent songs are
|
||||
cross-faded by this number of seconds. This is a run-time setting
|
||||
:ref:`which can be controlled by clients <command_crossfade>`,
|
||||
e.g. with :program:`mpc`::
|
||||
|
||||
mpc crossfade 10
|
||||
mpc crossfade 0
|
||||
|
||||
Zero means cross-fading is disabled.
|
||||
|
||||
Cross-fading is only possible if both songs have the same audio
|
||||
format. At the cost of quality loss and higher CPU usage, you can
|
||||
make sure this is always given by configuring
|
||||
:ref:`audio_output_format`.
|
||||
|
||||
.. _mixramp:
|
||||
|
||||
MixRamp
|
||||
^^^^^^^
|
||||
|
||||
MixRamp tags describe the loudness levels at start and end of a song
|
||||
and can be used by MPD to find the best time to begin cross-fading.
|
||||
MPD enables MixRamp if:
|
||||
|
||||
- Cross-fade is enabled
|
||||
- :ref:`mixrampdelay <command_mixrampdelay>` is set to a positive
|
||||
value, e.g.::
|
||||
mpc mixrampdelay 1
|
||||
- :ref:`mixrampdb <command_mixrampdb>` is set to a reasonable value,
|
||||
e.g.::
|
||||
mpc mixrampdb -17
|
||||
- both songs have MixRamp tags
|
||||
- both songs have the same audio format (or :ref:`audio_output_format`
|
||||
is configured)
|
||||
|
||||
The `MixRamp <http://sourceforge.net/projects/mixramp>`__ tool can be
|
||||
used to add MixRamp tags to your song files.
|
||||
|
||||
|
||||
|
||||
Client Connections
|
||||
------------------
|
||||
|
||||
@@ -979,7 +1063,19 @@ The "music directory" is where you store your music files. :program:`MPD` stores
|
||||
|
||||
Depending on the size of your music collection and the speed of the storage, this can take a while.
|
||||
|
||||
To exclude a file from the update, create a file called :file:`.mpdignore` in its parent directory. Each line of that file may contain a list of shell wildcards. Matching files in the current directory and all subdirectories are excluded.
|
||||
To exclude a file from the update, create a file called
|
||||
:file:`.mpdignore` in its parent directory. Each line of that file
|
||||
may contain a list of shell wildcards. Matching files (or
|
||||
directories) in the current directory and all subdirectories are
|
||||
excluded. Example::
|
||||
|
||||
*.opus
|
||||
99*
|
||||
|
||||
Subject to pattern matching is the file/directory name. It is (not
|
||||
yet) possible to match nested path names, e.g. something like
|
||||
``foo/*.flac`` is not possible.
|
||||
|
||||
|
||||
Mounting other storages into the music directory
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -1019,6 +1115,15 @@ See :ref:`tags` for a list of supported tags.
|
||||
The :ref:`metadata_to_use <metadata_to_use>` setting can be used to
|
||||
enable or disable certain tags.
|
||||
|
||||
Note that :program:`MPD` may not necessarily read metadata itself,
|
||||
instead relying on data reported by the decoder that was used to read
|
||||
a file. For example, this is the case for the FFmpeg decoder: both
|
||||
:program:`MPD` and FFmpeg need to support a given metadata format in
|
||||
order for metadata to be picked up correctly.
|
||||
|
||||
Only if a decoder does not have metadata support will :program:`MPD`
|
||||
attempt to parse a song's metadata itself.
|
||||
|
||||
The queue
|
||||
---------
|
||||
|
||||
@@ -1076,6 +1181,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.8',
|
||||
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()
|
||||
@@ -73,6 +73,9 @@ test_common_flags = [
|
||||
# clang specific warning options:
|
||||
'-Wunreachable-code-aggressive',
|
||||
'-Wused-but-marked-unused',
|
||||
|
||||
# suppress bogus GCC12 warnings in libfmt headers
|
||||
'-Wno-stringop-overflow',
|
||||
]
|
||||
|
||||
test_global_cxxflags = test_global_common_flags + [
|
||||
|
@@ -12,14 +12,14 @@ from build.boost import BoostProject
|
||||
from build.jack import JackProject
|
||||
|
||||
libmpdclient = MesonProject(
|
||||
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.19.tar.xz',
|
||||
'158aad4c2278ab08e76a3f2b0166c99b39fae00ee17231bd225c5a36e977a189',
|
||||
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.20.tar.xz',
|
||||
'18793f68e939c3301e34d8fcadea1f7daa24143941263cecadb80126194e277d',
|
||||
'lib/libmpdclient.a',
|
||||
)
|
||||
|
||||
libogg = CmakeProject(
|
||||
'http://downloads.xiph.org/releases/ogg/libogg-1.3.4.tar.xz',
|
||||
'c163bc12bc300c401b6aa35907ac682671ea376f13ae0969a220f7ddf71893fe',
|
||||
'http://downloads.xiph.org/releases/ogg/libogg-1.3.5.tar.xz',
|
||||
'c4d91be36fc8e54deae7575241e03f4211eb102afb3fc0775fbbc1b740016705',
|
||||
'lib/libogg.a',
|
||||
[
|
||||
'-DBUILD_SHARED_LIBS=OFF',
|
||||
@@ -43,8 +43,8 @@ opus = AutotoolsProject(
|
||||
)
|
||||
|
||||
flac = AutotoolsProject(
|
||||
'http://downloads.xiph.org/releases/flac/flac-1.3.3.tar.xz',
|
||||
'213e82bd716c9de6db2f98bcadbc4c24c7e2efe8c75939a1a84e28539c4e1748',
|
||||
'http://downloads.xiph.org/releases/flac/flac-1.3.4.tar.xz',
|
||||
'8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737',
|
||||
'lib/libFLAC.a',
|
||||
[
|
||||
'--disable-shared', '--enable-static',
|
||||
@@ -55,8 +55,8 @@ flac = AutotoolsProject(
|
||||
)
|
||||
|
||||
zlib = ZlibProject(
|
||||
'http://zlib.net/zlib-1.2.11.tar.xz',
|
||||
'4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066',
|
||||
'http://zlib.net/zlib-1.2.12.tar.xz',
|
||||
'7db46b8d7726232a621befaab4a1c870f00a90805511c0e0090441dac57def18',
|
||||
'lib/libz.a',
|
||||
)
|
||||
|
||||
@@ -151,8 +151,8 @@ gme = CmakeProject(
|
||||
)
|
||||
|
||||
ffmpeg = FfmpegProject(
|
||||
'http://ffmpeg.org/releases/ffmpeg-4.4.1.tar.xz',
|
||||
'eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02',
|
||||
'http://ffmpeg.org/releases/ffmpeg-5.0.1.tar.xz',
|
||||
'ef2efae259ce80a240de48ec85ecb062cecca26e4352ffb3fda562c21a93007b',
|
||||
'lib/libavcodec.a',
|
||||
[
|
||||
'--disable-shared', '--enable-static',
|
||||
@@ -177,6 +177,8 @@ ffmpeg = FfmpegProject(
|
||||
'--disable-filters',
|
||||
'--disable-v4l2_m2m',
|
||||
|
||||
'--disable-vulkan',
|
||||
|
||||
'--disable-parser=bmp',
|
||||
'--disable-parser=cavsvideo',
|
||||
'--disable-parser=dvbsub',
|
||||
@@ -380,14 +382,14 @@ ffmpeg = FfmpegProject(
|
||||
)
|
||||
|
||||
openssl = OpenSSLProject(
|
||||
'https://www.openssl.org/source/openssl-3.0.0.tar.gz',
|
||||
'59eedfcb46c25214c9bd37ed6078297b4df01d012267fe9e9eee31f61bc70536',
|
||||
'https://www.openssl.org/source/openssl-3.0.5.tar.gz',
|
||||
'aa7d8d9bef71ad6525c55ba11e5f4397889ce49c2c9349dcea6d3e4f0b024a7a',
|
||||
'include/openssl/ossl_typ.h',
|
||||
)
|
||||
|
||||
curl = CmakeProject(
|
||||
'https://curl.se/download/curl-7.79.1.tar.xz',
|
||||
'0606f74b1182ab732a17c11613cbbaf7084f2e6cca432642d0e3ad7c224c3689',
|
||||
'https://curl.se/download/curl-7.84.0.tar.xz',
|
||||
'2d118b43f547bfe5bae806d8d47b4e596ea5b25a6c1f080aef49fbcd817c5db8',
|
||||
'lib/libcurl.a',
|
||||
[
|
||||
'-DBUILD_CURL_EXE=OFF',
|
||||
@@ -415,14 +417,14 @@ curl = CmakeProject(
|
||||
'-DBUILD_TESTING=OFF',
|
||||
],
|
||||
windows_configure_args=[
|
||||
'-DCMAKE_USE_SCHANNEL=ON',
|
||||
'-DCURL_USE_SCHANNEL=ON',
|
||||
],
|
||||
patches='src/lib/curl/patches',
|
||||
)
|
||||
|
||||
libnfs = AutotoolsProject(
|
||||
'https://github.com/sahlberg/libnfs/archive/libnfs-4.0.0.tar.gz',
|
||||
'6ee77e9fe220e2d3e3b1f53cfea04fb319828cc7dbb97dd9df09e46e901d797d',
|
||||
'https://github.com/sahlberg/libnfs/archive/libnfs-5.0.1.tar.gz',
|
||||
'7ef445410b42f36b9bad426608b53ccb9ccca4101e545c383f564c11db672ca8',
|
||||
'lib/libnfs.a',
|
||||
[
|
||||
'--disable-shared', '--enable-static',
|
||||
@@ -433,8 +435,7 @@ libnfs = AutotoolsProject(
|
||||
|
||||
'--disable-utils', '--disable-examples',
|
||||
],
|
||||
base='libnfs-libnfs-4.0.0',
|
||||
patches='src/lib/nfs/patches',
|
||||
base='libnfs-libnfs-5.0.1',
|
||||
autoreconf=True,
|
||||
)
|
||||
|
||||
@@ -445,7 +446,7 @@ jack = JackProject(
|
||||
)
|
||||
|
||||
boost = BoostProject(
|
||||
'https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.bz2',
|
||||
'fc9f85fc030e233142908241af7a846e60630aa7388de9a5fafb1f3a26840854',
|
||||
'https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2',
|
||||
'475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39',
|
||||
'include/boost/version.hpp',
|
||||
)
|
||||
|
@@ -53,19 +53,21 @@ pkgconfig = '{toolchain.pkg_config}'
|
||||
f.write(f"""
|
||||
[properties]
|
||||
root = '{toolchain.install_prefix}'
|
||||
|
||||
[built-in options]
|
||||
c_args = {repr((toolchain.cppflags + ' ' + toolchain.cflags).split())}
|
||||
c_link_args = {repr(toolchain.ldflags.split() + toolchain.libs.split())}
|
||||
|
||||
cpp_args = {repr((toolchain.cppflags + ' ' + toolchain.cxxflags).split())}
|
||||
cpp_link_args = {repr(toolchain.ldflags.split() + toolchain.libs.split())}
|
||||
""")
|
||||
|
||||
if 'android' in toolchain.arch:
|
||||
f.write("""
|
||||
# Keep Meson from executing Android-x86 test binariees
|
||||
needs_exe_wrapper = true
|
||||
""")
|
||||
|
||||
f.write(f"""
|
||||
[built-in options]
|
||||
c_args = {repr((toolchain.cppflags + ' ' + toolchain.cflags).split())}
|
||||
c_link_args = {repr(toolchain.ldflags.split() + toolchain.libs.split())}
|
||||
|
||||
cpp_args = {repr((toolchain.cppflags + ' ' + toolchain.cxxflags).split())}
|
||||
cpp_link_args = {repr(toolchain.ldflags.split() + toolchain.libs.split())}
|
||||
""")
|
||||
|
||||
f.write(f"""
|
||||
|
@@ -48,15 +48,14 @@ LocateFileUri(const char *uri, const Client *client
|
||||
/* this path was relative to the music
|
||||
directory */
|
||||
// TODO: don't use suffix.data() (ok for now because we know it's null-terminated)
|
||||
return LocatedUri(LocatedUri::Type::RELATIVE,
|
||||
suffix.data());
|
||||
return {LocatedUri::Type::RELATIVE, suffix.data()};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client != nullptr)
|
||||
client->AllowFile(path);
|
||||
|
||||
return LocatedUri(LocatedUri::Type::PATH, uri, std::move(path));
|
||||
return {LocatedUri::Type::PATH, uri, std::move(path)};
|
||||
}
|
||||
|
||||
static LocatedUri
|
||||
@@ -90,8 +89,7 @@ LocateAbsoluteUri(UriPluginKind kind, const char *uri
|
||||
const auto suffix = storage->MapToRelativeUTF8(uri);
|
||||
if (suffix.data() != nullptr)
|
||||
// TODO: don't use suffix.data() (ok for now because we know it's null-terminated)
|
||||
return LocatedUri(LocatedUri::Type::RELATIVE,
|
||||
suffix.data());
|
||||
return {LocatedUri::Type::RELATIVE, suffix.data()};
|
||||
}
|
||||
|
||||
if (kind == UriPluginKind::STORAGE &&
|
||||
@@ -99,7 +97,7 @@ LocateAbsoluteUri(UriPluginKind kind, const char *uri
|
||||
throw std::invalid_argument("Unsupported URI scheme");
|
||||
#endif
|
||||
|
||||
return LocatedUri(LocatedUri::Type::ABSOLUTE, uri);
|
||||
return {LocatedUri::Type::ABSOLUTE, uri};
|
||||
}
|
||||
|
||||
LocatedUri
|
||||
|
@@ -45,7 +45,10 @@ void
|
||||
LogFmt(LogLevel level, const Domain &domain,
|
||||
const S &format_str, Args&&... args) noexcept
|
||||
{
|
||||
#if FMT_VERSION >= 70000
|
||||
#if FMT_VERSION >= 90000
|
||||
return LogVFmt(level, domain, format_str,
|
||||
fmt::make_format_args(args...));
|
||||
#elif FMT_VERSION >= 70000
|
||||
return LogVFmt(level, domain, fmt::to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str,
|
||||
args...));
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "PlaylistDatabase.hxx"
|
||||
#include "db/PlaylistVector.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/LineReader.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "time/ChronoUtil.hxx"
|
||||
#include "util/StringStrip.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
@@ -42,7 +42,7 @@ playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv)
|
||||
}
|
||||
|
||||
void
|
||||
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name)
|
||||
playlist_metadata_load(LineReader &file, PlaylistVector &pv, const char *name)
|
||||
{
|
||||
PlaylistInfo pm(name);
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
class PlaylistVector;
|
||||
class BufferedOutputStream;
|
||||
class TextFile;
|
||||
class LineReader;
|
||||
|
||||
void
|
||||
playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv);
|
||||
@@ -33,6 +33,7 @@ playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv);
|
||||
* Throws #std::runtime_error on error.
|
||||
*/
|
||||
void
|
||||
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name);
|
||||
playlist_metadata_load(LineReader &file, PlaylistVector &pv,
|
||||
const char *name);
|
||||
|
||||
#endif
|
||||
|
@@ -28,8 +28,8 @@
|
||||
#include "Mapper.hxx"
|
||||
#include "protocol/RangeArg.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/FileOutputStream.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/FileOutputStream.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "config/Data.hxx"
|
||||
#include "config/Option.hxx"
|
||||
#include "config/Defaults.hxx"
|
||||
|
@@ -28,8 +28,8 @@
|
||||
#include "fs/AllocatedPath.hxx"
|
||||
#include "fs/Traits.hxx"
|
||||
#include "fs/FileSystem.hxx"
|
||||
#include "fs/io/FileOutputStream.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/FileOutputStream.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "util/UriExtract.hxx"
|
||||
|
||||
static void
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ enum class SingleMode : uint8_t {
|
||||
/**
|
||||
* Return the string representation of a #SingleMode.
|
||||
*/
|
||||
[[gnu::pure]]
|
||||
[[gnu::const]]
|
||||
const char *
|
||||
SingleToString(SingleMode mode) noexcept;
|
||||
|
||||
|
@@ -22,8 +22,8 @@
|
||||
#include "db/plugins/simple/Song.hxx"
|
||||
#include "song/DetachedSong.hxx"
|
||||
#include "TagSave.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/LineReader.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "tag/ParseName.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "tag/Builder.hxx"
|
||||
@@ -85,7 +85,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
||||
}
|
||||
|
||||
DetachedSong
|
||||
song_load(TextFile &file, const char *uri,
|
||||
song_load(LineReader &file, const char *uri,
|
||||
std::string *target_r)
|
||||
{
|
||||
DetachedSong song(uri);
|
||||
|
@@ -28,7 +28,7 @@ struct Song;
|
||||
struct AudioFormat;
|
||||
class DetachedSong;
|
||||
class BufferedOutputStream;
|
||||
class TextFile;
|
||||
class LineReader;
|
||||
|
||||
void
|
||||
song_save(BufferedOutputStream &os, const Song &song);
|
||||
@@ -43,7 +43,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song);
|
||||
* Throws on error.
|
||||
*/
|
||||
DetachedSong
|
||||
song_load(TextFile &file, const char *uri,
|
||||
song_load(LineReader &file, const char *uri,
|
||||
std::string *target_r=nullptr);
|
||||
|
||||
#endif
|
||||
|
@@ -22,8 +22,8 @@
|
||||
#include "output/State.hxx"
|
||||
#include "queue/PlaylistState.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/FileOutputStream.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/FileOutputStream.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "storage/StorageState.hxx"
|
||||
#include "Partition.hxx"
|
||||
#include "Instance.hxx"
|
||||
|
@@ -21,12 +21,16 @@
|
||||
#include "TagStream.hxx"
|
||||
#include "TagFile.hxx"
|
||||
#include "tag/Generic.hxx"
|
||||
#include "song/LightSong.hxx"
|
||||
#include "db/Interface.hxx"
|
||||
#include "storage/StorageInterface.hxx"
|
||||
#include "client/Client.hxx"
|
||||
#include "protocol/Ack.hxx"
|
||||
#include "fs/AllocatedPath.hxx"
|
||||
#include "input/InputStream.hxx"
|
||||
#include "util/Compiler.h"
|
||||
#include "util/ScopeExit.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
#include "util/UriExtract.hxx"
|
||||
#include "LocateUri.hxx"
|
||||
|
||||
@@ -51,10 +55,67 @@ TagScanFile(const Path path_fs, TagHandler &handler)
|
||||
ScanGenericTags(path_fs, handler);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DATABASE
|
||||
|
||||
/**
|
||||
* Collapse "../" prefixes in a URI relative to the specified base
|
||||
* URI.
|
||||
*/
|
||||
static std::string
|
||||
ResolveUri(std::string_view base, const char *relative)
|
||||
{
|
||||
while (true) {
|
||||
const char *rest = StringAfterPrefix(relative, "../");
|
||||
if (rest == nullptr)
|
||||
break;
|
||||
|
||||
if (base == ".")
|
||||
throw ProtocolError(ACK_ERROR_NO_EXIST, "Bad real URI");
|
||||
|
||||
base = PathTraitsUTF8::GetParent(base);
|
||||
relative = rest;
|
||||
}
|
||||
|
||||
return PathTraitsUTF8::Build(base, relative);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the specified song in the database and return its
|
||||
* (resolved) "real" URI.
|
||||
*/
|
||||
static std::string
|
||||
GetRealSongUri(Client &client, std::string_view uri)
|
||||
{
|
||||
const auto &db = client.GetDatabaseOrThrow();
|
||||
|
||||
const auto *song = db.GetSong(uri);
|
||||
if (song == nullptr)
|
||||
throw ProtocolError(ACK_ERROR_NO_EXIST, "No such song");
|
||||
|
||||
AtScopeExit(&db, song) { db.ReturnSong(song); };
|
||||
|
||||
if (song->real_uri == nullptr)
|
||||
return {};
|
||||
|
||||
return ResolveUri(PathTraitsUTF8::GetParent(uri), song->real_uri);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
TagScanDatabase(Client &client, const char *uri, TagHandler &handler)
|
||||
{
|
||||
#ifdef ENABLE_DATABASE
|
||||
const auto real_uri = GetRealSongUri(client, uri);
|
||||
|
||||
if (!real_uri.empty()) {
|
||||
uri = real_uri.c_str();
|
||||
|
||||
// TODO: support absolute paths?
|
||||
if (uri_has_scheme(uri))
|
||||
return TagScanStream(uri, handler);
|
||||
}
|
||||
|
||||
const Storage *storage = client.GetStorage();
|
||||
if (storage == nullptr) {
|
||||
#else
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "TagSave.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
|
||||
#define SONG_TIME "Time: "
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "ErrorRef.hxx"
|
||||
#include "StringRef.hxx"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Apple {
|
||||
@@ -57,8 +58,8 @@ ThrowOSStatus(OSStatus status, const char *_msg)
|
||||
const Apple::StringRef cfstr(cferr.CopyDescription());
|
||||
|
||||
char msg[1024];
|
||||
strcpy(msg, _msg);
|
||||
size_t length = strlen(msg);
|
||||
std::strcpy(msg, _msg);
|
||||
size_t length = std::strlen(msg);
|
||||
|
||||
cfstr.GetCString(msg + length, sizeof(msg) - length);
|
||||
throw std::runtime_error(msg);
|
||||
|
@@ -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");
|
||||
}
|
||||
|
@@ -82,7 +82,10 @@ public:
|
||||
|
||||
template<typename S, typename... Args>
|
||||
bool Fmt(const S &format_str, Args&&... args) noexcept {
|
||||
#if FMT_VERSION >= 70000
|
||||
#if FMT_VERSION >= 90000
|
||||
return VFmt(format_str,
|
||||
fmt::make_format_args(args...));
|
||||
#elif FMT_VERSION >= 70000
|
||||
return VFmt(fmt::to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str,
|
||||
args...));
|
||||
@@ -109,7 +112,10 @@ public:
|
||||
template<typename S, typename... Args>
|
||||
void FmtError(enum ack code,
|
||||
const S &format_str, Args&&... args) noexcept {
|
||||
#if FMT_VERSION >= 70000
|
||||
#if FMT_VERSION >= 90000
|
||||
return VFmtError(code, format_str,
|
||||
fmt::make_format_args(args...));
|
||||
#elif FMT_VERSION >= 70000
|
||||
return VFmtError(code, fmt::to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str,
|
||||
args...));
|
||||
|
@@ -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);
|
||||
|
@@ -160,8 +160,7 @@ find_stream_art(std::string_view directory, Mutex &mutex)
|
||||
static constexpr auto art_names = std::array {
|
||||
"cover.png",
|
||||
"cover.jpg",
|
||||
"cover.tiff",
|
||||
"cover.bmp",
|
||||
"cover.webp",
|
||||
};
|
||||
|
||||
for(const auto name : art_names) {
|
||||
@@ -213,7 +212,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();
|
||||
}
|
||||
|
@@ -333,15 +333,11 @@ handle_getvol(Client &client, Request, Response &r)
|
||||
}
|
||||
|
||||
CommandResult
|
||||
handle_setvol(Client &client, Request args, Response &r)
|
||||
handle_setvol(Client &client, Request args, Response &)
|
||||
{
|
||||
unsigned level = args.ParseUnsigned(0, 100);
|
||||
|
||||
if (!volume_level_change(client.GetPartition().outputs, level)) {
|
||||
r.Error(ACK_ERROR_SYSTEM, "problems setting volume");
|
||||
return CommandResult::ERROR;
|
||||
}
|
||||
|
||||
volume_level_change(client.GetPartition().outputs, level);
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
||||
@@ -364,11 +360,8 @@ handle_volume(Client &client, Request args, Response &r)
|
||||
else if (new_volume > 100)
|
||||
new_volume = 100;
|
||||
|
||||
if (new_volume != old_volume &&
|
||||
!volume_level_change(outputs, new_volume)) {
|
||||
r.Error(ACK_ERROR_SYSTEM, "problems setting volume");
|
||||
return CommandResult::ERROR;
|
||||
}
|
||||
if (new_volume != old_volume)
|
||||
volume_level_change(outputs, new_volume);
|
||||
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
@@ -31,8 +31,8 @@
|
||||
#include "fs/FileSystem.hxx"
|
||||
#include "fs/List.hxx"
|
||||
#include "fs/Path.hxx"
|
||||
#include "fs/io/FileReader.hxx"
|
||||
#include "fs/io/BufferedReader.hxx"
|
||||
#include "io/FileReader.hxx"
|
||||
#include "io/BufferedReader.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
#include <cassert>
|
||||
|
@@ -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,
|
||||
],
|
||||
|
@@ -20,8 +20,8 @@
|
||||
#include "DatabaseSave.hxx"
|
||||
#include "db/DatabaseLock.hxx"
|
||||
#include "DirectorySave.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "io/LineReader.hxx"
|
||||
#include "tag/ParseName.hxx"
|
||||
#include "tag/Settings.hxx"
|
||||
#include "fs/Charset.hxx"
|
||||
@@ -64,7 +64,7 @@ db_save_internal(BufferedOutputStream &os, const Directory &music_root)
|
||||
}
|
||||
|
||||
void
|
||||
db_load_internal(TextFile &file, Directory &music_root)
|
||||
db_load_internal(LineReader &file, Directory &music_root)
|
||||
{
|
||||
char *line;
|
||||
unsigned format = 0;
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
struct Directory;
|
||||
class BufferedOutputStream;
|
||||
class TextFile;
|
||||
class LineReader;
|
||||
|
||||
void
|
||||
db_save_internal(BufferedOutputStream &os, const Directory &root);
|
||||
@@ -31,6 +31,6 @@ db_save_internal(BufferedOutputStream &os, const Directory &root);
|
||||
* Throws #std::runtime_error on error.
|
||||
*/
|
||||
void
|
||||
db_load_internal(TextFile &file, Directory &root);
|
||||
db_load_internal(LineReader &file, Directory &root);
|
||||
|
||||
#endif
|
||||
|
@@ -278,5 +278,5 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
||||
LightDirectory
|
||||
Directory::Export() const noexcept
|
||||
{
|
||||
return LightDirectory(GetPath(), mtime);
|
||||
return {GetPath(), mtime};
|
||||
}
|
||||
|
@@ -23,8 +23,8 @@
|
||||
#include "SongSave.hxx"
|
||||
#include "song/DetachedSong.hxx"
|
||||
#include "PlaylistDatabase.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "io/LineReader.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "time/ChronoUtil.hxx"
|
||||
#include "util/StringAPI.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
@@ -121,7 +121,7 @@ ParseLine(Directory &directory, const char *line)
|
||||
}
|
||||
|
||||
static Directory *
|
||||
directory_load_subdir(TextFile &file, Directory &parent, std::string_view name)
|
||||
directory_load_subdir(LineReader &file, Directory &parent, std::string_view name)
|
||||
{
|
||||
if (parent.FindChild(name) != nullptr)
|
||||
throw FormatRuntimeError("Duplicate subdirectory '%.*s'",
|
||||
@@ -152,7 +152,7 @@ directory_load_subdir(TextFile &file, Directory &parent, std::string_view name)
|
||||
}
|
||||
|
||||
void
|
||||
directory_load(TextFile &file, Directory &directory)
|
||||
directory_load(LineReader &file, Directory &directory)
|
||||
{
|
||||
const char *line;
|
||||
|
||||
|
@@ -21,7 +21,7 @@
|
||||
#define MPD_DIRECTORY_SAVE_HXX
|
||||
|
||||
struct Directory;
|
||||
class TextFile;
|
||||
class LineReader;
|
||||
class BufferedOutputStream;
|
||||
|
||||
void
|
||||
@@ -31,6 +31,6 @@ directory_save(BufferedOutputStream &os, const Directory &directory);
|
||||
* Throws #std::runtime_error on error.
|
||||
*/
|
||||
void
|
||||
directory_load(TextFile &file, Directory &directory);
|
||||
directory_load(LineReader &file, Directory &directory);
|
||||
|
||||
#endif
|
||||
|
@@ -34,8 +34,8 @@
|
||||
#include "db/DatabaseLock.hxx"
|
||||
#include "db/DatabaseError.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include "fs/io/BufferedOutputStream.hxx"
|
||||
#include "fs/io/FileOutputStream.hxx"
|
||||
#include "io/BufferedOutputStream.hxx"
|
||||
#include "io/FileOutputStream.hxx"
|
||||
#include "fs/FileInfo.hxx"
|
||||
#include "config/Block.hxx"
|
||||
#include "fs/FileSystem.hxx"
|
||||
@@ -46,7 +46,7 @@
|
||||
#include "Log.hxx"
|
||||
|
||||
#ifdef ENABLE_ZLIB
|
||||
#include "fs/io/GzipOutputStream.hxx"
|
||||
#include "lib/zlib/GzipOutputStream.hxx"
|
||||
#endif
|
||||
|
||||
#include <cerrno>
|
||||
@@ -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,10 +253,16 @@ public:
|
||||
|
||||
[[gnu::pure]]
|
||||
bool LockHasFailed() const noexcept {
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return HasFailed();
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
bool LockIsReplayGainEnabled() const noexcept {
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
return replay_gain_mode != ReplayGainMode::OFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transition this obejct from DecoderState::START to
|
||||
* DecoderState::DECODE.
|
||||
@@ -284,7 +290,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 +366,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"
|
||||
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#ifndef MPD_DECODER_READER_HXX
|
||||
#define MPD_DECODER_READER_HXX
|
||||
|
||||
#include "fs/io/Reader.hxx"
|
||||
#include "io/Reader.hxx"
|
||||
|
||||
class DecoderClient;
|
||||
class InputStream;
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "util/RuntimeError.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/ScopeExit.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
#include "thread/Name.hxx"
|
||||
#include "tag/ApeReplayGain.hxx"
|
||||
#include "Log.hxx"
|
||||
@@ -261,12 +262,16 @@ LoadReplayGain(DecoderClient &client, InputStream &is)
|
||||
static void
|
||||
MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is)
|
||||
{
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(bridge.dc.mutex);
|
||||
if (bridge.dc.replay_gain_mode == ReplayGainMode::OFF)
|
||||
/* ReplayGain is disabled */
|
||||
return;
|
||||
}
|
||||
if (!bridge.dc.LockIsReplayGainEnabled())
|
||||
/* ReplayGain is disabled */
|
||||
return;
|
||||
|
||||
if (is.HasMimeType() &&
|
||||
StringStartsWith(is.GetMimeType(), "audio/x-mpd-"))
|
||||
/* skip for (virtual) files (e.g. from the
|
||||
cdio_paranoia input plugin) which cannot possibly
|
||||
contain tags */
|
||||
return;
|
||||
|
||||
LoadReplayGain(bridge, is);
|
||||
}
|
||||
@@ -337,7 +342,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 +370,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"
|
||||
@@ -384,7 +384,8 @@ static void
|
||||
FfmpegParseMetaData(const AVStream &stream,
|
||||
ReplayGainInfo &rg, MixRampInfo &mr)
|
||||
{
|
||||
FfmpegParseMetaData(*stream.metadata, rg, mr);
|
||||
if (stream.metadata != nullptr)
|
||||
FfmpegParseMetaData(*stream.metadata, rg, mr);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -393,7 +394,9 @@ FfmpegParseMetaData(const AVFormatContext &format_context, int audio_stream,
|
||||
{
|
||||
assert(audio_stream >= 0);
|
||||
|
||||
FfmpegParseMetaData(*format_context.metadata, rg, mr);
|
||||
if (format_context.metadata != nullptr)
|
||||
FfmpegParseMetaData(*format_context.metadata, rg, mr);
|
||||
|
||||
FfmpegParseMetaData(*format_context.streams[audio_stream],
|
||||
rg, mr);
|
||||
}
|
||||
@@ -468,7 +471,7 @@ static bool
|
||||
IsSeekable(const AVFormatContext &format_context) noexcept
|
||||
{
|
||||
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 6, 100)
|
||||
return (format_context.ctx_flags & AVFMTCTX_UNSEEKABLE) != 0;
|
||||
return (format_context.ctx_flags & AVFMTCTX_UNSEEKABLE) == 0;
|
||||
#else
|
||||
(void)format_context;
|
||||
return false;
|
||||
@@ -530,9 +533,8 @@ FfmpegDecode(DecoderClient &client, InputStream *input,
|
||||
: FromFfmpegTimeChecked(format_context.duration, AV_TIME_BASE_Q);
|
||||
|
||||
client.Ready(audio_format,
|
||||
input
|
||||
? input->IsSeekable()
|
||||
: IsSeekable(format_context),
|
||||
(input ? input->IsSeekable() : false)
|
||||
|| IsSeekable(format_context),
|
||||
total_time);
|
||||
|
||||
FfmpegParseMetaData(client, format_context, audio_stream);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include "FfmpegIo.hxx"
|
||||
#include "libavutil/mem.h"
|
||||
#include "../DecoderAPI.hxx"
|
||||
#include "input/InputStream.hxx"
|
||||
|
||||
@@ -35,7 +36,11 @@ AvioStream::~AvioStream()
|
||||
inline int
|
||||
AvioStream::Read(void *dest, int size)
|
||||
{
|
||||
return decoder_read(client, input, dest, size);
|
||||
const auto nbytes = decoder_read(client, input, dest, size);
|
||||
if (nbytes == 0)
|
||||
return AVERROR_EOF;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
inline int64_t
|
||||
|
@@ -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"
|
||||
|
@@ -91,7 +91,8 @@ ScanOpusTags(const void *data, size_t size,
|
||||
if (!r.Expect("OpusTags", 8))
|
||||
return false;
|
||||
|
||||
if (!handler.WantPair() && !handler.WantTag())
|
||||
if (!handler.WantPair() && !handler.WantTag() &&
|
||||
!handler.WantPicture())
|
||||
return true;
|
||||
|
||||
if (!r.SkipString())
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "fs/AllocatedPath.hxx"
|
||||
#include "lib/icu/Converter.hxx"
|
||||
#ifdef HAVE_SIDPLAYFP
|
||||
#include "fs/io/FileReader.hxx"
|
||||
#include "io/FileReader.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
#endif
|
||||
#include "util/StringFormat.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
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "ToOutputStream.hxx"
|
||||
#include "EncoderInterface.hxx"
|
||||
#include "fs/io/OutputStream.hxx"
|
||||
#include "io/OutputStream.hxx"
|
||||
|
||||
void
|
||||
EncoderToOutputStream(OutputStream &os, Encoder &encoder)
|
||||
|
@@ -3,6 +3,23 @@ encoder_features = configuration_data()
|
||||
encoder_features.set('ENABLE_ENCODER', need_encoder)
|
||||
|
||||
if not need_encoder
|
||||
if need_wave_encoder
|
||||
# Special case for the Snapcast output plugin which only needs the
|
||||
# PCM wave encoder encoder plugin
|
||||
encoder_glue = static_library(
|
||||
'encoder_glue',
|
||||
'plugins/WaveEncoderPlugin.cxx',
|
||||
include_directories: inc,
|
||||
)
|
||||
|
||||
encoder_glue_dep = declare_dependency(
|
||||
link_with: encoder_glue,
|
||||
)
|
||||
|
||||
configure_file(output: 'Features.h', configuration: encoder_features)
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
encoder_glue_dep = dependency('', required: false)
|
||||
configure_file(output: 'Features.h', configuration: encoder_features)
|
||||
subdir_done()
|
||||
|
@@ -35,7 +35,7 @@ if libshine_dep.found()
|
||||
endif
|
||||
|
||||
encoder_features.set('ENABLE_WAVE_ENCODER', get_option('wave_encoder'))
|
||||
if get_option('wave_encoder')
|
||||
if get_option('wave_encoder') or need_wave_encoder
|
||||
encoder_plugins_sources += 'WaveEncoderPlugin.cxx'
|
||||
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>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include "filter/Prepared.hxx"
|
||||
#include "pcm/Buffer.hxx"
|
||||
#include "pcm/AudioFormat.hxx"
|
||||
#include "AudioCompress/compress.h"
|
||||
#include "pcm/AudioCompress/compress.h"
|
||||
#include "util/ConstBuffer.hxx"
|
||||
|
||||
#include <string.h>
|
||||
|
@@ -12,7 +12,6 @@ endif
|
||||
|
||||
filter_plugins = static_library(
|
||||
'filter_plugins',
|
||||
'../../AudioCompress/compress.c',
|
||||
'NullFilterPlugin.cxx',
|
||||
'TwoFilters.cxx',
|
||||
'AutoConvertFilterPlugin.cxx',
|
||||
|
@@ -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 {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -41,7 +41,7 @@
|
||||
#ifdef USE_XDG
|
||||
#include "util/StringStrip.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
#include "io/TextFile.hxx"
|
||||
#include "fs/io/TextFile.hxx"
|
||||
#include <string.h>
|
||||
#include <utility>
|
||||
#endif
|
||||
|
@@ -18,9 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "TextFile.hxx"
|
||||
#include "FileReader.hxx"
|
||||
#include "AutoGunzipReader.hxx"
|
||||
#include "BufferedReader.hxx"
|
||||
#include "io/FileReader.hxx"
|
||||
#include "io/BufferedReader.hxx"
|
||||
#include "lib/zlib/AutoGunzipReader.hxx"
|
||||
#include "fs/Path.hxx"
|
||||
|
||||
#include <cassert>
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#ifndef MPD_TEXT_FILE_HXX
|
||||
#define MPD_TEXT_FILE_HXX
|
||||
|
||||
#include "io/LineReader.hxx"
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -29,7 +30,7 @@ class FileReader;
|
||||
class AutoGunzipReader;
|
||||
class BufferedReader;
|
||||
|
||||
class TextFile {
|
||||
class TextFile final : public LineReader {
|
||||
const std::unique_ptr<FileReader> file_reader;
|
||||
|
||||
#ifdef ENABLE_ZLIB
|
||||
@@ -45,14 +46,8 @@ public:
|
||||
|
||||
~TextFile() noexcept;
|
||||
|
||||
/**
|
||||
* Reads a line from the input file, and strips trailing
|
||||
* space. There is a reasonable maximum line length, only to
|
||||
* prevent denial of service.
|
||||
*
|
||||
* @return a pointer to the line, or nullptr on end-of-file
|
||||
*/
|
||||
char *ReadLine();
|
||||
/* virtual methods from class LineReader */
|
||||
char *ReadLine() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -14,12 +14,7 @@ fs_sources = [
|
||||
'CheckFile.cxx',
|
||||
'LookupFile.cxx',
|
||||
'DirectoryReader.cxx',
|
||||
'io/PeekReader.cxx',
|
||||
'io/FileReader.cxx',
|
||||
'io/BufferedReader.cxx',
|
||||
'io/TextFile.cxx',
|
||||
'io/FileOutputStream.cxx',
|
||||
'io/BufferedOutputStream.cxx',
|
||||
]
|
||||
|
||||
if is_windows
|
||||
@@ -28,14 +23,6 @@ else
|
||||
shlwapi_dep = dependency('', required: false)
|
||||
endif
|
||||
|
||||
if zlib_dep.found()
|
||||
fs_sources += [
|
||||
'io/GunzipReader.cxx',
|
||||
'io/AutoGunzipReader.cxx',
|
||||
'io/GzipOutputStream.cxx',
|
||||
]
|
||||
endif
|
||||
|
||||
fs = static_library(
|
||||
'fs',
|
||||
fs_sources,
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "IcyInputStream.hxx"
|
||||
#include "IcyMetaDataParser.hxx"
|
||||
#include "tag/IcyMetaDataParser.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "util/UriExtract.hxx"
|
||||
#include "util/UriQueryParser.hxx"
|
||||
|
@@ -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;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#ifndef MPD_INPUT_READER_HXX
|
||||
#define MPD_INPUT_READER_HXX
|
||||
|
||||
#include "fs/io/Reader.hxx"
|
||||
#include "io/Reader.hxx"
|
||||
|
||||
class InputStream;
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user