Compare commits
108 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
323231d1dd | ||
![]() |
714011c81e | ||
![]() |
952ff4207b | ||
![]() |
150b16ec2c | ||
![]() |
c98bc4a243 | ||
![]() |
014f8cd693 | ||
![]() |
aea37e46e3 | ||
![]() |
31ab78ae8e | ||
![]() |
f82e1453e4 | ||
![]() |
a2b77c8813 | ||
![]() |
18add29472 | ||
![]() |
b111a8fe8d | ||
![]() |
3b23cf0258 | ||
![]() |
28e864e096 | ||
![]() |
1de19b921a | ||
![]() |
ff162b5a03 | ||
![]() |
d8e4705dd4 | ||
![]() |
338e1f5926 | ||
![]() |
a7fdfa08e1 | ||
![]() |
9703a401c5 | ||
![]() |
753a2aa462 | ||
![]() |
10990a0684 | ||
![]() |
91254e9211 | ||
![]() |
0f79287b04 | ||
![]() |
f2fac77d8c | ||
![]() |
81b7373637 | ||
![]() |
fa67c2548a | ||
![]() |
ea80587ddb | ||
![]() |
828f5f8384 | ||
![]() |
1295a1272a | ||
![]() |
66646d9276 | ||
![]() |
d0497dba92 | ||
![]() |
42914e8227 | ||
![]() |
59b49b7881 | ||
![]() |
5620f16330 | ||
![]() |
be024d4ad7 | ||
![]() |
75c740fe2b | ||
![]() |
6c8d86bb90 | ||
![]() |
b253a6b71e | ||
![]() |
ca7b4df812 | ||
![]() |
bc8dd57236 | ||
![]() |
f4f461b8bb | ||
![]() |
cbb9b6957f | ||
![]() |
f6b56c9317 | ||
![]() |
3717fb6c8d | ||
![]() |
f6abbc01bd | ||
![]() |
57a71c157d | ||
![]() |
cc76aeb7bb | ||
![]() |
811cabf8a9 | ||
![]() |
bf8d2f93d2 | ||
![]() |
07d8259ad6 | ||
![]() |
a00d412008 | ||
![]() |
5fb39658f1 | ||
![]() |
b0703b92c3 | ||
![]() |
dd9fd3d8a7 | ||
![]() |
cf0c59864f | ||
![]() |
4c0404c70d | ||
![]() |
573a413ee1 | ||
![]() |
f633e6ca49 | ||
![]() |
07b06d76be | ||
![]() |
856fe2da15 | ||
![]() |
f82aae65cd | ||
![]() |
3fbd11a104 | ||
![]() |
58a99f1907 | ||
![]() |
cf86dfd317 | ||
![]() |
a057b4f6d8 | ||
![]() |
62b03cfddf | ||
![]() |
18b827b979 | ||
![]() |
0a379fc514 | ||
![]() |
445c11b8d9 | ||
![]() |
8d290ad509 | ||
![]() |
b90c48b50f | ||
![]() |
d19e7db09e | ||
![]() |
9939904b02 | ||
![]() |
ca23b15f5c | ||
![]() |
ffa676f577 | ||
![]() |
6d023c4df3 | ||
![]() |
b31bd37a30 | ||
![]() |
78faee8c7c | ||
![]() |
40e2a703d0 | ||
![]() |
b01edcb9bc | ||
![]() |
f7fffc9be8 | ||
![]() |
50e8634097 | ||
![]() |
e3994e517e | ||
![]() |
2bb7785189 | ||
![]() |
90c8408111 | ||
![]() |
64786ec12a | ||
![]() |
b3c82f8886 | ||
![]() |
063259dc52 | ||
![]() |
b4c9d9c2a7 | ||
![]() |
fa2b59df4b | ||
![]() |
f41a169460 | ||
![]() |
f567083006 | ||
![]() |
a2a677e539 | ||
![]() |
9123c0b733 | ||
![]() |
788e3b31e1 | ||
![]() |
71f0ed8b74 | ||
![]() |
ac2e4e593d | ||
![]() |
edaa7d7748 | ||
![]() |
3cdf965fba | ||
![]() |
6b60d1e71f | ||
![]() |
7b7fb5acd5 | ||
![]() |
0a7d612f41 | ||
![]() |
38da76bbe0 | ||
![]() |
a13e045742 | ||
![]() |
811620c0a0 | ||
![]() |
504f5f7bdd | ||
![]() |
32bcad51b8 |
36
.travis.yml
Normal file
36
.travis.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
dist: trusty
|
||||||
|
language: cpp
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libcppunit-dev
|
||||||
|
- libboost-dev
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- MAKEFLAGS="-j2"
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
# C++14
|
||||||
|
- test "$TRAVIS_OS_NAME" != "linux" || sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
|
- test "$TRAVIS_OS_NAME" != "linux" || sudo apt-get update -qq
|
||||||
|
- test "$TRAVIS_OS_NAME" != "osx" || brew update
|
||||||
|
|
||||||
|
install:
|
||||||
|
# C++14
|
||||||
|
- test "$TRAVIS_OS_NAME" != "linux" || sudo apt-get install -qq g++-5
|
||||||
|
- test "$TRAVIS_OS_NAME" != "osx" || brew install cppunit
|
||||||
|
|
||||||
|
script:
|
||||||
|
- OPTIONS="--enable-test"
|
||||||
|
- test "$TRAVIS_OS_NAME" != "linux" || export CC=gcc-5 CXX=g++-5
|
||||||
|
- test "$TRAVIS_OS_NAME" != "osx" || OPTIONS="$OPTIONS --enable-osx"
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure --disable-silent-rules --disable-dependency-tracking $OPTIONS
|
||||||
|
- make
|
||||||
|
- make check
|
1
AUTHORS
1
AUTHORS
@@ -30,3 +30,4 @@ The following people have contributed code to MPD:
|
|||||||
Jurgen Kramer <gtmkramer@xs4all.nl>
|
Jurgen Kramer <gtmkramer@xs4all.nl>
|
||||||
Jean-Francois Dockes <jf@dockes.org>
|
Jean-Francois Dockes <jf@dockes.org>
|
||||||
Yue Wang <yuleopen@gmail.com>
|
Yue Wang <yuleopen@gmail.com>
|
||||||
|
Matthew Leon Grinshpun <ml@matthewleon.com>
|
||||||
|
206
INSTALL
206
INSTALL
@@ -1,206 +0,0 @@
|
|||||||
Music Player Daemon (MPD) - INSTALL
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
This document is a very small amount of documentation about what is needed to
|
|
||||||
install MPD. If more information is desired, read the user manual:
|
|
||||||
|
|
||||||
http://www.musicpd.org/doc/user/
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
------------
|
|
||||||
|
|
||||||
gcc 4.7 or later - http://gcc.gnu.org/
|
|
||||||
clang 3.2 or later - http://clang.llvm.org/
|
|
||||||
Any other C++11 compliant compiler should also work.
|
|
||||||
|
|
||||||
Boost 1.46 - http://www.boost.org/
|
|
||||||
|
|
||||||
|
|
||||||
Optional Output Dependencies
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
You will need at least one of these to compile MPD.
|
|
||||||
|
|
||||||
Most of these are available as packages on major distributions. Be sure to
|
|
||||||
install both the library package as well as the development package.
|
|
||||||
|
|
||||||
AO - http://www.xiph.org/ao/
|
|
||||||
A portable library that abstracts many audio output types as one API. Should
|
|
||||||
be used only if there is no native plugin available or if the native plugin
|
|
||||||
doesn't work. You will need libao.
|
|
||||||
|
|
||||||
ALSA - http://www.alsa-project.org/
|
|
||||||
The Advanced Linux Sound Architecture. Recommended audio output if you use
|
|
||||||
Linux. You will need libasound.
|
|
||||||
|
|
||||||
FIFO
|
|
||||||
This is a mostly undocumented, developer plugin to transmit raw data.
|
|
||||||
|
|
||||||
OSS - http://www.opensound.com
|
|
||||||
Open Sound System.
|
|
||||||
|
|
||||||
PulseAudio - http://www.pulseaudio.org/
|
|
||||||
An advanced sound daemon. You will need libpulse.
|
|
||||||
|
|
||||||
JACK - http://www.jackaudio.org/
|
|
||||||
A low-latency sound daemon.
|
|
||||||
|
|
||||||
libshout - http://www.icecast.org/
|
|
||||||
For streaming to an Icecast or Shoutcast server.
|
|
||||||
You also need an encoder: either libvorbisenc (ogg), or liblame (mp3).
|
|
||||||
|
|
||||||
OpenAL - http://kcat.strangesoft.net/openal.html
|
|
||||||
Open Audio Library
|
|
||||||
|
|
||||||
|
|
||||||
Optional Input Dependencies
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
You will need at least one of these to compile MPD.
|
|
||||||
|
|
||||||
Most of these are available as packages on major distributions. Be sure to
|
|
||||||
install both the library package as well as the development package.
|
|
||||||
|
|
||||||
MAD - http://www.underbit.com/products/mad/
|
|
||||||
For MP3 support. You will need libmad, and optionally libid3tag if you want
|
|
||||||
ID3 tag support.
|
|
||||||
|
|
||||||
libmpg123 - http://www.mpg123.de/
|
|
||||||
Alternative for MP3 support.
|
|
||||||
|
|
||||||
Ogg Vorbis - http://www.xiph.org/ogg/vorbis/
|
|
||||||
For Ogg Vorbis support. You will need libogg and libvorbis.
|
|
||||||
|
|
||||||
libopus - http://www.opus-codec.org/
|
|
||||||
Opus codec support
|
|
||||||
|
|
||||||
FLAC - http://flac.sourceforge.net/
|
|
||||||
For FLAC support. You will need version 1.2 or higher of libFLAC.
|
|
||||||
|
|
||||||
Audio File - http://www.68k.org/~michael/audiofile/
|
|
||||||
For WAVE, AIFF, and AU support. You will need libaudiofile.
|
|
||||||
|
|
||||||
FAAD2 - http://www.audiocoding.com/
|
|
||||||
For MP4/AAC support.
|
|
||||||
|
|
||||||
libmpcdec - http://www.musepack.net/
|
|
||||||
For Musepack support.
|
|
||||||
|
|
||||||
MikMod - http://mikmod.raphnet.net/
|
|
||||||
For MOD support. You will need libmikmod.
|
|
||||||
|
|
||||||
libavcodec, libavformat (ffmpeg or libav) - http://ffmpeg.mplayerhq.hu/ http://libav.org/
|
|
||||||
Multi-codec library.
|
|
||||||
|
|
||||||
libsidplay2 - http://sidplay2.sourceforge.net/
|
|
||||||
For C64 SID support.
|
|
||||||
|
|
||||||
libfluidsynth - http://fluidsynth.resonance.org/
|
|
||||||
For MIDI support.
|
|
||||||
|
|
||||||
libwildmidi 0.2.3 - http://wildmidi.sourceforge.net/
|
|
||||||
For MIDI support.
|
|
||||||
|
|
||||||
libsndfile - http://www.mega-nerd.com/libsndfile/
|
|
||||||
WAVE, AIFF, and many others.
|
|
||||||
|
|
||||||
libwavpack - http://www.wavpack.com/
|
|
||||||
For WavPack playback.
|
|
||||||
|
|
||||||
libadplug - http://adplug.sourceforge.net/
|
|
||||||
For AdLib playback.
|
|
||||||
|
|
||||||
|
|
||||||
Optional Miscellaneous Dependencies
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Avahi - http://www.avahi.org/
|
|
||||||
For Zeroconf support.
|
|
||||||
|
|
||||||
libsamplerate - http://www.mega-nerd.com/SRC/
|
|
||||||
For advanced samplerate conversions.
|
|
||||||
|
|
||||||
libcurl - http://curl.haxx.se/
|
|
||||||
For playing HTTP streams.
|
|
||||||
|
|
||||||
libmms - https://launchpad.net/libmms
|
|
||||||
For playing MMS streams.
|
|
||||||
|
|
||||||
SQLite - http://www.sqlite.org/
|
|
||||||
For the sticker database.
|
|
||||||
|
|
||||||
libcdio - http://www.gnu.org/software/libcdio/
|
|
||||||
For playing audio CDs.
|
|
||||||
|
|
||||||
libsystemd-daemon - http://freedesktop.org/wiki/Software/systemd/
|
|
||||||
For systemd activation.
|
|
||||||
|
|
||||||
|
|
||||||
pkg-config
|
|
||||||
----------
|
|
||||||
|
|
||||||
MPD uses pkg-config to locate most external libraries. If you do not
|
|
||||||
have pkg-config, or if your version of the library does not ship the
|
|
||||||
".pc" file, you have to provide the library's build options in
|
|
||||||
environment variables. These variables are documented in "./configure
|
|
||||||
--help". Example:
|
|
||||||
|
|
||||||
FLAC_CFLAGS=-I/usr/include/FLAC FLAC_LIBS=-lFLAC ./configure
|
|
||||||
|
|
||||||
|
|
||||||
Download
|
|
||||||
--------
|
|
||||||
|
|
||||||
Get the latest release from of MPD from <http://www.musicpd.org/>.
|
|
||||||
|
|
||||||
Compile
|
|
||||||
-------
|
|
||||||
|
|
||||||
1) unpack the archive
|
|
||||||
|
|
||||||
$ tar xf mpd-x.x.x.tar.xz
|
|
||||||
|
|
||||||
2) change to directory created
|
|
||||||
|
|
||||||
$ cd mpd-x.x.x
|
|
||||||
|
|
||||||
3) Run configure script (this will determine what dependencies you have)
|
|
||||||
|
|
||||||
$ ./configure
|
|
||||||
|
|
||||||
4) Compile
|
|
||||||
|
|
||||||
$ make
|
|
||||||
|
|
||||||
Install (Optional)
|
|
||||||
-------
|
|
||||||
|
|
||||||
(as root)
|
|
||||||
$ make install
|
|
||||||
|
|
||||||
Run
|
|
||||||
---
|
|
||||||
|
|
||||||
1) run mpd:
|
|
||||||
|
|
||||||
$ mpd <config file>
|
|
||||||
|
|
||||||
First default is $XDG_CONFIG_HOME/mpd/mpd.conf then ~/.mpdconf then
|
|
||||||
~/.mpd/mpd.conf then /etc/mpd.conf. If neither of these exist a mpd
|
|
||||||
configuration file must be specified at runtime.
|
|
||||||
|
|
||||||
A sample config file is included with the source of MPD, mpdconf.example.
|
|
||||||
|
|
||||||
The first time MPD is run it will attempt to discover all music in your
|
|
||||||
music root, recursively. This can be affected by the symbolic link
|
|
||||||
options specified in the example mpd.conf.
|
|
||||||
|
|
||||||
Using MPD
|
|
||||||
---------
|
|
||||||
|
|
||||||
You can download many different interfaces for MPD at
|
|
||||||
|
|
||||||
http://www.musicpd.org/clients/
|
|
@@ -243,6 +243,7 @@ CURL_SOURCES = \
|
|||||||
src/lib/curl/Slist.hxx
|
src/lib/curl/Slist.hxx
|
||||||
|
|
||||||
UPNP_SOURCES = \
|
UPNP_SOURCES = \
|
||||||
|
src/lib/upnp/Compat.hxx \
|
||||||
src/lib/upnp/Init.cxx src/lib/upnp/Init.hxx \
|
src/lib/upnp/Init.cxx src/lib/upnp/Init.hxx \
|
||||||
src/lib/upnp/ClientInit.cxx src/lib/upnp/ClientInit.hxx \
|
src/lib/upnp/ClientInit.cxx src/lib/upnp/ClientInit.hxx \
|
||||||
src/lib/upnp/Device.cxx src/lib/upnp/Device.hxx \
|
src/lib/upnp/Device.cxx src/lib/upnp/Device.hxx \
|
||||||
@@ -518,6 +519,8 @@ libevent_a_SOURCES = \
|
|||||||
# UTF-8 library
|
# UTF-8 library
|
||||||
|
|
||||||
libicu_a_SOURCES = \
|
libicu_a_SOURCES = \
|
||||||
|
src/lib/icu/CaseFold.cxx src/lib/icu/CaseFold.hxx \
|
||||||
|
src/lib/icu/Compare.cxx src/lib/icu/Compare.hxx \
|
||||||
src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \
|
src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \
|
||||||
src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx
|
src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx
|
||||||
|
|
||||||
@@ -923,6 +926,7 @@ libtag_a_SOURCES =\
|
|||||||
src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \
|
src/tag/ReplayGain.cxx src/tag/ReplayGain.hxx \
|
||||||
src/tag/MixRamp.cxx src/tag/MixRamp.hxx \
|
src/tag/MixRamp.cxx src/tag/MixRamp.hxx \
|
||||||
src/tag/Generic.cxx src/tag/Generic.hxx \
|
src/tag/Generic.cxx src/tag/Generic.hxx \
|
||||||
|
src/tag/Id3MusicBrainz.cxx src/tag/Id3MusicBrainz.hxx \
|
||||||
src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \
|
src/tag/ApeLoader.cxx src/tag/ApeLoader.hxx \
|
||||||
src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \
|
src/tag/ApeReplayGain.cxx src/tag/ApeReplayGain.hxx \
|
||||||
src/tag/ApeTag.cxx src/tag/ApeTag.hxx
|
src/tag/ApeTag.cxx src/tag/ApeTag.hxx
|
||||||
@@ -1489,6 +1493,8 @@ liboutput_plugins_a_SOURCES += \
|
|||||||
src/output/plugins/OSXOutputPlugin.cxx \
|
src/output/plugins/OSXOutputPlugin.cxx \
|
||||||
src/output/plugins/OSXOutputPlugin.hxx
|
src/output/plugins/OSXOutputPlugin.hxx
|
||||||
endif
|
endif
|
||||||
|
libmixer_plugins_a_SOURCES += \
|
||||||
|
src/mixer/plugins/OSXMixerPlugin.cxx
|
||||||
|
|
||||||
if ENABLE_PULSE
|
if ENABLE_PULSE
|
||||||
liboutput_plugins_a_SOURCES += \
|
liboutput_plugins_a_SOURCES += \
|
||||||
|
59
NEWS
59
NEWS
@@ -1,3 +1,62 @@
|
|||||||
|
ver 0.20.12 (2017/11/25)
|
||||||
|
* database
|
||||||
|
- upnp: adapt to libupnp 1.8 API changes
|
||||||
|
* input
|
||||||
|
- cdio_paranoia, ffmpeg, file, smbclient: reduce lock contention,
|
||||||
|
fixing lots of xrun problems
|
||||||
|
- curl: fix seeking
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: fix GCC 8 warning
|
||||||
|
- vorbis: fix Tremor support
|
||||||
|
* player
|
||||||
|
- log message when decoder is too slow
|
||||||
|
* encoder
|
||||||
|
- vorbis: default to quality 3
|
||||||
|
* output
|
||||||
|
- fix hanging playback with soxr resampler
|
||||||
|
- httpd: flush encoder after tag; fixes corrupt Vorbis stream
|
||||||
|
|
||||||
|
ver 0.20.11 (2017/10/18)
|
||||||
|
* storage
|
||||||
|
- curl: support Content-Type application/xml
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: more reliable song duration
|
||||||
|
- gme: fix track numbering
|
||||||
|
* improve random song order when switching songs manually
|
||||||
|
* fix case insensitive search without libicu
|
||||||
|
* fix Unicode file names in playlists on Windows
|
||||||
|
* fix endless loop when accessing malformed file names in ZIP files
|
||||||
|
|
||||||
|
ver 0.20.10 (2017/08/24)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: support MusicBrainz ID3v2 tags
|
||||||
|
* tags
|
||||||
|
- aiff: fix FORM chunk size endianess (is big-endian)
|
||||||
|
* mixer
|
||||||
|
- osx: add a mixer for OSX.
|
||||||
|
* fix crash when resuming playback before decoder is ready
|
||||||
|
* fix crash on Windows
|
||||||
|
|
||||||
|
ver 0.20.9 (2017/06/04)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: support *.adx
|
||||||
|
* fix byte order detection on FreeBSD/aarch64
|
||||||
|
* fix more random crashes when compiled with clang
|
||||||
|
|
||||||
|
ver 0.20.8 (2017/05/19)
|
||||||
|
* output
|
||||||
|
- osx: fix build failure due to missing "noexcept"
|
||||||
|
* playlist
|
||||||
|
- m3u: support MIME type `audio/mpegurl`
|
||||||
|
* fix build failure with GCC 4.x
|
||||||
|
|
||||||
|
ver 0.20.7 (2017/05/15)
|
||||||
|
* database
|
||||||
|
- simple: fix false positive directory loop detection with NFS
|
||||||
|
* enforce a reasonable minimum audio_buffer_size setting
|
||||||
|
* cap buffer_before_play at 80% to prevent deadlock
|
||||||
|
* fix random crashes when compiled with clang
|
||||||
|
|
||||||
ver 0.20.6 (2017/03/10)
|
ver 0.20.6 (2017/03/10)
|
||||||
* input
|
* input
|
||||||
- curl: fix headers after HTTP redirect to Shoutcast server
|
- curl: fix headers after HTTP redirect to Shoutcast server
|
||||||
|
@@ -7,14 +7,15 @@ server's audio device. The daemon stores info about all available music,
|
|||||||
and this info can be easily searched and retrieved. Player control, info
|
and this info can be easily searched and retrieved. Player control, info
|
||||||
retrieval, and playlist management can all be managed remotely.
|
retrieval, and playlist management can all be managed remotely.
|
||||||
|
|
||||||
For basic installation information see the INSTALL file.
|
For basic installation instructions
|
||||||
|
[read the manual](https://www.musicpd.org/doc/user/install.html).
|
||||||
|
|
||||||
# Users
|
# Users
|
||||||
|
|
||||||
- [Manual](http://www.musicpd.org/doc/user/)
|
- [Manual](http://www.musicpd.org/doc/user/)
|
||||||
- [Forum](http://forum.musicpd.org/)
|
- [Forum](http://forum.musicpd.org/)
|
||||||
- [IRC](irc://chat.freenode.net/#mpd)
|
- [IRC](irc://chat.freenode.net/#mpd)
|
||||||
- [Bug tracker](http://bugs.musicpd.org/)
|
- [Bug tracker](https://github.com/MusicPlayerDaemon/MPD/issues/)
|
||||||
|
|
||||||
# Developers
|
# Developers
|
||||||
|
|
||||||
|
@@ -154,5 +154,9 @@ configure = [
|
|||||||
|
|
||||||
] + configure_args
|
] + configure_args
|
||||||
|
|
||||||
|
from build.cmdline import concatenate_cmdline_variables
|
||||||
|
configure = concatenate_cmdline_variables(configure,
|
||||||
|
set(('CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'LIBS')))
|
||||||
|
|
||||||
subprocess.check_call(configure, env=toolchain.env)
|
subprocess.check_call(configure, env=toolchain.env)
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)
|
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)
|
||||||
|
10
configure.ac
10
configure.ac
@@ -1,10 +1,10 @@
|
|||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
|
|
||||||
AC_INIT(mpd, 0.20.6, musicpd-dev-team@lists.sourceforge.net)
|
AC_INIT(mpd, 0.20.12, musicpd-dev-team@lists.sourceforge.net)
|
||||||
|
|
||||||
VERSION_MAJOR=0
|
VERSION_MAJOR=0
|
||||||
VERSION_MINOR=20
|
VERSION_MINOR=20
|
||||||
VERSION_REVISION=6
|
VERSION_REVISION=12
|
||||||
VERSION_EXTRA=0
|
VERSION_EXTRA=0
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/Main.cxx])
|
AC_CONFIG_SRCDIR([src/Main.cxx])
|
||||||
@@ -241,6 +241,7 @@ AC_CHECK_FUNCS(getpwnam_r getpwuid_r)
|
|||||||
AC_CHECK_FUNCS(initgroups)
|
AC_CHECK_FUNCS(initgroups)
|
||||||
AC_CHECK_FUNCS(fnmatch)
|
AC_CHECK_FUNCS(fnmatch)
|
||||||
AC_CHECK_FUNCS(strndup)
|
AC_CHECK_FUNCS(strndup)
|
||||||
|
AC_CHECK_FUNCS(strcasestr)
|
||||||
|
|
||||||
if test x$host_is_linux = xyes; then
|
if test x$host_is_linux = xyes; then
|
||||||
MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
|
MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
|
||||||
@@ -1384,6 +1385,11 @@ then
|
|||||||
AX_APPEND_COMPILE_FLAGS([-Wcast-qual])
|
AX_APPEND_COMPILE_FLAGS([-Wcast-qual])
|
||||||
AX_APPEND_COMPILE_FLAGS([-Wwrite-strings])
|
AX_APPEND_COMPILE_FLAGS([-Wwrite-strings])
|
||||||
AX_APPEND_COMPILE_FLAGS([-Wsign-compare])
|
AX_APPEND_COMPILE_FLAGS([-Wsign-compare])
|
||||||
|
|
||||||
|
dnl This GCC8 warning for C++17 ABI compatibility is of no
|
||||||
|
dnl interest for us, because we're not a shared library.
|
||||||
|
AX_APPEND_COMPILE_FLAGS([-Wno-noexcept-type])
|
||||||
|
|
||||||
AC_LANG_POP
|
AC_LANG_POP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -97,20 +97,20 @@ Foo(const char *abc, int xyz)
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
MPD sources are managed in a git repository on <ulink
|
MPD sources are managed in a git repository on <ulink
|
||||||
url="http://git.musicpd.org/">git.musicpd.org</ulink>.
|
url="https://github.com/MusicPlayerDaemon/">GitHub</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Always write your code against the latest git:
|
Always write your code against the latest git:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>git clone git://git.musicpd.org/master/mpd.git</programlisting>
|
<programlisting>git clone git://github.com/MusicPlayerDaemon/MPD</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you already have a clone, update it:
|
If you already have a clone, update it:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>git pull --rebase git://git.musicpd.org/master/mpd.git master</programlisting>
|
<programlisting>git pull --rebase git://github.com/MusicPlayerDaemon/MPD master</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can do without "--rebase", but we recommend that you rebase
|
You can do without "--rebase", but we recommend that you rebase
|
||||||
@@ -188,17 +188,7 @@ Foo(const char *abc, int xyz)
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<command>git pull</command> requests are preferred. Regular
|
<command>git pull</command> requests are preferred.
|
||||||
contributors can get <ulink
|
|
||||||
url="http://git.musicpd.org/account-policy.html">an account on
|
|
||||||
git.musicpd.org</ulink>, but any public git repository will do.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
There is <ulink url="https://github.com/MaxKellermann/MPD">a
|
|
||||||
mirror of the <application>MPD</application> git repository on
|
|
||||||
GitHub</ulink>, and you can use that as well to submit pull
|
|
||||||
requests.
|
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ mpd.conf(5), mpc(1)
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
If you find a bug, please report it at
|
If you find a bug, please report it at
|
||||||
.br
|
.br
|
||||||
<\fBhttp://bugs.musicpd.org/bug_report_page.php\fP>.
|
<\fBhttps://github.com/MusicPlayerDaemon/MPD/issues/\fP>.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Max Kellermann <max.kellermann@gmail.com>
|
Max Kellermann <max.kellermann@gmail.com>
|
||||||
|
|
||||||
|
@@ -403,6 +403,15 @@
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Change events accumulate, even while the connection is
|
||||||
|
not in "idle" mode; no events gets lost while the client
|
||||||
|
is doing something else with the connection. If an
|
||||||
|
event had already occurred since the last call, the new
|
||||||
|
<command>idle</command> command will return immediately.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
While a client is waiting for <command>idle</command>
|
While a client is waiting for <command>idle</command>
|
||||||
results, the server disables timeouts, allowing a client
|
results, the server disables timeouts, allowing a client
|
||||||
@@ -436,7 +445,9 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>volume</varname>:
|
<varname>volume</varname>:
|
||||||
<returnvalue>0-100</returnvalue>
|
<returnvalue>0-100</returnvalue> or
|
||||||
|
<returnvalue>-1</returnvalue> if the volume cannot
|
||||||
|
be determined
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
251
doc/user.xml
251
doc/user.xml
@@ -80,13 +80,40 @@
|
|||||||
cd mpd-version</programlisting>
|
cd mpd-version</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Make sure that all the required libraries and build tools are
|
In any case, you need:
|
||||||
installed. The <filename>INSTALL</filename> file has a list.
|
</para>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
a C++14 compiler (e.g. <ulink
|
||||||
|
url="http://gcc.gnu.org/">gcc 4.9</ulink> or <ulink
|
||||||
|
url="http://clang.llvm.org/">clang 3.9</ulink>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="http://www.boost.org/">Boost 1.46</ulink>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="https://www.freedesktop.org/wiki/Software/pkg-config/">pkg-config</ulink>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Each plugin usually needs a codec library, which you also need
|
||||||
|
to install. Check the plugin reference for details about
|
||||||
|
required libraries.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For example, the following installs a fairly complete list of
|
For example, the following installs a fairly complete list of
|
||||||
build dependencies on Debian Wheezy:
|
build dependencies on Debian Jessie:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@@ -98,19 +125,20 @@ apt-get install g++ \
|
|||||||
libmpcdec-dev libwavpack-dev libwildmidi-dev \
|
libmpcdec-dev libwavpack-dev libwildmidi-dev \
|
||||||
libsidplay2-dev libsidutils-dev libresid-builder-dev \
|
libsidplay2-dev libsidutils-dev libresid-builder-dev \
|
||||||
libavcodec-dev libavformat-dev \
|
libavcodec-dev libavformat-dev \
|
||||||
libmp3lame-dev \
|
libmp3lame-dev libtwolame-dev libshine-dev \
|
||||||
libsamplerate0-dev libsoxr-dev \
|
libsamplerate0-dev libsoxr-dev \
|
||||||
libbz2-dev libcdio-paranoia-dev libiso9660-dev libmms-dev \
|
libbz2-dev libcdio-paranoia-dev libiso9660-dev libmms-dev \
|
||||||
libzzip-dev \
|
libzzip-dev \
|
||||||
libcurl4-gnutls-dev libyajl-dev libexpat-dev \
|
libcurl4-gnutls-dev libyajl-dev libexpat-dev \
|
||||||
libasound2-dev libao-dev libjack-jackd2-dev libopenal-dev \
|
libasound2-dev libao-dev libjack-jackd2-dev libopenal-dev \
|
||||||
libpulse-dev libroar-dev libshout3-dev \
|
libpulse-dev libroar-dev libshout3-dev \
|
||||||
|
libsndio-dev \
|
||||||
libmpdclient-dev \
|
libmpdclient-dev \
|
||||||
libnfs-dev libsmbclient-dev \
|
libnfs-dev libsmbclient-dev \
|
||||||
libupnp-dev \
|
libupnp-dev \
|
||||||
libavahi-client-dev \
|
libavahi-client-dev \
|
||||||
libsqlite3-dev \
|
libsqlite3-dev \
|
||||||
libsystemd-daemon-dev libwrap0-dev \
|
libsystemd-dev libwrap0-dev \
|
||||||
libcppunit-dev xmlto \
|
libcppunit-dev xmlto \
|
||||||
libboost-dev \
|
libboost-dev \
|
||||||
libicu-dev
|
libicu-dev
|
||||||
@@ -1035,6 +1063,40 @@ systemctl start mpd.socket</programlisting>
|
|||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="stickers">
|
||||||
|
<title>The Sticker Database</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
"Stickers" are pieces of information attached to songs.
|
||||||
|
Some clients use them to store ratings and other volatile
|
||||||
|
data. This feature requires <ulink
|
||||||
|
url="http://www.sqlite.org/">SQLite</ulink>, compile-time
|
||||||
|
configure option <parameter>--enable-sqlite</parameter>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<informaltable>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Setting</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>sticker_file</varname>
|
||||||
|
<parameter>PATH</parameter>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
The location of the sticker database.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</informaltable>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>Resource Limitations</title>
|
<title>Resource Limitations</title>
|
||||||
|
|
||||||
@@ -1165,6 +1227,55 @@ systemctl start mpd.socket</programlisting>
|
|||||||
</tgroup>
|
</tgroup>
|
||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="zeroconf">
|
||||||
|
<title>Zeroconf</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If Zeroconf support (<ulink
|
||||||
|
url="http://avahi.org/">Avahi</ulink> or Apple's Bonjour)
|
||||||
|
was enabled at compile time with
|
||||||
|
<parameter>--with-zeroconf=...</parameter>, MPD can announce
|
||||||
|
its presence on the network. The following settings control
|
||||||
|
this feature:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<informaltable>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Setting</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>zeroconf_enabled</varname>
|
||||||
|
<parameter>yes|no</parameter>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Enables or disables this feature. Default is
|
||||||
|
<parameter>yes</parameter>.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>zeroconf_name</varname>
|
||||||
|
<parameter>NAME</parameter>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
The service name to publish via Zeroconf. The
|
||||||
|
default is "<parameter>Music Player</parameter>".
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</informaltable>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
@@ -1747,7 +1858,7 @@ buffer_size: 16384</programlisting>
|
|||||||
<para>
|
<para>
|
||||||
If you believe you found a bug in
|
If you believe you found a bug in
|
||||||
<application>MPD</application>, report it on <ulink
|
<application>MPD</application>, report it on <ulink
|
||||||
url="https://bugs.musicpd.org/my_view_page.php">the bug
|
url="https://github.com/MusicPlayerDaemon/MPD/issues/">the bug
|
||||||
tracker</ulink>.
|
tracker</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -2078,7 +2189,9 @@ run</programlisting>
|
|||||||
<title><varname>cdio_paranoia</varname></title>
|
<title><varname>cdio_paranoia</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Plays audio CDs. The URI has the form:
|
Plays audio CDs using <ulink
|
||||||
|
url="http://www.gnu.org/software/libcdio/"><filename>libcdio</filename></ulink>.
|
||||||
|
The URI has the form:
|
||||||
"<filename>cdda://[DEVICE][/TRACK]</filename>". The
|
"<filename>cdda://[DEVICE][/TRACK]</filename>". The
|
||||||
simplest form <filename>cdda://</filename> plays the whole
|
simplest form <filename>cdda://</filename> plays the whole
|
||||||
disc in the default drive.
|
disc in the default drive.
|
||||||
@@ -2114,7 +2227,8 @@ run</programlisting>
|
|||||||
<title><varname>curl</varname></title>
|
<title><varname>curl</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Opens remote files or streams over HTTP.
|
Opens remote files or streams over HTTP using <ulink
|
||||||
|
url="http://curl.haxx.se/"><filename>libcurl</filename></ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -2207,7 +2321,8 @@ run</programlisting>
|
|||||||
<title><varname>mms</varname></title>
|
<title><varname>mms</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Plays streams with the MMS protocol.
|
Plays streams with the MMS protocol using <ulink
|
||||||
|
url="https://launchpad.net/libmms"><filename>libmms</filename></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2263,7 +2378,8 @@ run</programlisting>
|
|||||||
<title><varname>adplug</varname></title>
|
<title><varname>adplug</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes AdLib files.
|
Decodes AdLib files using <ulink
|
||||||
|
url="http://adplug.sourceforge.net/">libadplug</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<informaltable>
|
<informaltable>
|
||||||
@@ -2294,8 +2410,8 @@ run</programlisting>
|
|||||||
<title><varname>audiofile</varname></title>
|
<title><varname>audiofile</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes WAV and AIFF files using
|
Decodes WAV and AIFF files using <ulink
|
||||||
<filename>libaudiofile</filename>.
|
url="http://audiofile.68k.org/"><filename>libaudiofile</filename></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2303,7 +2419,8 @@ run</programlisting>
|
|||||||
<title><varname>faad</varname></title>
|
<title><varname>faad</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes AAC files using <filename>libfaad</filename>.
|
Decodes AAC files using <ulink
|
||||||
|
url="http://www.audiocoding.com/"><filename>libfaad</filename></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2311,8 +2428,8 @@ run</programlisting>
|
|||||||
<title><varname>ffmpeg</varname></title>
|
<title><varname>ffmpeg</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes various codecs using
|
Decodes various codecs using <ulink
|
||||||
<application>FFmpeg</application>.
|
url="https://ffmpeg.org/"><application>FFmpeg</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<informaltable>
|
<informaltable>
|
||||||
@@ -2363,7 +2480,7 @@ run</programlisting>
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes FLAC files using
|
Decodes FLAC files using
|
||||||
<application>libFLAC</application>.
|
<ulink url="https://xiph.org/flac/"><application>libFLAC</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2483,7 +2600,8 @@ run</programlisting>
|
|||||||
<title><varname>mad</varname></title>
|
<title><varname>mad</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes MP3 files using <application>libmad</application>.
|
Decodes MP3 files using <ulink
|
||||||
|
url="http://www.underbit.com/products/mad/"><application>libmad</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2563,8 +2681,8 @@ run</programlisting>
|
|||||||
<title><varname>mpcdec</varname></title>
|
<title><varname>mpcdec</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes Musepack files using
|
Decodes Musepack files using <ulink
|
||||||
<application>libmpcdec</application>.
|
url="http://www.musepack.net/"><application>libmpcdec</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2572,7 +2690,17 @@ run</programlisting>
|
|||||||
<title><varname>mpg123</varname></title>
|
<title><varname>mpg123</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes MP3 files using <application>libmpg123</application>.
|
Decodes MP3 files using <ulink
|
||||||
|
url="http://www.mpg123.de/"><application>libmpg123</application></ulink>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="opus_decoder">
|
||||||
|
<title><varname>opus</varname></title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Decodes Opus files using <ulink
|
||||||
|
url="http://www.opus-codec.org/"><application>libopus</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2592,8 +2720,8 @@ run</programlisting>
|
|||||||
<title><varname>sidplay</varname></title>
|
<title><varname>sidplay</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
C64 SID decoder based on
|
C64 SID decoder based on <ulink
|
||||||
<application>libsidplay</application>.
|
url="http://sidplay2.sourceforge.net/"><application>libsidplay</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<informaltable>
|
<informaltable>
|
||||||
@@ -2649,8 +2777,8 @@ run</programlisting>
|
|||||||
<title><varname>sndfile</varname></title>
|
<title><varname>sndfile</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes WAV and AIFF files using
|
Decodes WAV and AIFF files using <ulink
|
||||||
<filename>libsndfile</filename>.
|
url="http://www.mega-nerd.com/libsndfile/"><filename>libsndfile</filename></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2658,8 +2786,8 @@ run</programlisting>
|
|||||||
<title><varname>vorbis</varname></title>
|
<title><varname>vorbis</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes Ogg-Vorbis files using
|
Decodes Ogg-Vorbis files using <ulink
|
||||||
<application>libvorbis</application>.
|
url="http://www.xiph.org/ogg/vorbis/"><application>libvorbis</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2668,7 +2796,7 @@ run</programlisting>
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
Decodes WavPack files using
|
Decodes WavPack files using
|
||||||
<application>libwavpack</application>.
|
<ulink url="http://www.wavpack.com/"><application>libwavpack</application></ulink>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -2863,6 +2991,60 @@ run</programlisting>
|
|||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="opus_encoder">
|
||||||
|
<title><varname>opus</varname></title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Encodes into <ulink
|
||||||
|
url="http://www.opus-codec.org/">Ogg Opus</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<informaltable>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Setting</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>bitrate</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the data rate in bit per second. The special
|
||||||
|
value "auto" lets <application>libopus</application>
|
||||||
|
choose a rate (which is the default), and "max" uses
|
||||||
|
the maximum possible data rate.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>complexity</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the <ulink
|
||||||
|
url="https://wiki.xiph.org/OpusFAQ#What_is_the_complexity_of_Opus.3F">Opus
|
||||||
|
complexity</ulink>.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>signal</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the Opus signal type. Valid values are "auto"
|
||||||
|
(the default), "voice" and "music".
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</informaltable>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="vorbis_encoder">
|
<section id="vorbis_encoder">
|
||||||
<title><varname>vorbis</varname></title>
|
<title><varname>vorbis</varname></title>
|
||||||
|
|
||||||
@@ -2886,8 +3068,8 @@ run</programlisting>
|
|||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
Sets the quality for VBR. -1 is the lowest quality,
|
Sets the quality for VBR. -1 is the lowest quality,
|
||||||
10 is the highest quality. Cannot be used with
|
10 is the highest quality. Defaults to 3. Cannot
|
||||||
<varname>bitrate</varname>.
|
be used with <varname>bitrate</varname>.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@@ -3492,7 +3674,7 @@ run</programlisting>
|
|||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section id="jack_output">
|
||||||
<title><varname>jack</varname></title>
|
<title><varname>jack</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -3772,7 +3954,7 @@ run</programlisting>
|
|||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section id="openal_output">
|
||||||
<title><varname>openal</varname></title>
|
<title><varname>openal</varname></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -3923,7 +4105,7 @@ run</programlisting>
|
|||||||
<para>
|
<para>
|
||||||
The <varname>pulse</varname> plugin connects to a <ulink
|
The <varname>pulse</varname> plugin connects to a <ulink
|
||||||
url="http://www.freedesktop.org/wiki/Software/PulseAudio/"><application>PulseAudio</application></ulink>
|
url="http://www.freedesktop.org/wiki/Software/PulseAudio/"><application>PulseAudio</application></ulink>
|
||||||
server.
|
server. Requires <filename>libpulse</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<informaltable>
|
<informaltable>
|
||||||
@@ -4080,7 +4262,7 @@ run</programlisting>
|
|||||||
(logical "and") can be used to select portions of
|
(logical "and") can be used to select portions of
|
||||||
the format string depending on the existing tag
|
the format string depending on the existing tag
|
||||||
values. Example:
|
values. Example:
|
||||||
<parameter>~/.mpd/recorder/[%title|%name%].ogg</parameter>
|
<parameter>~/.mpd/recorder/[%title%|%name%].ogg</parameter>
|
||||||
(use the "name" tag if no title exists)
|
(use the "name" tag if no title exists)
|
||||||
</para>
|
</para>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -4111,7 +4293,8 @@ run</programlisting>
|
|||||||
url="http://www.shoutcast.com/"><application>ShoutCast</application></ulink>
|
url="http://www.shoutcast.com/"><application>ShoutCast</application></ulink>
|
||||||
or <ulink
|
or <ulink
|
||||||
url="http://icecast.org/"><application>IceCast</application></ulink>
|
url="http://icecast.org/"><application>IceCast</application></ulink>
|
||||||
server. It forwards tags to this server.
|
server using <filename>libshout</filename>. It forwards
|
||||||
|
tags to this server.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
29
python/build/cmdline.py
Normal file
29
python/build/cmdline.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
def concatenate_cmdline_variables(src, names):
|
||||||
|
"""Find duplicate variable declarations on the given source list, and
|
||||||
|
concatenate the values of those in the 'names' list."""
|
||||||
|
|
||||||
|
# the result list being constructed
|
||||||
|
dest = []
|
||||||
|
|
||||||
|
# a map of variable name to destination list index
|
||||||
|
positions = {}
|
||||||
|
|
||||||
|
for item in src:
|
||||||
|
i = item.find('=')
|
||||||
|
if i > 0:
|
||||||
|
# it's a variable
|
||||||
|
name = item[:i]
|
||||||
|
if name in names:
|
||||||
|
# it's a known variable
|
||||||
|
if name in positions:
|
||||||
|
# already specified: concatenate instead of
|
||||||
|
# appending it
|
||||||
|
dest[positions[name]] += ' ' + item[i + 1:]
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# not yet seen: append it and remember the list
|
||||||
|
# index
|
||||||
|
positions[name] = len(dest)
|
||||||
|
dest.append(item)
|
||||||
|
|
||||||
|
return dest
|
@@ -19,8 +19,8 @@ libvorbis = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
opus = AutotoolsProject(
|
opus = AutotoolsProject(
|
||||||
'http://downloads.xiph.org/releases/opus/opus-1.1.4.tar.gz',
|
'https://archive.mozilla.org/pub/opus/opus-1.2.1.tar.gz',
|
||||||
'9122b6b380081dd2665189f97bfd777f04f92dc3ab6698eea1dbb27ad59d8692',
|
'cfafd339ccd9c5ef8d6ab15d7e1a412c054bf4cb4ecbbbcc78c12ef2def70732',
|
||||||
'lib/libopus.a',
|
'lib/libopus.a',
|
||||||
['--disable-shared', '--enable-static'],
|
['--disable-shared', '--enable-static'],
|
||||||
)
|
)
|
||||||
@@ -36,8 +36,8 @@ flac = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
zlib = ZlibProject(
|
zlib = ZlibProject(
|
||||||
'http://zlib.net/zlib-1.2.8.tar.xz',
|
'http://zlib.net/zlib-1.2.11.tar.xz',
|
||||||
'28f1205d8dd2001f26fec1e8c2cebe37',
|
'4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066',
|
||||||
'lib/libz.a',
|
'lib/libz.a',
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,9 +57,20 @@ libmad = AutotoolsProject(
|
|||||||
autogen=True,
|
autogen=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
liblame = AutotoolsProject(
|
||||||
|
'http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz',
|
||||||
|
'24346b4158e4af3bd9f2e194bb23eb473c75fb7377011523353196b19b9a23ff',
|
||||||
|
'lib/libmp3lame.a',
|
||||||
|
[
|
||||||
|
'--disable-shared', '--enable-static',
|
||||||
|
'--disable-gtktest', '--disable-analyzer-hooks',
|
||||||
|
'--disable-decoder', '--disable-frontend',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-3.2.4.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-3.3.3.tar.xz',
|
||||||
'6e38ff14f080c98b58cf5967573501b8cb586e3a173b591f3807d8f0660daf7a',
|
'd2a9002cdc6b533b59728827186c044ad02ba64841f1b7cd6c21779875453a1e',
|
||||||
'lib/libavcodec.a',
|
'lib/libavcodec.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
@@ -82,8 +93,8 @@ ffmpeg = FfmpegProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
curl = AutotoolsProject(
|
curl = AutotoolsProject(
|
||||||
'http://curl.haxx.se/download/curl-7.52.1.tar.lzma',
|
'http://curl.haxx.se/download/curl-7.55.1.tar.xz',
|
||||||
'44286d4b825936e2430fc44ad730ce899afb736a5d328cbb8b5d42462f3f2365',
|
'3eafca6e84ecb4af5f35795dee84e643d5428287e88c041122bb8dac18676bb7',
|
||||||
'lib/libcurl.a',
|
'lib/libcurl.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
@@ -103,7 +114,7 @@ curl = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
boost = BoostProject(
|
boost = BoostProject(
|
||||||
'http://downloads.sourceforge.net/project/boost/boost/1.63.0/boost_1_63_0.tar.bz2',
|
'http://downloads.sourceforge.net/project/boost/boost/1.65.0/boost_1_65_0.tar.bz2',
|
||||||
'beae2529f759f6b3bf3f4969a19c2e9d6f0c503edcb2de4a61d1428519fcb3b0',
|
'ea26712742e2fb079c2a566a31f3266973b76e38222b9f88b387e3c8b2f9902c',
|
||||||
'include/boost/version.hpp',
|
'include/boost/version.hpp',
|
||||||
)
|
)
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioFormat::ApplyMask(AudioFormat mask)
|
AudioFormat::ApplyMask(AudioFormat mask) noexcept
|
||||||
{
|
{
|
||||||
assert(IsValid());
|
assert(IsValid());
|
||||||
assert(mask.IsMaskValid());
|
assert(mask.IsMaskValid());
|
||||||
@@ -42,7 +42,7 @@ AudioFormat::ApplyMask(AudioFormat mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuffer<24>
|
StringBuffer<24>
|
||||||
ToString(const AudioFormat af)
|
ToString(const AudioFormat af) noexcept
|
||||||
{
|
{
|
||||||
StringBuffer<24> buffer;
|
StringBuffer<24> buffer;
|
||||||
|
|
||||||
|
@@ -124,10 +124,10 @@ struct AudioFormat {
|
|||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyMask(AudioFormat mask);
|
void ApplyMask(AudioFormat mask) noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
AudioFormat WithMask(AudioFormat mask) const {
|
AudioFormat WithMask(AudioFormat mask) const noexcept {
|
||||||
AudioFormat result = *this;
|
AudioFormat result = *this;
|
||||||
result.ApplyMask(mask);
|
result.ApplyMask(mask);
|
||||||
return result;
|
return result;
|
||||||
@@ -223,6 +223,6 @@ AudioFormat::GetTimeToSize() const
|
|||||||
*/
|
*/
|
||||||
gcc_const
|
gcc_const
|
||||||
StringBuffer<24>
|
StringBuffer<24>
|
||||||
ToString(AudioFormat af);
|
ToString(AudioFormat af) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -25,8 +25,6 @@
|
|||||||
#ifndef MPD_AUDIO_PARSER_HXX
|
#ifndef MPD_AUDIO_PARSER_HXX
|
||||||
#define MPD_AUDIO_PARSER_HXX
|
#define MPD_AUDIO_PARSER_HXX
|
||||||
|
|
||||||
#include "Compiler.h"
|
|
||||||
|
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +36,6 @@ struct AudioFormat;
|
|||||||
* @param src the input string
|
* @param src the input string
|
||||||
* @param mask if true, then "*" is allowed for any number of items
|
* @param mask if true, then "*" is allowed for any number of items
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
AudioFormat
|
AudioFormat
|
||||||
ParseAudioFormat(const char *src, bool mask);
|
ParseAudioFormat(const char *src, bool mask);
|
||||||
|
|
||||||
|
@@ -37,19 +37,19 @@ DetachedSong::~DetachedSong()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DetachedSong::IsRemote() const
|
DetachedSong::IsRemote() const noexcept
|
||||||
{
|
{
|
||||||
return uri_has_scheme(GetRealURI());
|
return uri_has_scheme(GetRealURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DetachedSong::IsAbsoluteFile() const
|
DetachedSong::IsAbsoluteFile() const noexcept
|
||||||
{
|
{
|
||||||
return PathTraitsUTF8::IsAbsolute(GetRealURI());
|
return PathTraitsUTF8::IsAbsolute(GetRealURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DetachedSong::IsInDatabase() const
|
DetachedSong::IsInDatabase() const noexcept
|
||||||
{
|
{
|
||||||
/* here, we use GetURI() and not GetRealURI() because
|
/* here, we use GetURI() and not GetRealURI() because
|
||||||
GetRealURI() is never relative */
|
GetRealURI() is never relative */
|
||||||
@@ -59,7 +59,7 @@ DetachedSong::IsInDatabase() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
SignedSongTime
|
SignedSongTime
|
||||||
DetachedSong::GetDuration() const
|
DetachedSong::GetDuration() const noexcept
|
||||||
{
|
{
|
||||||
SongTime a = start_time, b = end_time;
|
SongTime a = start_time, b = end_time;
|
||||||
if (!b.IsPositive()) {
|
if (!b.IsPositive()) {
|
||||||
|
@@ -100,7 +100,7 @@ public:
|
|||||||
~DetachedSong();
|
~DetachedSong();
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetURI() const {
|
const char *GetURI() const noexcept {
|
||||||
return uri.c_str();
|
return uri.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ public:
|
|||||||
* displayed URI?
|
* displayed URI?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool HasRealURI() const {
|
bool HasRealURI() const noexcept {
|
||||||
return !real_uri.empty();
|
return !real_uri.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
* GetURI().
|
* GetURI().
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetRealURI() const {
|
const char *GetRealURI() const noexcept {
|
||||||
return (HasRealURI() ? real_uri : uri).c_str();
|
return (HasRealURI() ? real_uri : uri).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,36 +137,36 @@ public:
|
|||||||
* song.
|
* song.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsSame(const DetachedSong &other) const {
|
bool IsSame(const DetachedSong &other) const noexcept {
|
||||||
return uri == other.uri &&
|
return uri == other.uri &&
|
||||||
start_time == other.start_time &&
|
start_time == other.start_time &&
|
||||||
end_time == other.end_time;
|
end_time == other.end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure gcc_nonnull_all
|
gcc_pure gcc_nonnull_all
|
||||||
bool IsURI(const char *other_uri) const {
|
bool IsURI(const char *other_uri) const noexcept {
|
||||||
return uri == other_uri;
|
return uri == other_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsRemote() const;
|
bool IsRemote() const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsFile() const {
|
bool IsFile() const noexcept {
|
||||||
return !IsRemote();
|
return !IsRemote();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsAbsoluteFile() const;
|
bool IsAbsoluteFile() const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsInDatabase() const;
|
bool IsInDatabase() const noexcept;
|
||||||
|
|
||||||
const Tag &GetTag() const {
|
const Tag &GetTag() const noexcept {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tag &WritableTag() {
|
Tag &WritableTag() noexcept {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
SignedSongTime GetDuration() const;
|
SignedSongTime GetDuration() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the #tag and #mtime.
|
* Update the #tag and #mtime.
|
||||||
|
@@ -96,7 +96,7 @@ io_thread_deinit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
EventLoop &
|
EventLoop &
|
||||||
io_thread_get()
|
io_thread_get() noexcept
|
||||||
{
|
{
|
||||||
assert(io.loop != nullptr);
|
assert(io.loop != nullptr);
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ io_thread_get()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
io_thread_inside(void)
|
io_thread_inside() noexcept
|
||||||
{
|
{
|
||||||
return io.thread.IsInside();
|
return io.thread.IsInside();
|
||||||
}
|
}
|
||||||
|
@@ -51,13 +51,13 @@ io_thread_deinit();
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
EventLoop &
|
EventLoop &
|
||||||
io_thread_get();
|
io_thread_get() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the current thread the I/O thread?
|
* Is the current thread the I/O thread?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool
|
bool
|
||||||
io_thread_inside();
|
io_thread_inside() noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -46,13 +46,13 @@ static const char *const idle_names[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char*const*
|
const char*const*
|
||||||
idle_get_names(void)
|
idle_get_names() noexcept
|
||||||
{
|
{
|
||||||
return idle_names;
|
return idle_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
idle_parse_name(const char *name)
|
idle_parse_name(const char *name) noexcept
|
||||||
{
|
{
|
||||||
#if !CLANG_CHECK_VERSION(3,6)
|
#if !CLANG_CHECK_VERSION(3,6)
|
||||||
/* disabled on clang due to -Wtautological-pointer-compare */
|
/* disabled on clang due to -Wtautological-pointer-compare */
|
||||||
|
@@ -70,8 +70,9 @@ static constexpr unsigned IDLE_MOUNT = 0x1000;
|
|||||||
/**
|
/**
|
||||||
* Get idle names
|
* Get idle names
|
||||||
*/
|
*/
|
||||||
|
gcc_const
|
||||||
const char*const*
|
const char*const*
|
||||||
idle_get_names();
|
idle_get_names() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an idle name and return its mask. Returns 0 if the given
|
* Parse an idle name and return its mask. Returns 0 if the given
|
||||||
@@ -79,6 +80,6 @@ idle_get_names();
|
|||||||
*/
|
*/
|
||||||
gcc_nonnull_all gcc_pure
|
gcc_nonnull_all gcc_pure
|
||||||
unsigned
|
unsigned
|
||||||
idle_parse_name(const char *name);
|
idle_parse_name(const char *name) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -117,7 +117,6 @@ struct Instance final
|
|||||||
* DatabaseError if this MPD configuration has no database (no
|
* DatabaseError if this MPD configuration has no database (no
|
||||||
* music_directory was configured).
|
* music_directory was configured).
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
const Database &GetDatabaseOrThrow() const;
|
const Database &GetDatabaseOrThrow() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
41
src/Main.cxx
41
src/Main.cxx
@@ -117,7 +117,21 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
static constexpr unsigned DEFAULT_BUFFER_SIZE = 4096;
|
static constexpr size_t KILOBYTE = 1024;
|
||||||
|
static constexpr size_t MEGABYTE = 1024 * KILOBYTE;
|
||||||
|
|
||||||
|
static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE;
|
||||||
|
|
||||||
|
static
|
||||||
|
#if GCC_OLDER_THAN(5,0)
|
||||||
|
/* gcc 4.x has no "constexpr" for std::max() */
|
||||||
|
const
|
||||||
|
#else
|
||||||
|
constexpr
|
||||||
|
#endif
|
||||||
|
size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32,
|
||||||
|
64 * KILOBYTE);
|
||||||
|
|
||||||
static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10;
|
static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10;
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
@@ -130,7 +144,6 @@ struct Config {
|
|||||||
ReplayGainConfig replay_gain;
|
ReplayGainConfig replay_gain;
|
||||||
};
|
};
|
||||||
|
|
||||||
gcc_const
|
|
||||||
static Config
|
static Config
|
||||||
LoadConfig()
|
LoadConfig()
|
||||||
{
|
{
|
||||||
@@ -307,12 +320,17 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
|
|||||||
FormatFatalError("buffer size \"%s\" is not a "
|
FormatFatalError("buffer size \"%s\" is not a "
|
||||||
"positive integer, line %i",
|
"positive integer, line %i",
|
||||||
param->value.c_str(), param->line);
|
param->value.c_str(), param->line);
|
||||||
buffer_size = tmp;
|
buffer_size = tmp * KILOBYTE;
|
||||||
|
|
||||||
|
if (buffer_size < MIN_BUFFER_SIZE) {
|
||||||
|
FormatWarning(config_domain, "buffer size %lu is too small, using %lu bytes instead",
|
||||||
|
(unsigned long)buffer_size,
|
||||||
|
(unsigned long)MIN_BUFFER_SIZE);
|
||||||
|
buffer_size = MIN_BUFFER_SIZE;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
buffer_size = DEFAULT_BUFFER_SIZE;
|
buffer_size = DEFAULT_BUFFER_SIZE;
|
||||||
|
|
||||||
buffer_size *= 1024;
|
|
||||||
|
|
||||||
const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
|
const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
|
||||||
|
|
||||||
if (buffered_chunks >= 1 << 15)
|
if (buffered_chunks >= 1 << 15)
|
||||||
@@ -330,6 +348,19 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
|
|||||||
"than 100 percent, line %i",
|
"than 100 percent, line %i",
|
||||||
param->value.c_str(), param->line);
|
param->value.c_str(), param->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (perc > 80) {
|
||||||
|
/* this upper limit should avoid deadlocks
|
||||||
|
which can occur because the DecoderThread
|
||||||
|
cannot ever fill the music buffer to
|
||||||
|
exactly 100%; a few chunks always need to
|
||||||
|
be available to generate silence in
|
||||||
|
Player::SendSilence() */
|
||||||
|
FormatError(config_domain,
|
||||||
|
"buffer_before_play is too large (%f%%), capping at 80%%; please fix your configuration",
|
||||||
|
perc);
|
||||||
|
perc = 80;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
perc = DEFAULT_BUFFER_BEFORE_PLAY;
|
perc = DEFAULT_BUFFER_BEFORE_PLAY;
|
||||||
|
|
||||||
|
@@ -59,14 +59,14 @@ mapper_init(AllocatedPath &&_playlist_dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mapper_finish()
|
mapper_finish() noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
map_uri_fs(const char *uri)
|
map_uri_fs(const char *uri) noexcept
|
||||||
{
|
{
|
||||||
assert(uri != nullptr);
|
assert(uri != nullptr);
|
||||||
assert(*uri != '/');
|
assert(*uri != '/');
|
||||||
@@ -86,7 +86,7 @@ map_uri_fs(const char *uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
map_fs_to_utf8(Path path_fs)
|
map_fs_to_utf8(Path path_fs) noexcept
|
||||||
{
|
{
|
||||||
if (path_fs.IsAbsolute()) {
|
if (path_fs.IsAbsolute()) {
|
||||||
if (instance->storage == nullptr)
|
if (instance->storage == nullptr)
|
||||||
@@ -109,13 +109,13 @@ map_fs_to_utf8(Path path_fs)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
const AllocatedPath &
|
const AllocatedPath &
|
||||||
map_spl_path()
|
map_spl_path() noexcept
|
||||||
{
|
{
|
||||||
return playlist_dir_fs;
|
return playlist_dir_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
map_spl_utf8_to_fs(const char *name)
|
map_spl_utf8_to_fs(const char *name) noexcept
|
||||||
{
|
{
|
||||||
if (playlist_dir_fs.IsNull())
|
if (playlist_dir_fs.IsNull())
|
||||||
return AllocatedPath::Null();
|
return AllocatedPath::Null();
|
||||||
|
@@ -37,7 +37,7 @@ void
|
|||||||
mapper_init(AllocatedPath &&playlist_dir);
|
mapper_init(AllocatedPath &&playlist_dir);
|
||||||
|
|
||||||
void
|
void
|
||||||
mapper_finish();
|
mapper_finish() noexcept;
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ mapper_finish();
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
map_uri_fs(const char *uri);
|
map_uri_fs(const char *uri) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a file system path (relative to the music directory or
|
* Maps a file system path (relative to the music directory or
|
||||||
@@ -60,7 +60,7 @@ map_uri_fs(const char *uri);
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
std::string
|
std::string
|
||||||
map_fs_to_utf8(Path path_fs);
|
map_fs_to_utf8(Path path_fs) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ map_fs_to_utf8(Path path_fs);
|
|||||||
*/
|
*/
|
||||||
gcc_const
|
gcc_const
|
||||||
const AllocatedPath &
|
const AllocatedPath &
|
||||||
map_spl_path();
|
map_spl_path() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a playlist name (without the ".m3u" suffix) to a file system
|
* Maps a playlist name (without the ".m3u" suffix) to a file system
|
||||||
@@ -79,6 +79,6 @@ map_spl_path();
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
map_spl_utf8_to_fs(const char *name);
|
map_spl_utf8_to_fs(const char *name) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -31,45 +31,45 @@ class MixRampInfo {
|
|||||||
public:
|
public:
|
||||||
MixRampInfo() = default;
|
MixRampInfo() = default;
|
||||||
|
|
||||||
void Clear() {
|
void Clear() noexcept {
|
||||||
start.clear();
|
start.clear();
|
||||||
end.clear();
|
end.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsDefined() const {
|
bool IsDefined() const noexcept {
|
||||||
return !start.empty() || !end.empty();
|
return !start.empty() || !end.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetStart() const {
|
const char *GetStart() const noexcept {
|
||||||
return start.empty() ? nullptr : start.c_str();
|
return start.empty() ? nullptr : start.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetEnd() const {
|
const char *GetEnd() const noexcept {
|
||||||
return end.empty() ? nullptr : end.c_str();
|
return end.empty() ? nullptr : end.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStart(const char *new_value) {
|
void SetStart(const char *new_value) noexcept {
|
||||||
if (new_value == nullptr)
|
if (new_value == nullptr)
|
||||||
start.clear();
|
start.clear();
|
||||||
else
|
else
|
||||||
start = new_value;
|
start = new_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStart(std::string &&new_value) {
|
void SetStart(std::string &&new_value) noexcept {
|
||||||
start = std::move(new_value);
|
start = std::move(new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEnd(const char *new_value) {
|
void SetEnd(const char *new_value) noexcept {
|
||||||
if (new_value == nullptr)
|
if (new_value == nullptr)
|
||||||
end.clear();
|
end.clear();
|
||||||
else
|
else
|
||||||
end = new_value;
|
end = new_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEnd(std::string &&new_value) {
|
void SetEnd(std::string &&new_value) noexcept {
|
||||||
end = std::move(new_value);
|
end = std::move(new_value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -23,19 +23,19 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
MusicBuffer::MusicBuffer(unsigned num_chunks) noexcept
|
||||||
:buffer(num_chunks) {
|
:buffer(num_chunks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicChunk *
|
MusicChunk *
|
||||||
MusicBuffer::Allocate()
|
MusicBuffer::Allocate() noexcept
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
return buffer.Allocate();
|
return buffer.Allocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MusicBuffer::Return(MusicChunk *chunk)
|
MusicBuffer::Return(MusicChunk *chunk) noexcept
|
||||||
{
|
{
|
||||||
assert(chunk != nullptr);
|
assert(chunk != nullptr);
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ public:
|
|||||||
* @param num_chunks the number of #MusicChunk reserved in
|
* @param num_chunks the number of #MusicChunk reserved in
|
||||||
* this buffer
|
* this buffer
|
||||||
*/
|
*/
|
||||||
MusicBuffer(unsigned num_chunks);
|
MusicBuffer(unsigned num_chunks) noexcept;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
* music_buffer_new().
|
* music_buffer_new().
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
unsigned GetSize() const {
|
unsigned GetSize() const noexcept {
|
||||||
return buffer.GetCapacity();
|
return buffer.GetCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,13 +71,13 @@ public:
|
|||||||
* @return an empty chunk or nullptr if there are no chunks
|
* @return an empty chunk or nullptr if there are no chunks
|
||||||
* available
|
* available
|
||||||
*/
|
*/
|
||||||
MusicChunk *Allocate();
|
MusicChunk *Allocate() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a chunk to the buffer. It can be reused by
|
* Returns a chunk to the buffer. It can be reused by
|
||||||
* Allocate() then.
|
* Allocate() then.
|
||||||
*/
|
*/
|
||||||
void Return(MusicChunk *chunk);
|
void Return(MusicChunk *chunk) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -31,7 +31,7 @@ MusicChunk::~MusicChunk()
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool
|
bool
|
||||||
MusicChunk::CheckFormat(const AudioFormat other_format) const
|
MusicChunk::CheckFormat(const AudioFormat other_format) const noexcept
|
||||||
{
|
{
|
||||||
assert(other_format.IsValid());
|
assert(other_format.IsValid());
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ MusicChunk::CheckFormat(const AudioFormat other_format) const
|
|||||||
|
|
||||||
WritableBuffer<void>
|
WritableBuffer<void>
|
||||||
MusicChunk::Write(const AudioFormat af,
|
MusicChunk::Write(const AudioFormat af,
|
||||||
SongTime data_time, uint16_t _bit_rate)
|
SongTime data_time, uint16_t _bit_rate) noexcept
|
||||||
{
|
{
|
||||||
assert(CheckFormat(af));
|
assert(CheckFormat(af));
|
||||||
assert(length == 0 || audio_format.IsValid());
|
assert(length == 0 || audio_format.IsValid());
|
||||||
@@ -64,7 +64,7 @@ MusicChunk::Write(const AudioFormat af,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MusicChunk::Expand(const AudioFormat af, size_t _length)
|
MusicChunk::Expand(const AudioFormat af, size_t _length) noexcept
|
||||||
{
|
{
|
||||||
const size_t frame_size = af.GetFrameSize();
|
const size_t frame_size = af.GetFrameSize();
|
||||||
|
|
||||||
|
@@ -111,7 +111,7 @@ struct MusicChunk {
|
|||||||
* specified audio_format.
|
* specified audio_format.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool CheckFormat(AudioFormat audio_format) const;
|
bool CheckFormat(AudioFormat audio_format) const noexcept;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +127,7 @@ struct MusicChunk {
|
|||||||
*/
|
*/
|
||||||
WritableBuffer<void> Write(AudioFormat af,
|
WritableBuffer<void> Write(AudioFormat af,
|
||||||
SongTime data_time,
|
SongTime data_time,
|
||||||
uint16_t bit_rate);
|
uint16_t bit_rate) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the length of the chunk after the caller has written to
|
* Increases the length of the chunk after the caller has written to
|
||||||
@@ -138,7 +138,7 @@ struct MusicChunk {
|
|||||||
* @param length the number of bytes which were appended
|
* @param length the number of bytes which were appended
|
||||||
* @return true if the chunk is full
|
* @return true if the chunk is full
|
||||||
*/
|
*/
|
||||||
bool Expand(AudioFormat af, size_t length);
|
bool Expand(AudioFormat af, size_t length) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MusicPipe::Contains(const MusicChunk *chunk) const
|
MusicPipe::Contains(const MusicChunk *chunk) const noexcept
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ MusicPipe::Contains(const MusicChunk *chunk) const
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
MusicChunk *
|
MusicChunk *
|
||||||
MusicPipe::Shift()
|
MusicPipe::Shift() noexcept
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ MusicPipe::Shift()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MusicPipe::Clear(MusicBuffer &buffer)
|
MusicPipe::Clear(MusicBuffer &buffer) noexcept
|
||||||
{
|
{
|
||||||
MusicChunk *chunk;
|
MusicChunk *chunk;
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ MusicPipe::Clear(MusicBuffer &buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MusicPipe::Push(MusicChunk *chunk)
|
MusicPipe::Push(MusicChunk *chunk) noexcept
|
||||||
{
|
{
|
||||||
assert(!chunk->IsEmpty());
|
assert(!chunk->IsEmpty());
|
||||||
assert(chunk->length == 0 || chunk->audio_format.IsValid());
|
assert(chunk->length == 0 || chunk->audio_format.IsValid());
|
||||||
|
@@ -77,7 +77,7 @@ public:
|
|||||||
* audio_format.
|
* audio_format.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool CheckFormat(AudioFormat other) const {
|
bool CheckFormat(AudioFormat other) const noexcept {
|
||||||
return !audio_format.IsDefined() ||
|
return !audio_format.IsDefined() ||
|
||||||
audio_format == other;
|
audio_format == other;
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ public:
|
|||||||
* Checks if the specified chunk is enqueued in the music pipe.
|
* Checks if the specified chunk is enqueued in the music pipe.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Contains(const MusicChunk *chunk) const;
|
bool Contains(const MusicChunk *chunk) const noexcept;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,37 +94,37 @@ public:
|
|||||||
* nullptr if the pipe is empty.
|
* nullptr if the pipe is empty.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const MusicChunk *Peek() const {
|
const MusicChunk *Peek() const noexcept {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the first chunk from the head, and returns it.
|
* Removes the first chunk from the head, and returns it.
|
||||||
*/
|
*/
|
||||||
MusicChunk *Shift();
|
MusicChunk *Shift() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the whole pipe and returns the chunks to the buffer.
|
* Clears the whole pipe and returns the chunks to the buffer.
|
||||||
*
|
*
|
||||||
* @param buffer the buffer object to return the chunks to
|
* @param buffer the buffer object to return the chunks to
|
||||||
*/
|
*/
|
||||||
void Clear(MusicBuffer &buffer);
|
void Clear(MusicBuffer &buffer) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes a chunk to the tail of the pipe.
|
* Pushes a chunk to the tail of the pipe.
|
||||||
*/
|
*/
|
||||||
void Push(MusicChunk *chunk);
|
void Push(MusicChunk *chunk) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of chunks currently in this pipe.
|
* Returns the number of chunks currently in this pipe.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
unsigned GetSize() const {
|
unsigned GetSize() const noexcept {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const noexcept {
|
||||||
return GetSize() == 0;
|
return GetSize() == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -200,7 +200,6 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
|
|||||||
*/
|
*/
|
||||||
const Database *GetDatabase() const;
|
const Database *GetDatabase() const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
const Database &GetDatabaseOrThrow() const;
|
const Database &GetDatabaseOrThrow() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -49,7 +49,6 @@ static std::map<std::string, unsigned> permission_passwords;
|
|||||||
|
|
||||||
static unsigned permission_default;
|
static unsigned permission_default;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
static unsigned
|
static unsigned
|
||||||
ParsePermission(const char *p)
|
ParsePermission(const char *p)
|
||||||
{
|
{
|
||||||
|
@@ -207,13 +207,12 @@ try {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
wchar_t buffer[MAX_PATH];
|
/* on Windows, playlists always contain UTF-8, because
|
||||||
auto result = MultiByteToWideChar(CP_ACP, 0, s, -1,
|
its "narrow" charset (i.e. CP_ACP) is incapable of
|
||||||
buffer, ARRAY_SIZE(buffer));
|
storing all Unicode paths */
|
||||||
if (result <= 0)
|
const auto path = AllocatedPath::FromUTF8(s);
|
||||||
|
if (path.IsNull())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Path path = Path::FromFS(buffer);
|
|
||||||
#else
|
#else
|
||||||
const Path path = Path::FromFS(s);
|
const Path path = Path::FromFS(s);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -28,13 +28,25 @@
|
|||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "fs/NarrowPath.hxx"
|
|
||||||
#include "fs/io/FileOutputStream.hxx"
|
#include "fs/io/FileOutputStream.hxx"
|
||||||
#include "fs/io/BufferedOutputStream.hxx"
|
#include "fs/io/BufferedOutputStream.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
static void
|
||||||
|
playlist_print_path(BufferedOutputStream &os, const Path path)
|
||||||
|
{
|
||||||
|
#ifdef _UNICODE
|
||||||
|
/* on Windows, playlists always contain UTF-8, because its
|
||||||
|
"narrow" charset (i.e. CP_ACP) is incapable of storing all
|
||||||
|
Unicode paths */
|
||||||
|
os.Format("%s\n", path.ToUTF8().c_str());
|
||||||
|
#else
|
||||||
|
os.Format("%s\n", path.c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_print_song(BufferedOutputStream &os, const DetachedSong &song)
|
playlist_print_song(BufferedOutputStream &os, const DetachedSong &song)
|
||||||
{
|
{
|
||||||
@@ -44,7 +56,7 @@ playlist_print_song(BufferedOutputStream &os, const DetachedSong &song)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const auto uri_fs = AllocatedPath::FromUTF8Throw(uri_utf8);
|
const auto uri_fs = AllocatedPath::FromUTF8Throw(uri_utf8);
|
||||||
os.Format("%s\n", NarrowPath(uri_fs).c_str());
|
playlist_print_path(os, uri_fs);
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +75,7 @@ playlist_print_uri(BufferedOutputStream &os, const char *uri)
|
|||||||
AllocatedPath::FromUTF8Throw(uri);
|
AllocatedPath::FromUTF8Throw(uri);
|
||||||
|
|
||||||
if (!path.IsNull())
|
if (!path.IsNull())
|
||||||
os.Format("%s\n", NarrowPath(path).c_str());
|
playlist_print_path(os, path);
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
float
|
float
|
||||||
ReplayGainTuple::CalculateScale(const ReplayGainConfig &config) const
|
ReplayGainTuple::CalculateScale(const ReplayGainConfig &config) const noexcept
|
||||||
{
|
{
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
|
@@ -40,23 +40,23 @@ struct ReplayGainTuple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
float CalculateScale(const ReplayGainConfig &config) const;
|
float CalculateScale(const ReplayGainConfig &config) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReplayGainInfo {
|
struct ReplayGainInfo {
|
||||||
ReplayGainTuple track, album;
|
ReplayGainTuple track, album;
|
||||||
|
|
||||||
constexpr bool IsDefined() const {
|
constexpr bool IsDefined() const noexcept {
|
||||||
return track.IsDefined() || album.IsDefined();
|
return track.IsDefined() || album.IsDefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReplayGainTuple &Get(ReplayGainMode mode) const {
|
const ReplayGainTuple &Get(ReplayGainMode mode) const noexcept {
|
||||||
return mode == ReplayGainMode::ALBUM
|
return mode == ReplayGainMode::ALBUM
|
||||||
? (album.IsDefined() ? album : track)
|
? (album.IsDefined() ? album : track)
|
||||||
: (track.IsDefined() ? track : album);
|
: (track.IsDefined() ? track : album);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() noexcept {
|
||||||
track.Clear();
|
track.Clear();
|
||||||
album.Clear();
|
album.Clear();
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ToString(ReplayGainMode mode)
|
ToString(ReplayGainMode mode) noexcept
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ReplayGainMode::AUTO:
|
case ReplayGainMode::AUTO:
|
||||||
|
@@ -36,13 +36,12 @@ enum class ReplayGainMode : uint8_t {
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *
|
const char *
|
||||||
ToString(ReplayGainMode mode);
|
ToString(ReplayGainMode mode) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string to a #ReplayGainMode. Throws std::runtime_error on
|
* Parse a string to a #ReplayGainMode. Throws std::runtime_error on
|
||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
ReplayGainMode
|
ReplayGainMode
|
||||||
FromString(const char *s);
|
FromString(const char *s);
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
#include "util/TimeParser.hxx"
|
#include "util/TimeParser.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "lib/icu/Collate.hxx"
|
#include "lib/icu/CaseFold.hxx"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
#define LOCATE_TAG_ANY_KEY "any"
|
#define LOCATE_TAG_ANY_KEY "any"
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
locate_parse_type(const char *str)
|
locate_parse_type(const char *str) noexcept
|
||||||
{
|
{
|
||||||
if (StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY) ||
|
if (StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY) ||
|
||||||
StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY_OLD))
|
StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY_OLD))
|
||||||
@@ -57,18 +57,10 @@ locate_parse_type(const char *str)
|
|||||||
return tag_name_parse_i(str);
|
return tag_name_parse_i(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
static AllocatedString<>
|
|
||||||
ImportString(const char *p, bool fold_case)
|
|
||||||
{
|
|
||||||
return fold_case
|
|
||||||
? IcuCaseFold(p)
|
|
||||||
: AllocatedString<>::Duplicate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SongFilter::Item::Item(unsigned _tag, const char *_value, bool _fold_case)
|
SongFilter::Item::Item(unsigned _tag, const char *_value, bool _fold_case)
|
||||||
:tag(_tag), fold_case(_fold_case),
|
:tag(_tag),
|
||||||
value(ImportString(_value, _fold_case))
|
value(AllocatedString<>::Duplicate(_value)),
|
||||||
|
fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +70,7 @@ SongFilter::Item::Item(unsigned _tag, time_t _time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::StringMatch(const char *s) const
|
SongFilter::Item::StringMatch(const char *s) const noexcept
|
||||||
{
|
{
|
||||||
#if !CLANG_CHECK_VERSION(3,6)
|
#if !CLANG_CHECK_VERSION(3,6)
|
||||||
/* disabled on clang due to -Wtautological-pointer-compare */
|
/* disabled on clang due to -Wtautological-pointer-compare */
|
||||||
@@ -88,23 +80,21 @@ SongFilter::Item::StringMatch(const char *s) const
|
|||||||
assert(tag != LOCATE_TAG_MODIFIED_SINCE);
|
assert(tag != LOCATE_TAG_MODIFIED_SINCE);
|
||||||
|
|
||||||
if (fold_case) {
|
if (fold_case) {
|
||||||
const auto folded = IcuCaseFold(s);
|
return fold_case.IsIn(s);
|
||||||
assert(!folded.IsNull());
|
|
||||||
return StringFind(folded.c_str(), value.c_str()) != nullptr;
|
|
||||||
} else {
|
} else {
|
||||||
return StringIsEqual(s, value.c_str());
|
return StringIsEqual(s, value.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::Match(const TagItem &item) const
|
SongFilter::Item::Match(const TagItem &item) const noexcept
|
||||||
{
|
{
|
||||||
return (tag == LOCATE_TAG_ANY_TYPE || (unsigned)item.type == tag) &&
|
return (tag == LOCATE_TAG_ANY_TYPE || (unsigned)item.type == tag) &&
|
||||||
StringMatch(item.value);
|
StringMatch(item.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::Match(const Tag &_tag) const
|
SongFilter::Item::Match(const Tag &_tag) const noexcept
|
||||||
{
|
{
|
||||||
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
|
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
|
||||||
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
|
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
|
||||||
@@ -140,7 +130,7 @@ SongFilter::Item::Match(const Tag &_tag) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::Match(const DetachedSong &song) const
|
SongFilter::Item::Match(const DetachedSong &song) const noexcept
|
||||||
{
|
{
|
||||||
if (tag == LOCATE_TAG_BASE_TYPE)
|
if (tag == LOCATE_TAG_BASE_TYPE)
|
||||||
return uri_is_child_or_same(value.c_str(), song.GetURI());
|
return uri_is_child_or_same(value.c_str(), song.GetURI());
|
||||||
@@ -155,7 +145,7 @@ SongFilter::Item::Match(const DetachedSong &song) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::Match(const LightSong &song) const
|
SongFilter::Item::Match(const LightSong &song) const noexcept
|
||||||
{
|
{
|
||||||
if (tag == LOCATE_TAG_BASE_TYPE) {
|
if (tag == LOCATE_TAG_BASE_TYPE) {
|
||||||
const auto uri = song.GetURI();
|
const auto uri = song.GetURI();
|
||||||
@@ -185,7 +175,7 @@ SongFilter::~SongFilter()
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static time_t
|
static time_t
|
||||||
ParseTimeStamp(const char *s)
|
ParseTimeStamp(const char *s) noexcept
|
||||||
{
|
{
|
||||||
assert(s != nullptr);
|
assert(s != nullptr);
|
||||||
|
|
||||||
@@ -246,7 +236,7 @@ SongFilter::Parse(ConstBuffer<const char *> args, bool fold_case)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Match(const DetachedSong &song) const
|
SongFilter::Match(const DetachedSong &song) const noexcept
|
||||||
{
|
{
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (!i.Match(song))
|
if (!i.Match(song))
|
||||||
@@ -256,7 +246,7 @@ SongFilter::Match(const DetachedSong &song) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Match(const LightSong &song) const
|
SongFilter::Match(const LightSong &song) const noexcept
|
||||||
{
|
{
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (!i.Match(song))
|
if (!i.Match(song))
|
||||||
@@ -266,7 +256,7 @@ SongFilter::Match(const LightSong &song) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::HasOtherThanBase() const
|
SongFilter::HasOtherThanBase() const noexcept
|
||||||
{
|
{
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (i.GetTag() != LOCATE_TAG_BASE_TYPE)
|
if (i.GetTag() != LOCATE_TAG_BASE_TYPE)
|
||||||
@@ -276,7 +266,7 @@ SongFilter::HasOtherThanBase() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
SongFilter::GetBase() const
|
SongFilter::GetBase() const noexcept
|
||||||
{
|
{
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (i.GetTag() == LOCATE_TAG_BASE_TYPE)
|
if (i.GetTag() == LOCATE_TAG_BASE_TYPE)
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#ifndef MPD_SONG_FILTER_HXX
|
#ifndef MPD_SONG_FILTER_HXX
|
||||||
#define MPD_SONG_FILTER_HXX
|
#define MPD_SONG_FILTER_HXX
|
||||||
|
|
||||||
|
#include "lib/icu/Compare.hxx"
|
||||||
#include "util/AllocatedString.hxx"
|
#include "util/AllocatedString.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
@@ -48,10 +49,13 @@ public:
|
|||||||
class Item {
|
class Item {
|
||||||
uint8_t tag;
|
uint8_t tag;
|
||||||
|
|
||||||
bool fold_case;
|
|
||||||
|
|
||||||
AllocatedString<> value;
|
AllocatedString<> value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This value is only set if case folding is enabled.
|
||||||
|
*/
|
||||||
|
IcuCompare fold_case;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For #LOCATE_TAG_MODIFIED_SINCE
|
* For #LOCATE_TAG_MODIFIED_SINCE
|
||||||
*/
|
*/
|
||||||
@@ -80,19 +84,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure gcc_nonnull(2)
|
gcc_pure gcc_nonnull(2)
|
||||||
bool StringMatch(const char *s) const;
|
bool StringMatch(const char *s) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const TagItem &tag_item) const;
|
bool Match(const TagItem &tag_item) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const Tag &tag) const;
|
bool Match(const Tag &tag) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const DetachedSong &song) const;
|
bool Match(const DetachedSong &song) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const LightSong &song) const;
|
bool Match(const LightSong &song) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -112,20 +116,20 @@ public:
|
|||||||
bool Parse(ConstBuffer<const char *> args, bool fold_case=false);
|
bool Parse(ConstBuffer<const char *> args, bool fold_case=false);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const Tag &tag) const;
|
bool Match(const Tag &tag) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const DetachedSong &song) const;
|
bool Match(const DetachedSong &song) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const LightSong &song) const;
|
bool Match(const LightSong &song) const noexcept;
|
||||||
|
|
||||||
const std::list<Item> &GetItems() const {
|
const std::list<Item> &GetItems() const noexcept {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const noexcept {
|
||||||
return items.empty();
|
return items.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +137,7 @@ public:
|
|||||||
* Is there at least one item with "fold case" enabled?
|
* Is there at least one item with "fold case" enabled?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool HasFoldCase() const {
|
bool HasFoldCase() const noexcept {
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (i.GetFoldCase())
|
if (i.GetFoldCase())
|
||||||
return true;
|
return true;
|
||||||
@@ -145,14 +149,14 @@ public:
|
|||||||
* Does this filter contain constraints other than "base"?
|
* Does this filter contain constraints other than "base"?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool HasOtherThanBase() const;
|
bool HasOtherThanBase() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the "base" specification (if there is one) or
|
* Returns the "base" specification (if there is one) or
|
||||||
* nullptr.
|
* nullptr.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetBase() const;
|
const char *GetBase() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,6 +164,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
unsigned
|
unsigned
|
||||||
locate_parse_type(const char *str);
|
locate_parse_type(const char *str) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -50,7 +50,7 @@ StateFile::StateFile(AllocatedPath &&_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
StateFile::RememberVersions()
|
StateFile::RememberVersions() noexcept
|
||||||
{
|
{
|
||||||
prev_volume_version = sw_volume_state_get_hash();
|
prev_volume_version = sw_volume_state_get_hash();
|
||||||
prev_output_version = audio_output_state_get_version();
|
prev_output_version = audio_output_state_get_version();
|
||||||
@@ -59,7 +59,7 @@ StateFile::RememberVersions()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StateFile::IsModified() const
|
StateFile::IsModified() const noexcept
|
||||||
{
|
{
|
||||||
return prev_volume_version != sw_volume_state_get_hash() ||
|
return prev_volume_version != sw_volume_state_get_hash() ||
|
||||||
prev_output_version != audio_output_state_get_version() ||
|
prev_output_version != audio_output_state_get_version() ||
|
||||||
|
@@ -67,14 +67,14 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Save the current state versions for use with IsModified().
|
* Save the current state versions for use with IsModified().
|
||||||
*/
|
*/
|
||||||
void RememberVersions();
|
void RememberVersions() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if MPD's state was modified since the last
|
* Check if MPD's state was modified since the last
|
||||||
* RememberVersions() call.
|
* RememberVersions() call.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsModified() const;
|
bool IsModified() const noexcept;
|
||||||
|
|
||||||
/* virtual methods from TimeoutMonitor */
|
/* virtual methods from TimeoutMonitor */
|
||||||
void OnTimeout() override;
|
void OnTimeout() override;
|
||||||
|
@@ -40,7 +40,7 @@
|
|||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
CheckDecoderPlugin(const DecoderPlugin &plugin,
|
CheckDecoderPlugin(const DecoderPlugin &plugin,
|
||||||
const char *suffix, const char *mime)
|
const char *suffix, const char *mime) noexcept
|
||||||
{
|
{
|
||||||
return (mime != nullptr && plugin.SupportsMimeType(mime)) ||
|
return (mime != nullptr && plugin.SupportsMimeType(mime)) ||
|
||||||
(suffix != nullptr && plugin.SupportsSuffix(suffix));
|
(suffix != nullptr && plugin.SupportsSuffix(suffix));
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static char *
|
static char *
|
||||||
FindSlash(char *p, size_t i)
|
FindSlash(char *p, size_t i) noexcept
|
||||||
{
|
{
|
||||||
for (; i > 0; --i)
|
for (; i > 0; --i)
|
||||||
if (p[i] == '/')
|
if (p[i] == '/')
|
||||||
@@ -39,7 +39,7 @@ FindSlash(char *p, size_t i)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static const char *
|
static const char *
|
||||||
FindSuffix(const char *p, const char *i)
|
FindSuffix(const char *p, const char *i) noexcept
|
||||||
{
|
{
|
||||||
for (; i > p; --i) {
|
for (; i > p; --i) {
|
||||||
if (*i == '.')
|
if (*i == '.')
|
||||||
|
@@ -93,7 +93,7 @@ public:
|
|||||||
~Bzip2InputStream();
|
~Bzip2InputStream();
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
/* virtual methods from InputStream */
|
||||||
bool IsEOF() override;
|
bool IsEOF() noexcept override;
|
||||||
size_t Read(void *ptr, size_t size) override;
|
size_t Read(void *ptr, size_t size) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -205,7 +205,7 @@ Bzip2InputStream::Read(void *ptr, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Bzip2InputStream::IsEOF()
|
Bzip2InputStream::IsEOF() noexcept
|
||||||
{
|
{
|
||||||
return eof;
|
return eof;
|
||||||
}
|
}
|
||||||
|
@@ -162,7 +162,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
/* virtual methods from InputStream */
|
||||||
bool IsEOF() override;
|
bool IsEOF() noexcept override;
|
||||||
size_t Read(void *ptr, size_t size) override;
|
size_t Read(void *ptr, size_t size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ Iso9660InputStream::Read(void *ptr, size_t read_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Iso9660InputStream::IsEOF()
|
Iso9660InputStream::IsEOF() noexcept
|
||||||
{
|
{
|
||||||
return offset == size;
|
return offset == size;
|
||||||
}
|
}
|
||||||
|
@@ -116,7 +116,7 @@ struct ZzipInputStream final : public InputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
/* virtual methods from InputStream */
|
||||||
bool IsEOF() override;
|
bool IsEOF() noexcept override;
|
||||||
size_t Read(void *ptr, size_t size) override;
|
size_t Read(void *ptr, size_t size) override;
|
||||||
void Seek(offset_type offset) override;
|
void Seek(offset_type offset) override;
|
||||||
};
|
};
|
||||||
@@ -147,7 +147,7 @@ ZzipInputStream::Read(void *ptr, size_t read_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ZzipInputStream::IsEOF()
|
ZzipInputStream::IsEOF() noexcept
|
||||||
{
|
{
|
||||||
return offset_type(zzip_tell(file)) == size;
|
return offset_type(zzip_tell(file)) == size;
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ const Domain client_domain("client");
|
|||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
const Database *
|
const Database *
|
||||||
Client::GetDatabase() const
|
Client::GetDatabase() const noexcept
|
||||||
{
|
{
|
||||||
return partition.instance.GetDatabase();
|
return partition.instance.GetDatabase();
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ Client::GetDatabaseOrThrow() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Storage *
|
const Storage *
|
||||||
Client::GetStorage() const
|
Client::GetStorage() const noexcept
|
||||||
{
|
{
|
||||||
return partition.instance.storage;
|
return partition.instance.storage;
|
||||||
}
|
}
|
||||||
|
@@ -100,7 +100,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsExpired() const {
|
bool IsExpired() const noexcept {
|
||||||
return !FullyBufferedSocket::IsDefined();
|
return !FullyBufferedSocket::IsDefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsSubscribed(const char *channel_name) const {
|
bool IsSubscribed(const char *channel_name) const noexcept {
|
||||||
return subscriptions.find(channel_name) != subscriptions.end();
|
return subscriptions.find(channel_name) != subscriptions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,16 +186,15 @@ public:
|
|||||||
* Wrapper for Instance::GetDatabase().
|
* Wrapper for Instance::GetDatabase().
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const Database *GetDatabase() const;
|
const Database *GetDatabase() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for Instance::GetDatabaseOrThrow().
|
* Wrapper for Instance::GetDatabaseOrThrow().
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
const Database &GetDatabaseOrThrow() const;
|
const Database &GetDatabaseOrThrow() const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const Storage *GetStorage() const;
|
const Storage *GetStorage() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* virtual methods from class BufferedSocket */
|
/* virtual methods from class BufferedSocket */
|
||||||
|
@@ -23,14 +23,14 @@
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static bool
|
static bool
|
||||||
valid_channel_char(const char ch)
|
valid_channel_char(const char ch) noexcept
|
||||||
{
|
{
|
||||||
return IsAlphaNumericASCII(ch) ||
|
return IsAlphaNumericASCII(ch) ||
|
||||||
ch == '_' || ch == '-' || ch == '.' || ch == ':';
|
ch == '_' || ch == '-' || ch == '.' || ch == ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
client_message_valid_channel_name(const char *name)
|
client_message_valid_channel_name(const char *name) noexcept
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
if (!valid_channel_char(*name))
|
if (!valid_channel_char(*name))
|
||||||
|
@@ -53,6 +53,6 @@ public:
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool
|
bool
|
||||||
client_message_valid_channel_name(const char *name);
|
client_message_valid_channel_name(const char *name) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static enum ack
|
static enum ack
|
||||||
ToAck(PlaylistResult result)
|
ToAck(PlaylistResult result) noexcept
|
||||||
{
|
{
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case PlaylistResult::SUCCESS:
|
case PlaylistResult::SUCCESS:
|
||||||
@@ -90,7 +90,7 @@ ToAck(PlaylistResult result)
|
|||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
gcc_const
|
gcc_const
|
||||||
static enum ack
|
static enum ack
|
||||||
ToAck(DatabaseErrorCode code)
|
ToAck(DatabaseErrorCode code) noexcept
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case DatabaseErrorCode::DISABLED:
|
case DatabaseErrorCode::DISABLED:
|
||||||
@@ -107,7 +107,7 @@ ToAck(DatabaseErrorCode code)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static enum ack
|
static enum ack
|
||||||
ToAck(std::exception_ptr ep)
|
ToAck(std::exception_ptr ep) noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::rethrow_exception(ep);
|
std::rethrow_exception(ep);
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
SkipNameFS(PathTraitsFS::const_pointer_type name_fs)
|
SkipNameFS(PathTraitsFS::const_pointer_type name_fs) noexcept
|
||||||
{
|
{
|
||||||
return name_fs[0] == '.' &&
|
return name_fs[0] == '.' &&
|
||||||
(name_fs[1] == 0 ||
|
(name_fs[1] == 0 ||
|
||||||
@@ -53,7 +53,7 @@ SkipNameFS(PathTraitsFS::const_pointer_type name_fs)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
skip_path(Path name_fs)
|
skip_path(Path name_fs) noexcept
|
||||||
{
|
{
|
||||||
return name_fs.HasNewline();
|
return name_fs.HasNewline();
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ handle_listfiles_local(Response &r, Path path_fs)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
IsValidName(const char *p)
|
IsValidName(const char *p) noexcept
|
||||||
{
|
{
|
||||||
if (!IsAlphaASCII(*p))
|
if (!IsAlphaASCII(*p))
|
||||||
return false;
|
return false;
|
||||||
@@ -123,7 +123,7 @@ IsValidName(const char *p)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
IsValidValue(const char *p)
|
IsValidValue(const char *p) noexcept
|
||||||
{
|
{
|
||||||
while (*p) {
|
while (*p) {
|
||||||
const char ch = *p++;
|
const char ch = *p++;
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
bool
|
bool
|
||||||
neighbor_commands_available(const Instance &instance)
|
neighbor_commands_available(const Instance &instance) noexcept
|
||||||
{
|
{
|
||||||
return instance.neighbors != nullptr;
|
return instance.neighbors != nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ class Response;
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool
|
bool
|
||||||
neighbor_commands_available(const Instance &instance);
|
neighbor_commands_available(const Instance &instance) noexcept;
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listneighbors(Client &client, Request request, Response &response);
|
handle_listneighbors(Client &client, Request request, Response &response);
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
#include "util/ConstBuffer.hxx"
|
#include "util/ConstBuffer.hxx"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
playlist_commands_available()
|
playlist_commands_available() noexcept
|
||||||
{
|
{
|
||||||
return !map_spl_path().IsNull();
|
return !map_spl_path().IsNull();
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ class Response;
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
bool
|
bool
|
||||||
playlist_commands_available();
|
playlist_commands_available() noexcept;
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_save(Client &client, Request request, Response &response);
|
handle_save(Client &client, Request request, Response &response);
|
||||||
|
@@ -45,68 +45,57 @@ public:
|
|||||||
: default_value;
|
: default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int ParseInt(unsigned idx) const {
|
int ParseInt(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgInt(data[idx]);
|
return ParseCommandArgInt(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int ParseInt(unsigned idx, int min_value, int max_value) const {
|
int ParseInt(unsigned idx, int min_value, int max_value) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgInt(data[idx], min_value, max_value);
|
return ParseCommandArgInt(data[idx], min_value, max_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int ParseUnsigned(unsigned idx) const {
|
int ParseUnsigned(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgUnsigned(data[idx]);
|
return ParseCommandArgUnsigned(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int ParseUnsigned(unsigned idx, unsigned max_value) const {
|
int ParseUnsigned(unsigned idx, unsigned max_value) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgUnsigned(data[idx], max_value);
|
return ParseCommandArgUnsigned(data[idx], max_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool ParseBool(unsigned idx) const {
|
bool ParseBool(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgBool(data[idx]);
|
return ParseCommandArgBool(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
RangeArg ParseRange(unsigned idx) const {
|
RangeArg ParseRange(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgRange(data[idx]);
|
return ParseCommandArgRange(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
float ParseFloat(unsigned idx) const {
|
float ParseFloat(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgFloat(data[idx]);
|
return ParseCommandArgFloat(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
SongTime ParseSongTime(unsigned idx) const {
|
SongTime ParseSongTime(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgSongTime(data[idx]);
|
return ParseCommandArgSongTime(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
SignedSongTime ParseSignedSongTime(unsigned idx) const {
|
SignedSongTime ParseSignedSongTime(unsigned idx) const {
|
||||||
assert(idx < size);
|
assert(idx < size);
|
||||||
return ParseCommandArgSignedSongTime(data[idx]);
|
return ParseCommandArgSignedSongTime(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int ParseOptional(unsigned idx, int default_value) const {
|
int ParseOptional(unsigned idx, int default_value) const {
|
||||||
return idx < size
|
return idx < size
|
||||||
? ParseInt(idx)
|
? ParseInt(idx)
|
||||||
: default_value;
|
: default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
RangeArg ParseOptional(unsigned idx, RangeArg default_value) const {
|
RangeArg ParseOptional(unsigned idx, RangeArg default_value) const {
|
||||||
return idx < size
|
return idx < size
|
||||||
? ParseRange(idx)
|
? ParseRange(idx)
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
skip_path(const char *name_utf8)
|
skip_path(const char *name_utf8) noexcept
|
||||||
{
|
{
|
||||||
return strchr(name_utf8, '\n') != nullptr;
|
return strchr(name_utf8, '\n') != nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,7 @@ ConfigBlock::~ConfigBlock()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BlockParam *
|
const BlockParam *
|
||||||
ConfigBlock::GetBlockParam(const char *name) const
|
ConfigBlock::GetBlockParam(const char *name) const noexcept
|
||||||
{
|
{
|
||||||
for (const auto &i : block_params) {
|
for (const auto &i : block_params) {
|
||||||
if (i.name == name) {
|
if (i.name == name) {
|
||||||
@@ -81,7 +81,8 @@ ConfigBlock::GetBlockParam(const char *name) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ConfigBlock::GetBlockValue(const char *name, const char *default_value) const
|
ConfigBlock::GetBlockValue(const char *name,
|
||||||
|
const char *default_value) const noexcept
|
||||||
{
|
{
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
if (bp == nullptr)
|
if (bp == nullptr)
|
||||||
@@ -128,7 +129,6 @@ ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const
|
|||||||
return bp->GetUnsignedValue();
|
return bp->GetUnsignedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool
|
bool
|
||||||
ConfigBlock::GetBlockValue(const char *name, bool default_value) const
|
ConfigBlock::GetBlockValue(const char *name, bool default_value) const
|
||||||
{
|
{
|
||||||
|
@@ -44,13 +44,10 @@ struct BlockParam {
|
|||||||
BlockParam(const char *_name, const char *_value, int _line=-1)
|
BlockParam(const char *_name, const char *_value, int _line=-1)
|
||||||
:name(_name), value(_value), line(_line), used(false) {}
|
:name(_name), value(_value), line(_line), used(false) {}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int GetIntValue() const;
|
int GetIntValue() const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
unsigned GetUnsignedValue() const;
|
unsigned GetUnsignedValue() const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool GetBoolValue() const;
|
bool GetBoolValue() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,12 +82,12 @@ struct ConfigBlock {
|
|||||||
* object that was synthesized and not loaded from a
|
* object that was synthesized and not loaded from a
|
||||||
* configuration file.
|
* configuration file.
|
||||||
*/
|
*/
|
||||||
bool IsNull() const {
|
bool IsNull() const noexcept {
|
||||||
return line < 0;
|
return line < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const noexcept {
|
||||||
return block_params.empty();
|
return block_params.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +98,11 @@ struct ConfigBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_nonnull_all gcc_pure
|
gcc_nonnull_all gcc_pure
|
||||||
const BlockParam *GetBlockParam(const char *_name) const;
|
const BlockParam *GetBlockParam(const char *_name) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetBlockValue(const char *name,
|
const char *GetBlockValue(const char *name,
|
||||||
const char *default_value=nullptr) const;
|
const char *default_value=nullptr) const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as config_get_path(), but looks up the setting in the
|
* Same as config_get_path(), but looks up the setting in the
|
||||||
@@ -116,13 +113,10 @@ struct ConfigBlock {
|
|||||||
AllocatedPath GetPath(const char *name,
|
AllocatedPath GetPath(const char *name,
|
||||||
const char *default_value=nullptr) const;
|
const char *default_value=nullptr) const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int GetBlockValue(const char *name, int default_value) const;
|
int GetBlockValue(const char *name, int default_value) const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
unsigned GetBlockValue(const char *name, unsigned default_value) const;
|
unsigned GetBlockValue(const char *name, unsigned default_value) const;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool GetBlockValue(const char *name, bool default_value) const;
|
bool GetBlockValue(const char *name, bool default_value) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -75,7 +75,7 @@ void config_global_check(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ConfigParam *
|
const ConfigParam *
|
||||||
config_get_param(ConfigOption option)
|
config_get_param(ConfigOption option) noexcept
|
||||||
{
|
{
|
||||||
auto *param = config_data.params[unsigned(option)];
|
auto *param = config_data.params[unsigned(option)];
|
||||||
if (param != nullptr)
|
if (param != nullptr)
|
||||||
@@ -84,7 +84,7 @@ config_get_param(ConfigOption option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ConfigBlock *
|
const ConfigBlock *
|
||||||
config_get_block(ConfigBlockOption option)
|
config_get_block(ConfigBlockOption option) noexcept
|
||||||
{
|
{
|
||||||
ConfigBlock *block = config_data.blocks[unsigned(option)];
|
ConfigBlock *block = config_data.blocks[unsigned(option)];
|
||||||
if (block != nullptr)
|
if (block != nullptr)
|
||||||
@@ -110,7 +110,7 @@ config_find_block(ConfigBlockOption option, const char *key, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
config_get_string(ConfigOption option, const char *default_value)
|
config_get_string(ConfigOption option, const char *default_value) noexcept
|
||||||
{
|
{
|
||||||
const auto *param = config_get_param(option);
|
const auto *param = config_get_param(option);
|
||||||
|
|
||||||
|
@@ -48,11 +48,11 @@ ReadConfigFile(Path path);
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const ConfigParam *
|
const ConfigParam *
|
||||||
config_get_param(enum ConfigOption option);
|
config_get_param(enum ConfigOption option) noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const ConfigBlock *
|
const ConfigBlock *
|
||||||
config_get_block(enum ConfigBlockOption option);
|
config_get_block(enum ConfigBlockOption option) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a block with a matching attribute.
|
* Find a block with a matching attribute.
|
||||||
@@ -61,20 +61,12 @@ config_get_block(enum ConfigBlockOption option);
|
|||||||
* @param key the attribute name
|
* @param key the attribute name
|
||||||
* @param value the expected attribute value
|
* @param value the expected attribute value
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
const ConfigBlock *
|
const ConfigBlock *
|
||||||
config_find_block(ConfigBlockOption option, const char *key, const char *value);
|
config_find_block(ConfigBlockOption option, const char *key, const char *value);
|
||||||
|
|
||||||
/* Note on gcc_pure: Some of the functions declared pure are not
|
|
||||||
really pure in strict sense. They have side effect such that they
|
|
||||||
validate parameter's value and signal an error if it's invalid.
|
|
||||||
However, if the argument was already validated or we don't care
|
|
||||||
about the argument at all, this may be ignored so in the end, we
|
|
||||||
should be fine with calling those functions pure. */
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
const char *
|
const char *
|
||||||
config_get_string(enum ConfigOption option, const char *default_value=nullptr);
|
config_get_string(enum ConfigOption option,
|
||||||
|
const char *default_value=nullptr) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an optional configuration variable which contains an
|
* Returns an optional configuration variable which contains an
|
||||||
@@ -86,11 +78,9 @@ config_get_string(enum ConfigOption option, const char *default_value=nullptr);
|
|||||||
AllocatedPath
|
AllocatedPath
|
||||||
config_get_path(enum ConfigOption option);
|
config_get_path(enum ConfigOption option);
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
unsigned
|
unsigned
|
||||||
config_get_unsigned(enum ConfigOption option, unsigned default_value);
|
config_get_unsigned(enum ConfigOption option, unsigned default_value);
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
static inline std::chrono::steady_clock::duration
|
static inline std::chrono::steady_clock::duration
|
||||||
config_get_unsigned(ConfigOption option,
|
config_get_unsigned(ConfigOption option,
|
||||||
std::chrono::steady_clock::duration default_value)
|
std::chrono::steady_clock::duration default_value)
|
||||||
@@ -100,11 +90,9 @@ config_get_unsigned(ConfigOption option,
|
|||||||
return std::chrono::steady_clock::duration(u);
|
return std::chrono::steady_clock::duration(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
unsigned
|
unsigned
|
||||||
config_get_positive(enum ConfigOption option, unsigned default_value);
|
config_get_positive(enum ConfigOption option, unsigned default_value);
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
static inline std::chrono::steady_clock::duration
|
static inline std::chrono::steady_clock::duration
|
||||||
config_get_positive(ConfigOption option,
|
config_get_positive(ConfigOption option,
|
||||||
std::chrono::steady_clock::duration default_value)
|
std::chrono::steady_clock::duration default_value)
|
||||||
@@ -114,7 +102,6 @@ config_get_positive(ConfigOption option,
|
|||||||
return std::chrono::steady_clock::duration(u);
|
return std::chrono::steady_clock::duration(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool config_get_bool(enum ConfigOption option, bool default_value);
|
bool config_get_bool(enum ConfigOption option, bool default_value);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -102,13 +102,13 @@ enum class ConfigBlockOption {
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
enum ConfigOption
|
enum ConfigOption
|
||||||
ParseConfigOptionName(const char *name);
|
ParseConfigOptionName(const char *name) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return #ConfigOption::MAX if not found
|
* @return #ConfigOption::MAX if not found
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
enum ConfigBlockOption
|
enum ConfigBlockOption
|
||||||
ParseConfigBlockOptionName(const char *name);
|
ParseConfigBlockOptionName(const char *name) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -101,7 +101,7 @@ static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX),
|
|||||||
gcc_pure
|
gcc_pure
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
|
ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
|
||||||
const char *name)
|
const char *name) noexcept
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (; i < count; ++i)
|
for (; i < count; ++i)
|
||||||
@@ -112,7 +112,7 @@ ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConfigOption
|
ConfigOption
|
||||||
ParseConfigOptionName(const char *name)
|
ParseConfigOptionName(const char *name) noexcept
|
||||||
{
|
{
|
||||||
return ConfigOption(ParseConfigTemplateName(config_param_templates,
|
return ConfigOption(ParseConfigTemplateName(config_param_templates,
|
||||||
n_config_param_templates,
|
n_config_param_templates,
|
||||||
@@ -120,7 +120,7 @@ ParseConfigOptionName(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConfigBlockOption
|
ConfigBlockOption
|
||||||
ParseConfigBlockOptionName(const char *name)
|
ParseConfigBlockOptionName(const char *name) noexcept
|
||||||
{
|
{
|
||||||
return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
|
return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
|
||||||
n_config_block_templates,
|
n_config_block_templates,
|
||||||
|
@@ -71,7 +71,6 @@ struct ConfigParam {
|
|||||||
*
|
*
|
||||||
* Throws #std::runtime_error on error.
|
* Throws #std::runtime_error on error.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
AllocatedPath GetPath() const;
|
AllocatedPath GetPath() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -45,7 +45,7 @@ extern ThreadId db_mutex_holder;
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static inline bool
|
static inline bool
|
||||||
holding_db_lock(void)
|
holding_db_lock() noexcept
|
||||||
{
|
{
|
||||||
return db_mutex_holder.IsInside();
|
return db_mutex_holder.IsInside();
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@ class DetachedSong;
|
|||||||
* "Detach" the #Song object, i.e. convert it to a #DetachedSong
|
* "Detach" the #Song object, i.e. convert it to a #DetachedSong
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
|
||||||
DetachedSong
|
DetachedSong
|
||||||
DatabaseDetachSong(const Storage &storage, const LightSong &song);
|
DatabaseDetachSong(const Storage &storage, const LightSong &song);
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
struct StringLess {
|
struct StringLess {
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool operator()(const char *a, const char *b) const {
|
bool operator()(const char *a, const char *b) const noexcept {
|
||||||
return strcmp(a, b) < 0;
|
return strcmp(a, b) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -106,7 +106,6 @@ public:
|
|||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag) const = 0;
|
VisitTag visit_tag) const = 0;
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
virtual DatabaseStats GetStats(const DatabaseSelection &selection) const = 0;
|
virtual DatabaseStats GetStats(const DatabaseSelection &selection) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +126,7 @@ public:
|
|||||||
* Returns 0 if that is not not known/available.
|
* Returns 0 if that is not not known/available.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
virtual time_t GetUpdateStamp() const = 0;
|
virtual time_t GetUpdateStamp() const noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -44,16 +44,16 @@ struct LightDirectory {
|
|||||||
constexpr LightDirectory(const char *_uri, time_t _mtime)
|
constexpr LightDirectory(const char *_uri, time_t _mtime)
|
||||||
:uri(_uri), mtime(_mtime) {}
|
:uri(_uri), mtime(_mtime) {}
|
||||||
|
|
||||||
static constexpr LightDirectory Root() {
|
static constexpr LightDirectory Root() noexcept {
|
||||||
return LightDirectory("", 0);
|
return LightDirectory("", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRoot() const {
|
bool IsRoot() const noexcept {
|
||||||
return *uri == 0;
|
return *uri == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetPath() const {
|
const char *GetPath() const noexcept {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
|
|
||||||
SignedSongTime
|
SignedSongTime
|
||||||
LightSong::GetDuration() const
|
LightSong::GetDuration() const noexcept
|
||||||
{
|
{
|
||||||
SongTime a = start_time, b = end_time;
|
SongTime a = start_time, b = end_time;
|
||||||
if (!b.IsPositive()) {
|
if (!b.IsPositive()) {
|
||||||
|
@@ -76,7 +76,7 @@ struct LightSong {
|
|||||||
SongTime end_time;
|
SongTime end_time;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
std::string GetURI() const {
|
std::string GetURI() const noexcept {
|
||||||
if (directory == nullptr)
|
if (directory == nullptr)
|
||||||
return std::string(uri);
|
return std::string(uri);
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ struct LightSong {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
SignedSongTime GetDuration() const;
|
SignedSongTime GetDuration() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -45,7 +45,7 @@ struct PlaylistInfo {
|
|||||||
constexpr CompareName(const char *_name):name(_name) {}
|
constexpr CompareName(const char *_name):name(_name) {}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool operator()(const PlaylistInfo &pi) const {
|
bool operator()(const PlaylistInfo &pi) const noexcept {
|
||||||
return pi.name.compare(name) == 0;
|
return pi.name.compare(name) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
PlaylistVector::iterator
|
PlaylistVector::iterator
|
||||||
PlaylistVector::find(const char *name)
|
PlaylistVector::find(const char *name) noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(name != nullptr);
|
assert(name != nullptr);
|
||||||
|
@@ -31,7 +31,7 @@ protected:
|
|||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
iterator find(const char *name);
|
iterator find(const char *name) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using std::list<PlaylistInfo>::empty;
|
using std::list<PlaylistInfo>::empty;
|
||||||
|
@@ -38,7 +38,7 @@ const DatabasePlugin *const database_plugins[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DatabasePlugin *
|
const DatabasePlugin *
|
||||||
GetDatabasePluginByName(const char *name)
|
GetDatabasePluginByName(const char *name) noexcept
|
||||||
{
|
{
|
||||||
for (auto i = database_plugins; *i != nullptr; ++i)
|
for (auto i = database_plugins; *i != nullptr; ++i)
|
||||||
if (strcmp((*i)->name, name) == 0)
|
if (strcmp((*i)->name, name) == 0)
|
||||||
|
@@ -32,6 +32,6 @@ extern const DatabasePlugin *const database_plugins[];
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const DatabasePlugin *
|
const DatabasePlugin *
|
||||||
GetDatabasePluginByName(const char *name);
|
GetDatabasePluginByName(const char *name) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "Selection.hxx"
|
#include "Selection.hxx"
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
|
|
||||||
@@ -34,19 +35,19 @@ DatabaseSelection::DatabaseSelection(const char *_uri, bool _recursive,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseSelection::IsEmpty() const
|
DatabaseSelection::IsEmpty() const noexcept
|
||||||
{
|
{
|
||||||
return uri.empty() && (filter == nullptr || filter->IsEmpty());
|
return uri.empty() && (filter == nullptr || filter->IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseSelection::HasOtherThanBase() const
|
DatabaseSelection::HasOtherThanBase() const noexcept
|
||||||
{
|
{
|
||||||
return filter != nullptr && filter->HasOtherThanBase();
|
return filter != nullptr && filter->HasOtherThanBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseSelection::Match(const LightSong &song) const
|
DatabaseSelection::Match(const LightSong &song) const noexcept
|
||||||
{
|
{
|
||||||
return filter == nullptr || filter->Match(song);
|
return filter == nullptr || filter->Match(song);
|
||||||
}
|
}
|
||||||
|
@@ -45,16 +45,16 @@ struct DatabaseSelection {
|
|||||||
const SongFilter *_filter=nullptr);
|
const SongFilter *_filter=nullptr);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this selection contain constraints other than "base"?
|
* Does this selection contain constraints other than "base"?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool HasOtherThanBase() const;
|
bool HasOtherThanBase() const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const LightSong &song) const;
|
bool Match(const LightSong &song) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -127,7 +127,7 @@ public:
|
|||||||
|
|
||||||
unsigned Update(const char *uri_utf8, bool discard) override;
|
unsigned Update(const char *uri_utf8, bool discard) override;
|
||||||
|
|
||||||
time_t GetUpdateStamp() const override {
|
time_t GetUpdateStamp() const noexcept override {
|
||||||
return update_stamp;
|
return update_stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ ProxySong::ProxySong(const mpd_song *song)
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static enum mpd_tag_type
|
static enum mpd_tag_type
|
||||||
Convert(TagType tag_type)
|
Convert(TagType tag_type) noexcept
|
||||||
{
|
{
|
||||||
for (auto i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
|
for (auto i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
|
||||||
if (i->d == tag_type)
|
if (i->d == tag_type)
|
||||||
@@ -574,7 +574,7 @@ Visit(struct mpd_connection *connection,
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
Match(const SongFilter *filter, const LightSong &song)
|
Match(const SongFilter *filter, const LightSong &song) noexcept
|
||||||
{
|
{
|
||||||
return filter == nullptr || filter->Match(song);
|
return filter == nullptr || filter->Match(song);
|
||||||
}
|
}
|
||||||
@@ -717,7 +717,7 @@ SearchSongs(struct mpd_connection *connection,
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
ServerSupportsSearchBase(const struct mpd_connection *connection)
|
ServerSupportsSearchBase(const struct mpd_connection *connection) noexcept
|
||||||
{
|
{
|
||||||
#if LIBMPDCLIENT_CHECK_VERSION(2,9,0)
|
#if LIBMPDCLIENT_CHECK_VERSION(2,9,0)
|
||||||
return mpd_connection_cmp_server_version(connection, 0, 18, 0) >= 0;
|
return mpd_connection_cmp_server_version(connection, 0, 18, 0) >= 0;
|
||||||
|
@@ -65,7 +65,7 @@ Directory::Delete()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
Directory::GetName() const
|
Directory::GetName() const noexcept
|
||||||
{
|
{
|
||||||
assert(!IsRoot());
|
assert(!IsRoot());
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ Directory::CreateChild(const char *name_utf8)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Directory *
|
const Directory *
|
||||||
Directory::FindChild(const char *name) const
|
Directory::FindChild(const char *name) const noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ Directory::FindChild(const char *name) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::PruneEmpty()
|
Directory::PruneEmpty() noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ Directory::PruneEmpty()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Directory::LookupResult
|
Directory::LookupResult
|
||||||
Directory::LookupDirectory(const char *uri)
|
Directory::LookupDirectory(const char *uri) noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(uri != nullptr);
|
assert(uri != nullptr);
|
||||||
@@ -173,7 +173,7 @@ Directory::AddSong(Song *song)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::RemoveSong(Song *song)
|
Directory::RemoveSong(Song *song) noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(song != nullptr);
|
assert(song != nullptr);
|
||||||
@@ -183,7 +183,7 @@ Directory::RemoveSong(Song *song)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Song *
|
const Song *
|
||||||
Directory::FindSong(const char *name_utf8) const
|
Directory::FindSong(const char *name_utf8) const noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(name_utf8 != nullptr);
|
assert(name_utf8 != nullptr);
|
||||||
@@ -200,13 +200,13 @@ Directory::FindSong(const char *name_utf8) const
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
directory_cmp(const Directory &a, const Directory &b)
|
directory_cmp(const Directory &a, const Directory &b) noexcept
|
||||||
{
|
{
|
||||||
return IcuCollate(a.path.c_str(), b.path.c_str()) < 0;
|
return IcuCollate(a.path.c_str(), b.path.c_str()) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::Sort()
|
Directory::Sort() noexcept
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LightDirectory
|
LightDirectory
|
||||||
Directory::Export() const
|
Directory::Export() const noexcept
|
||||||
{
|
{
|
||||||
return LightDirectory(GetPath(), mtime);
|
return LightDirectory(GetPath(), mtime);
|
||||||
}
|
}
|
||||||
|
@@ -86,7 +86,7 @@ struct Directory {
|
|||||||
|
|
||||||
Directory *parent;
|
Directory *parent;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
unsigned inode, device;
|
uint64_t inode, device;
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
@@ -134,10 +134,10 @@ public:
|
|||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const Directory *FindChild(const char *name) const;
|
const Directory *FindChild(const char *name) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
Directory *FindChild(const char *name) {
|
Directory *FindChild(const char *name) noexcept {
|
||||||
const Directory *cthis = this;
|
const Directory *cthis = this;
|
||||||
return const_cast<Directory *>(cthis->FindChild(name));
|
return const_cast<Directory *>(cthis->FindChild(name));
|
||||||
}
|
}
|
||||||
@@ -177,17 +177,17 @@ public:
|
|||||||
* @return the Directory, or nullptr if none was found
|
* @return the Directory, or nullptr if none was found
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
LookupResult LookupDirectory(const char *uri);
|
LookupResult LookupDirectory(const char *uri) noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const noexcept {
|
||||||
return children.empty() &&
|
return children.empty() &&
|
||||||
songs.empty() &&
|
songs.empty() &&
|
||||||
playlists.empty();
|
playlists.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetPath() const {
|
const char *GetPath() const noexcept {
|
||||||
return path.c_str();
|
return path.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,13 +195,13 @@ public:
|
|||||||
* Returns the base name of the directory.
|
* Returns the base name of the directory.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const char *GetName() const;
|
const char *GetName() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this the root directory of the music database?
|
* Is this the root directory of the music database?
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsRoot() const {
|
bool IsRoot() const noexcept {
|
||||||
return parent == nullptr;
|
return parent == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,10 +229,10 @@ public:
|
|||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const Song *FindSong(const char *name_utf8) const;
|
const Song *FindSong(const char *name_utf8) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
Song *FindSong(const char *name_utf8) {
|
Song *FindSong(const char *name_utf8) noexcept {
|
||||||
const Directory *cthis = this;
|
const Directory *cthis = this;
|
||||||
return const_cast<Song *>(cthis->FindSong(name_utf8));
|
return const_cast<Song *>(cthis->FindSong(name_utf8));
|
||||||
}
|
}
|
||||||
@@ -248,19 +248,19 @@ public:
|
|||||||
* invalidates the song object, because the "parent" attribute becomes
|
* invalidates the song object, because the "parent" attribute becomes
|
||||||
* stale), but does not free it.
|
* stale), but does not free it.
|
||||||
*/
|
*/
|
||||||
void RemoveSong(Song *song);
|
void RemoveSong(Song *song) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
void PruneEmpty();
|
void PruneEmpty() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort all directory entries recursively.
|
* Sort all directory entries recursively.
|
||||||
*
|
*
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
void Sort();
|
void Sort() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock #db_mutex.
|
* Caller must lock #db_mutex.
|
||||||
@@ -270,7 +270,7 @@ public:
|
|||||||
VisitPlaylist visit_playlist) const;
|
VisitPlaylist visit_playlist) const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
LightDirectory Export() const;
|
LightDirectory Export() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static const char *
|
static const char *
|
||||||
DeviceToTypeString(unsigned device)
|
DeviceToTypeString(unsigned device) noexcept
|
||||||
{
|
{
|
||||||
switch (device) {
|
switch (device) {
|
||||||
case DEVICE_INARCHIVE:
|
case DEVICE_INARCHIVE:
|
||||||
@@ -56,7 +56,7 @@ DeviceToTypeString(unsigned device)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static unsigned
|
static unsigned
|
||||||
ParseTypeString(const char *type)
|
ParseTypeString(const char *type) noexcept
|
||||||
{
|
{
|
||||||
if (strcmp(type, "archive") == 0)
|
if (strcmp(type, "archive") == 0)
|
||||||
return DEVICE_INARCHIVE;
|
return DEVICE_INARCHIVE;
|
||||||
|
@@ -76,7 +76,7 @@ public:
|
|||||||
const ConfigBlock &block);
|
const ConfigBlock &block);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
Directory &GetRoot() {
|
Directory &GetRoot() noexcept {
|
||||||
assert(root != NULL);
|
assert(root != NULL);
|
||||||
|
|
||||||
return *root;
|
return *root;
|
||||||
@@ -125,7 +125,7 @@ public:
|
|||||||
|
|
||||||
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
||||||
|
|
||||||
time_t GetUpdateStamp() const override {
|
time_t GetUpdateStamp() const noexcept override {
|
||||||
return mtime;
|
return mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -77,7 +77,7 @@ Song::Free()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Song::GetURI() const
|
Song::GetURI() const noexcept
|
||||||
{
|
{
|
||||||
assert(*uri);
|
assert(*uri);
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ Song::GetURI() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
LightSong
|
LightSong
|
||||||
Song::Export() const
|
Song::Export() const noexcept
|
||||||
{
|
{
|
||||||
LightSong dest;
|
LightSong dest;
|
||||||
dest.directory = parent->IsRoot()
|
dest.directory = parent->IsRoot()
|
||||||
|
@@ -123,10 +123,10 @@ struct Song {
|
|||||||
* location within the music directory.
|
* location within the music directory.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
std::string GetURI() const;
|
std::string GetURI() const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
LightSong Export() const;
|
LightSong Export() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::intrusive::list<Song,
|
typedef boost::intrusive::list<Song,
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_utf8_string(const char *a, const char *b)
|
compare_utf8_string(const char *a, const char *b) noexcept
|
||||||
{
|
{
|
||||||
if (a == nullptr)
|
if (a == nullptr)
|
||||||
return b == nullptr ? 0 : -1;
|
return b == nullptr ? 0 : -1;
|
||||||
@@ -42,8 +42,7 @@ compare_utf8_string(const char *a, const char *b)
|
|||||||
* nullptr.
|
* nullptr.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
compare_string_tag_item(const Tag &a, const Tag &b,
|
compare_string_tag_item(const Tag &a, const Tag &b, TagType type) noexcept
|
||||||
TagType type)
|
|
||||||
{
|
{
|
||||||
return compare_utf8_string(a.GetValue(type),
|
return compare_utf8_string(a.GetValue(type),
|
||||||
b.GetValue(type));
|
b.GetValue(type));
|
||||||
@@ -54,7 +53,7 @@ compare_string_tag_item(const Tag &a, const Tag &b,
|
|||||||
* (e.g. disc or track number). Either one may be nullptr.
|
* (e.g. disc or track number). Either one may be nullptr.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
compare_number_string(const char *a, const char *b)
|
compare_number_string(const char *a, const char *b) noexcept
|
||||||
{
|
{
|
||||||
long ai = a == nullptr ? 0 : strtol(a, nullptr, 10);
|
long ai = a == nullptr ? 0 : strtol(a, nullptr, 10);
|
||||||
long bi = b == nullptr ? 0 : strtol(b, nullptr, 10);
|
long bi = b == nullptr ? 0 : strtol(b, nullptr, 10);
|
||||||
@@ -69,7 +68,7 @@ compare_number_string(const char *a, const char *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_tag_item(const Tag &a, const Tag &b, TagType type)
|
compare_tag_item(const Tag &a, const Tag &b, TagType type) noexcept
|
||||||
{
|
{
|
||||||
return compare_number_string(a.GetValue(type),
|
return compare_number_string(a.GetValue(type),
|
||||||
b.GetValue(type));
|
b.GetValue(type));
|
||||||
@@ -78,7 +77,7 @@ compare_tag_item(const Tag &a, const Tag &b, TagType type)
|
|||||||
/* Only used for sorting/searchin a songvec, not general purpose compares */
|
/* Only used for sorting/searchin a songvec, not general purpose compares */
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
song_cmp(const Song &a, const Song &b)
|
song_cmp(const Song &a, const Song &b) noexcept
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -102,7 +101,7 @@ song_cmp(const Song &a, const Song &b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
song_list_sort(SongList &songs)
|
song_list_sort(SongList &songs) noexcept
|
||||||
{
|
{
|
||||||
songs.sort(song_cmp);
|
songs.sort(song_cmp);
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,6 @@
|
|||||||
#include "Song.hxx"
|
#include "Song.hxx"
|
||||||
|
|
||||||
void
|
void
|
||||||
song_list_sort(SongList &songs);
|
song_list_sort(SongList &songs) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -39,7 +39,7 @@ UPnPDirContent::~UPnPDirContent()
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static UPnPDirObject::ItemClass
|
static UPnPDirObject::ItemClass
|
||||||
ParseItemClass(StringView name)
|
ParseItemClass(StringView name) noexcept
|
||||||
{
|
{
|
||||||
if (name.EqualsLiteral("object.item.audioItem.musicTrack"))
|
if (name.EqualsLiteral("object.item.audioItem.musicTrack"))
|
||||||
return UPnPDirObject::ItemClass::MUSIC;
|
return UPnPDirObject::ItemClass::MUSIC;
|
||||||
@@ -51,7 +51,7 @@ ParseItemClass(StringView name)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static SignedSongTime
|
static SignedSongTime
|
||||||
ParseDuration(const char *duration)
|
ParseDuration(const char *duration) noexcept
|
||||||
{
|
{
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ ParseDuration(const char *duration)
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static std::string &&
|
static std::string &&
|
||||||
TitleToPathSegment(std::string &&s)
|
TitleToPathSegment(std::string &&s) noexcept
|
||||||
{
|
{
|
||||||
std::replace(s.begin(), s.end(), '/', '_');
|
std::replace(s.begin(), s.end(), '/', '_');
|
||||||
return std::move(s);
|
return std::move(s);
|
||||||
|
@@ -40,7 +40,7 @@ public:
|
|||||||
~UPnPDirContent();
|
~UPnPDirContent();
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
UPnPDirObject *FindObject(const char *name) {
|
UPnPDirObject *FindObject(const char *name) noexcept {
|
||||||
for (auto &o : objects)
|
for (auto &o : objects)
|
||||||
if (o.name == name)
|
if (o.name == name)
|
||||||
return &o;
|
return &o;
|
||||||
|
@@ -80,7 +80,7 @@ public:
|
|||||||
|
|
||||||
UPnPDirObject &operator=(UPnPDirObject &&) = default;
|
UPnPDirObject &operator=(UPnPDirObject &&) = default;
|
||||||
|
|
||||||
void Clear() {
|
void Clear() noexcept {
|
||||||
id.clear();
|
id.clear();
|
||||||
parent_id.clear();
|
parent_id.clear();
|
||||||
url.clear();
|
url.clear();
|
||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Check() const {
|
bool Check() const noexcept {
|
||||||
return !id.empty() && !parent_id.empty() && !name.empty() &&
|
return !id.empty() && !parent_id.empty() && !name.empty() &&
|
||||||
(type != UPnPDirObject::Type::ITEM ||
|
(type != UPnPDirObject::Type::ITEM ||
|
||||||
item_class != UPnPDirObject::ItemClass::UNKNOWN);
|
item_class != UPnPDirObject::ItemClass::UNKNOWN);
|
||||||
|
@@ -93,7 +93,7 @@ public:
|
|||||||
|
|
||||||
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
||||||
|
|
||||||
time_t GetUpdateStamp() const override {
|
time_t GetUpdateStamp() const noexcept override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExcludeList::LoadFile(Path path_fs)
|
ExcludeList::LoadFile(Path path_fs) noexcept
|
||||||
try {
|
try {
|
||||||
#ifdef HAVE_CLASS_GLOB
|
#ifdef HAVE_CLASS_GLOB
|
||||||
TextFile file(path_fs);
|
TextFile file(path_fs);
|
||||||
@@ -67,7 +67,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExcludeList::Check(Path name_fs) const
|
ExcludeList::Check(Path name_fs) const noexcept
|
||||||
{
|
{
|
||||||
assert(!name_fs.IsNull());
|
assert(!name_fs.IsNull());
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ public:
|
|||||||
:parent(&_parent) {}
|
:parent(&_parent) {}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const noexcept {
|
||||||
#ifdef HAVE_CLASS_GLOB
|
#ifdef HAVE_CLASS_GLOB
|
||||||
return ((parent == nullptr) || parent->IsEmpty()) && patterns.empty();
|
return ((parent == nullptr) || parent->IsEmpty()) && patterns.empty();
|
||||||
#else
|
#else
|
||||||
@@ -62,13 +62,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Loads and parses a .mpdignore file.
|
* Loads and parses a .mpdignore file.
|
||||||
*/
|
*/
|
||||||
bool LoadFile(Path path_fs);
|
bool LoadFile(Path path_fs) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether one of the patterns in the .mpdignore file matches
|
* Checks whether one of the patterns in the .mpdignore file matches
|
||||||
* the specified file name.
|
* the specified file name.
|
||||||
*/
|
*/
|
||||||
bool Check(Path name_fs) const;
|
bool Check(Path name_fs) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ InotifyQueue::OnTimeout()
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static bool
|
static bool
|
||||||
path_in(const char *path, const char *possible_parent)
|
path_in(const char *path, const char *possible_parent) noexcept
|
||||||
{
|
{
|
||||||
if (StringIsEmpty(path))
|
if (StringIsEmpty(path))
|
||||||
return true;
|
return true;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user