diff --git a/meson.build b/meson.build index 8695e3ff1..1716898c7 100644 --- a/meson.build +++ b/meson.build @@ -279,6 +279,8 @@ sources = [ 'src/command/PartitionCommands.cxx', 'src/command/OtherCommands.cxx', 'src/command/CommandListBuilder.cxx', + 'src/config/PartitionConfig.cxx', + 'src/config/PlayerConfig.cxx', 'src/Idle.cxx', 'src/IdleFlags.cxx', 'src/decoder/Thread.cxx', diff --git a/src/Main.cxx b/src/Main.cxx index 77575a008..bf59eb26f 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -32,7 +32,6 @@ #include "command/AllCommands.hxx" #include "Partition.hxx" #include "tag/Config.hxx" -#include "ReplayGainGlobal.hxx" #include "IdleFlags.hxx" #include "Log.hxx" #include "LogInit.hxx" @@ -46,7 +45,6 @@ #include "playlist/PlaylistRegistry.hxx" #include "zeroconf/Glue.hxx" #include "decoder/DecoderList.hxx" -#include "pcm/AudioParser.hxx" #include "pcm/Convert.hxx" #include "unix/SignalHandlers.hxx" #include "thread/Slack.hxx" @@ -60,6 +58,7 @@ #include "config/Option.hxx" #include "config/Domain.hxx" #include "config/Parser.hxx" +#include "config/PartitionConfig.hxx" #include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" @@ -116,15 +115,6 @@ #include <clocale> #endif -static constexpr size_t KILOBYTE = 1024; -static constexpr size_t MEGABYTE = 1024 * KILOBYTE; - -static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE; - -static constexpr -size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32, - 64 * KILOBYTE); - #ifdef ANDROID Context *context; LogListener *logListener; @@ -132,13 +122,6 @@ LogListener *logListener; Instance *global_instance; -struct Config { - ReplayGainConfig replay_gain; - - explicit Config(const ConfigData &raw) - :replay_gain(LoadReplayGainConfig(raw)) {} -}; - #ifdef ENABLE_DAEMON static void @@ -293,53 +276,11 @@ glue_state_file_init(Instance &instance, const ConfigData &raw_config) static void initialize_decoder_and_player(Instance &instance, const ConfigData &config, - const ReplayGainConfig &replay_gain_config) + const PartitionConfig &partition_config) { - const ConfigParam *param; - - size_t buffer_size; - param = config.GetParam(ConfigOption::AUDIO_BUFFER_SIZE); - if (param != nullptr) { - buffer_size = param->With([](const char *s){ - size_t result = ParseSize(s, KILOBYTE); - if (result <= 0) - throw FormatRuntimeError("buffer size \"%s\" is not a " - "positive integer", s); - - if (result < MIN_BUFFER_SIZE) { - FmtWarning(config_domain, "buffer size {} is too small, using {} bytes instead", - result, MIN_BUFFER_SIZE); - result = MIN_BUFFER_SIZE; - } - - return result; - }); - } else - buffer_size = DEFAULT_BUFFER_SIZE; - - const unsigned buffered_chunks = buffer_size / CHUNK_SIZE; - - if (buffered_chunks >= 1 << 15) - throw FormatRuntimeError("buffer size \"%lu\" is too big", - (unsigned long)buffer_size); - - const unsigned max_length = - config.GetPositive(ConfigOption::MAX_PLAYLIST_LENGTH, - DEFAULT_PLAYLIST_MAX_LENGTH); - - AudioFormat configured_audio_format = config.With(ConfigOption::AUDIO_OUTPUT_FORMAT, [](const char *s){ - if (s == nullptr) - return AudioFormat::Undefined(); - - return ParseAudioFormat(s, true); - }); - instance.partitions.emplace_back(instance, "default", - max_length, - buffered_chunks, - configured_audio_format, - replay_gain_config); + partition_config); auto &partition = instance.partitions.back(); partition.replay_gain_mode = config.With(ConfigOption::REPLAYGAIN, [](const char *s){ @@ -392,7 +333,7 @@ MainConfigured(const CommandLineOptions &options, #endif InitPathParser(raw_config); - const Config config(raw_config); + const PartitionConfig partition_config{raw_config}; #ifdef ENABLE_DAEMON glue_daemonize_init(options, raw_config); @@ -426,7 +367,7 @@ MainConfigured(const CommandLineOptions &options, } initialize_decoder_and_player(instance, - raw_config, config.replay_gain); + raw_config, partition_config); listen_global_init(raw_config, *instance.partitions.front().listener); @@ -465,7 +406,7 @@ MainConfigured(const CommandLineOptions &options, partition.outputs.Configure(instance.io_thread.GetEventLoop(), instance.rtio_thread.GetEventLoop(), raw_config, - config.replay_gain); + partition_config.player.replay_gain); partition.UpdateEffectiveReplayGainMode(); } diff --git a/src/Partition.cxx b/src/Partition.cxx index cf3396652..e2967daa4 100644 --- a/src/Partition.cxx +++ b/src/Partition.cxx @@ -21,6 +21,7 @@ #include "Partition.hxx" #include "Instance.hxx" #include "Log.hxx" +#include "config/PartitionConfig.hxx" #include "lib/fmt/ExceptionFormatter.hxx" #include "song/DetachedSong.hxx" #include "mixer/Volume.hxx" @@ -34,21 +35,18 @@ static constexpr Domain cache_domain("cache"); Partition::Partition(Instance &_instance, const char *_name, - unsigned max_length, - unsigned buffer_chunks, - AudioFormat configured_audio_format, - const ReplayGainConfig &replay_gain_config) noexcept + const PartitionConfig &_config) noexcept :instance(_instance), name(_name), + config(_config), listener(new ClientListener(instance.event_loop, *this)), idle_monitor(instance.event_loop, BIND_THIS_METHOD(OnIdleMonitor)), global_events(instance.event_loop, BIND_THIS_METHOD(OnGlobalEvent)), - playlist(max_length, *this), + playlist(config.queue.max_length, *this), outputs(pc, *this), pc(*this, outputs, instance.input_cache.get(), - buffer_chunks, - configured_audio_format, replay_gain_config) + config.player) { UpdateEffectiveReplayGainMode(); } diff --git a/src/Partition.hxx b/src/Partition.hxx index b90a01101..7679b5879 100644 --- a/src/Partition.hxx +++ b/src/Partition.hxx @@ -38,6 +38,7 @@ #include <string> #include <memory> +struct PartitionConfig; struct Instance; struct RangeArg; class MultipleOutputs; @@ -58,6 +59,8 @@ struct Partition final : QueueListener, PlayerListener, MixerListener { const std::string name; + const PartitionConfig &config; + std::unique_ptr<ClientListener> listener; boost::intrusive::list<Client, @@ -82,10 +85,7 @@ struct Partition final : QueueListener, PlayerListener, MixerListener { Partition(Instance &_instance, const char *_name, - unsigned max_length, - unsigned buffer_chunks, - AudioFormat configured_audio_format, - const ReplayGainConfig &replay_gain_config) noexcept; + const PartitionConfig &_config) noexcept; ~Partition() noexcept; diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index 7035136df..1fb1b9fcb 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -33,6 +33,7 @@ #include "config/Data.hxx" #include "config/Option.hxx" #include "config/Defaults.hxx" +#include "config/QueueConfig.hxx" #include "Idle.hxx" #include "fs/Limits.hxx" #include "fs/Traits.hxx" @@ -55,7 +56,7 @@ spl_global_init(const ConfigData &config) { playlist_max_length = config.GetPositive(ConfigOption::MAX_PLAYLIST_LENGTH, - DEFAULT_PLAYLIST_MAX_LENGTH); + QueueConfig::DEFAULT_MAX_LENGTH); playlist_saveAbsolutePaths = config.GetBool(ConfigOption::SAVE_ABSOLUTE_PATHS, diff --git a/src/command/PartitionCommands.cxx b/src/command/PartitionCommands.cxx index 10426a2b2..83108b7dc 100644 --- a/src/command/PartitionCommands.cxx +++ b/src/command/PartitionCommands.cxx @@ -101,11 +101,7 @@ handle_newpartition(Client &client, Request request, Response &response) } instance.partitions.emplace_back(instance, name, - // TODO: use real configuration - 16384, - 1024, - AudioFormat::Undefined(), - ReplayGainConfig()); + client.GetPartition().config); auto &partition = instance.partitions.back(); partition.UpdateEffectiveReplayGainMode(); diff --git a/src/config/Defaults.hxx b/src/config/Defaults.hxx index a5b8467e5..eaa16ace8 100644 --- a/src/config/Defaults.hxx +++ b/src/config/Defaults.hxx @@ -20,7 +20,6 @@ #ifndef MPD_CONFIG_DEFAULTS_HXX #define MPD_CONFIG_DEFAULTS_HXX -static constexpr unsigned DEFAULT_PLAYLIST_MAX_LENGTH = 16 * 1024; static constexpr bool DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS = false; #endif diff --git a/src/config/PartitionConfig.cxx b/src/config/PartitionConfig.cxx new file mode 100644 index 000000000..974e7562b --- /dev/null +++ b/src/config/PartitionConfig.cxx @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "PartitionConfig.hxx" +#include "Data.hxx" + +PartitionConfig::PartitionConfig(const ConfigData &config) + :player(config) +{ + queue.max_length = + config.GetPositive(ConfigOption::MAX_PLAYLIST_LENGTH, + QueueConfig::DEFAULT_MAX_LENGTH); +} diff --git a/src/config/PartitionConfig.hxx b/src/config/PartitionConfig.hxx new file mode 100644 index 000000000..21192eab7 --- /dev/null +++ b/src/config/PartitionConfig.hxx @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#pragma once + +#include "QueueConfig.hxx" +#include "PlayerConfig.hxx" + +struct PartitionConfig { + QueueConfig queue; + PlayerConfig player; + + PartitionConfig() = default; + + explicit PartitionConfig(const ConfigData &config); +}; diff --git a/src/config/PlayerConfig.cxx b/src/config/PlayerConfig.cxx new file mode 100644 index 000000000..206420949 --- /dev/null +++ b/src/config/PlayerConfig.cxx @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include "PartitionConfig.hxx" +#include "Data.hxx" +#include "Domain.hxx" +#include "Parser.hxx" +#include "pcm/AudioParser.hxx" +#include "util/RuntimeError.hxx" +#include "Log.hxx" +#include "MusicChunk.hxx" +#include "ReplayGainGlobal.hxx" + +static constexpr +size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32, + 64 * KILOBYTE); + +PlayerConfig::PlayerConfig(const ConfigData &config) +{ + size_t buffer_size = PlayerConfig::DEFAULT_BUFFER_SIZE; + if (auto *param = config.GetParam(ConfigOption::AUDIO_BUFFER_SIZE)) { + buffer_size = param->With([](const char *s){ + size_t result = ParseSize(s, KILOBYTE); + if (result <= 0) + throw FormatRuntimeError("buffer size \"%s\" is not a " + "positive integer", s); + + if (result < MIN_BUFFER_SIZE) { + FmtWarning(config_domain, "buffer size {} is too small, using {} bytes instead", + result, MIN_BUFFER_SIZE); + result = MIN_BUFFER_SIZE; + } + + return result; + }); + } + + buffer_chunks = buffer_size / CHUNK_SIZE; + if (buffer_chunks >= 1 << 15) + throw FormatRuntimeError("buffer size \"%lu\" is too big", + (unsigned long)buffer_size); + + audio_format = config.With(ConfigOption::AUDIO_OUTPUT_FORMAT, [](const char *s){ + if (s == nullptr) + return AudioFormat::Undefined(); + + return ParseAudioFormat(s, true); + }); + + replay_gain = LoadReplayGainConfig(config); +} diff --git a/src/config/PlayerConfig.hxx b/src/config/PlayerConfig.hxx new file mode 100644 index 000000000..07bbcf089 --- /dev/null +++ b/src/config/PlayerConfig.hxx @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#pragma once + +#include "pcm/AudioFormat.hxx" +#include "ReplayGainConfig.hxx" + +struct ConfigData; + +static constexpr size_t KILOBYTE = 1024; +static constexpr size_t MEGABYTE = 1024 * KILOBYTE; + +struct PlayerConfig { + static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE; + + unsigned buffer_chunks = DEFAULT_BUFFER_SIZE; + + /** + * The "audio_output_format" setting. + */ + AudioFormat audio_format = AudioFormat::Undefined(); + + ReplayGainConfig replay_gain; + + PlayerConfig() = default; + + explicit PlayerConfig(const ConfigData &config); +}; diff --git a/src/config/QueueConfig.hxx b/src/config/QueueConfig.hxx new file mode 100644 index 000000000..65ecb4fa3 --- /dev/null +++ b/src/config/QueueConfig.hxx @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#pragma once + +struct QueueConfig { + static constexpr unsigned DEFAULT_MAX_LENGTH = 16 * 1024; + + unsigned max_length = DEFAULT_MAX_LENGTH; +}; diff --git a/src/player/Control.cxx b/src/player/Control.cxx index f4650bef6..5e919aa1f 100644 --- a/src/player/Control.cxx +++ b/src/player/Control.cxx @@ -28,15 +28,12 @@ PlayerControl::PlayerControl(PlayerListener &_listener, PlayerOutputs &_outputs, InputCacheManager *_input_cache, - unsigned _buffer_chunks, - AudioFormat _configured_audio_format, - const ReplayGainConfig &_replay_gain_config) noexcept + const PlayerConfig &_config) noexcept :listener(_listener), outputs(_outputs), input_cache(_input_cache), - buffer_chunks(_buffer_chunks), - configured_audio_format(_configured_audio_format), - thread(BIND_THIS_METHOD(RunThread)), - replay_gain_config(_replay_gain_config) + config(_config), + thread(BIND_THIS_METHOD(RunThread)) + { } diff --git a/src/player/Control.hxx b/src/player/Control.hxx index 73f026496..26373f2a7 100644 --- a/src/player/Control.hxx +++ b/src/player/Control.hxx @@ -21,13 +21,13 @@ #define MPD_PLAYER_CONTROL_HXX #include "output/Client.hxx" +#include "config/PlayerConfig.hxx" #include "pcm/AudioFormat.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "thread/Thread.hxx" #include "CrossFade.hxx" #include "Chrono.hxx" -#include "ReplayGainConfig.hxx" #include "ReplayGainMode.hxx" #include "MusicChunkPtr.hxx" @@ -36,6 +36,7 @@ #include <memory> struct Tag; +struct PlayerConfig; class PlayerListener; class PlayerOutputs; class InputCacheManager; @@ -118,12 +119,7 @@ class PlayerControl final : public AudioOutputClient { InputCacheManager *const input_cache; - const unsigned buffer_chunks; - - /** - * The "audio_output_format" setting. - */ - const AudioFormat configured_audio_format; + const PlayerConfig config; /** * The handle of the player thread. @@ -229,17 +225,13 @@ class PlayerControl final : public AudioOutputClient { CrossFadeSettings cross_fade; - const ReplayGainConfig replay_gain_config; - FloatDuration total_play_time = FloatDuration::zero(); public: PlayerControl(PlayerListener &_listener, PlayerOutputs &_outputs, InputCacheManager *_input_cache, - unsigned buffer_chunks, - AudioFormat _configured_audio_format, - const ReplayGainConfig &_replay_gain_config) noexcept; + const PlayerConfig &_config) noexcept; ~PlayerControl() noexcept; void Kill() noexcept; diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx index 7d1416837..03012fcf2 100644 --- a/src/player/Thread.cxx +++ b/src/player/Thread.cxx @@ -1165,11 +1165,11 @@ try { DecoderControl dc(mutex, cond, input_cache, - configured_audio_format, - replay_gain_config); + config.audio_format, + config.replay_gain); dc.StartThread(); - MusicBuffer buffer(buffer_chunks); + MusicBuffer buffer{config.buffer_chunks}; std::unique_lock<Mutex> lock(mutex);