From 2efa142ec92772dc71c2dbb2e33076f00be4115f Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Wed, 24 Feb 2021 16:06:06 +0100
Subject: [PATCH] output/init: use the real-time I/O thread only for the ALSA
 plugin

---
 src/Main.cxx                   |  3 ++-
 src/output/Filtered.hxx        |  2 +-
 src/output/Init.cxx            | 10 +++++++++-
 src/output/MultipleOutputs.cxx | 14 ++++++++------
 src/output/MultipleOutputs.hxx |  2 +-
 5 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/Main.cxx b/src/Main.cxx
index 1b99ce736..ca4abfbc1 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -441,7 +441,8 @@ MainConfigured(const struct options &options, const ConfigData &raw_config)
 	command_init();
 
 	for (auto &partition : instance.partitions) {
-		partition.outputs.Configure(instance.rtio_thread.GetEventLoop(),
+		partition.outputs.Configure(instance.io_thread.GetEventLoop(),
+					    instance.rtio_thread.GetEventLoop(),
 					    raw_config,
 					    config.replay_gain);
 		partition.UpdateEffectiveReplayGainMode();
diff --git a/src/output/Filtered.hxx b/src/output/Filtered.hxx
index 1f34fbb97..29e40f006 100644
--- a/src/output/Filtered.hxx
+++ b/src/output/Filtered.hxx
@@ -239,7 +239,7 @@ public:
  * Throws on error.
  */
 std::unique_ptr<FilteredAudioOutput>
-audio_output_new(EventLoop &event_loop,
+audio_output_new(EventLoop &event_loop, EventLoop &rt_event_loop,
 		 const ReplayGainConfig &replay_gain_config,
 		 const ConfigBlock &block,
 		 const AudioOutputDefaults &defaults,
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index ba4e0b3ca..508133bda 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -264,7 +264,7 @@ FilteredAudioOutput::Setup(EventLoop &event_loop,
 }
 
 std::unique_ptr<FilteredAudioOutput>
-audio_output_new(EventLoop &event_loop,
+audio_output_new(EventLoop &normal_event_loop, EventLoop &rt_event_loop,
 		 const ReplayGainConfig &replay_gain_config,
 		 const ConfigBlock &block,
 		 const AudioOutputDefaults &defaults,
@@ -294,6 +294,14 @@ audio_output_new(EventLoop &event_loop,
 			     plugin->name);
 	}
 
+	/* use the real-time I/O thread only for the ALSA plugin;
+	   other plugins like httpd don't need real-time so badly,
+	   because they have larger buffers */
+	// TODO: don't hard-code the plugin name
+	auto &event_loop = StringIsEqual(plugin->name, "alsa")
+		? rt_event_loop
+		: normal_event_loop;
+
 	std::unique_ptr<AudioOutput> ao(ao_plugin_init(event_loop, *plugin,
 						       block));
 	assert(ao != nullptr);
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index c9b55fcd5..88c7d98d1 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -49,14 +49,14 @@ MultipleOutputs::~MultipleOutputs() noexcept
 }
 
 static std::unique_ptr<FilteredAudioOutput>
-LoadOutput(EventLoop &event_loop,
+LoadOutput(EventLoop &event_loop, EventLoop &rt_event_loop,
 	   const ReplayGainConfig &replay_gain_config,
 	   MixerListener &mixer_listener,
 	   const ConfigBlock &block,
 	   const AudioOutputDefaults &defaults,
 	   FilterFactory *filter_factory)
 try {
-	return audio_output_new(event_loop, replay_gain_config, block,
+	return audio_output_new(event_loop, rt_event_loop, replay_gain_config, block,
 				defaults,
 				filter_factory,
 				mixer_listener);
@@ -69,14 +69,15 @@ try {
 }
 
 static std::unique_ptr<AudioOutputControl>
-LoadOutputControl(EventLoop &event_loop,
+LoadOutputControl(EventLoop &event_loop, EventLoop &rt_event_loop,
 		  const ReplayGainConfig &replay_gain_config,
 		  MixerListener &mixer_listener,
 		  AudioOutputClient &client, const ConfigBlock &block,
 		  const AudioOutputDefaults &defaults,
 		  FilterFactory *filter_factory)
 {
-	auto output = LoadOutput(event_loop, replay_gain_config,
+	auto output = LoadOutput(event_loop, rt_event_loop,
+				 replay_gain_config,
 				 mixer_listener,
 				 block, defaults, filter_factory);
 	auto control = std::make_unique<AudioOutputControl>(std::move(output), client);
@@ -85,7 +86,7 @@ LoadOutputControl(EventLoop &event_loop,
 }
 
 void
-MultipleOutputs::Configure(EventLoop &event_loop,
+MultipleOutputs::Configure(EventLoop &event_loop, EventLoop &rt_event_loop,
 			   const ConfigData &config,
 			   const ReplayGainConfig &replay_gain_config)
 {
@@ -94,7 +95,7 @@ MultipleOutputs::Configure(EventLoop &event_loop,
 
 	for (const auto &block : config.GetBlockList(ConfigBlockOption::AUDIO_OUTPUT)) {
 		block.SetUsed();
-		auto output = LoadOutputControl(event_loop,
+		auto output = LoadOutputControl(event_loop, rt_event_loop,
 						replay_gain_config,
 						mixer_listener,
 						client, block, defaults,
@@ -110,6 +111,7 @@ MultipleOutputs::Configure(EventLoop &event_loop,
 		/* auto-detect device */
 		const ConfigBlock empty;
 		outputs.emplace_back(LoadOutputControl(event_loop,
+						       rt_event_loop,
 						       replay_gain_config,
 						       mixer_listener,
 						       client, empty, defaults,
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index c46fcd71d..9e101bb0a 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -74,7 +74,7 @@ public:
 			MixerListener &_mixer_listener) noexcept;
 	~MultipleOutputs() noexcept;
 
-	void Configure(EventLoop &event_loop,
+	void Configure(EventLoop &event_loop, EventLoop &rt_event_loop,
 		       const ConfigData &config,
 		       const ReplayGainConfig &replay_gain_config);