Compare commits

...

1850 Commits

Author SHA1 Message Date
Frank Dana
af649ae85f Document SELinux-blocked io_uring failures 2025-03-14 22:15:29 -04:00
Camille Scholtz
30e1cbbcba fs/glue/StandardDirectory: Add standard directories for macOS 2025-03-14 08:25:30 +01:00
Camille Scholtz
86ab4bc62c config/Path: Always allow getting of XDG... variables 2025-03-13 22:22:14 +01:00
Camille Scholtz
a34bf3588e fs/glue/StandardDirectory: Remove double import 2025-03-13 22:21:15 +01:00
Max Kellermann
64c9e5a2d4 .gitignore: remove tool-specific patterns
If somebody uses tools that create these files, they should put them
in their global gitignore.
2025-03-13 14:55:09 +01:00
Max Kellermann
9f02a88d19 .github/workflows: add more paths-ignore 2025-03-13 14:53:17 +01:00
Max Kellermann
e6a25e7e0b doc/conf.py: use "sphinx_rtd_theme" only if it is installed
Don't fail at build time only because the RTD scheme is not installed.
Such a problem should be detected at configure time.
2025-03-13 14:44:23 +01:00
Max Kellermann
f6337dd95e doc/conf.py: remove the "~git" version suffix in the 0.24 stable branch 2025-03-13 14:19:32 +01:00
Max Kellermann
42fc26cc6d .github/workflows/build_android.yml: switch to the installed NDK r27 2025-03-13 11:33:46 +01:00
Max Kellermann
1b6567b31b test/net/TestIPv[46]Address: initialize WinSock for some of the tests
Not necessary with WINE, but the "real" Windows seems to be picky
about this.
2025-03-13 11:26:05 +01:00
Max Kellermann
171bb9b737 test/TestStringFilter: enable another failing test on Windows 2025-03-13 11:25:57 +01:00
Max Kellermann
3626d4ec9a Revert "lib/icu/Compare: add LINGUISTIC_IGNORECASE [Windows]"
This reverts commit 1bd204527e010a59a375903d7c03cfe68c788d74.  This
fixes a test on WINE, but fails many others on Windows.  D'oh!
2025-03-13 11:22:02 +01:00
Max Kellermann
71c8f4de40 test/TestStringFilter: disable two failing checks on Windows 2025-03-13 10:37:01 +01:00
Max Kellermann
1bd204527e lib/icu/Compare: add LINGUISTIC_IGNORECASE [Windows]
This fixes one check in the "StringFilterTest.Normalize" unit test.
2025-03-13 10:35:42 +01:00
Max Kellermann
9b25d59120 test/TestStringFilter: re-enable two tests on Windows
These don't fail anymore.  I don't know what has changed since these
`#ifndefs` were added by commit d7f545721bec9
2025-03-13 10:35:33 +01:00
Max Kellermann
ca5580a560 test/util/TestIntrusiveTreeSet: do not add duplicates in the LargeRandom tests
This can fail randomly if the order of identical values is different
in the std::deque and the IntrusiveTreeSet.
2025-03-13 09:55:01 +01:00
Max Kellermann
dd59db2be2 fs/LookupFile: check for empty file name on Windows
Fixes crash bug in the (synthetic) unit test.  See code comment.
2025-03-13 09:21:04 +01:00
Max Kellermann
c290e0b965 LogBackend: remove the colon after the time stamp
This colon with spaces around it looked weird and was somewhat
redundant.  Let's use a space only.  This looks better if we replace
the space between date and time with a 'T', so it's mostly the ISO8601
format only in local time instead of UTC.
2025-03-13 09:02:01 +01:00
Max Kellermann
689d231809 LogBackend: include year in time stamp
Also use a numeric month instead of the month name.
2025-03-13 09:00:37 +01:00
Max Kellermann
84ff3c6a0d LogBackend: use %T 2025-03-13 08:58:36 +01:00
Max Kellermann
093122aaeb LogBackend: use fmt to format the time stamp 2025-03-13 08:57:23 +01:00
Max Kellermann
4f981adb97 lib/fmt/Unsafe: new library 2025-03-13 08:55:12 +01:00
Max Kellermann
3945b808a2 CommandLine: update copyright year 2025-03-13 08:30:28 +01:00
Max Kellermann
a171a588cf queue/QueuePrint: switch to SPDX header 2025-03-13 08:30:28 +01:00
Max Kellermann
2388f38d7d NEWS: mention the id3tag build failure fix merged from the obsolete v0.23.x branch 2025-03-13 08:30:28 +01:00
Jzavrk
dac2c4df9b output/plugins/SndioOutputPlugin: Fix sndio volume calculation
This commit addresses issues  and .
MPD and sndio volume ranges being different, the formula to transform a
value from one set to the other is in the form of `(a * x + b) / c`
where:
 - a = output set max value
 - b = adjustment term
 - c = input set max value
Previous calculation formula had `b = 0`, scaling values too low and
rendering increment impossible. Having `b = out_maxval / 2` balances the
transformation, ensuring a better spread of values across the output
range.

Closes 
2025-03-12 12:24:00 +01:00
Max Kellermann
843cb1604d net: delete UniqueSocketDescriptor.hxx.orig
This got committed accidently.
2025-03-11 17:16:58 +01:00
Max Kellermann
59c289c7d8 README.md: update manual and forum links
It's on readthedocs and GitHub now.
2025-03-11 13:03:28 +01:00
Max Kellermann
4b85bb57cc Merge branch 'v0.23.x' 2025-03-11 12:52:05 +01:00
Max Kellermann
a19b6919e0 increment version number to 0.24.1 2025-03-11 11:24:59 +01:00
Max Kellermann
1caeb9b418 release v0.24 2025-03-11 11:05:29 +01:00
Max Kellermann
d3717c5b81 test/util/TestIntrusiveTreeSet: add test with all-zero items 2025-03-11 10:45:33 +01:00
Max Kellermann
90987194cb .github/workflows/build.yml: run unit tests on Windows
The unit tests currently fail on Windows.  That needs to be fixed, but
good to know that there are problems currently.
2025-03-11 10:18:19 +01:00
Max Kellermann
2953737478 .github/workflows/build.yml: remove "warning_level=3", it is the default 2025-03-11 10:11:06 +01:00
Max Kellermann
ac3a5e27ec .github/workflows/build.yml: split "Compile and Test" into two steps 2025-03-11 10:11:06 +01:00
Max Kellermann
4ae89b7b4a .github/workflows/build.yml: enable ccache for Windows builds 2025-03-11 10:11:06 +01:00
Max Kellermann
568494440f .github/workflows/build.yml: add matrix.os to ccache key 2025-03-11 10:11:06 +01:00
Max Kellermann
5d0aeda4e9 .github/workflows/build.yml: run unit tests with "--print-errorlogs"
With this option, Meson prints errors instead of logging them to a
file (that would be inaccessible).
2025-03-11 10:11:06 +01:00
Max Kellermann
d89b9d1683 test/fs/TestParsePath: include "fs/XDG.hxx" for USE_XDG 2025-03-11 10:09:52 +01:00
Max Kellermann
c7c4e7a6bf python/build/libs.py: update libopenmpt to 0.7.13 2025-03-11 09:26:13 +01:00
Max Kellermann
1c7c2026db config/Path: check for empty XDG variables 2025-03-11 09:23:33 +01:00
Max Kellermann
a9805db500 config/Path: move code to GetVariable() 2025-03-11 09:19:20 +01:00
Max Kellermann
e8a4317f31 config/Path: simplify tilde expansion 2025-03-11 09:17:01 +01:00
Max Kellermann
f4f5e94a36 config/Path: pass std::string_view to ParsePath() 2025-03-11 09:15:18 +01:00
Max Kellermann
b2326b9a98 test/fs/TestParsePath: unit test for ParsePath() 2025-03-11 09:13:31 +01:00
Max Kellermann
1dc8cd8eef config/Path: allow expanding $HOME even without XDG 2025-03-11 08:45:04 +01:00
Max Kellermann
147fe18ad6 config/Path: adjust error message (not an environment variable) 2025-03-11 08:44:18 +01:00
Max Kellermann
6fd6a5110c config/Path: use string_view literals 2025-03-11 08:36:57 +01:00
JoanVC
e8ce417150
Initial support for $HOME and some XDG variables inside the configuration file
This commit tries to address issues  and . It enables the path expansion of HOME, XDG_CONFIG_HOME, XDG_MUSIC_DIR, XDG_CACHE_HOME and XDG_RUNTIME_DIR by using the glue functions already available in MPD.

Signed-off-by: Joan Vilardaga <github-91yu@joanvc.cat>
2025-03-10 22:21:03 +01:00
Max Kellermann
da40483666 event/Loop: destroy the UringWake instance in DisableUring() 2025-03-10 19:14:10 +01:00
Max Kellermann
06bc373ace event/Loop: read eventfd with io_uring
This eliminates a roundtrip to epoll.
2025-03-10 18:59:08 +01:00
Max Kellermann
7797158ea6 event/Loop: auto-restart io_uring_prep_poll_multishot()
Applications need to check the `IORING_CQE_F_MORE` flag to see whether
the kernel is still polling, or whether it has stopped for some reason.
2025-03-10 18:52:31 +01:00
Max Kellermann
01a04baf7b util/DivideString: remove unused library 2025-03-10 18:35:20 +01:00
Max Kellermann
46b461df42 playlist/pls: migrate the line parser to use std::string_view 2025-03-10 18:35:20 +01:00
Max Kellermann
898e0a2bc4 test/playlist: unit tests for the playlist plugins
Only "pls" for now.
2025-03-10 18:35:20 +01:00
Max Kellermann
2d3271859f input/memory: new implementation (for unit tests) 2025-03-10 18:17:33 +01:00
Max Kellermann
b6672004bc util/StringCompare: add SkipPrefixIgnoreCase() 2025-03-10 18:17:33 +01:00
Max Kellermann
eafca183a6 input/meson.build: add libinput_basic.a
This is the middle ground between libinput_api.a (the raw API) and
libinput_glue.a (dependencies on all plugins).
2025-03-10 17:13:51 +01:00
Max Kellermann
59f9e0ca70 input/meson.build: do not compile ProxyInputStream.cxx twice 2025-03-10 17:11:12 +01:00
Max Kellermann
800a03f0dc playlist/plugins/meson.build: add missing dependencies 2025-03-10 14:33:41 +01:00
Max Kellermann
55c11448ff util/NumberParser: add ParseIntegerTo()
An version of the function without the `std::optional` overhead.
2025-03-10 14:04:50 +01:00
Max Kellermann
e9c1ea684b util/NumberParser: add std::from_chars() wrapper taking std::string_view 2025-03-10 14:04:50 +01:00
Max Kellermann
103487e8ad event/InotifyEvent: add method IsDefined() 2025-03-10 14:04:50 +01:00
Max Kellermann
fb59bbc481 python/build/libs.py: update FFmpeg to 7.1.1 2025-03-10 14:04:50 +01:00
Max Kellermann
d0f6aa5b87 subprojects: update libnpupnp to 6.2.1-1 2025-03-10 14:04:12 +01:00
Max Kellermann
fdb8874803 python/build/libs.py: update libnfs to 6.0.2 2025-02-28 19:47:57 +01:00
Max Kellermann
c9a22b3404 meson.build: disable unnecessary libsndfile features 2025-02-28 19:41:19 +01:00
Max Kellermann
fc5d10b776 subprojects: add libsndfile.wrap 2025-02-28 19:37:17 +01:00
Max Kellermann
4cefb30dd9 decoder/flac: ignore FLAC__STREAM_DECODER_END_OF_LINK (FLAC 1.5)
Fixes -Wswitch compiler warning when building with FLAC 1.5.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2219
2025-02-28 10:32:47 +01:00
Max Kellermann
36482f5e6a subprojects: update gtest to 1.15.2-2 2025-02-28 09:59:07 +01:00
Jochen Sprickerhof
d822685c53
config/File: support resetting repeatable params
This allows resetting bind_to_address to override the default value in a
included config.
2025-02-21 13:52:44 +01:00
Max Kellermann
9d87fb5e09 subprojects: update sqlite3 to 3.49.1-1 2025-02-20 13:59:06 +01:00
Max Kellermann
85014b5fa2 event/Loop: move code to Wait() 2025-02-13 16:54:36 +01:00
Max Kellermann
aff929dbd6 event/Loop: rename Wait() to Poll()
Preparing to have another Wait() method wrapping Poll() and io_uring.
2025-02-13 16:53:49 +01:00
Max Kellermann
dda85e02bf io/Open: add TryOpen(struct open_how), Open(struct open_how) 2025-02-13 16:09:12 +01:00
Max Kellermann
5b393052ee event/Loop: pass timeout=nullptr to io_uring if there is no timer 2025-02-13 16:04:07 +01:00
Max Kellermann
624da8ce5b event/Loop: use io_uring_prep_poll_multishot() on the epoll fd
This wraps epoll and io_uring the other way: previously, we had the
io_uring file descriptor registered in epoll and when it became ready,
we could query its completion ring.  The problem is that the poll
wakeups cause considerable overhead in the Linux kernel, see
https://lore.kernel.org/io-uring/20250128133927.3989681-9-max.kellermann@ionos.com/

By wrapping epoll inside io_uring using
io_uring_prep_poll_multishot(), the "outer" loop is io_uring and
inside it, we have epoll.  This adds another system call for epoll,
but that will go away as soon as most operations are going through
io_uring.  Previously, io_uring had this extra system call.
2025-02-13 16:02:40 +01:00
Max Kellermann
bca9e3e347 io/uring/Queue: dispatch all completions in SubmitAndWaitDispatchOneCompletion()
io_uring_submit_and_wait_timeout() can return multiple completions,
even if we wait for only one.  We should dispatch them all or we miss
wakeups.
2025-02-13 14:53:30 +01:00
Max Kellermann
2276ebd70f io/uring/Queue: add DispatchCompletions() overload using io_uring_for_each_cqe() 2025-02-13 14:53:24 +01:00
Max Kellermann
a9bee1c64b io/uring/Ring: add io_uring_for_each_cqe() wrapper 2025-02-13 14:53:17 +01:00
Max Kellermann
c8e88408b2 io/uring/Ring: ignore EINTR 2025-02-13 14:53:11 +01:00
Max Kellermann
45644759fe io/uring/CancellableOperation: invoke OnUringCompletion() in destructor
This is important for operations that have complex cancellation
procedures (e.g. if they need to free buffers).  They might leave an
Operation instance in the queue.
2025-02-13 14:52:52 +01:00
Max Kellermann
e014d31972 io/uring/Ring: add io_uring_submit_and_wait_timeout() wrapper 2025-02-13 14:52:37 +01:00
Max Kellermann
b7655d38f7 io/uring/Queue: support IORING_CQE_F_MORE 2025-02-13 14:52:30 +01:00
Max Kellermann
268f737ac4 meson.build: suppress -Wmissing-field-initializers
There's nothing wrong with initializing only some fields.
2025-02-13 14:21:38 +01:00
Max Kellermann
80ff0a062a system/EpollFD: add method GetFileDescriptor() 2025-02-13 14:19:28 +01:00
Max Kellermann
24bcf44a47 subprojects: update sqlite to 3.49.0-1 2025-02-13 14:12:53 +01:00
gd
f1e43cb498 android: Loader - load early (before service thread) both in activity and service.
Loader converted from java to kotlin.

Instead of loading libmpd when the service thread is started,
the service will not start the the thread if libmpd failed to load.

The loader is also accessed by the view data to let
the ui adjust if failed to load, by showing the failure reason
and disabling the Start MPD button.
2025-02-06 14:23:26 +02:00
gd
ae1c5e3424 android: build.gradle - added build flavor "fail-test" to test System.loadLibrary("mpd") failure 2025-02-06 14:11:06 +02:00
gd
9eb5879542 android: IntentUtils - added license comment 2025-02-06 14:06:53 +02:00
gd
038759506f android: added 'universal' flavor that includes both both arm64-v8a and x86_64 versions of libmpd.so 2025-02-05 20:31:43 +02:00
gd
2bf9fdf10e android: migrated build to version catalogs
For easier management of dependencies versions: https://developer.android.com/build/migrate-to-catalogs
2025-02-05 20:15:58 +02:00
gd
0bf77f4eb3 android: converted Main from java to kotlin 2025-02-05 11:20:39 +02:00
gd
034bcf4f44 android: added product flavors to separatly build apk for arm64-v8a or x86_64 2025-02-04 10:23:26 +02:00
gd
834d6dcf46 android: build version of kotlin and compose updated.
Changed to compatible versions according to https://developer.android.com/jetpack/androidx/releases/compose-kotlin#kts
2025-02-04 10:22:57 +02:00
gd
8a642c8a83 android: MainScreen - use Icons.AutoMirrored.Filled.List instead of deprecated Icons.Default.List 2025-02-04 10:22:57 +02:00
gd
fe42ad2439 android: .gitignore - added previously misspelled app/src/main/jniLibs/ 2025-02-04 10:22:57 +02:00
gd
51242be72b android: changed permissions handling UI in status screen when show rationale is false
Android will ignore permission request and will not show the request dialog
if the user's action implies "don't ask again."
This leaves the app in a crippled state and the user confused.
Google says "don't try to convince the user", so it returns false for `shouldShowRequestPermissionRationale`.

To help the user proceed, we show the `Request permission` button only if `shouldShowRequestPermissionRationale == true`
because there's a good chance the premission request dialog will not be ignored.

If `shouldShowRequestPermissionRationale == false` we instead show the "rationale" message and a button to open
the app info dialog where the user can explicitly grand the permission.
2025-02-04 10:22:57 +02:00
gd
cb62aff43e android: added missing package declaration in SettingsScreen.kt 2025-02-04 10:22:57 +02:00
gd
491e726540 android: manifest - added sdk version to legacy permission READ_EXTERNAL_STORAGE, added permission READ_MEDIA_AUDIO
Change fo r SDK version 33 and above
2025-02-04 10:22:57 +02:00
gd
7404be41dc android: git ignoring .idea directory completely until a good reason emerges not to 2025-02-04 10:22:57 +02:00
Camille Scholtz
b8289ae923 input/meson.build: Add missing dependency 2025-02-03 23:07:58 +01:00
Max Kellermann
6b92b7adb9 util/PacketBigEndian: add operator| 2025-02-01 19:30:17 +01:00
Max Kellermann
00a352ffcd event/Loop: explicit io_uring initialization
Log the io_uring initialization error at MPD startup.
2025-02-01 19:20:50 +01:00
Max Kellermann
63cc07b8a7 event/Loop: add method SetThread()
Require to call it before calling Run(); remove the setter from Run().
This gives class EventThread more control over when it is initialized.
2025-02-01 19:19:59 +01:00
Max Kellermann
b2bf95009b event/Thread: use inline initializers 2025-02-01 18:24:02 +01:00
gd
7df041310c android: build.gradle.kts - updated dependencies versions. Updated compile sdk to 35, and target sdk to 34 2025-02-01 18:09:12 +01:00
gd
cd9522c1d1 android: manifest - added android:foregroundServiceType=mediaPlayback and permission FOREGROUND_SERVICE_MEDIA_PLAYBACK
Required by newer android sdk.
2025-02-01 18:09:07 +01:00
gd
59bd0fe0f0 android: added README.md for notes and resources for MPD android maintainers. 2025-02-01 18:09:02 +01:00
gd
0872a761c8 android: gradle build - add ndk.abiFilters to package the prebuilt arm64-v8a/libmpd.so with the apk 2025-02-01 18:08:58 +01:00
gd
996e158f56 android: updated gradle version 2025-02-01 18:08:55 +01:00
gd
7fb195bc0b android: Context.cxx - in GetExternalFilesDir removed assert type != nullptr
May be null for the root of the files directory.
2025-02-01 18:08:52 +01:00
gd
2fabaa2e95 android: meson.build - changed output dir name from jnilibs to jniLibs
It is the default name: https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs
2025-02-01 18:08:48 +01:00
Camille Scholtz
e3cf9bb0a1 Fix deamon mode on macos 2025-02-01 18:05:49 +01:00
Camille Scholtz
407db96d4a Install some more dependencies in the macos workflow 2025-02-01 18:05:42 +01:00
Camille Scholtz
3689200b78 Add prcr2 dependency to macos workflow 2025-02-01 18:05:34 +01:00
Camille Scholtz
6c16430a85 Remove whitespace 2025-02-01 18:05:24 +01:00
Camille Scholtz
ff37d11610 Workflow fixes for macOS 2025-02-01 18:05:17 +01:00
Camille Scholtz
509786cbf1 Revert "remove macOS support"
This reverts commit 518ce0187a29bea666b9abf71788625262d015be.
2025-02-01 18:05:13 +01:00
allixx
148050898a doc/user: update windows build meson version 2025-02-01 12:16:38 +03:00
Max Kellermann
a29d3eb975 Merge branch 'id3tag-meson-fix' of https://github.com/allixx/MPD into v0.23.x 2025-02-01 08:23:12 +01:00
allixx
1247ee5347 subprojects/packagefiles/id3tag/meson.build: fix meson errors 2025-02-01 09:59:40 +03:00
gd
f15b6a43d3 Logging: curl - write debug output through MPD log instead of curl writing directly to stderr.
The output gets the standard MPD log format with domain curl and a timestamp.
Using CURLOPT_DEBUGFUNCTION that is only called when CURLOPT_VERBOSE is in effect
when MPD log level is verbose.
2025-02-01 08:53:38 +02:00
Max Kellermann
bddfff9c2b meson.build: fix typo 2025-01-31 19:51:00 +01:00
allixx
cdc99812c9 python/build/libs.py: replace broken Boost 1.81.0 url 2025-01-31 19:17:28 +03:00
Max Kellermann
63ad12bb89 storage/nfs: MapUTF8("") returns the full URL including parameters
Closes https://github.com/MusicPlayerDaemon/MPD/issues/2154
2025-01-30 20:04:19 +01:00
Max Kellermann
7c4ddb5943 input/uring: initialize uring_input_queue lazily
The BlockingCall() in InitUringInputPlugin() did not work because the
EventThread was not yet started.  This was never noticed until commit
e309941646e which enabled `IORING_SETUP_SINGLE_ISSUER`, and suddenly
the kernel refused to accept io_uring_submit() calls from the
io_thread because io_uring_setup() had been called from the main
thread.
2025-01-30 20:00:57 +01:00
Max Kellermann
3cf5354e3f Revert "Main: start IO threads before initializing the rest"
This reverts commit abc84206977744f30f528f2ef27d87220266276d.  This
was a bad idea, too, because it broke daemonization.
2025-01-30 19:58:15 +01:00
Max Kellermann
838398103c Revert "event/Thread: start the thread in the constructor"
This reverts commit b49cfe96f406bf0b750b7a1ea73609905d606335.  It was
a bad idea because it broke signal handlers.  I need to find a better
way to fix io_uring intialization.
2025-01-30 19:58:15 +01:00
Max Kellermann
30bd70939a lib/nfs/Connection: remove unnecessary include 2025-01-30 17:24:20 +01:00
Max Kellermann
275cd9d1d0 lib/nfs/Connection: give up connection after NFS4ERR_EXPIRED
Once a NFS request fails with NFS4ERR_EXPIRED, the whole connection is
broken and we need to open a new one.  I wish libnfs would report this
to us as a connection-level error, but instead only the one request
fails; therefore this workaround is an ugly kludge.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2175
2025-01-30 17:23:39 +01:00
Max Kellermann
5b001957c7 input/async: skip resume and seek if there is a pending error
The resume/seek was received asynchronously and meanwhile an error
might have occurred that needs to be handled.

This fixes another NFS-related crash bug.
2025-01-30 16:47:51 +01:00
Max Kellermann
d1e5c90c3b decoder/flac: do not seek when DecoderCommand::STOP is received
libFLAC tries to keep on seeking a stream even after a (fatal) read
error has occurred.  Let the DecoderClient decide whether proceeding
is possible.

This fixes a crash bug when playing a file over NFS and the NFS
connection fails.
2025-01-30 16:46:04 +01:00
Max Kellermann
715ef846b6 input/Plugin: pass URI as std::string_view 2025-01-30 13:38:30 +01:00
Max Kellermann
aee49d1c1c input/cdio: pass std::string_view to parse_cdio_uri() 2025-01-30 13:17:47 +01:00
Max Kellermann
459390cd56 input/alsa: use std::string_view in class SourceSpec 2025-01-30 13:03:52 +01:00
Max Kellermann
7ca8dedb35 pcm/AudioParser: use std::string_view 2025-01-30 12:27:20 +01:00
Max Kellermann
f6cee35896 fs/Traits: add IsAbsolute(string_view) 2025-01-30 11:55:44 +01:00
gd
66ee03741d Logging: enable log timestamp to stdout logging
When running with stdout output to debug the server
or misbehaving clients, it is useful to have the timestamp
to detect timing issues and response times.
Especially when opening and playing online sources that
block the connection thread sometime for a significantly
long time that makes the client-server unresponsive
and cause timeouts in clients.
2025-01-30 11:33:21 +01:00
Max Kellermann
b49cfe96f4 event/Thread: start the thread in the constructor
This is the proper fix for the e309941646e0ff1b6 regression; see
commit abc84206977744f30f528f2ef27d87220266276d
2025-01-30 10:58:34 +01:00
Max Kellermann
ae112fe077 Merge branch 'sticker_errors' of https://github.com/jcorporation/MPD 2025-01-30 10:48:18 +01:00
Max Kellermann
a1cbfa1623 Merge branch 'sticker_set' of https://github.com/jcorporation/MPD 2025-01-30 10:46:23 +01:00
Max Kellermann
e06d775af5 util/CircularBuffer: add method MoveTo()
This implements wraparound, so AsyncInputStream and ThreadInputStream
can now return all of the buffer contents in one Read() call.
2025-01-29 21:28:28 +01:00
Max Kellermann
950f5f4d32 input/{async,thread}: move code to ReadFromBuffer() 2025-01-29 21:26:05 +01:00
Max Kellermann
abc8420697 Main: start IO threads before initializing the rest
This fixes a regression triggered by commit e309941646e0ff1b6 -
IORING_SETUP_SINGLE_ISSUER broke because io_uring_setup() was called
fromm the main thread, yet io_uring_submit() in the I/O thread.  This
is because the I/O thread was not yet started when
InitUringInputPlugin() was called, and BlockingCall() was invoked
synchronously in the main thread.  This has always been wrong, but was
never noticed.
2025-01-29 21:25:59 +01:00
Max Kellermann
e309941646 event/Loop: initialize io_uring with IORING_SETUP_SINGLE_ISSUER
This might give tiny kernel-side optimizations.
2025-01-29 20:29:42 +01:00
Max Kellermann
ea2ced6b9f event/UringManager: replace with new Uring::Manager class
From https://github.com/CM4all/libcommon - the new class is mostly
identical, and I want to maintain only one of them.
2025-01-29 20:27:13 +01:00
Max Kellermann
f1d06396a7 client: replace num with a name string
This logs the client address (or the process id and uid for local
connections) in each log line instead of the number.
2025-01-29 20:24:05 +01:00
Max Kellermann
95c0e2505c client/New: pass SocketPeerCredentials to client_new() 2025-01-29 19:36:47 +01:00
Max Kellermann
7adda0aa66 event/ServerSocket: move GetPeerCredentials() call to ClientListener::OnAccept() 2025-01-29 19:32:53 +01:00
Max Kellermann
a0825e6ce0 net/PeerCredentials: add getpeereid() support 2025-01-29 19:28:09 +01:00
Max Kellermann
c7621ec0e4 net/PeerCredentials: wrapper for struct ucred 2025-01-29 19:28:03 +01:00
Max Kellermann
2c7ca16c4e lib/fmt/ToBuffer: add constexpr 2025-01-29 18:12:08 +01:00
Max Kellermann
ad8c2577c4 util/PackedBigEndian: add class PackedSignedBE16 2025-01-29 18:11:47 +01:00
Max Kellermann
7c9a460786 io/uring/Ring: add method SetMaxWorkers() 2025-01-29 18:10:59 +01:00
Max Kellermann
c644b7616a io/uring/Ring: add ctor wrapping io_uring_queue_init_params() 2025-01-29 18:10:20 +01:00
Max Kellermann
badf7101e2 io/uring/Ring: use if with initializer 2025-01-29 18:10:04 +01:00
Max Kellermann
6fb91e661c io/uring/Queue: DispatchCompletions() returns bool 2025-01-29 18:09:57 +01:00
Max Kellermann
ed819a05e3 io/uring/Ring: add SubmitAndGetEvents() 2025-01-29 18:09:52 +01:00
Max Kellermann
2e3a51a5da io/uring/Close: use IOSQE_CQE_SKIP_SUCCESS
We don't want to get any completion events for "close".  It's
fire-and-forget.
2025-01-29 18:09:29 +01:00
Max Kellermann
e682940c54 event/PipeEvent: add GetScheduledFlags(), [GS]etReadyFlags() 2025-01-29 18:09:10 +01:00
Max Kellermann
fa375cbaeb event/uring/Manager: un-inline the ctor 2025-01-29 18:09:06 +01:00
Max Kellermann
3f638bfa03 io/uring/Operation: add method GetUringData() 2025-01-29 18:07:55 +01:00
Max Kellermann
0ba0c64093 event/uring/Manager: add flags parameter 2025-01-29 18:07:46 +01:00
Max Kellermann
5e107c33d9 event/DeferEvent: add ScheduleNext() 2025-01-29 18:05:50 +01:00
Max Kellermann
4bb379a218 event/ServerSocket: use SocketDescriptor::GetPeerCredentials() 2025-01-29 17:56:26 +01:00
Max Kellermann
3710b54d43 event/ServerSocket: pass SocketDescriptor to get_remote_uid() 2025-01-29 17:56:26 +01:00
Max Kellermann
70f1f9cff8 subprojects: update gtest to 1.15.2 2025-01-29 17:41:24 +01:00
Max Kellermann
9787d39c3f subprojects: update expat to 2.6.4 2025-01-29 17:41:11 +01:00
Max Kellermann
54527068d5 .github/workflows/build.yml: fix matrix name
Regression by commit ab011adf77e1bd003c33cf46c8ff999c22f394bd
2025-01-29 17:35:33 +01:00
Max Kellermann
0186f73c7a client/Process: let libfmt quote the command string 2025-01-29 17:32:42 +01:00
gd
88594c81d6 Logging: added seconds to log time string.
Time was only in minutes before.
Seconds is more useful in analyzing the log for example
with issues of timeouts, and reponse times.
2025-01-29 17:31:21 +01:00
Max Kellermann
f6bd49ba61 Merge branch 'tag-compare' of https://github.com/geneticdrift/MPD 2025-01-29 17:21:54 +01:00
Max Kellermann
a404e5754e release v0.23.17
-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmeaU0kQHG1heEBtdXNp
 Y3BkLm9yZwAKCRAjbopYxttFEtYUD/9a1KtdDSVTQAk6flFs71DYEvu1HKPlB51u
 9N2R0yx4dVvFIDEJi+O+I8RK0kfTuEyQFFm9/QzgmB5P7MBWbQH5nHzSINJ6aMlo
 OqeChrlLflGZWPypJQmT+gku80SgfrkRfC1pgVGDjh2a2y++0TQfAtuVlkIZEvl3
 rJ1auKuPGc/3+bM5/WC5zbsQSUrn24iEfh0akfz4tExBd17+DF7JN8IejapnCV1s
 EchsLaCONwxUW4SqeRUoU0OzO6triRFwglYa0pwHKUijHuL9ud5xvW7KVz+c7tTs
 2W5EgZshOyRNCIehV/ZNx9NL0zKM0ehb6//pBPmdZhXBJBsWS1YQzYLgJK+RNXeS
 sWEc1ANNS8R8V5b13sE+8mLwmjgUO6lLsjsuywrS0+ac3b8XeKU8PDqVq+oSZWdK
 jNh0SBN8MJpCLwJ/jFa6q36A+534G4hEV/QG0wvviK+wAf3OLpi3G0++wRyh0RcS
 msQWeoXHcY/nhfgDK2TrUjaJsHjVqqZljNaoiZSdseLFsXt73aTHQ6Eu12GXZNZF
 gxvd3jBGSrR5Zq+tes4oQ8unes/AEqXBN+PtJuLaZYxn8aOhButt6UEyfERO7NJY
 AMQomtwx3TVhpRwz/9LZMvpK4UIbd80i/3zv5w1mxns1LThErXgcEoqbKN86SJmU
 185T/UdrVA==
 =hdJY
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.17'

release v0.23.17
2025-01-29 17:20:02 +01:00
Max Kellermann
b080ca8627 release v0.23.17 2025-01-29 17:11:53 +01:00
Max Kellermann
0e8cd3b961 client/Process: explicitly disallow "idle" and "noidle" in command lists
These commands cannot possibly work with command lists because command
lists are supposed to be atomic, but suspended command execution
conflicts with that.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2167
2025-01-29 17:08:53 +01:00
Max Kellermann
8fcb6e148f decoder/list: probe "ffmpeg" before "sndfile" and "audiofile"
For FFmpeg's DTS-WAV support, see code comment.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2158
2025-01-29 15:42:54 +01:00
gd
ce9ee38304 decoder/Bridge: DecoderBridge::UpdateStreamTag - return false if stream tag not changed.
Some streams send the same tags frequently, causeing unnecessary update
events.
2025-01-29 16:02:20 +02:00
gd
f9d47502d8 player/Thread: update song tag from remote stream only if changed.
Some streams send the same tags frequently, causing unnecessary player queue update events.
2025-01-29 16:00:37 +02:00
gd
f15014b6af tag/Item: made TagItem constructor private and friend TagPoolItem
To only allow construction as part of TagPoolItem with its special var size allocator in TagPoolItem::Create.
2025-01-29 16:00:37 +02:00
gd
2a9c3a2e50 tag/Tag: added operator==(Tag&) 2025-01-29 16:00:37 +02:00
gd
3e9c2cce71 tag/Item: added operator== to TagItem 2025-01-29 16:00:37 +02:00
gd
93bf99f639 util/DereferenceIterator, TerminatedArray: added operator-(const IteratorType&) to DereferenceIterator and TerminatedArray::iterator
It is required by std::distance and some std algos.
2025-01-29 16:00:20 +02:00
Max Kellermann
c0a9434f34 command/file: "albumart" tries to send larger chunks if available
If we only receive very little data from the InputStream, try a second
Read() call to get more data.  This works around tiny reads at input
buffer boundaries with the io_uring input plugin.  These tiny reads
are inefficient, and we can afford to wait one more low-level I/O
iteration to finish (but not more).

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2186
2025-01-29 13:07:05 +01:00
Max Kellermann
d7212624b0 input/{async,thread}: clear the CircularBuffer when it becomes empty
First step towards fixing https://github.com/MusicPlayerDaemon/MPD/issues/2186
2025-01-29 13:05:24 +01:00
Max Kellermann
70a0a781c8 input/async: move the IsEOF() check to a separate block 2025-01-29 12:59:04 +01:00
Max Kellermann
ab011adf77 meson.build: require GCC 12 or clang 14
GCC 10 doesn't have std::make_unique_for_overwrite(), so let's drop it.
2025-01-29 12:24:48 +01:00
Max Kellermann
8ea3f86f43 Revert "meson.build: disable -Wsuggest-override with GCC 8"
This reverts commit 56c0733b427b444beebb9e1a85d5082a20e2a72b.  GCC 8
is no longer supported.
2025-01-29 12:22:11 +01:00
Max Kellermann
bd78307940 input/{async,thread}: add an additional Cond field
This eliminates the ScopeExchangeInputStreamHandler kludge.
2025-01-29 12:14:42 +01:00
Max Kellermann
3cc7b7dbf9 Merge branch 'v0.23.x' 2025-01-29 12:09:18 +01:00
Max Kellermann
57e7fb3f62 tag/Id3Load, ...: use std::make_unique_for_overwrite()
Don't zero-initialize the buffers.  This removes some useless
overhead.
2025-01-29 12:01:27 +01:00
Max Kellermann
687475cf3c db/update/InotifyUpdate: handle IN_CREATE without IN_ISDIR
A new symlink causes `IN_CREATE`.  Usually, we catch `IN_CREATE` only with
IN_ISDIR to watch the new directory, but otherwise `IN_CREATE` is not
handled.  Regular files are "created" but they have usable content
only with `IN_CLOSE_WRITE`.  Yet symlinks have only `IN_CREATE` and
they are immediately usable.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2192
2025-01-29 09:41:08 +01:00
Max Kellermann
c48dbd5dd4 lib/nfs/meson.build: reject libnfs 6
libnfs version 6 has major API changes and MPD 0.23 has never been
adapted to these.  This additional configure-time check fixes
potential compile-time failures.
2025-01-29 09:04:55 +01:00
Max Kellermann
37049aab36 lib/nfs/Connection: remove EnableCloseOnExec() call
SOCK_CLOEXEC has been added to libnfs version 2, and since we require
at least version 4, we can safely remove this call.
2025-01-29 09:02:05 +01:00
Max Kellermann
18495fbb4e lib/nfs/meson.build: require libnfs 4.0
All Linux distributions have at least version 4, and thus I cannot
test with older versions.
2025-01-29 09:00:37 +01:00
Max Kellermann
cdcee16738 client/File: improve error message
Users are confused by "Access denied".  Let's write an error message
that is more clear.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2184
2025-01-29 08:28:30 +01:00
Max Kellermann
83c2d9c964 test/meson.build: add another missing dependency on libevent.a
Necessary for including Client.hxx.
2025-01-28 19:52:25 +01:00
Max Kellermann
074a041760 test/meson.build: add missing dependencies on libevent.a 2025-01-28 19:47:36 +01:00
Max Kellermann
083d39ea80 decoder/plugins/meson.build: add missing dependency to libid3tag 2025-01-28 19:38:50 +01:00
Max Kellermann
a5da7fd51a Merge branch 'v0.23.x' 2025-01-28 19:33:19 +01:00
Max Kellermann
cf9a2eb508 .github/workflows/build.yml: disable yajl on macOS
This yajl on Homebrew comes with broken headers:

 /opt/homebrew/Cellar/yajl/2.1.0/include/yajl/yajl_parse.h:22:10: fatal error: 'yajl/yajl_common.h' file not found
 #include <yajl/yajl_common.h>
          ^~~~~~~~~~~~~~~~~~~~
2025-01-28 19:31:35 +01:00
Max Kellermann
0aeda01ba6 lib/yajl: drop "yajl/" prefix from #include paths
According to the yajl API documentation, #include lines should have
the "yajl/" path prefix, but the actual pkg-config file contains:

 includedir=${dollar}{prefix}/include/yajl

.. which already contains this directory name, and thus the "yajl/"
prefix cannot work.  Unfortunately, the yajl project hasn't been
maintained for nearly 10 years, and there's little chance this bug
will ever be fixed.
2025-01-28 19:27:46 +01:00
Max Kellermann
3798d11a8d .github/workflows/build.yml: disable NFS support
Homebrew comes with libnfs 6 which is not supported by MPD 0.23.
2025-01-28 19:23:36 +01:00
Max Kellermann
fab03f800a subprojects: remove libmicrohttpd
This one will be pulled in by libnpupnp automatically.  No need to
have it here.
2025-01-28 19:17:06 +01:00
Max Kellermann
5b5b101c56 subprojects: add id3tag 2025-01-28 19:15:43 +01:00
Max Kellermann
7770accee0 python/build/libs.py: remove libmad (unused) 2025-01-28 19:14:03 +01:00
Max Kellermann
eb3cd7bed3 subprojects: add lame 2025-01-28 19:13:59 +01:00
Max Kellermann
56cc2f4c65 subprojects: add libmpdclient wrap 2025-01-28 19:13:46 +01:00
Max Kellermann
9723af3f35 subprojects: add openssl 2025-01-28 19:13:45 +01:00
Max Kellermann
dcf3cf4216 subprojects: add ogg, flac, opus 2025-01-28 19:13:19 +01:00
Max Kellermann
578c94081f subprojects: add curl 2025-01-28 19:12:57 +01:00
Max Kellermann
efa8304d2d subprojects/.gitignore: sort 2025-01-28 19:12:42 +01:00
Max Kellermann
2752f67877 lib/nfs/meson.build: add missing dependency on libevent.a 2025-01-28 19:05:09 +01:00
Max Kellermann
f55e0df614 lib/curl/meson.build: add missing internal dependency on libevent.a 2025-01-28 18:52:37 +01:00
Max Kellermann
177ffde90f Merge branch 'v0.23.x' 2025-01-28 18:45:02 +01:00
Max Kellermann
0d1fb9a02c meson.build: build libnpupnp and libmicrohttpd statically as submodules 2025-01-28 18:43:23 +01:00
Max Kellermann
a0a39ae828 .github/workflows/build.yml: update actions/checkout to v4 2025-01-28 18:39:17 +01:00
Max Kellermann
e57c60e3d8 .github/workflows/build.yml: update hendrikmuhs/ccache-action to v1.2 2025-01-28 18:38:59 +01:00
Max Kellermann
53090e3745 .github/workflows/build.yml: update actions/setup-python to v5 2025-01-28 18:37:06 +01:00
Max Kellermann
93eb3da48a subprojects: add liburing 2025-01-28 18:35:21 +01:00
Max Kellermann
75a3d9340e python/build/libs.py: update FFmpeg to 7.1 2025-01-28 18:34:29 +01:00
Max Kellermann
9445ea1565 subprojects: add libnpupnp 2025-01-28 18:34:29 +01:00
Max Kellermann
a5a26d304b subprojects: update sqlite3 to 3.48.0-1 2025-01-28 18:34:29 +01:00
Max Kellermann
1d8d298a22 subprojects: update fmt to 11.1.1-2 2025-01-28 18:34:28 +01:00
Max Kellermann
508bfbe334 pipewire/meson.build: add "include_type:system"
This suppresses a compiler warning due to sloppy code in PipeWire:

 /usr/include/spa-0.2/spa/utils/json-core.h:440:29: error: implicit conversion increases floating-point precision: 'float' to 'double' [-Werror,-Wdouble-promotion]
   440 |         return spa_dtoa(str, size, val);
       |                ~~~~~~~~            ^~~
2025-01-28 18:34:12 +01:00
Max Kellermann
1385212572 io/uring/meson.build: detect liburing with include_type=system
This avoids breakages due to `-Wgnu-anonymous-struct`.
2025-01-28 18:34:07 +01:00
Max Kellermann
8dcd6ea2b4 increment version number to 0.23.17 2025-01-28 18:13:07 +01:00
Max Kellermann
75d0914373 Merge branch 'fix-handle-status' of https://github.com/geneticdrift/MPD 2025-01-28 06:18:19 +01:00
Max Kellermann
35dc1fc589 io/UniqueFileDescriptor: use AdoptTag in the constructors that adopt ownership 2025-01-23 16:57:39 +01:00
Max Kellermann
765a6a2f20 net/UniqueSocketDescriptor: use AdoptTag in the constructors that adopt ownership
This makes it a little bit harder to use the ownershop-adopting
constructors accidently.
2025-01-23 16:56:57 +01:00
Max Kellermann
131263cbe3 util/TagStructs: add struct AdoptTag 2025-01-23 16:56:00 +01:00
Max Kellermann
936611b47c util/ShallowCopy: rename header to TagStructs.hxx
This new header will be a collection of more structs like ShallowCopy.
2025-01-23 16:55:51 +01:00
gd
266eb393eb fix: output of command status broken by a misplaced comma in the format arguments 2025-01-21 14:03:41 +02:00
Michael Herstine
194ecd69e0 lib/fmt: remove even more now-broken uses of FMT_STRING
MPD stopped building since fmt 11.1.0; see
<https://github.com/fmtlib/fmt/issues/4304>. The first commit
fixing this was 9db7144, followed by 5de0909 (both on the
unstable branch).

This commit removes what the author believes to be the remaining
uses in the MPD codebase.
2025-01-20 19:54:41 -08:00
Michael Herstine
b24b3c1054 Merge remote-tracking branch 'upstream/v0.23.x' 2025-01-20 09:44:07 -08:00
Alfred Wingate
5de0909ae5
lib/fmt: remove the rest of the broken use of FMT_STRING
Fixes: 9db7144d0fa4512335070a984690f3f5034210a5
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2025-01-18 03:29:14 +02:00
Rudi Heitbaum
da6efd6361 plugins/meson.build: revert unintentional static link change
Minor revert of 9db7144d0fa4512335070a984690f3f5034210a5
- no change was to be done to meson.build.
2025-01-13 22:39:12 +00:00
Rudi Heitbaum
9db7144d0f lib/fmt: drop use of FMT_STRING
When compiling with libfmt-11.1.0 and newer the following compile errors occur:

In file included from ../src/decoder/DecoderPrint.cxx:23:
../src/client/Response.hxx: In instantiation of 'bool Response::Fmt(const S&, Args&& ...) [with S = decoder_plugin_print(Response&, const DecoderPlugin&)::<lambda()>::FMT_COMPILE_STRING; Args = {const char* const&}]':
../src/decoder/DecoderPrint.cxx:38:7:   required from here
   38 |         r.Fmt(FMT_STRING("plugin: {}\n"), plugin.name);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/client/Response.hxx:86:28: error: cannot convert 'const decoder_plugin_print(Response&, const DecoderPlugin&)::<lambda()>::FMT_COMPILE_STRING' to 'fmt::v11::string_view' {aka 'fmt::v11::basic_string_view<char>'}
   86 |                 return VFmt(format_str,
      |                        ~~~~^~~~~~~~~~~~
   87 |                             fmt::make_format_args(args...));
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/client/Response.hxx:81:36: note: initializing argument 1 of 'bool Response::VFmt(fmt::v11::string_view, fmt::v11::format_args)'
   81 |         bool VFmt(fmt::string_view format_str, fmt::format_args args) noexcept;
      |                   ~~~~~~~~~~~~~~~~~^~~~~~~~~~
../src/client/Response.hxx: In instantiation of 'bool Response::Fmt(const S&, Args&& ...) [with S = decoder_plugin_print(Response&, const DecoderPlugin&)::<lambda()>::FMT_COMPILE_STRING; Args = {const char* const&}]':

The error is due to the use of FMT_STRING. The libfmt team shared the following:

    The correct way of using FMT_STRING is to wrap a format string when passing to a
    function with compile-time checks (i.e. that takes format_string) as documented
    in https://fmt.dev/11.1/api/#legacy-compile-time-checks.

    Noting that FMT_STRING is a legacy API and has been superseded by consteval-based
    API starting from version 8: https://github.com/fmtlib/fmt/releases/tag/8.0.0. It
    looks like MPD is trying to emulate {fmt}'s old way of implementing compile-time
    checks which was never properly documented because it was basically a hack. So the
    correct fix is to switch to format_string and, possibly, remove usage of FMT_STRING.

    The old way of doing compile-time checks (fmt::make_args_checked) was documented
    in https://fmt.dev/7.1/api.html#argument-lists but it looks like MPD is not using
    that API so the problematic uses of FMT_STRING have no effect and can just be removed.

The FMT_STRING has been removed in this change based on the fmt-7.1 API and now MPD is
successfully compile against the current libfmt-11.1.0 which highlighted the issue that
had been present in the codebase as it is now triggering the error, is legacy and was
not using the API for which FMT_STRING was aligned with.
2025-01-13 06:17:01 +00:00
jcorporation
bd36b5e310 Response with error for sticker set,inc,dec and add missing asserts 2024-12-12 19:40:06 +01:00
jcorporation
015870ac71 Replace STICKER_SQL_INSERT and STICKER_SQL_UPDATE with STICKER_SQL_SET that lets handle sqlite insertion or update of the sticker value. 2024-12-12 19:15:22 +01:00
Max Kellermann
b1677bf79c Merge branch 'sticker_inc_dec' of https://github.com/jcorporation/MPD 2024-12-12 08:38:58 +01:00
jcorporation
1078c1c1bf Add sticker sub-commands inc and dec
Let sqlite do the work for incrementing or decrementing a sticker value.
This sub-commands are usefull to track playcounts with sticker values and
saves us one roundtrip.
2024-12-11 21:41:24 +01:00
Max Kellermann
9a8579d956 event/ServerSocket: do not close all listeners before rethrowing
If binding one address fails, we don't need to close all listeners.
For fatal errors, this will be done automatically and implicitly; and
for non-fatal errors (e.g. binding to the default port failed, but
there is an XDG listener), this closes the good listeners which are
supposed to be used.

Closes https://github.com/MusicPlayerDaemon/MPD/pull/2157
2024-12-04 14:25:42 +01:00
Max Kellermann
b6e187efd8 release v0.23.16
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmdO8gkNHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEgdSEACRi/mJGq9at6GAlyBDuemzAo/UyyAa2fR8xTxf
 V7qGMlWfyylSFp9J1SwPvl56J5s28VpoFL4sfW9TYb9U3bl/eTTlyEvxZBgCbYq8
 fSDzVY7ReWxr1u/Fv7GuR9Nbu/tN0NItlBRB23FkNIYmdRxxH0h/fKbgXRD9TUiG
 qs4w97AqeWvxDuEyaoX0Y/l2tdlLyUENi7G7Np34giSFKpq9ldD28nKl18ORSuby
 +tK124wW1s/p7ncrzhzd9NyrEvmCMKB951H95H7+sfgojAY1LuVWGtiJSfMYw+w0
 LqCd23l78kwOfDYPwvB8sp4lUpVdxv4u9YhGwgNfzwavCrOWfzYMVg+hub3V0N//
 Xx79wGSkR1NQcbfUD05U6c4+jfDGARDRx9dUQWpeJGOF3LHFFFIyAPGW5T0DZrDY
 aPdoaLKbtK7F36QdBPZryhv49lXdsbd1OKhFV54QMR04bM3a150t6CiFk53nQIk0
 akIKCDt0Gi3GrLRkSwOeOwVuWsI/Y0SQC8dp8cIzCa9toIzfn42hG14SKM2FWAP1
 4BmekNkfqsG6xY8xcRwq6+HF1aq3dDHoPqIfE0r71/hadlIX9OjSNlepP2VIyzY/
 Gl5jvkf9el2MfI4JeCXafsZCyqlV6mx4HVPXrtiLgSdY3odTA1aShFI6/jfEjxXM
 Yo/ngQ==
 =640n
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.16'

release v0.23.16
2024-12-03 13:01:15 +01:00
Max Kellermann
30d2a31473 command/sticker: remove unreachable code 2024-12-03 12:32:33 +01:00
Max Kellermann
9a7a8ec137 io: always pass O_NONBLOCK to open()
Opening a FIFO may block indefinitely (until a writer connects).  This
is dangerous because it may be a DoS vulnerability in many programs
that do not expect open() to block.

This obsoletes the method FileDescriptor::OpenNonBlocking() which
wasn't used anyway.
2024-12-03 12:28:17 +01:00
Max Kellermann
88fa68f030 net/SocketDescriptor: add GetPeerPidfd() 2024-12-03 12:27:20 +01:00
borine
78e643150f output/Source: fix Close()
Close the filter before cancelling when closing a source.
Fixes 
2024-11-19 10:59:35 +00:00
Max Kellermann
eb1463fd7c test/util/TestIntrusiveTreeSet: add constant_time_size test 2024-11-13 10:44:28 +01:00
Max Kellermann
6dce8dcaa5 io/FileDescriptor: add readv()/writev() wrappers 2024-11-13 10:44:03 +01:00
Max Kellermann
fc4a579d83 io/FileDescriptor: remove Read()/Write() with void pointers
Obsolete and unsafe.
2024-11-13 10:43:34 +01:00
Max Kellermann
263b9916c2 unix/PidFile: pass std::span to FileDescriptor::Read() 2024-11-13 10:43:33 +01:00
Max Kellermann
16604997d6 system/{Event,Signal}FD: pass std::span to FileDescriptor::Read() 2024-11-13 10:43:08 +01:00
Max Kellermann
77226bc0d8 test/ReadFrames: pass std::span to FileDescriptor::Read() 2024-11-13 10:42:35 +01:00
Max Kellermann
7a6672b7ed util/IntrusiveTreeSet: update the counter, fixing constant_time_size 2024-11-13 10:36:57 +01:00
Max Kellermann
8db14c9cb3 Instance: add method FindOutput()
Move code from handle_moveoutput().
2024-11-11 19:08:45 +01:00
Max Kellermann
370df37596 io/uring/Ring: add more API documentation 2024-11-11 19:04:24 +01:00
Max Kellermann
84e3501084 io/uring/Queue: remove redundant include 2024-11-11 19:04:21 +01:00
Max Kellermann
a7d41a99a1 util/ForeignFifoBuffer: pass std::span to constructor 2024-11-11 19:03:31 +01:00
Max Kellermann
c9c5e84119 util/ForeignFifoBuffer: store buffer as std::span 2024-11-11 19:02:58 +01:00
Max Kellermann
8a3b48754e util/ForeignFifoBuffer: use Read() in MoveBuffer() and Shift() 2024-11-11 19:02:43 +01:00
Max Kellermann
849c4012c0 filter/Filter: add method ReadMore()
This allows FilterPCM() to return more data, which some
implementations may need to do (e.g. FFmpeg).
2024-11-08 19:31:16 +01:00
Max Kellermann
d8bb833ba3 output/Source: convert runtime check to assert()
Flush() may only be called if the source is open.
2024-11-08 19:09:31 +01:00
Max Kellermann
4d8a2ea688 output/Source: add assert(filter) 2024-11-08 18:50:48 +01:00
Max Kellermann
a7a61e9e41 output/Source: add inline 2024-11-08 18:34:22 +01:00
Max Kellermann
415cf096e9 output/Thread: add another inline 2024-11-08 18:24:48 +01:00
Max Kellermann
7774c3369e filter/two: check empty() instead of data()==nullptr
See bcab29d53a8981993444c5d5fda642bc82ccd73f
2024-11-05 22:37:36 +01:00
Max Kellermann
bcab29d53a filter/Filter: Flush() returns empty span, not nullptr 2024-11-05 13:19:25 +01:00
Max Kellermann
d6195025fb filter/Filter: clarify Flush() documentation 2024-11-05 13:11:25 +01:00
Max Kellermann
d7ae512b5e filter/Filter: clarify that the FilterPCM() return value may be empty
And adjust TwoFilter accordingly.
2024-11-05 12:35:10 +01:00
Max Kellermann
b7b4c6b4ea filter/Filter: Flush() also invalidates the returned buffer
Just API documentation.
2024-11-05 12:35:09 +01:00
Max Kellermann
f59f17013d MusicChunk: add method ReadData() 2024-11-05 12:34:35 +01:00
Max Kellermann
4beedec3ad MusicChunk: add missing include 2024-11-05 12:31:30 +01:00
Max Kellermann
950888d161 output/Source: fix indent 2024-11-05 12:28:41 +01:00
Max Kellermann
76562fc093 test/run_{filter,output}: use fmt 2024-11-05 11:48:37 +01:00
Max Kellermann
0676ab7f47 filter/two: use if with initializer 2024-11-02 22:48:02 +01:00
Max Kellermann
fc5d258890 filter/ffmpeg: fill AVFrame::pts
Some libavfilter plugins don't produce any output if `pts` is never
set, e.g. the `lowpass` plugin.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2114
2024-11-02 22:24:53 +01:00
Max Kellermann
7dce7ad32d Merge branch 'tagtypes_reset' of https://github.com/jcorporation/MPD 2024-11-02 20:58:06 +01:00
Max Kellermann
fa29693550 filter/ffmpeg: implement method Flush() 2024-11-02 20:55:04 +01:00
Pascal Nkornyui
2c881c63ba
doc/plugins.rst: fix spelling 2024-11-02 19:37:13 +00:00
jcorporation
fd7d251358 Add "reset" subcommand to tagtypes.
This subcommand combines "clear" and "enable" in one command.
2024-11-01 18:07:06 +01:00
Max Kellermann
acb9ee9792 filter/ffmpeg: move code to ReadOutput() 2024-10-30 22:49:20 +01:00
Max Kellermann
3d99f1d8a6 filter/ffmpeg: use if with initializer 2024-10-30 22:47:21 +01:00
Max Kellermann
2ef36af68d test/run_filter: add command line parser 2024-10-30 22:17:42 +01:00
Max Kellermann
d7b4634e5e io/FileLineReader: add missing include 2024-10-30 21:47:37 +01:00
Max Kellermann
2bc57c38d2 meson.build: set cpp_std=c++20
Meson supports this since version 0.57.0.
2024-10-30 21:37:49 +01:00
Max Kellermann
744308bfff python/build/libs.py: update FFmpeg to 7.1 2024-10-30 21:31:17 +01:00
Max Kellermann
7db93fb20b subprojects: update sqlite3 to 3.47.0-1 2024-10-30 21:29:57 +01:00
Max Kellermann
95db2db736 subprojects: update curl to 8.10.1-1 2024-10-30 21:29:47 +01:00
Max Kellermann
f807345022 event/Loop: use std::chrono::ceil()
Thanks to C++17, we don't need our custom implementation anymore.
2024-10-30 21:29:16 +01:00
Max Kellermann
b745d1f226 util/StringCompare: add constexpr 2024-10-30 21:29:16 +01:00
Max Kellermann
52e2130d51 util/StringCompare: simplify StringIsEqual() using operator== 2024-10-30 21:28:15 +01:00
Max Kellermann
1930ed16cb Merge branch 'icu76-support' of https://github.com/cho-m/MPD 2024-10-27 15:22:04 +01:00
Michael Cho
1a063fee7e
meson.build: support building with ICU 76
ICU 76 decided to reduce overlinking[^1] thus `icu-i18n` will no longer
add `icu-uc` when linking to shared libraries. This results in failure:
```
src/lib/icu/libicu.a.p/Converter.cxx.o: undefined reference to symbol 'ucnv_fromUnicode_76'
```

[^1]: 199bc82702
2024-10-27 09:57:22 -04:00
jcorporation
51e0fefda7 Fix order of commands 2024-10-26 11:32:36 +02:00
Max Kellermann
449f8af7d0 Merge branch 'protocol_features' of https://github.com/jcorporation/MPD 2024-10-26 08:18:56 +02:00
Max Kellermann
38b46e680a Merge branch 'stickernames-types' of https://github.com/jcorporation/MPD 2024-10-26 08:16:53 +02:00
Max Kellermann
17d0cd0abd Merge branch 'queue_loaded_playlist' of https://github.com/jcorporation/MPD 2024-10-26 08:15:23 +02:00
Max Kellermann
98bc63251e Merge branch 'searchplaylist_pos' of https://github.com/jcorporation/MPD 2024-10-26 08:14:31 +02:00
Max Kellermann
030bac441f Merge branch 'playlistlength_fix' of https://github.com/jcorporation/MPD 2024-10-26 08:13:14 +02:00
Max Kellermann
f82a385be2 Merge branch 'tagtypes_available' of https://github.com/jcorporation/MPD 2024-10-26 08:10:07 +02:00
jcorporation
052719c0e4 Fix integer overflow calculating length of very large playlists 2024-10-20 12:12:50 +02:00
jcorporation
bfbff31860 Store last loaded playlist
Stores the last loaded playlist uri in the queue struct.
Last loaded playlist is set on load command and cleared with the clear command.
The last loaded playlist is printed in the status command and saved / restored from the partition state file.

Resolves issue 
2024-10-20 12:03:31 +02:00
jcorporation
b1067333dc Print positions in the search playlist functions. 2024-10-20 11:55:52 +02:00
jcorporation
35bdf74952 Mention contains and starts_with for "sticker find" 2024-09-28 22:43:20 +02:00
jcorporation
23c2bba483 This commit adds a new protocol command to toggle protocol features
for a client connection. It works like the tag_mask and the associated
tagtypes command.

New commands:

- protocol
  Shows enabled protocol features.

- protocol available
  Show all available protocol features.

- protocol enable {feature...}
  Enables protocol features.

- protocol disable {feature...}
  Disables protocol features.

- protocol all
  Enables all available protocol features.

- protocol clear
  Disables all protocol features.

This commit adds also the first protocol feature.

hide_playlists_in_root
  Disables the listing of playlists in the root folder
  for the lsinfo command.
2024-09-28 22:41:35 +02:00
jcorporation
25e8ce2d37 New command tagtypes available
Shows the list of tag types configured by the ``metadata_to_use`` setting.
2024-09-28 22:40:29 +02:00
Max Kellermann
124c0e66ee subprojects: update libnpupnp to 6.2.0-1, libmicrohttpd to 0.9.77-3 2024-09-27 08:53:01 +02:00
Max Kellermann
202bb4f90f subprojects: update fmt to 11.0.2-1 2024-09-27 08:52:22 +02:00
Max Kellermann
5ee42ada67 subprojects: update curl to 8.10.0-1 2024-09-27 08:52:10 +02:00
Max Kellermann
752c6c1f03 lib/fmt/ExceptionFormatter: move the exception_ptr 2024-09-27 08:48:30 +02:00
Max Kellermann
def2221dfd Merge branch 'searchplaylist_syntax' of https://github.com/jcorporation/MPD 2024-09-27 08:47:02 +02:00
Max Kellermann
9ff8e02e54 net/Resolver: use StringIsEqual() 2024-09-04 17:26:45 +02:00
Max Kellermann
32dd9704ce util/DeleteDisposer: add const and noexcept 2024-09-04 17:24:42 +02:00
Max Kellermann
523519182a util/IntrusiveHashSet: add concept checks 2024-09-04 17:24:24 +02:00
jcorporation
3f718e8924 Change the semantic of the searchplaylist protocol command
Old: searchplaylist {NAME} {FILTER} [{START:END}]
New: searchplaylist {NAME} {FILTER} [window {START:END}]

This is more similar to the other search commands and we can reuse search specific functions in libmpdclient.
2024-08-30 21:06:50 +02:00
jcorporation
26c4211cd4 New command stickernamestypes
Lists sticker names with their types and optionally filters by type
2024-08-30 20:14:55 +02:00
Max Kellermann
a3a07280e8 Merge branch 'mpd-2100-nested-and' of https://github.com/m7a/mpd 2024-08-30 12:57:20 +02:00
Max Kellermann
ed755f04e9 lib/fmt/meson.build: suppress -Warray-bounds with GCC 14
The bug is still present in GCC 14.
2024-08-30 12:48:41 +02:00
Max Kellermann
2809db8b40 Merge branch 'searchplaylist' of https://github.com/jcorporation/MPD 2024-08-30 12:47:24 +02:00
Max Kellermann
c866199d4c net/SocketError: cast to socket_error_t to fix -Wsign-compare
Only relevant on Windows where socket_error_t is a `DWORD` (unsigned).
2024-08-30 12:45:10 +02:00
Max Kellermann
39937be2e1 Merge branch 'stickertypes' of https://github.com/jcorporation/MPD 2024-08-30 12:43:54 +02:00
Max Kellermann
d207c144d6 lib/curl/Multi: remove the Wait() overload with "int" timeout
Enforce type-safety.
2024-08-30 12:30:18 +02:00
Max Kellermann
435f1eb6cc lib/curl/Multi: remove default timeout value
-1 is an illegal value and leads to CURLM_BAD_FUNCTION_ARGUMENT.  Our
API shouldn't imply this value.
2024-08-30 12:30:15 +02:00
Max Kellermann
c7b80b0828 io/FileDescriptor: add method WriteAt() 2024-08-30 12:29:32 +02:00
Max Kellermann
59199b5620 io/FileDescriptor: pass std::span to ReadAt() 2024-08-30 12:29:27 +02:00
Max Kellermann
ebfc83dac5 io/FileDescriptor: add method SetPipeCapacity() 2024-08-30 12:28:51 +02:00
Max Kellermann
f535ccf9bf net/UniqueSocketDescriptor: add UniqueFileDescriptor constructor 2024-08-30 12:28:19 +02:00
Max Kellermann
75eb2c257c net/SocketError: add IsSocketError() overload with socket_error_t 2024-08-30 12:27:19 +02:00
Max Kellermann
314667259e net/SocketDescriptor: add Duplicate() method
The the Duplicate() method we inherited from class FileDescriptor
returns a UniqueFileDescriptor, but we really want to return a
UniqueSocketDescriptor.
2024-08-30 12:27:13 +02:00
Max Kellermann
dbb2b29271 net/IPv6Address: add method GetPortBE() 2024-08-30 12:24:12 +02:00
Max Kellermann
7f25ede888 net/AddressInfo: add method Cast() 2024-08-30 12:23:45 +02:00
Max Kellermann
4a2fff019a util/DisposablePointer: suppress -Wuninitialized
I pretend to know what I'm doing :-)
2024-08-30 12:23:45 +02:00
Max Kellermann
fae5d16d43 subprojects: update curl to 8.9.1-1 2024-08-30 12:23:41 +02:00
Max Kellermann
7bc2259b35 subprojects: update sqlite3 to 3.46.1-1 2024-08-30 12:23:27 +02:00
Max Kellermann
f66aed921c python/build/libs: update FFmpeg to 7.0.2 2024-08-30 12:22:37 +02:00
Linux-Fan, Ma_Sys.ma
6db4b818e6 song/Filter: Fix spacing error on nested AND
Previously, `AND` expressions were the only filters which used `++s` instead
of `s = StripLeft(s + 1)` making them sensitive to spacing issues. This caused
nested AND expressions (like e.g. `(((A) AND (B)) AND (C))`) to needlessly be
rejected with the following error message: `{find} Word expected` due to the
fact that the inner AND expression would leave the cursor `s` at a space rather
than the beginning of the next word (remainder was ` AND (C))` rather than
`AND (C)`).

This commit fixes this by consistently using `s = StripLeft(s + 1)` instead
of `++s` when parsing AND expressions. Although it is not strictly necessary
to resolve the AND nesting bug, the case of trivial AND expressions (consisting
basically of only superfluous parentheses) is also changed to the new handling.
This should be more robust although I expect that case to be even less common
than the direct nesting of AND expressions.

see 
2024-08-23 21:36:53 +02:00
jcorporation
f94caa96b8 Add command stickertypes
Prints all available stickertypes like tagtypes for tags.
2024-08-14 21:07:14 +02:00
Max Kellermann
965c466e9b Merge branch 'mpg-duration-fix' of https://github.com/boedy/MPD 2024-08-10 16:54:48 +02:00
boedy
731f20111a Override the value for file size in bytes. Useful for getting sensible track length values in feed mode or for HTTP streams.
https://www.mpg123.de/api/group__mpg123__status.shtml#gad0301e80dbc3f48e47e27d39cd328755
2024-08-08 18:43:15 +02:00
jcorporation
d62f7cdc34 New command searchplaylist 2024-08-02 23:46:17 +02:00
Max Kellermann
f7790430a0 lib/curl/Multi: add SetSocketFunction(), SetTimerFunction() 2024-07-31 10:06:29 +02:00
Max Kellermann
959826d1d1 input/ffmpeg: offload FFmpeg calls to thread
Prepare for interruptible I/O.
2024-07-30 12:43:05 +02:00
Max Kellermann
ec30716e01 input/thread: implement size and seek 2024-07-30 12:33:44 +02:00
Max Kellermann
dc51015c75 input/mms: move MMS_BUFFER_SIZE into the class 2024-07-30 12:33:30 +02:00
Max Kellermann
72b0eeb7b1 input/mms: invoke Start() in constructor 2024-07-30 12:31:58 +02:00
Max Kellermann
b050e0132e input/{async,thread}: add an additional Cond field
This eliminates the ScopeExchangeInputStreamHandler kludge.
2024-07-29 23:17:33 +02:00
Max Kellermann
cf962d94c7 input/thread: remove bogus inline 2024-07-29 23:14:16 +02:00
Max Kellermann
c29d23b4c3 input/thread: use notify_one() instead of notify_all()
There's only ever one waiter, and notify_one() may be faster than
notify_all().
2024-07-29 23:09:07 +02:00
Max Kellermann
61e8df913d input/thread: check IsEOF() in IsAvailable() 2024-07-29 23:05:00 +02:00
Max Kellermann
4a55e3e8bd input/thread: check buffer.empty() in IsEOF() 2024-07-29 23:03:00 +02:00
Max Kellermann
2e78bd430c input/thread: use pass std::span<std::byte> to ThreadRead() 2024-07-29 22:32:52 +02:00
Max Kellermann
dbaa72cb40 util/CircularBuffer: use std::span internally 2024-07-29 22:24:54 +02:00
Max Kellermann
596d2d93dd util/CircularBuffer: use using instead of typedef 2024-07-29 22:21:38 +02:00
Max Kellermann
10311b3a65 util/CircularBuffer: explicitly forbid the copy operator 2024-07-29 22:20:15 +02:00
Max Kellermann
332ba42073 util/HugeAllocator: add std::span cast operator 2024-07-29 22:20:12 +02:00
Max Kellermann
4262d29965 util/HugeAllocator: add constexpr 2024-07-29 22:19:28 +02:00
Max Kellermann
0899d80ae0 util/CircularBuffer: add noexcept and constexpr 2024-07-29 22:14:59 +02:00
Max Kellermann
9fe6493fc2 util/CircularBuffer: use inline initializer 2024-07-29 22:13:50 +02:00
Max Kellermann
902cb8efac input/thread: use std::byte instead of uint8_t 2024-07-29 22:13:50 +02:00
Max Kellermann
f54210bf68 input/async: move enum definition down 2024-07-29 22:13:42 +02:00
Max Kellermann
fb151c8662 lib/fmt/meson.build: suppress -Warray-bounds with GCC 13 2024-07-29 22:13:11 +02:00
Max Kellermann
323517753d lib/fmt/meson.build: remove obsolete clang 14 workaround
Android NDK r27 has clang 18 and I don't feel like supporting clang 14.
2024-07-29 22:11:20 +02:00
Max Kellermann
5726d9f06a mixer/Memento: include cleanup 2024-07-29 17:04:53 +02:00
Max Kellermann
0992fab1c8 filter/ReplayGain: include cleanup 2024-07-29 17:04:30 +02:00
Max Kellermann
b546ddc54c client/Idle: include cleanup 2024-07-29 17:03:59 +02:00
Max Kellermann
d45b7cc972 IdleFlags: move to procool/ 2024-07-29 17:02:33 +02:00
Max Kellermann
12eaaef210 output/Thread: allow Delay() to return duration::max()
Eliminate the periodic wakeups while paused in some output plugins.
2024-07-29 16:52:36 +02:00
Max Kellermann
5b8ef9a62b python/build/__init__.py: add missing file 2024-07-29 16:51:40 +02:00
Max Kellermann
196258ea13 .github/workflows/build_android.yml: update NDK to r27 2024-07-29 16:38:26 +02:00
Max Kellermann
0a035f3ce0 output/alsa: add option "close_on_pause"
This allows keeping the ALSA PCM open even if playback is paused.  As
a side effect, this allows using the "always_on" option with ALSA
outputs, because "always_on" pauses the output.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1623
2024-07-29 16:31:09 +02:00
Max Kellermann
7ab789fbaf doc/user.rst: add clarification to the "always_on" option 2024-07-29 16:30:15 +02:00
Max Kellermann
9c8f4aaf99 lib/alsa/meson.build: require libasound 1.2 or later
This allows us to drop the 1.1.4 snd_pcm_drain() bug workaround (added
by commit f85d4d28d1e).
2024-07-29 15:42:46 +02:00
Max Kellermann
3bef4f839a output/alsa: fix coding style 2024-07-29 15:40:52 +02:00
Max Kellermann
1dfda3a5e1 output/alsa: reorder fields to improve packing 2024-07-29 15:38:02 +02:00
Max Kellermann
9d9c4045e2 output/alsa: move redundant code to UnregisterSockets() 2024-07-29 15:28:58 +02:00
Max Kellermann
d466deedad output/alsa: fix lambda indent 2024-07-29 15:28:27 +02:00
Max Kellermann
bbbbf5f4bd event/MultiSocketMonitor: reschedule epoll/EPERM workaround forever
Fixes a regression by commit 3558317dc9c which caused the ALSA null
plugin to cease to work because the workaround timer was never rescheduled.
2024-07-25 20:16:53 +02:00
Max Kellermann
f030b22bec player/thread: wait for the first chunk in CheckCrossFade()
This fixes MixRamp problems which occur because CheckCrossFade() is
called before the decoder has parsed MixRamp tags after
DecoderClient::Ready().

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2084
2024-07-25 20:07:52 +02:00
Max Kellermann
a693052f2c Merge branch 'feat/showmovement' of https://github.com/mayanez/MPD 2024-07-25 14:01:19 +02:00
Miguel A. Arroyo
e3809bd4f0 feat: Add ShowMovement Tag
This commit adds the `SHOWMOVEMENT` [tag](https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#show-work-movement-4). Historically, this tag originates from iTunes' MP4, but has since become widely used. It is created by Picard's Classical music [plugins](https://picard-docs.musicbrainz.org/en/variables/variables_classical.html) (such as "Classical Extras" or "Work & Movement").

The reasoning behind this tag is to display Work & Movement titles without redundant information and in a more uniform way. Moreover, it additionally serves as an implicit marker denoting classical music tracks (genre tags aren't sufficient).

If the client so chooses to support this tag, they can display `Work` and `Movement` instead of the track title allowing for cleaner display. Other clients can continue to display the `%title%` as before without any fuss.
2024-07-23 21:09:31 -07:00
Max Kellermann
41cc695848 Instance: fix io/rtio thread mixup
Fixes regression by commit 43d633f560ee2499a02094039fa1ec24d8f47f14
2024-07-23 15:12:30 +02:00
Max Kellermann
3558317dc9 event/MultiSocketMonitor: remove force-refresh on every iteration
libasound guarantees that the file descriptors never change for a
"prepared" PCM device, thus we can omit this defensive kludge.
2024-07-23 15:08:55 +02:00
Max Kellermann
18cb34825d input/alsa: use libfmt instead of std::string concatenation 2024-07-23 15:04:49 +02:00
Max Kellermann
4c4a3c8664 event/TimerList: use FineTimerEvent::GetDue()
Avoid accessing the private field from an inner class of the friend
class, because some compilers apparently don't like it (Apple clang).
2024-07-23 13:38:05 +02:00
Max Kellermann
b4374ddb35 python/build/libs.py: update libopenmpt to 0.7.9 2024-07-23 13:08:04 +02:00
Max Kellermann
d24e7763f6 net/AddressInfo: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:05:19 +02:00
Max Kellermann
49ad4e9f3c io/FileDescriptor: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:05:02 +02:00
Max Kellermann
ea96b321dc net/SocketAdddress: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:04:48 +02:00
Max Kellermann
bc758cece0 util/StringPointer: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:04:37 +02:00
Max Kellermann
0e4885c1fa util/IterableSplitString: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:04:30 +02:00
Max Kellermann
9944c97203 util/AllocatedString: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:04:20 +02:00
Max Kellermann
58a5550439 util/AllocatedArray: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-23 13:04:10 +02:00
Max Kellermann
8e42467bd2 decoder/mpg123: relax mpg123_length() check in Scan()
Do not fail the Scan() function completely if libmpg123 cannot
determine the duration.
2024-07-12 16:11:08 +02:00
Max Kellermann
e00e7802c8 decoder/mpg123: report unknown duration if mpg123_length()<0
Closes https://github.com/MusicPlayerDaemon/MPD/issues/2058
2024-07-12 16:09:35 +02:00
Max Kellermann
55d0bbade2 decoder/mpg123: move code to GetDuration() 2024-07-12 16:08:11 +02:00
Max Kellermann
de9f0dc910 playlist/Plugin: convert _init() and _finish() to methods 2024-07-12 16:00:42 +02:00
Max Kellermann
cf5970a6e1 output/Registry: replace output_plugins_for_each() with a container class 2024-07-12 15:55:01 +02:00
Max Kellermann
29747a213f playlist/Registry: replace playlist_plugins_for_each() with a container class 2024-07-12 15:52:05 +02:00
Max Kellermann
c64b4838dc encoder/List: replace encoder_plugins_for_each() with a container class 2024-07-12 14:59:18 +02:00
Max Kellermann
040c4a8560 archive/ArchiveList: replace archive_plugins_for_each() with a container class 2024-07-12 09:58:19 +02:00
Max Kellermann
90dfa437e0 lib/alsa/NonBlock: use a persistent pollfd array
This implements the semantic API change introduced by commit
cd04da2bcf
2024-07-11 21:47:15 +02:00
Max Kellermann
4486b2eded lib/alsa/NonBlock: add common base class 2024-07-11 21:38:45 +02:00
Max Kellermann
3db8a4f41b lib/alsa/NonBlock: embed in "namespace Alsa" 2024-07-11 21:33:03 +02:00
Max Kellermann
9704cf3dcb lib/alsa/NonBlock: fix lambda indent 2024-07-11 21:12:18 +02:00
Max Kellermann
9aa6b03ba8 event/MultiSocketMonitor: pass std::span to ReplaceSocketList() 2024-07-11 21:09:27 +02:00
Max Kellermann
45f92f0ef0 event/MultiSocketMonitor: fix lambda indent 2024-07-11 21:06:33 +02:00
Max Kellermann
23a3278b4e event/MultiSocketMonitor: make ctor protected and explicit 2024-07-11 21:05:11 +02:00
Max Kellermann
951f916440 mixer/alsa: add noexcept 2024-07-11 21:03:41 +02:00
Max Kellermann
fb87e19bae input/Registry: replace the input_plugins_for_each macros with a container class 2024-07-11 20:52:44 +02:00
Max Kellermann
49edb16de0 decoder/Thread: add enum DecodeResult, log better diagnostics
Closes https://github.com/MusicPlayerDaemon/MPD/issues/2076
2024-07-11 16:47:43 +02:00
Max Kellermann
8671896e4c decoder/Thread: throw StopDecoder if command==STOP in decoder_run_stream()
Everybody else is doing that, so let's do the same and not pretend
playback was successful.
2024-07-11 16:28:57 +02:00
Max Kellermann
c2470ebd9c decoder/List: eliminate decoder_plugins_try()
Migrate callers to GetEnabledDecoderPlugins().  By not using lambdas,
we can switch to enums as return value for better diagnostics.
2024-07-11 16:15:38 +02:00
Max Kellermann
a27fb71c4c decoder/List: add iterable container for decoder plugins 2024-07-11 15:30:31 +02:00
Max Kellermann
f6a687dc2b util/FilteredContainer: new class 2024-07-11 15:30:30 +02:00
Max Kellermann
9210705598 util/TerminatedArray: new class 2024-07-11 15:30:30 +02:00
Max Kellermann
3d995bba5f util/DereferenceIterator: add class DereferenceContainerAdapter 2024-07-11 14:55:35 +02:00
Max Kellermann
c77f5095d6 util/DereferenceIterator: allow comparing with sentinel end iterators 2024-07-11 14:55:35 +02:00
Max Kellermann
3701378449 util/DereferenceIterator: fix operator- and operator+ return types 2024-07-11 14:29:10 +02:00
Max Kellermann
cb9f3c1a5b util/DereferenceIterator: optimize and simplify increment/decrement operators 2024-07-11 14:27:23 +02:00
Max Kellermann
fe66cde616 util/DereferenceIterator: add constexpr 2024-07-10 20:13:24 +02:00
Max Kellermann
0cc9ef0aee util/DereferenceIterator: remove unnecessary operator!=()
The compiler must generate this implicitly from operator==().
2024-07-10 20:13:19 +02:00
Max Kellermann
68a424d9e1 util/DereferenceIterator: add missing const 2024-07-10 20:11:55 +02:00
Max Kellermann
13576b8a2e lib/curl/Easy: use pass std::chrono::duration to SetTimeout() 2024-07-10 16:58:16 +02:00
Max Kellermann
7c21d57953 config/Block: add method GetDuration() 2024-07-10 16:58:16 +02:00
Max Kellermann
1e9e182a32 config/Data: merge the two duration parser methods, pass minimum value 2024-07-10 16:49:18 +02:00
Max Kellermann
3733bc57b7 config/{Block,Data,Param}: add concept checks to With() 2024-07-10 16:38:08 +02:00
Max Kellermann
a196d1ddf2 decoder/Thread, ...: quote log strings 2024-07-10 15:40:04 +02:00
Max Kellermann
8861279add Merge branch 'explicit_case_sensitivity' of https://github.com/geneticdrift/MPD 2024-07-10 15:33:47 +02:00
Max Kellermann
f2f6dc5897 subprojects: update fmt to 11.0.1 2024-07-10 09:32:11 +02:00
Max Kellermann
00c4abfd2e Merge branch 'opus' of https://github.com/neheb/MPD 2024-07-10 09:27:16 +02:00
Rosen Penev
2d1feb78b5 subprojects: opus: update to 1.5.2
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-07-09 15:04:43 -07:00
Rosen Penev
266deaaef1 subprojects: libnpupnp: update to 6.1.3
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-07-09 14:48:37 -07:00
gd
d2382e8de9 ParseStringFilter: when failed to parse the operator, indicate the unknown operator in the error message 2024-07-09 17:25:45 +03:00
gd
c39d8e5813 Added explicitly case sensitive/insensitive filter operators.
The default case sensitivity is hard coded for each command.
These operators allow to override the this default case sensitivity.
2024-07-09 17:25:45 +03:00
Max Kellermann
bd59c889f3 util/StringVerify: new library 2024-07-08 16:02:40 +02:00
Max Kellermann
553c2e9e2b output/Command: trigger IDLE_OUTPUT only for the current partition
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1622
2024-07-08 15:54:14 +02:00
Max Kellermann
bdc5602244 meson.build: update the required GCC/clang versions 2024-07-08 15:44:45 +02:00
Max Kellermann
3229da48e3 tag/Mask: pass 64 bit integer to constructor, prevent truncation
Commit f49d4ef4ad0 changed the bit mask size to 64 bit, but I forgot
to change the constructor as well.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2057
2024-07-08 15:34:27 +02:00
Max Kellermann
e380ae90eb Log: add missing include for std::back_inserter()
Closes https://github.com/MusicPlayerDaemon/MPD/issues/2071
2024-07-07 10:10:27 +02:00
Max Kellermann
8d15e0fed3 Merge branch 'meson' of https://github.com/leigh123linux/MPD 2024-07-06 13:43:28 +02:00
Leigh Scott
b459fd3910
Fix bin install location on linux.
For Linux, Meson's default value for bindir is 'bin' [1].
This commit restores mpd's previous functionality of installation in ${prefix}/bin.

[1] https://mesonbuild.com/Builtin-options.html

Fixes https://github.com/MusicPlayerDaemon/MPD/issues/2043
2024-07-06 09:43:01 +01:00
Max Kellermann
8790f2469c lib/fmt/SocketAddressFormatter: switch to the new net/FormatAddress library 2024-07-05 18:39:10 +02:00
Max Kellermann
d3ef4ab234 net/FormatAddress: new library to replace ToString.cxx
This library writes to a caller-specified buffer instead of
allocating a std::string which can be faster by avoiding heap
allocations.
2024-07-05 18:38:17 +02:00
Max Kellermann
fcddab84c6 subprojects: add libnpupnp/GCC14 fix 2024-07-05 18:26:51 +02:00
Max Kellermann
28c030c0f0 lib/fmt/SocketAddressFormatter: add const for fmt 11 support
See d70729215f
2024-07-05 18:21:38 +02:00
Max Kellermann
175103e8d4 lib/fmt/ExceptionFormatter: un-inline to reduce header dependencies 2024-07-05 18:20:31 +02:00
Max Kellermann
3f638eeed6 lib/fmt/SocketAddressFormatter: un-inline to reduce header dependencies 2024-07-05 18:20:31 +02:00
Max Kellermann
df2be0a75f Log: add missing include for GetFullMessage() 2024-07-05 18:20:31 +02:00
Max Kellermann
608c2a8c93 .github/workflows/build.yml: add clang build
Due to linker failures, we need to build our own libfmt and
googletest.
2024-07-05 18:05:56 +02:00
Max Kellermann
2d918bf2c9 .github/workflows/build.yml: add matrix.packages 2024-07-05 17:50:46 +02:00
Max Kellermann
0bd1289371 .github/workflows/build.yml: remove the forced fallback for libfmt
Ubuntu 24.04 has fmt 9.1.0, so we don't need that anymore.
2024-07-05 17:50:44 +02:00
Max Kellermann
b2e2d36d79 .github/workflows/build.yml: add Meson option "--wrap-mode nofallback"
The library setup should be well-defined without implicit downloads.
2024-07-05 17:43:39 +02:00
Max Kellermann
11bb2ad0fd .github/workflows/build_android.yml: update NDK to 27rc1 2024-07-05 17:35:54 +02:00
Max Kellermann
f37b699349 .github/workflows/build_android.yml: switch to Ubuntu 24.04 as well
Since 24.04 comes with Meson 1.3.2, we can install it with "apt-get"
instead of "pip".
2024-07-05 17:29:37 +02:00
Max Kellermann
044280c538 meson.build: require Meson 1.0
Debian Bookworm (the current stable) has 1.0.1 and Ubuntu LTS 24.04
has 1.3.2.  It's acceptable to require at least version 1.0 now.
2024-07-05 17:23:52 +02:00
Max Kellermann
473fb4e19f .github/workflows/build.yml: update GCC 11 build to GCC 14
We only need the oldest supported compiler (i.e. GCC 10) and the
newest one available in the runner (i.e. GCC 14).
2024-07-05 17:21:31 +02:00
Max Kellermann
404e1c3912 .github/workflows/build.yml: update ubuntu-22.04 to ubuntu-24.04 2024-07-05 17:12:34 +02:00
Max Kellermann
3648475f87 Merge branch 'libfmt' of https://github.com/heitbaum/MPD 2024-07-05 16:47:04 +02:00
Rudi Heitbaum
1402869715 lib/fmt: support build with libfmt-11.0.0
Upstream libfmt commit fmtlib/fmt@d707292
now requires the format function to be const.

Adjust the function prototype so it is const and can compile.

Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>
2024-07-05 14:33:07 +00:00
Max Kellermann
a64ea486e8 Merge branch 'albumart_doc' of https://github.com/jcorporation/MPD 2024-07-05 16:27:47 +02:00
Max Kellermann
ffa917e9b5 Merge branch 'stickernames_cmd' of https://github.com/jcorporation/MPD 2024-07-05 16:26:58 +02:00
Max Kellermann
ac1265b9cc output/alsa: set up the ALSA channel map
This is necessary for proper multi-channel support because many ALSA
drivers do not use the channel maps from surround*.conf.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2063
2024-06-27 21:52:38 +02:00
Max Kellermann
2ce8310448 time/Convert: forward-declare struct tm 2024-06-25 20:33:13 +02:00
Max Kellermann
a739eefb01 lib/zlib/Error: derive from std::system_error 2024-06-25 20:32:33 +02:00
Max Kellermann
432bfa15f4 net/SocketError: move check to IsSocketError() 2024-06-25 20:29:27 +02:00
Max Kellermann
7b938b4d14 util/Exception: sanitize message strings
This should prevent leaking unsanitized strings from libraries.
2024-06-25 20:29:07 +02:00
Max Kellermann
abb23ba894 event/EpollEvents: add mapping for EPOLLPRI 2024-06-25 20:28:34 +02:00
Max Kellermann
cd64f9c422 subprojects: update curl to 8.8.0-1 2024-06-25 20:08:45 +02:00
Max Kellermann
c65d0cefc1 subprojects: update sqlite3 to 3.46.0-1 2024-06-25 20:08:45 +02:00
Max Kellermann
799e89af9e python/build/libs.py: update FFmpeg to 7.0.1 2024-06-25 20:08:00 +02:00
Max Kellermann
381215fd73 *: use std::scoped_lock with implicit template parameter 2024-05-23 20:54:49 +02:00
Max Kellermann
4fc3230fe6 event/Loop: use std::scoped_lock with implicit template parameter 2024-05-23 20:44:12 +02:00
Max Kellermann
64bdaa46fb lib/curl/Init: use std::scoped_lock with implicit template parameter 2024-05-23 20:44:12 +02:00
Max Kellermann
6e16eaebba lib/fmt/SystemError: include <array> only on Windows 2024-05-23 20:31:56 +02:00
Max Kellermann
a67f7f88e4 util/MimeType: add missing include 2024-05-23 20:31:10 +02:00
Max Kellermann
ec8f467585 util/Intrusive*: add IWYU pragmas 2024-05-23 20:30:50 +02:00
Max Kellermann
9e3a66d5bf util/djb_hash: make inline and constexpr
Allows calculating hashes at compile time.
2024-05-23 20:30:17 +02:00
Max Kellermann
c7409d1e04 util/AllocatedString: add missing include 2024-05-23 20:22:44 +02:00
Max Kellermann
b64d01677b storage/nfs: optimize OpenFile() 2024-05-17 13:39:42 +02:00
Max Kellermann
9e8128ecb5 lib/nfs/FileReader: convert path to std::string 2024-05-17 12:54:08 +02:00
Max Kellermann
131dcce0a1 playlist/Mapper: use Storage::OpenFile() 2024-05-17 12:54:08 +02:00
Max Kellermann
6dfdd8c1c2 db/update/Walk: use Storage::OpenFile() 2024-05-17 12:54:08 +02:00
Max Kellermann
1b6c279850 db/update/Paylist: use Storage::OpenFile() 2024-05-17 12:54:08 +02:00
Max Kellermann
81c778a529 SongUpdate: use Storage::OpenFile() 2024-05-17 12:54:08 +02:00
Max Kellermann
f578a1cb2b storage/Interface: add virtual method OpenFile()
This should replace most InputStream::Open() calls because it is a
chance to reuse existing resources (e.g. the NFS connection).  No such
optimization is implemented, currently (and the method is not yet used
by anybody).
2024-05-17 12:54:08 +02:00
Max Kellermann
2576e66a55 input/nfs: cancel the pending read operation on seek 2024-05-17 12:54:08 +02:00
Max Kellermann
58e3b830e9 lib/nfs/FileReader: clear the read_buffer in CancelRead()
Fixes assertion failure with libnfs 6.
2024-05-17 12:53:35 +02:00
Max Kellermann
1d35031024 lib/nfs/Connection: merge CancelAndClose() into Cancel() 2024-05-17 12:53:30 +02:00
Max Kellermann
96b61755da lib/nfs/FileReader: fix doc typo 2024-05-15 21:31:30 +02:00
Max Kellermann
9f174c56ce playlist/Mapper: postpone the stored playlist error
Fixes another regression by commit
f53cd44c7a557cde5b16928728ceea10d4431c0a - an exception thrown by
playlist_open_in_playlist_dir() would skip over
playlist_open_in_storage().
2024-05-15 21:08:46 +02:00
Max Kellermann
c8be9662bb playlist/Print: add missing exception handler
This went missing in commit f53cd44c7a557cde5b16928728ceea10d4431c0a
2024-05-15 20:53:55 +02:00
Max Kellermann
f53cd44c7a playlist/{Stream,Mapper,Any}: propagate exceptions, do not catch&log them
Let the caller handle all the exceptions.
2024-05-15 20:19:57 +02:00
Max Kellermann
9303764a83 playlist/Print: throw PlaylistError::NoSuchList instead of returning false 2024-05-15 20:19:09 +02:00
Max Kellermann
a5456a89dc playlist/Length: throw PlaylistError::NoSuchList instead of returning false 2024-05-15 20:15:16 +02:00
Max Kellermann
c974fc664c playlist/Plugin: add noexcept 2024-05-15 20:02:12 +02:00
Max Kellermann
eceead671e playlist/Stream: add API documentation 2024-05-15 19:59:57 +02:00
Max Kellermann
4e7b554605 TagAny, playlist/Mapper: use if with initializer 2024-05-15 15:02:59 +02:00
Max Kellermann
a701da6386 db/update/InotifyUpdate: use OpenLocalInputStream() 2024-05-15 14:48:32 +02:00
Max Kellermann
1f47fe47c7 input/Open: move code to WaitReady() 2024-05-15 14:39:40 +02:00
Max Kellermann
5dd07ac040 test/run_storage: use the OptionParser class for command-line options
Introducing the option "--verbose".
2024-05-15 14:11:25 +02:00
Max Kellermann
ca8a2aeb7b test/run_storage: print a combined usage text for all commands 2024-05-15 11:17:30 +02:00
Max Kellermann
57fad1d4b2 test/run_storage: move initialization to class GlobalInit 2024-05-15 10:15:12 +02:00
Max Kellermann
5c2720a931 .github/workflows/build.yml: drop MINGW32 build
The MINGW32 build has been failing for a while because the MSYS2
repository has dropped MINGW32 versions of various packages in commit
6866be94df

I suppose nobody really uses 32 bit anymore.  I'd like to have a 32
bit test of MPD, just to verify code correctness, but on the other
hand, I don't like solving problems like this MSYS2 packaging problem.
2024-05-15 06:20:57 +02:00
Max Kellermann
31e583e9f8 lib/nfs: initial support for libnfs API 2
Commit
5e8f7ce273
introduced the libnfs API version 2 which may eventually become libnfs
version 6.

This version detection depends on my pull request
https://github.com/sahlberg/libnfs/pull/468
2024-05-15 06:01:42 +02:00
Max Kellermann
0ac24e5a24 lib/nfs/FileReader: move code to ReadCallback() 2024-05-15 06:00:37 +02:00
Max Kellermann
98f53b6d3d lib/nfs/Connection: add DisposablePointer parameter to CancelAndClose()
Just in case somebody needs to free a buffer after the NFS
cancellation has completed.
2024-05-15 06:00:35 +02:00
Max Kellermann
f5092cb73d util/DisposablePointer: new class 2024-05-15 05:58:23 +02:00
Max Kellermann
48d3bd1cca lib/nfs/Connection: add API documentation 2024-05-14 19:57:50 +02:00
Max Kellermann
5cffd4f673 lib/nfs/Connection: remove EnableCloseOnExec() call
SOCK_CLOEXEC has been added to libnfs version 2, and since we require
at least version 4, we can safely remove this call.
2024-05-14 19:51:52 +02:00
Max Kellermann
416f65fe01 util/RoundPowerOfTwo: new library 2024-05-13 20:25:57 +02:00
Max Kellermann
64c291ba78 lib/nfs/Connection: suppress bogus clang warning
We do need to capture "this" because we use "this->active_leases", but
clang 18 is too dumb to understand this.
2024-05-13 18:30:05 +02:00
Max Kellermann
dcde2a0bae lib/nfs/Connection: fix -Wunused-lambda-capture 2024-05-13 18:27:38 +02:00
Max Kellermann
f0ac0c19b7 lib/nfs/Connection: remove obsolete debug field "in_destroy"
This is obsolete because PrepareDestroyContext() no longer calls
nfs_destroy_context().
2024-05-13 16:53:18 +02:00
Max Kellermann
ba1b8533a5 lib/nfs/Connection: fix assertion failure on mount timeout
When nfs_destroy_context() is called while nfs_mount_async() is in
progress, libnfs invokes MountCallback(-EINTR) (but only if a NFS RPC
call is in progress; if the TCP connect is in progress, that callback
is not invoked).

If the mount operation had timed out, OnMountTimeout() set
mount_state=FINISHED, which triggered an assertion failure in
MountCallback(); this commit adds a check on whether the mount has
timed out and ignores the MountCallback.
2024-05-13 16:51:44 +02:00
Max Kellermann
84e8927b1b lib/nfs/FileReader: remove obsolete stat64 cast
Obsoleted (and broken) by commit 9947d3e67fb4f7ab388c4ae1593dad8bce0f3153
2024-05-13 12:33:03 +02:00
Max Kellermann
556300d59a input/InputStream: add [[nodiscard]] 2024-05-13 12:29:16 +02:00
Max Kellermann
34f7b38f39 input/InputStream: pass std::span<std::byte> to Read() 2024-05-13 12:28:40 +02:00
Max Kellermann
f28d10d934 decoder/dsdiff: convert pointers to references 2024-05-13 11:34:05 +02:00
Max Kellermann
d6adc59265 test/run_storage: use FormatISO8601() 2024-05-13 10:37:33 +02:00
Max Kellermann
c154dc00d7 test/run_storage: use StringIsEqual() 2024-05-13 10:37:25 +02:00
Max Kellermann
6d5dab38dd input/async: pass std::string_view to constructor 2024-05-13 10:18:18 +02:00
jcorporation
480f4d4cf1 Fix filename list for albumart 2024-05-12 22:17:13 +02:00
jcorporation
f8271fec12 command_available return stickernames only if stickerdb is enabled 2024-05-12 21:23:29 +02:00
Max Kellermann
4800f1d8f2 storage/Interface: add [[nodiscard]] 2024-05-10 19:08:57 +02:00
Max Kellermann
48ce8e9fb7 subprojects: update sqlite3 to 3450300 2024-05-10 18:18:04 +02:00
Max Kellermann
f746e5b7d7 subprojects: update liburing to 2.5 2024-05-10 18:17:52 +02:00
Max Kellermann
cdce257512 subprojects: update libnpupnp to 6.1.2 2024-05-10 18:17:42 +02:00
Max Kellermann
227ab998bc lib/nfs/Connection: pass status and data to the NfsClientError ctor
This way, we avoid calling the FormatNfsClientError() which crashes
when nfs_get_error() returns nullptr; that can happen on RPC errors:
then, libnfs's check_nfs4_error() doesn't call nfs_set_error().

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2040
2024-05-10 16:36:29 +02:00
Max Kellermann
9384bff6f9 lib/nfs/Manager: add method MakeConnection()
This uses the libnfs function nfs_parse_url_dir() which means MPD
gains support for the libnfs arguments like "version".

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2039
2024-05-07 21:22:43 +02:00
Max Kellermann
9947d3e67f lib/nfs/Connection: use nfs_fstat64_async()
This is 64-bit-safe and anyway, nfs_fstat_async() doesn't work with
NFSv4.
2024-05-07 21:22:40 +02:00
Max Kellermann
67f01fbdb6 db/plugins/simple/Song: pass StorageFileInfo to UpdateFile()
Eliminates a redundant GetInfo() call.
2024-05-07 21:22:39 +02:00
Max Kellermann
164b5b0cf3 db/Song, SongUpdate: remove unnecessary c_str() calls
Just case implicitly to std::string_view, which is both simpler and
safer.
2024-05-07 21:13:38 +02:00
Max Kellermann
56bb1dddd7 lib/nfs/Connection: simplify error handling in OnSocketReady() 2024-05-06 18:35:58 +02:00
Max Kellermann
e6b1cf540b lib/nfs/Connection: remove unnecessary initializers from MountInternal() 2024-05-06 18:24:36 +02:00
Max Kellermann
d61c83ace8 lib/nfs/Connection: create the nfs_context in the constructor
Another lifetime simplification.
2024-05-06 18:22:23 +02:00
Max Kellermann
4139024b3d lib/nfs/Connection: return from OnSocketReady() after error 2024-05-06 18:20:42 +02:00
Max Kellermann
48fe8666c9 lib/nfs/Connection: call nfs_destroy_context() only in the destructor
This simplifies the lifetime of the nfs_context object.
2024-05-06 18:16:11 +02:00
Max Kellermann
90a44a0c07 lib/nfs/Connection: replace flag "mount_finished" with enum 2024-05-06 18:16:11 +02:00
Max Kellermann
e013c19223 storage/nfs: remove unused method EnsureConnected() 2024-05-06 18:16:11 +02:00
Max Kellermann
4684d05fa6 player/Thread: reset the decoder_starting flag in StopDecoder()
Fixes crash bug (assertion failure) if a new "play" command is handled
while the player thread waits for decoder startup.
2024-05-06 17:38:58 +02:00
Max Kellermann
1c3a1c842d lib/nfs/Lease: use InstrusiveList instead of std::list 2024-05-06 17:22:36 +02:00
Max Kellermann
f5127686fe lib/nfs/Connection: pass std::exception_ptr by value 2024-05-06 17:03:21 +02:00
Max Kellermann
2b0275a1c8 lib/nfs/Connection: pass server and export_name as std::string_view 2024-05-06 17:01:15 +02:00
Max Kellermann
028693c380 lib/nfs/Manager: forward-declare class ManagedConnection 2024-05-06 16:58:41 +02:00
Max Kellermann
63920be17e lib/nfs/Connection: make server and export_name const 2024-05-06 16:55:57 +02:00
Max Kellermann
96888cce9c storage/nfs: pass std::string_view to the NfsStorage ctor 2024-05-06 15:28:01 +02:00
Max Kellermann
bcc39be784 lib/nfs/Base: use std::string_view 2024-05-06 15:25:55 +02:00
Max Kellermann
b6314b4c4b lib/nfs/Base: use std::array 2024-05-06 15:22:49 +02:00
Max Kellermann
23d895415a lib/nfs/meson.build: require libnfs 4.0
All Linux distributions have at least version 4, and thus I cannot
test with older versions.
2024-05-06 14:54:04 +02:00
Max Kellermann
518ce0187a remove macOS support
There were a few macOS related bug reports on the bug tracker which
have been open for years without a volunteer caring for them.  The
GitHub actions build has also been broken for a long time due to bugs
in the ancient LLVM toolchain shipped with macOS, making macOS an
unsuitable non-Linux target for testing MPD's portability.

All of this makes macOS support an annoying liability for me.  To
avoid more frustration, I'm hereby dropping macOS support completely
from MPD.  Maybe this causes enough pain for a new maintainer to
spawn, but maybe nobody cares, so... let's see.
2024-05-06 14:11:50 +02:00
Max Kellermann
1c69498c58 .github/workflows/build.yml: do not install yajl on macOS
The Brew package of yajl is broken, it fails to build:

 In file included from ../src/lib/yajl/Handle.cxx:4:
 In file included from ../src/lib/yajl/Handle.hxx:6:
 /opt/homebrew/Cellar/yajl/2.1.0/include/yajl/yajl_parse.h:22:10: fatal error: 'yajl/yajl_common.h' file not found
 #include <yajl/yajl_common.h>
          ^~~~~~~~~~~~~~~~~~~~
 1 error generated.

Therefore, MPD cannot support building with yajl on macOS.
2024-05-06 13:39:02 +02:00
Max Kellermann
615f6f50ce lib/yajl: drop "yajl/" prefix from #include paths
According to the yajl API documentation, #include lines should have
the "yajl/" path prefix, but the actual pkg-config file contains:

 includedir=${dollar}{prefix}/include/yajl

.. which already contains this directory name, and thus the "yajl/"
prefix cannot work.  Unfortunately, the yajl project hasn't been
maintained for nearly 10 years, and there's little chance this bug
will ever be fixed.
2024-05-06 13:31:34 +02:00
Max Kellermann
79df6a646b Merge branch 'mpdlib' of https://github.com/DDRBoxman/MPD 2024-05-06 13:03:50 +02:00
Max Kellermann
89d68fb2af Merge branch 'debian-build-doc' of https://github.com/mxjeff/MPD 2024-05-06 13:03:05 +02:00
Max Kellermann
03b674ce73 net/meson.build: compile IPv[46]Address.cxx only if TCP is enabled 2024-05-06 12:57:55 +02:00
Max Kellermann
9c421997bf net/SocketDescriptor: WriteNoWait() uses MSG_NOSIGNAL 2024-05-06 12:55:02 +02:00
Max Kellermann
3813433e02 test/net/TestLocalSocketAddress: add unit tests for GetLocalRaw() 2024-05-06 12:54:45 +02:00
Max Kellermann
73509fc189 net/LocalSocketAddress: new class wrapping struct sockaddr_un 2024-05-06 12:54:45 +02:00
Max Kellermann
7c9b7fa311 net/SocketAddress: use std::string_view::find() instead of std::memchr() 2024-05-06 12:54:45 +02:00
Max Kellermann
cbba22c947 net/SocketAddress: include IPv[46]Address.hxx only ifdef HAVE_TCP 2024-05-06 12:50:44 +02:00
Max Kellermann
f8529d4fe6 net/{Allocated,Static}SocketAddress: inline GetLocalRaw() 2024-05-06 12:50:29 +02:00
Max Kellermann
2a206ef309 net/StaticSocketAddress: add method GetLocalPath() 2024-05-06 12:50:24 +02:00
Max Kellermann
6200c0dc46 net/StaticSocketAddress: include <string_view> only ifdef HAVE_UN 2024-05-06 12:50:19 +02:00
Max Kellermann
1760310123 Revert "util/IntrusiveList: allow the last disposer to destroy the IntrusiveList"
This reverts commit 669cbcd25aec664c465907347601e48ab51c9aed
("util/IntrusiveList: allow the last disposer to destroy the
IntrusiveList").  It was bad because it could lead to off-by-one crash
bugs when the last item was removed inside the previous item's
disposer.

We need a different solution for the other crash bug that was fixed by
the reverted commit.
2024-05-06 12:49:30 +02:00
Max Kellermann
c8ed28e9c6 test/util/TestIntrusiveList: add test for clear_and_dispose() with modifying disposer 2024-05-06 12:49:04 +02:00
Max Kellermann
56d4784b11 util/IntrusiveList: add API documentation 2024-05-06 12:48:53 +02:00
Max Kellermann
4d3adaa557 event/SocketEvent: erase IMPLICIT_FLAGS in Cancel{Read,Write}()
Without this, calling CancelRead() after ScheduleRead() would leave
the HANGUP scheduled, and the caller could receive HANGUP events over
and over which are never properly handled, leading to a busy loop.

The semantics of this API are hard to get right, because the
IMPLICIT_FLAGS (a property of epoll) are somewhat weird.  But it seems
that this change repairs a side effect of the SocketEvent interface
that seemed counterintuitive.
2024-05-06 12:48:42 +02:00
Max Kellermann
6830cf9dcf net/AllocatedSocketAddress: add SetLocal() overload with std::string_view 2024-05-06 12:48:42 +02:00
Max Kellermann
4ba288501d .github/workflows/build.yml: install ccache manually
This eliminates the additionoal "apt-get install" call by
ccache-action.
2024-05-06 12:46:44 +02:00
Colin Edwards
9dcd0604f2 android: Install the libmpd.so output on android
libmpd.so was getting written as a file called `arm64-v8a` instead of `arm64-v8a/libmpd.so`
2024-05-04 00:13:25 -05:00
kaliko
5a9b0c7142 doc: debian build, add pkconf build dep.
Build dep on pkconf is not explicitly needed because other dependencies
pull pkconf indirectly (ie libid3tag0-dev), but explicit declaration of
a direct MPD build dep is better IMHO.
2024-04-28 15:06:27 +02:00
Max Kellermann
823d6c9c0f Merge branch 'android_deps' of https://github.com/DDRBoxman/MPD 2024-04-24 14:52:31 +02:00
Colin Edwards
57e26eb832 android: Always force wrap deps
This ensures that android is always built with the deps we build
with wrap.

Also put back the asm disable for openssl since the version we use needs
that flag
2024-04-23 17:58:43 -05:00
jcorporation
f9c2c2b558 Remove deprecation flag for volume command 2024-04-23 20:37:55 +02:00
Colin Edwards
a0e9dfbec2 android: null check intent in onStartCommand
For some reason the type annotations here show @NonNull but that is
actually false according to the documentation under service.

This may be null if the service is being restarted after its process has gone away, and it had previously returned anything except START_STICKY_COMPATIBILITY.
2024-04-23 00:24:32 -05:00
Colin Edwards
cb6f61cf37 android: Update to NDK 27 2024-04-22 22:34:34 -05:00
kaliko
964e18ab49 doc: debian build, add libpipewire 2024-04-16 19:51:46 +02:00
kaliko
709acd8920 doc: debian build, add libsystemd 2024-04-16 19:18:57 +02:00
kaliko
6f0aecbfb3 doc: debian build, fixed libexpat-dev 2024-04-16 19:05:23 +02:00
Max Kellermann
7ebe56fdd9 util/SpanCast: allow ToStringView() only with integral char types
This avoids std::string_view specialization that make no sense.
2024-04-16 12:37:08 +02:00
Max Kellermann
fae235197f util/SpanCast: allow ReferenceAsBytes() only with trivially-copyable
Addd the std::has_unique_object_representations_v constraint so we
cast stuff to std::byte only if this would make sense.
2024-04-16 12:33:36 +02:00
Max Kellermann
141f518bdd .github/workflows/build.yml: add missing backslashes 2024-04-16 12:10:32 +02:00
Max Kellermann
d9fefbbc5a .github/workflows/build.yml: run Meson manually without BSFishy/meson-build
This eliminates the options duplication in the "build" and "tests" steps.
2024-04-16 12:07:50 +02:00
Max Kellermann
122d71a05d .github/workflows/build.yml: build only on Ubuntu 22.04 2024-04-16 12:03:24 +02:00
Max Kellermann
3b4825dd29 .github/workflows/build.yml: do not install outdated libfmt-dev 2024-04-16 11:51:19 +02:00
Max Kellermann
0c1ecc96a8 *: let libfmt quote strings 2024-04-16 11:50:18 +02:00
Max Kellermann
39c9e92f42 lib/fmt: require libfmt 9
Version 9 added the "debug format" which I'd like to use.
2024-04-16 11:50:18 +02:00
Max Kellermann
08810991c2 .github/workflows/build.yml: install ccache manually
This eliminates the additionoal "apt-get install" call by
ccache-action.
2024-04-16 11:39:40 +02:00
Max Kellermann
f8581c4d6a doc/user.rst: switch to Debian Bookworm 2024-04-16 11:33:00 +02:00
Max Kellermann
0d8498f1d1 lib/fmt/SocketAddressFormatter: simpler template syntax 2024-04-16 11:02:36 +02:00
Max Kellermann
7198db758d lib/fmt/PathFormatter: eliminate AllocatedPath specialization with std::convertible_to<Path> 2024-04-16 11:00:21 +02:00
Max Kellermann
7a4743d00e config/File: add missing include 2024-04-16 11:00:21 +02:00
Max Kellermann
ae85c2a979 db/Configured: log debug message when there is no cache directory
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1525
2024-04-16 10:57:28 +02:00
Max Kellermann
de4bdfcd1f python/build/libs.py: disable the FFmpeg "LEAD MCMP" decoder
This decoder causes linker failures and MPD has no use for it anyway.
2024-04-15 22:28:03 +02:00
Max Kellermann
9c7b930f8f Merge branch 'alsa-drain-recovery' of https://github.com/borine/MPD 2024-04-15 22:21:53 +02:00
Max Kellermann
9e8bca4879 python/build/libs.py: update FFmpeg to 7.0 2024-04-15 22:05:08 +02:00
Max Kellermann
5bd3934c00 python/build/libs.py: update WildMidi to 0.4.6 2024-04-15 22:05:08 +02:00
Max Kellermann
57212d5a35 player/Thread: remove unnecessary StartDecoder() call
Let Run() do this in the next loop iteration.
2024-04-15 21:49:11 +02:00
Max Kellermann
7236f83999 player/Thread: do not start the decoder twice
Upon receiving PlayerCommand::QUEUE, call StartDecoder() only if the
decoder is not already starting.  Checking just
DecoderControl::IsIdle() is not enough because the decoder may already
have finished decoding the song before the player has started playing
it and before it had a chance to call CheckDecoderStartup().

Omitting the StartDecoder() call now means it will be started later in
the Run() main loop, after CheckDecoderStartup() has succeeded (which
effectively switches to the song that has already been decoded by the
current decoder).

This fixes an assertion failure when compiled in debug mode
(`-Db_ndebug=false`) and random noise playback in non-debug mode
(`-Db_ndebug=true`).

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1900
2024-04-15 21:39:53 +02:00
Max Kellermann
c8ece786dd player/Thread: add assert() to StartDecoder()
StartDecoder() must not be called when a decoder is still being
started.  This detects the bug
https://github.com/MusicPlayerDaemon/MPD/issues/1900 earlier.
2024-04-15 21:36:11 +02:00
Max Kellermann
60fae87e59 doc/mpdconf.example: move "replaygain_limit" to user.rst 2024-04-15 18:58:53 +02:00
Max Kellermann
3145b10f51 doc/mpdconf.example: remove advanced replay gain settings
Keep the example file short, omit settings that are probably only used
by few users.
2024-04-15 18:55:03 +02:00
Max Kellermann
75047a26f8 doc/mpdconf.example: fix replaygain_limit description
The description (added by commit 43806d524da7) was wrong.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1977
2024-04-15 18:51:27 +02:00
Max Kellermann
1e4bf90c60 io, net, evnet: quote file names in error messages 2024-04-10 13:36:05 +02:00
Max Kellermann
b3a31b69ee util/RedBlackTree: fix lost "right" child while swapping with successor
Fixes a tree corruption bug that led to assertion failures.
2024-04-10 13:35:31 +02:00
Max Kellermann
88475f2e2b util/RedBlackTree: swap colors when swapping with successor
Swapping was incomplete without swapping the colors; this led to
assertion failures under certain conditions.
2024-04-10 13:35:28 +02:00
Max Kellermann
3cf0896998 test/util/TestIntrusiveTreeSet: add test with large randomized tree, erasing random elements
Test fails currently due to two bugs in the red-black tree
implementation.
2024-04-10 13:35:24 +02:00
Max Kellermann
e0a53d4747 util/IntrusiveTreeSet: add debug method Check()
Only for the unit test.
2024-04-10 13:35:21 +02:00
Max Kellermann
669cbcd25a util/IntrusiveList: allow the last disposer to destroy the IntrusiveList
Fixes a use-after-free bug in Co::MultiAwaitable::SetReady() when the
last callback frees the Co::MultiAwaitable owner.
2024-04-10 13:35:09 +02:00
Max Kellermann
2f7c19f139 util/SpanCast: rewrite ToStringView(std::span<std::byte>) to avoid cast ambiguities 2024-04-10 13:34:51 +02:00
Max Kellermann
e131f22642 util/SpanCast: merge two ToStringView() using std::remove_const_t 2024-04-10 13:34:25 +02:00
Max Kellermann
a09e33bf8e Merge branch 'RoboSchmied-AGfixT118' of https://github.com/RoboSchmied/MusicPlayerDaemon-MPD 2024-04-08 08:23:48 +02:00
Max Kellermann
cd3c34e7b9 Merge branch 'intents' of https://github.com/DDRBoxman/MPD 2024-04-08 08:23:25 +02:00
Max Kellermann
b3733ef32a Merge branch 'sticker_filters' of https://github.com/jcorporation/MPD 2024-04-08 08:20:28 +02:00
RoboSchmied
f3b9674fed Fix: 1 typo
Co-authored-by: RoAGmer <no-reply@github.com>
Signed-off-by: RoboSchmied <github@roboschmie.de>
2024-04-07 18:59:40 +02:00
Colin Edwards
b0cd456753 android: Button to jump to bottom of log view
This adds a button that can jump to the bottom of the log view.
If the user scrolls up we now disable the auto scroll down and show the
down button. When the down button is clicked the auto scroll resumes and
the button is removed.
2024-04-06 20:11:01 -05:00
jcorporation
c613d25f29 Add operators contains and starts_with to sticker find 2024-04-06 20:08:59 +02:00
Colin Edwards
fff9ceccc2 android: Add intents for service start and stop
org.musicpd.action.StartService
org.musicpd.action.StopService

You can test these actions like:
adb shell am broadcast -a org.musicpd.action.StartService org.musicpd

Calling these from an app like tasker should allow for automation
2024-04-05 23:46:14 -05:00
Colin Edwards
4bcbeae1e0 android: Move service client into it's own file
The service file was getting harder to read so lets pull the client code
into it's own file
2024-04-05 23:27:41 -05:00
Max Kellermann
4c56e87e36 lib/curl/Global: remove empty line 2024-04-04 09:18:34 +02:00
Max Kellermann
011b96ff98 net/UniqueSocketDescriptor: add method MoveToFileDescriptor() 2024-04-04 09:16:44 +02:00
Max Kellermann
d563f5fc87 decoder/mpg123: use mpg123_ssize_t only on MPG123_API_VERSION >= 47 2024-04-03 23:21:54 +02:00
Max Kellermann
9c2df5ce19 decoder/mpg123: implement stream_decode 2024-04-03 23:12:26 +02:00
Max Kellermann
1745c485f3 decoder/mpg123: move code to Scan() 2024-04-03 22:52:56 +02:00
Max Kellermann
a53db82ae4 decoder/mpg123: move code to Decode() 2024-04-03 22:49:43 +02:00
Max Kellermann
a20a83eb76 decoder/mpg123: move code to GetAudioFormat() 2024-04-03 22:37:29 +02:00
Max Kellermann
65e5a43e46 decoder/List: prefer "mpg123" over "mad"
libmad hasn't been maintained for many many years, while libmpg123 is
still maintained.

Our "mad" plugin can't do streams, but MPD will automatically fall
back to "mad" (or "ffmpeg") for streams.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1954
2024-04-03 22:25:34 +02:00
Max Kellermann
b6afdf1201 util/UriUtil: disable path segment stripping
This bug introduced by commit 49ed9dae34f29f499d193490af2c8a869d170e8e
and activated by commit acc1bd6297ed4550f2e567aa2d2d27ffc6784629
caused leading spaces to disappear from the beginning of all file
names.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1961
2024-04-03 22:00:36 +02:00
Max Kellermann
08a00ee21b config/PartitionConfig: clip the max_playlist_length setting
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1932
2024-04-03 21:43:39 +02:00
Max Kellermann
41a1e98cb9 subprojects: update sqlite3 to 3.45.2-1 2024-04-03 21:34:40 +02:00
Max Kellermann
99da022775 util/IntrusiveSortedList: remove unused class 2024-04-03 21:31:08 +02:00
Max Kellermann
1ee25b4234 event/TimerList: remove option NO_BOOST
Always use the new IntrusiveTreeSet class.
2024-04-03 21:30:59 +02:00
Max Kellermann
c5e607a310 event/TimerList: use IntrusiveTreeSet instead of boost::intrusive::multiset 2024-04-03 21:30:31 +02:00
Max Kellermann
5a0bad3b2f util/IntrusiveTreeSet: new class 2024-04-03 21:29:34 +02:00
Max Kellermann
6a99f20828 util/IntrusiveHashSet: add concept checks to *Operators
This requires adding another template argument and reordering the others.
2024-04-03 21:27:37 +02:00
Max Kellermann
91ca502e10 output/httpd/Client: pass std::string_view to HandleLine() 2024-04-03 21:06:11 +02:00
Max Kellermann
1e5c37ee78 util/SpanCast: add ToStringView() with non-const std::byte
Without this, we would get std::string_view<std::byte> which makes no
sense.
2024-04-03 20:58:03 +02:00
Max Kellermann
ef2cdc0c6a output/httpd/Client: remove duplicate API docs 2024-04-03 20:50:31 +02:00
Max Kellermann
c94c08c6b4 event/BufferedSocket: pass std::span to OnSocketInput() 2024-04-03 20:43:40 +02:00
Max Kellermann
5de8edced6 output/httpd/HttpdClient: convert metaint to a compile-time constant
After all these years, we had this as a field but there was never a
way to change the value.  So let's just hard-code it until we actually
have a reason to make it variable at runtime.
2024-04-03 20:30:53 +02:00
Max Kellermann
8906ce07de output/httpd/IcyMetaDataServer: pass metaint as std::size_t 2024-04-03 20:29:47 +02:00
Max Kellermann
9d66fc491c output/httpd/Client: fix API doc syntax 2024-04-03 20:21:18 +02:00
Max Kellermann
f8a838db5d output/httpd/Client: convert variable to std::string_view
In all cases, we already know the length, and casting the C string to
std::string_view has to call strlen() again.
2024-04-03 20:20:33 +02:00
Max Kellermann
e4ba736d03 input/{async,rewind}, decoder/dsdiff: use std::cmp_*() for safer integer comparisons 2024-03-15 18:45:46 +01:00
Max Kellermann
cc291e8c98 Merge branch 'extend-robustness-of-cdda-playback' of https://github.com/lazypingu/MPD 2024-03-15 18:39:45 +01:00
lazypingu
c00d217a53 Skip track if returned LSNs are negative which indicates track errors or if track is not an audio track 2024-03-12 20:39:51 +01:00
lazypingu
9d853897cd Use track and disc functions from libcdio-paranoia to enable playback of hidden tracks and audio tracks on multisession CDs 2024-03-12 20:37:50 +01:00
lazypingu
88c77f9c8a Add debug logging if setting speed failed 2024-03-12 20:37:50 +01:00
lazypingu
1a7278f1d3 Move cddap_speed_set below cddap_open to make sure that the drive was initialized and opened before attemting to set the speed 2024-03-12 20:36:28 +01:00
Max Kellermann
9916d455f9 python/build/libs: fix libnfs 5.0.3 path 2024-03-11 15:55:25 +01:00
Max Kellermann
541707f9a8 lib/curl/Easy: add SetRequestBody() overload with std::span 2024-03-11 15:32:24 +01:00
Max Kellermann
00cf036d58 lib/avahi/Client: relax assertion after COLLISION/REGISTERING
Turns out that `AVAHI_CLIENT_S_COLLISION` can occur after
`AVAHI_CLIENT_S_RUNNING`, and `connected==true`.  Relaxing this fixes
a bogus assertion failure.
2024-03-11 15:32:24 +01:00
Max Kellermann
9c68f24cfc net/SocketError: fix typo
Whoops.  This function has never been used.
2024-03-11 15:32:24 +01:00
Max Kellermann
02c4512b00 util/CharUtil: add IsLowerHexDigit() 2024-03-11 15:32:24 +01:00
Max Kellermann
be84b189dc util, io, net, ...: use "#pragma once" 2024-03-11 15:32:24 +01:00
Max Kellermann
313f2a1894 python/build/libs: update libnfs to 5.0.3 2024-03-11 15:32:24 +01:00
Max Kellermann
a1ae1a1e95 python/build/libs: update FFmpeg to 6.1.1 2024-03-11 15:32:24 +01:00
Max Kellermann
4874bcf8e8 python/build/libs: update libopenmpt to 0.7.4 2024-03-11 15:32:24 +01:00
Max Kellermann
280ff9211f python/build/libs: update zlib to 1.3.1 2024-03-11 15:32:24 +01:00
Max Kellermann
494f658dee meson.build: suppress -Wnan-infinity-disabled (clang 18) due to libfmt 2024-03-11 15:32:24 +01:00
Max Kellermann
c144d0a00d meson.build: build fmt in C++20 mode
Enables `char8_t` support which eliminates clang 18's
`-Wdeprecated-declarations` warning about fmt's use of
`std::string_view<unsigned char>`.
2024-03-11 15:32:24 +01:00
Max Kellermann
696a36bd5a subprojects: update sqlite3 to 3.45.1-1 2024-03-11 15:32:24 +01:00
Max Kellermann
3a3fc5e13a subprojects: update openssl to 3.0.8-3 2024-03-11 15:32:24 +01:00
Max Kellermann
0b89cc306e subprojects: update fmt to 10.2.0-2 2024-03-11 15:32:24 +01:00
Max Kellermann
dbc68047ad subprojects: update flac to 1.4.3-2 2024-03-11 15:32:24 +01:00
Max Kellermann
2fdfe3a854 subprojects: update curl to 8.6.0 2024-03-11 15:10:41 +01:00
Max Kellermann
d685d693e8 input/rewind, archive/iso9660: use use std::cmp_*() for safe integer comparison 2024-03-11 15:09:57 +01:00
Max Kellermann
b0cfdfa257 client/Idle: consume only idle flags that were subscribed to
Since the very beginning when idle subscriptions where introduced
(commit 0bad84066bc12), waiting for a certain idle mask would clear
all other idle flags as well.  This would cause idle events to get
lost.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1998
2024-03-11 15:07:07 +01:00
Marius Feraru
7b6909f2c0 db/update/Walk:FindAncestorLoop: uint64_t inode & device
Previously, inode numbers were truncated to 32 bits, which could lead
to problems on XFS where inodes are 64 bit; this could lead to bogus
"recursive directory found" errors during database update.

[mk: added commit description and NEWS line]

Closes https://github.com/MusicPlayerDaemon/MPD/issues/2000
2024-03-11 13:34:27 +01:00
jcorporation
45553c5f61 This commit adds the sort and window parameter to "sticker find"
The three new compare operators "eq", "gt" and "lt" are casting the values to int.

Sort supports:
- uri: sort by uri
- value: sort by value as string
- value_int: casts value to int

Closes 
2024-03-07 20:52:11 +01:00
naglis
1efb9d41db doc/protocol.rst: clarify message event
The term "queue" is used in MPD to refer to the current playlist;
clarify that in this case it refers to the client's message queue.
2024-02-25 19:59:26 +01:00
naglis
9292b39cf5 doc/protocol.rst: document max number of subscriptions 2024-02-18 12:42:53 +02:00
Max Kellermann
9eb26ab90c Merge branch 'countplaylist' of https://github.com/jcorporation/MPD 2024-02-15 11:28:11 +01:00
jcorporation
f801f299c9 New command playlistlength
Count the number of songs and their total playtime in the playlist.
2024-02-15 11:25:34 +01:00
Max Kellermann
7f18cae2e4 Merge branch 'skidoo23-patch-1' of https://github.com/skidoo23/MPD 2024-02-13 08:06:16 +01:00
jcorporation
a3794f8c3b Allow range in listplaylist and listplaylistinfo 2024-02-08 21:26:28 +01:00
skidoo23
31a88e7ccc
Update Templates.cxx
Remove Spotify leftovers
2024-01-26 14:34:58 +01:00
skidoo23
4074e3a9e4
Update Option.hxx 2024-01-26 14:31:08 +01:00
Max Kellermann
c71e586c53 .readthedocs.yaml: install sphinx-rtd-theme 2024-01-19 10:31:50 +01:00
Max Kellermann
1039fb5582 .readthedocs.yaml: add 2024-01-19 10:22:36 +01:00
Max Kellermann
7f60acdfdd util/CharUtil: add IsUpperAlphaNumericASCII() 2024-01-18 18:53:05 +01:00
Max Kellermann
aef2c5dc14 lib/avahi/Service: add field visible
Now individual services can be hidden or shown at any time.
2024-01-18 18:50:06 +01:00
Max Kellermann
8d02986b0e lib/avahi/Publisher: add missing defer_register_services.Cancel() calls 2024-01-18 18:50:01 +01:00
Max Kellermann
461da92064 lib/avahi/Publisher: make the service list dynamic
This allows editing the list of services at any time instead of
passing a constant list at construction time.  To do this, Service
instances are now caller-owned and managed in an IntrusiveList instead
of Publisher-owned in a std::forward_list.
2024-01-18 18:48:27 +01:00
Max Kellermann
b20b773189 zeroconf/avahi/Helper: embed the Avahi::Publisher without std::unique_ptr 2024-01-18 18:45:51 +01:00
Max Kellermann
74125c0922 test/meson.build: suppress compiler warnings in GTest headers 2024-01-18 18:42:56 +01:00
Max Kellermann
5023432802 lib/avahi/Publisher: use DeferEvent for RegisterServices()
Prepares making the service list dyammic; the DeferEvent not only
moves the operation out of the current stack frame, but also allows
combining several AddService() calls.
2024-01-18 18:24:08 +01:00
Max Kellermann
4a14248004 lib/avahi/Publisher: move code to RegisterServices(AvahiEntryGroup) 2024-01-18 18:24:04 +01:00
Max Kellermann
1b241fc97a lib/avahi/Publisher: allow RegisterServices() to throw 2024-01-18 18:24:01 +01:00
Max Kellermann
09d1ab7abe lib/avahi/Publisher: move try/catch in GroupCallback() to the top level 2024-01-18 18:23:57 +01:00
Max Kellermann
d28cb93835 lib/avahi/Client: add method IsConnected()
Publish only if the client is really connected.
2024-01-18 18:23:52 +01:00
Max Kellermann
6b43338e06 lib/avahi/Client: add assert() 2024-01-18 18:23:48 +01:00
Max Kellermann
9a7a49350c lib/avahi/Client: free the AvahiClient on AVAHI_CLIENT_FAILURE
Previously the AvahiClient was only freed when AVAHI_ERR_DISCONNECTED
was detected, but all other error conditions would lead to a memory
leak.
2024-01-18 18:23:45 +01:00
Max Kellermann
f85629afa6 lib/avahi/Client: is if with initializer 2024-01-18 18:23:42 +01:00
Max Kellermann
a39473a912 lib/avahi/Service: add API docs 2024-01-18 18:23:37 +01:00
Max Kellermann
05d0e9b8bb lib/avahi/Publisher: reuse the AvahiEntryGroup
The libavahi-client documentation recommends reusing AvahiEntryGroup
instances instead of freeing them and creating new ones.
2024-01-18 18:23:30 +01:00
Max Kellermann
b68c3b7f55 net/SocketDescriptor: disable msghdr methods on Windows 2024-01-18 15:44:44 +01:00
Max Kellermann
0fbed6dec1 net/SocketDescriptor: remove misplaced [[nodiscard]] 2024-01-18 15:44:43 +01:00
naglis
16af2a2998 CommandLine: fix typo
I believe this is a typo since all other sections have the form
"<Singular> plugins", e.g. "Encoder plugins".
2024-01-18 14:23:41 +02:00
Max Kellermann
7a40ac52a8 Merge branch 'bottombar' of https://github.com/DDRBoxman/MPD 2024-01-18 09:59:48 +01:00
Max Kellermann
6352d1b1ca Merge branch 'sdkcheck' of https://github.com/DDRBoxman/MPD 2024-01-18 09:59:17 +01:00
Max Kellermann
c93fc161dc Merge branch 'next_prev_fix' of https://github.com/DDRBoxman/MPD 2024-01-18 09:58:39 +01:00
Colin Edwards
5b7de2bc2f android: Refactor settings UI into screens and add a bottom bar.
This puts Status, logs, and settings all on different tabs. This gives us plenty more room to work to improve these views going forward
2024-01-18 01:23:31 -06:00
Colin Edwards
04ba7eb987 android: Use build tools and SDK 34
The gradle config for the app is already compiling with the 34 SDK
so lets bump it for the bridge build too
2024-01-17 23:55:01 -06:00
Colin Edwards
5a2267bdb4 Android: Look for license to verify Android SDK folder
The `android` command was depricated and has been removed from new installs of the sdk

The license file existing is about all that is stable between different sdk versions and
cli vs Android studio installs
2024-01-17 23:46:17 -06:00
Colin Edwards
0075c57bd4 android: Check playlist state before changing track
Playlist will throw an exception if we call next or previous track when it is not in the "playing" state
2024-01-13 23:23:29 -06:00
Colin Edwards
87873c9a73 android: Support play / pause from media session 2024-01-13 23:15:56 -06:00
Max Kellermann
380e0abbe4 python/build/libs.py: fix libopenmpt source path
Fixes regression by commit ea23ea28ce7f57a021d0fab017f5e62dc3104c36
2024-01-13 22:51:07 +01:00
Max Kellermann
e4cc89b2d9 Merge branch 'jg' of https://github.com/neheb/MPD 2024-01-13 22:38:34 +01:00
Max Kellermann
14dea04ee9 test/util: use unsigned integer literals for -Wsign-compare 2024-01-13 22:33:23 +01:00
Max Kellermann
6f6cbeba80 net/SocketDescriptor: add Send()/Receive() overloads with iovec 2024-01-13 22:32:35 +01:00
Max Kellermann
974ed0166c net/SocketDescriptor: add sendmsg(), recvmsg() wrappers 2024-01-13 22:31:58 +01:00
Max Kellermann
a91920a8ff net/SocketDescriptor: pass span<byte> to Read()/Write() 2024-01-13 22:31:34 +01:00
Max Kellermann
7cd38dde09 net/SocketDescriptor: add [[nodiscard]] 2024-01-13 22:31:24 +01:00
Max Kellermann
b63a794fbe io/FileDescriptor: add [[nodiscard]] 2024-01-13 22:31:16 +01:00
Max Kellermann
3e862b85d4 Merge branch 'mediasession' of https://github.com/DDRBoxman/MPD 2024-01-13 22:27:00 +01:00
Max Kellermann
85bca660d1 Merge branch 'update-failure-response-example' of https://github.com/naglis/MPD 2024-01-13 22:25:00 +01:00
Max Kellermann
87704f49c9 Merge branch 'NEWS-update' of https://github.com/mxjeff/MPD 2024-01-13 22:24:31 +01:00
Max Kellermann
9f9cbb8823 Merge branch 'logging' of https://github.com/DDRBoxman/MPD 2024-01-13 22:24:22 +01:00
kaliko
fa6ef6f1c7 Add NEWS entry about the switch to sphinx_rtd_theme
Change introduced in 6913148d99
2024-01-13 11:32:55 +01:00
naglis
db354f5e53 doc/protocol.rst: update failure response example
The commands in the example currently result in `ACK_ERROR_ARG`.
2024-01-10 21:03:26 +02:00
Max Kellermann
d3335f9947 db/simple: make more fields const 2024-01-08 13:55:15 +01:00
Max Kellermann
1a67062e1e db/simple: reorder fields to reduce padding 2024-01-08 13:54:15 +01:00
Max Kellermann
fec1a4ac32 db/simple: pass hide_playlist_targets to sub-instance 2024-01-08 13:53:59 +01:00
Max Kellermann
7f439b01a3 net/SocketAddress: move code to IsInet() 2024-01-08 13:48:13 +01:00
Max Kellermann
0fd6f83766 net/StaticSocketAddress: add constexpr 2024-01-08 13:48:05 +01:00
Max Kellermann
b15b2125e2 net/AddressInfo: add methods IsInet(), IsTCP() 2024-01-08 13:47:59 +01:00
Colin Edwards
3711bd0d24 android: Implement basic media session handling for next and previous track
This starts a Media3 MediaSession when the service starts. A custom player class gets passed into that session to receive commands from other apps and the android os.

Currently we pad out some dummy items to make SimpleBasePlayer think we can do next and previous tracks.

MPD handles the threading for the native calls so we can just directly call the bridge from the player class.
2024-01-05 18:23:16 -06:00
Colin Edwards
e086f09d48 android: add next and previous track to the jni bridge
This will allow the android client to directly make calls to the mpd process to change tracks

I went with camel case on the function names here, if you use an underscore
javac generates a function tht looks like this:
 JNIEXPORT void JNICALL Java_org_musicpd_Bridge_play_1previous

I figured what we ended up with looks a little nicer:
JNIEXPORT void JNICALL Java_org_musicpd_Bridge_playPrevious
2024-01-05 18:21:46 -06:00
Colin Edwards
324bd95c91 android: Move logging into it's own repository class.
Logs will be maintained and appended even when the main UI is not bound to the service.

This also lets us log without filling a Handler with a bunch of messages we might just throw away anyway.
2024-01-04 17:44:49 -06:00
Colin Edwards
5d122c3bc8 android: Add dependencies and new application class for dagger / hilt support
Dagger and hilt give us dependency injection which makes it easier to split up parts of the app. This lets us easily split out things like logging and paves the way to migrate off preferences to DataStore

This also remove the process name on the service to pull eveything into one process so we don't have to do IPC to pass logs around. This lets us use the same instances of injected classes between the UI and the service side.
2024-01-04 17:44:43 -06:00
Rosen Penev
8e123e7fc9 test: archive: fix compilation with Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
e8163124e3 mpg123: fix compilation under Windows
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
0651be8366 fluidsynth: fix compilation on Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
4957035be6 mikmod: fix compilation on Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
bcd55c0b75 sidplay: fix compilation under Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
914ee92015 wavpack: fix compilation on Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:25 -08:00
Rosen Penev
fb9194b537 tests: fix ChromaPrint test on Windows
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 14:22:24 -08:00
Max Kellermann
c04490bd52 storage/curl: eliminate std::strings, parse string_view directly 2024-01-04 21:11:07 +01:00
Max Kellermann
b601f4dc15 util/CNumberParser: remove unused function ParseInt64() 2024-01-04 21:07:50 +01:00
Max Kellermann
4086190c80 decoder/OpusTags: use ParseInteger() 2024-01-04 21:06:38 +01:00
Max Kellermann
e1eea9d98a util/NumberParser: new library based on std::from_chars() 2024-01-04 21:03:37 +01:00
Max Kellermann
393d57b387 util/NumberParser: rename to CNumberParser
A new NumberParser library based on std::from_chars() will be added.
2024-01-04 21:02:45 +01:00
Max Kellermann
b283fe07af lib/expat/ExpatParser: pass std::string_view to CharacterData() 2024-01-04 20:55:14 +01:00
Max Kellermann
feeb21577f lib/upnp/Device: use std::forward_list instead of std::vector 2024-01-04 20:51:20 +01:00
Max Kellermann
1fca16737d lib/upnp/Device: remove unnecessary ctors/dtors 2024-01-04 20:49:27 +01:00
Max Kellermann
4ec85a12e3 lib/upnp/Discovery: use std::map instead of std::list 2024-01-04 20:45:24 +01:00
Max Kellermann
3d2aebccad lib/upnp/Discovery: pass std::string_view to LockRemove() 2024-01-04 20:40:47 +01:00
Max Kellermann
22382f799c lib/upnp/Discovery: add noexcept 2024-01-04 20:39:21 +01:00
Max Kellermann
468eceabff lib/upnp/Discovery: remove unreachable exception handler 2024-01-04 18:04:46 +01:00
Max Kellermann
08e0eb79f5 lib/upnp/Discovery: remove unused default ctor 2024-01-04 18:04:21 +01:00
Max Kellermann
8b03ce562c input/curl: increase CURLOPT_BUFFERSIZE from 16 kB to 512 kB 2024-01-04 17:57:42 +01:00
Max Kellermann
997311ba14 lib/curl/Easy: add method TrySetOption() 2024-01-04 17:51:48 +01:00
Max Kellermann
cbd031ca7f lib/upnp/Action: common UpnpSendAction() wrapper for pupnp and npupnp
Merge a lot of duplicate code.
2024-01-04 17:40:59 +01:00
Max Kellermann
95842e7984 db/upnp: eliminate the std::forward_list, use IterableSplitString() 2024-01-04 16:31:28 +01:00
Max Kellermann
cc41e95806 db/upnp: add rootid_sv 2024-01-04 16:20:44 +01:00
Max Kellermann
2c77e088b4 db/upnp: eliminate temporary std::string from Visit() 2024-01-04 16:19:03 +01:00
Max Kellermann
4eefc2e47c test/DumpDatabase: add "URI" parameter 2024-01-04 15:37:10 +01:00
Max Kellermann
7c13666226 test/DumpDatabase: remove the "PLUGIN" parameter, load from config file 2024-01-04 15:36:18 +01:00
Max Kellermann
4ed8313954 test/DumpDatabase: use libfmt 2024-01-04 15:32:26 +01:00
Max Kellermann
c8e2ab6781 db/upnp/Object: smaller enums 2024-01-04 14:31:41 +01:00
Max Kellermann
b2ed29b8c0 lib/upnp/ContentDirectoryService: getFriendlyName() returns std::string reference
This can avoid the overhead of casting a C string back to std::string_view.
2024-01-04 14:28:12 +01:00
Max Kellermann
1789b56a85 db/upnp: pass std::string_view to songPath() 2024-01-04 14:28:12 +01:00
Max Kellermann
714dbc9294 lib/upnp/Discovery: forward-declare inner class ContentDirectoryDescriptor 2024-01-04 14:28:12 +01:00
Max Kellermann
f40eb963fd lib/upnp/Discovery: forward-declare inner class Downloader 2024-01-04 14:28:12 +01:00
Max Kellermann
ee4b49d12f lib/expat/ExpatParser: pass std::string_view to Parse() 2024-01-04 14:28:12 +01:00
Max Kellermann
4c9942534c lib/upnp/Device: pass url as std::string_view to Parse() 2024-01-04 14:28:12 +01:00
Max Kellermann
d5f7db59a8 lib/upnp/Util: pass std::string_view to path_getfather() 2024-01-04 14:28:12 +01:00
Max Kellermann
8d1b73ae89 lib/upnp/Discovery: use string_view::starts_with() instead of strncmp() 2024-01-04 14:28:08 +01:00
Rosen Penev
afa77099cf msys2 CI
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 12:49:43 +01:00
Rosen Penev
f68fab53a7 zzip: fix compilation on Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 12:38:36 +01:00
Rosen Penev
6a4dc281d1 bzip2: fix compilation on Windows
NarrowPath is needed.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-04 12:38:30 +01:00
Max Kellermann
26831a417a subproject: update expat to 2.5.0-4 2024-01-04 09:49:10 +01:00
Max Kellermann
6293818c35 subproject: update fmt to 10.2.0-1 2024-01-04 09:49:09 +01:00
Rosen Penev
a859de6806 sndfile: fix compilation with clang's libc++
error: non-constant-expression cannot be narrowed from type 'sf_count_t'
(aka 'long long') to 'size_type' (aka 'unsigned int') in initializer list
 [-Wc++11-narrowing]
  215 |                      std::span{buffer, num_frames * frame_size},
      |                                        ^~~~~~~~~~~~~~~~~~~~~~~
note: insert an explicit cast to silence this issue
  215 |                      std::span{buffer, num_frames * frame_size},
      |                                        ^~~~~~~~~~~~~~~~~~~~~~~
      |                                        static_cast<size_type>()

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-03 12:18:52 -08:00
Rosen Penev
13202bfce4 test: neighbor_explorer: fix compilation on WIN32
Need NarrowPath. Matches what is done in other tests.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-31 15:38:49 -08:00
Rosen Penev
f3d031b38a libnpupnp: update subproject
Fixes compilation under Windows.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-31 13:58:10 -08:00
Rosen Penev
f6dbf38e99 upnp: change interface variable name
rpc.h under Windows defines interface as struct, which blows up the
build here. Rename to avoid.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-28 19:39:05 -08:00
Max Kellermann
d0a4270449 lib/upnp/Compat: remove obsolete kludges
Those bugs have been fixed looong ago.
2023-12-28 21:24:58 +01:00
Max Kellermann
b9a7a9981e lib/upnp/ContentDirectoryService: remove unused fields 2023-12-28 21:22:41 +01:00
Max Kellermann
d9fb152b95 lib/upnp/ContentDirectoryService: include some headers only with libpupnp 2023-12-28 21:18:41 +01:00
Max Kellermann
09a0f7a45c Merge branch 'android_fix' of https://github.com/DDRBoxman/MPD 2023-12-28 21:02:49 +01:00
Max Kellermann
9396ffb509 db/plugins/upnp/ContentDirectoryService: add missing closing curly brace 2023-12-28 20:52:53 +01:00
Max Kellermann
66a8afd18c subprojects: add libnpupnp 2023-12-28 20:51:13 +01:00
Rosen Penev
e7e07c39c5 meson: fix flac_dep under Windows
declare_dependency's found() method evaluates to true always, resulting
in MPD trying to build flac when not found. Check for dependency()'s
find() first.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-27 12:43:08 -08:00
Colin Edwards
201e081750 android: Fix boot receiver settings and intent check 2023-12-27 13:38:38 -06:00
Colin Edwards
5f7f1d738d android: set kotlin target to 9
The naming scheme was changed in kotlin but not java after java 8
2023-12-27 13:34:37 -06:00
Colin Edwards
8a3d144714 android: Set kotlin jvm target to 1.9 2023-12-27 13:27:02 -06:00
Rosen Penev
44080154b0 no setenv on Windows
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-27 10:50:00 -08:00
Max Kellermann
c17493f2d3 Merge branch 'fs' of https://github.com/neheb/MPD 2023-12-27 12:38:30 +01:00
Max Kellermann
dcfc1ca6a0 Merge branch 'doc-time-case' of https://github.com/naglis/MPD 2023-12-27 12:37:58 +01:00
Max Kellermann
07e1bae0af Merge branch 'doc-config-comments' of https://github.com/naglis/MPD 2023-12-27 12:35:32 +01:00
Max Kellermann
658a7f1ca7 Merge branch 'material' of https://github.com/DDRBoxman/MPD 2023-12-27 12:35:13 +01:00
Max Kellermann
bd408cd627 Merge branch 'bootfix' of https://github.com/DDRBoxman/MPD 2023-12-27 12:33:14 +01:00
Rosen Penev
7c520f6475 fs: fix typo
Wrong macro used.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2023-12-26 10:57:44 -08:00
naglis
07ee11b963 doc/protocol.rst: fix time tag case
The `Time` song tag starts with an uppercase letter.
2023-12-26 10:51:34 +02:00
Colin Edwards
a4c7041561 subprojects: properly export id3tag include headers
According to the Makefile.am from libid3 only i3dtag.h should be installed to the include directory.
include_HEADERS =	id3tag.h
2023-12-24 11:31:29 -06:00
naglis
d7eb223343 doc: mention config file comment syntax 2023-12-23 09:33:01 +02:00
Colin Edwards
ddc048e2c3 android: Move settings to compose and material UI 3
This changes lets us use the latest UI design from Google, Material 3.

Google only provides the material UI 3 themes for compose, compose only works with kotlin.
2023-12-22 23:04:51 -06:00
Colin Edwards
625ab6decd android: Move preferences class out of settings 2023-12-22 22:51:14 -06:00
Colin Edwards
2638396df5 android: add dependencies for Material 3 and Compose 2023-12-22 13:30:43 -06:00
Colin Edwards
3d8e285e2b android: Fix launching on device boot 2023-12-22 12:30:45 -06:00
Colin Edwards
793a12d58d android: Use Java 9 2023-12-22 12:30:27 -06:00
Max Kellermann
23b4688c44 util/ByteOrder: move Packed* classes to separate headers 2023-12-22 18:20:46 +01:00
Max Kellermann
c4d8888972 subprojects: add id3tag 2023-12-22 18:15:25 +01:00
Max Kellermann
6e50031c49 python/build/libs.py: remove libmad (unused) 2023-12-22 18:05:40 +01:00
Max Kellermann
833ca1e350 test/dump_rva2: fix TCHAR/char confusion on Windows 2023-12-22 18:05:40 +01:00
Max Kellermann
a888b3a707 decoder/plugins/meson.build: add missing dependency to libid3tag 2023-12-22 18:03:47 +01:00
Max Kellermann
d9bbe39f48 android/include/meson.build: remove custom "-I" flag
This is not necessary because the declared dependency is enough for
Meson to generate the "-I" flag automatically.
2023-12-22 17:07:50 +01:00
Max Kellermann
38226dfe81 android/include/meson.build: generate *.class in @PRIVATE_DIR@
We're not interested in the *.class files, we run javac only to
generate the JNI header.  By using @PRIVATE_DIR@, it gets stored to a
directory we can ignore, and not into the source tree.
2023-12-22 16:46:25 +01:00
Max Kellermann
94ef1e13e0 android/include/meson.build: call javac directly, eliminate run-javac.sh 2023-12-22 16:41:35 +01:00
Max Kellermann
35c7c005ba android/meson.build: move target org_musicpd_Bridge.h to include/meson.build 2023-12-22 16:39:13 +01:00
Max Kellermann
1e732f9b9b android/run-javac.sh: remove unnecessary realpath call 2023-12-22 16:35:06 +01:00
Max Kellermann
ee5c471280 android/meson.build: pass @OUTDIR@ to run-javac.sh 2023-12-22 16:32:10 +01:00
Max Kellermann
8ef47147a0 .github/workflows/build_android.yml: do not ignore "python"
Python scripts are used to build Android.
2023-12-22 15:17:47 +01:00
Max Kellermann
fb4dd4e1ce .github/workflows/build_android.yml: remove branch v0.23.x
This branch cannot be built this way.
2023-12-22 15:17:45 +01:00
Max Kellermann
a19f3a4f9f python/build/meson.py: put ccache prefix in array instead of stripping it
Turns out Meson disables ccache auto-detection when a cross-file is
used.  To use ccache, the ccache prefix must be expressed in an array
instead of a single string with spaces.
2023-12-22 15:11:53 +01:00
Max Kellermann
c3ba52a1fc python/build/toolchain.py: auto-detect ccache 2023-12-22 15:05:41 +01:00
Max Kellermann
1b2bd0cc0a .github/workflows/build_android.yml: use preinstalled Android SDK/NDK 2023-12-22 14:39:20 +01:00
Max Kellermann
dd3779d64b .github/workflows/build_android.yml: use preinstalled Java 2023-12-22 14:39:20 +01:00
Max Kellermann
806d1483a8 .github/workflows/build_android.yml: install Meson 1.3.0
We need at least 0.63.0 for "diff_files" support in subprojects;
without this, the Opus build breaks.
2023-12-22 14:39:20 +01:00
borine
b1f28d6003 output/alsa: Fix (theoretical error in) ALSA device recovery
It is not possible to prepare an ALSA device when it is is state
SND_PCM_STATE_OPEN; it is necessary to set the hardware parameters
first.

This pedantic commit corrects that error. Note that in practice
this code path cannot be encountered because MPD always sets the
hardware parameters before attempting to start playback.
2023-12-22 12:02:33 +00:00
borine
50e6950fa8 output/alsa: handle recoverable errors in DrainInternal()
It is possible that an underrun may occur in the ALSA output
device while MPD is draining its own internal buffer. If this
happens then MPD stops playback, reporting the error EPIPE.

This commit attempts to recover the ALSA device instead of
stopping playback, so that the drain can complete and the next
song in the play queue is played.
2023-12-22 11:53:20 +00:00
Max Kellermann
1d60d3cd2b subprojects: update libmpdclient to 2.22
2.22 fixes the "version.h" conflict.

Closes https://github.com/MusicPlayerDaemon/MPD/pull/1927
2023-12-22 12:08:02 +01:00
Max Kellermann
59ed18e112 Merge branch 'android_network_address' of https://github.com/DDRBoxman/MPD 2023-12-22 10:26:36 +01:00
Colin Edwards
c4c1044427 android: Add a text field to display the devices network address 2023-12-21 11:50:10 -06:00
Max Kellermann
791b3c65f3 python/build/meson: bringt back configure()
This reverts part of commit a3765cd363426a4e6b7d2554f69562baff736f31.
The MesonProject class was not used, but the "configure" function.
2023-12-21 12:02:05 +01:00
Max Kellermann
a3765cd363 python/build: remove Meson project support
Obsolete, we're now using Meson subprojects.
2023-12-21 11:50:33 +01:00
Max Kellermann
3c5b864396 tag/IcyMetadataParser: use std::span 2023-12-21 08:42:23 +01:00
Colin Edwards
b09654b53a
build: Remove absolute path on pkg-config
This allows it to be found on macOS and should fix linking libnfs with builds of the Android app
2023-12-20 23:23:18 -06:00
Max Kellermann
58fc857a2d tag/IcyMetadataParser: pass std::string_view to icy_parse_tag() 2023-12-20 20:18:39 +01:00
Max Kellermann
e443ee357a tag/IcyMetadataParser: do not null-terminate strings in icy_parse_tag()
Just pass std::string_views into the unmodified buffer to
icy_parse_tag_item().
2023-12-20 19:58:35 +01:00
Max Kellermann
2618294eb7 tag/IcyMetadataParser: pass std::string_view to icy_parse_tag_item() 2023-12-20 19:51:22 +01:00
Max Kellermann
03352cb4ad tag/IcyMetadataParser: use std::byte in ParseInPlace() 2023-12-20 19:49:08 +01:00
Max Kellermann
2c851498cc meson.build: do not leak CPP macros to subprojects 2023-12-20 17:49:13 +01:00
Max Kellermann
a52292ae17 subprojects: update sqlite to 3.44.2-1 2023-12-20 17:34:05 +01:00
Max Kellermann
f6a886f092 subprojects: update curl to 8.5.0-2 2023-12-20 17:33:28 +01:00
Max Kellermann
6234ae5a8b doc/user.rst: do not name the deprecated /var/run/ directory 2023-12-20 17:32:13 +01:00
Max Kellermann
a4ead670ed subprojects: add libmpdclient wrap 2023-12-20 17:15:29 +01:00
Max Kellermann
303d981099 subprojects: add lame 2023-12-20 16:50:13 +01:00
Max Kellermann
7727311df7 meson.build: disable "openssl:asm"
Work around "call to undeclared function "asm" on Android.
2023-12-20 16:30:16 +01:00
Max Kellermann
5f54a8e94e release v0.23.15
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmWDBpUNHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEm/yD/oCg59J/hUm+pyVtS9X74UAaoVH+icwZetvj5Ui
 DMFCZ7N3sCeXq+at7ZBsSCFXEIynjMZwyXMusJbz3lGmjOC7eZ5QH/jNlMNu1ERg
 m3cninK3MJ5+hWQoKJJGbSkLHCwer2gBBI7NMe1w9evZLXLAZd6+YHV3xTeBSm1d
 uAaIJgVe6qM6UTRKn8x5XBK3KK8f2joXSaWF+gKrZELEEo4zrVHR3ANqajxpSN+j
 QA3rcWghUD9pDilpDZoV5/DxkMDceuK10uM5Bxfjstq4EUpk6QvSf37CPOtYs5FE
 52X68yWix7HsNjljC2TYSogmBqzhRc9JnYM4lP8d7XE0y3mrF+Xsc8psfZAjFE0v
 TKxQKJRjXJnl6/2k7zTOV5hE5HNEouIuJg7QtQa2Z1mWv95k+iqVYO4xbBPKWt+7
 VboWGTHZMOmOWReweDnDcJ092f1AAfIe3oItjjkMWwRC2yhNLb+6tlM4UtHS4Wga
 2eZHYUAnk80vI/l4Bly5KLvR9WBv5x0nDe5sWaZ1k3heSUxtQrtm0LzFG/bXcyoD
 rgz0N6wRoHKvg3Ztobe4N1RqtcLCLlO8s9ZvlgPsjQH0+QJaJ+xxRJiu976VxD+C
 UOCBedcLuJLZF+rXh1EJAxrAwYm3y3QZ6KH6TJvgVK8vGQXz505dhFIbMM5ks2vl
 DkTq2Q==
 =n4dl
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.15'

release v0.23.15
2023-12-20 16:23:58 +01:00
Max Kellermann
7727630f24 Merge branch 'alsa_input_exception' of https://github.com/borine/MPD 2023-12-20 13:21:37 +01:00
Max Kellermann
e2f8c9a4c2 Merge branch 'android_action' of https://github.com/DDRBoxman/MPD 2023-12-20 10:55:44 +01:00
Max Kellermann
22dbfec126 Merge branch 'android_shutdown' of https://github.com/DDRBoxman/MPD 2023-12-20 10:54:35 +01:00
Max Kellermann
efc462eebf Merge branch 'doc-features' of https://github.com/mxjeff/MPD 2023-12-20 10:53:34 +01:00
Max Kellermann
c3883e2fe0
Merge pull request from MusicPlayerDaemon/dependabot/github_actions/actions/setup-python-5
build(deps): bump actions/setup-python from 4 to 5
2023-12-20 10:53:16 +01:00
Colin Edwards
16c91a3f4b android: Fix MPD shutdown from settings UI 2023-12-19 22:05:03 -06:00
Colin Edwards
80bb5a0542 android: Add github action
This lives under a separate workflow so it can have different ignore paths.
2023-12-19 17:25:25 -06:00
Colin Edwards
906d58a918 android: migrate app build system to use gradle
Most of the Android specific meson code has been removed and replaced with
the grade build system.

The new meson build scripts build and move the libmpd.so binaries into the correct
location that gradle expects. After than gradle handles building the rest of the Android app.

Icons and banners have been updated for the modern app packaging expectations.

For reference here was the figma template Google provides that I used to back the png versions
for older versions of Android <https://www.figma.com/community/file/1283953738855070149>
2023-12-17 22:38:34 -06:00
kaliko
23b34fe142 Document new added-since filter introduced in 1615fbc 2023-12-17 10:00:19 +01:00
Colin Edwards
8d6f503e04 android: require NDK r26b
This fixes `no member named 'invocable' in namespace 'std'`
2023-12-13 12:01:30 -06:00
Colin Edwards
3284a61f43 android: build with java 8 target
The latest Android `sdkmanager` tool requires a version of the jdk that no longer
supports Java 7 as a target
2023-12-13 11:50:21 -06:00
Colin Edwards
c1a852d0e8 android: Pick toolchain based on current OS 2023-12-13 11:48:22 -06:00
Colin Edwards
4c90ad3704 android: realdir doesn't accept nonexistant files on macOS 2023-12-13 11:47:18 -06:00
Colin Edwards
a92a801f08 android: List additional build dependencies in instructions 2023-12-13 10:38:51 -06:00
Colin Edwards
9059c6c657 android: find apksigner in build tools folder 2023-12-13 10:35:52 -06:00
dependabot[bot]
bd6f8cd585
build(deps): bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 15:18:48 +00:00
Max Kellermann
a6024f476a subprojects: add openssl 2023-12-11 11:01:32 +01:00
Max Kellermann
dfef30a737 subprojects: add curl 2023-12-11 10:53:43 +01:00
Max Kellermann
55ca3709ef subprojects: add ogg, flac, opus 2023-12-11 10:53:43 +01:00
Max Kellermann
ab6ae7520d doc/developer.rst: add missing return type to code style sample 2023-12-10 08:24:05 +01:00
Max Kellermann
c7a300d12d meson.build: static liburing wrap build 2023-12-09 21:00:18 +01:00
Max Kellermann
babf322695 subprojects: update liburing to 2.4-2 2023-12-09 20:55:13 +01:00
Max Kellermann
642de1510b lib/curl/Request: remove redundant CurlEasy wrapper methods 2023-12-09 20:54:21 +01:00
borine
f61eed1a82 input/plugins/Alsa: catch all exceptions
snd_pcm_poll_descriptors_revents() may return any error code; the
ALSA docs do not constrain the permitted values. A 'hw' device
will only ever return an error if the pfd array passed in is
invalid (-EINVAL), but other I/O plugins may return arbitary
errors. For example a network-based device may return -EPIPE etc.
The resulting exception thrown by
AlsaNonBlockPcm::DispatchSockets() must be caught to prevent the
mpd process from being aborted.
2023-11-26 15:36:42 +00:00
Max Kellermann
e9c40dead8 output/SharedPipeConsumer: add noexcept 2023-11-26 08:48:45 +01:00
Max Kellermann
31bf6d29b9 BulkEdit: forbid copying 2023-11-26 08:47:06 +01:00
Max Kellermann
571b6f0cdb queue/IdTable: add constexpr (because we can) 2023-11-26 08:43:50 +01:00
Max Kellermann
e7b9e8de14 queue/IdTable: add API docs 2023-11-26 08:43:20 +01:00
Max Kellermann
321553d5f9 queue/IdTable: add explicit 2023-11-26 08:41:57 +01:00
Max Kellermann
4d23068c5c queue/IdTable: use C++11 initializer 2023-11-26 08:41:19 +01:00
Max Kellermann
634b38169a Merge branch 'alsa_input_buffer' of https://github.com/borine/MPD 2023-11-26 08:24:51 +01:00
Max Kellermann
fe4695f92a Merge branch 'added_time_proxy_plugin' of https://github.com/jcorporation/MPD 2023-11-26 08:20:18 +01:00
Max Kellermann
3c7941b24b Instance: work around -Wunused-parameter 2023-11-26 08:13:57 +01:00
Max Kellermann
a5d7f5e1fa client/Client: add interface IClient
This allows detangling dependencies and fixes a linker problem in
test/test_translate_song.cxx.
2023-11-26 08:11:06 +01:00
Max Kellermann
0dfd7e3d8c net/SocketDescriptor: SO_PROTOCOL is really Linux-specific 2023-11-25 23:03:30 +01:00
Max Kellermann
f757dfdc4f SongLoader: add noexcept 2023-11-25 22:57:24 +01:00
Max Kellermann
eb675ad1b1 pcm/meson.build: add missing dependency on libconfig.a 2023-11-25 22:51:43 +01:00
Max Kellermann
08a5768764 fs/io/TextFile: split into class FileLineReader and AutoGunzipFileLineReader
Detangle dependencies.
2023-11-25 22:50:32 +01:00
Max Kellermann
d888bb1902 io/meson.build: move libfmt dependency to libio.a 2023-11-25 22:16:47 +01:00
Max Kellermann
6dc708f53f net/SocketDescriptor: use method GetOption() internally 2023-11-25 21:58:17 +01:00
Max Kellermann
60033f3eb4 net/SocketDescriptor: add method GetProtocol() 2023-11-25 21:58:09 +01:00
Max Kellermann
1239e075b8 net/SocketDescriptor: add method GetIntOption() 2023-11-25 21:56:07 +01:00
Max Kellermann
85286d74ef python/build/libs.py: update CURL to 8.4.0 2023-11-25 21:52:41 +01:00
Max Kellermann
f8f646497c python/build/libs.py: update OpenSSL to 3.1.4 2023-11-25 21:52:41 +01:00
Max Kellermann
24ace6da25 python/build/libs.py: update FFmpeg to 6.1 2023-11-25 21:52:41 +01:00
Max Kellermann
ea23ea28ce python/build/libs.py: update openmpt to 0.7.3 2023-11-25 21:52:41 +01:00
Max Kellermann
4072a6e445 python/build/cmake.py: add CMAKE_FIND_ROOT_PATH on Windows
Works around CURL build failure because cmake insists on using
/usr/include/zlib.h.
2023-11-25 21:52:41 +01:00
Max Kellermann
54601b292a subprojects: update liburing to 2.4-1 2023-11-25 21:52:41 +01:00
Max Kellermann
964e193fcd subprojects: update sqlite to 3.44.1-1 2023-11-25 21:52:41 +01:00
Max Kellermann
d5909b6d5d subprojects: update expat to 2.5.0-3 2023-11-25 20:47:43 +01:00
Max Kellermann
67a00ee541 subprojects: update fmt to 10.1.1-1 2023-11-25 20:47:11 +01:00
Max Kellermann
d0eea87b1a song/*SongFilter: use libfmt 2023-11-25 20:42:50 +01:00
Max Kellermann
273fc329e0 Merge branch 'added-since' of https://github.com/jcorporation/MPD 2023-11-25 20:36:38 +01:00
Max Kellermann
d85be95c30 Merge branch 'doc-mention-song-id-lifetime' of https://github.com/naglis/MPD 2023-11-25 20:34:40 +01:00
kaliko
ff60cf8a4c Document new added attribute introduced in 7bf43a97 2023-11-25 14:40:03 +01:00
Max Kellermann
b9daeef524 event/FineTimerEvent: add SetDue(), ScheduleCurrent() 2023-11-21 20:47:29 +01:00
Max Kellermann
9383ceac30 event/{Coarse,Fine}TimerEvent: add API docs 2023-11-21 20:47:25 +01:00
Max Kellermann
3d2bd08132 test/meson.build: eliminate variable gtest_main_dep 2023-11-21 20:46:10 +01:00
Max Kellermann
1259fdc2e3 test/meson.build: re-enable various compiler warnings with GTest 2023-11-21 20:46:10 +01:00
Max Kellermann
a564b7eedb test/test_translate_song: remove unused Log() symbol 2023-11-21 20:46:10 +01:00
Max Kellermann
ebf1fc7ca4 util/IntrusiveList: convert static_assert to concept check 2023-11-21 20:42:01 +01:00
Max Kellermann
73708e7be7 event/TimerEvent: remove transitional header 2023-11-21 20:41:55 +01:00
Max Kellermann
0c409aa290 input/LastInputStream: use CoarseTimerEvent 2023-11-21 20:41:47 +01:00
Max Kellermann
edfa329e64 util/DereferenceIterator: use *declval() to guess the default value type
This allows the iterator to point to another iterator.
2023-11-21 20:40:47 +01:00
Max Kellermann
5ab2c31500 Merge branch 'v0.23.x' 2023-11-21 20:37:46 +01:00
naglis
ce178c7e1f doc/protocol.rst: mention song id lifetime 2023-11-16 22:58:07 +02:00
jcorporation
1615fbc30e Add "added-since" filter expression 2023-11-04 17:25:24 +01:00
jcorporation
45a4fcab1e Add support for added attribute to proxy plugin 2023-11-02 21:22:48 +01:00
Max Kellermann
68b19ae087 util/SpanCast: add ReferenceAsWritableBytes() 2023-11-02 10:50:24 +01:00
Max Kellermann
a073db1e52 util/SpanCast: add ReferenceAsBytes() 2023-11-02 10:50:00 +01:00
Max Kellermann
10940da381 util/Intrusive{List,HashSet}: add "tag" for base hooks 2023-11-02 10:48:46 +01:00
Max Kellermann
57d9cffc42 event/PipeEvent: expose the EventPollBackendEvents constants 2023-11-02 10:48:21 +01:00
Max Kellermann
65a3062f45 Merge branch 'configure-systemd-units-based-on-build-options' of https://github.com/naglis/MPD 2023-11-02 10:43:02 +01:00
Max Kellermann
ac25f3456a Merge branch 'added_time' of https://github.com/jcorporation/MPD 2023-11-02 10:42:31 +01:00
jcorporation
f4f79a3d5f New command "stickernames" lists uniq and sorted sticker names 2023-10-21 18:21:03 +02:00
jcorporation
7bf43a9712 Add "added" timestamp to song database
- added is set to current time, if a new song is added to the database.
- GetAdded falls back to mtime.

Code for proxy plugin is missing, this needs a patch for libmpdclient.

closes 
2023-10-20 17:29:31 +02:00
Nick Steel
97da29cc90
Stickers: fix documentation typos 2023-10-16 14:25:58 +01:00
Max Kellermann
de1da485ab LICENSES: add all licenses referred to by SPDX headers
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1877
2023-10-15 11:39:08 +02:00
Max Kellermann
2b10cf3c15 pcm/Normalizer: change license identifier to LGPL-2.1-only
"LGPL-2.1" doesn't exist, and the old copyright header did not specify
the "or later" clause, so I must assume it's 2.1 only.
2023-10-15 11:37:21 +02:00
gd
432675d4c2 Stickers: added support for stickers on playlists and some tag types 2023-10-15 11:25:16 +02:00
Max Kellermann
70ac638d93 tag/Mask: make everything constexpr 2023-10-15 11:03:56 +02:00
Max Kellermann
ccbacb369b io/linux/ProcPath: new library 2023-10-15 10:55:32 +02:00
Max Kellermann
7c0b561a16 event/InotifyEvent: add method TryAddWatch() 2023-10-15 10:51:06 +02:00
Max Kellermann
db5f270f42 util/AllocatedString: fix string_view specialization in TotalSize() 2023-10-09 14:54:40 +02:00
Max Kellermann
3a86956257 release v0.23.14
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmUiZBkNHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEiKQD/9kvDc7xvg72IKD80uU3Z7pN6zOeSgsJqSAOaaF
 F/j1gsDzwWYkIwlFM/Rr4zt9FkwKgusEknZGj3mUVLRATYk+oZpH4PzwHcqjk/x6
 jBimj/IFvW51E2hYTpvjTa3UwDBIXuuRG+URcsub1zUMfdMWYS5N4CZgXKf/Nx+i
 EOqfZFhNxdl53wNKt8buyNBvXaX6JvV1dIkF6tDrJLXVphwNTvWRRNtO+ll9VHCG
 r5vTH2E1N9K14P8He/pMMnJ4ykJ2zIGQl9GQLagcKbWQUNqn1Nv7gnKIjO09VT3Z
 HLHirYWAlC8kp2kOhxC+UuTcc4uRPqgLMYg/XRaJezf5b8wZYxMHeNBypRBPiNbG
 6h2Hme4xwsAM0r7G+SEwCkBD91AGr61BxHYTPbU58hFe6w4jbtmrXWZJ6jJnSepr
 HJSsI5/fhdGsJMEMF5QbsNb2cHmvJjUurgJvoae52+5MnZEIVQUgOBxvtm8h3/x3
 ixO+UIW6T7RFXEF95pDHLgEFeMIuFKes1ANDVsqaE5ioIbeXzZnBVW/Y6DpbsHuN
 5onhMdPmvHu6+CCuE3505HSKFXe8ctzefrVJlA8pzDdptuLZpnGGgSG069Zoj9JC
 xJ0iFComqJC8uELySJvJfHwC44ElSfRjXDKzlyxYQdrJgxGF5QqCgPaP03tjbe47
 8KlqLg==
 =oxwG
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.14'

release v0.23.14
2023-10-08 10:12:34 +02:00
Max Kellermann
f49d4ef4ad tag/Mask: switch to 64 bit because have we 34 tags now and 32 bits are not enough 2023-10-08 10:02:50 +02:00
Max Kellermann
2859845567 Merge branch 'v0.23.x' 2023-10-08 10:02:19 +02:00
Max Kellermann
e521b58b01 io/PeekReader: fix offset/size mixup
Regression by commit 7ccc4ddf0de992462de03b10a2450ae7c2cdb588
2023-10-08 09:55:59 +02:00
Max Kellermann
34182990ef fs/FileInfo: add fstat() wrapper 2023-10-07 12:49:07 +02:00
Max Kellermann
1ca5d6baa6 io/FileReader: do not copy the path 2023-10-07 12:48:03 +02:00
Max Kellermann
9365f68454 io/FileReader: use GetFileInfoByHandle() 2023-10-07 12:47:57 +02:00
Max Kellermann
7b5f107341 fs/FileInfo: add GetFileInformationByHandleEx() wrapper 2023-10-07 12:37:49 +02:00
Max Kellermann
e9ec03f769 PlaylistFile: use uint_least64_t 2023-10-07 12:29:14 +02:00
Max Kellermann
579a6ee299 fs/FileInfo: un-inline the constructor to reduce header dependencies 2023-10-07 12:28:31 +02:00
Max Kellermann
7d31659137 PlaylistFile: add missing include 2023-10-07 12:28:31 +02:00
Max Kellermann
f549c611ab fs/FileInfo: make constructor explicit 2023-10-07 12:24:05 +02:00
Max Kellermann
51c0a03e94 fs/FileInfo: add constexpr and noexcept 2023-10-07 12:22:54 +02:00
Max Kellermann
19c73680cf io/FileReader: use uint_least64_t 2023-10-07 08:49:04 +02:00
Max Kellermann
a9ba9a5f92 io/Reader: add [[nodiscard]] 2023-10-07 08:45:59 +02:00
Max Kellermann
3032792563 io/Reader: add method ReadFull() 2023-10-07 08:45:52 +02:00
Max Kellermann
7ccc4ddf0d io/Reader: use std::span 2023-10-07 08:44:42 +02:00
Max Kellermann
b9704715fb io/FileOutputStream: pass dfd=-1 for absolute /proc/self/fd/N path 2023-10-07 08:42:35 +02:00
Max Kellermann
86e7dff2fc util/TextFile: add missing cast 2023-10-07 08:39:24 +02:00
Max Kellermann
c450f644e6 lib/xiph/OggSyncState: fix indent 2023-10-07 08:30:12 +02:00
Max Kellermann
496184b1bc io/Reader: add method ReadT() 2023-10-07 08:27:13 +02:00
Max Kellermann
b81cac3305 lib/nfs/Error: include cleanup 2023-10-04 23:12:45 +02:00
Max Kellermann
bf9dd24536 lib/pcre/UniqueRegex: wrap Compile() options in struct 2023-10-04 17:32:12 +02:00
Max Kellermann
e5680c712b util/IntrusiveList: add reverse_iterator 2023-10-04 16:51:17 +02:00
Max Kellermann
44daa6d3e6 util/IntrusiveForwardList: reset last_cache properly in clear() 2023-10-04 16:50:46 +02:00
Max Kellermann
5ddddbb16f test/util/TestIntrusiveForwardList: add push_back() test 2023-10-04 16:50:38 +02:00
Max Kellermann
5aaa3f50aa util/BindMethod: move SignatureHelper to return type 2023-10-04 16:50:25 +02:00
Max Kellermann
7d26cd74c1 util/BindMethod: add noexcept 2023-10-04 16:50:25 +02:00
Max Kellermann
7e6941acc8 util/BindMethod: add constexpr 2023-10-04 16:50:25 +02:00
Max Kellermann
63d865666e util/StringBuffer: use using instead of typedef 2023-10-04 16:50:25 +02:00
Max Kellermann
5dda4084df util/BindMethod: use using instead of typedef 2023-10-04 16:50:25 +02:00
Max Kellermann
19f9238ef0 util/BindMethod: fix indent 2023-10-04 16:50:25 +02:00
Max Kellermann
491cc8f54d net/SocketDescriptor: add {Read,Write}NoWait()
It was surprising that Read() was non-blocking, but there was no
blocking version of it.  Let's make the non-blocking behavior explicit
and change Read() to be blocking.

In order to find existing callers easily with compiler errors, this
also refactors Read()/Write() to take a std::span parameter.
2023-09-27 11:39:55 +02:00
Max Kellermann
cad35a83fb io/FileDescriptor: add Read()/Write() overloads with std::span 2023-09-27 11:14:23 +02:00
Max Kellermann
5fbe5951ab output/snapcast/Client: use SocketDescriptor::Send() 2023-09-27 10:39:48 +02:00
Max Kellermann
21590e60e6 event/FullyBufferedSocket: pass std::span to DirectWrite() 2023-09-27 10:36:56 +02:00
Max Kellermann
fe69ad0861 event/BufferedSocket: pass std::span to DirectRead() 2023-09-27 10:34:50 +02:00
Max Kellermann
9daf8f6de5 event/BufferedSocket: use std::byte 2023-09-27 10:30:09 +02:00
Max Kellermann
8ca6606323 net/SocketDescriptor: move code to Receive(), Send() 2023-09-27 10:16:21 +02:00
Max Kellermann
09a2da89a2 io/FileDescriptor: pass std::span to Full{Read,Write}() 2023-09-27 10:14:02 +02:00
Max Kellermann
9a0b3775d8 encoder/ToOutputStream: add API docs 2023-09-26 15:48:55 +02:00
Max Kellermann
2075a9a999 encoder/ToOutputStream: remove unnecessary cast 2023-09-26 15:48:22 +02:00
Max Kellermann
1090cc964a event/Loop: relicense to BSD-2
This library has been initially developed at CM4all and eventually
published here:
 https://github.com/CM4all/libcommon/tree/master/src/event/

On this copy of it, there were only minor modifications by people
other than me, and these are below the copyright threshold; only
non-epoll backends (which remain under the GPL) were developed by
somebody else.
2023-09-26 15:47:09 +02:00
Max Kellermann
39476bed85 Merge branch 'v0.23.x' 2023-09-26 15:36:26 +02:00
Max Kellermann
5cea03bb4f Merge branch 'v0.23.x' 2023-09-26 11:49:30 +02:00
Max Kellermann
26467e61a3 Merge branch 'consume_single_oneshot-restore' of https://github.com/jcorporation/MPD 2023-09-26 11:43:27 +02:00
Max Kellermann
2bb4c7cfa7 test/meson.build: add missing libfmt dependency
Should have been part of 64647edbe1f0712a173a73896f270f6bf6ae6065
2023-09-26 10:47:52 +02:00
Max Kellermann
fbdd2324a5 sticker/Database: add method Reopen() 2023-09-26 10:14:05 +02:00
Max Kellermann
dc31aa6a61 decoder/Plugin: remove unused and broken wrapper method ContainerScan() 2023-09-26 10:13:42 +02:00
Max Kellermann
5b28a987e5 util/IntrusiveForwardList: add method remove_and_dispose_if() 2023-09-22 11:32:40 +02:00
Max Kellermann
78d28063c4 util/IntrusiveForwardList: push_{front,back}() returns iterator 2023-09-22 11:32:33 +02:00
Max Kellermann
64647edbe1 lib/fmt/SocketAddressFormatter: new library 2023-09-19 11:22:39 +02:00
Max Kellermann
b36f5f1ec4 net/ToString: use #pragma once 2023-09-18 22:01:40 +02:00
Max Kellermann
592649d3f2 net/ToString: check family==AF_INET6 instead of looking for colons 2023-09-18 21:59:27 +02:00
Max Kellermann
9398599816 net/ToString: use libfmt 2023-09-18 21:58:55 +02:00
Max Kellermann
61c29473d3 net/ToString: append port only if it is non-zero 2023-09-18 11:11:00 +02:00
Max Kellermann
5fd2fc77f3 net/ToString: add null check 2023-09-18 11:08:16 +02:00
Max Kellermann
3eb0681e3d net/ToString: use SocketAddress::GetLocalRaw() 2023-09-18 10:54:52 +02:00
Max Kellermann
e831af35fd input/curl: move code to CreateEasy() 2023-09-17 14:26:47 +02:00
Max Kellermann
fb2e0f734e lib/fmt/ToBuffer: add overload with StringBuffer parameter 2023-09-16 23:05:48 +02:00
Max Kellermann
3d69f43cff event/Loop: include SocketEvent.hxx only if HAVE_THREADED_EVENT_LOOP 2023-09-16 22:55:04 +02:00
Max Kellermann
41b1931d91 event/Loop: move the poll_backend to the top
This is where all sockets are registered, so it should be initialized
first and destructed last.
2023-09-16 22:45:45 +02:00
Max Kellermann
f086444e4a lib/curl/Easy: add method SetRequestBody(std::string_view) 2023-09-16 22:39:03 +02:00
Max Kellermann
b8210bbc45 lib/avahi/Poll: fix copyright header 2023-09-16 22:39:03 +02:00
Max Kellermann
ce2965b5bc io/uring/meson.build: disable io_uring on Android
On Android, the feature is forbidden by a seccomp filter, see

 https://security.googleblog.com/2023/06/learnings-from-kctf-vrps-42-linux.html
2023-09-16 22:39:03 +02:00
Max Kellermann
18000ff499 io/uring/Handler: remove unused header 2023-09-16 22:39:03 +02:00
Max Kellermann
64e91d6eb7 test/util/TestIntrusiveForwardList: add constant_time_size test 2023-09-16 22:39:03 +02:00
Max Kellermann
6f7dce6dca test/util/TestIntrusiveForwardList: implement size() only if options.constant_time_size is set 2023-09-16 22:39:03 +02:00
Max Kellermann
175524ad02 util/IntrusiveForwardList: make end() non-static
So we can have a `const` overload which is important for some
algorithm templates.
2023-09-16 22:39:03 +02:00
Max Kellermann
bfbde72676 util/Intrusive*: insertion methods return an iterator 2023-09-16 22:39:03 +02:00
Max Kellermann
f76583a08a util/IntrusiveList: document the erase() return value 2023-09-16 22:39:03 +02:00
Max Kellermann
6d39b401b5 util/IntrusiveForwardList: add method iterator_to() 2023-09-16 22:39:03 +02:00
Max Kellermann
f448bfd3f3 util/IntrusiveForwardList: add option cache_last 2023-09-16 22:39:03 +02:00
Max Kellermann
64b0587e78 util/OptionalField: new library 2023-09-16 22:39:03 +02:00
Max Kellermann
9fe813e572 util/IntrusiveForwardList: add pop_front_and_dispose() 2023-09-16 22:39:03 +02:00
Max Kellermann
b0da0bbf8b util/IntrusiveForwardList: pop_front() returns reference 2023-09-16 22:39:03 +02:00
Max Kellermann
5c44082b77 util/IntrusiveForwardList: add non-static insert_after() implementation 2023-09-16 22:39:03 +02:00
Max Kellermann
df7ed27b78 util/IntrusiveForwardList: fix move operator, really swap counter 2023-09-16 22:39:03 +02:00
Max Kellermann
bef7ce37d9 RemoteTagCache: use the pop_front() return value 2023-09-16 22:39:03 +02:00
Max Kellermann
c74cf79e0f
Merge pull request from MusicPlayerDaemon/dependabot/github_actions/actions/checkout-4
build(deps): bump actions/checkout from 3 to 4
2023-09-16 21:58:20 +02:00
naglis
992488c6c6 doc/plugins.rst: document missing httpd settings 2023-09-16 00:18:03 +03:00
naglis
bdfe5e97cd systemd: base "RestrictAddressFamilies" on build options
This allows to not allow `AF_NETLINK` if `smbclient` is not enabled.
2023-09-15 23:39:00 +03:00
naglis
df069bc456 systemd: base "ListenStream" on build options
Make `mpd.socket` configurable based on build options, so that e.g.
`ListenStream=6600` is not added if `tcp` option is not enabled.
2023-09-15 23:38:59 +03:00
Max Kellermann
9bb67ae7f0 subprojects: update sqlite to 3.43.0-1 2023-09-12 10:21:27 +02:00
Max Kellermann
c994fe4879 io/uring/meson.build: detect liburing with include_type=system
This avoids breakages due to `-Wgnu-anonymous-struct`.
2023-09-12 10:20:58 +02:00
Max Kellermann
32421fed89 subprojects: update liburing to 2.3-3 2023-09-12 10:17:03 +02:00
Max Kellermann
077add79cd subprojects: update fmt to 9.1.0-2 2023-09-12 10:16:56 +02:00
Max Kellermann
50f0163f5f time/SystemClock: pass by value 2023-09-12 09:56:06 +02:00
Max Kellermann
481c1b6f2e lib/dbus/ReadIter: add method GetBool() 2023-09-12 09:53:58 +02:00
Max Kellermann
474b6610fa lib/dbus/Error: add method GetName() 2023-09-12 09:53:15 +02:00
Max Kellermann
11c49da871 io/FileReader: remove unused method Close()
It's enough to have the destructor.
2023-09-12 09:53:06 +02:00
Max Kellermann
678828b56f io/FileOutputStream: remove obsolete maybe_unused 2023-09-12 09:43:14 +02:00
Max Kellermann
9e802ad721 util/StringCompare: add pure attribute 2023-09-12 09:34:52 +02:00
Max Kellermann
859ffddea3 io/BufferedReader: fix ReadFullT() after std::span migration 2023-09-12 09:32:20 +02:00
Max Kellermann
daf935d310 util/HexFormat: add non-const overload 2023-09-12 09:11:38 +02:00
Max Kellermann
6953800628 python/build/libs.py: update CURL to 8.2.1 2023-09-11 22:24:27 +02:00
Max Kellermann
7c65c4f485 python/build/libs.py: update OpenSSL to 3.1.2 2023-09-11 22:23:59 +02:00
Max Kellermann
8950fb9393 python/build/libs.py: update zlib to 1.3 2023-09-11 22:22:00 +02:00
Max Kellermann
b754f3dc34 python/build/libs.py: update Opus to 1.4 2023-09-11 22:21:04 +02:00
Max Kellermann
e8a25dc8d9 python/build/libs.py: update FLAC to 1.4.3 2023-09-11 22:19:41 +02:00
Max Kellermann
99765cc704 modplug: add patch to remove the deprecated register keyword 2023-09-11 22:17:45 +02:00
Max Kellermann
a868dbce3b android/AndroidManifest.xml: raise minSdkVersion to 24
This is needed to build libFLAC which uses ftello().
2023-09-11 22:14:23 +02:00
Max Kellermann
f68305bf00 util/NumberParser: remove obsolete __ANDROID_API__ check 2023-09-11 22:12:13 +02:00
Max Kellermann
517c234461 lib/zlib/GzipOutputStream: use MAX_WBITS 2023-09-11 22:02:04 +02:00
Max Kellermann
a58275591d util/StaticVector: add methods erase(), pop_front() 2023-09-11 21:59:28 +02:00
Max Kellermann
a2f4fb9ddb util/StaticVector: add method pop_back() 2023-09-11 21:59:21 +02:00
Max Kellermann
b2acf02af9 util/StaticVector: push_back(), emplace_back() return reference
Imitating std::vector since C++17.
2023-09-11 21:59:12 +02:00
Max Kellermann
d5b1ca1a52 util/StaticVector: use emplace_back() to implement push_back()
For this class, both are equal.
2023-09-11 21:58:56 +02:00
Max Kellermann
339b9f6e7b net/StaticSocketAddress: add method GetSteadyPart() 2023-09-11 21:27:12 +02:00
Max Kellermann
35cfa6efa3 net/StaticSocketAddress: add SocketAddress cast constructor 2023-09-11 21:27:12 +02:00
Max Kellermann
34ec024bf4 net/AllocatedSocketAddress: add method GetSteadyPart() 2023-09-11 21:27:12 +02:00
Max Kellermann
75aa08ed6b tag/Pool: use a power-of-2 hash table size
This is simpler to calculate and the advantage of using a prime is
negligible anyway.
2023-09-11 21:23:11 +02:00
Max Kellermann
c8dc1e0665 tag/Pool: use class IntrusiveHashSet intead of rolling a custom hash table 2023-09-11 21:15:28 +02:00
Max Kellermann
847ae7dd7c util/IntrusiveHashSet: add insert_check_if() 2023-09-11 21:15:28 +02:00
Max Kellermann
44f55e1866 util/IntrusiveList: add missing initializer to insert_after()
We must not call std::next() if the list head was not yet initialized.
This was missing in commit 70654259270fdaae2906fb9fe4f34c6e3a740c37
2023-09-11 21:15:28 +02:00
Max Kellermann
c391adad10 tag/Pool: move code from calc_hash() to util/djb_hash.cxx 2023-09-11 20:53:37 +02:00
Max Kellermann
f578b06d83 tag/Pool: move calc_hash() returns std::size_t 2023-09-11 20:51:44 +02:00
Max Kellermann
0748f75d9b tag/Pool: rename TagPoolSlot to TagPoolItem 2023-09-11 20:44:55 +02:00
Max Kellermann
7dff29bcd1 util/IntrusiveHashSet: add option zero_initialized 2023-09-11 20:34:17 +02:00
Max Kellermann
3e09f95b40 tag/Pool: enable option zero_initialized
Commit 44beae519d1966ebf96d53f858f4ea15932d0849 caused the MPD
executable to grow by more than 1 MB because the `slots` array
suddenly was not zero-initialized anymore, because the doubly-linked
list is circular, while the singly-linked list is zero-terminated.

This option moves the array back to the `bss` section.
2023-09-11 20:32:26 +02:00
Max Kellermann
7065425927 util/IntrusiveList: add option zero_initialized 2023-09-11 20:30:38 +02:00
Max Kellermann
f01793ad4a util/Intrusive*: move constant_time_size to an options struct
This makes it easier to add more options later.
2023-09-11 19:18:36 +02:00
Max Kellermann
1f495efb46 test/LoadDatabase: ignore tag/charset mismatches
This program shouldn't fail just because the configuration doesn't
match - it has no configuration, it's just a dumb test program.
2023-09-07 09:54:03 +02:00
Max Kellermann
38d8359384 test/LoadDatabase: new test program (for benchmarking the database loader) 2023-09-06 16:17:24 +02:00
Max Kellermann
2c01e79b47 SongSave: omit FixTagString() for strings from the database file
Strings in the database should have been sanitized already, so let's
not waste CPU on this.
2023-09-06 16:12:20 +02:00
Max Kellermann
a573d57de8 tag/Builder: remove unnecessary explicit AddItem() overload 2023-09-06 16:10:31 +02:00
Max Kellermann
2f4e2935a3 db/upnp, playlist/pls: use AddItem(std::string_view) 2023-09-06 16:08:42 +02:00
Max Kellermann
44beae519d tag/Pool: use doubly-linked list
This adds some memory overhead but eliminates the linear search from
tag_pool_put_item().
2023-09-06 16:00:25 +02:00
Max Kellermann
b896711fc6 tag/Pool: fix crash in tag_pool_put_item()
Regression by commit 76bdfabcc56c618d8562a7a6f5ccbfd169b97813
2023-09-06 15:53:17 +02:00
Max Kellermann
76bdfabcc5 tag/Pool: use class IntrusiveForwardList 2023-09-06 15:33:26 +02:00
Max Kellermann
b35e8a588f util/IntrusiveForwardList: add operator++(int) 2023-09-06 15:31:07 +02:00
Max Kellermann
6c48f5ac63 tag/Pool: use std::array 2023-09-06 15:10:47 +02:00
Max Kellermann
1448f52eac util/VarSize: convert static_assert to concept check 2023-09-06 15:05:26 +02:00
Max Kellermann
c96e8ab47c db/simple/DirectorySave: optimize duplicate checks with std::set
This reduces the CPU usage for loading a large database by more than 50%.
2023-09-06 14:56:41 +02:00
Max Kellermann
2c4ef4460f db/update/SpecialDirectory: more std::string_view migration 2023-09-06 14:51:37 +02:00
Max Kellermann
20bbe1b57b fs/Traits: add GetFilenameSuffix() overload with std::string_view 2023-09-06 14:50:36 +02:00
Max Kellermann
449d59af2f db/simple/Directory: use operator== to compare strings 2023-09-06 14:30:08 +02:00
Max Kellermann
851136e6fd db/simple/Directory: GetName() returns std::string_view 2023-09-06 14:29:32 +02:00
Max Kellermann
ad854e9867 db/simple/Save: initialize array without memset() 2023-09-06 14:17:07 +02:00
dependabot[bot]
f53dde970f
build(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 15:51:28 +00:00
naglis
046a385070 doc/user.rst: use explicit meson setup command
The implicit setup command is deprecated since 0.64.0
2023-08-24 13:57:03 +03:00
jcorporation
9a28176d72 Save consume and single oneshot as string
Consume and single oneshot should be saved as string.

closes 
2023-08-07 23:23:08 +02:00
Max Kellermann
ba2df05fb4 lib/zlib/GzipOutputStream: add noexcept 2023-08-03 20:58:43 +02:00
Max Kellermann
8722c51306 lib/dbus/AppendIter: add Append(int32_t), Append(int64_t) 2023-08-03 20:58:01 +02:00
Max Kellermann
80104eb6d5 util/IntrusiveList: fix illegal downcast (ubsan)
Fixes UBSanitizer warning:

 src/util/IntrusiveList.hxx:108:10: runtime error: downcast of address 0xdeadbeef which does not point to an object of type 'Foo'
2023-08-03 20:56:34 +02:00
Max Kellermann
8743326924 sticker/Database: allow moving 2023-08-03 20:54:57 +02:00
Max Kellermann
83a6cb804b util/IntrusiveHashSet: add template argument GetKey
This is a big simplification of all IntrusiveHashSet users: instead of
having to implement multiple overloads of Hash and Equal, the
IntrusiveHashSet class can first extract the effective key from an
item and then pass it to the Hash/Equal functions.
2023-08-03 20:50:21 +02:00
Max Kellermann
78801f303e test/util/TestIntrusiveHashSet: add test for remove_and_dispose_key() 2023-08-03 20:44:52 +02:00
Max Kellermann
9691b609a2 util/IntrusiveHashSet: remove_and_dispose() returns number of removed elements 2023-08-03 20:44:47 +02:00
Max Kellermann
250fa8c732 util/IntrusiveHashSet: rename remove_and_dispose() to remove_and_dispose_key() 2023-08-03 20:44:39 +02:00
Max Kellermann
2cd5f4cd3e util/IntrusiveHashSet: replace template parameters Hash/Equal with a single one
Preparing to add a key extraction function.  Without this "Operators"
template parameter, we'd have even more template parameters, and that
parameter list would grow too complex.  Better wrap it in one single
template that contains all operators.

This is an API change which all callers need to adjust to, but it will
be worth it.
2023-08-03 20:44:14 +02:00
Max Kellermann
dcd7c6337c util/Intrusive{List,HashSet}: reimplement hook mode detection with implicit cast 2023-08-03 20:33:15 +02:00
Max Kellermann
43d633f560 Instance: use C++11 initializers 2023-07-23 09:14:25 +02:00
Max Kellermann
1c37b0487c lib/fmt/SystemError: add VFmtErrno() 2023-07-21 19:44:45 +02:00
Max Kellermann
acc92b156b util/Concepts: remove obsolete fallbacks 2023-07-21 19:43:04 +02:00
Max Kellermann
aeadae5399 util/IntrusiveHashSet: insert_check() returns the bucket head on success
The list head is a stable value that is guaranteed to be still valid
when insert_commit() gets called.

This fixes a linked list corruption bug in class StaticCache which
occurs when the cache item pointed to by the iterator gets evicted
between insert_check() and insert_commit().
2023-07-21 19:42:35 +02:00
Max Kellermann
42d5b05f54 util/IntrusiveHashSet: rename insert() to insert_commit()
Clarify that the method is not a freestanding insertion method but
should only be used after insert_check().
2023-07-21 19:42:26 +02:00
Max Kellermann
e133f621a4 util/IntrusiveHashSet: add insert_check() documentation 2023-07-21 19:41:46 +02:00
Max Kellermann
91437d9e63 util/IntrusiveList: add insert_after() 2023-07-21 19:41:40 +02:00
Max Kellermann
f1b497fb0c util/IntrusiveList: document insert() 2023-07-21 19:41:36 +02:00
Max Kellermann
cc9d061e51 util/IntrusiveList: pop_front() and pop_back() return reference 2023-07-21 19:41:13 +02:00
Max Kellermann
62ee9a4d60 util/DynamicFifoBuffer: use T instead of std::byte
Mistake added by commit b528b467649754
2023-07-21 19:40:38 +02:00
jcorporation
082f72dd20 Add support of TAG_MUSICBRAINZ_RELEASEGROUPID
Closes 
2023-07-12 19:43:37 +02:00
Max Kellermann
9c19368fc7 Merge branch 'v0.23.x' 2023-06-02 14:36:02 +02:00
Max Kellermann
45f81cde6d Merge branch 'null-always-off' of https://github.com/nomis/MPD 2023-05-25 10:42:58 +02:00
John Regan
a482c798ad pcm: declare IsSilentSample as const
GNU libstdc++ declares cmath functions as constexpr, but libc++ does
not. The C++ standards state the standard library functions should not
be declared constexpr unless explicitly required.
2023-05-24 15:05:19 -04:00
Naïm Favier
838af929a0
meson: use correct prefix for systemd dirs
See https://www.bassi.io/articles/2018/03/15/pkg-config-and-paths/

Fixes the build in nixpkgs
2023-05-22 22:23:38 +02:00
Max Kellermann
d9b1f6223e io/uring/Close: wrapper for io_uring_prep_close() 2023-05-22 21:59:44 +02:00
Max Kellermann
26577d1301 io/uring/Queue: make Submit() virtual, Push() not
This allows submitting io_uring calls without an `Operation` instance
(fire & forget).  We'll do that for close().
2023-05-22 21:57:18 +02:00
Max Kellermann
6496c1b806 util/ScopeExit: convert the function from base class to member
This allows using `final` callables.
2023-05-22 21:20:49 +02:00
Max Kellermann
7bb251dad8 db/update/Walk: use marker to remove deleted items
This eliminates all `Storage::GetInfo()` calls from
`UpdateWalk::PurgeDeletedFromDirectory()` and instead uses a "marker"
field to mark items that have been visited; later, all unmarked items
can be deleted.

This eliminates a lot of redundant I/O which is noticable with the
`curl` storage plugin (i.e. WebDAV).
2023-05-22 20:13:01 +02:00
Max Kellermann
9027e5c5bb release v0.23.13
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmRrqn4NHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFErXiD/9QIaeO5d+U7BJK1yGkQgu5vHo4Pm34ewP8LTxs
 K2MYxQQ2jZc7PXqi5Z04wmUw8ymq1BVA2D0ytMdl1Ejcbrste7UrP+1TuD8L9JBj
 WCE+4otNVYDpx1PB32BN+gxCmJqiFtAQS+eMIz/SXdEXZ9sJvIgYRRkSiSFd0WHM
 dT3OeeZ0V8cANbXpgI+RLghRGkVdpZJo4uXh3c0OHog1fjEBWPw6+7tH/mkotM0n
 /hQjI5j14wnzZuIpkDR1kuzvGYmxJKG6LkuUqcm1WexNFbxMqDSbAlXeCmzJn7eK
 NQvtROOGNjQ84thxRPLlDlYa6vbxoTqdYgZsVHzsQZWejhqw8zsPsF+Ea0A4tkLd
 UKDQFTphZMVqx74+1u7IjQyW7x+k02iXWLwH2IheEl+BJhvEB7zEflN9TR81jek4
 RrGx7jcTArdpt7okAe2ONkHvTYtIpaK5E2voza8K4TGOMzpkVlOkyvJ+rpn8CDRf
 w0faVvmCQdSrgHKfwUUY8Z47a7d+kkKpFLlvvzNoDV8drQXfgIj5t9HOLATSVVux
 l2pbgauXFsKyd4IsByXj+m8cBSvmy2C4eLJCsmguiZEvcobdJtzwOr4KuwQDjBsC
 8HW0BD0t9S1dSL59vJdMG+CfK/QU5rmAIkxdydD42uo9UmSS78xw1uQgi9oDaPa8
 XNCGdQ==
 =nOGh
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.13'

release v0.23.13
2023-05-22 19:52:08 +02:00
Max Kellermann
8ba68fdb47 io/OutputStream: use std::span 2023-05-21 21:35:11 +02:00
Max Kellermann
e72d27566c io/BufferedOutputStream: use std::string_view 2023-05-21 21:31:32 +02:00
Max Kellermann
01c02a1ef8 util/StaticFifoBuffer: add method MoveFrom() 2023-05-21 21:26:20 +02:00
Max Kellermann
4bb4611e78 Merge branch 'v0.23.x' 2023-05-21 21:18:45 +02:00
Max Kellermann
c69b9780df Merge branch 'reorder-decoder-plugins' of https://github.com/fuck-shithub/MPD 2023-05-15 21:03:35 +02:00
Max Kellermann
f869593ac8 TimePrint: minor fixup for libfmt 10
libfmt version 10 has difficulties formatting a `StringBuffer`, and we
need to help it by explicitly invoking the `c_str()` method.
2023-05-15 21:00:24 +02:00
Max Kellermann
181b96dd2d command/player, SongPrint: use AudioFormatFormatter()
libfmt version 10 apparently doesn't know how to format a
`StringBuffer`, failing the MPD build.  Since we have a formatter
specialization for `AudioFormat`, let's use that - it's better and
easier to use.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1807
2023-05-15 20:59:05 +02:00
latex
4e9f463bb6 reorder ffmpeg to be lower priority than gme
This should prevent ffmpeg from taking priority over the gme plugin.
The ffmpeg plugin is more buggy than gme.
One of the prominent bugs of preferring ffmpeg over gme is that ffmpeg
cannot seek SAP files while gme can. This should prevent that from
happening.
2023-05-12 00:28:56 +02:00
borine
4947bb113d input/plugins/Alsa: limit ALSA buffer time to 2 seconds maximum
Some ALSA capture devices can have very large buffers, holding 10
seconds or more audio. Using the maximum buffer size with such
devices leads to unacceptably large, and unnecessary, latency.
Also, some ALSA drivers (e.g. HDA Intel PCH) report an invalid
maximum period size, and the period size that mpd calculates from
the maximum buffer size results in "Invalid argument" error when
applying the hw_params. Note that the "default" capture device on
many cards includes the "dsnoop" plugin which imposes a buffer
size of 16384 frames, so that "alsa://" works OK but
"alsa://plughw" or "alsa://hw" both fail.

Limit the maximum buffer time for ALSA input devices to a more useable
2 seconds, thereby avoiding both the above problems.
2023-05-06 10:33:48 +01:00
skidoo23
4345a656aa
output/httpd: fix libfmt icy-metaint replacement field
Since using libfmt (commit: dfc5b49) ICY MetaData was broken. Eg MP3 streams encoded with LAME were affected resulting in missing stream titles on VLC or strange noises on Sonos hardware. This commit fixes the icy-metaint field.
2023-05-04 18:15:13 +02:00
Max Kellermann
31dc8b73b7 db/update/Archive: validate directory names
Fixes assertion failure if the ZIP file contains a path that begins
with a slash.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1793
2023-04-30 08:46:52 +02:00
Max Kellermann
e84db4f411 db/update/Archive: ignore filenames with newline character 2023-04-30 08:45:34 +02:00
Max Kellermann
395bf34a91 db/update/Archive: move check to IsAcceptableFilename() 2023-04-30 08:42:16 +02:00
Max Kellermann
dcc7628b67 db/update/Archive: remove useless log message 2023-04-30 08:39:34 +02:00
Max Kellermann
f2a4ae15aa db/update: pass filenames as std::string_view 2023-04-30 08:28:43 +02:00
Max Kellermann
434bcb08ee db/simple/Song: pass std::string_view to Load{File,FromArchive}() 2023-04-30 08:21:20 +02:00
Max Kellermann
99885c4cbc util/IntrusiveHashSet: add method remove_and_dispose() 2023-04-22 08:40:53 +02:00
Simon Arlott
ab196f7afc
output/Control: Support always_off outputs that are never used for playback
Add an `always_off` option to outputs that causes them to never start
playback even if they're enabled.

This allows placeholder `null` outputs to be defined for the purpose
of having an external client react to the enabled state without the
side effects of real outputs. Like an external mixer, the client can
perform some action when an output is enabled.

Normally `null` outputs can be used for playback so it's possible for
MPD to continue playback silently if a problem occurs with all the real
outputs (or there are none enabled).
2023-04-21 20:54:37 +01:00
Max Kellermann
90c3fe22f5 decoder/openmpt: check libopenmpt version at compile time, not at configure time 2023-04-21 17:29:20 +02:00
Simon Arlott
ad8117e7c8 decoder/openmpt: Fix build error with libopenmpt < 0.5
openmpt_at_end is a string, not an integer

Fixes build error:

 src/decoder/plugins/OpenmptDecoderPlugin.cxx: In function 'void mod_decode(DecoderClient&, InputStream&)':
 src/decoder/plugins/OpenmptDecoderPlugin.cxx:85:44: error: invalid cast from type 'std::string_view' {aka 'std::basic_string_view<char>'} to type 'unsigned in '
   85 |  mod.ctl_set("play.at_end", std::to_string((unsigned)openmpt_at_end));
      |                                            ^~~~~~~~~~~~~~~~~~~~~~~~
2023-04-21 17:24:42 +02:00
Benjamin Cremer
82568c0b52
Fix syntax error in mpdconf.example 2023-04-13 08:47:43 +02:00
datasone
838b19c2b5 db/SimpleDatabasePlugin: store in_playlist value of songs into database
Fixes hide_playlist_targets not working after server restart

Currently, `hide_playlists_targets` works by skipping songs with
`in_playlist` value set to true in
[`Directory::Walk`](a57bcd0238/src/db/plugins/simple/Directory.cxx (L237)). But
`in_playlist` is not stored and only updated in
[`UpdateWalk::PurgeDanglingFromPlaylists`](a57bcd0238/src/db/update/Playlist.cxx (L139)),
which will only be executed while updating DB.

This causes the problem that playlist target songs are correctly
hidden after database update, but will remain visible after mpd server
restarted. This pr solves the problem by storing `in_playlist` value
of songs into the `SimpleDatabase` file.
2023-04-12 05:18:21 +02:00
kaliko
0d2f67b523 check systemd unit dir from systemd.pc in meson 2023-04-11 21:06:53 +02:00
Max Kellermann
a57bcd0238 thread/Mutex: add RecursiveMutex 2023-04-06 21:32:18 +02:00
Max Kellermann
76497bd5f7 util/IntrusiveSortedList, event/TimerList: include cleanup 2023-04-06 10:24:53 +02:00
Max Kellermann
53ec02d5e9 net/SocketDescriptor: decouple from FileDescriptor on Windows
On Windows, a socket is not a file descriptor; it is a different beast
(and anyway, Windows doesn't have file descriptors).
2023-03-29 10:12:50 +02:00
Max Kellermann
7a5f485cf8 event/ServerSocket: use class UniqueSocketDescriptor in SupportsIPv6() 2023-03-29 10:06:48 +02:00
Max Kellermann
90565b1e36 test/run_{input,output}: add missing includes 2023-03-29 10:06:48 +02:00
Max Kellermann
6f7c7a2149 event/EpollBackend: add missing header guard 2023-03-21 11:00:41 +01:00
Max Kellermann
91123983ad Revert "python/build/meson.py: keep Meson from executing Android-x86 test binaries"
This reverts commit 8ab2722300f680fc693677eee66194e963dd4ec9.  The
"needs_exe_wrapper" setting was already there, and the new one was
misplaced, it belongs in "[properties]".
2023-03-21 09:46:25 +01:00
Max Kellermann
2506edbffb python/build/libs.py: update OpenSSL to 3.1.0 2023-03-21 09:39:28 +01:00
Max Kellermann
929520ecd2 python/build/libs.py: update CURL to 8.0.1 2023-03-21 09:38:22 +01:00
Max Kellermann
a20d467bf1 event/Loop: move quit_injected check to inside #ifdef HAVE_THREADED_EVENT_LOOP 2023-03-20 15:02:32 +01:00
Max Kellermann
102dc123e8 LogBackend: log to stderr (regression fix) 2023-03-14 20:25:28 +01:00
Max Kellermann
b4d0b23369 LogBackend: use fmt::print() 2023-03-14 20:24:14 +01:00
Max Kellermann
119a949bb5 ls: use fmt::print() 2023-03-14 20:20:46 +01:00
Max Kellermann
f5b22bf2c3 input/Offset: remove unused macro PRIoffset 2023-03-14 20:20:10 +01:00
Max Kellermann
5b7a89d714 mixer/plugins/volume_mapping: convert to C++ 2023-03-14 20:18:41 +01:00
Max Kellermann
5b41857a22 mixer/plugins/volume_mapping: add SPDX header 2023-03-14 20:08:43 +01:00
Max Kellermann
688d9ff114 util/UriExtract: add uri_get_path_query_fragment()
Rename uri_get_path() to uri_get_path_query_fragment() and add a new
uri_get_path() function.
2023-03-14 20:03:17 +01:00
Max Kellermann
c2d202e9b0 meson_options.txt: add option "libfuzzer"
This option allows disabling libFuzzer, which is required to run the
fuzzers with Honggfuzz.
2023-03-14 19:47:22 +01:00
Max Kellermann
bc51bc2933 pcm/Normalizer: add method Reset() 2023-03-13 13:54:12 +01:00
Max Kellermann
f547a56b1d pcm/Normalizer: use Traits::long_type 2023-03-13 13:51:27 +01:00
Max Kellermann
1f6637d49a pcm/Normalizer: add constant SHIFT 2023-03-13 13:49:25 +01:00
Max Kellermann
de155a740c pcm/Normalizer: convert peakPos to std::size_t 2023-03-13 13:47:04 +01:00
Max Kellermann
f323fc48d7 pcm/Normalizer: eliminate the local variable slot 2023-03-13 13:45:28 +01:00
Max Kellermann
2ea634c302 pcm/Normalizer: replace the gain array with a simple prev_gain variable 2023-03-13 13:44:45 +01:00
Max Kellermann
c0d38d941a pcm/Normalizer: split the normalization loop
Performance improvement because the ramp code is now moved out of the
hot code path, allowing the compiler to vectorize.
2023-03-13 13:38:19 +01:00
Max Kellermann
d7f2d90fd3 pcm/Normalizer: no in-place editing, separate src/dest parameters
This eliminates the memcpy() call from NormalizeFilter::FilterPCM().
2023-03-13 13:37:49 +01:00
Max Kellermann
8ea9b89321 pcm/Normalizer: use std::span 2023-03-13 13:16:44 +01:00
Max Kellermann
738254b2fc pcm/Normalizer: use SampleTraits 2023-03-13 12:42:37 +01:00
Max Kellermann
fcc9a98cad pcm/Normalizer: use PcmClamp() 2023-03-13 12:42:36 +01:00
Max Kellermann
dcf0a3e475 pcm/Normalizer: remove clipped (only written to, never read) 2023-03-13 12:42:34 +01:00
Max Kellermann
e990d6eecc pcm/Normalizer: make variables more local 2023-03-13 12:42:31 +01:00
Max Kellermann
941636b87b pcm/Normalizer: eliminate local variable ap 2023-03-13 12:31:16 +01:00
Max Kellermann
1298a82f4f pcm/Normalizer: use std::size_t 2023-03-13 12:31:16 +01:00
Max Kellermann
e6fedcbd10 pcm/Normalizer: expose the class, convert functions to methods 2023-03-13 12:25:09 +01:00
Max Kellermann
48c8c7daf5 pcm/Normalizer: move code to ctor/dtor 2023-03-13 12:25:09 +01:00
Max Kellermann
6e5d9d4490 pcm/Normalizer: hard-code the preferences 2023-03-13 12:25:09 +01:00
Max Kellermann
d2f2dde2e1 pcm/Normalizer: eliminate struct CompressorConfig 2023-03-13 12:25:09 +01:00
Max Kellermann
d0dd035075 pcm/Normalizer: use new/delete instead of malloc()/free() 2023-03-13 12:25:09 +01:00
Max Kellermann
7702643e1b pcm/Normalizer: remove Compressor_setHistory(), no resize possible
This feature was never used.
2023-03-13 12:25:09 +01:00
Max Kellermann
984c9c317a pcm/Normalizer: add noexcept 2023-03-13 12:25:09 +01:00
Max Kellermann
2d7068a09d pcm/AudioCompress: convert to C++ 2023-03-13 12:25:01 +01:00
Max Kellermann
d712c3b408 pcm/AudioCompress: fold config.h into compress.c 2023-03-13 11:55:44 +01:00
Max Kellermann
0a623122dc pcm/AudioCompress: add SPDX header 2023-03-13 11:40:46 +01:00
Max Kellermann
68c36c0d3f decoder/dsf: use PackedLE64 instead of DsdUint64 2023-03-12 20:27:05 +01:00
Max Kellermann
f3ebaf8bdd util/ByteOrder: add class PackedLE64 2023-03-12 20:25:49 +01:00
Max Kellermann
c472046cbb decoder/dsdiff: use PackedBE64 instead of DffDsdUint64 2023-03-12 20:22:50 +01:00
Max Kellermann
02296adbba io/FileDescriptor: include cleanup 2023-03-12 20:18:13 +01:00
Max Kellermann
a375f0f160 io/BufferedReader: add method ReadFullT() 2023-03-12 20:15:41 +01:00
Max Kellermann
fb961e89da util/StringCompare: add constexpr 2023-03-12 20:14:23 +01:00
Max Kellermann
3e2bff296f event/SocketEvent: add method GetReadyFlags() 2023-03-12 20:12:15 +01:00
Max Kellermann
cf01db4d08 event/Chrono, ...: relicense to BSD-2 2023-03-12 20:02:54 +01:00
Max Kellermann
08dbb4a69a event/BackendEvents: relicense to BSD-2
These headers contain only trivial integer constants and these are
probably not even copyrightable.
2023-03-12 19:53:03 +01:00
Max Kellermann
b5eff3cecd decoder/plugin: kludge for Android NDK r25c 2023-03-12 19:53:03 +01:00
Max Kellermann
89d66b6100 decoder/ffmpeg: check for DST codec
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1756
2023-03-12 19:39:49 +01:00
Max Kellermann
c53ee41855 decoder/ffmpeg: check for DSD codec
DSD uses a generic demuxer, therefore it does not appear in the
demuxer list.
2023-03-12 19:37:09 +01:00
Max Kellermann
3c798b4907 decoder/ffmpeg: query supported demuxers at runtime 2023-03-12 19:37:09 +01:00
Max Kellermann
78a9c17bc6 decoder/plugin: add "suffixes" function
For decoder plugins like FFmpeg where the supported codecs cannot be
determined at compile time.
2023-03-12 09:17:38 +01:00
Max Kellermann
8b77da545d *: use transparent comparison for std::{map,set} with std::string keys
This avoids many std::string temporaries for lookups.
2023-03-12 09:12:02 +01:00
Max Kellermann
27d3dcf14c CommandLine: use libfmt 2023-03-12 09:02:21 +01:00
Max Kellermann
5388759bd5 db/proxy: require libmpdclient 2.15 or later 2023-03-10 13:45:37 +01:00
Max Kellermann
e927655774 db/proxy: require MPD 0.21 or later 2023-03-10 13:43:49 +01:00
Max Kellermann
3be8375e4f subprojects/sqlite3.wrap: update to 3.41.0-1 2023-03-10 13:35:01 +01:00
Max Kellermann
27ba8c181f pcm/SoxrResampler: require libsoxr 0.1.2 or later 2023-03-10 12:49:57 +01:00
Max Kellermann
1410bcbce9 lib/alsa: require alsa-lib 1.1 or later 2023-03-10 12:49:40 +01:00
Max Kellermann
43b26ee612 {de,en}coder/flac: remove obsolete FLAC_API_VERSION_CURRENT checks
We check the libFLAC version via pkg-config at configure time, no need
to do it again.
2023-03-10 12:43:19 +01:00
Max Kellermann
2c47357991 python/build/libs.py: update WildMidi to 0.4.5 2023-03-09 18:33:21 +01:00
Max Kellermann
7e2538e07a decoder/sidplay: require libsidplayfp (drop support for the original sidplay)
The original sidplay project has been mostly unmaintained for nearly
12 years, and the most recent release was in 2016, while the
libsidplayfp project has been actively maintained all the time.
2023-03-09 18:27:05 +01:00
Max Kellermann
851fcf4823 decoder/gme: require GME 0.6 or later
This allows dropping a few compile-time version checks and we can use
pkg-config to detect the library.
2023-03-09 18:27:05 +01:00
Max Kellermann
63b9fb3d2b event/meson.build: add missing dependency on libio.a 2023-03-09 18:27:05 +01:00
Max Kellermann
a79454f6a6 io/FileDescriptor: fold CreateSignalFD() into the SignalFD constructor 2023-03-09 18:04:58 +01:00
Max Kellermann
b5fbfe9aa6 io/FileDescriptor: fold CreateEventFD() into the EventFD constructor 2023-03-09 17:59:56 +01:00
Max Kellermann
598894211f decoder/ffmpeg: require FFmpeg 4.0 or later 2023-03-08 20:32:35 +01:00
Max Kellermann
dbfd0a833d io/meson.build: move sources to libio_fs.a
Only that one has a dependency on libfs.a (for class AllocatedPath
etc.).
2023-03-07 12:48:47 +01:00
Max Kellermann
d45994268f system/PeriodClock: move to time/ 2023-03-07 12:08:44 +01:00
Max Kellermann
815b248990 */Registry: use constinit 2023-03-07 12:04:16 +01:00
Max Kellermann
333b36f090 output/Registry: add noexcept 2023-03-07 11:57:55 +01:00
Max Kellermann
b18ef61361 output/Registry: rename function 2023-03-07 11:57:36 +01:00
Max Kellermann
86ae45108c output/Finish: fold into Filtered.cxx 2023-03-07 11:54:46 +01:00
Max Kellermann
5ef29c424d output/meson.build: add liboutput_registry.a 2023-03-07 11:53:16 +01:00
Max Kellermann
c8dfb57408 output/meson.build: move OutputPlugin.cxx to liboutput_api.a 2023-03-07 11:52:32 +01:00
Max Kellermann
b773ef3f0f win32/HResult: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
c8f54b3509 lib/pcre/UniqueRegex: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
00d5e6e9c7 lib/avahi/Publisher: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
1132a1c9a7 protocol/ArgParser: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
149d1a2f47 output/shout: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
17f2c0ae88 output/httpd: use libfmt 2023-03-06 20:10:06 +01:00
Max Kellermann
ce0b4d5c19 system/Error: remove unused function FormatSystemError() 2023-03-06 20:10:06 +01:00
Max Kellermann
0c102a8f2f meson.build: add missing libfmt dependencies 2023-03-06 20:10:06 +01:00
Max Kellermann
415de497d3 use more libfmt instead of sprintf() 2023-03-06 19:50:53 +01:00
Max Kellermann
02d108774c test/meson.build: add missing dependencies on libio.a 2023-03-06 19:50:52 +01:00
Max Kellermann
2c66d90626 fs/io: move to separate library
To eliminate the libio.a dependency.
2023-03-06 19:47:29 +01:00
Max Kellermann
e4cdf29951 fs/meson.build: make several dependencies internal 2023-03-06 19:44:34 +01:00
Max Kellermann
b5d224ce22 fs/{StandardDirectory,CheckFile}: move to fs/glue/
Distangle library dependencies.
2023-03-06 19:43:09 +01:00
Max Kellermann
c937a299f7 fs/Charset: assign fs_charset
This got lost 8 years ago in commit 87c88fcb27692a

D'oh!
2023-03-06 19:25:44 +01:00
Max Kellermann
6d4ec8b46f fs/Charset: remove useless log message 2023-03-06 19:20:22 +01:00
Max Kellermann
941f2ca60d pcm/{Traits,Dsd*}: use std::byte 2023-03-06 18:44:20 +01:00
Max Kellermann
7a1b996da9 pcm/Dsd2Pcm: use SampleTraits<SampleFormat::DSD>::SILENCE 2023-03-06 18:30:16 +01:00
Max Kellermann
302a571367 pcm/Buffer: use std::byte 2023-03-06 18:22:12 +01:00
Max Kellermann
ec195acf4f pcm/Interleave: use std::byte 2023-03-06 18:22:10 +01:00
Max Kellermann
8f41e05a39 db/upnp/ContentDirectoryService: use fmt::format_int 2023-03-06 16:45:59 +01:00
Max Kellermann
35b6d65f27 util/Compiler.h: remove unused compiler version check macros 2023-03-06 16:37:46 +01:00
Max Kellermann
e602bcf41e pcm/ReplayGainAnalyzer: remove GCC version checks, assume proper C++17 support 2023-03-06 16:37:45 +01:00
Max Kellermann
8c5ba50840 command/{file,storage}: remove stray "#pragma GCC diagnostic pop" 2023-03-06 16:37:45 +01:00
Max Kellermann
ff239fff4f util/ByteOrder: check only __GNUC__
Assume GCC/clang is recent enough.
2023-03-06 16:37:45 +01:00
Max Kellermann
abdbaf605e player/Thread, ...: assume [[fallthrough]] is supported 2023-03-06 16:29:55 +01:00
Max Kellermann
47b3577d6b util/Compiler.h: remove unused macro gcc_printf 2023-03-06 16:27:47 +01:00
Max Kellermann
2ffc7c2088 io/BufferedOutputStream: remove unused method Format() 2023-03-06 16:27:28 +01:00
Max Kellermann
1f56960c44 util/FormatString: remove unused library 2023-03-06 16:24:51 +01:00
Max Kellermann
dfc5b4972b output/httpd/IcyMetaDataServer: use libfmt 2023-03-06 16:23:43 +01:00
Max Kellermann
18c3c2118d util/Compiler.h: remove unused macros 2023-03-06 16:14:30 +01:00
Max Kellermann
42f6a0441c use [[gnu::...]] attributes 2023-03-06 16:14:15 +01:00
Max Kellermann
3b9aab0684 util/UTF8: fix indent 2023-03-06 16:12:09 +01:00
Max Kellermann
7a46c57ef3 tag/Type: require C++ 2023-03-06 15:28:44 +01:00
Max Kellermann
118b76a8f1 db/Interface, ...: forward-declare TagType 2023-03-06 15:25:30 +01:00
Max Kellermann
a302d34f6d tag/Names: convert to C++ 2023-03-06 15:16:33 +01:00
Max Kellermann
148aca23be use SPDX IDs, replacing the long copyright headers 2023-03-06 14:59:48 +01:00
Max Kellermann
8ab2722300 python/build/meson.py: keep Meson from executing Android-x86 test binaries 2023-03-06 14:21:37 +01:00
Max Kellermann
bd25528ca3 python/build/meson.py: remove unused import 2023-03-06 14:17:44 +01:00
Max Kellermann
9f02d8978b build/python/cmake: set CMAKE_C_FLAGS_INIT, not CMAKE_C_FLAGS
According to
https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS_INIT.html
the _INIT variables should be set in the toolchain file.
2023-03-06 14:15:57 +01:00
Max Kellermann
7e51d1dba0 build/python/cmake: set CMAKE_OSX_SYSROOT on macOS 2023-03-06 14:15:23 +01:00
Max Kellermann
4d4755352d build/python/cmake: add "env" parameter 2023-03-06 14:13:08 +01:00
Max Kellermann
0360f79e6f build/python/build/project.py: add "lazy" parameter to make_build_path() 2023-03-06 14:10:10 +01:00
Max Kellermann
6d8f92c185 build/python/build/project.py: raise exception on regex mismatch 2023-03-06 14:07:59 +01:00
Max Kellermann
c989327eb0 python/build/zlib.py: use autotools to be more portable
Right now, zlib is only built for Windows, but we may eventually
changed that, so don't hard-code `win32/Makefile.gcc`.
2023-03-06 13:48:40 +01:00
Max Kellermann
22eccaa64f python/build/autotools.py: use toolchain.arflags 2023-03-06 13:33:11 +01:00
Max Kellermann
740cc8ce49 python/{cmake,autotools}: build in verbose mode
Make sure all the gory details are visible in CI logs.
2023-03-06 13:32:48 +01:00
Max Kellermann
70eafba0d4 python/build/autotools.py: dump config.log on configure error
For better error logs on CI.
2023-03-06 13:32:42 +01:00
Felix Hädicke
79fb9834d9 python/makeproject: do not use hard-code absolute path to make 2023-03-06 13:32:37 +01:00
Felix Hädicke
146db77025 python/makeproject: set appropriate build jobs count depending on the number of CPUs 2023-03-06 13:32:32 +01:00
Felix Hädicke
e6d607fef3 build/python: do not use absolute path for tar 2023-03-06 13:10:03 +01:00
Max Kellermann
ca46992d3e build/python/build/project.py: lazy tarball extraction 2023-03-06 13:07:17 +01:00
Max Kellermann
c83ab0dc58 unix/SignalHandlers: shut down if parent process dies in --no-daemon mode
By default, if the parent of a process dies, the process gets SIGHUP
and is supposed to shut down.  This however doesn't work for MPD,
because MPD redefines SIGHUP with a different meaning (like most
daemons do).

To work around this, we configure the kernel to send SIGTERM instead
of SIGHUP.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1706
2023-03-06 13:00:07 +01:00
Max Kellermann
d9952b9054 CommandLine: hard-code daemon=false if ENABLE_DAEMON is not set 2023-03-06 13:00:06 +01:00
Max Kellermann
04e60d67ae command/playlist: allow range in "playlistmove"
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1689
2023-03-06 12:01:45 +01:00
Max Kellermann
f4adbdbe31 python/build/libs.py: update FFmpeg to 6.0 2023-03-06 10:13:12 +01:00
Max Kellermann
484b820dfc python/build/libs.py: disable more unused FFmpeg features 2023-03-06 10:06:39 +01:00
Max Kellermann
9bcba41cd6 Merge branch 'pipewire-lock' of https://github.com/ncfavier/MPD
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1753
2023-03-06 10:06:03 +01:00
Naïm Favier
eabc487e59
output/PipeWire: lock thread loop in SendTag 2023-03-06 10:03:14 +01:00
Max Kellermann
5c5e522fcd output/jack: remove DLL support
This effectively reverts commit 0f02bbc2fe4fa5e3 which was a horrible
kludge for JACK support on Windows.  Maintaining this kludge doesn't
seem worth the trouble (the JACK version was never updated), and
apparently nobody uses this.
2023-03-06 08:10:00 +01:00
Max Kellermann
f687028c87 output/PipeWire: use class StaticVector 2023-03-06 08:09:07 +01:00
Max Kellermann
05f0b9c29c python/build/libs.py: update CURL to 7.88.1 2023-03-06 07:56:08 +01:00
Max Kellermann
4a8ec20858 python/build/libs.py: update OpenSSL to 3.0.8 2023-03-06 07:56:08 +01:00
Max Kellermann
c5e36a7dd8 subprojects: update expat to 2.5.0-2 2023-03-06 07:51:02 +01:00
Max Kellermann
d5fafa1340 output/PipeWire: map tags "Date" and "Comment" 2023-03-06 07:48:25 +01:00
Max Kellermann
e8994b43a0 output/PipeWire: convert tag mapping to array 2023-03-06 07:44:06 +01:00
Max Kellermann
6ada2c9c3f lib/curl/Request: add method GetEasy() 2023-03-05 08:50:39 +01:00
Max Kellermann
bbf190fc42 lib/curl/Multi: add noexcept 2023-03-05 08:49:20 +01:00
Max Kellermann
963ff1997d lib/curl/Easy: add methods SetXferInfoFunction(), SetMimePost() 2023-03-05 08:47:40 +01:00
Max Kellermann
5c2a576546 io/BufferedReader: add missing include 2023-03-05 08:43:41 +01:00
Max Kellermann
452400b7ef net/SocketAddress: remove __cpp_lib_span checks 2023-03-05 08:41:33 +01:00
Moviuro
20a5276560
doc/mpd.1.rst: add documentation for --systemd
This switch was introduced in ce77b148d927c3012d04f629266476c8ffeb183a
2023-03-01 09:55:27 +01:00
Max Kellermann
c94eee6199 Merge branch 'master' of https://github.com/lerenwe/MPD-Windows-With-Libsample 2023-02-23 14:44:06 +01:00
Sweet Blue
2a75222fe2
Added libsamplerate to win32 build script 2023-02-23 14:26:32 +01:00
Sweet Blue
7d9d173c9f
Updated libs.py to integrate libsamplerate 0.2.2 2023-02-23 14:25:11 +01:00
Dave Hocker
f248fe2dec Resolve deprecation warnings by replacing use of sprintf with FmtBuffer 2023-02-06 11:56:49 +01:00
Brad Smith
e0df0b6d74 oss: Remove use of the soundcard.h header, OpenBSD no longer uses OSS 2023-02-03 18:38:20 -05:00
Sean DuBois
a41414e0e0 Decoder/FluidSynth: Allow gain to be adjusted 2023-02-01 12:00:19 -05:00
Max Kellermann
f1cea1f152 util/IntrusiveHashSet: add unlink(), is_linked() 2023-01-31 13:07:26 +01:00
Max Kellermann
02f5698868 event/Loop: remove unnecessary include
Not used since a3b32819b1578a261c1cc40cc384c8af3ed8fb0f
2023-01-31 13:04:25 +01:00
Bryan Waite
e25816fc05
Provide alternative ways to check for
https://superuser.com/questions/287371/obtain-kernel-config-from-currently-running-linux-system/287372#287372
2023-01-31 08:21:39 +00:00
Max Kellermann
5b07c8fc6c util/CharUtil: add IsLowerAlphaNumericASCII() 2023-01-29 09:39:40 +01:00
Max Kellermann
b45afd1cab util/StringBuffer: add constexpr 2023-01-29 09:38:40 +01:00
Max Kellermann
8b73257a86 storage/meson.build: move MemoryDirectoryReader.cxx to storage_api.a
This library is required by the plugins, so this fixes a dependency issue.
2023-01-29 08:21:58 +01:00
Max Kellermann
def6fffcf1 event/Loop: fixup for NO_FINE_TIMER_EVENT 2023-01-29 08:07:03 +01:00
Max Kellermann
78b13577ef test/net/TestIPv[46]Address: add more tests 2023-01-28 08:15:41 +01:00
Max Kellermann
1f5d50ccce lib/curl/Setup: include cleanup 2023-01-28 08:06:10 +01:00
Max Kellermann
ebf65572dd util/ByteOrder: remove unnecessary operator=
The compiler can just use the uint32_t constructor instead.  This was
redundant code.
2023-01-28 07:48:03 +01:00
Max Kellermann
c30c293d6f input/async: check for errors in Seek()
Fixes a busy loop in BufferingInputStream::RunThreadLocked() because
the method never learns that seeking is ignored, even though the HTTP
stream is already broken and can never be read; nobody cared to check
for errors.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1727
2023-01-28 07:44:59 +01:00
Max Kellermann
9ee1be6fba command/database: add missing include for UINT_MAX 2023-01-23 15:50:49 +01:00
Max Kellermann
76177dbc79 win32/HResult: use [[gnu::const]] 2023-01-23 15:35:36 +01:00
Max Kellermann
6cc532c9a0 win32/HResult: remove unused function FormatHResultError() 2023-01-23 15:35:36 +01:00
Max Kellermann
3cc770a00b remove obsolete Boost dependency
Boost makes building a piece of software much more difficult than
necessary.  It's a huge library, and just uncompressing it takes a
considerable amount of time. MPD only used a tiny fraction of it, yet
its header bloat made the MPD build very slow.  Locating Boost was
difficult due to its arcane build system and its resistance to use
pkg-config; it's always a special case.  MPD could never use features
of newer Boost versions because Linux distributions always shipped old
Boost versions.  Boost made everything complicated and slow.

So, finally, after getting rid of GLib (commit ccdb94b06c), switching
to C++ and using Boost (commit 0801b3f495a), we've finally get rid of
it 8 years later.

Unfortunately, I had to reimplement parts of it along the way
(e.g. IntrusiveList).  Kind of NIH, but on the other hand, compiling
MPD has become much easier for users.
2023-01-23 15:06:58 +01:00
Max Kellermann
7ef0bfbdf1 event/meson.build: disable Boost 2023-01-23 14:58:38 +01:00
Max Kellermann
bafde1900b lib/nfs/Manager: use IntrusiveList instead of boost::intrusive::set
MPD usually has only one NFS connection, maybe two, so managing them
in a tree seems like overkill, and since we want to get rid of Boost
anyway...
2023-01-23 14:58:09 +01:00
Max Kellermann
5844242cfb input/cache/Manager: use IntrusiveHashSet instead of boost::intrusive::set 2023-01-23 14:19:22 +01:00
Max Kellermann
7e7cdf73b9 input/InputStream: add method GetUriView() 2023-01-23 14:15:18 +01:00
Max Kellermann
5ca74acd8d input/InputStream: allow emplacing the URI 2023-01-23 14:15:18 +01:00
Max Kellermann
cd2aaac0c2 output/osx: fix typo 2023-01-23 14:15:18 +01:00
Max Kellermann
ff8a7225fc output/osx: change type to std::size_t to fix -Wc++11-narrowing 2023-01-23 14:06:56 +01:00
Max Kellermann
c6eac285ea test/util/TestRingBuffer: add "U" literal suffix to work around -Wsign-compare 2023-01-23 14:05:55 +01:00
Max Kellermann
d0be122fc6 output/osx: use class RingBuffer instead of boost::lockfree::spsc_queue 2023-01-23 13:55:50 +01:00
Max Kellermann
01e5a7b1b5 output/wasapi: use class RingBuffer instead of boost::lockfree::spsc_queue 2023-01-23 13:44:54 +01:00
Max Kellermann
0b42018377 output/PipeWire: use class RingBuffer instead of boost::lockfree::spsc_queue 2023-01-23 13:44:54 +01:00
Max Kellermann
7cb6c70bc2 output/alsa: use class RingBuffer instead of boost::lockfree::spsc_queue 2023-01-23 13:44:54 +01:00
Max Kellermann
f31ae7c556 util/RingBuffer: replacement for boost::lockfree::spsc_queue 2023-01-23 13:44:54 +01:00
Max Kellermann
5728c514d1 output/wasapi: use std::hardware_destructive_interference_size 2023-01-23 13:44:53 +01:00
Max Kellermann
debac0dfd4 win32/ComWorker: use std::queue/Mutex/Cond instead of boost::lockfree::spsc_queue/WinEvent 2023-01-23 13:25:07 +01:00
Max Kellermann
80b1f49af7 lib/dbus/AppendIter: add missing include 2023-01-22 12:29:54 +01:00
Max Kellermann
868958e159 util/IntrusiveHashSet: fix find_if() concept 2023-01-22 12:25:55 +01:00
Max Kellermann
52af03a5a6 util/IntrusiveHashSet: implement remove_and_dispose_if() with constant_time_size 2023-01-22 12:24:50 +01:00
Max Kellermann
7475e971bc util/IntrusiveList: remove_and_dispose_if() returns the number of removed items 2023-01-22 12:24:43 +01:00
Max Kellermann
c65b1fee8d util/IntrusiveHashSet: check key equivalence in remove_and_dispose_if() 2023-01-22 12:24:41 +01:00
Max Kellermann
e2abade6aa util/IntrusiveList: add postfix operator++ 2023-01-22 12:24:33 +01:00
Max Kellermann
57673136d8 util/IntrusiveHashSet: add method expire_find_if() 2023-01-22 12:24:30 +01:00
Max Kellermann
49e122a81d util/IntrusiveHashSet: add method remove_and_dispose_if(key) 2023-01-22 12:24:23 +01:00
Max Kellermann
74976d3199 event: make FineTimerEvent optional
Several applications don't need it, so let's eliminate the code from
the executable.
2023-01-22 12:21:46 +01:00
Max Kellermann
a750e4afa7 event/Loop: move code to GetEarlierTimeout() 2023-01-22 12:19:07 +01:00
Max Kellermann
c122e990a3 Merge branch 'master' of https://github.com/faceless2/MPD 2023-01-17 19:03:49 +01:00
Max Kellermann
b1422fbda4 release v0.23.12
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmPG4OcNHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFElGQD/4lXFixr2fJuAWFYyFT4ebr2w7sPyhXwjlt5uCL
 HTaMxTgQbhMmkHbGEO96UbF7gROGfq+dyvYTEmjWcVPTr/US3M8/mjT9T/DCLj6+
 kF7rZM5ft6npqVxqikg/TQcUgoiSsgfI7dEK/vcXELPyx78bCaq0M0sd2GZvwiiM
 vK9cxxDJ/RkF2dtfXRfGTJlihgQxaiuBZx8Bi3wJjbjvi/Lg85cu3iot9zFy5iDN
 gNzC39dnPYv261lAT/LLNpzLYQzIFE5ul+8ucRNPo+mMS/odSPRdL9XYFDtarsqP
 3Va83DChg7S6/GWfDeW81mQYPDuZ+1rPqbV5zEGimPsDWP9RugzPpZiFJlZrh8w7
 MJp66RYxUWQpracRZIW4zMRiSzGSI3OXbvhx6qBmsn1CuQ19TkovWuRleD4lpfFv
 dFzKHrdatJivM3xvq6CSg8ws+Q6f/j5sw1gzfvOofPlpybtvIrCvlvw78sKLW5n1
 Ecwc+xN38bIVL3E2Ae6zeYQwArpB4+gKT3Wb+r3bjXz7YQYpETI3IbX0vixbl8pP
 9O4ZKot/khOCaQBiZ5hHmiDmF5kxofLnJE4qgGX/c87ZaMUsu7hoKzksy9v7Z9wj
 PNTshhWk1WrSwM1JnVjD5Ahz+Oe43UsKsGZ8Kturbuu+61uTX4QcmYpbaNilGnwk
 J0cLyw==
 =MW7q
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.12'

release v0.23.12
2023-01-17 18:58:04 +01:00
Mike Bremford
b96e44b362 Unlike album, artist and albumartist, title and composer were not used as a fallback
when titlesort and composersort were specified but unavailable - this patch fixes that.
2023-01-09 18:15:44 +00:00
Max Kellermann
8a7b7dffec Merge branch 'v0.23.x' 2023-01-06 08:12:38 +01:00
latex
7774e78864 openmpt: add at_end option 2023-01-06 03:18:36 +01:00
Max Kellermann
d7de8b1453 Merge branch 'iss-1546' of https://github.com/sp1ff/MPD 2022-12-29 08:37:25 +01:00
Max Kellermann
3242943cd1 doc/protocol.rst: fix reference target 2022-12-18 08:30:25 +01:00
Mike Bremford
6adff85fd6 Added "searchcount" command, a case-insensitive "count"
The `count` command isn't case-insensitive.  This adds `searchcount`
which is a case-insensitive version of `count`.
2022-12-18 08:29:14 +01:00
Alex
8b1ff3f005
build: harden build.yml permissions
This PR adds explicit [permissions section](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions) to workflows. This is a security best practice because by default workflows run with [extended set of permissions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) (except from `on: pull_request` [from external forks](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)). By specifying any permission explicitly all others are set to none. By using the principle of least privilege the damage a compromised workflow can do (because of an [injection](https://securitylab.github.com/research/github-actions-untrusted-input/) or compromised third party tool or action) is restricted.
It is recommended to have [most strict permissions on the top level](https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions) and grant write permissions on [job level](https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs) case by case.

Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-12-09 11:28:26 +01:00
Max Kellermann
756621c6e4 neighbor/meson.build: add missing dependency on libfmt 2022-12-01 15:57:28 +01:00
Max Kellermann
7e2ab1fd53 lib/yajl/meson.build: add missing dependency on libfmt 2022-12-01 15:50:34 +01:00
Max Kellermann
c7a0597fe7 util/Intrusive*: add C++20 concept checks 2022-12-01 15:43:51 +01:00
Max Kellermann
253d551684 lib/dbus/meson.build: add missing dependency on libfmt 2022-12-01 15:43:51 +01:00
Max Kellermann
00b7535cf1 util/Concepts: compatibility wrapper for std::predicate 2022-12-01 15:11:27 +01:00
Max Kellermann
5945877313 util/IntrusiveHashSet: add missing Cast()/ToHook() functions to IntrusiveHashSetMemberHookTraits 2022-12-01 15:10:42 +01:00
Max Kellermann
fe3e1d31bf util/IntrusiveHashSet: remove unused type alias "ListHookTraits" 2022-12-01 15:10:38 +01:00
Max Kellermann
65f1cafa43 util/IntrusiveHashSet: add method find_if() 2022-12-01 15:10:32 +01:00
Max Kellermann
d9b1f2fefa net/SocketAddress: add method HasPort() 2022-12-01 15:10:25 +01:00
Max Kellermann
e3ef0929f1 util/IntrusiveHashSet: add const overloads 2022-12-01 15:10:20 +01:00
Max Kellermann
8860962e09 util/IntrusiveHashSet: make several methods const 2022-12-01 15:10:13 +01:00
Max Kellermann
f13b8f669d util/IntrusiveList: simplify ToHook() overload with const_cast 2022-12-01 15:10:09 +01:00
Max Kellermann
fa58db798b lib/fmt/RuntimeError: new library
Replacing FormatRuntimeError().
2022-11-29 14:10:34 +01:00
Max Kellermann
45b13fc2a6 util/OptionParser: move to cmdline/
This library will depend on libfmt, and libutil shouldn't depend on
any library.
2022-11-29 11:32:16 +01:00
Max Kellermann
cf3f3a7750 lib/pulse/Error: use std::system_error 2022-11-29 09:56:47 +01:00
Max Kellermann
e455b93fac lib/nfs/Connection: use class NfsClientError 2022-11-29 09:45:25 +01:00
Max Kellermann
cf762f2a9d lib/icu/Error: std::system_error with UErrorCode 2022-11-29 09:31:48 +01:00
Max Kellermann
8ad0d919b1 lib/icuConverter, ...: use FmtBuffer() and FmtErrno() 2022-11-29 09:09:11 +01:00
Max Kellermann
4b5c8d1f3e mixer/meson.build: split libmixer_api from libmixer_glue 2022-11-29 09:09:11 +01:00
Max Kellermann
eb6c649d47 lib/fmt/SystemError: add concept check to work around ambiguous overloads 2022-11-29 09:09:10 +01:00
Max Kellermann
f2b025ca6c lib/alsa/meson.build: add dependency on libpcm_basic
For PcmExport::CalcInputSampleRate().
2022-11-29 09:09:10 +01:00
Max Kellermann
4328a6f77d lib/fmt/ToBuffer: fix FMT_VERSION check 2022-11-29 09:09:10 +01:00
Max Kellermann
97a6851525 lib/curl/Error: std::system_error with CURLcode 2022-11-29 06:33:32 +01:00
Max Kellermann
846d7dc317 lib/curl/Error: rename header to HttpStatusError.hxx 2022-11-29 06:33:32 +01:00
Max Kellermann
f62d61f088 lib/fmt/ToBuffer: add missing template parameters 2022-11-29 06:33:32 +01:00
Max Kellermann
1f33ac3e98 lib/upnp/Error: wrap libupnp errors in std::system_error 2022-11-29 00:32:48 +01:00
Max Kellermann
ed08a4bd58 lib/fmt/ToBuffer: use iterator instead of pointer 2022-11-28 23:10:25 +01:00
Max Kellermann
40d0828ccd util/StringBuffer: add non-const iterator 2022-11-28 23:10:01 +01:00
Max Kellermann
66029c405f system/FmtError: move to lib/fmt/ 2022-11-28 23:09:27 +01:00
Max Kellermann
7d8c076e06 lib/fmt/ToBuffer: include fmt/format.h on libfmt 7 to fix linker error 2022-11-28 23:03:52 +01:00
Max Kellermann
05dcac55f9 lib/fmt: add meson.build 2022-11-28 22:18:46 +01:00
Max Kellermann
2aa42d2647 lib/fmt/ToBuffer: new library 2022-11-28 22:18:46 +01:00
Max Kellermann
dc8e0c9c5c archive/zzip: add missing include 2022-11-28 22:18:45 +01:00
Max Kellermann
96ae659fdf system/FmtError: new library
Replaces the Format*() functions in system/Error.hxx.
2022-11-28 21:56:12 +01:00
Max Kellermann
124e75c286 thread/Thread, fs: add missing WIN32 includes 2022-11-28 21:56:11 +01:00
Max Kellermann
25da798e7a system/Clock: compile only on Windows 2022-11-28 21:16:49 +01:00
Max Kellermann
88d5347d94 Log, client/Response, io/BufferedOutputStream: remove unnecessary libfmt include 2022-11-28 20:44:48 +01:00
Max Kellermann
7f3868727b Log, client/Response, io/BufferedOutputStream: drop support for libfmt < 7
Remove some compatibility code.
2022-11-28 20:17:16 +01:00
Max Kellermann
b09a776a26 .travis.yml: remove obsolete file
We've migrated to GitHub actions in commit
c13911b171b96bba509e1738602363120daea6a8 a year ago
2022-11-28 20:17:16 +01:00
Max Kellermann
3103e8d719 fs/StandardDirectory: update #ifdef for GetEnvPath()
Fixes regression from a38eabc8bc8e5bda084025158221179c29640bea
2022-11-28 20:17:16 +01:00
Max Kellermann
cfbd751742 fs/StandardDirectory: pass Path to IsValidDir() 2022-11-28 18:48:10 +01:00
Max Kellermann
a38eabc8bc fs/StandardDirectory: move code to GetExistingEnvDirectory() 2022-11-28 18:43:45 +01:00
Max Kellermann
9669ea6a12 fs/StandardDirectory: add noexcept 2022-11-28 18:27:06 +01:00
Max Kellermann
863a28daa3 fs/StandardDirectory: eliminate global variable "home_prefix" 2022-11-28 18:27:06 +01:00
Max Kellermann
ea5bcfed8b fs/StandardDirectory: pass std::string_view to ParseConfigLine() 2022-11-28 17:11:17 +01:00
Max Kellermann
f6f3c4c25b fs/StandardDirectory: pass const string to ParseConfigLine() 2022-11-28 17:07:29 +01:00
Max Kellermann
8fe29f5728 release v0.23.11
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmOE2gINHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEiugD/9OKEBR9tfrJvtVGuO2INtaMeAzlZ9swFYCkphF
 i2R7H9/9E0AvtgyFi/6EDNgFCBbnUzSIGbtdc78EwHE6GxeK/Q9G1fo9AC+6I8Ww
 2ScEV9NKIMGTbsRvoomKnGZWpvNTpadPlLa02bckXpKK3wQUPhLb8RAH3newZ0RC
 OXs+mzSRReRKpjUBxZsI+6f+aajM6/PoiOmBbrNbYbsSlkpKtLeW8ptkQxPME12B
 QD9e7yf9ZndYfoHJdmmPxfvIGIEDATCs8MzY8tFUYkhdbEk0C0aRZQTODQS3DATp
 0wrmlJzmceiN2nhKjthg1bvC+jobPywIuDZdrEuyFumN/EZxldKAUCezduV+Dohm
 UPkQp5yiSTZRZVYQMEOSW6cMndC7URFrtn643+jV7SGkTmmV6nVOyg4e9GR1BakT
 rY0nZGr7dwEInODkA5lXMhph3u8aZa2Mfo5B8m2aloGVHYOX1t3bH07ym5oJiviq
 eiQx/bMpaS6ECCSnmHPGDl0NHHWDiPGv96EyPO2N9oeWiNuZz/Fla0N99Mi/JbVI
 EpSHF89F+bfiw5qIeet93ZrXjwQjMuC6zofZ1jbVFek2eKszCZSNdx233VLz170G
 edyN5Vxy3r24YBy/nrZVXPRxsj65KOxF1TZ9SzHKmfnuU45a+JZjZuWz5yedPn2/
 3fy7oA==
 =eLEd
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.11'

release v0.23.11
2022-11-28 17:00:38 +01:00
Michael Herstine
1adc2c0c51 playlist_load_into_queue: log on failure to load song.
Log at level error when failing to load a song. Limit the number
of log messages produced to avoid flooding the log file when attempting
to load a large, broken playlist.

Closes 
2022-11-26 08:28:10 -08:00
Max Kellermann
a3b32819b1 event/Loop: split InjectBreak() from Break() 2022-11-22 22:30:12 +01:00
Max Kellermann
a57cf443ed event/Loop: set "again" in AddDefer() only if HAVE_THREADED_EVENT_LOOP
Only AddDefer()/AddIdle() calls from within DeferEvents are relevant.
2022-11-22 21:40:52 +01:00
Max Kellermann
d0d095cbcd util/IntrusiveHashSet: rename "slot" to "bucket" 2022-11-22 21:40:52 +01:00
Max Kellermann
3239fce5c1 util/IntrusiveHashSet: add remove_and_dispose_if() 2022-11-22 21:40:11 +01:00
Max Kellermann
200b770104 util/IntrusiveHashSet: add for_each() 2022-11-22 21:40:04 +01:00
Max Kellermann
3aa959eda7 util/IntrusiveHashSet: add erase_and_dispose() 2022-11-22 21:39:40 +01:00
Max Kellermann
72c047f4f0 util/IntrusiveHashSet: add hash_function(), key_eq() 2022-11-21 09:10:44 +01:00
Max Kellermann
c71958af4b input/async: pass std::span to AppendToBuffer() 2022-11-17 06:15:58 +01:00
Max Kellermann
ce13d82657 input/async: use std::byte instead of uint8_t 2022-11-17 06:15:19 +01:00
Max Kellermann
73dc8ff6bd lib/nfs/FileReader: pass std::span to OnNfsFileRead() 2022-11-17 06:15:16 +01:00
Max Kellermann
3278ad2ed8 storage/State: remove obsolete Boost compiler warning workaround 2022-11-17 05:32:29 +01:00
Max Kellermann
2e453ef58a storage/State: use std::hash() instead of boost::crc
Also eliminate the useless std::set.
2022-11-17 05:28:53 +01:00
Max Kellermann
a5d04be21f storage/State: add noexcept 2022-11-17 05:19:11 +01:00
Max Kellermann
9467df526c song/StringFilter: add enum Position
Replaces two conflicting bools.
2022-11-15 21:55:55 +01:00
Max Kellermann
9ca75589c0 song/StringFilter: simplify GetOperator() 2022-11-15 21:55:55 +01:00
Max Kellermann
c158abe87c lib/icu/Compare: use StringIsEqualIgnoreCase() 2022-11-15 21:13:01 +01:00
Max Kellermann
53530bd1d5 lib/icu/Canonicalize: convert all punctuation to ASCII
To make tag matching easier.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1669
2022-11-15 21:04:16 +01:00
Max Kellermann
d7f545721b lib/icu/Canonicalize: use unorm2_normalize() instead of u_strFoldCase()
unorm2_normalize() can case-fold as well, plus it applies Unicode
normalization which MPD should do for proper string comparisons.
2022-11-15 20:53:29 +01:00
Max Kellermann
8b72cb64b2 lib/icu/CaseFold: rename to IcuCanonicalize() and add flag parameter
Prepare for adding more transformations.
2022-11-15 20:53:04 +01:00
Max Kellermann
852df2239e lib/icu/Transliterator: pass std::basic_string_view<UChar> to constructor 2022-11-15 20:53:03 +01:00
Max Kellermann
5a1fbe60af test/TestStringFilter: new unit test 2022-11-15 20:52:53 +01:00
Max Kellermann
88e33b7b32 test/TestTagSongFilter: initialize ICU 2022-11-15 20:51:59 +01:00
Max Kellermann
264b3f8543 lib/icu/Collate: clear the global variable in IcuCollateFinish()
To allow repeated init/finish cycles.
2022-11-15 20:48:50 +01:00
Max Kellermann
ac2bce8b7b lib/icu/Transliterator: add missing include 2022-11-15 17:07:54 +01:00
Max Kellermann
9f3faaf3c4 lib/icu/Transliterator: wrapper for UTransliterator 2022-11-15 01:09:27 +01:00
Max Kellermann
7be39e07e1 lib/icu/Normalize: wrapper for unorm2_normalize() 2022-11-15 00:49:25 +01:00
Max Kellermann
154fb4317f lib/icu/CaseFold: move low-level wrapper to FoldCase.cxx 2022-11-15 00:46:58 +01:00
Max Kellermann
aad5210820 lib/icu/CaseFold: use ToStringView() 2022-11-15 00:36:47 +01:00
Max Kellermann
7c4fca0ae1 util/SpanCast: add ToStringView() template 2022-11-15 00:36:28 +01:00
Max Kellermann
1a6ec716ef lib/icu/Converter: add noexcept 2022-11-15 00:28:41 +01:00
Max Kellermann
0b22cc962d Merge branch 'private_users' of https://github.com/bluca/MPD 2022-11-14 23:53:43 +01:00
Max Kellermann
51769c40d8 util/IntrusiveSortedList: new class 2022-11-13 09:08:36 +01:00
Max Kellermann
85ab89a08b util/IntrusiveHashSet: add missing typename (to make clang happy) 2022-11-13 08:40:53 +01:00
Max Kellermann
a43062c575 RemoteTagCache: use IntrusiveHashSet instead of boost::intrusive::unordered_set 2022-11-13 08:39:04 +01:00
Max Kellermann
c943e27d51 util/IntrusiveHashSet: new class
Incomplete draft implementation, just enough methods for current
needs.
2022-11-13 08:38:53 +01:00
Max Kellermann
fb5d77158a util/IntrusiveList: add enum LinkMode
Compile-time code simplification.
2022-11-13 08:15:47 +01:00
Max Kellermann
3023816491 subprojects/.gitignore: ignore liburing 2022-11-12 12:40:44 +01:00
Max Kellermann
51e17e89f4 subprojects: add liburing.wrap 2022-11-12 12:30:13 +01:00
Max Kellermann
98c24d1a32 Merge branch 'v0.23.x' 2022-11-12 12:29:21 +01:00
Max Kellermann
f1dc1af85d util/IntrusiveList: use const_cast to eliminate duplicate HookTraits functions
I hate const_cast, but what I hate more is duplicate code.  Sigh.
2022-11-12 08:45:24 +01:00
Max Kellermann
7b3d870516 util/IntrusiveForwardList: remove unnecessary initializer from hook 2022-11-11 21:14:52 +01:00
Max Kellermann
963ff846ff test/util/TestIntrusiveForwardList: new unit test 2022-11-11 21:13:41 +01:00
Max Kellermann
48c4081ba1 test/util/TestIntrusiveList: remove unused code 2022-11-11 21:11:22 +01:00
Max Kellermann
970ccf043b util/SortList: enable the std::predicate kludge for macOS as well
Sigh.
2022-11-11 19:30:58 +01:00
Max Kellermann
0c92c12adf Merge branch 'v0.23.x' 2022-11-11 19:27:22 +01:00
Max Kellermann
29143dec87 util/SortList: kludge for Android NDK compatibility 2022-11-11 19:17:13 +01:00
Max Kellermann
0fd4c14043 db/simple/Directory: re-add Song.hxx to fix clang build failure 2022-11-11 19:13:01 +01:00
Max Kellermann
81e1f87e8c db/simple/{Directory,Song}: use IntrusiveList instead of boost::intrusive::list 2022-11-11 19:08:22 +01:00
Max Kellermann
a448d04d46 util/SortList: library which sorts linked lists 2022-11-11 19:03:39 +01:00
Max Kellermann
60e640af5a util/IntrusiveList: add single-item splice() overload 2022-11-11 18:29:50 +01:00
Max Kellermann
df15c418c7 util/IntrusiveList: fix swap() implementation if second list is empty 2022-11-11 18:29:50 +01:00
Max Kellermann
04ab8ae27b util/IntrusiveList: add type aliases value_type, pointer, reference 2022-11-11 17:15:20 +01:00
Max Kellermann
b4a64af15e util/IntrusiveList: constant_time_size is a template argument, not a variable 2022-11-11 17:15:16 +01:00
Max Kellermann
1ccfd1fb67 test/util/TestIntrusiveList: simplify tests 2022-11-11 16:41:24 +01:00
Max Kellermann
838c057231 util/IntrusiveList: use auto
Fixes typos in the const_iterator return types, and fixes returning
references to stack values.
2022-11-11 16:33:49 +01:00
Max Kellermann
af544bb16f util/IntrusiveList: fix typos 2022-11-11 10:11:42 +01:00
Max Kellermann
84fd401d21 util/IntrusiveList: add method splice() 2022-11-11 10:05:20 +01:00
Max Kellermann
b78d6c9dd7 test/util/TestIntrusiveList: add tests for reverse iterators 2022-11-11 09:53:00 +01:00
Max Kellermann
b5d224496f util/IntrusiveList: iterators are bidirectional 2022-11-11 09:20:09 +01:00
Max Kellermann
78d8b5f73c util/OptionalCounter: add operator+= and operator-= 2022-11-10 16:55:04 +01:00
Max Kellermann
5670d98c54 util/IntrusiveList: move code to IntrusiveListNode::Connect() 2022-11-10 16:52:34 +01:00
gd
440c676be2 EventLoop: added assert(IsInside()) in Insert(CoarseTimerEvent &) and AddIdle(DeferEvent &)
Like AddDefer(DeferEvent &), Insert(FineTimerEvent &), these methods don't lock to update EventLoop::again
2022-11-10 15:35:14 +01:00
Max Kellermann
e820222c5b lib/nfs/Manager: use IntrusiveForwardList instead of boost::intrusive::slist 2022-11-10 12:08:23 +01:00
Max Kellermann
1786eef8e6 util/IntrusiveForwardList: new class 2022-11-10 12:07:59 +01:00
Max Kellermann
5f2fa1dbe3 RemoteTagCache: use IntrusiveList instead of boost::intrusive::list 2022-11-10 12:06:00 +01:00
Max Kellermann
77d257de27 input/cache: use IntrusiveList instead of boost::intrusive::list 2022-11-10 12:05:09 +01:00
Max Kellermann
89d950e9a7 output/httpd: use IntrusiveList instead of boost::intrusive::list 2022-11-10 12:02:54 +01:00
Max Kellermann
4041d87c34 lib/nfs/Cancellable: use IntrusiveList instead of boost::intrusive::list 2022-11-10 12:01:11 +01:00
Max Kellermann
b3c5e6a3cc event/Loop: use IntrusiveList instead of boost::intrusive::list 2022-11-10 11:57:57 +01:00
Max Kellermann
1da8faa285 client/List: use IntrusiveList instead of boost::intrusive::list 2022-11-10 11:08:11 +01:00
Max Kellermann
988f5d1b5d util/StringSplit: add SplitWhile() 2022-11-09 19:23:19 +01:00
Max Kellermann
3ab3d5555e util/StringSplit: reimplement without std::distance()
Avoid including <iterator>.
2022-11-09 19:23:10 +01:00
Max Kellermann
2e5d46c399 util/StringSplit: add constexpr 2022-11-09 19:23:05 +01:00
Max Kellermann
7600ad7cac util/StringSplit: add Partition() 2022-11-09 19:22:54 +01:00
Max Kellermann
485ad583a0 util/CharUtil: add IsLowerAlphaNumericASCII() 2022-11-09 19:21:43 +01:00
Max Kellermann
bbc82a9892 io/FileDescriptor, net/SocketDescriptor: make lots of methods "const"
Only the file descriptor value itself is const, but the file itself
may be readable/writable.
2022-11-09 19:19:20 +01:00
Max Kellermann
69596106d3 io/FileDescriptor: add pread() wrapper 2022-11-09 19:18:41 +01:00
gd
6913148d99 Docs: changed sphinx theme from classic to sphinx_rtd_theme
Dependency: pip install sphinx-rtd-theme
2022-11-09 09:35:59 +02:00
gd
14460c6b6d Docs: added custom.css to override default hyphenation and text align styles 2022-11-08 17:31:37 +02:00
Max Kellermann
a0a11be79b Merge branch 'v0.23.x' 2022-11-08 14:36:09 +01:00
gd
4fa5bd9d5c doc/plugins.rst: changed 'More information' links to unnamed to suppress warning: Duplicate explicit target name 2022-11-08 14:34:45 +01:00
Luca Boccassi
714bb991aa systemd: use PrivateUsers= in user unit
ProtectSystem= and other sandboxing options require a user namespace in
order to work as user units (the user manager does not run as root and
thus without a user namespace it is unable to perform mounts).
2022-11-03 23:11:13 +00:00
gd
a1359f2388 TagBuilder: skip unnecessary preperation if there are no items to add 2022-11-01 17:55:42 +02:00
gd
ab687481cc Tag: skip tag pool lock if there are no items 2022-11-01 15:37:54 +02:00
Max Kellermann
0efbd4df8b lib/gcrypt: use std::size_t 2022-10-29 07:31:25 +02:00
gd
caaa050e60 curl input plugin - added config options: verbose, low_speed_limit, low_speed_time, tcp_keepalive, tcp_keepidle, tcp_keepintvl 2022-10-22 13:49:58 +03:00
Max Kellermann
b4e3891912 Merge branch 'config_curl_conn_timeout' of https://github.com/geneticdrift/MPD 2022-10-16 11:45:19 +02:00
gd
160f793e2a Added connect_timeout configuration to curl input plugin 2022-10-16 12:13:51 +03:00
Max Kellermann
1429d6bfb9 playlist/cue/Parser: use Split() 2022-10-15 08:33:51 +02:00
Max Kellermann
ced6a5ae07 playlist/cue/Parser: remove always-failing assert()
Not the assert() here fails, but the illegal src[-1] call.  Yet
another regression from commit 21e4c25e61ce54bedde77d21e0fa9ade9115116c
2022-10-15 08:32:37 +02:00
Max Kellermann
d6d0f78e93 release v0.23.10
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmNJ2e0NHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEjBYEACk4QtVnD52sGtz0CwThFYzekvkZHOBcP2fYOH7
 rVcQaNmV7Fpnv+iz+k7zrqhs/A8FgQq6KUNpUn3gzxae4KsA7i1yEpopIqfzRh71
 eVrjTGijMirddehsxKbkjZ1TZy5S+SkZ+Bu965qzXUZuIrErKm4m5xqkIxXBHMEc
 twK9BSCqlTT2vpND5cmX90T/NBDgZd3uQxQP2ohWjVXvg9ou2gtns18ZdYUVRTym
 rLqRLfx1rG1lS8hzKqUqt9YxbWSD606T4giC2vYg2+2OFA9VFh3TNCSaFgWEJMZe
 ou6iaX+aSoCP+H6nktxfYravwdmHvBseRtrOouxPd8Br2k1eSQGXEVlZVTKrpBME
 OZnncEGqN27GggYH1RyVZ6showJ7G05HOhGFDDs8ABR0EbAbNkGvhrjl8cGXONYH
 ScTBbvqkTrhRMOOSmiAp7X1eLJ4QICAfhCV85YzSV93u69egO1MQLYzVYUurOOyt
 TuT+XbUD+Irk3DrHvhxs/IE+ciIvilFsvCmeNjCAyH4ZPvvHt/AIskQNyF3Jj720
 XKjtq6rMF9bizut/kboPgsVQoFbnj7ncCaIZ90h27obeqqiXajTx7ixJldvwDbrp
 yKQY6xDdm7DZChqYF0KKWWzLt2BoAzqVPW3zgRfJRqb9HtQ+ZVJuljvV8bBVFKN1
 zIA4Nw==
 =GQl1
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.10'

release v0.23.10
2022-10-14 23:56:33 +02:00
jcorporation
2937a55582 add precondition for mount/unmount in commands response 2022-10-07 13:59:54 +02:00
Max Kellermann
209e4e940e Merge branch 'queue_save_with_append' of https://github.com/geneticdrift/MPD 2022-10-02 11:41:17 +02:00
gd
cd093a6014 Added new optional argument MODE to command 'save' to be able to append or replace an existing playlist 2022-10-02 11:19:36 +03:00
Max Kellermann
b0d6c0e7cb Merge branch 'v0.23.x' 2022-09-28 13:08:34 +02:00
Max Kellermann
ac7bf12743 event/Loop: move call to FlushClockCaches() 2022-09-28 10:03:39 +02:00
Max Kellermann
db21e20c99 event/Loop: improve API doc wording 2022-09-28 09:55:35 +02:00
Max Kellermann
56adb27b44 event/Loop: push new idle events to the back of the list 2022-09-28 09:47:36 +02:00
Max Kellermann
520e96b6e8 event/Loop: rename parameter 2022-09-28 09:45:58 +02:00
Max Kellermann
45599e7840 Merge branch 'v0.23.x' 2022-09-27 20:40:41 +02:00
Max Kellermann
8d9b0c42cb Merge branch 'reflection' of https://github.com/jcorporation/MPD 2022-09-27 20:35:17 +02:00
Max Kellermann
2c11095eed lib/icu/Compare: use StringStartsWith() for improved code clarity
Also fixes the inverted strncmp() call.
2022-09-27 20:23:10 +02:00
jcorporation
07a0369b74 Add pcre status to config response 2022-09-27 20:10:35 +02:00
Max Kellermann
cd253e470a Merge branch 'starts_with' of https://github.com/jcorporation/MPD 2022-09-27 20:05:38 +02:00
jcorporation
868a06eaf9 Add starts_with to filter expressions 2022-09-27 19:45:15 +02:00
Max Kellermann
512cd7b0de Merge branch 'ConsumeMode' of https://github.com/jcorporation/MPD 2022-09-21 11:36:25 +02:00
Max Kellermann
352c598916 command/other: use if-with-initializer 2022-09-20 22:07:10 +02:00
Max Kellermann
661aee29da Merge branch 'reflection' of https://github.com/jcorporation/MPD 2022-09-20 21:07:06 +02:00
jcorporation
0439df05cc Add playlist_directory to config command response 2022-09-20 21:04:25 +02:00
jcorporation
4333854293 Add documentation for consume oneshot mode 2022-09-20 20:32:32 +02:00
jcorporation
eb3baf7e99 Cast enum to unsigned 2022-09-20 20:27:25 +02:00
jcorporation
48a936ef5b Add ConsumeMode oneshot, closes 2022-09-20 20:26:49 +02:00
Max Kellermann
5a7d2be77d Merge remote-tracking branch 'jcorporation/idle' 2022-09-20 15:11:41 +02:00
jcorporation
310a146a55 OutputCommands get ride of global mixer idle events 2022-09-06 21:58:18 +02:00
Max Kellermann
0e201ffdcc archive/iso9660: simplify std::span initializer 2022-09-06 21:16:28 +02:00
Max Kellermann
d5d25d78da Merge branch 'v0.23.x' 2022-09-06 21:15:42 +02:00
jcorporation
4f8b4c605e player/Control: Change idle events from global to partition scope 2022-08-28 11:33:14 +02:00
Max Kellermann
b2fb920d28 android/PrivacyPolicy.rst: add Privacy Policy
The Google overlords require me to publish a privacy policy, even if
MPD does not collect any data.
2022-08-18 18:53:10 +02:00
Max Kellermann
4f041694d3 release v0.23.9
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmL+ZuYNHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEmxjD/4sJEq9DroRRK2qnVL1c6rwdzAL05LQwXGfWMCY
 /eIfoYGgu+PPN65Xf/A7qEvsXXSpuDzq0jTzdmtSvQwfKgg5jy72Qn+LN0dmoSRn
 mqQoqPFFxr7URf7QhL/6/EKcKYSexu/dxLnnuOC/yB/32WB+JINGNLWABrCpFMW0
 4kbVSC6t/e07bfBxNoYKx+kSxX88n82v5LNjkPctx0oU0gRoyRZds273uuKHOIYQ
 KFHHuaW9eNT0x/JrrsBD0ASXcp/9CfyVvyoag4bqJIc6Bg4fJTEZ9QPy9SUF2R8L
 0QCG2DBqFoht7Xqyo7qe5vYy2lww/flVrH/UwB1V7xfWzbuv3qUYs2pRnFmPKjQx
 23FRBkmC3tWmno+pZFaYmzprRKQK7WS9DJUzaQ8DCjNVpncadNPDRvz13BZjVLAE
 LeAFxPZ3B3yrDIjNRGl9LEySMJs7M4jrqzXQZuWS3+O9IZV19ajGczWmFCyQOyu4
 F7bj9tfy1yhUjMYOiUIxXsWvxZSVIo8wK1payCJzvKTobnUUeDfDucnD/lpVRMF8
 HyJsaZrXwFIClBmK8nCh3LiB5Dh9nxl8xjtmrCiPVzGZvj5qnzMkZWF+C4wxblnZ
 XTVmHFrpdcI3nK4BzLVrxF+3A08gPkIHta9boqrMhfX4gPWkKmD1vH/+u2OD2BIY
 I2MASg==
 =tk1U
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.9'

release v0.23.9
2022-08-18 18:23:12 +02:00
Max Kellermann
51aa1d2db8 mixer/Internal: hide internal fields 2022-08-18 17:42:30 +02:00
Max Kellermann
2d2df25d04 mixer/Mixer: avoid locking twice 2022-08-18 17:39:17 +02:00
Max Kellermann
29eb3e9ebc mixer/Control: move some code to Lock*() methods 2022-08-18 17:34:00 +02:00
Max Kellermann
b0873fbc90 mixer/Mixer*: drop the "Mixer" prefix from source files 2022-08-18 17:21:39 +02:00
Max Kellermann
c14484a5cc mixer/MixerList: eliminate header 2022-08-18 17:14:42 +02:00
Max Kellermann
a966cfeb1f playlist/cue/CueParser: fix nullptr dereference
Regression from commit 21e4c25e61ce54bedde77d21e0fa9ade9115116c
2022-08-18 17:06:51 +02:00
Max Kellermann
6c0546d829 mixer/Internal: document that caller must lock the mutex 2022-08-18 16:57:58 +02:00
Max Kellermann
e1e8f45983 mixer/Control: add noexcept 2022-08-18 16:56:32 +02:00
Max Kellermann
3eedcc55b9 mixer/Control: convert pointers to references 2022-08-18 16:56:06 +02:00
Max Kellermann
dd2cab1488 Merge branch 'v0.23.x' 2022-08-18 16:54:18 +02:00
Max Kellermann
f883c09b6b fs/FileSystem: add pure attributes 2022-08-18 16:53:32 +02:00
Max Kellermann
71acad6c21 fs/FileSystem: add noexcept 2022-08-18 16:53:31 +02:00
Max Kellermann
938054bdb8 command/all: fix off-by-one bug in parameter count check 2022-08-09 12:47:57 +02:00
Max Kellermann
d0909adf6b command/all: use class StaticVector 2022-08-09 12:46:26 +02:00
Max Kellermann
a12b004fa4 util/StaticVector: new class 2022-08-09 12:44:02 +02:00
Max Kellermann
a8452957fc command/Request: pass std::span to constructor 2022-08-09 12:43:52 +02:00
Max Kellermann
feb334756e command/all: convert macro to constexpr 2022-08-09 12:39:18 +02:00
Max Kellermann
50a4d7169e TagAny: pass std::string_view to uri_has_scheme() 2022-08-09 11:43:35 +02:00
Max Kellermann
6239b6c0e2 Merge branch 'v0.23.x' 2022-08-08 23:48:38 +02:00
Max Kellermann
b789ffd2bf Merge branch 'v0.23.x' 2022-08-08 23:46:22 +02:00
Max Kellermann
0279f4fb57 output/jack: fix bogus assertion failure
Regression from commit 45071607aa277dbbf3814e9a06c8371be75f27c5

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1571
2022-08-08 22:01:59 +02:00
Max Kellermann
88793cbc1a output/httpd: avoid extra buffer copy if possible 2022-08-08 21:00:38 +02:00
Max Kellermann
2afe427ab3 output/httpd: copy from returned encoder buffer
This fixes a regression from commits c266fb77581 and 00b8ced09f6,
but really caused by API change in commit 7e14f8f8300f, and this
plugin's failure to adapt to this API change.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1585
2022-08-08 21:00:27 +02:00
Max Kellermann
4c08c0b8b1 Merge branch 'v0.23.x' 2022-07-27 11:06:47 +02:00
Max Kellermann
b864094fdc Merge branch 'master' of https://github.com/Sonico98/MPD 2022-07-21 21:14:15 +02:00
Sonico
3ef83cc34e Add titleSort tag 2022-07-20 23:05:10 -03:00
Rosen Penev
3f133dd586 use data() instead of &[0]
No need for C pointer manipulation.

Removed data() for string_view as [] can be used without.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2022-07-20 13:50:48 -07:00
Max Kellermann
0c98d93e9a io/FileOutputStream: write to temporary file if O_TMPFILE is not available 2022-07-14 18:45:33 +02:00
Max Kellermann
c344403bed fs/Path: add operator+ 2022-07-14 18:42:25 +02:00
Max Kellermann
150e8f78bf io/FileOutputStream: use fsync() if fdatasync() is unavailable
Fixes the macOS build which apparently doesn't implement the POSIX
function fdatasync().
2022-07-14 18:34:44 +02:00
Max Kellermann
bc7fdba36d test/fs/TestPath: add missing PATH_LITERAL 2022-07-14 18:34:43 +02:00
Max Kellermann
fe3ab7b937 fs/Path: add WithSuffix() 2022-07-14 18:23:48 +02:00
Max Kellermann
458084d79b fs/Path: add GetSuffix() 2022-07-14 18:20:55 +02:00
Max Kellermann
f44bc19ce1 test/fs/TestPath: new unit test 2022-07-14 18:20:45 +02:00
Max Kellermann
d3947d0ad5 fs/Path: GetExtension() skips all leading dots
Don't return an empty string for "..", because this path doesn't have
an extension.
2022-07-14 18:20:45 +02:00
Max Kellermann
849ed122c7 fs/Path: document GetExtension() 2022-07-14 18:12:00 +02:00
Max Kellermann
254ee00c37 fs/Path: rename GetSuffix() to GetExtension()
The "extension" is the name after the dot, but the "suffix" is the
string including the dot.
2022-07-14 18:12:00 +02:00
Max Kellermann
594b97feb1 fs/Path: change cast syntax 2022-07-14 18:12:00 +02:00
Max Kellermann
cc0def15c4 Copyright year 2022 2022-07-14 17:59:35 +02:00
Max Kellermann
81154130b5 test/fs: rename TestFs.cxx to TestGlob.cxx 2022-07-14 17:57:10 +02:00
Max Kellermann
0514f25c61 test/TestFs: move to test/fs/ 2022-07-14 17:56:37 +02:00
Max Kellermann
2670bbdcc8 io/FileOutputStream: simplify OpenTempFile() call 2022-07-14 15:47:10 +02:00
Max Kellermann
bd3e096411 io/FileOutputStream: move code to Delete() 2022-07-14 15:43:36 +02:00
Max Kellermann
270a74e53b io/FileOutputStream: add method Sync() 2022-07-14 15:41:12 +02:00
Max Kellermann
47d103e8a1 io/FileOutputStream: add API documentation 2022-07-14 15:41:03 +02:00
Max Kellermann
188f7ab795 thread/WindowsCond: add explicit cast 2022-07-14 13:04:08 +02:00
Max Kellermann
4953a57c1c java/String: add std::string_view constructor 2022-07-14 13:03:23 +02:00
Max Kellermann
199037c682 config: allow configuring partitions
This just allows creating empty partitions.  More features to come.
2022-07-13 15:18:06 +02:00
Max Kellermann
64f84d5468 player/Listener: add virtual method OnPlayerState(), wrapping IDLE_PLAYER
This eliminates most of the remaining global "player" idle events.
2022-07-13 14:11:36 +02:00
Max Kellermann
047561dc22 player/Listener: add virtual method OnPlayerError()
Replaces two global idle_add() calls.
2022-07-13 14:11:36 +02:00
Max Kellermann
a542a0804a Partition: OnPlayerTagModified() emits IDLE_PLAYER
Replaces one global idle_add() call.
2022-07-13 14:11:36 +02:00
Max Kellermann
cddeb2a0df io/BufferedOutputStream: add missing #include 2022-07-13 14:11:36 +02:00
Max Kellermann
de1d443db1 output/Multiple: use std::size_t 2022-07-13 13:26:27 +02:00
Max Kellermann
e2040ed395 output/Multiple: use [[gnu::pure]] 2022-07-13 13:25:17 +02:00
Max Kellermann
8a0ba7a725 output/Control: GetName() returns std::string& 2022-07-13 13:23:21 +02:00
Max Kellermann
e74788ea32 output/Control: inline GetName() 2022-07-13 13:13:23 +02:00
Max Kellermann
fef79931c5 output/Multiple: pass std::string_view to FindByName() 2022-07-13 13:13:21 +02:00
Max Kellermann
b52b0ac85a *: use BufferedOutputStream::Fmt() 2022-07-13 13:10:14 +02:00
Max Kellermann
9a30286289 io/BufferedOutputStream: add libfmt support 2022-07-13 12:52:20 +02:00
Max Kellermann
20310437d0 .github/workflows/build.yml: build with Ubuntu 22.04 as well 2022-07-13 12:41:04 +02:00
Max Kellermann
d29e1544bf .github/workflows/build.yml: explicitly select ubuntu-20.04
According to https://github.com/actions/virtual-environments
"ubuntu-latest" maps to "ubuntu-20.04", even though "ubuntu-22.04" is
also available.  Since our job description is very specific to
"ubuntu-20.04", let's select this explicitly.
2022-07-13 12:37:02 +02:00
Max Kellermann
ae4f4d3533 config/Data: add WithEach(ConfigBlockOption)
To improve error messages without making callers more complex.
2022-07-13 11:05:21 +02:00
Max Kellermann
89a18b49a7 Merge branch 'v0.23.x' 2022-07-12 14:00:00 +02:00
Max Kellermann
eb589b0a46 output/osx: fix CI failure 2022-07-12 13:37:46 +02:00
Max Kellermann
52eff41379 remove Haiku support
Haiku support has been unmaintained for many years, and this issue has
been open for more than 5 years, but apparently the Haiku people have
lost interest:

 https://github.com/MusicPlayerDaemon/MPD/pull/183

Haiku support was therefore deprecated by this commit 4 years ago:
7de8fd04a4 - but in those 4 years, nobody stepped up to adopt
maintainership.

I don't have any computer (or VM) with Haiku and there is no CI with
Haiku support, so I'm unable to adapt the Haiku specific code to API
changes.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/182
Closes https://github.com/MusicPlayerDaemon/MPD/issues/185
2022-07-12 13:14:49 +02:00
Max Kellermann
45071607aa output/Interface: pass std::span to Play() 2022-07-12 12:59:47 +02:00
Max Kellermann
f5d104e7af output/ao: simplify write_size checks 2022-07-12 12:58:19 +02:00
Max Kellermann
4f8d2a8b1c output/alsa: use std::byte instead of uint8_t 2022-07-12 12:36:39 +02:00
Max Kellermann
0158a2b6b9 encoder/flac: refactor input buffer conversion 2022-07-12 12:31:08 +02:00
Max Kellermann
00b8ced09f encoder/flac: Read() returns the internal buffer 2022-07-12 12:19:55 +02:00
Max Kellermann
5f51be43cf decoder/flac: add noexcept and inline 2022-07-12 12:15:06 +02:00
Max Kellermann
3e2de560ca encoder/lame: eliminate the audio_format field 2022-07-12 12:08:46 +02:00
Max Kellermann
c266fb7758 encoder/lame: Read() returns the internal buffer
Eliminate memcpy() calls.
2022-07-12 12:01:31 +02:00
Max Kellermann
0d09f307b2 encoder/Interface: update API docs 2022-07-12 12:00:02 +02:00
Max Kellermann
eb7d321cb8 Merge branch 'v0.23.x' 2022-07-12 11:59:49 +02:00
Max Kellermann
7e14f8f830 encoder/Interface: pass std::span to Write() and Read() 2022-07-12 10:33:59 +02:00
Max Kellermann
28e044a36a encoder/lame: use std::size_t 2022-07-12 10:14:10 +02:00
Max Kellermann
4e91d8279b encoder/vorbis: use std::size_t 2022-07-12 10:11:30 +02:00
Max Kellermann
ff3d8509ac output/httpd: move buffer to stack 2022-07-12 10:08:26 +02:00
Max Kellermann
e861d4f83d encoder/interface: make Read() noexcept (all implementations are) 2022-07-12 10:07:38 +02:00
Max Kellermann
31d89b36cf encoder/flac: use std::size_t 2022-07-12 09:53:16 +02:00
Max Kellermann
6b24344031 output/shout: move buffer to stack 2022-07-12 09:48:02 +02:00
Max Kellermann
c55e250c45 encoder/Interface: include cleanup 2022-07-11 22:38:24 +02:00
Max Kellermann
cd241a93c1 util/DynamicFifoBuffer: pass std::span to Append() 2022-07-11 22:38:24 +02:00
Max Kellermann
53acf7ae82 encoder/*: use std::byte instead of uint8_t 2022-07-11 22:38:24 +02:00
Max Kellermann
c34f6ed8c0 decoder/Client: pass std::span to SubmitData() 2022-07-11 22:37:38 +02:00
Max Kellermann
329c448d30 decoder/wavpack: use [[gnu::pure]] 2022-07-11 22:11:42 +02:00
Max Kellermann
a6619e9a13 decoder/wavpack: add "constexpr" and "const_cast" 2022-07-11 22:10:11 +02:00
Max Kellermann
24ce5da2b8 decoder/wavpack: convert pointer to reference 2022-07-11 22:08:49 +02:00
Max Kellermann
b4f751080d decoder/wavpack: add noexcept 2022-07-11 22:06:10 +02:00
Max Kellermann
6d02edebc9 decoder/wavpack: rename "samples" to "frames" 2022-07-11 22:05:49 +02:00
Max Kellermann
349882ed75 decoder/wavpack: require libwavpack version 5 2022-07-11 22:04:15 +02:00
Max Kellermann
4464310e74 release v0.23.8
-----BEGIN PGP SIGNATURE-----
 
 iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmLIuEINHG1heEBibGFy
 Zy5kZQAKCRAjbopYxttFEm1JD/9j/a82cNccPLUfTptgb8ak5fAnYA65edbtGPr9
 dLv1BSjMrsTpMpgJ8FT5wjQn7H5drmE2GLvCN+oZUqaSz99F5BC+Hof7bfvv/sVF
 opLTiZn2iAtanwtHP6ZEPPswTbdN2FgtZeFhJIGmFspghJV5hdbM7vbwNX1SIpc6
 LH+WvE42ZG/w5wNajRvr6/lPYQhJc70wUqODXLzgdYu3WYmIclUAyFv7tVr067Hh
 uXP6b6MZV60cqh+a0xX01n5kwDo2reqmmE0IY0Le7H6xg5quE7DzCVElTOAa7R1x
 MZJCqY/thjvXl3JfHW5/ZwmiNrxsmx8nzGhrDyg4tb3hjbwip1iEI/OgnDyacdl4
 34njeFxO40AJhienDWLAp2oSYh4pNdfjFvnfSJXeQ9HD2sIzGi692WUgzjdM1VmA
 83iVRe9Bx4OTyAg1jwPOFyAYnRqhWsYFSp7GjwNBQwTRSwwBtmOxwAhWKwuspuLi
 YfDoF7wGYVY5lOXuDBw+rvhGRWqGKsbQzZFy0bQFoD8dbwG9huLJCumNWZCbqELF
 TAfU5sRcQlAjwSGncEpKOitYjdrtylYRb12p2DSedFuBWxcRGGPiCFfTVUKV8hz1
 LGD1xj1g/4ClEUbfDNVwa7sAEO7o84Qojfkt/siBjhE427i11CpPGIlMCVeO2FkG
 fI1f3Q==
 =KgWM
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.8'

release v0.23.8
2022-07-09 01:08:16 +02:00
Max Kellermann
4b3dcf831b output/Timer: add noexcept 2022-07-08 22:58:45 +02:00
Max Kellermann
7dd65f3028 Merge branch 'v0.23.x' 2022-07-04 19:21:18 +02:00
Max Kellermann
bc56f8c2f0 util/ConstBuffer: remove obsolete library
Everything has been migrated to std::span.
2022-07-04 19:15:10 +02:00
Max Kellermann
596ff7e6bf output/*: use std::span instead of ConstBuffer 2022-07-04 19:14:12 +02:00
Max Kellermann
e8667f99be util/OptionParser: use std::span instead of ConstBuffer 2022-07-04 19:04:16 +02:00
Max Kellermann
9b427b3171 command/*: use std::span instead of ConstBuffer 2022-07-04 18:58:13 +02:00
Max Kellermann
baff5e5594 lib/yajl: use std::span instead of ConstBuffer 2022-07-04 18:37:36 +02:00
Max Kellermann
020c9b41cc lib/icu: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
e975e2e477 lib/ffmpeg: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
4e1dc562f7 lib/curl: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
d097babe73 lib/chromaprint: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
8fa212f04d lib/cdio: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
b9c9a5f1dd db/*: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
4fb8b45111 song/Filter: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Max Kellermann
6c107443d3 input/qobuz: include cleanup 2022-07-04 18:37:35 +02:00
Max Kellermann
67c6d111a8 filter/*: use std::span instead of ConstBuffer 2022-07-04 18:37:35 +02:00
Marceline Cramer
18ebd42c52
.github: Add reminder to include backtrace in issue template 2022-07-04 10:32:58 -06:00
Max Kellermann
9675cc77e2 decoder/*: use std::span instead of ConstBuffer 2022-07-04 18:11:21 +02:00
Max Kellermann
4ce1dae673 pcm/*: use std::span instead of ConstBuffer 2022-07-04 18:11:21 +02:00
Max Kellermann
d89136b09c util/ConstBuffer: hard-code std::span support 2022-07-04 18:09:32 +02:00
Max Kellermann
d58c38943a util/StringView: remove obsolete class
Everything has been migrated to std::string_view.
2022-07-04 15:04:31 +02:00
Max Kellermann
66704ec879 util/UriExtract: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
422c1e9288 util/TemplateString: remove StringView support 2022-07-04 15:04:31 +02:00
Max Kellermann
683f0da2e7 tag/*: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
c7a8fc91c0 storage/curl: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
cfd255a014 lib/xiph: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
1c30b3d5a1 lib/dbus/UDisks2: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
4964eda167 fs/StandardDirectory: use std::string_view instead of StringView 2022-07-04 15:04:31 +02:00
Max Kellermann
502e5f006a decoder/*: use std::string_view instead of StringView 2022-07-04 14:50:18 +02:00
Max Kellermann
23235e3194 db/upnp/Directory: use std::string_view instead of StringView 2022-07-04 14:50:18 +02:00
Max Kellermann
93834fe389 db/simple/Directory: use std::string_view instead of StringView 2022-07-04 14:50:18 +02:00
Max Kellermann
bd32b229b5 config/Path: use std::string_view instead of StringView 2022-07-04 14:41:39 +02:00
Max Kellermann
c7d2cb855a Permission: use std::string_view instead of StringView 2022-07-04 14:38:29 +02:00
Max Kellermann
04c924ae3b playlist/Registry: use std::string_view instead of StringView 2022-07-04 14:36:21 +02:00
Max Kellermann
6c8a85a391 playlist/{asx,cue,rss,xspf}: use std::string_view instead of StringView 2022-07-04 14:35:52 +02:00
Max Kellermann
74780131bd lib/zlib/GzipOutputStream: add SyncFlush() 2022-07-04 10:09:04 +02:00
Max Kellermann
2c092d2613 lib/zlib/GzipOutputStream: add exception API docs 2022-07-04 10:08:55 +02:00
Max Kellermann
171b31ae67 lib/zlib/GzipOutputStream: rename Flush() to Finish() 2022-07-04 10:08:54 +02:00
Max Kellermann
5b3abe2c9c lib/zlib/GzipOutputStream: grow Write() buffer to 64 kB 2022-07-04 10:08:53 +02:00
Max Kellermann
59186f1fb0 event/Loop: include cleanup 2022-07-04 09:55:48 +02:00
Max Kellermann
5e68531428 event/SocketEvent: move ssize_t to class BufferedSocket 2022-07-04 09:54:08 +02:00
Max Kellermann
e7b15a9041 lib/curl/Request: remove obsolete method prototypes 2022-07-02 18:42:08 +02:00
Max Kellermann
853afa1bce lib/curl/Adapter: add missing StripLeft() call
Fixes regression by commit 88a66df9d67dd156dcdf145348a5e2d1a464aa66
2022-07-02 18:36:15 +02:00
Max Kellermann
627fd755e8 lib/curl/Adapter: remove redundant size check 2022-07-01 16:54:47 +02:00
Max Kellermann
88a66df9d6 lib/curl/Adapter: use std::string_view internally 2022-07-01 16:51:37 +02:00
Max Kellermann
af951dc08a Merge branch 'v0.23.x' 2022-07-01 12:45:07 +02:00
Max Kellermann
a6d20d1907 Merge branch 'v0.23.x' 2022-07-01 12:39:41 +02:00
Max Kellermann
d882c3361d playlist/PlaylistPlugin: use std::string_view 2022-07-01 11:31:31 +02:00
Max Kellermann
9d50306e2f lib/xiph/ScanVorbisComment: use std::string_view 2022-07-01 11:30:44 +02:00
Max Kellermann
96f99aeb8f TagPrint: use std::string_view 2022-07-01 11:29:58 +02:00
Max Kellermann
ed7263ee3e decoder/OpusTags: use std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
f32d752ccb util/NumberParser: use std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
671b7e079f decoder/OpusReader: use std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
e10b15010c decoder/OpusReader: add noexcept 2022-07-01 11:29:11 +02:00
Max Kellermann
02fe857755 util/IterableSplitString: return std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
ea3f044cd8 util/SplitString: use std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
e6bb6c59ec storage/Composite: use std::string_view 2022-07-01 11:29:11 +02:00
Max Kellermann
6d23ac67f9 util/UriQueryParser: use std::string_view 2022-07-01 11:29:10 +02:00
Max Kellermann
ca46b4d7a7 util/MimeType: use std::string_view 2022-07-01 11:29:10 +02:00
Max Kellermann
0727ee94c0 tag/Id3Scan: use std::string_view 2022-07-01 11:29:10 +02:00
Max Kellermann
21e4c25e61 playlist/cue/CueParser: more std::string_view 2022-07-01 11:29:10 +02:00
Max Kellermann
e921c0b40b lib/yajl/Callbacks: use std::string_view 2022-07-01 11:16:42 +02:00
Max Kellermann
c05d4cddfb input/qobuz: use std::string_view 2022-07-01 11:16:42 +02:00
Max Kellermann
c9723ee4b7 playlist/SoundCloud: use std::string_view 2022-07-01 11:16:42 +02:00
Max Kellermann
ca90c75c61 lib/alsa/AllowedFormat: pass std::string_view to constructor 2022-07-01 10:57:49 +02:00
Max Kellermann
9976665cc7 util/UriRelative: use std::string_view internally 2022-07-01 10:56:29 +02:00
Max Kellermann
c5f037fa64 util/StringCompare: move code from StringView 2022-07-01 10:48:34 +02:00
Max Kellermann
5ec13c0b06 util/StringStrip: add libc++ compatibility kludge 2022-07-01 10:45:37 +02:00
Max Kellermann
60ca12e4bd db/simple/Song: use std::string_view 2022-06-30 21:04:13 +02:00
Max Kellermann
67fcf7d7c5 output/ao: add missing include 2022-06-30 21:03:25 +02:00
Max Kellermann
c953ed48b7 output/ao: use std::string_view 2022-06-30 21:01:29 +02:00
Max Kellermann
6440df60aa output/jack: use std::string_view 2022-06-30 21:00:23 +02:00
Max Kellermann
b806b0a97f util/StringStrip: add std::string_view overloads 2022-06-30 21:00:07 +02:00
Max Kellermann
10197a0041 util/IterableSplitString: use std::string_view internally 2022-06-30 20:54:42 +02:00
Max Kellermann
166885802a util/StringSplit: move code from StringView.hxx 2022-06-30 20:40:41 +02:00
Max Kellermann
4a97c45585 tag/Config: use IterableSplitString instead of SplitString() 2022-06-30 20:39:39 +02:00
Max Kellermann
0173d3b313 util/IterableSplitString: use StringView::Split() 2022-06-30 20:37:58 +02:00
Max Kellermann
aadd32c973 util/IterableSplitString: add noexcept 2022-06-30 20:34:04 +02:00
Max Kellermann
0f4bf5569a event/InotifyEvent: new class wrapping inotify
Replaces class InotifySource.
2022-06-30 12:05:50 +02:00
Max Kellermann
ff4cf6c6d1 test/run_inotify: add class Instance 2022-06-30 11:57:03 +02:00
Max Kellermann
a7b7e35512 tag/ReplayGainParser: use std::string_view 2022-06-30 10:59:56 +02:00
Max Kellermann
11135b48e6 tag/MixRampParser: use std::string_view 2022-06-30 10:59:27 +02:00
Max Kellermann
d0382caa88 tag/ApeLoader: use std::string_view 2022-06-30 10:58:22 +02:00
Max Kellermann
4765726bda tag/VorbisComment: use std::string_view 2022-06-30 10:57:01 +02:00
Max Kellermann
455a412aaa tag/Table: use std::string_view 2022-06-30 10:53:26 +02:00
Max Kellermann
1a2b505979 tag/ParseName: use std::string_view 2022-06-30 10:52:21 +02:00
Max Kellermann
c34f3c9b94 tag/Handler: use StringIsEqualIgnoreCase() 2022-06-30 10:50:56 +02:00
Max Kellermann
232084c2f9 playlist/cue/CueParser: use std::string_view in public API 2022-06-30 10:50:53 +02:00
Max Kellermann
2ba092711f event/net/UdpListener: use IsSocketErrorReceiveWouldBlock() 2022-06-30 10:32:25 +02:00
Max Kellermann
8aa4227c0c net/SocketAddress: add std::span cast operators 2022-06-30 10:30:54 +02:00
Max Kellermann
81afb47cd0 util/ByteOrder: add class PackedBE64 2022-06-30 10:30:54 +02:00
Max Kellermann
60a3aae35f io/FileDescriptor: add OpenReadOnly() overload with directory fd 2022-06-30 10:30:54 +02:00
Max Kellermann
bc3415ce8b Copyright year 2022 2022-06-30 09:41:53 +02:00
Max Kellermann
3f1acd3642 lib/avahi/Publisher: fix comment typo 2022-06-30 09:38:44 +02:00
Max Kellermann
4564d251a8 zeroconf/avahi: move generic sources to lib/avahi 2022-06-30 09:37:30 +02:00
Max Kellermann
8783ed1981 lib/curl/Adapter: use std::string_view 2022-06-29 17:38:58 +02:00
Max Kellermann
1da09f5b1b lib/curl: use std::span 2022-06-29 17:37:12 +02:00
Max Kellermann
062df65b1e lib/dbus: use std::span 2022-06-29 17:32:58 +02:00
Max Kellermann
899eaa3307 io/FileDescriptor: add Duplicate() returning UniqueFileDescriptor 2022-06-29 17:31:37 +02:00
Max Kellermann
5140eaa5e7 util/IntrusiveList: use std::is_base_of_v 2022-06-29 17:30:11 +02:00
Max Kellermann
cca20fec07 event/FineTimerEvent: adjust "friend" declaration 2022-06-29 17:29:44 +02:00
Max Kellermann
12d67dad35 net/SocketError: support ETIMEDOUT 2022-06-29 17:28:47 +02:00
Max Kellermann
8a68d085b4 util/IntrusiveList: add option "constant_time_size" 2022-06-29 17:28:39 +02:00
Max Kellermann
e437cc4faf util/IntrusiveList: add size() 2022-06-29 17:28:35 +02:00
Max Kellermann
1fb858e2d7 util/IntrusiveList: add struct IntrusiveListMemberHookTraits 2022-06-29 17:28:16 +02:00
Max Kellermann
3945a3add9 util/MemberPointer: new library 2022-06-29 17:28:15 +02:00
Max Kellermann
5348a446a7 util/IntrusiveList: move various static functions to struct IntrusiveListBaseHook 2022-06-29 17:27:40 +02:00
Max Kellermann
e8e33d5fc4 util/IntrusiveList: add missing ToHook() calls 2022-06-29 17:27:37 +02:00
Max Kellermann
c28580745b util/IntrusiveList: move struct HookDetection to top-level 2022-06-29 17:24:08 +02:00
Max Kellermann
e7b587d550 util/CopyConst: use std::add_const 2022-06-29 17:23:50 +02:00
Max Kellermann
5d34b9b5bb util/SpanCast: move CopyConst to separate header 2022-06-29 17:23:44 +02:00
Max Kellermann
86be7938f1 util/SpanCast: swap the CopyConst template parameters 2022-06-29 17:23:41 +02:00
Max Kellermann
7ad5a5efec util/OffsetPointer: use std::byte 2022-06-29 17:23:32 +02:00
Max Kellermann
64f2735e60 util/SpanCast: add ToStringView() 2022-06-29 17:23:14 +02:00
Max Kellermann
3a0a0facdf util/SpanCast: suppress alignment warnings 2022-06-29 17:23:13 +02:00
Max Kellermann
ec66ee3bfb tag/Handler: use std::string_view instead of StringView 2022-06-29 17:22:17 +02:00
Max Kellermann
ca9dd74fbf tag/Builder: use std::string_view instead of StringView 2022-06-29 17:22:17 +02:00
Max Kellermann
2da847dd30 tag/Pool: use std::string_view instead of StringView 2022-06-29 17:22:17 +02:00
Max Kellermann
4cb5c3782b util/HexFormat: require std::span 2022-06-29 17:22:17 +02:00
Max Kellermann
dcf39ee44e .github/workflows/build.yml: add "python-version: 3.x"
This appears to be necessary as of actions/setup-python@v4 (commit
45d908e25fe16a7a2bdbb3294316c606f58a5277).
2022-06-13 21:37:04 +02:00
Max Kellermann
f2cfa3e1c4 net/SocketError: add SocketErrorCategory() 2022-06-13 21:26:58 +02:00
Max Kellermann
0c2c20254b system/Error: add IsLastError() 2022-06-13 21:23:11 +02:00
Max Kellermann
193d6a4fd4 system/Error: add LastErrorCategory() 2022-06-13 21:19:20 +02:00
Max Kellermann
acfeec7a5d system/Error: add [[gnu::const]] attribute 2022-06-13 21:16:24 +02:00
dependabot[bot]
45d908e25f
build(deps): bump actions/setup-python from 3 to 4
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 15:23:52 +00:00
Max Kellermann
b4f454a553
Merge pull request from MusicPlayerDaemon/dependabot/github_actions/actions/setup-python-3
build(deps): bump actions/setup-python from 1 to 3
2022-06-08 12:56:55 +02:00
Max Kellermann
299f813e28
Merge pull request from MusicPlayerDaemon/dependabot/github_actions/actions/checkout-3
build(deps): bump actions/checkout from 2 to 3
2022-06-08 12:56:21 +02:00
Max Kellermann
eedd490e2d net/AddressInfo: add iterator type aliases 2022-06-07 10:11:26 +02:00
Max Kellermann
0a8aca516a util/StringBuffer: use data() instead of &front() 2022-06-07 10:11:05 +02:00
Max Kellermann
70808bde64 util/ForeignFifoBuffer: add MoveFrom() overload with std::span 2022-06-07 10:09:08 +02:00
Max Kellermann
93bf0fc547 util/ForeignFifoBuffer: use iterators 2022-06-07 10:08:58 +02:00
Max Kellermann
95e7f8b1c8 util/ForeignFifoBuffer: more constexpr 2022-06-07 10:08:58 +02:00
dependabot[bot]
e2d6bb7444
build(deps): bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-05 08:28:29 +00:00
dependabot[bot]
f89916e6fb
build(deps): bump actions/setup-python from 1 to 3
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 1 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v1...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-05 08:28:27 +00:00
naveen
7d95b15cbc chore: Included githubactions in the dependabot config
This should help with keeping the GitHub actions updated on new releases. This will also help with keeping it secure.

Dependabot helps in keeping the supply chain secure https://docs.github.com/en/code-security/dependabot

GitHub actions up to date https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot

https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool
Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com>
2022-06-05 01:30:13 +00:00
Max Kellermann
27e78c71e0 util/HexFormat: use std::span instead of ConstBuffer 2022-06-01 22:50:54 +02:00
Max Kellermann
8333927737 time/Zone: add native Windows implementation 2022-06-01 22:35:04 +02:00
Max Kellermann
db03db0dca util/SpanCast: add FromBytesStrict() 2022-06-01 21:50:01 +02:00
Max Kellermann
bd96f6e572 util/SpanCast: add const support to FromBytesFloor() 2022-06-01 21:49:35 +02:00
Max Kellermann
04041f9583 util/Manual: use std::aligned_storage_t
By using std::launder(), we can re-enable -Wstrict-aliasing.
2022-05-31 16:44:07 +02:00
Max Kellermann
826d1b207e util/Manual: add type aliases 2022-05-31 16:44:07 +02:00
Max Kellermann
f92bae887f util/Manual: add noexcept 2022-05-31 16:44:07 +02:00
Max Kellermann
d2983b7fde net/SocketAddress: include cleanup 2022-05-31 13:54:19 +02:00
Max Kellermann
059955a48c net/SocketAddress: add #ifdefs for std::span 2022-05-31 13:51:12 +02:00
Max Kellermann
6ebac6a0b2 net/StaticSocketAddress: use std::string_view instead of StringView 2022-05-31 13:49:18 +02:00
Max Kellermann
b5a9d0654e net/Resolver: use std::copy() 2022-05-31 13:44:25 +02:00
Max Kellermann
242ba727b2 net/HostParser: use std::string_view instead of StringView 2022-05-31 13:44:25 +02:00
Max Kellermann
d5db4ca0e7 net/SocketAddress: GetSteadyPart() returns std::span 2022-05-31 13:32:27 +02:00
Max Kellermann
d256d3dabe util/StringCompare: use std::string_view instead of StringView 2022-05-31 13:24:45 +02:00
Max Kellermann
759da033fc lib/curl/Escape: use std::string_view instead of StringView 2022-05-31 13:22:56 +02:00
Max Kellermann
c074338f4c system/EventFD: include cleanup 2022-05-31 12:43:26 +02:00
Max Kellermann
3dd2434149 lib/crypto/Base64: add overload which returns AllocatedArray<std::byte> 2022-05-24 14:29:41 +02:00
Max Kellermann
3699514d18 lib/xiph/VorbisPicture: use std::string_view instead of StringView 2022-05-24 14:24:48 +02:00
Max Kellermann
f045cf43e4 output/snapcast/Client: work around clang 14 std::span cast bug
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1538
2022-05-24 14:18:50 +02:00
Max Kellermann
843dad19e9 output/snapcast/Client: use std::string_view instead of StringView 2022-05-24 14:18:33 +02:00
Max Kellermann
73e2ac4211 tag/FixString: use std::string_view instead of StringView 2022-05-24 14:18:33 +02:00
Max Kellermann
6d113de1f8 tag/Handler: pass std::span to OnPicture() 2022-05-24 14:18:33 +02:00
Max Kellermann
2e6f115bcc Merge branch 'v0.23.x' 2022-05-24 10:58:40 +02:00
Max Kellermann
97f78059a2 util/AllocatedArray: add missing type alias "value_type" 2022-05-23 22:15:20 +02:00
Max Kellermann
fd47edb905 apple/AudioObject: call AllocatedArray::data() instead of begin()
Since commit 5fb97b81d15f95b30aac107081e1317fb897d737, begin() returns
an iterator class and not a pointer.

Fixes one part of https://github.com/MusicPlayerDaemon/MPD/issues/1538
2022-05-23 22:06:54 +02:00
Max Kellermann
8ee442e9b1 Merge branch 'v0.23.x' 2022-05-23 21:35:26 +02:00
Max Kellermann
6633c7fd42 lib/crypto/Base64: use std::string_view 2022-05-20 11:25:04 +02:00
Max Kellermann
01b32d5ee0 util/WritableBuffer: remove unused library 2022-05-20 11:22:03 +02:00
Max Kellermann
1260a0147a lib/crypto/Base64: use std::span 2022-05-20 11:21:44 +02:00
Max Kellermann
ef54b7d9de archive/iso9660: use std::span 2022-05-20 11:15:45 +02:00
Max Kellermann
f66315d2de MusicChunk: use std::span 2022-05-20 11:15:45 +02:00
Max Kellermann
b50173ae8b util/CircularBuffer: use std::span 2022-05-20 11:15:45 +02:00
Max Kellermann
b37c031fd1 util/{HugeAllocator,SparseBuffer}: use std::span 2022-05-20 11:15:45 +02:00
Max Kellermann
84e5da4bf0 pcm/Silence: use std::span 2022-05-20 11:15:45 +02:00
Max Kellermann
3bb7693200 decoder/HybridDsd: remove
This is a proprietary extension which nobody appears to use.
2022-05-20 10:08:17 +02:00
Max Kellermann
b22c00d0cd Merge branch 'v0.23.x' 2022-05-20 10:04:19 +02:00
Max Kellermann
7006b075c3 util/AllocatedArray: fix -Wunused-parameter 2022-05-20 09:48:49 +02:00
Max Kellermann
774024a41b net/SocketAddress: add std::span cast operator 2022-05-19 20:52:48 +02:00
Max Kellermann
5fb97b81d1 util/AllocatedArray: migrate from {Const,Writable}Buffer to std::span 2022-05-19 20:52:48 +02:00
Max Kellermann
23dd613ff9 system/VmaName: suppress -Wunused-parameter 2022-05-19 14:01:57 +02:00
Max Kellermann
bb7be9a4cd util/*FifoBuffer: migrate from WritableBuffer to std::span 2022-05-19 14:01:57 +02:00
Max Kellermann
570755f05a io/BufferedReader: migrate from WritableBuffer to std::span 2022-05-19 13:25:19 +02:00
Max Kellermann
957d3e51e0 util/{Const,Writable}Buffer: add std::span cast operators 2022-05-19 13:25:02 +02:00
Max Kellermann
fc6c274c97 pcm/{Dop,Dsd*}: explicitly capture "this"
Implicit capturing is deprecated in C++20.
2022-05-19 13:25:02 +02:00
Max Kellermann
313b092ba8 system/meson.build: depend on libfmt, not our log.a
Fixes linker error.
2022-05-19 13:25:02 +02:00
Max Kellermann
0e9e213324 meson.build: switch to C++20 2022-05-19 09:46:59 +02:00
Max Kellermann
86e6f4fcc0 Merge branch 'v0.23.x' 2022-05-19 09:27:06 +02:00
Max Kellermann
122db76781 release v0.23.7
-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmJ5gd4QHG1heEBtdXNp
 Y3BkLm9yZwAKCRAjbopYxttFEi1vD/9mcxGKnkx4yTDJZhtSWfsSE/5v+oFu09Qy
 Uk5ggk6PN18hMFZ2mcVYXdh7Yc1QiiAycgVFnchiVMYaF+K3LXefXvtkn81xuUNN
 QnJLX/o2hbnmr5Or/Ps+hgiQ0PEn0ui1+t70jJ8a3Ad9sJy3YFQc/HjLUeOZqT0p
 4qVyp614TtjtPlw/q0GHgiD1BxpH/pbcdMvioGj80MwBlwyrvA5IlV4HxxAAervw
 4KKT9XbtnHzR+fyUPv633CDU/bWNkTgbpMVyEhRXxE3heNaXMC4wSfsD/5XKDYLb
 zt/q1pAj6totKJwgdm76MoOKuVeNvw54jBE7st46+lPoH97h5uN9rpEAk00dXtSA
 2FuOw8bc79uN5ZRsWXJ6ZBWzwUvssAtx9ee2seR9BUpdeSGurdOfkKq0h/c/aUzN
 Qn6oWX75e7fMAB9MZhdCpM8lC0Nm5l9il+pA9811qaeZLO6yveW6by2Hmbo6BU0Q
 3MQKyhXJkLFAOwPR9qMAtr3rQ/Wyl4WsJ/kXIYBu7I7HjOxSHjNnZOMsvcLfCMC9
 dcRmtHOPjuVbafiypZ88SekIS0U+deXg33mKaWhH7FrCFEFbXf6GTBzXh/hHKtBm
 icGTwGoOHX53fTgQ9GwC0XBpVBFbY5/gGr2KuzABecU2TeL3QqLl8tolsnBGVYun
 JJ9n+RP0dQ==
 =iQJC
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.7'

release v0.23.7
2022-05-09 23:14:07 +02:00
Max Kellermann
601e5e6abc net/AddressInfo: add noexcept 2022-04-26 21:17:01 +02:00
Max Kellermann
6bacb23002 decoder/ffmpeg: add "noexcept" 2022-04-26 21:07:25 +02:00
Max Kellermann
5c300a9f1a tag/ReplayGainParser: add "noexcept" 2022-04-26 21:06:26 +02:00
Max Kellermann
6e1500c251 Merge branch 'v0.23.x' 2022-04-26 21:05:39 +02:00
Max Kellermann
9e1b24f3a1 input/{Async,Buffering,Thread}InputStream: set VMA name 2022-04-26 20:45:49 +02:00
Max Kellermann
58a345d346 MusicBuffer: set VMA name
Shows the name in /proc/PID/maps, e.g.:

 7fa57b000000-7fa57c000000 rw-p 00000000 00:00 0                          [anon:MusicBuffer]
2022-04-26 20:44:36 +02:00
Max Kellermann
7ed67d216b util/HugeAllocator: add SetName() 2022-04-26 20:44:36 +02:00
Max Kellermann
3ae660ca90 system/VmaName: new library 2022-04-26 20:31:56 +02:00
Max Kellermann
a742e1fc71 util/PeakBuffer, ...: use [[gnu::]] attributes 2022-04-26 20:31:56 +02:00
Max Kellermann
ce88dee14d Merge branch 'v0.23.x' 2022-04-26 18:30:34 +02:00
Max Kellermann
a360475c7b Merge branch 'v0.23.x' 2022-03-26 06:49:51 +01:00
Tim Sweet
3a3f605a56 decoder/opus: Implement bitrate calculation 2022-03-15 10:34:23 +01:00
Max Kellermann
407fa2720a release v0.23.6
-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmIvgaMQHG1heEBtdXNp
 Y3BkLm9yZwAKCRAjbopYxttFEpzhEACOJOyOjtmeuu7Uc147O4YzL/7g5PEZMKHI
 yB/H2QOWnbgAKh+8AFT2YudR89mIXslfuIILRg8/NYkEFgNCrkBQETWsATPyqrCr
 rYJxPtjlC2fAlKkl9XM+qL1WMATIhvRVD9SZajZKwa+9H1y5mZGlMBWdzdxaJoUY
 bhlu7fYvyRMXsStUncyYfsKsuHyibq3d4Pk/jegZhJeMI9/MOKdjc9GJE6Rzz0cT
 dWGqpfBJ/WMZ9aKXB3fh7WVtiIl/hr/5K1QizL10pwmJ5o/LBNKk7eEREbPUvNc6
 S5BHBOyVYaqVTGZyaoF9XkMKv7qnKYNoD2g2H+J5cN87rMRI8DzY/MqUxmX0bCGc
 jOQinMcQuL7zMvYx0ypKdTiMas2OG/RlKluOgzhNIvzkWYCxh9iCozm7Wl3qsvY5
 uJEsaeIb/zgSmUC2637ltBE37lW/8m7RYWpuq82M2CnFx9oL6W3ah8SMm5ToBzYB
 jHrN7h+YcKoIrFcZsYVTCbLzGQnQ2kmzsyGecDeCK9aP16gTkALZdpexn0oIzEKv
 fNtNSU7MgYXLs0knrcBoQw0nQnH9ICuswqFiyr4jcFfqxbIw9mvHyLRIWnyhL9zj
 XiYEr3SqnuVnmuLSgHlYk6g4zpYFLJEHo+/7IlEqTItXeAcsIhjn6B/NDyKVvYQa
 Pfb1ORoumQ==
 =jMu8
 -----END PGP SIGNATURE-----

Merge tag 'v0.23.6'

release v0.23.6
2022-03-14 18:58:47 +01:00
Max Kellermann
7293b32025 util/HexFormat: faster implementation without snprintf() 2022-03-14 12:18:52 +01:00
Max Kellermann
fed8f12863 input/plugins/QobuzClient: pass std::string_view to QueryStringBuilder() 2022-03-14 12:11:46 +01:00
Max Kellermann
718ae433b2 Merge branch 'build-nits' of git://github.com/sp1ff/MPD 2022-02-27 17:23:17 +01:00
Michael Herstine
ed65f52f50 Address feedback on PR .
Move the invocation of `find_program` for doxygen into the if
branch & make failure to find the program fatal.
2022-02-27 08:00:12 -08:00
Michael Herstine
ba1d86ec80 Add (resurrect?) doxygen support.
Added a `doxygen` option to the `doc` build. It makes use of the
already-present but unused file `doxygen.conf.in`.
2022-02-20 10:42:39 -08:00
Max Kellermann
7661c408a4 Merge branch 'master' of git://github.com/jcorporation/MPD 2022-02-16 05:29:22 +01:00
Max Kellermann
ee8d5f18ef doc/protocol.rst: fix misnamed priority filter
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1443
2022-02-16 05:29:02 +01:00
Jürgen Mang
de3b9b8232
Update protocol version to 0.24.0 2022-02-15 23:12:06 +01:00
Max Kellermann
8e99448819 lib/curl/Headers: make the comparison type "transparent" 2022-02-14 18:19:28 +01:00
Max Kellermann
1e548fb6e3 lib/curl/Headers: central type definition for the header map 2022-02-14 18:19:05 +01:00
Max Kellermann
fdc0329e64 archive/List: add option to disable archive plugins in mpd.conf
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1384
2022-02-14 17:54:21 +01:00
Max Kellermann
d3db0400b0 archive/List: convert pointer to reference 2022-02-14 16:43:44 +01:00
Max Kellermann
b1096a9935 test/{visit_archive,dump_text_file}: add basic config file support (not wired yet) 2022-02-14 16:43:37 +01:00
Max Kellermann
ab5b6f83fd queue/Print: support sorting by priority 2022-02-14 14:10:33 +01:00
Max Kellermann
2172aaf1ce song/PrioritySongFilter: new filter
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1412
2022-02-14 14:06:37 +01:00
Max Kellermann
c68dbc4e5c queue/Queue: add method GetLight() 2022-02-14 13:33:34 +01:00
Max Kellermann
ec961f26e9 song/DetachedSong: add API docs 2022-02-14 13:27:52 +01:00
Max Kellermann
c3be961ccf queue/Print: implement sorting 2022-02-14 13:07:13 +01:00
Max Kellermann
166ce0da5a db/VHelper: move CompareTags() to tag/Sort.cxx 2022-02-14 12:37:05 +01:00
Max Kellermann
edbaea8df2 db/Selection: refactor IsEmpty() to IsFiltered() 2022-02-14 09:21:32 +01:00
Max Kellermann
af3a625f64 time/Convert: move GetTimeZoneOffset() to Zone.cxx 2022-02-14 09:21:10 +01:00
Max Kellermann
11d24a583d command/queue: "playlistfind"/"playlistsearch" have a "window" parameter 2022-02-14 09:12:19 +01:00
Max Kellermann
e9e3d8c57c queue/Selection: add "window" field 2022-02-14 09:12:18 +01:00
Max Kellermann
5588291a35 queue/Selection: wrap SongFilter in a new struct 2022-02-14 09:12:18 +01:00
Max Kellermann
4b41e766c6 queue/Queue{Save,Print}: remove redundant "Queue" prefix from file name 2022-02-14 09:12:06 +01:00
Max Kellermann
90d52b6501 Merge branch 'v0.23.x' 2022-02-14 09:11:50 +01:00
Max Kellermann
ad4cf79cc9 tag: new tag "Mood"
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1435
2022-02-12 07:50:18 +01:00
dgcampea
4f3828237a
Fix DSCP LE value
Correct value is 0x04 since we need to account for the 2 ECN bits.
2022-02-02 16:29:01 +00:00
Max Kellermann
946cf25732 Merge branch 'v0.23.x' 2022-01-26 14:44:37 +01:00
Max Kellermann
be72d45356 output/httpd: add config option "dscp"
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1401
2022-01-11 20:31:52 +01:00
Max Kellermann
219c416a1e event/ServerSocket: rename ip_tos to dscp_class and support IPv6 2022-01-11 20:31:52 +01:00
Max Kellermann
16f7ec9950 net/DscpParser: new library 2022-01-11 20:31:52 +01:00
Max Kellermann
d79bf853b1 output/httpd: make configuration fields const 2022-01-10 22:59:50 +01:00
Max Kellermann
1ae6378d85 event/ServerSocket: add ip_tos setting 2022-01-10 22:59:50 +01:00
Max Kellermann
089a843abd net/SocketDescriptor: add method SetIntOption() 2022-01-10 21:36:15 +01:00
Max Kellermann
aea4d3c4b0 lib/zlib/GunzipReader: use std::size_t 2022-01-10 16:59:13 +01:00
Max Kellermann
dda0dfc140 lib/curl/Request: move code from SetupEasy() to Setup.cxx 2021-12-08 20:03:30 +01:00
Max Kellermann
e0f56b9e2d lib/curl/Request: move code to class CurlResponseHandlerAdapter 2021-12-08 19:51:54 +01:00
August2111
3c3c3eeeca MSVC: use winsock2.h instead of sys/time.h for struct timeval 2021-12-08 19:45:03 +01:00
Max Kellermann
31c7151580 time/Calendar: add DaysInYear() 2021-12-08 19:44:31 +01:00
Max Kellermann
50a617764a lib/curl/Handler: fix typo 2021-12-08 19:41:39 +01:00
Max Kellermann
7d67c87a47 io/FileReader: use std::size_t 2021-12-08 19:40:22 +01:00
Philipp Wollschlegel
c072902f23 io/FileOutputStream: merge win32 function Cancel
Win32 had a separate implementation for FileOutputStream::CANCEL Logic
was added to the other platform function, but forgotten in this one.

This merges the functions into one, as only the call for file deletion
is platform specific.
2021-12-08 19:35:11 +01:00
Max Kellermann
5ad4f3c54b system/EventPipe: include cleanup 2021-12-08 19:32:06 +01:00
Max Kellermann
0b6055954d thread/AsyncWaiter: new class
Merges some redundant code.
2021-12-08 19:26:57 +01:00
Max Kellermann
80c177e9a0 io/BufferedOutputStream: add missing char* cast 2021-12-07 12:07:13 +01:00
Max Kellermann
cdcef49eef lib/curl/Request: add constructor with CurlEasy parameter 2021-12-07 12:01:09 +01:00
Max Kellermann
9e18aafccc lib/curl/Request: use std::size_t 2021-12-07 12:00:12 +01:00
Max Kellermann
f7346c1d78 lib/curl/Request: move code to SetupEasy() 2021-12-07 11:57:42 +01:00
Max Kellermann
b709401814 lib/curl/Request: add API docs 2021-12-07 11:56:45 +01:00
Max Kellermann
4074db5f50 io/BufferedReader: use std::size_t 2021-12-07 11:54:11 +01:00
Max Kellermann
8c6bc02bf7 io/BufferedOutputStream: use std::byte 2021-12-07 11:47:45 +01:00
Max Kellermann
35c11afd54 player/Thread: add option "mixramp_analyzer" 2021-12-06 23:06:08 +01:00
Max Kellermann
c884e2f285 config/PlayerConfig: default buffer size is 8 MB
Computers are getting more and more RAM, and 8 MB is rarely ever
noticable, but allows longer MixRamp-assisted cross-fading.
2021-12-06 23:05:45 +01:00
Max Kellermann
b6ba17a865 Merge branch 'v0.23.x' 2021-12-06 21:32:48 +01:00
Max Kellermann
713c7585b5 pcm/MixRampAnalyzer: a MixRamp implementation 2021-12-06 21:09:28 +01:00
Max Kellermann
f12c25b7ae pcm/ReplayGainAnalyzer: new library 2021-12-06 21:06:19 +01:00
Max Kellermann
0a54b987a1 test/run_filter: move ReadFrames() to separate source 2021-12-06 10:31:52 +01:00
Max Kellermann
2240327286 ReplayGainInfo: move to tag/ 2021-12-06 09:28:36 +01:00
Max Kellermann
866e7ff3ce config/PlayerConfig: move code to functions 2021-12-06 09:14:36 +01:00
Max Kellermann
2cafbb2aba player/CrossFade: move code to CanCrossFade() 2021-12-03 23:45:34 +01:00
Max Kellermann
b78c64376f player/Thread: move code to CheckCrossFade() 2021-12-03 23:32:41 +01:00
Max Kellermann
2518612b1b player/CrossFade: add method IsMixRampEnabled() 2021-12-03 23:22:55 +01:00
Max Kellermann
dda521a150 ReplayGain{Config,Global}: move to config/ 2021-12-03 23:08:16 +01:00
Max Kellermann
95a155b10d Partition: pass configuration as struct 2021-12-03 23:03:41 +01:00
Max Kellermann
2384a240e0 increment version number to 0.24 2021-12-03 23:01:43 +01:00
1951 changed files with 36098 additions and 49727 deletions
.github
.gitignore.readthedocs.yaml.travis.ymlAUTHORS
LICENSES
NEWSREADME.md
android
build
doc

@ -24,3 +24,4 @@ about: Create a bug report
## Log
<!-- Paste relevant portions of the log file here (--verbose) -->
<!-- If MPD has crashed, include a backtrace (see https://mpd.readthedocs.io/en/stable/user.html#mpd-crashes) -->

6
.github/dependabot.yml vendored Normal file

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

@ -3,6 +3,11 @@ on:
workflow_dispatch:
push:
paths-ignore:
- 'AUTHORS'
- 'COPYING'
- 'LICENSES/**'
- 'NEWS'
- 'README.md'
- 'android/**'
- 'build/**'
- 'doc/**'
@ -15,6 +20,11 @@ on:
- v0.23.x
pull_request:
paths-ignore:
- 'AUTHORS'
- 'COPYING'
- 'LICENSES/**'
- 'NEWS'
- 'README.md'
- 'android/**'
- 'build/**'
- 'doc/**'
@ -26,24 +36,52 @@ on:
- master
- v0.23.x
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build-linux:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: [gcc14, gcc12, clang]
include:
- compiler: gcc14
os: ubuntu-24.04
cc: gcc-14
cxx: g++-14
packages: g++-14
meson_options:
- compiler: gcc12
os: ubuntu-24.04
cc: gcc-12
cxx: g++-12
packages: g++-12
meson_options:
- compiler: clang
os: ubuntu-24.04
cc: clang
cxx: clang++
packages: clang
meson_options: --force-fallback-for=fmt,gtest
runs-on: ${{ matrix.os }}
env:
CC: 'ccache gcc-10'
CXX: 'ccache g++-10'
CC: ccache ${{ matrix.cc }}
CXX: ccache ${{ matrix.cxx }}
steps:
- id: checkout
uses: actions/checkout@v2
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: linux
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
g++-10 libfmt-dev libboost-dev \
${{ matrix.packages }} \
meson \
ccache \
libfmt-dev \
libgtest-dev \
libpcre2-dev \
libsystemd-dev libdbus-1-dev \
@ -73,83 +111,225 @@ jobs:
libchromaprint-dev \
libgcrypt20-dev
- name: Full Build
uses: BSFishy/meson-build@v1.0.3
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
action: build
directory: output/full
setup-options: -Ddocumentation=disabled -Dtest=true -Dsystemd=enabled -Dpcre=enabled
options: --verbose
meson-version: 0.56.0
key: ${{ matrix.os }}-${{ matrix.compiler }}
- name: Configure
run: |
meson setup \
-Ddocumentation=disabled \
-Dtest=true \
-Dsystemd=enabled \
-Dpcre=enabled \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/full
- name: Build
run: meson compile -C output/full --verbose
- name: Unit Tests
uses: BSFishy/meson-build@v1.0.3
with:
action: test
directory: output/full
setup-options: -Ddocumentation=disabled -Dtest=true -Dsystemd=enabled -Dpcre=enabled
options: --verbose
meson-version: 0.56.0
run: meson test -C output/full --print-errorlogs
- name: Mini Build
uses: BSFishy/meson-build@v1.0.3
with:
action: build
directory: output/mini
setup-options: -Dbuildtype=minsize -Dauto_features=disabled -Dtest=true -Ddaemon=false -Dinotify=false -Depoll=false -Deventfd=false -Dsignalfd=false -Dtcp=false -Ddsd=false -Ddatabase=false -Dneighbor=false -Dcue=false -Dfifo=false -Dhttpd=false -Dpipe=false -Drecorder=false -Dsnapcast=false
options: --verbose
meson-version: 0.56.0
- name: Configure Mini
run: |
meson setup \
-Dbuildtype=minsize \
-Dauto_features=disabled \
-Dtest=true \
-Ddaemon=false \
-Dinotify=false -Depoll=false -Deventfd=false \
-Dsignalfd=false \
-Dtcp=false \
-Ddsd=false \
-Ddatabase=false \
-Dneighbor=false \
-Dcue=false \
-Dfifo=false \
-Dhttpd=false -Dpipe=false -Drecorder=false \
-Dsnapcast=false \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/mini
- name: Build Mini
run: meson compile -C output/mini --verbose
- name: Unit Tests Mini
run: meson test -C output/mini --print-errorlogs
build-macos:
runs-on: macos-latest
strategy:
matrix:
compiler: [clang]
include:
- compiler: clang
os: macos-latest
cc: clang
cxx: clang++
brew_packages: >
meson ninja
pkgconf
ccache
expat
fmt
googletest
pcre2
icu4c
ffmpeg
libnfs
libupnp
libid3tag
chromaprint
libsamplerate
libsoxr
flac
opus
libvorbis
faad2
sqlite
wavpack
libmpdclient
meson_options: --force-fallback-for=fmt,gtest
runs-on: ${{ matrix.os }}
env:
CC: ccache ${{ matrix.cc }}
CXX: ccache ${{ matrix.cxx }}
steps:
- id: checkout
uses: actions/checkout@v2
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: macos
- uses: actions/setup-python@v1
uses: actions/checkout@v4
- name: Install dependencies
run: |
brew update
brew install \
meson ninja \
fmt \
boost \
googletest \
icu4c \
ffmpeg \
libnfs \
yajl \
libupnp \
libid3tag \
chromaprint \
libsamplerate \
libsoxr \
flac \
opus \
libvorbis \
faad2 \
wavpack \
libmpdclient
${{ matrix.brew_packages }}
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ matrix.os }}-${{ matrix.compiler }}
- name: Configure
run: |
meson setup \
-Ddocumentation=disabled \
-Dtest=true \
-Dpcre=enabled \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/full
- name: Build
uses: BSFishy/meson-build@v1.0.3
with:
action: build
directory: output
setup-options: -Ddocumentation=disabled -Dtest=true
options: --verbose
meson-version: 0.56.0
run: meson compile -C output/full --verbose
- name: Unit Tests
uses: BSFishy/meson-build@v1.0.3
run: meson test -C output/full --print-errorlogs
- name: Configure Mini
run: |
meson setup \
-Dbuildtype=minsize \
-Dauto_features=disabled \
-Dtest=true \
-Ddaemon=false \
-Dinotify=false -Depoll=false -Deventfd=false \
-Dsignalfd=false \
-Dtcp=false \
-Ddsd=false \
-Ddatabase=false \
-Dneighbor=false \
-Dcue=false \
-Dfifo=false \
-Dhttpd=false -Dpipe=false -Drecorder=false \
-Dsnapcast=false \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/mini
- name: Build Mini
run: meson compile -C output/mini --verbose
- name: Unit Tests Mini
run: meson test -C output/mini --print-errorlogs
build-msys2:
strategy:
matrix:
platform: ['MINGW64', 'UCRT64']
defaults:
run:
shell: msys2 {0}
runs-on: windows-latest
steps:
- id: checkout
uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
with:
action: test
directory: output
setup-options: -Ddocumentation=disabled -Dtest=true
options: --verbose
meson-version: 0.56.0
msystem: ${{matrix.platform}}
pacboy: >-
cc:p
ccache:p
cmake:p
dbus:p
faad2:p
ffmpeg:p
fmt:p
flac:p
gtest:p
jack2:p
libao:p
libid3tag:p
libmad:p
libmpcdec:p
libopenmpt:p
libsamplerate:p
libshout:p
libsndfile:p
libsoxr:p
libvorbis:p
meson:p
ninja:p
opus:p
pulseaudio:p
shine:p
twolame:p
yajl:p
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ matrix.platform }}
- name: Configure
run: |
meson setup \
-Dbzip2=disabled \
-Dcdio_paranoia=disabled \
-Dchromaprint=disabled \
-Ddocumentation=disabled \
-Dfluidsynth=disabled \
-Dicu=disabled \
-Diso9660=disabled \
-Dmikmod=disabled \
-Dmpg123=disabled \
-Dnfs=disabled \
-Dsidplay=disabled \
-Dudisks=disabled \
-Dupnp=disabled \
-Dwavpack=disabled \
-Dzzip=disabled \
-Dtest=true \
"${{github.workspace}}/build"
- name: Build
run: meson compile -C "${{github.workspace}}/build" --verbose
- name: Unit Tests
run: meson test -C "${{github.workspace}}/build" --print-errorlogs

68
.github/workflows/build_android.yml vendored Normal file

@ -0,0 +1,68 @@
---
on:
workflow_dispatch:
push:
paths-ignore:
- 'AUTHORS'
- 'COPYING'
- 'LICENSES/**'
- 'NEWS'
- 'README.md'
- 'build/**'
- 'doc/**'
- 'subprojects/**'
- 'systemd/**'
- 'win32/**'
branches:
- master
pull_request:
paths-ignore:
- 'AUTHORS'
- 'COPYING'
- 'LICENSES/**'
- 'NEWS'
- 'README.md'
- 'build/**'
- 'doc/**'
- 'subprojects/**'
- 'systemd/**'
- 'win32/**'
branches:
- master
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build-android:
runs-on: ubuntu-24.04
steps:
- id: checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
meson \
ccache \
quilt
- id: cache-ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: android
- name: Build
run: |
mkdir -p output/android
cd ./output/android
../../android/build.py $ANDROID_SDK_ROOT $ANDROID_NDK_HOME arm64-v8a \
--buildtype=debugoptimized -Db_ndebug=true \
-Dwrap_mode=forcefallback
cd -
cd ./android
export JAVA_HOME=$JAVA_HOME_17_X64
./gradlew assembleDebug

8
.gitignore vendored

@ -1,11 +1,3 @@
*~
.#*
.stgit*
/output/
__pycache__/
/.clangd/
/compile_commands.json

19
.readthedocs.yaml Normal file

@ -0,0 +1,19 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.12"
python:
install:
- requirements: "doc/requirements.txt"
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: doc/conf.py

@ -1,117 +0,0 @@
language: cpp
jobs:
include:
# Ubuntu Focal (20.04) with GCC 9.3
- os: linux
dist: focal
addons:
apt:
packages:
- meson
- libgtest-dev
- libboost-dev
- libfmt-dev
# Ubuntu Focal (20.04) with GCC 9.3 on big-endian
- os: linux
arch: s390x
dist: focal
addons:
apt:
packages:
- meson
- libgtest-dev
- libboost-dev
- libfmt-dev
# Ubuntu Focal (20.04) with GCC 9.3 on ARM64
- os: linux
arch: arm64
dist: focal
addons:
apt:
packages:
- meson
- libgtest-dev
- libboost-dev
- libfmt-dev
# Ubuntu Trusty (16.04) with GCC 8
- os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
- sourceline: 'ppa:ricotz/toolchain'
- sourceline: 'ppa:deadsnakes/ppa' # for Python 3.7 (required by Meson)
packages:
- g++-8
- libgtest-dev
- boost1.67
- python3.6
- python3-urllib3
- ninja-build
before_install:
- wget https://bootstrap.pypa.io/get-pip.py
- /usr/bin/python3.6 get-pip.py --user --no-cache-dir
install:
- /usr/bin/python3.6 $HOME/.local/bin/pip install --user meson --no-cache-dir
env:
# use gold as workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17068
- MATRIX_EVAL="export CC='ccache gcc-8' CXX='ccache g++-8' LDFLAGS=-fuse-ld=gold PATH=\$HOME/.local/bin:\$PATH"
- os: osx
osx_image: xcode11.6
addons:
homebrew:
packages:
- ccache
- meson
- fmt
- googletest
- icu4c
- ffmpeg
- libnfs
- yajl
- libupnp
- libid3tag
- chromaprint
- libsamplerate
- libsoxr
# libzzip appears to be broken on Homebrew: "ld: library not found for -lzzip"
#- libzzip
- flac
- opus
- libvorbis
- faad2
- wavpack
- libmpdclient
env:
- MATRIX_EVAL="export PATH=/usr/local/opt/ccache/libexec:$PATH HOMEBREW_NO_ANALYTICS=1"
cache:
apt: true
ccache: true
directories:
- $HOME/Library/Caches/Homebrew
before_cache:
- test "$TRAVIS_OS_NAME" != "osx" || brew cleanup
before_install:
- eval "${MATRIX_EVAL}"
install:
before_script:
- ccache -s
script:
- eval "${MATRIX_EVAL}"
- OPTIONS="-Dtest=true"
- meson . output --werror $OPTIONS
- ninja -C output -v test
- ccache -s

@ -1,5 +1,5 @@
Music Player Daemon - http://www.musicpd.org
Copyright 2003-2021 The Music Player Daemon Project
Copyright 2003-2025 The Music Player Daemon Project
The following people have contributed code to MPD:

@ -0,0 +1,9 @@
Copyright (c) <year> <owner>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,117 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice

8
LICENSES/ISC.txt Normal file

@ -0,0 +1,8 @@
ISC License:
Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
Copyright (c) 1995-2003 by Internet Software Consortium
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

175
LICENSES/LGPL-2.1-only.txt Normal file

@ -0,0 +1,175 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the library's name and an idea of what it does.
Copyright (C) year name of author
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.
signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

93
NEWS

@ -1,3 +1,94 @@
ver 0.24.1 (not yet released)
* output
- sndio: fix rounding error in volume calculation
* log: include year in time stamp
* macOS: implement standard directories
* fix build failure in the "id3tag" Meson subproject
* doc: use "sphinx_rtd_theme" only if it is installed
ver 0.24 (2025/03/11)
* protocol
- new command "searchcount" (case-insensitive "count")
- "playlistfind"/"playlistsearch" have "sort" and "window" parameters
- allow range in "playlistmove"
- "save" can append to or replace an existing playlist
- filter "prio" (for "playlistfind"/"playlistsearch")
- limit "player" idle events to the current partition
- operator "starts_with"
- show PCRE support in "config" response
- apply Unicode normalization to case-insensitive filter expressions
- stickers on playlists and some tag types
- new commands "stickernames", "stickertypes", "stickernamestypes", "playlistlength", "searchplaylist", "protocol"
- new "search"/"find" filter "added-since"
- allow range in listplaylist and listplaylistinfo
- "sticker find" supports sort and window parameter and new sticker compare operators "eq", "lt", "gt", "contains" and "starts_with"
- consume only idle flags that were subscribed to
- volume command is no longer deprecated
- new "available" and "reset" subcommands for tagtypes
- searching stored playlists respond now with song position
- new sticker subcommand "inc" and "dec"
* database
- attribute "added" shows when each song was added to the database
- proxy: require MPD 0.21 or later
- proxy: require libmpdclient 2.15 or later
* archive
- add option to disable archive plugins in mpd.conf
* storage
- curl: optimize database update
- nfs: require libnfs 4.0 or later
- nfs: support libnfs 6 (API version 2)
- nfs: support libnfs URL arguments
* input
- alsa: limit ALSA buffer time to 2 seconds
- alsa: set up a channel map
- alsa: support the alsa-lib 1.2.11 API
- alsa: add option "close_on_pause"
- curl: add "connect_timeout" configuration
* decoder
- ffmpeg: require FFmpeg 4.0 or later
- ffmpeg: query supported demuxers at runtime
- hybrid_dsd: remove
- mpg123: prefer over "mad"
- mpg123: support streaming
- opus: implement bitrate calculation
- sidplay: require libsidplayfp (drop support for the original sidplay)
- wavpack: require libwavpack version 5
- fix MixRamp bug
* resampler
- soxr: require libsoxr 0.1.2 or later
* player
- add option "mixramp_analyzer" to scan MixRamp tags on-the-fly
- "one-shot" consume mode
* tags
- new tags "TitleSort", "Mood", "ShowMovement"
* output
- add option "always_off"
- alsa: require alsa-lib 1.1 or later
- pipewire: map tags "Date" and "Comment"
* switch to C++20
- GCC 12 or clang 14 (or newer) recommended
* static partition configuration
* Windows
- build with libsamplerate
- remove JACK DLL support
* remove Haiku support
* remove Boost dependency
* require libfmt 9 or later
* documentation: switch to sphinx-rtd-theme
* require Meson 1.0
ver 0.23.17 (2025/01/29)
* protocol
- "albumart" tries to send larger chunks if available
- explicitly disallow "idle" and "noidle" in command lists
* storage
- nfs: require libnfs 4.0 or later
* database
- inotify: trigger update after symlink was created
* decoder
- ffmpeg: prefer over sndfile and audiofile for its DTS-WAV support
* support libfmt 11.1
ver 0.23.16 (2024/12/03)
* database
- fix integer overflows with 64-bit inode numbers
@ -958,7 +1049,7 @@ ver 0.20.10 (2017/08/24)
* decoder
- ffmpeg: support MusicBrainz ID3v2 tags
* tags
- aiff: fix FORM chunk size endianess (is big-endian)
- aiff: fix FORM chunk size endianness (is big-endian)
* mixer
- osx: add a mixer for OSX.
* fix crash when resuming playback before decoder is ready

@ -12,15 +12,15 @@ For basic installation instructions
# Users
- [Manual](http://www.musicpd.org/doc/user/)
- [Forum](http://forum.musicpd.org/)
- [Manual](https://mpd.readthedocs.io/en/stable/user.html)
- [Forum](https://github.com/MusicPlayerDaemon/MPD/discussions)
- [IRC](ircs://irc.libera.chat:6697/#mpd)
- [Bug tracker](https://github.com/MusicPlayerDaemon/MPD/issues/)
# Developers
- [Protocol specification](http://www.musicpd.org/doc/protocol/)
- [Developer manual](http://www.musicpd.org/doc/developer/)
- [Protocol specification](https://mpd.readthedocs.io/en/latest/protocol.html)
- [Developer manual](https://mpd.readthedocs.io/en/latest/developer.html)
# Legal

24
android/.gitignore vendored Normal file

@ -0,0 +1,24 @@
*.iml
.gradle
/local.properties
## ignoring .idea completely
# until a good reason emerges not to
/.idea
##--
## moved the following into .idea/.gitignore
#/.idea/caches
#/.idea/libraries
#/.idea/modules.xml
#/.idea/workspace.xml
#/.idea/navEditor.xml
#/.idea/assetWizardSettings.xml
## --
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
# both were used: different spelling
app/src/main/jnilibs/
app/src/main/jniLibs/

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.musicpd"
android:installLocation="auto"
android:versionCode="74"
android:versionName="0.23.16">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30"/>
<uses-feature android:name="android.software.leanback"
android:required="false" />
<uses-feature android:name="android.hardware.touchscreen"
android:required="false" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application android:allowBackup="true"
android:debuggable="true"
android:requestLegacyExternalStorage="true"
android:icon="@drawable/icon"
android:banner="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".Settings"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Settings"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Receiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".Main" android:process=":main"/>
</application>
</manifest>

@ -0,0 +1,8 @@
MPD for Android Privacy Policy
==============================
Music Player Daemon is an open source project currently maintained by
`Max Kellermann <mailto:max.kellermann+googleplay@gmail.com>`__.
Music Player Daemon does not access, collect, use or share any
personal or sensitive user data.

49
android/README.md Normal file

@ -0,0 +1,49 @@
# Android
Notes and resources for MPD android maintainers.
## Build
See [Compiling for Android](https://github.com/MusicPlayerDaemon/MPD/blob/45cb098cd765af12316f8dca5635ef10a852e013/doc/user.rst#compiling-for-android)
## Android studio
### Version control
git ignoring .idea directory completely until a good reason emerges not to
* [How to manage projects under Version Control Systems (jetbrains.com)](https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems)
* [gradle.xml should work like workspace.xml? (jetbrains.com)](https://youtrack.jetbrains.com/issue/IDEA-55923)
### Native libraries
* [Include prebuilt native libraries (developer.android.com)](https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs)
## Permissions
### Files access
The required permission depends on android SDK version:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
Manifest.permission.READ_MEDIA_AUDIO
else
Manifest.permission.READ_EXTERNAL_STORAGE
### Permission request
[Request runtime permissions](https://developer.android.com/training/permissions/requesting)
Since Android 6.0 (API level 23):
Android will ignore permission request and will not show the request dialog
if the user's action implies "don't ask again."
This leaves the app in a crippled state and the user confused.
Google says "don't try to convince the user", so it returns false for `shouldShowRequestPermissionRationale`.
To help the user proceed, we show the `Request permission` button only if `shouldShowRequestPermissionRationale == true`
because there's a good chance the permission request dialog will not be ignored.
If `shouldShowRequestPermissionRationale == false` we instead show the "rationale" message and a button to open
the app info dialog where the user can explicitly grand the permission.

@ -1,21 +0,0 @@
#!/bin/sh -e
S=`dirname "$0"`
ANDROID_ABI=$1
STRIP=$2
ZIP=$3
UNSIGNED_APK=$4
LIBMPD_SO=$5
CLASSES_DEX=$6
RESOURCES_APK=$7
D=`dirname "$UNSIGNED_APK"`
rm -rf "$D/apk"
mkdir -p "$D/apk/lib/$ANDROID_ABI"
"$STRIP" "$LIBMPD_SO" -o "$D/apk/lib/$ANDROID_ABI/`basename $LIBMPD_SO`"
cp "$CLASSES_DEX" "$D/apk/"
cp "$RESOURCES_APK" "$UNSIGNED_APK"
cd "$D/apk"
exec zip -q -r -X "../`basename $UNSIGNED_APK`" .

@ -1,58 +0,0 @@
unsigned_apk = custom_target(
'mpd-unsigned.apk',
output: 'mpd-unsigned.apk',
input: [mpd, classes_dex, resources_apk[0]],
command: [
join_paths(meson.current_source_dir(), 'make-unsigned-apk.sh'),
android_abi,
get_option('android_strip'),
zip,
'@OUTPUT0@',
'@INPUT@',
],
)
aligned_apk = custom_target(
'mpd-aligned.apk',
output: 'mpd-aligned.apk',
input: unsigned_apk,
command: [
android_zipalign,
'-f', '4',
'@INPUT@', '@OUTPUT@',
],
)
if get_option('android_debug_keystore') != ''
debug_apk = custom_target(
'mpd-debug.apk',
output: 'mpd-debug.apk',
input: aligned_apk,
command: [
apksigner, 'sign',
'--in', '@INPUT@',
'--out', '@OUTPUT@',
'--debuggable-apk-permitted',
'-ks', get_option('android_debug_keystore'),
'--ks-key-alias', 'androiddebugkey',
'--ks-pass', 'pass:android',
],
build_by_default: true
)
endif
if get_option('android_keystore') != '' and get_option('android_keyalias') != '' and get_option('android_keypass') != ''
unaligned_apk = custom_target(
'mpd.apk',
output: 'mpd.apk',
input: aligned_apk,
command: [
apksigner, 'sign',
'--in', '@INPUT@',
'--out', '@OUTPUT@',
'-ks', get_option('android_keystore'),
'--ks-key-alias', get_option('android_keyalias'),
'--ks-pass', 'pass:' + get_option('android_keypass'),
],
)
endif

1
android/app/.gitignore vendored Normal file

@ -0,0 +1 @@
/build

@ -0,0 +1,128 @@
plugins {
id("com.google.devtools.ksp")
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.dagger.hilt.android)
}
android {
namespace = "org.musicpd"
compileSdk = 35
defaultConfig {
applicationId = "org.musicpd"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
vectorDrawables {
useSupportLibrary = true
}
}
buildFeatures {
aidl = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.10"
}
buildTypes {
debug {
isMinifyEnabled = false
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
// flavors
flavorDimensions += "base"
productFlavors {
create("fail-test") {
// To test System.loadLibrary("mpd") failure
// exclude the native lib from the package
packaging {
jniLibs {
// it appears the 'excludes' is applied to all flavors
// even if it's only inside this flavor.
// this filters by task name to apply the exclusion only
// for this flavor name.
// (clearing the 'abiFilters' will only create a universal apk
// with all of the abi versions)
gradle.startParameter.getTaskNames().forEach { task ->
if (task.contains("fail-test", ignoreCase = true)) {
println("NOTICE: excluding libmpd.so from package $task for testing")
excludes += "**/libmpd.so"
}
}
}
}
}
create("arm64-v8a") {
ndk {
// ABI to include in package
//noinspection ChromeOsAbiSupport
abiFilters += listOf("arm64-v8a")
}
}
create("x86_64") {
ndk {
// ABI to include in package
abiFilters += listOf("x86_64")
}
}
create("universal") {
ndk {
// ABI to include in package
abiFilters += listOf("arm64-v8a", "x86_64")
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_9
targetCompatibility = JavaVersion.VERSION_1_9
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_9.toString()
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.material3)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.material.icons.extended)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.compose.settings.ui.m3)
implementation(libs.compose.settings.storage.preferences)
implementation(libs.accompanist.permissions)
implementation(libs.hilt.android)
ksp(libs.dagger.compiler)
ksp(libs.hilt.compiler)
implementation(libs.androidx.media3.session)
// Android Studio Preview support
implementation(libs.androidx.ui.tooling.preview)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.androidx.appcompat)
}

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
android:versionCode="73"
android:versionName="0.23.15">
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<application
android:allowBackup="true"
android:banner="@mipmap/ic_banner"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.MPD"
android:name=".MPDApplication">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".Receiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver android:name=".AutomationReceiver"
android:exported="true">
<intent-filter>
<action android:name="org.musicpd.action.StartService" />
</intent-filter>
<intent-filter>
<action android:name="org.musicpd.action.StopService" />
</intent-filter>
</receiver>
<service
android:name=".Main"
android:foregroundServiceType="mediaPlayback"
/>
</application>
</manifest>

@ -5,5 +5,4 @@ interface IMainCallback
void onStarted();
void onStopped();
void onError(String error);
void onLog(int priority, String msg);
}

Binary file not shown.

After

(image error) Size: 49 KiB

@ -0,0 +1,24 @@
package org.musicpd
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class AutomationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when(intent.action) {
"org.musicpd.action.StartService" -> {
val wakelock = Preferences.getBoolean(
context,
Preferences.KEY_WAKELOCK, false
)
Main.startService(context, wakelock)
}
"org.musicpd.action.StopService" -> {
context.startService(Intent(context, Main::class.java)
.setAction(Main.SHUTDOWN_ACTION))
}
}
}
}

@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
package org.musicpd;
import android.content.Context;
/**
* Bridge to native code.
*/
public class Bridge {
/* used by jni */
public interface LogListener {
public void onLog(int priority, String msg);
}
public static native void run(Context context, LogListener logListener);
public static native void shutdown();
public static native void pause();
public static native void playPause();
public static native void playNext();
public static native void playPrevious();
}

@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
package org.musicpd
import android.content.Context
import android.os.Build
import android.util.Log
object Loader {
private const val TAG = "Loader"
private var loaded: Boolean = false
private var error: String? = null
private val failReason: String get() = error ?: ""
val isLoaded: Boolean get() = loaded
init {
load()
}
private fun load() {
if (loaded) return
loaded = try {
error = null
System.loadLibrary("mpd")
Log.i(TAG, "mpd lib loaded")
true
} catch (e: Throwable) {
error = e.message ?: e.javaClass.simpleName
Log.e(TAG, "failed to load mpd lib: $failReason")
false
}
}
fun loadFailureMessage(context: Context): String {
return context.getString(
R.string.mpd_load_failure_message,
Build.SUPPORTED_ABIS.joinToString(),
Build.PRODUCT,
Build.FINGERPRINT,
failReason
)
}
}

@ -0,0 +1,9 @@
package org.musicpd
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MPDApplication : Application() {
}

@ -0,0 +1,76 @@
package org.musicpd;
import android.annotation.SuppressLint;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.media3.common.Player;
import androidx.media3.common.SimpleBasePlayer;
import androidx.media3.common.util.UnstableApi;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Arrays;
import java.util.List;
@UnstableApi
public class MPDPlayer extends SimpleBasePlayer {
List<MediaItemData> placeholderItems;
public MPDPlayer(Looper looper) {
super(looper);
// Dummy items to let us receive next and previous commands
MediaItemData item0 = new MediaItemData.Builder(0)
.build();
MediaItemData item1 = new MediaItemData.Builder(1)
.build();
MediaItemData item2 = new MediaItemData.Builder(2)
.build();
MediaItemData[] items = new MediaItemData[] { item0, item1, item2 };
placeholderItems = Arrays.asList(items);
}
@NonNull
@Override
protected State getState() {
Commands commands = new Commands.Builder().addAll(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM,
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM,
COMMAND_PLAY_PAUSE
).build();
return new State.Builder()
.setAvailableCommands(commands)
.setPlaybackState(Player.STATE_READY)
.setPlaylist(placeholderItems)
.setCurrentMediaItemIndex(1)
.build();
}
@NonNull
@Override
protected ListenableFuture<?> handleSetPlayWhenReady(boolean playWhenReady) {
Bridge.playPause();
return Futures.immediateVoidFuture();
}
@NonNull
@SuppressLint("SwitchIntDef")
@Override
protected ListenableFuture<?> handleSeek(int mediaItemIndex, long positionMs, int seekCommand) {
switch (seekCommand) {
case COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM:
case COMMAND_SEEK_TO_PREVIOUS:
Bridge.playPrevious();
break;
case COMMAND_SEEK_TO_NEXT_MEDIA_ITEM:
case COMMAND_SEEK_TO_NEXT:
Bridge.playNext();
break;
}
return Futures.immediateVoidFuture();
}
}

@ -0,0 +1,326 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
package org.musicpd
import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.media.AudioManager
import android.os.Build
import android.os.IBinder
import android.os.Looper
import android.os.PowerManager
import android.os.PowerManager.WakeLock
import android.os.RemoteCallbackList
import android.os.RemoteException
import android.util.Log
import androidx.annotation.OptIn
import androidx.core.app.ServiceCompat
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaSession
import dagger.hilt.android.AndroidEntryPoint
import org.musicpd.Bridge.LogListener
import org.musicpd.data.LoggingRepository
import java.lang.reflect.Constructor
import javax.inject.Inject
@AndroidEntryPoint
class Main : Service(), Runnable {
companion object {
private const val TAG = "Main"
private const val WAKELOCK_TAG = "mpd:wakelockmain"
private const val MAIN_STATUS_ERROR = -1
private const val MAIN_STATUS_STOPPED = 0
private const val MAIN_STATUS_STARTED = 1
private const val MSG_SEND_STATUS = 0
const val SHUTDOWN_ACTION: String = "org.musicpd.action.ShutdownMPD"
/*
* start Main service without any callback
*/
@JvmStatic
fun startService(context: Context, wakelock: Boolean) {
val intent = Intent(context, Main::class.java)
.putExtra("wakelock", wakelock)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) /* in Android 8+, we need to use this method
or else we'll get "IllegalStateException:
app is in background" */
context.startForegroundService(intent)
else context.startService(intent)
}
}
private lateinit var mpdApp: MPDApplication
private lateinit var mpdLoader: Loader
private var mThread: Thread? = null
private var mStatus = MAIN_STATUS_STOPPED
private var mAbort = false
private var mError: String? = null
private val mCallbacks = RemoteCallbackList<IMainCallback>()
private val mBinder: IBinder = MainStub(this)
private var mPauseOnHeadphonesDisconnect = false
private var mWakelock: WakeLock? = null
private var mMediaSession: MediaSession? = null
@JvmField
@Inject
var logging: LoggingRepository? = null
internal class MainStub(private val mService: Main) : IMain.Stub() {
override fun start() {
mService.start()
}
override fun stop() {
mService.stop()
}
override fun setPauseOnHeadphonesDisconnect(enabled: Boolean) {
mService.setPauseOnHeadphonesDisconnect(enabled)
}
override fun setWakelockEnabled(enabled: Boolean) {
mService.setWakelockEnabled(enabled)
}
override fun isRunning(): Boolean {
return mService.isRunning
}
override fun registerCallback(cb: IMainCallback) {
mService.registerCallback(cb)
}
override fun unregisterCallback(cb: IMainCallback) {
mService.unregisterCallback(cb)
}
}
override fun onCreate() {
super.onCreate()
mpdLoader = Loader
}
@Synchronized
private fun sendMessage(
@Suppress("SameParameterValue") what: Int,
arg1: Int,
arg2: Int,
obj: Any?
) {
var i = mCallbacks.beginBroadcast()
while (i > 0) {
i--
val cb = mCallbacks.getBroadcastItem(i)
try {
when (what) {
MSG_SEND_STATUS -> when (arg1) {
MAIN_STATUS_ERROR -> cb.onError(obj as String?)
MAIN_STATUS_STOPPED -> cb.onStopped()
MAIN_STATUS_STARTED -> cb.onStarted()
}
}
} catch (ignored: RemoteException) {
}
}
mCallbacks.finishBroadcast()
}
private val mLogListener = LogListener { priority, msg ->
logging?.addLogItem(priority, msg)
}
override fun onBind(intent: Intent): IBinder {
return mBinder
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.action == SHUTDOWN_ACTION) {
stop()
} else {
start()
if (intent?.getBooleanExtra(
"wakelock",
false
) == true
) setWakelockEnabled(true)
}
return START_REDELIVER_INTENT
}
override fun run() {
synchronized(this) {
if (mAbort) return
setStatus(MAIN_STATUS_STARTED, null)
}
Bridge.run(this, mLogListener)
setStatus(MAIN_STATUS_STOPPED, null)
}
@Synchronized
private fun setStatus(status: Int, error: String?) {
mStatus = status
mError = error
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError)
}
private fun createNotificationBuilderWithChannel(): Notification.Builder? {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
?: return null
val id = "org.musicpd"
val name = "MPD service"
val importance = 3 /* NotificationManager.IMPORTANCE_DEFAULT */
try {
val ncClass = Class.forName("android.app.NotificationChannel")
val ncCtor = ncClass.getConstructor(
String::class.java,
CharSequence::class.java,
Int::class.javaPrimitiveType
)
val nc = ncCtor.newInstance(id, name, importance)
val nmCreateNotificationChannelMethod =
NotificationManager::class.java.getMethod("createNotificationChannel", ncClass)
nmCreateNotificationChannelMethod.invoke(notificationManager, nc)
val nbCtor: Constructor<*> = Notification.Builder::class.java.getConstructor(
Context::class.java, String::class.java
)
return nbCtor.newInstance(this, id) as Notification.Builder
} catch (e: Exception) {
Log.e(TAG, "error creating the NotificationChannel", e)
return null
}
}
@OptIn(markerClass = [UnstableApi::class])
private fun start() {
if (mThread != null) return
val filter = IntentFilter()
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (!mPauseOnHeadphonesDisconnect) return
if (intent.action === AudioManager.ACTION_AUDIO_BECOMING_NOISY) pause()
}
}, filter)
val mainIntent = Intent(this, MainActivity::class.java)
mainIntent.setAction("android.intent.action.MAIN")
mainIntent.addCategory("android.intent.category.LAUNCHER")
val contentIntent = PendingIntent.getActivity(
this, 0,
mainIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val nBuilder: Notification.Builder?
if (Build.VERSION.SDK_INT >= 26 /* Build.VERSION_CODES.O */) {
nBuilder = createNotificationBuilderWithChannel()
if (nBuilder == null) return
} else nBuilder = Notification.Builder(this)
val notification =
nBuilder.setContentTitle(getText(R.string.notification_title_mpd_running))
.setContentText(getText(R.string.notification_text_mpd_running))
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(contentIntent)
.build()
if (mpdLoader.isLoaded) {
mThread = Thread(this).apply { start() }
}
val player = MPDPlayer(Looper.getMainLooper())
mMediaSession = MediaSession.Builder(this, player).build()
startForeground(R.string.notification_title_mpd_running, notification)
startService(Intent(this, Main::class.java))
}
private fun stop() {
mMediaSession?.let {
it.release()
mMediaSession = null
}
mThread?.let { thread ->
if (thread.isAlive) {
synchronized(this) {
if (mStatus == MAIN_STATUS_STARTED) Bridge.shutdown()
else mAbort = true
}
}
try {
thread.join()
mThread = null
mAbort = false
} catch (ie: InterruptedException) {
Log.e(TAG, "failed to join", ie)
}
}
setWakelockEnabled(false)
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
stopSelf()
}
private fun pause() {
if (mThread?.isAlive == true) {
synchronized(this) {
if (mStatus == MAIN_STATUS_STARTED) Bridge.pause()
}
}
}
private fun setPauseOnHeadphonesDisconnect(enabled: Boolean) {
mPauseOnHeadphonesDisconnect = enabled
}
private fun setWakelockEnabled(enabled: Boolean) {
if (enabled) {
val wakeLock =
mWakelock ?: run {
val pm = getSystemService(POWER_SERVICE) as PowerManager
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG).also {
mWakelock = it
}
}
wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/)
Log.d(TAG, "Wakelock acquired")
} else {
mWakelock?.let {
it.release()
mWakelock = null
}
Log.d(TAG, "Wakelock released")
}
}
private val isRunning: Boolean
get() = mThread?.isAlive == true
private fun registerCallback(cb: IMainCallback?) {
if (cb != null) {
mCallbacks.register(cb)
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError)
}
}
private fun unregisterCallback(cb: IMainCallback?) {
if (cb != null) {
mCallbacks.unregister(cb)
}
}
}

@ -0,0 +1,57 @@
package org.musicpd
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.material3.MaterialTheme
import androidx.core.view.WindowCompat
import dagger.hilt.android.AndroidEntryPoint
import org.musicpd.ui.MPDApp
import org.musicpd.ui.SettingsViewModel
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val settingsViewModel: SettingsViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
MaterialTheme {
MPDApp(settingsViewModel = settingsViewModel)
}
}
}
private fun connectClient() {
val client = MainServiceClient(this, object : MainServiceClient.Callback {
override fun onStopped() {
settingsViewModel.updateStatus("", false)
}
override fun onStarted() {
settingsViewModel.updateStatus("MPD Service Started", true)
}
override fun onError(error: String) {
settingsViewModel.removeClient()
settingsViewModel.updateStatus(error, false)
connectClient()
}
})
settingsViewModel.setClient(client)
}
override fun onStart() {
//mFirstRun = false
connectClient()
super.onStart()
}
override fun onStop() {
settingsViewModel.removeClient()
super.onStop()
}
}

@ -0,0 +1,157 @@
package org.musicpd;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
/*
* Client that bind the Main Service in order to send commands and receive callback
*/
public class MainServiceClient {
private static final String REMOTE_ERROR = "MPD process was killed";
public interface Callback {
public void onStarted();
public void onStopped();
public void onError(String error);
}
private boolean mBound = false;
private final Context mContext;
private Callback mCallback;
private IMain mIMain = null;
private final IMainCallback.Stub mICallback = new IMainCallback.Stub() {
@Override
public void onStopped() throws RemoteException {
mCallback.onStopped();
}
@Override
public void onStarted() throws RemoteException {
mCallback.onStarted();
}
@Override
public void onError(String error) throws RemoteException {
mCallback.onError(error);
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (this) {
mIMain = IMain.Stub.asInterface(service);
try {
if (mCallback != null)
mIMain.registerCallback(mICallback);
} catch (RemoteException e) {
if (mCallback != null)
mCallback.onError(REMOTE_ERROR);
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (mCallback != null)
mCallback.onError(REMOTE_ERROR);
}
};
public MainServiceClient(Context context, Callback cb) throws IllegalArgumentException {
if (context == null)
throw new IllegalArgumentException("Context can't be null");
mContext = context;
mCallback = cb;
mBound = mContext.bindService(new Intent(mContext, Main.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
public boolean start() {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.start();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean stop() {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.stop();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean setPauseOnHeadphonesDisconnect(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.setPauseOnHeadphonesDisconnect(enabled);
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean setWakelockEnabled(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.setWakelockEnabled(enabled);
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean isRunning() {
synchronized (this) {
if (mIMain != null) {
try {
return mIMain.isRunning();
} catch (RemoteException e) {
}
}
return false;
}
}
public void release() {
if (mBound) {
synchronized (this) {
if (mIMain != null && mICallback != null) {
try {
if (mCallback != null)
mIMain.unregisterCallback(mICallback);
} catch (RemoteException e) {
}
}
}
mBound = false;
mContext.unbindService(mServiceConnection);
}
}
}

@ -0,0 +1,34 @@
package org.musicpd;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import androidx.annotation.Nullable;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.List;
public class NetworkUtil {
@Nullable
public static String getDeviceIPV4Address(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
LinkProperties linkProperties = connectivityManager.getLinkProperties(connectivityManager.getActiveNetwork());
if (linkProperties != null) {
List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
for (LinkAddress address : linkAddresses) {
if (!address.getAddress().isLinkLocalAddress() && !address.getAddress().isLoopbackAddress()) {
InetAddress address1 = address.getAddress();
if (address1 instanceof Inet4Address) {
return address1.getHostAddress();
}
}
}
}
return null;
}
}

@ -0,0 +1,34 @@
package org.musicpd;
import static android.content.Context.MODE_PRIVATE;
import android.content.Context;
import android.content.SharedPreferences;
public class Preferences {
private static final String TAG = "Settings";
public static final String KEY_RUN_ON_BOOT ="run_on_boot";
public static final String KEY_WAKELOCK ="wakelock";
public static final String KEY_PAUSE_ON_HEADPHONES_DISCONNECT ="pause_on_headphones_disconnect";
public static SharedPreferences get(Context context) {
return context.getSharedPreferences(TAG, MODE_PRIVATE);
}
public static void putBoolean(Context context, String key, boolean value) {
final SharedPreferences prefs = get(context);
if (prefs == null)
return;
final SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(key, value);
editor.apply();
}
public static boolean getBoolean(Context context, String key, boolean defValue) {
final SharedPreferences prefs = get(context);
return prefs != null ? prefs.getBoolean(key, defValue) : defValue;
}
}

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
package org.musicpd;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.util.Set;
public class Receiver extends BroadcastReceiver {
private static final Set<String> BOOT_ACTIONS = Set.of(
"android.intent.action.BOOT_COMPLETED",
"android.intent.action.QUICKBOOT_POWERON"
);
@Override
public void onReceive(Context context, Intent intent) {
Log.d("Receiver", "onReceive: " + intent);
if (BOOT_ACTIONS.contains(intent.getAction())) {
if (Preferences.getBoolean(context,
Preferences.KEY_RUN_ON_BOOT,
false)) {
final boolean wakelock =
Preferences.getBoolean(context,
Preferences.KEY_WAKELOCK, false);
Main.startService(context, wakelock);
}
}
}
}

@ -0,0 +1,34 @@
package org.musicpd.data
import android.util.Log
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import javax.inject.Singleton
private const val MAX_LOGS = 500
@Singleton
class LoggingRepository @Inject constructor() {
private val _logItemFLow = MutableStateFlow(listOf<String>())
val logItemFLow: StateFlow<List<String>> = _logItemFLow
fun addLogItem(priority: Int, message: String) {
if (_logItemFLow.value.size > MAX_LOGS) {
_logItemFLow.value = _logItemFLow.value.drop(1)
}
val priorityString: String = when (priority) {
Log.DEBUG -> "D"
Log.ERROR -> "E"
Log.INFO -> "I"
Log.VERBOSE -> "V"
Log.WARN -> "W"
else -> ""
}
_logItemFLow.value = _logItemFLow.value + ("$priorityString/$message")
}
}

@ -0,0 +1,79 @@
package org.musicpd.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.VerticalAlignBottom
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Composable
fun LogView(messages: List<String>) {
val lazyListState = rememberLazyListState()
var userScrolled = remember { mutableStateOf(false) }
LaunchedEffect(lazyListState) {
snapshotFlow { lazyListState.isScrollInProgress }
.collect {
if (it) {
userScrolled.value = true
}
}
}
Box(Modifier.fillMaxSize()) {
LazyColumn(
Modifier.padding(4.dp),
lazyListState
) {
items(messages) { message ->
Text(text = message, fontFamily = FontFamily.Monospace)
}
CoroutineScope(Dispatchers.Main).launch {
lazyListState.scrollToItem(messages.count(), 0)
}
}
if (lazyListState.canScrollForward) {
FloatingActionButton(
onClick = {
userScrolled.value = false
CoroutineScope(Dispatchers.Main).launch {
lazyListState.scrollToItem(messages.count(), 0)
}
},
modifier = Modifier.padding(16.dp).align(Alignment.BottomEnd)
) {
Icon(Icons.Filled.VerticalAlignBottom, "Scroll to bottom icon")
}
}
}
}
@Preview
@Composable
fun LogViewPreview() {
val data = listOf("test",
"test2",
"test3")
LogView(data)
}

@ -0,0 +1,109 @@
package org.musicpd.ui
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.List
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
enum class Screen {
HOME,
LOGS,
SETTINGS,
}
sealed class NavigationItem(val route: String, val label: String, val icon: ImageVector) {
data object Home : NavigationItem(
Screen.HOME.name,
"Home",
Icons.Default.Home
)
data object Logs : NavigationItem(
Screen.LOGS.name,
"Logs",
Icons.AutoMirrored.Filled.List)
data object Settings : NavigationItem(
Screen.SETTINGS.name,
"Settings",
Icons.Default.Settings)
}
@Composable
fun MPDApp(
navController: NavHostController = rememberNavController(),
settingsViewModel: SettingsViewModel = viewModel()
) {
Scaffold(
topBar = {
},
bottomBar = {
BottomNavigationBar(navController)
},
) { innerPadding ->
NavHost(
navController = navController,
startDestination = NavigationItem.Home.route,
modifier = Modifier.padding(innerPadding)
) {
composable(NavigationItem.Home.route) {
StatusScreen(settingsViewModel)
}
composable(NavigationItem.Logs.route) {
LogView(settingsViewModel.getLogs().collectAsStateWithLifecycle().value)
}
composable(NavigationItem.Settings.route) {
MPDSettings(settingsViewModel)
}
}
}
}
@Composable
fun BottomNavigationBar(navController: NavController) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val items = listOf(
NavigationItem.Home,
NavigationItem.Logs,
NavigationItem.Settings,
)
NavigationBar {
items.forEach { item ->
NavigationBarItem(
icon = {
Icon(
imageVector = item.icon,
contentDescription = null
)
},
label = { Text (item.label) },
onClick = {
navController.navigate(item.route) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
},
selected = currentRoute == item.route,
)
}
}
}

@ -0,0 +1,39 @@
package org.musicpd.ui
import android.app.Application
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Wifi
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import org.musicpd.NetworkUtil
@Composable
fun NetworkAddress() {
val address = NetworkUtil.getDeviceIPV4Address(LocalContext.current)
val padding = 4.dp
Row(
Modifier
.padding(padding)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Icon(
imageVector = Icons.Default.Wifi,
contentDescription = "Wifi")
Spacer(Modifier.size(padding))
Text(text = address ?: "")
}
}

@ -0,0 +1,77 @@
package org.musicpd.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BatteryAlert
import androidx.compose.material.icons.filled.Headphones
import androidx.compose.material.icons.filled.PowerSettingsNew
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.alorma.compose.settings.storage.preferences.rememberPreferenceBooleanSettingState
import com.alorma.compose.settings.ui.SettingsSwitch
import org.musicpd.Preferences
import org.musicpd.R
@Composable
fun MPDSettings(settingsViewModel: SettingsViewModel) {
val context = LocalContext.current
Column(Modifier.fillMaxSize()) {
SettingsOptions(
onBootChanged = { newValue ->
if (newValue) {
settingsViewModel.startMPD(context)
}
},
onWakeLockChanged = { newValue ->
settingsViewModel.setWakelockEnabled(newValue)
},
onHeadphonesChanged = { newValue ->
settingsViewModel.setPauseOnHeadphonesDisconnect(newValue)
}
)
}
}
@Composable
fun SettingsOptions(
onBootChanged: (Boolean) -> Unit,
onWakeLockChanged: (Boolean) -> Unit,
onHeadphonesChanged: (Boolean) -> Unit
) {
val bootState = rememberPreferenceBooleanSettingState(
key = Preferences.KEY_RUN_ON_BOOT,
defaultValue = false
)
val wakelockState =
rememberPreferenceBooleanSettingState(key = Preferences.KEY_WAKELOCK, defaultValue = false)
val headphoneState = rememberPreferenceBooleanSettingState(
key = Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT,
defaultValue = false
)
SettingsSwitch(
icon = { Icon(imageVector = Icons.Default.PowerSettingsNew, contentDescription = "Power") },
title = { Text(text = stringResource(R.string.checkbox_run_on_boot)) },
onCheckedChange = onBootChanged,
state = bootState
)
SettingsSwitch(
icon = { Icon(imageVector = Icons.Default.BatteryAlert, contentDescription = "Battery") },
title = { Text(text = stringResource(R.string.checkbox_wakelock)) },
onCheckedChange = onWakeLockChanged,
state = wakelockState
)
SettingsSwitch(
icon = { Icon(imageVector = Icons.Default.Headphones, contentDescription = "Headphones") },
title = { Text(text = stringResource(R.string.checkbox_pause_on_headphones_disconnect)) },
onCheckedChange = onHeadphonesChanged,
state = headphoneState
)
}

@ -0,0 +1,73 @@
package org.musicpd.ui
import android.content.Context
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.musicpd.Loader
import org.musicpd.MainServiceClient
import org.musicpd.Preferences
import org.musicpd.data.LoggingRepository
import javax.inject.Inject
@HiltViewModel
class SettingsViewModel @Inject constructor(
private var loggingRepository: LoggingRepository
) : ViewModel() {
private var mClient: MainServiceClient? = null
val mpdLoader = Loader
data class StatusUiState(
val statusMessage: String = "",
val running: Boolean = false
)
private val _statusUIState = MutableStateFlow(StatusUiState())
val statusUIState: StateFlow<StatusUiState> = _statusUIState.asStateFlow()
fun getLogs(): StateFlow<List<String>> {
return loggingRepository.logItemFLow
}
fun updateStatus(message: String, running: Boolean) {
_statusUIState.value = StatusUiState(message, running)
}
fun setClient(client: MainServiceClient) {
mClient = client
}
fun removeClient() {
mClient?.release()
mClient = null
}
fun startMPD(context: Context) {
mClient?.start()
if (Preferences.getBoolean(
context,
Preferences.KEY_WAKELOCK, false
)
) mClient?.setWakelockEnabled(true)
if (Preferences.getBoolean(
context,
Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false
)
) mClient?.setPauseOnHeadphonesDisconnect(true)
}
fun stopMPD() {
mClient?.stop()
}
fun setWakelockEnabled(enabled: Boolean) {
mClient?.setWakelockEnabled(enabled)
}
fun setPauseOnHeadphonesDisconnect(enabled: Boolean) {
mClient?.setPauseOnHeadphonesDisconnect(enabled)
}
}

@ -0,0 +1,188 @@
package org.musicpd.ui
import android.Manifest
import android.content.Context
import android.os.Build
import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Circle
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale
import org.musicpd.R
import org.musicpd.utils.openAppSettings
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun StatusScreen(settingsViewModel: SettingsViewModel) {
val storagePermissionState = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
rememberPermissionState(
Manifest.permission.READ_MEDIA_AUDIO
)
} else {
rememberPermissionState(
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
Column(
Modifier
.padding(4.dp)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
NetworkAddress()
ServerStatus(settingsViewModel, storagePermissionState)
AudioMediaPermission(storagePermissionState)
MPDLoaderStatus(settingsViewModel)
}
}
@ColorInt
fun getThemeColorAttribute(context: Context, @AttrRes attr: Int): Int {
val value = TypedValue()
if (context.theme.resolveAttribute(attr, value, true)) {
return value.data
}
return android.graphics.Color.BLACK
}
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ServerStatus(settingsViewModel: SettingsViewModel, storagePermissionState: PermissionState) {
val context = LocalContext.current
val statusUiState by settingsViewModel.statusUIState.collectAsState()
Column {
Row(
Modifier
.padding(4.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.Circle,
contentDescription = "",
tint = Color(
getThemeColorAttribute(
context,
if (statusUiState.running) R.attr.appColorPositive else R.attr.appColorNegative
)
),
modifier = Modifier
.padding(end = 8.dp)
.alpha(0.6f)
)
Text(text = stringResource(id = if (statusUiState.running) R.string.running else R.string.stopped))
}
Button(
onClick = {
if (statusUiState.running)
settingsViewModel.stopMPD()
else
settingsViewModel.startMPD(context)
},
enabled = settingsViewModel.mpdLoader.isLoaded
&& storagePermissionState.status.isGranted
) {
Text(
text = stringResource(id = if (statusUiState.running) R.string.stopMPD else R.string.startMPD)
)
}
}
Row(
Modifier
.padding(4.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Text(text = statusUiState.statusMessage)
}
}
}
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun AudioMediaPermission(storagePermissionState: PermissionState) {
val permissionStatus = storagePermissionState.status
if (!permissionStatus.isGranted) {
val context = LocalContext.current
Column(
Modifier
.padding(4.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
stringResource(id = R.string.external_files_permission_request),
Modifier.padding(16.dp)
)
if (storagePermissionState.status.shouldShowRationale) {
Button(onClick = {
storagePermissionState.launchPermissionRequest()
}) {
Text("Request permission")
}
} else {
OutlinedButton(
onClick = {
openAppSettings(context, context.packageName)
},
Modifier.padding(16.dp)
) {
Text(
stringResource(id = R.string.title_open_app_info),
color = MaterialTheme.colorScheme.secondary
)
}
}
}
}
}
@Composable
fun MPDLoaderStatus(settingsViewModel: SettingsViewModel) {
val loader = settingsViewModel.mpdLoader
if (!loader.isLoaded) {
val context = LocalContext.current
SelectionContainer {
Text(
loader.loadFailureMessage(context),
Modifier.padding(16.dp),
color = MaterialTheme.colorScheme.error
)
}
}
}

@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
package org.musicpd.utils
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import android.util.Log
private const val TAG = "IntentUtils"
fun openAppSettings(
context: Context,
packageName: String
) {
try {
context.startActivity(Intent().apply {
setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
setData(Uri.parse("package:$packageName"))
addCategory(Intent.CATEGORY_DEFAULT)
addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
})
} catch (e: ActivityNotFoundException) {
Log.e(
TAG,
"failed to open app settings for package: $packageName", e
)
}
}

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z"/>
</vector>

@ -0,0 +1,239 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="320dp"
android:height="180dp"
android:viewportWidth="320"
android:viewportHeight="180">
<path
android:pathData="M179.13,108.5H162.71V106.64C163.3,106.62 164.06,106.56 164.99,106.46C165.93,106.35 166.58,106.2 166.93,106.01C167.47,105.68 167.86,105.31 168.1,104.89C168.37,104.45 168.5,103.91 168.5,103.26V76.24H168.1L155.43,107.9H154.12L142.05,75.58H141.71V97.76C141.71,99.91 141.84,101.54 142.1,102.66C142.38,103.78 142.8,104.58 143.36,105.07C143.74,105.44 144.54,105.79 145.74,106.12C146.94,106.45 147.73,106.62 148.1,106.64V108.5H133.09V106.64C133.88,106.57 134.7,106.44 135.55,106.25C136.43,106.06 137.1,105.77 137.57,105.38C138.18,104.89 138.6,104.14 138.83,103.13C139.05,102.12 139.17,100.43 139.17,98.05V79.04C139.17,77.94 139.04,77.04 138.77,76.34C138.51,75.64 138.14,75.07 137.65,74.64C137.11,74.17 136.44,73.82 135.66,73.59C134.87,73.36 134.09,73.23 133.33,73.2V71.34H146L156.63,99.2L165.72,75.9C166.05,75.04 166.33,74.15 166.56,73.22C166.8,72.28 166.93,71.65 166.95,71.34H179.08V73.2C178.59,73.22 177.96,73.29 177.19,73.43C176.44,73.57 175.89,73.7 175.54,73.83C174.95,74.04 174.55,74.39 174.34,74.87C174.13,75.36 174.02,75.9 174.02,76.47V103.26C174.02,103.87 174.13,104.39 174.34,104.81C174.55,105.23 174.95,105.59 175.54,105.91C175.86,106.08 176.41,106.25 177.22,106.4C178.02,106.54 178.66,106.62 179.13,106.64V108.5Z"
android:fillColor="#000000"/>
<path
android:pathData="M212.6,80.5C212.6,82.44 212.21,84.16 211.45,85.66C210.7,87.15 209.65,88.38 208.3,89.36C206.98,90.33 205.52,91.05 203.93,91.5C202.34,91.96 200.66,92.18 198.88,92.18H194.71V103.45C194.71,104.06 194.81,104.6 195,105.07C195.21,105.52 195.63,105.87 196.26,106.12C196.57,106.24 197.12,106.35 197.91,106.46C198.71,106.56 199.44,106.62 200.11,106.64V108.5H184.16V106.64C184.58,106.61 185.18,106.54 185.96,106.46C186.77,106.37 187.33,106.26 187.64,106.12C188.16,105.89 188.54,105.56 188.77,105.12C189.01,104.68 189.13,104.13 189.13,103.45V76.63C189.13,76.02 189.05,75.47 188.87,74.98C188.7,74.49 188.29,74.12 187.64,73.88C186.98,73.65 186.31,73.49 185.65,73.41C185.01,73.3 184.45,73.23 183.98,73.2V71.34H200.95C204.4,71.34 207.2,72.18 209.35,73.85C211.52,75.51 212.6,77.73 212.6,80.5ZM204.64,86.84C205.23,86 205.62,85.14 205.82,84.25C206.01,83.34 206.1,82.53 206.1,81.81C206.1,80.82 205.98,79.81 205.74,78.78C205.51,77.75 205.11,76.85 204.53,76.08C203.92,75.26 203.12,74.62 202.12,74.17C201.13,73.71 199.89,73.49 198.4,73.49H194.71V89.91H197.38C199.27,89.91 200.8,89.62 201.97,89.04C203.15,88.45 204.04,87.71 204.64,86.84Z"
android:fillColor="#000000"/>
<path
android:pathData="M252.48,90.14C252.48,93.3 251.89,96.04 250.7,98.36C249.52,100.69 247.97,102.59 246.07,104.07C244.15,105.56 241.99,106.67 239.6,107.4C237.21,108.13 234.74,108.5 232.19,108.5H216.79V106.64C217.29,106.64 217.95,106.6 218.75,106.51C219.57,106.4 220.12,106.29 220.38,106.17C220.9,105.94 221.28,105.61 221.5,105.17C221.75,104.72 221.87,104.18 221.87,103.55V76.73C221.87,76.14 221.76,75.61 221.55,75.14C221.36,74.66 220.97,74.29 220.38,74.01C219.84,73.75 219.25,73.56 218.62,73.43C217.99,73.31 217.45,73.23 217,73.2V71.34H233.24C235.47,71.34 237.67,71.69 239.84,72.39C242,73.07 243.89,73.99 245.49,75.16C247.67,76.72 249.38,78.75 250.63,81.26C251.86,83.78 252.48,86.74 252.48,90.14ZM246.07,90.12C246.07,87.62 245.74,85.37 245.07,83.36C244.41,81.33 243.44,79.57 242.17,78.07C240.96,76.64 239.48,75.51 237.71,74.69C235.97,73.87 234.02,73.46 231.87,73.46C231.16,73.46 230.35,73.48 229.44,73.51C228.55,73.53 227.88,73.55 227.45,73.56V102.14C227.45,103.72 227.91,104.82 228.84,105.44C229.76,106.05 231.18,106.35 233.1,106.35C235.32,106.35 237.26,105.96 238.92,105.17C240.58,104.39 241.92,103.3 242.95,101.9C244.03,100.43 244.82,98.74 245.31,96.82C245.82,94.88 246.07,92.65 246.07,90.12Z"
android:fillColor="#000000"/>
<group>
<clip-path
android:pathData="M23,51h71v71h-71z"/>
<path
android:pathData="M87.49,88.31C87.49,88.07 87.29,87.87 87.06,87.87H60.89C60.66,87.87 60.46,88.07 60.46,88.31V110.83C60.46,111.07 60.66,111.26 60.89,111.26H87.06C87.29,111.26 87.49,111.07 87.49,110.83V88.31Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M93.82,68.38C93.82,68.14 93.63,67.95 93.39,67.95H59.19C58.96,67.95 58.76,68.14 58.76,68.38V97.86C58.76,98.1 58.96,98.29 59.19,98.29H93.39C93.63,98.29 93.82,98.1 93.82,97.86V68.38Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M91.36,96.94C91.36,96.73 91.2,96.57 90.99,96.57H59.64C59.44,96.57 59.28,96.73 59.28,96.94V101.2C59.28,101.4 59.44,101.56 59.64,101.56H90.99C91.2,101.56 91.36,101.4 91.36,101.2V96.94Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M89.3,96.89C89.3,96.75 89.19,96.64 89.05,96.64H59.09C58.96,96.64 58.85,96.75 58.85,96.89V99.8C58.85,99.94 58.96,100.05 59.09,100.05H89.05C89.19,100.05 89.3,99.94 89.3,99.8V96.89Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="76.53"
android:startY="102.12"
android:endX="69.28"
android:endY="95.45"
android:type="linear">
<item android:offset="0" android:color="#BFD2D2D2"/>
<item android:offset="1" android:color="#BFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M58.61,96.89C58.61,96.63 58.83,96.41 59.09,96.41H89.05C89.32,96.41 89.53,96.63 89.53,96.89V99.8C89.53,100.07 89.32,100.28 89.05,100.28H59.09C58.83,100.28 58.61,100.07 58.61,99.8V96.89ZM59.09,96.87C59.08,96.87 59.08,96.88 59.08,96.89V99.8C59.08,99.81 59.08,99.82 59.09,99.82H89.05C89.06,99.82 89.07,99.81 89.07,99.8V96.89C89.07,96.88 89.06,96.87 89.05,96.87H59.09Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M90.5,69.91C90.5,69.41 90.09,69 89.59,69H59.29C58.79,69 58.38,69.41 58.38,69.91V94.21C58.38,94.71 58.79,95.12 59.29,95.12H89.59C90.09,95.12 90.5,94.71 90.5,94.21V69.91Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="91.12"
android:startY="94.89"
android:endX="74.39"
android:endY="79.87"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M85.59,110.3C85.59,110.1 85.42,109.93 85.22,109.93H61.22C61.02,109.93 60.86,110.1 60.86,110.3V113.42C60.86,113.62 61.02,113.78 61.22,113.78H85.22C85.42,113.78 85.59,113.62 85.59,113.42V110.3Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M92.05,67.72C92.05,67.29 91.71,66.94 91.28,66.94H56.97C56.55,66.94 56.2,67.29 56.2,67.72V96.16C56.2,96.59 56.55,96.93 56.97,96.93H91.28C91.71,96.93 92.05,96.59 92.05,96.16V67.72Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="95.17"
android:startY="93.03"
android:endX="87.12"
android:endY="79.61"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M55.74,67.72C55.74,67.04 56.29,66.48 56.97,66.48H91.28C91.96,66.48 92.51,67.04 92.51,67.72V96.16C92.51,96.84 91.96,97.39 91.28,97.39H56.97C56.29,97.39 55.74,96.84 55.74,96.16V67.72ZM56.97,67.4C56.8,67.4 56.66,67.54 56.66,67.72V96.16C56.66,96.33 56.8,96.47 56.97,96.47H91.28C91.45,96.47 91.59,96.33 91.59,96.16V67.72C91.59,67.54 91.45,67.4 91.28,67.4H56.97Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M88.17,70.66C88.17,70.49 88.03,70.36 87.87,70.36H60.11C59.94,70.36 59.81,70.49 59.81,70.66V92.22C59.81,92.39 59.94,92.52 60.11,92.52H87.87C88.03,92.52 88.17,92.39 88.17,92.22V70.66Z"
android:fillColor="#00B4ED"
android:fillType="evenOdd"/>
<path
android:pathData="M59.59,70.66C59.59,70.37 59.82,70.14 60.11,70.14H87.87C88.16,70.14 88.39,70.37 88.39,70.66V92.22C88.39,92.51 88.16,92.74 87.87,92.74H60.11C59.82,92.74 59.59,92.51 59.59,92.22V70.66ZM60.11,70.58C60.06,70.58 60.03,70.61 60.03,70.66V92.22C60.03,92.27 60.06,92.31 60.11,92.31H87.87C87.91,92.31 87.95,92.27 87.95,92.22V70.66C87.95,70.61 87.91,70.58 87.87,70.58H60.11Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M84.93,89.59C84.93,89.09 84.52,88.68 84.02,88.68H61.07C60.57,88.68 60.17,89.09 60.17,89.59V107.91C60.17,108.41 60.57,108.82 61.07,108.82H84.02C84.52,108.82 84.93,108.41 84.93,107.91V89.59Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="85.4"
android:startY="108.64"
android:endX="72.51"
android:endY="97.06"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M72.64,108.86C72.35,110.81 63.69,112.41 53.46,112.41C43.24,112.41 35.07,110.81 35.36,108.86C35.66,106.92 44.32,105.32 54.54,105.32C64.77,105.32 72.94,106.92 72.64,108.86Z"
android:fillColor="#444040"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M46.49,87.74C43.2,95.65 45.43,104.45 51.42,107.24C57.42,110.04 65.06,105.82 68.34,97.92C71.63,90.01 69.4,81.21 63.41,78.42C57.41,75.62 49.77,79.83 46.49,87.74Z"
android:fillColor="#4E4D4B"
android:fillType="evenOdd"/>
<path
android:pathData="M68.58,86.44C69.43,89.79 69.19,93.78 67.61,97.58C66.03,101.38 63.41,104.26 60.51,105.86C57.6,107.47 54.45,107.76 51.73,106.49C49.01,105.23 47.09,102.57 46.25,99.22C45.4,95.87 45.64,91.88 47.22,88.08C48.8,84.28 51.42,81.4 54.32,79.79C57.23,78.19 60.37,77.9 63.1,79.17C65.82,80.43 67.74,83.09 68.58,86.44ZM70.13,86.06C69.18,82.34 66.99,79.19 63.72,77.67C60.44,76.14 56.77,76.56 53.54,78.34C50.31,80.12 47.46,83.29 45.75,87.4C44.04,91.5 43.76,95.87 44.7,99.6C45.65,103.32 47.84,106.47 51.11,107.99C54.39,109.52 58.06,109.1 61.29,107.32C64.52,105.54 67.37,102.37 69.08,98.26C70.78,94.15 71.07,89.79 70.13,86.06Z"
android:fillColor="#000000"
android:fillAlpha="0.95"
android:fillType="evenOdd"/>
<path
android:pathData="M30.48,75.66C23.76,88.96 25.17,103.77 33.61,108.47C42.05,113.17 54.53,106.08 61.25,92.78C67.98,79.48 66.56,64.67 58.12,59.98C49.68,55.28 37.21,62.36 30.48,75.66Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="89.23"
android:startY="61.39"
android:endX="8.66"
android:endY="47.26"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#FF000000"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M64.24,73.24C64.78,78.94 63.51,85.74 60.24,92.22C56.96,98.7 52.31,103.62 47.51,106.34C42.69,109.07 37.89,109.53 34.13,107.43C30.37,105.34 28.04,100.92 27.49,95.2C26.95,89.5 28.22,82.7 31.49,76.22C34.77,69.75 39.42,64.83 44.22,62.1C49.04,59.37 53.84,58.92 57.6,61.01C61.36,63.1 63.7,67.53 64.24,73.24ZM66.51,73.07C65.92,66.88 63.33,61.55 58.65,58.95C53.96,56.34 48.31,57.08 43.09,60.04C37.86,63 32.92,68.28 29.47,75.1C26.02,81.92 24.63,89.17 25.23,95.38C25.81,101.57 28.4,106.9 33.09,109.5C37.77,112.11 43.42,111.37 48.64,108.41C53.87,105.44 58.81,100.17 62.26,93.35C65.71,86.52 67.1,79.27 66.51,73.07Z"
android:fillColor="#000000"
android:fillAlpha="0.95"
android:fillType="evenOdd"/>
<path
android:pathData="M31.01,75.59C25.32,87.25 26.23,100.23 33.04,104.34C39.84,108.46 50.12,102.25 55.81,90.6C61.51,78.94 60.59,65.96 53.78,61.84C46.98,57.73 36.7,63.93 31.01,75.59Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="16.83"
android:centerY="104.4"
android:gradientRadius="32.44"
android:type="radial">
<item android:offset="0" android:color="#9EFFFFFF"/>
<item android:offset="1" android:color="#FF5D6567"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M59.34,73.4C59.71,78.58 58.52,84.71 55.68,90.52C52.85,96.33 48.87,100.77 44.77,103.25C40.66,105.73 36.44,106.23 33.1,104.21C29.76,102.19 27.85,97.98 27.48,92.79C27.12,87.61 28.3,81.48 31.14,75.67C33.97,69.86 37.95,65.42 42.05,62.94C46.16,60.46 50.38,59.96 53.72,61.98C57.06,64 58.97,68.21 59.34,73.4ZM59.63,73.39C59.26,68.14 57.32,63.8 53.85,61.71C50.39,59.61 46.06,60.15 41.9,62.66C37.74,65.17 33.73,69.66 30.88,75.51C28.02,81.36 26.82,87.55 27.19,92.8C27.56,98.04 29.5,102.38 32.97,104.48C36.43,106.58 40.76,106.03 44.92,103.52C49.08,101.01 53.09,96.53 55.94,90.68C58.8,84.83 60,78.64 59.63,73.39Z"
android:fillColor="#000000"
android:fillAlpha="0.98"
android:fillType="evenOdd"/>
<path
android:pathData="M42.76,79.77C39.61,85.38 38.93,92.2 41.26,94.88C43.59,97.55 48.1,95.14 51.24,89.54C54.39,83.93 55.06,77.11 52.74,74.43C50.41,71.75 45.9,74.16 42.76,79.77Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M42.46,79.6C39.52,84.65 38.89,90.8 41.07,93.21C43.24,95.62 47.46,93.45 50.4,88.4C53.35,83.35 53.98,77.21 51.8,74.79C49.62,72.38 45.41,74.55 42.46,79.6Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="34.56"
android:startY="87.9"
android:endX="59.05"
android:endY="97.29"
android:type="linear">
<item android:offset="0" android:color="#FFD7D5D5"/>
<item android:offset="1" android:color="#66000000"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M52.89,80.57C52.64,83.01 51.76,85.78 50.3,88.28C48.84,90.79 47.06,92.58 45.39,93.44C43.72,94.3 42.18,94.22 41.15,93.07C40.11,91.93 39.72,89.87 39.97,87.43C40.22,85 41.11,82.22 42.57,79.72C44.03,77.21 45.8,75.43 47.47,74.57C49.15,73.7 50.69,73.78 51.72,74.93C52.75,76.07 53.14,78.13 52.89,80.57ZM53.15,80.64C53.41,78.15 53.02,75.93 51.88,74.66C50.73,73.39 49.08,73.35 47.37,74.23C45.65,75.11 43.84,76.94 42.36,79.48C40.88,82.03 39.97,84.85 39.71,87.36C39.46,89.85 39.84,92.08 40.99,93.35C42.13,94.61 43.79,94.65 45.5,93.77C47.22,92.89 49.02,91.06 50.51,88.52C51.99,85.97 52.9,83.15 53.15,80.64Z"
android:fillColor="#3F3B3B"
android:fillType="evenOdd"/>
<path
android:pathData="M84,110.24C84,110.1 83.89,109.99 83.75,109.99H60.77C60.64,109.99 60.53,110.1 60.53,110.24V112.37C60.53,112.5 60.64,112.61 60.77,112.61H83.75C83.89,112.61 84,112.5 84,112.37V110.24Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="74.16"
android:startY="114.32"
android:endX="68.55"
android:endY="108.99"
android:type="linear">
<item android:offset="0" android:color="#BFD2D2D2"/>
<item android:offset="1" android:color="#BFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M60.3,110.24C60.3,109.97 60.51,109.76 60.77,109.76H83.75C84.02,109.76 84.23,109.97 84.23,110.24V112.37C84.23,112.63 84.02,112.85 83.75,112.85H60.77C60.51,112.85 60.3,112.63 60.3,112.37V110.24ZM60.77,110.22C60.76,110.22 60.76,110.23 60.76,110.24V112.37C60.76,112.38 60.76,112.39 60.77,112.39H83.75C83.76,112.39 83.77,112.38 83.77,112.37V110.24C83.77,110.23 83.76,110.22 83.75,110.22H60.77Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M86.12,87.87C86.12,87.44 85.78,87.1 85.35,87.1H59.26C58.83,87.1 58.49,87.44 58.49,87.87V109.44C58.49,109.87 58.83,110.21 59.26,110.21H85.35C85.78,110.21 86.12,109.87 86.12,109.44V87.87Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="88.53"
android:startY="107.21"
android:endX="82.32"
android:endY="96.86"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M58.13,87.87C58.13,87.25 58.64,86.74 59.26,86.74H85.35C85.97,86.74 86.48,87.25 86.48,87.87V109.44C86.48,110.06 85.97,110.57 85.35,110.57H59.26C58.64,110.57 58.13,110.06 58.13,109.44V87.87ZM59.26,87.45C59.03,87.45 58.84,87.64 58.84,87.87V109.44C58.84,109.67 59.03,109.86 59.26,109.86H85.35C85.58,109.86 85.77,109.67 85.77,109.44V87.87C85.77,87.64 85.58,87.45 85.35,87.45H59.26Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M83.13,90.18C83.13,90.02 82.99,89.88 82.83,89.88H61.57C61.4,89.88 61.27,90.02 61.27,90.18V106.67C61.27,106.83 61.4,106.97 61.57,106.97H82.83C82.99,106.97 83.13,106.83 83.13,106.67V90.18Z"
android:fillColor="#003D88"
android:fillType="evenOdd"/>
<path
android:pathData="M61.1,90.18C61.1,89.92 61.31,89.71 61.57,89.71H82.83C83.09,89.71 83.3,89.92 83.3,90.18V106.67C83.3,106.93 83.09,107.14 82.83,107.14H61.57C61.31,107.14 61.1,106.93 61.1,106.67V90.18ZM61.57,90.05C61.5,90.05 61.44,90.11 61.44,90.18V106.67C61.44,106.74 61.5,106.8 61.57,106.8H82.83C82.9,106.8 82.96,106.74 82.96,106.67V90.18C82.96,90.11 82.9,90.05 82.83,90.05H61.57Z"
android:fillColor="#000000"
android:fillAlpha="0.93"
android:fillType="evenOdd"/>
</group>
</vector>

@ -0,0 +1,235 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group android:scaleX="0.7121053"
android:scaleY="0.7121053"
android:translateX="14.83421"
android:translateY="16.25842">
<group>
<clip-path
android:pathData="M15,15h78v78h-78z"/>
<path
android:pathData="M85.85,55.98C85.85,55.72 85.63,55.51 85.37,55.51H56.63C56.37,55.51 56.15,55.72 56.15,55.98V80.73C56.15,80.99 56.37,81.2 56.63,81.2H85.37C85.63,81.2 85.85,80.99 85.85,80.73V55.98Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M92.81,34.1C92.81,33.83 92.59,33.62 92.33,33.62H54.76C54.5,33.62 54.29,33.83 54.29,34.1V66.48C54.29,66.74 54.5,66.96 54.76,66.96H92.33C92.59,66.96 92.81,66.74 92.81,66.48V34.1Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M90.1,65.47C90.1,65.24 89.92,65.06 89.7,65.06H55.26C55.03,65.06 54.85,65.24 54.85,65.47V70.15C54.85,70.37 55.03,70.55 55.26,70.55H89.7C89.92,70.55 90.1,70.37 90.1,70.15V65.47Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M87.84,65.41C87.84,65.26 87.72,65.14 87.57,65.14H54.65C54.5,65.14 54.38,65.26 54.38,65.41V68.61C54.38,68.76 54.5,68.89 54.65,68.89H87.57C87.72,68.89 87.84,68.76 87.84,68.61V65.41Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="73.8"
android:startY="71.16"
android:endX="65.84"
android:endY="63.83"
android:type="linear">
<item android:offset="0" android:color="#BFD2D2D2"/>
<item android:offset="1" android:color="#BFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M54.13,65.41C54.13,65.12 54.36,64.89 54.65,64.89H87.57C87.86,64.89 88.09,65.12 88.09,65.41V68.61C88.09,68.9 87.86,69.14 87.57,69.14H54.65C54.36,69.14 54.13,68.9 54.13,68.61V65.41ZM54.65,65.39C54.64,65.39 54.63,65.4 54.63,65.41V68.61C54.63,68.62 54.64,68.63 54.65,68.63H87.57C87.58,68.63 87.59,68.62 87.59,68.61V65.41C87.59,65.4 87.58,65.39 87.57,65.39H54.65Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M89.15,35.77C89.15,35.22 88.71,34.78 88.16,34.78H54.86C54.31,34.78 53.87,35.22 53.87,35.77V62.47C53.87,63.02 54.31,63.47 54.86,63.47H88.16C88.71,63.47 89.15,63.02 89.15,62.47V35.77Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="89.84"
android:startY="63.22"
android:endX="71.46"
android:endY="46.71"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M83.76,80.15C83.76,79.92 83.58,79.74 83.36,79.74H56.99C56.77,79.74 56.59,79.92 56.59,80.15V83.57C56.59,83.79 56.77,83.97 56.99,83.97H83.36C83.58,83.97 83.76,83.79 83.76,83.57V80.15Z"
android:fillColor="#000000"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M90.86,33.37C90.86,32.9 90.48,32.51 90.01,32.51H52.32C51.85,32.51 51.47,32.9 51.47,33.37V64.61C51.47,65.08 51.85,65.46 52.32,65.46H90.01C90.48,65.46 90.86,65.08 90.86,64.61V33.37Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="94.29"
android:startY="61.18"
android:endX="85.44"
android:endY="46.43"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M50.97,33.37C50.97,32.62 51.58,32.01 52.32,32.01H90.01C90.76,32.01 91.37,32.62 91.37,33.37V64.61C91.37,65.36 90.76,65.97 90.01,65.97H52.32C51.58,65.97 50.97,65.36 50.97,64.61V33.37ZM52.32,33.02C52.13,33.02 51.98,33.17 51.98,33.37V64.61C51.98,64.8 52.13,64.96 52.32,64.96H90.01C90.2,64.96 90.36,64.8 90.36,64.61V33.37C90.36,33.17 90.2,33.02 90.01,33.02H52.32Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M86.59,36.59C86.59,36.41 86.45,36.26 86.26,36.26H55.77C55.59,36.26 55.44,36.41 55.44,36.59V60.29C55.44,60.47 55.59,60.62 55.77,60.62H86.26C86.45,60.62 86.59,60.47 86.59,60.29V36.59Z"
android:fillColor="#00B4ED"
android:fillType="evenOdd"/>
<path
android:pathData="M55.2,36.59C55.2,36.28 55.45,36.02 55.77,36.02H86.26C86.58,36.02 86.83,36.28 86.83,36.59V60.29C86.83,60.6 86.58,60.86 86.26,60.86H55.77C55.45,60.86 55.2,60.6 55.2,60.29V36.59ZM55.77,36.51C55.72,36.51 55.68,36.55 55.68,36.59V60.29C55.68,60.34 55.72,60.38 55.77,60.38H86.26C86.31,60.38 86.35,60.34 86.35,60.29V36.59C86.35,36.55 86.31,36.51 86.26,36.51H55.77Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M83.03,57.4C83.03,56.85 82.59,56.4 82.04,56.4H56.83C56.28,56.4 55.83,56.85 55.83,57.4V77.52C55.83,78.07 56.28,78.52 56.83,78.52H82.04C82.59,78.52 83.03,78.07 83.03,77.52V57.4Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="83.56"
android:startY="78.32"
android:endX="69.39"
android:endY="65.6"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M69.54,78.57C69.21,80.71 59.7,82.46 48.47,82.46C37.23,82.46 28.26,80.71 28.58,78.57C28.91,76.43 38.42,74.68 49.65,74.68C60.89,74.68 69.87,76.43 69.54,78.57Z"
android:fillColor="#444040"
android:fillAlpha="0.47"
android:fillType="evenOdd"/>
<path
android:pathData="M40.8,55.36C37.19,64.05 39.64,73.72 46.22,76.79C52.81,79.86 61.2,75.23 64.81,66.55C68.42,57.86 65.98,48.19 59.39,45.12C52.8,42.05 44.41,46.68 40.8,55.36Z"
android:fillColor="#4E4D4B"
android:fillType="evenOdd"/>
<path
android:pathData="M65.08,53.93C66.01,57.61 65.74,62 64.01,66.17C62.27,70.34 59.4,73.51 56.2,75.27C53.01,77.03 49.55,77.36 46.57,75.97C43.58,74.57 41.47,71.66 40.54,67.98C39.61,64.3 39.87,59.91 41.61,55.74C43.34,51.56 46.22,48.39 49.41,46.63C52.6,44.87 56.06,44.55 59.05,45.94C62.04,47.33 64.15,50.25 65.08,53.93ZM66.77,53.52C65.74,49.43 63.33,45.97 59.73,44.3C56.13,42.62 52.1,43.08 48.55,45.03C45,46.99 41.87,50.47 39.99,54.99C38.12,59.5 37.81,64.29 38.84,68.39C39.88,72.48 42.29,75.93 45.88,77.61C49.48,79.29 53.51,78.83 57.06,76.87C60.62,74.92 63.74,71.43 65.62,66.92C67.5,62.41 67.81,57.62 66.77,53.52Z"
android:fillColor="#000000"
android:fillAlpha="0.95"
android:fillType="evenOdd"/>
<path
android:pathData="M23.22,42.09C15.83,56.7 17.38,72.97 26.65,78.13C35.93,83.29 49.63,75.52 57.02,60.9C64.41,46.29 62.86,30.02 53.59,24.86C44.31,19.7 30.61,27.48 23.22,42.09Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="87.76"
android:startY="26.41"
android:endX="-0.75"
android:endY="10.89"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#FF000000"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M60.31,39.44C60.9,45.7 59.51,53.17 55.91,60.29C52.31,67.4 47.2,72.81 41.92,75.8C36.63,78.8 31.36,79.3 27.23,77C23.1,74.7 20.53,69.84 19.93,63.56C19.34,57.3 20.73,49.83 24.33,42.71C27.93,35.59 33.04,30.19 38.32,27.2C43.61,24.2 48.88,23.7 53.01,26C57.14,28.3 59.71,33.16 60.31,39.44ZM62.8,39.24C62.15,32.44 59.3,26.59 54.16,23.73C49.02,20.87 42.8,21.68 37.08,24.93C31.33,28.19 25.9,33.98 22.11,41.47C18.32,48.97 16.79,56.94 17.44,63.76C18.09,70.56 20.94,76.41 26.08,79.27C31.22,82.13 37.44,81.32 43.16,78.07C48.91,74.81 54.34,69.02 58.13,61.52C61.92,54.03 63.45,46.06 62.8,39.24Z"
android:fillColor="#000000"
android:fillAlpha="0.95"
android:fillType="evenOdd"/>
<path
android:pathData="M23.8,42.01C17.54,54.82 18.55,69.08 26.03,73.6C33.5,78.12 44.8,71.31 51.05,58.5C57.3,45.69 56.29,31.43 48.82,26.91C41.34,22.39 30.05,29.21 23.8,42.01Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="8.22"
android:centerY="73.66"
android:gradientRadius="35.64"
android:type="radial">
<item android:offset="0" android:color="#9EFFFFFF"/>
<item android:offset="1" android:color="#FF5D6567"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M54.92,39.6C55.32,45.3 54.02,52.03 50.91,58.41C47.79,64.79 43.42,69.68 38.91,72.4C34.4,75.12 29.77,75.67 26.1,73.45C22.43,71.23 20.32,66.61 19.92,60.91C19.52,55.22 20.82,48.48 23.94,42.1C27.05,35.72 31.42,30.84 35.93,28.12C40.45,25.39 45.08,24.84 48.75,27.06C52.41,29.28 54.52,33.91 54.92,39.6ZM55.24,39.6C54.84,33.83 52.7,29.07 48.89,26.76C45.09,24.46 40.33,25.06 35.77,27.81C31.2,30.57 26.79,35.5 23.65,41.93C20.51,48.35 19.2,55.15 19.6,60.92C20.01,66.68 22.14,71.45 25.95,73.75C29.76,76.06 34.51,75.46 39.08,72.7C43.65,69.94 48.05,65.01 51.19,58.59C54.33,52.16 55.65,45.36 55.24,39.6Z"
android:fillColor="#000000"
android:fillAlpha="0.98"
android:fillType="evenOdd"/>
<path
android:pathData="M36.7,46.61C33.25,52.77 32.51,60.26 35.06,63.2C37.62,66.14 42.57,63.5 46.03,57.34C49.48,51.18 50.22,43.69 47.67,40.74C45.11,37.8 40.16,40.45 36.7,46.61Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M36.38,46.42C33.15,51.97 32.46,58.72 34.85,61.37C37.24,64.02 41.87,61.64 45.1,56.09C48.34,50.54 49.03,43.79 46.64,41.14C44.25,38.49 39.62,40.87 36.38,46.42Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="27.7"
android:startY="55.54"
android:endX="54.6"
android:endY="65.85"
android:type="linear">
<item android:offset="0" android:color="#FFD7D5D5"/>
<item android:offset="1" android:color="#66000000"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M47.84,47.49C47.56,50.16 46.59,53.21 44.99,55.96C43.38,58.71 41.44,60.68 39.6,61.62C37.76,62.57 36.07,62.48 34.93,61.22C33.8,59.96 33.37,57.7 33.65,55.02C33.92,52.35 34.89,49.3 36.5,46.55C38.1,43.8 40.05,41.83 41.89,40.89C43.73,39.94 45.42,40.03 46.55,41.29C47.69,42.55 48.11,44.8 47.84,47.49ZM48.12,47.57C48.41,44.82 47.98,42.38 46.73,40.99C45.47,39.6 43.65,39.55 41.77,40.52C39.88,41.49 37.9,43.5 36.27,46.29C34.64,49.09 33.64,52.19 33.36,54.94C33.08,57.69 33.5,60.13 34.76,61.52C36.02,62.91 37.84,62.96 39.72,61.99C41.61,61.02 43.59,59.01 45.22,56.22C46.85,53.42 47.84,50.32 48.12,47.57Z"
android:fillColor="#3F3B3B"
android:fillType="evenOdd"/>
<path
android:pathData="M82.02,80.08C82.02,79.93 81.9,79.8 81.74,79.8H56.5C56.35,79.8 56.23,79.93 56.23,80.08V82.42C56.23,82.57 56.35,82.69 56.5,82.69H81.74C81.9,82.69 82.02,82.57 82.02,82.42V80.08Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="71.21"
android:startY="84.56"
android:endX="65.04"
android:endY="78.7"
android:type="linear">
<item android:offset="0" android:color="#BFD2D2D2"/>
<item android:offset="1" android:color="#BFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M55.97,80.08C55.97,79.79 56.21,79.55 56.5,79.55H81.74C82.04,79.55 82.27,79.79 82.27,80.08V82.42C82.27,82.71 82.04,82.94 81.74,82.94H56.5C56.21,82.94 55.97,82.71 55.97,82.42V80.08ZM56.5,80.06C56.49,80.06 56.48,80.07 56.48,80.08V82.42C56.48,82.43 56.49,82.44 56.5,82.44H81.74C81.76,82.44 81.76,82.43 81.76,82.42V80.08C81.76,80.07 81.76,80.06 81.74,80.06H56.5Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M84.35,55.51C84.35,55.04 83.96,54.65 83.5,54.65H54.84C54.37,54.65 53.99,55.04 53.99,55.51V79.2C53.99,79.67 54.37,80.05 54.84,80.05H83.5C83.96,80.05 84.35,79.67 84.35,79.2V55.51Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="86.99"
android:startY="76.75"
android:endX="80.17"
android:endY="65.38"
android:type="linear">
<item android:offset="0" android:color="#FFD2D2D2"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M53.6,55.51C53.6,54.82 54.15,54.26 54.84,54.26H83.5C84.18,54.26 84.74,54.82 84.74,55.51V79.2C84.74,79.89 84.18,80.44 83.5,80.44H54.84C54.15,80.44 53.6,79.89 53.6,79.2V55.51ZM54.84,55.04C54.58,55.04 54.38,55.25 54.38,55.51V79.2C54.38,79.45 54.58,79.66 54.84,79.66H83.5C83.75,79.66 83.96,79.45 83.96,79.2V55.51C83.96,55.25 83.75,55.04 83.5,55.04H54.84Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M81.06,58.05C81.06,57.86 80.91,57.72 80.73,57.72H57.37C57.19,57.72 57.04,57.86 57.04,58.05V76.16C57.04,76.34 57.19,76.49 57.37,76.49H80.73C80.91,76.49 81.06,76.34 81.06,76.16V58.05Z"
android:fillColor="#003D88"
android:fillType="evenOdd"/>
<path
android:pathData="M56.85,58.05C56.85,57.76 57.09,57.53 57.37,57.53H80.73C81.01,57.53 81.24,57.76 81.24,58.05V76.16C81.24,76.44 81.01,76.67 80.73,76.67H57.37C57.09,76.67 56.85,76.44 56.85,76.16V58.05ZM57.37,57.9C57.29,57.9 57.23,57.97 57.23,58.05V76.16C57.23,76.24 57.29,76.3 57.37,76.3H80.73C80.81,76.3 80.87,76.24 80.87,76.16V58.05C80.87,57.97 80.81,57.9 80.73,57.9H57.37Z"
android:fillColor="#000000"
android:fillAlpha="0.93"
android:fillType="evenOdd"/>
</group>
</group>
</vector>

Binary file not shown.

After

(image error) Size: 1.5 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_banner_background"/>
<foreground android:drawable="@drawable/ic_banner_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

(image error) Size: 4.7 KiB

Binary file not shown.

After

(image error) Size: 1.7 KiB

Binary file not shown.

After

(image error) Size: 3.5 KiB

Binary file not shown.

After

(image error) Size: 2.9 KiB

Binary file not shown.

After

(image error) Size: 1.2 KiB

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 6.7 KiB

Binary file not shown.

After

(image error) Size: 2.5 KiB

Binary file not shown.

After

(image error) Size: 4.4 KiB

Binary file not shown.

After

(image error) Size: 11 KiB

Binary file not shown.

After

(image error) Size: 3.9 KiB

Binary file not shown.

After

(image error) Size: 7.5 KiB

Binary file not shown.

After

(image error) Size: 16 KiB

Binary file not shown.

After

(image error) Size: 5.7 KiB

Binary file not shown.

After

(image error) Size: 10 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_banner_background">#FFFFFF</color>
</resources>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MPD</string>
<string name="notification_title_mpd_running">Music Player Daemon is running</string>
<string name="notification_text_mpd_running">Touch for MPD options.</string>
<string name="toggle_button_run_on">MPD is running</string>
<string name="toggle_button_run_off">MPD is not running</string>
<string name="checkbox_run_on_boot">Run MPD automatically on boot</string>
<string name="checkbox_wakelock">Prevent suspend when MPD is running (Wakelock)</string>
<string name="checkbox_pause_on_headphones_disconnect">Pause MPD when headphones disconnect</string>
<string name="external_files_permission_request">MPD requires access to external files to play local music. Please grant the permission.</string>
<string name="title_open_app_info">Open app info</string>
<string name="mpd_load_failure_message">"Failed to load the native MPD library.
Report this problem to us, and include the following information:
SUPPORTED_ABIS=%1$s
PRODUCT=%2$s
FINGERPRINT=%3$s
error=%4$s"
</string>
<string name="stopped">Stopped</string>
<string name="running">Running</string>
<string name="stopMPD">Stop MPD</string>
<string name="startMPD">Start MPD</string>
</resources>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="red_500">#F44336</color>
<color name="red_900">#B71C1C</color>
<color name="green_300">#81C784</color>
<color name="green_700">#388E3C</color>
<color name="colorErrorOnLight">@color/red_900</color>
<color name="colorErrorOnDark">@color/red_500</color>
<color name="colorSuccessOnLight">@color/green_700</color>
<color name="colorSuccessOnDark">@color/green_300</color>
<attr name="appColorNegative" format="color|reference" />
<attr name="appColorPositive" format="color|reference" />
<style name="Theme.MPD" parent="android:Theme.Material.Light.NoActionBar">
<item name="appColorNegative">@color/colorErrorOnLight</item>
<item name="appColorPositive">@color/colorSuccessOnLight</item>
</style>
</resources>

7
android/build.gradle.kts Normal file

@ -0,0 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.google.devtools.ksp") version "1.9.22-1.0.16" apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.jetbrains.kotlin.android) apply false
alias(libs.plugins.dagger.hilt.android) apply false
}

@ -1,6 +1,7 @@
#!/usr/bin/env -S python3 -u
import os, os.path
import shutil
import sys, subprocess
if len(sys.argv) < 4:
@ -12,7 +13,7 @@ ndk_path = sys.argv[2]
android_abi = sys.argv[3]
configure_args = sys.argv[4:]
if not os.path.isfile(os.path.join(sdk_path, 'tools', 'android')):
if not os.path.isfile(os.path.join(sdk_path, 'licenses', 'android-sdk-license')):
print("SDK not found in", sdk_path, file=sys.stderr)
sys.exit(1)
@ -31,19 +32,11 @@ from build.toolchain import AndroidNdkToolchain
# a list of third-party libraries to be used by MPD on Android
from build.libs import *
thirdparty_libs = [
libmpdclient,
libogg,
opus,
flac,
libid3tag,
libmodplug,
wildmidi,
gme,
ffmpeg,
openssl,
curl,
libnfs,
boost,
]
# build the third-party libraries
@ -66,8 +59,24 @@ configure_args += [
'-Dandroid_ndk=' + ndk_path,
'-Dandroid_abi=' + android_abi,
'-Dandroid_strip=' + toolchain.strip,
'-Dopenssl:asm=disabled',
'-Dwrap_mode=forcefallback'
]
from build.meson import configure as run_meson
run_meson(toolchain, mpd_path, '.', configure_args)
subprocess.check_call(['/usr/bin/ninja'], env=toolchain.env)
ninja = shutil.which("ninja")
subprocess.check_call([ninja], env=toolchain.env)
subprocess.check_call([ninja, 'install'], env=toolchain.env)
print("""
-------------------------------------
## To build the android app:
# cd ../../android
# ./gradlew assemble{}Debug
## or, for a universal apk (includes both arm64-v8a and x86_64)
# ./gradlew assembleUniversalDebug
-------------------------------------
""".format(android_abi.capitalize()))

21
android/gradle.properties Normal file

@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

@ -0,0 +1,41 @@
[versions]
androidGradlePlugin = "8.5.2"
accompanistPermissions = "0.33.2-alpha"
activityCompose = "1.10.0"
appcompat = "1.7.0"
composeBom = "2025.01.01"
composeSettingsStoragePreferences = "1.0.3"
composeSettingsUiM3 = "1.0.3"
daggerCompiler = "2.49"
hiltAndroid = "2.49"
hiltCompiler = "2.49"
lifecycleRuntimeKtx = "2.8.7"
media3Session = "1.5.1"
navigationCompose = "2.8.6"
kotlin = "1.9.22"
[libraries]
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
androidx-material3 = { module = "androidx.compose.material3:material3" }
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3Session" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
compose-settings-storage-preferences = { module = "com.github.alorma:compose-settings-storage-preferences", version.ref = "composeSettingsStoragePreferences" }
compose-settings-ui-m3 = { module = "com.github.alorma:compose-settings-ui-m3", version.ref = "composeSettingsUiM3" }
dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "daggerCompiler" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hiltCompiler" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" }

Binary file not shown.

@ -0,0 +1,6 @@
#Sun Dec 17 15:00:03 CST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
android/gradlew vendored Executable file

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
android/gradlew.bat vendored Normal file

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1,21 @@
javac = find_program('javac')
bridge_header = custom_target(
'org_musicpd_Bridge.h',
output: 'org_musicpd_Bridge.h',
input: [
'../app/src/main/java/org/musicpd/Bridge.java',
],
command: [
javac,
'-source', '1.8', '-target', '1.8',
'-Xlint:-options',
'-cp', join_paths(android_sdk_platform_dir, 'android.jar'),
# not interested in *.class, we only want the JNI header
'-d', '@PRIVATE_DIR@',
'-h', '@OUTDIR@',
'@INPUT@',
],
)

@ -1,24 +0,0 @@
#!/bin/sh -e
S=`dirname "$0"`
AAPT=$1
BASE_JAR=$2
JAVA_PKG=$3
JAVA_PKG_PATH=$4
APK_FILE="$5"
D=`dirname "$APK_FILE"`
rm -rf "$D/res"
mkdir -p "$D/res/drawable" "$D/src"
cp "$D/icon.png" "$D/notification_icon.png" "$D/res/drawable/"
"$AAPT" package -f -m --auto-add-overlay \
--custom-package "$JAVA_PKG" \
-M "$S/AndroidManifest.xml" \
-S "$D/res" \
-S "$S/res" \
-J "$D/src" \
-I "$BASE_JAR" \
-F "$D/resources.apk"
cp "$D/src/$JAVA_PKG_PATH/R.java" "$D/"

@ -5,136 +5,13 @@ android_ndk = get_option('android_ndk')
android_sdk = get_option('android_sdk')
android_abi = get_option('android_abi')
android_sdk_build_tools_version = '29.0.3'
android_sdk_platform = 'android-29'
android_sdk_build_tools_version = '34.0.0'
android_sdk_platform = 'android-34'
android_build_tools_dir = join_paths(android_sdk, 'build-tools', android_sdk_build_tools_version)
android_sdk_platform_dir = join_paths(android_sdk, 'platforms', android_sdk_platform)
android_aidl = join_paths(android_build_tools_dir, 'aidl')
android_aapt = join_paths(android_build_tools_dir, 'aapt')
android_dx = join_paths(android_build_tools_dir, 'dx')
android_zipalign = join_paths(android_build_tools_dir, 'zipalign')
javac = find_program('javac')
apksigner = find_program('apksigner')
rsvg_convert = find_program('rsvg-convert')
convert = find_program('convert')
zip = find_program('zip')
android_gradlew = join_paths(meson.current_source_dir(), 'gradlew')
common_cppflags += '-I' + join_paths(meson.current_build_dir(), 'include')
#
# AIDL
#
IMainCallback_java = custom_target(
'IMainCallback.java',
output: 'IMainCallback.java',
input: join_paths(meson.current_source_dir(), 'src', 'IMainCallback.aidl'),
command: [
join_paths(meson.current_source_dir(), 'run-aidl.sh'),
android_aidl,
'@INPUT@',
'@OUTPUT@',
join_paths(meson.current_build_dir(), 'src'),
android_package_path,
],
)
IMain_java = custom_target(
'IMain.java',
output: 'IMain.java',
input: join_paths(meson.current_source_dir(), 'src', 'IMain.aidl'),
depends: IMainCallback_java,
command: [
join_paths(meson.current_source_dir(), 'run-aidl.sh'),
android_aidl,
'@INPUT@',
'@OUTPUT@',
join_paths(meson.current_build_dir(), 'src'),
android_package_path,
],
)
#
# Resources
#
android_icon = custom_target(
'Android icon',
output: 'icon.png',
input: '../mpd.svg',
command: [
rsvg_convert, '--width=48', '--height=48', '@INPUT@', '-o', '@OUTPUT@',
],
)
android_notification_icon = custom_target(
'Android notification icon',
output: 'notification_icon.png',
input: android_icon,
command: [
convert, '@INPUT@', '-colorspace', 'Gray', '-gamma', '2.2', '@OUTPUT@',
],
)
resources_apk = custom_target(
'resources.apk',
output: ['resources.apk', 'R.java'],
input: [
'res/layout/custom_notification_gb.xml',
'res/layout/log_item.xml',
'res/layout/settings.xml',
'res/values/strings.xml',
android_icon,
android_notification_icon,
],
command: [
join_paths(meson.current_source_dir(), 'make-resources-apk.sh'),
android_aapt,
join_paths(android_sdk_platform_dir, 'android.jar'),
android_package,
android_package_path,
'@OUTPUT0@',
],
)
#
# Compile Java
#
classes_jar = custom_target(
'classes.jar',
output: 'classes.jar',
input: [
'src/Bridge.java',
'src/Loader.java',
'src/Main.java',
'src/Receiver.java',
'src/Settings.java',
IMain_java,
IMainCallback_java,
resources_apk[1],
],
command: [
join_paths(meson.current_source_dir(), 'run-javac.sh'),
javac,
join_paths(android_sdk_platform_dir, 'android.jar'),
android_package_path,
zip,
'@OUTPUT@',
'@INPUT@',
],
)
classes_dex = custom_target(
'classes.dex',
output: 'classes.dex',
input: classes_jar,
command: [
android_dx,
'--dex', '--output', '@OUTPUT@',
'@INPUT@',
],
)
subdir('include')

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:typeface="monospace" />

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ToggleButton
android:id="@+id/run"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textOn="@string/toggle_button_run_on"
android:textOff="@string/toggle_button_run_off" />
<CheckBox
android:id="@+id/run_on_boot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/checkbox_run_on_boot" />
<CheckBox
android:id="@+id/wakelock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/checkbox_wakelock" />
<CheckBox
android:id="@+id/pause_on_headphones_disconnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/checkbox_pause_on_headphones_disconnect" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/log_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dip" />
</LinearLayout>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MPD</string>
<string name="notification_title_mpd_running">Music Player Daemon is running</string>
<string name="notification_text_mpd_running">Touch for MPD options.</string>
<string name="toggle_button_run_on">MPD is running</string>
<string name="toggle_button_run_off">MPD is not running</string>
<string name="checkbox_run_on_boot">Run MPD automatically on boot</string>
<string name="checkbox_wakelock">Prevent suspend when MPD is running (Wakelock)</string>
<string name="checkbox_pause_on_headphones_disconnect">Pause MPD when headphones disconnect</string>
</resources>

@ -1,12 +0,0 @@
#!/bin/sh -e
AIDL=$1
SRC=$2
DST=$3
GENSRC=$4
JAVA_PKG_PATH=$5
mkdir -p "$GENSRC/$JAVA_PKG_PATH"
cp "$SRC" "$GENSRC/$JAVA_PKG_PATH/"
"$AIDL" -I"$GENSRC" -o"$GENSRC" "$GENSRC/$JAVA_PKG_PATH/`basename $SRC`"
exec cp "$GENSRC/$JAVA_PKG_PATH/`basename $DST`" "$DST"

@ -1,22 +0,0 @@
#!/bin/sh -e
JAVAC=$1
CLASSPATH=$2
JAVA_PKG_PATH=$3
ZIP=$4
JARFILE=`realpath "$5"`
shift 5
D=`dirname "$JARFILE"`
GENSRC="$D/src"
GENCLASS="$D/classes"
GENINCLUDE="$D/include"
mkdir -p "$GENSRC/$JAVA_PKG_PATH"
"$JAVAC" -source 1.7 -target 1.7 -Xlint:-options \
-cp "$CLASSPATH" \
-h "$GENINCLUDE" \
-d "$GENCLASS" \
"$@"
cd "$GENCLASS"
zip -q -r "$JARFILE" .

@ -0,0 +1,18 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "MPD"
include(":app")

@ -1,37 +0,0 @@
/*
* Copyright 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.musicpd;
import android.content.Context;
/**
* Bridge to native code.
*/
public class Bridge {
/* used by jni */
public interface LogListener {
public void onLog(int priority, String msg);
}
public static native void run(Context context, LogListener logListener);
public static native void shutdown();
public static native void pause();
}

@ -1,39 +0,0 @@
/*
* Copyright 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.musicpd;
import android.util.Log;
public class Loader {
private static final String TAG = "MPD";
public static boolean loaded = false;
public static String error;
static {
try {
System.loadLibrary("mpd");
loaded = true;
} catch (UnsatisfiedLinkError e) {
Log.e(TAG, e.getMessage());
error = e.getMessage();
}
}
}

@ -1,475 +0,0 @@
/*
* Copyright 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.musicpd;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import android.widget.RemoteViews;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Main extends Service implements Runnable {
private static final String TAG = "Main";
private static final String REMOTE_ERROR = "MPD process was killed";
private static final int MAIN_STATUS_ERROR = -1;
private static final int MAIN_STATUS_STOPPED = 0;
private static final int MAIN_STATUS_STARTED = 1;
private static final int MSG_SEND_STATUS = 0;
private static final int MSG_SEND_LOG = 1;
private Thread mThread = null;
private int mStatus = MAIN_STATUS_STOPPED;
private boolean mAbort = false;
private String mError = null;
private final RemoteCallbackList<IMainCallback> mCallbacks = new RemoteCallbackList<IMainCallback>();
private final IBinder mBinder = new MainStub(this);
private boolean mPauseOnHeadphonesDisconnect = false;
private PowerManager.WakeLock mWakelock = null;
static class MainStub extends IMain.Stub {
private Main mService;
MainStub(Main service) {
mService = service;
}
public void start() {
mService.start();
}
public void stop() {
mService.stop();
}
public void setPauseOnHeadphonesDisconnect(boolean enabled) {
mService.setPauseOnHeadphonesDisconnect(enabled);
}
public void setWakelockEnabled(boolean enabled) {
mService.setWakelockEnabled(enabled);
}
public boolean isRunning() {
return mService.isRunning();
}
public void registerCallback(IMainCallback cb) {
mService.registerCallback(cb);
}
public void unregisterCallback(IMainCallback cb) {
mService.unregisterCallback(cb);
}
}
private synchronized void sendMessage(int what, int arg1, int arg2, Object obj) {
int i = mCallbacks.beginBroadcast();
while (i > 0) {
i--;
final IMainCallback cb = mCallbacks.getBroadcastItem(i);
try {
switch (what) {
case MSG_SEND_STATUS:
switch (arg1) {
case MAIN_STATUS_ERROR:
cb.onError((String)obj);
break;
case MAIN_STATUS_STOPPED:
cb.onStopped();
break;
case MAIN_STATUS_STARTED:
cb.onStarted();
break;
}
break;
case MSG_SEND_LOG:
cb.onLog(arg1, (String) obj);
break;
}
} catch (RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
private Bridge.LogListener mLogListener = new Bridge.LogListener() {
@Override
public void onLog(int priority, String msg) {
sendMessage(MSG_SEND_LOG, priority, 0, msg);
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
start();
if (intent != null && intent.getBooleanExtra("wakelock", false))
setWakelockEnabled(true);
return START_STICKY;
}
@Override
public void run() {
if (!Loader.loaded) {
final String error = "Failed to load the native MPD libary.\n" +
"Report this problem to us, and include the following information:\n" +
"SUPPORTED_ABIS=" + String.join(", ", Build.SUPPORTED_ABIS) + "\n" +
"PRODUCT=" + Build.PRODUCT + "\n" +
"FINGERPRINT=" + Build.FINGERPRINT + "\n" +
"error=" + Loader.error;
setStatus(MAIN_STATUS_ERROR, error);
stopSelf();
return;
}
synchronized (this) {
if (mAbort)
return;
setStatus(MAIN_STATUS_STARTED, null);
}
Bridge.run(this, mLogListener);
setStatus(MAIN_STATUS_STOPPED, null);
}
private synchronized void setStatus(int status, String error) {
mStatus = status;
mError = error;
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError);
}
private Notification.Builder createNotificationBuilderWithChannel() {
final NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null)
return null;
final String id = "org.musicpd";
final String name = "MPD service";
final int importance = 3; /* NotificationManager.IMPORTANCE_DEFAULT */
try {
Class<?> ncClass = Class.forName("android.app.NotificationChannel");
Constructor<?> ncCtor = ncClass.getConstructor(String.class, CharSequence.class, int.class);
Object nc = ncCtor.newInstance(id, name, importance);
Method nmCreateNotificationChannelMethod =
NotificationManager.class.getMethod("createNotificationChannel", ncClass);
nmCreateNotificationChannelMethod.invoke(notificationManager, nc);
Constructor nbCtor = Notification.Builder.class.getConstructor(Context.class, String.class);
return (Notification.Builder) nbCtor.newInstance(this, id);
} catch (Exception e)
{
Log.e(TAG, "error creating the NotificationChannel", e);
return null;
}
}
private void start() {
if (mThread != null)
return;
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!mPauseOnHeadphonesDisconnect)
return;
if (intent.getAction() == AudioManager.ACTION_AUDIO_BECOMING_NOISY)
pause();
}
}, filter);
final Intent mainIntent = new Intent(this, Settings.class);
mainIntent.setAction("android.intent.action.MAIN");
mainIntent.addCategory("android.intent.category.LAUNCHER");
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
mainIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder nBuilder;
if (Build.VERSION.SDK_INT >= 26 /* Build.VERSION_CODES.O */)
{
nBuilder = createNotificationBuilderWithChannel();
if (nBuilder == null)
return;
}
else
nBuilder = new Notification.Builder(this);
Notification notification = nBuilder.setContentTitle(getText(R.string.notification_title_mpd_running))
.setContentText(getText(R.string.notification_text_mpd_running))
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(contentIntent)
.build();
mThread = new Thread(this);
mThread.start();
startForeground(R.string.notification_title_mpd_running, notification);
startService(new Intent(this, Main.class));
}
private void stop() {
if (mThread != null) {
if (mThread.isAlive()) {
synchronized (this) {
if (mStatus == MAIN_STATUS_STARTED)
Bridge.shutdown();
else
mAbort = true;
}
}
try {
mThread.join();
mThread = null;
mAbort = false;
} catch (InterruptedException ie) {}
}
setWakelockEnabled(false);
stopForeground(true);
stopSelf();
}
private void pause() {
if (mThread != null) {
if (mThread.isAlive()) {
synchronized (this) {
if (mStatus == MAIN_STATUS_STARTED)
Bridge.pause();
}
}
}
}
private void setPauseOnHeadphonesDisconnect(boolean enabled) {
mPauseOnHeadphonesDisconnect = enabled;
}
private void setWakelockEnabled(boolean enabled) {
if (enabled && mWakelock == null) {
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakelock.acquire();
Log.d(TAG, "Wakelock acquired");
} else if (!enabled && mWakelock != null) {
mWakelock.release();
mWakelock = null;
Log.d(TAG, "Wakelock released");
}
}
private boolean isRunning() {
return mThread != null && mThread.isAlive();
}
private void registerCallback(IMainCallback cb) {
if (cb != null) {
mCallbacks.register(cb);
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError);
}
}
private void unregisterCallback(IMainCallback cb) {
if (cb != null) {
mCallbacks.unregister(cb);
}
}
/*
* Client that bind the Main Service in order to send commands and receive callback
*/
public static class Client {
public interface Callback {
public void onStarted();
public void onStopped();
public void onError(String error);
public void onLog(int priority, String msg);
}
private boolean mBound = false;
private final Context mContext;
private Callback mCallback;
private IMain mIMain = null;
private final IMainCallback.Stub mICallback = new IMainCallback.Stub() {
@Override
public void onStopped() throws RemoteException {
mCallback.onStopped();
}
@Override
public void onStarted() throws RemoteException {
mCallback.onStarted();
}
@Override
public void onError(String error) throws RemoteException {
mCallback.onError(error);
}
@Override
public void onLog(int priority, String msg) throws RemoteException {
mCallback.onLog(priority, msg);
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (this) {
mIMain = IMain.Stub.asInterface(service);
try {
if (mCallback != null)
mIMain.registerCallback(mICallback);
} catch (RemoteException e) {
if (mCallback != null)
mCallback.onError(REMOTE_ERROR);
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (mCallback != null)
mCallback.onError(REMOTE_ERROR);
}
};
public Client(Context context, Callback cb) throws IllegalArgumentException {
if (context == null)
throw new IllegalArgumentException("Context can't be null");
mContext = context;
mCallback = cb;
mBound = mContext.bindService(new Intent(mContext, Main.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
public boolean start() {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.start();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean stop() {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.stop();
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean setPauseOnHeadphonesDisconnect(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.setPauseOnHeadphonesDisconnect(enabled);
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean setWakelockEnabled(boolean enabled) {
synchronized (this) {
if (mIMain != null) {
try {
mIMain.setWakelockEnabled(enabled);
return true;
} catch (RemoteException e) {
}
}
return false;
}
}
public boolean isRunning() {
synchronized (this) {
if (mIMain != null) {
try {
return mIMain.isRunning();
} catch (RemoteException e) {
}
}
return false;
}
}
public void release() {
if (mBound) {
synchronized (this) {
if (mIMain != null && mICallback != null) {
try {
if (mCallback != null)
mIMain.unregisterCallback(mICallback);
} catch (RemoteException e) {
}
}
}
mBound = false;
mContext.unbindService(mServiceConnection);
}
}
}
/*
* start Main service without any callback
*/
public static void start(Context context, boolean wakelock) {
Intent intent = new Intent(context, Main.class)
.putExtra("wakelock", wakelock);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
/* in Android 8+, we need to use this method
or else we'll get "IllegalStateException:
app is in background" */
context.startForegroundService(intent);
else
context.startService(intent);
}
}

@ -1,42 +0,0 @@
/*
* Copyright (C) 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.musicpd;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("Receiver", "onReceive: " + intent);
if (intent.getAction() == "android.intent.action.BOOT_COMPLETED") {
if (Settings.Preferences.getBoolean(context,
Settings.Preferences.KEY_RUN_ON_BOOT,
false)) {
final boolean wakelock =
Settings.Preferences.getBoolean(context,
Settings.Preferences.KEY_WAKELOCK, false);
Main.start(context, wakelock);
}
}
}
}

@ -1,308 +0,0 @@
/*
* Copyright 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.musicpd;
import java.util.LinkedList;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ToggleButton;
public class Settings extends Activity {
private static final String TAG = "Settings";
private Main.Client mClient;
private TextView mTextStatus;
private ToggleButton mRunButton;
private boolean mFirstRun;
private LinkedList<String> mLogListArray = new LinkedList<String>();
private ListView mLogListView;
private ArrayAdapter<String> mLogListAdapter;
private static final int MAX_LOGS = 500;
private static final int MSG_ERROR = 0;
private static final int MSG_STOPPED = 1;
private static final int MSG_STARTED = 2;
private static final int MSG_LOG = 3;
public static class Preferences {
public static final String KEY_RUN_ON_BOOT ="run_on_boot";
public static final String KEY_WAKELOCK ="wakelock";
public static final String KEY_PAUSE_ON_HEADPHONES_DISCONNECT ="pause_on_headphones_disconnect";
public static SharedPreferences get(Context context) {
return context.getSharedPreferences(TAG, MODE_PRIVATE);
}
public static void putBoolean(Context context, String key, boolean value) {
final SharedPreferences prefs = get(context);
if (prefs == null)
return;
final Editor editor = prefs.edit();
editor.putBoolean(key, value);
editor.apply();
}
public static boolean getBoolean(Context context, String key, boolean defValue) {
final SharedPreferences prefs = get(context);
return prefs != null ? prefs.getBoolean(key, defValue) : defValue;
}
}
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_ERROR:
Log.d(TAG, "onError");
mClient.release();
connectClient();
mRunButton.setEnabled(false);
mRunButton.setChecked(false);
mTextStatus.setText((String)msg.obj);
mFirstRun = true;
break;
case MSG_STOPPED:
Log.d(TAG, "onStopped");
mRunButton.setEnabled(true);
if (!mFirstRun && Preferences.getBoolean(Settings.this, Preferences.KEY_RUN_ON_BOOT, false))
mRunButton.setChecked(true);
else
mRunButton.setChecked(false);
mFirstRun = true;
mTextStatus.setText("");
break;
case MSG_STARTED:
Log.d(TAG, "onStarted");
mRunButton.setChecked(true);
mFirstRun = true;
mTextStatus.setText("MPD service started");
break;
case MSG_LOG:
if (mLogListArray.size() > MAX_LOGS)
mLogListArray.remove(0);
String priority;
switch (msg.arg1) {
case Log.DEBUG:
priority = "D";
break;
case Log.ERROR:
priority = "E";
break;
case Log.INFO:
priority = "I";
break;
case Log.VERBOSE:
priority = "V";
break;
case Log.WARN:
priority = "W";
break;
default:
priority = "";
}
mLogListArray.add(priority + "/ " + (String)msg.obj);
mLogListAdapter.notifyDataSetChanged();
break;
}
return true;
}
});
private final OnCheckedChangeListener mOnRunChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mClient != null) {
if (isChecked) {
mClient.start();
if (Preferences.getBoolean(Settings.this,
Preferences.KEY_WAKELOCK, false))
mClient.setWakelockEnabled(true);
if (Preferences.getBoolean(Settings.this,
Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false))
mClient.setPauseOnHeadphonesDisconnect(true);
} else {
mClient.stop();
}
}
}
};
private final OnCheckedChangeListener mOnRunOnBootChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Preferences.putBoolean(Settings.this, Preferences.KEY_RUN_ON_BOOT, isChecked);
if (isChecked && mClient != null && !mRunButton.isChecked())
mRunButton.setChecked(true);
}
};
private final OnCheckedChangeListener mOnWakelockChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Preferences.putBoolean(Settings.this, Preferences.KEY_WAKELOCK, isChecked);
if (mClient != null && mClient.isRunning())
mClient.setWakelockEnabled(isChecked);
}
};
private final OnCheckedChangeListener mOnPauseOnHeadphonesDisconnectChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Preferences.putBoolean(Settings.this, Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, isChecked);
if (mClient != null && mClient.isRunning())
mClient.setPauseOnHeadphonesDisconnect(isChecked);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
/* TODO: this sure is the wrong place to request
permissions - it will cause MPD to quit
immediately; we should request permissions when we
need them, but implementing that is complicated, so
for now, we do it here to give users a quick
solution for the problem */
requestAllPermissions();
setContentView(R.layout.settings);
mRunButton = (ToggleButton) findViewById(R.id.run);
mRunButton.setOnCheckedChangeListener(mOnRunChangeListener);
mTextStatus = (TextView) findViewById(R.id.status);
mLogListAdapter = new ArrayAdapter<String>(this, R.layout.log_item, mLogListArray);
mLogListView = (ListView) findViewById(R.id.log_list);
mLogListView.setAdapter(mLogListAdapter);
mLogListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
CheckBox checkbox = (CheckBox) findViewById(R.id.run_on_boot);
checkbox.setOnCheckedChangeListener(mOnRunOnBootChangeListener);
if (Preferences.getBoolean(this, Preferences.KEY_RUN_ON_BOOT, false))
checkbox.setChecked(true);
checkbox = (CheckBox) findViewById(R.id.wakelock);
checkbox.setOnCheckedChangeListener(mOnWakelockChangeListener);
if (Preferences.getBoolean(this, Preferences.KEY_WAKELOCK, false))
checkbox.setChecked(true);
checkbox = (CheckBox) findViewById(R.id.pause_on_headphones_disconnect);
checkbox.setOnCheckedChangeListener(mOnPauseOnHeadphonesDisconnectChangeListener);
if (Preferences.getBoolean(this, Preferences.KEY_PAUSE_ON_HEADPHONES_DISCONNECT, false))
checkbox.setChecked(true);
super.onCreate(savedInstanceState);
}
private void checkRequestPermission(String permission) {
if (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED)
return;
try {
this.requestPermissions(new String[]{permission}, 0);
} catch (Exception e) {
Log.e(TAG, "requestPermissions(" + permission + ") failed",
e);
}
}
private void requestAllPermissions() {
if (android.os.Build.VERSION.SDK_INT < 23)
/* we don't need to request permissions on
this old Android version */
return;
/* starting with Android 6.0, we need to explicitly
request all permissions before using them;
mentioning them in the manifest is not enough */
checkRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
}
private void connectClient() {
mClient = new Main.Client(this, new Main.Client.Callback() {
private void removeMessages() {
/* don't remove log messages */
mHandler.removeMessages(MSG_STOPPED);
mHandler.removeMessages(MSG_STARTED);
mHandler.removeMessages(MSG_ERROR);
}
@Override
public void onStopped() {
removeMessages();
mHandler.sendEmptyMessage(MSG_STOPPED);
}
@Override
public void onStarted() {
removeMessages();
mHandler.sendEmptyMessage(MSG_STARTED);
}
@Override
public void onError(String error) {
removeMessages();
mHandler.sendMessage(Message.obtain(mHandler, MSG_ERROR, error));
}
@Override
public void onLog(int priority, String msg) {
mHandler.sendMessage(Message.obtain(mHandler, MSG_LOG, priority, 0, msg));
}
});
}
@Override
protected void onStart() {
mFirstRun = false;
connectClient();
super.onStart();
}
@Override
protected void onStop() {
mClient.release();
mClient = null;
super.onStop();
}
}

@ -10,4 +10,4 @@ ROOT=`dirname "$BIN"`
export PKG_CONFIG_DIR=
export PKG_CONFIG_LIBDIR="${ROOT}/lib/pkgconfig:${ROOT}/share/pkgconfig"
exec /usr/bin/pkg-config "$@"
exec pkg-config "$@"

3
doc/_static/css/custom.css vendored Normal file

@ -0,0 +1,3 @@
/*
* css to override sphinx theme
*/

@ -30,7 +30,7 @@ master_doc = 'index'
# General information about the project.
project = 'Music Player Daemon'
copyright = '2003-2021 The Music Player Daemon Project'
copyright = '2003-2025 The Music Player Daemon Project'
author = 'Max Kellermann'
# The version info for the project you're documenting, acts as replacement for
@ -103,14 +103,27 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'classic'
html_theme = 'sphinx_rtd_theme'
try:
__import__(html_theme)
except ModuleNotFoundError:
import sys
print(f"Warning: Sphinx theme {html_theme!r} not available, falling back to the default theme", file=sys.stderr)
del html_theme
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_theme_options = {"sidebarwidth": "300px"}
html_theme_options = {
'navigation_depth': -1,
'sticky_navigation': False,
'includehidden': True,
'prev_next_buttons_location': 'both',
'github_url': "https://github.com/MusicPlayerDaemon/"
}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
@ -140,6 +153,10 @@ html_theme_options = {"sidebarwidth": "300px"}
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'css/custom.css',
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.

@ -12,7 +12,7 @@ Code Style
* indent with tabs (width 8)
* don't write CPP when you can write C++: use inline functions and constexpr instead of macros
* comment your code, document your APIs
* the code should be C++17 compliant, and must compile with :program:`GCC` 8 and :program:`clang` 5
* the code should be C++20 compliant, and must compile with :program:`GCC` 12 and :program:`clang` 14
* all code must be exception-safe
* classes and functions names use CamelCase; variables are lower-case with words separated by underscore

@ -2038,9 +2038,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = GCC_CHECK_VERSION(major,minor)=0 \
CLANG_OR_GCC_VERSION(major,minor)=0 \
GCC_OLDER_THAN(major,minor)=0
PREDEFINED = GCC_CHECK_VERSION(major,minor)=0
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

Some files were not shown because too many files have changed in this diff Show More