diff --git a/NEWS b/NEWS index a9f1d07e19..d51e59c8e9 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,9 @@ ver 0.25 (not yet released) * require Meson 1.2 ver 0.24.7 (not yet released) +* decoder + - ffmpeg: allow seeking only if both AVFormatContext and InputStream allow it +* fix GCC 16 compiler warning * fix spurious linker failures ver 0.24.6 (2025/10/20) diff --git a/doc/mpd.conf.5.rst b/doc/mpd.conf.5.rst index 10150451be..2ea618dbdd 100644 --- a/doc/mpd.conf.5.rst +++ b/doc/mpd.conf.5.rst @@ -80,23 +80,34 @@ Global Settings System Settings ^^^^^^^^^^^^^^^ -user +.. confval:: user + :type: NAME + This specifies the user that MPD will run as, if set. MPD should never run as root, and you may use this option to make MPD change its user id after initialization. Do not use this option if you start MPD as an unprivileged user. -group +.. confval:: group + :type: NAME + Change to this group. This discards all default groups and uses only this group. Do not use this setting. -pid_file +.. confval:: pid_file + :type: PATH + This specifies the file to save mpd's process ID in. -log_file +.. confval:: log_file + :type: PATH + This specifies where the log file should be located. The special value "syslog" makes MPD use the local syslog daemon. -log_level +.. confval:: log_level + :type: LEVEL + :default: ``notice`` + Suppress all messages below the given threshold. The following log levels are available: @@ -107,109 +118,152 @@ log_level - :samp:`verbose`: debug messages (for developers and for troubleshooting) - The default is :samp:`notice`. - Client Settings ^^^^^^^^^^^^^^^ -port - This specifies the port that mpd listens on. The default is 6600. +.. confval:: port + :type: number + :default: :samp:`6600` + + This specifies the port that mpd listens on. File Settings ^^^^^^^^^^^^^ -db_file +.. confval:: db_file + :type: PATH + This specifies where the db file will be stored. -sticker_file +.. confval:: sticker_file + :type: PATH + The location of the sticker database. This is a database which manages dynamic information attached to songs. -music_directory +.. confval:: music_directory + :type: PATH + This specifies the directory where music is located. If you do not configure this, you can only play streams. -playlist_directory +.. confval:: playlist_directory + :type: PATH + This specifies the directory where saved playlists are stored. If you do not configure this, you cannot save playlists. -state_file +.. confval:: state_file + :type: PATH + This specifies if a state file is used and where it is located. The state of mpd will be saved to this file when mpd is terminated by a TERM signal or by the :program:`kill` command. When mpd is restarted, it will read the state file and restore the state of mpd (including the playlist). -follow_outside_symlinks - Control if MPD will follow symbolic links pointing outside the music dir. You - must recreate the database after changing this option. The default is "yes". +.. confval:: follow_outside_symlinks + :type: ``yes`` or ``no`` + :default: ``yes`` + + Control if MPD will follow symbolic links pointing outside the music dir. You + must recreate the database after changing this option. + +.. confval:: follow_inside_symlinks + :type: ``yes`` or ``no`` + :default: ``yes`` -follow_inside_symlinks - Control if MPD will follow symbolic links pointing inside the music dir, - potentially adding duplicates to the database. You must recreate the - database after changing this option. The default is "yes". + Control if MPD will follow symbolic links pointing inside the music dir, + potentially adding duplicates to the database. You must recreate the + database after changing this option. -auto_update - This specifies the whether to support automatic update of music database - when files are changed in music_directory. The default is to disable - autoupdate of database. - (Only implemented on Linux.) +.. confval:: auto_update + :type: ``yes`` or ``no`` + :default: ``no`` -auto_update_depth - Limit the depth of the directories being watched, 0 means only watch the - music directory itself. There is no limit by default. + This specifies the whether to support automatic update of music database + when files are changed in music_directory. + (Only implemented on Linux.) -save_absolute_paths_in_playlists - This specifies whether relative or absolute paths for song filenames are used - when saving playlists. The default is "no". +.. confval:: auto_update_depth + :type: number + :default: unlimited -filesystem_charset - This specifies the character set used for the filesystem. A list of supported - character sets can be obtained by running "iconv -l". The default is - determined from the locale when the db was originally created. + Limit the depth of the directories being watched, 0 means only watch the + music directory itself. + +.. confval:: save_absolute_paths_in_playlists + :type: ``yes`` or ``no`` + :default: ``no`` + + This specifies whether relative or absolute paths for song filenames are used + when saving playlists. + +.. confval:: filesystem_charset + :type: CHARSET + + This specifies the character set used for the filesystem. A list of supported + character sets can be obtained by running "iconv -l". The default is + determined from the locale when the db was originally created. Player Settings ^^^^^^^^^^^^^^^ -restore_paused +.. confval:: restore_paused + :type: ``yes`` or ``no`` + :default: ``no`` + Put MPD into pause mode instead of starting playback after startup. Other Settings ^^^^^^^^^^^^^^ -zeroconf_enabled - If yes, and MPD has been compiled with support for Avahi or Bonjour, service - information will be published with Zeroconf. The default is yes. +.. confval:: zeroconf_enabled + :type: ``yes`` or ``no`` + :default: ``yes`` + + If yes, and MPD has been compiled with support for Avahi or Bonjour, service + information will be published with Zeroconf. + +.. confval:: zeroconf_name + :type: NAME + :default: :samp:`Music Player @ %h` -zeroconf_name - If Zeroconf is enabled, this is the service name to publish. This name should - be unique to your local network, but name collisions will be properly dealt - with. The default is "Music Player @ %h", where %h will be replaced with the - hostname of the machine running MPD. + If Zeroconf is enabled, this is the service name to publish. This + name should be unique to your local network, but name collisions + will be properly dealt with. ``%h`` will be replaced with the + hostname of the machine running MPD. -audio_output - See DESCRIPTION and the various ``AUDIO OUTPUT OPTIONS`` sections for the - format of this block. Multiple audio_output sections may be specified. If - no audio_output section is specified, then MPD will scan for a usable audio - output. +.. confval:: audio_output + + See DESCRIPTION and the various ``AUDIO OUTPUT OPTIONS`` sections for the + format of this block. Multiple audio_output sections may be specified. If + no audio_output section is specified, then MPD will scan for a usable audio + output. Required Audio Output Settings ------------------------------ -type - This specifies the audio output type. See the list of supported outputs in - ``mpd --version`` for possible values. +.. confval:: type + :type: NAME + + This specifies the audio output type. See the list of supported outputs in + ``mpd --version`` for possible values. + +.. confval:: name + :type: NAME -name - This specifies a unique name for the audio output. + This specifies a unique name for the audio output. Optional Audio Output Settings ------------------------------ -format +.. confval:: format + :type: ``sample_rate:bits:channels`` + This specifies the sample rate, bits per sample, and number of channels of audio that is sent to the audio output device. See documentation for the ``audio_output_format`` option for more details. The default is to use @@ -217,16 +271,21 @@ format attributes may be an asterisk to specify that this attribute should not be enforced -replay_gain_handler - Specifies how replay gain is applied. The default is "software", which uses - an internal software volume control. "mixer" uses the configured (hardware) - mixer control. "none" disables replay gain on this audio output. +.. confval:: replay_gain_handler + :type: ``software``, ``mixer`` or ``none`` + :default: ``software`` + + Specifies how replay gain is applied. ``software`` uses an internal + software volume control. ``mixer`` uses the configured (hardware) + mixer control. ``none`` disables replay gain on this audio output. + +.. confval:: mixer_type + :type: ``hardware``, ``software`` or ``none`` + :default: ``hardware`` (if supported) or ``none`` -mixer_type - Specifies which mixer should be used for this audio output: the hardware - mixer (available for ALSA, OSS and PulseAudio), the software mixer or no - mixer ("none"). By default, the hardware mixer is used for devices which - support it, and none for the others. + Specifies which mixer should be used for this audio output: the hardware + mixer (available for ALSA, OSS and PulseAudio), the software mixer or no + mixer (``none``). Files ----- diff --git a/doc/mpdconf.example b/doc/mpdconf.example index 419fd59e6a..dd16a74d99 100644 --- a/doc/mpdconf.example +++ b/doc/mpdconf.example @@ -1,5 +1,5 @@ # An example configuration file for MPD. -# Read the user manual for documentation: http://www.musicpd.org/doc/user/ +# Read the user manual for documentation: https://mpd.readthedocs.io/en/stable/user.html#configuration # Files and directories ####################################################### @@ -166,6 +166,15 @@ # If this setting is set, MPD will require password authorization. The password # setting can be specified multiple times for different password profiles. # +# Possible permisisons: +# +# NAME DESCRIPTION +# read Allows reading of the database, displaying the current playlist, and current status of MPD. +# add Allows adding songs and loading playlists. +# player Allows any player and queue manipulation (start/pause/stop playback etc.). +# control Allows all other player and playlist manipulations. +# admin Allows manipulating outputs, stickers and partitions, mounting/unmounting storage and shutting down MPD. +# #password "password@read,add,control,admin" # # This setting specifies the permissions a user has who has not yet logged in. diff --git a/doc/user.rst b/doc/user.rst index 425896c108..a1b2d4da1b 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -249,9 +249,16 @@ information about the :program:`MPD` configuration file. Configuring the music directory ------------------------------- -When you play local files, you should organize them within a directory called the "music directory". This is configured in :program:`MPD` with the music_directory setting. +When you play local files, you should organize them within a directory +called the "music directory". This is configured in :program:`MPD` +with the :confval:`music_directory` setting. -By default, :program:`MPD` follows symbolic links in the music directory. This behavior can be switched off: :code:`follow_outside_symlinks` controls whether :program:`MPD` follows links pointing to files outside of the music directory, and :code:`follow_inside_symlinks` lets you disable symlinks to files inside the music directory. +By default, :program:`MPD` follows symbolic links in the music +directory. This behavior can be switched off: +:confval:`follow_outside_symlinks` controls whether :program:`MPD` +follows links pointing to files outside of the music directory, and +:confval:`follow_inside_symlinks` lets you disable symlinks to files +inside the music directory. Instead of using local files, you can use storage plugins to access files on a remote file server. For example, to use music from the @@ -788,7 +795,7 @@ address:: bind_to_address "@mpd" If no port is specified, the default port is 6600. This default can -be changed with the port setting:: +be changed with the :confval:`port` setting:: port "6601" @@ -984,7 +991,14 @@ One approach for optimization is running :program:`MPD` on the file server, whic host "fileserver.local" } -The :code:`music_directory` setting tells :program:`MPD` to read files from the given NFS server. It does this by connecting to the server from userspace. This does not actually mount the file server into the kernel's virtual file system, and thus requires no kernel cooperation and no special privileges. It does not even require a kernel with NFS support, only the nfs storage plugin (using the libnfs userspace library). The same can be done with SMB/CIFS using the smbclient storage plugin (using libsmbclient). +The :confval:`music_directory` setting tells :program:`MPD` to read +files from the given NFS server. It does this by connecting to the +server from userspace. This does not actually mount the file server +into the kernel's virtual file system, and thus requires no kernel +cooperation and no special privileges. It does not even require a +kernel with NFS support, only the nfs storage plugin (using the libnfs +userspace library). The same can be done with SMB/CIFS using the +smbclient storage plugin (using libsmbclient). The database setting tells :program:`MPD` to pass all database queries on to the :program:`MPD` instance running on the file server (using the proxy plugin). @@ -1056,7 +1070,7 @@ simply type:: This will start :program:`MPD` as a daemon process (which means it detaches from your terminal and continues to run in background). To stop it, send ``SIGTERM`` to the process; if you have configured a -``pid_file``, you can use the ``--kill`` option:: +:confval:`pid_file`, you can use the ``--kill`` option:: mpd --kill @@ -1192,7 +1206,10 @@ Mounting is only possible with the simple database plugin and a :code:`cache_dir # cache_directory "~/.mpd/cache" } -This requires migrating from the old :code:`db_file` setting to a database section. The cache directory must exist, and :program:`MPD` will put one file per mount there, which will be reused when the same storage is used again later. +This requires migrating from the old :confval:`db_file` setting to a +database section. The cache directory must exist, and :program:`MPD` +will put one file per mount there, which will be reused when the same +storage is used again later. Metadata -------- @@ -1225,7 +1242,7 @@ Stored Playlists Stored playlists are some kind of secondary playlists which can be created, saved, edited and deleted by the client. They are addressed by their names. Its contents can be loaded into the queue, to be -played back. The :code:`playlist_directory` setting specifies where +played back. The :confval:`playlist_directory` setting specifies where those playlists are stored. Advanced usage @@ -1395,7 +1412,7 @@ Database I can't see my music in the MPD database ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Check your :code:`music_directory` setting. +* Check your :confval:`music_directory` setting. * Does the MPD user have read permission on all music files, and read+execute permission on all music directories (and all of their parent directories)? * Did you update the database? (mpc update) * Did you enable all relevant decoder plugins at compile time? :command:`mpd --version` will tell you. diff --git a/python/build/libs.py b/python/build/libs.py index e53a5bcad3..fa90cc8e00 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -36,8 +36,8 @@ ) libopenmpt = AutotoolsProject( - 'https://lib.openmpt.org/files/libopenmpt/src/libopenmpt-0.8.3+release.autotools.tar.gz', - '0b18a9b67674e300f4915f52ef902a9bb184b96a0d93efbc2058ec9526dc97039e0da53d9605e7fda97c46734529813008c2110e2cb4822e04e411444ff21db9', + 'https://lib.openmpt.org/files/libopenmpt/src/libopenmpt-0.8.4+release.autotools.tar.gz', + '627f9bf11aacae615a1f2c982c7e88cb21f11b2d6f0267946f7c82c5eae4943b', 'lib/libopenmpt.a', [ '--disable-shared', '--enable-static', @@ -79,8 +79,8 @@ ) ffmpeg = FfmpegProject( - 'http://ffmpeg.org/releases/ffmpeg-8.0.tar.xz', - 'b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e', + 'http://ffmpeg.org/releases/ffmpeg-8.0.1.tar.xz', + '05ee0b03119b45c0bdb4df654b96802e909e0a752f72e4fe3794f487229e5a41', 'lib/libavcodec.a', [ '--disable-shared', '--enable-static', diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx index f3f739b13e..023da614ed 100644 --- a/src/db/plugins/ProxyDatabasePlugin.cxx +++ b/src/db/plugins/ProxyDatabasePlugin.cxx @@ -20,6 +20,7 @@ #include "tag/Builder.hxx" #include "tag/Tag.hxx" #include "tag/ParseName.hxx" +#include "tag/WithTagBuffer.hxx" #include "lib/fmt/RuntimeError.hxx" #include "util/RecursiveMap.hxx" #include "util/ScopeExit.hxx" @@ -48,9 +49,7 @@ class LibmpdclientError final : public std::runtime_error { } }; -class ProxySong : public LightSong { - Tag tag2; - +class ProxySong : WithTagBuffer, public LightSong { public: explicit ProxySong(const mpd_song *song); }; @@ -206,7 +205,7 @@ Copy(TagBuilder &tag, TagType d_tag, } ProxySong::ProxySong(const mpd_song *song) - :LightSong(mpd_song_get_uri(song), tag2) + :LightSong(mpd_song_get_uri(song), tag_buffer) { const auto _mtime = mpd_song_get_last_modified(song); if (_mtime > 0) @@ -265,7 +264,7 @@ ProxySong::ProxySong(const mpd_song *song) for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i) Copy(tag_builder, i->d, song, i->s); - tag_builder.Commit(tag2); + tag_builder.Commit(tag_buffer); } [[gnu::const]] diff --git a/src/db/plugins/simple/ExportedSong.hxx b/src/db/plugins/simple/ExportedSong.hxx index af2795d2bb..0e04bfd564 100644 --- a/src/db/plugins/simple/ExportedSong.hxx +++ b/src/db/plugins/simple/ExportedSong.hxx @@ -1,44 +1,35 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_DB_SIMPLE_EXPORTED_SONG_HXX -#define MPD_DB_SIMPLE_EXPORTED_SONG_HXX +#pragma once #include "song/LightSong.hxx" -#include "tag/Tag.hxx" +#include "tag/WithTagBuffer.hxx" /** * The return type for Song::Export(). In addition to implementing * #LightSong, it hold allocations necessary to represent the #Song as * a #LightSong, e.g. a merged #Tag. */ -class ExportedSong : public LightSong { - /** - * A reference target for LightSong::tag, but it is only used - * if this instance "owns" the #Tag. For instances referring - * to a foreign #Tag instance (e.g. a Song::tag), this field - * is not used (and empty). - */ - Tag tag_buffer; - +class ExportedSong : WithTagBuffer, public LightSong { public: using LightSong::LightSong; ExportedSong(const char *_uri, Tag &&_tag) noexcept - :LightSong(_uri, tag_buffer), - tag_buffer(std::move(_tag)) {} + :WithTagBuffer(std::move(_tag)), + LightSong(_uri, tag_buffer) {} /* this custom move constructor is necessary so LightSong::tag points to this instance's #Tag field instead of leaving a dangling reference to the source object's #Tag field */ ExportedSong(ExportedSong &&src) noexcept - :LightSong(src, + :WithTagBuffer(std::move(src.tag_buffer)), + LightSong(src, /* refer to tag_buffer only if the moved-from instance also owned the Tag which its LightSong::tag field refers to */ - src.OwnsTag() ? tag_buffer : src.tag), - tag_buffer(std::move(src.tag_buffer)) {} + src.OwnsTag() ? tag_buffer : src.tag) {} ExportedSong &operator=(ExportedSong &&) = delete; @@ -47,5 +38,3 @@ private: return &tag == &tag_buffer; } }; - -#endif diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 7ca75a524b..024763c171 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -520,8 +520,8 @@ FfmpegDecode(DecoderClient &client, InputStream *input, : FromFfmpegTimeChecked(format_context.duration, AV_TIME_BASE_Q); client.Ready(audio_format, - (input ? input->IsSeekable() : false) - || IsSeekable(format_context), + IsSeekable(format_context) && + (!input || input->IsSeekable()), total_time); FfmpegParseMetaData(client, format_context, audio_stream); diff --git a/src/tag/WithTagBuffer.hxx b/src/tag/WithTagBuffer.hxx new file mode 100644 index 0000000000..44f7327e38 --- /dev/null +++ b/src/tag/WithTagBuffer.hxx @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright The Music Player Daemon Project + +#pragma once + +#include "Tag.hxx" + +/** + * Helper class for #ExportedSong and #ProxySong so the #Tag field + * gets initialized before the #LightSong base class. This + * initialization order is needed so #LightSong is allowed to refer to + * the #Tag field. + */ +struct WithTagBuffer { + /** + * A reference target for LightSong::tag, but it is only used + * if this instance "owns" the #Tag. For instances referring + * to a foreign #Tag instance (e.g. a Song::tag), this field + * is not used (and empty). + */ + Tag tag_buffer; + + WithTagBuffer() noexcept = default; + + WithTagBuffer(Tag &&src) noexcept + :tag_buffer(std::move(src)) {} +}; diff --git a/subprojects/libnpupnp.wrap b/subprojects/libnpupnp.wrap index c91d1ee769..768b541666 100644 --- a/subprojects/libnpupnp.wrap +++ b/subprojects/libnpupnp.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = libnpupnp-6.2.1 -source_url = https://www.lesbonscomptes.com/upmpdcli/downloads/libnpupnp-6.2.1.tar.gz -source_filename = libnpupnp-6.2.1.tar.gz -source_hash = 1cc1222512d480826d2923cc7b98b7361183a2add8c6b646a7fa32c2f34b32b3 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libnpupnp_6.2.1-1/libnpupnp-6.2.1.tar.gz -wrapdb_version = 6.2.1-1 +directory = libnpupnp-6.2.3 +source_url = https://www.lesbonscomptes.com/upmpdcli/downloads/libnpupnp-6.2.3.tar.gz +source_filename = libnpupnp-6.2.3.tar.gz +source_hash = 563d2a9e4afe603717343dc4667c0b89c6a017008ac6b52262da17a1e4f6bb96 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libnpupnp_6.2.3-1/libnpupnp-6.2.3.tar.gz +wrapdb_version = 6.2.3-1 [provide] libnpupnp = libnpupnp_dep diff --git a/subprojects/opus.wrap b/subprojects/opus.wrap index 357643b19c..ce808de0d5 100644 --- a/subprojects/opus.wrap +++ b/subprojects/opus.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = opus-1.5.2 -source_url = https://downloads.xiph.org/releases/opus/opus-1.5.2.tar.gz -source_filename = opus-1.5.2.tar.gz -source_hash = 65c1d2f78b9f2fb20082c38cbe47c951ad5839345876e46941612ee87f9a7ce1 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/opus_1.5.2-1/opus-1.5.2.tar.gz -wrapdb_version = 1.5.2-1 +directory = opus-1.6 +source_url = https://downloads.xiph.org/releases/opus/opus-1.6.tar.gz +source_filename = opus-1.6.tar.gz +source_hash = b7637334527201fdfd6dd6a02e67aceffb0e5e60155bbd89175647a80301c92c +source_fallback_url = https://wrapdb.mesonbuild.com/v2/opus_1.6-1/get_source/opus-1.6.tar.gz +wrapdb_version = 1.6-1 [provide] opus = opus_dep diff --git a/subprojects/sqlite3.wrap b/subprojects/sqlite3.wrap index 0dc6d35f81..5f21fb00ed 100644 --- a/subprojects/sqlite3.wrap +++ b/subprojects/sqlite3.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = sqlite-amalgamation-3510000 -source_url = https://www.sqlite.org/2025/sqlite-amalgamation-3510000.zip -source_filename = sqlite-amalgamation-3510000.zip -source_hash = 1caf7116f2910600d04473ad69d37ec538fa62fa36adccd37b5e0e43647c98be -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.51.0-1/sqlite-amalgamation-3510000.zip -patch_filename = sqlite3_3.51.0-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.0-1/get_patch -patch_hash = 098cc87a1492881d99f4bf85e23021882e5527d6899385098b562ac74ebaf1ec -wrapdb_version = 3.51.0-1 +directory = sqlite-amalgamation-3510100 +source_url = https://www.sqlite.org/2025/sqlite-amalgamation-3510100.zip +source_filename = sqlite-amalgamation-3510100.zip +source_hash = 84a85d6a1b920234349f01720912c12391a4f0cb5cb998087e641dee3ef8ef2e +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.51.1-1/sqlite-amalgamation-3510100.zip +patch_filename = sqlite3_3.51.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.1-1/get_patch +patch_hash = 081f7997f22175049ebfa463f876fbd707352fafdb87c13638990cd99656ef15 +wrapdb_version = 3.51.1-1 [provide] dependency_names = sqlite3