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 #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 #include +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 listener; boost::intrusive::listWith([](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 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 lock(mutex);