From e8938b1069739eca2bd2f27705c1c7783e834e59 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Wed, 5 Feb 2014 00:02:02 +0100
Subject: [PATCH] MixerPlugin: add EventLoop& init() parameter

---
 src/Main.cxx                              |  3 ++-
 src/mixer/MixerControl.cxx                |  5 +++--
 src/mixer/MixerControl.hxx                |  3 ++-
 src/mixer/MixerPlugin.hxx                 |  4 +++-
 src/mixer/plugins/AlsaMixerPlugin.cxx     | 13 ++++++++-----
 src/mixer/plugins/OssMixerPlugin.cxx      |  3 ++-
 src/mixer/plugins/PulseMixerPlugin.cxx    |  3 ++-
 src/mixer/plugins/RoarMixerPlugin.cxx     |  3 ++-
 src/mixer/plugins/SoftwareMixerPlugin.cxx |  2 +-
 src/mixer/plugins/WinmmMixerPlugin.cxx    |  3 ++-
 src/output/Init.cxx                       | 15 ++++++++-------
 src/output/Internal.hxx                   |  3 ++-
 src/output/MultipleOutputs.cxx            | 10 +++++-----
 src/output/MultipleOutputs.hxx            |  3 ++-
 test/read_mixer.cxx                       |  8 ++------
 test/run_output.cxx                       | 13 +++++--------
 16 files changed, 51 insertions(+), 43 deletions(-)

diff --git a/src/Main.cxx b/src/Main.cxx
index 1bee66ca8..a4f01dba8 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -476,7 +476,8 @@ int mpd_main(int argc, char *argv[])
 	initialize_decoder_and_player();
 	volume_init();
 	initAudioConfig();
-	instance->partition->outputs.Configure(instance->partition->pc);
+	instance->partition->outputs.Configure(*main_loop,
+					       instance->partition->pc);
 	client_manager_init();
 	replay_gain_global_init();
 
diff --git a/src/mixer/MixerControl.cxx b/src/mixer/MixerControl.cxx
index bdf6fcc2b..d64ff2c8e 100644
--- a/src/mixer/MixerControl.cxx
+++ b/src/mixer/MixerControl.cxx
@@ -25,7 +25,8 @@
 #include <assert.h>
 
 Mixer *
-mixer_new(const struct mixer_plugin *plugin, void *ao,
+mixer_new(EventLoop &event_loop,
+	  const mixer_plugin *plugin, void *ao,
 	  const config_param &param,
 	  Error &error)
 {
@@ -33,7 +34,7 @@ mixer_new(const struct mixer_plugin *plugin, void *ao,
 
 	assert(plugin != nullptr);
 
-	mixer = plugin->init(ao, param, error);
+	mixer = plugin->init(event_loop, ao, param, error);
 
 	assert(mixer == nullptr || mixer->IsPlugin(*plugin));
 
diff --git a/src/mixer/MixerControl.hxx b/src/mixer/MixerControl.hxx
index 3f8e11e86..8ffc683f4 100644
--- a/src/mixer/MixerControl.hxx
+++ b/src/mixer/MixerControl.hxx
@@ -27,11 +27,12 @@
 
 class Error;
 class Mixer;
+class EventLoop;
 struct mixer_plugin;
 struct config_param;
 
 Mixer *
-mixer_new(const mixer_plugin *plugin, void *ao,
+mixer_new(EventLoop &event_loop, const mixer_plugin *plugin, void *ao,
 	  const config_param &param,
 	  Error &error);
 
diff --git a/src/mixer/MixerPlugin.hxx b/src/mixer/MixerPlugin.hxx
index 2df0d809e..79ba378a0 100644
--- a/src/mixer/MixerPlugin.hxx
+++ b/src/mixer/MixerPlugin.hxx
@@ -29,6 +29,7 @@
 
 struct config_param;
 class Mixer;
+class EventLoop;
 class Error;
 
 struct mixer_plugin {
@@ -41,7 +42,8 @@ struct mixer_plugin {
 	 * nullptr to ignore errors
 	 * @return a mixer object, or nullptr on error
 	 */
-	Mixer *(*init)(void *ao, const config_param &param,
+	Mixer *(*init)(EventLoop &event_loop, void *ao,
+		       const config_param &param,
 		       Error &error);
 
 	/**
diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx
index a15820fc7..6e99cfa3e 100644
--- a/src/mixer/plugins/AlsaMixerPlugin.cxx
+++ b/src/mixer/plugins/AlsaMixerPlugin.cxx
@@ -21,7 +21,6 @@
 #include "mixer/MixerInternal.hxx"
 #include "output/OutputAPI.hxx"
 #include "GlobalEvents.hxx"
-#include "Main.hxx"
 #include "event/MultiSocketMonitor.hxx"
 #include "event/DeferredMonitor.hxx"
 #include "event/Loop.hxx"
@@ -62,6 +61,8 @@ private:
 };
 
 class AlsaMixer final : public Mixer {
+	EventLoop &event_loop;
+
 	const char *device;
 	const char *control;
 	unsigned int index;
@@ -75,7 +76,8 @@ class AlsaMixer final : public Mixer {
 	AlsaMixerMonitor *monitor;
 
 public:
-	AlsaMixer():Mixer(alsa_mixer_plugin) {}
+	AlsaMixer(EventLoop &_event_loop)
+		:Mixer(alsa_mixer_plugin), event_loop(_event_loop) {}
 
 	void Configure(const config_param &param);
 	bool Setup(Error &error);
@@ -162,10 +164,11 @@ AlsaMixer::Configure(const config_param &param)
 }
 
 static Mixer *
-alsa_mixer_init(gcc_unused void *ao, const config_param &param,
+alsa_mixer_init(EventLoop &event_loop, gcc_unused void *ao,
+		const config_param &param,
 		gcc_unused Error &error)
 {
-	AlsaMixer *am = new AlsaMixer();
+	AlsaMixer *am = new AlsaMixer(event_loop);
 	am->Configure(param);
 
 	return am;
@@ -237,7 +240,7 @@ AlsaMixer::Setup(Error &error)
 
 	snd_mixer_elem_set_callback(elem, alsa_mixer_elem_callback);
 
-	monitor = new AlsaMixerMonitor(*main_loop, handle);
+	monitor = new AlsaMixerMonitor(event_loop, handle);
 
 	return true;
 }
diff --git a/src/mixer/plugins/OssMixerPlugin.cxx b/src/mixer/plugins/OssMixerPlugin.cxx
index 095ace015..96dade06e 100644
--- a/src/mixer/plugins/OssMixerPlugin.cxx
+++ b/src/mixer/plugins/OssMixerPlugin.cxx
@@ -96,7 +96,8 @@ OssMixer::Configure(const config_param &param, Error &error)
 }
 
 static Mixer *
-oss_mixer_init(gcc_unused void *ao, const config_param &param,
+oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused void *ao,
+	       const config_param &param,
 	       Error &error)
 {
 	OssMixer *om = new OssMixer();
diff --git a/src/mixer/plugins/PulseMixerPlugin.cxx b/src/mixer/plugins/PulseMixerPlugin.cxx
index 4df88d06b..636656081 100644
--- a/src/mixer/plugins/PulseMixerPlugin.cxx
+++ b/src/mixer/plugins/PulseMixerPlugin.cxx
@@ -143,7 +143,8 @@ pulse_mixer_on_change(PulseMixer *pm,
 }
 
 static Mixer *
-pulse_mixer_init(void *ao, gcc_unused const config_param &param,
+pulse_mixer_init(gcc_unused EventLoop &event_loop, void *ao,
+		 gcc_unused const config_param &param,
 		 Error &error)
 {
 	PulseOutput *po = (PulseOutput *)ao;
diff --git a/src/mixer/plugins/RoarMixerPlugin.cxx b/src/mixer/plugins/RoarMixerPlugin.cxx
index 958688cd7..ce0462520 100644
--- a/src/mixer/plugins/RoarMixerPlugin.cxx
+++ b/src/mixer/plugins/RoarMixerPlugin.cxx
@@ -34,7 +34,8 @@ struct RoarMixer final : public Mixer {
 };
 
 static Mixer *
-roar_mixer_init(void *ao, gcc_unused const config_param &param,
+roar_mixer_init(gcc_unused EventLoop &event_loop, void *ao,
+		gcc_unused const config_param &param,
 		gcc_unused Error &error)
 {
 	return new RoarMixer((RoarOutput *)ao);
diff --git a/src/mixer/plugins/SoftwareMixerPlugin.cxx b/src/mixer/plugins/SoftwareMixerPlugin.cxx
index 67ddee1a4..e5d4ba5ca 100644
--- a/src/mixer/plugins/SoftwareMixerPlugin.cxx
+++ b/src/mixer/plugins/SoftwareMixerPlugin.cxx
@@ -67,7 +67,7 @@ struct SoftwareMixer final : public Mixer {
 };
 
 static Mixer *
-software_mixer_init(gcc_unused void *ao,
+software_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused void *ao,
 		    gcc_unused const config_param &param,
 		    gcc_unused Error &error)
 {
diff --git a/src/mixer/plugins/WinmmMixerPlugin.cxx b/src/mixer/plugins/WinmmMixerPlugin.cxx
index 093a026a9..c040b19fd 100644
--- a/src/mixer/plugins/WinmmMixerPlugin.cxx
+++ b/src/mixer/plugins/WinmmMixerPlugin.cxx
@@ -55,7 +55,8 @@ winmm_volume_encode(int volume)
 }
 
 static Mixer *
-winmm_mixer_init(void *ao, gcc_unused const config_param &param,
+winmm_mixer_init(gcc_unused EventLoop &event_loop, void *ao,
+		 gcc_unused const config_param &param,
 		 gcc_unused Error &error)
 {
 	assert(ao != nullptr);
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index 372bb4276..a983ff7c8 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -112,7 +112,7 @@ audio_output_mixer_type(const config_param &param)
 }
 
 static Mixer *
-audio_output_load_mixer(AudioOutput *ao,
+audio_output_load_mixer(EventLoop &event_loop, AudioOutput *ao,
 			const config_param &param,
 			const struct mixer_plugin *plugin,
 			Filter &filter_chain,
@@ -129,10 +129,10 @@ audio_output_load_mixer(AudioOutput *ao,
 		if (plugin == nullptr)
 			return nullptr;
 
-		return mixer_new(plugin, ao, param, error);
+		return mixer_new(event_loop, plugin, ao, param, error);
 
 	case MIXER_TYPE_SOFTWARE:
-		mixer = mixer_new(&software_mixer_plugin, nullptr,
+		mixer = mixer_new(event_loop, &software_mixer_plugin, nullptr,
 				  config_param(),
 				  IgnoreError());
 		assert(mixer != nullptr);
@@ -211,7 +211,8 @@ AudioOutput::Configure(const config_param &param, Error &error)
 }
 
 static bool
-audio_output_setup(AudioOutput *ao, const config_param &param,
+audio_output_setup(EventLoop &event_loop, AudioOutput *ao,
+		   const config_param &param,
 		   Error &error)
 {
 
@@ -241,7 +242,7 @@ audio_output_setup(AudioOutput *ao, const config_param &param,
 	/* set up the mixer */
 
 	Error mixer_error;
-	ao->mixer = audio_output_load_mixer(ao, param,
+	ao->mixer = audio_output_load_mixer(event_loop, ao, param,
 					    ao->plugin.mixer_plugin,
 					    *ao->filter, mixer_error);
 	if (ao->mixer == nullptr && mixer_error.IsDefined())
@@ -277,7 +278,7 @@ audio_output_setup(AudioOutput *ao, const config_param &param,
 }
 
 AudioOutput *
-audio_output_new(const config_param &param,
+audio_output_new(EventLoop &event_loop, const config_param &param,
 		 PlayerControl &pc,
 		 Error &error)
 {
@@ -316,7 +317,7 @@ audio_output_new(const config_param &param,
 	if (ao == nullptr)
 		return nullptr;
 
-	if (!audio_output_setup(ao, param, error)) {
+	if (!audio_output_setup(event_loop, ao, param, error)) {
 		ao_plugin_finish(ao);
 		return nullptr;
 	}
diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx
index a443d0642..9b08a9228 100644
--- a/src/output/Internal.hxx
+++ b/src/output/Internal.hxx
@@ -32,6 +32,7 @@
 class Error;
 class Filter;
 class MusicPipe;
+class EventLoop;
 struct music_chunk;
 struct config_param;
 struct PlayerControl;
@@ -422,7 +423,7 @@ private:
 extern struct notify audio_output_client_notify;
 
 AudioOutput *
-audio_output_new(const config_param &param,
+audio_output_new(EventLoop &event_loop, const config_param &param,
 		 PlayerControl &pc,
 		 Error &error);
 
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index 66390f24d..a65fb73c0 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -50,10 +50,10 @@ MultipleOutputs::~MultipleOutputs()
 }
 
 static AudioOutput *
-LoadOutput(PlayerControl &pc, const config_param &param)
+LoadOutput(EventLoop &event_loop, PlayerControl &pc, const config_param &param)
 {
 	Error error;
-	AudioOutput *output = audio_output_new(param, pc, error);
+	AudioOutput *output = audio_output_new(event_loop, param, pc, error);
 	if (output == nullptr) {
 		if (param.line > 0)
 			FormatFatalError("line %i: %s",
@@ -67,12 +67,12 @@ LoadOutput(PlayerControl &pc, const config_param &param)
 }
 
 void
-MultipleOutputs::Configure(PlayerControl &pc)
+MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
 {
 	const config_param *param = nullptr;
 	while ((param = config_get_next_param(CONF_AUDIO_OUTPUT,
 					      param)) != nullptr) {
-		auto output = LoadOutput(pc, *param);
+		auto output = LoadOutput(event_loop, pc, *param);
 		if (FindByName(output->name) != nullptr)
 			FormatFatalError("output devices with identical "
 					 "names: %s", output->name);
@@ -83,7 +83,7 @@ MultipleOutputs::Configure(PlayerControl &pc)
 	if (outputs.empty()) {
 		/* auto-detect device */
 		const config_param empty;
-		auto output = LoadOutput(pc, empty);
+		auto output = LoadOutput(event_loop, pc, empty);
 		outputs.push_back(output);
 	}
 }
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index 7790f83a4..4fe1aa4f1 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -37,6 +37,7 @@
 struct AudioFormat;
 class MusicBuffer;
 class MusicPipe;
+class EventLoop;
 struct music_chunk;
 struct PlayerControl;
 struct AudioOutput;
@@ -72,7 +73,7 @@ public:
 	MultipleOutputs();
 	~MultipleOutputs();
 
-	void Configure(PlayerControl &pc);
+	void Configure(EventLoop &event_loop, PlayerControl &pc);
 
 	/**
 	 * Returns the total number of audio output devices, including
diff --git a/test/read_mixer.cxx b/test/read_mixer.cxx
index 095d9945d..4849b7a8c 100644
--- a/test/read_mixer.cxx
+++ b/test/read_mixer.cxx
@@ -35,8 +35,6 @@
 #include <string.h>
 #include <unistd.h>
 
-EventLoop *main_loop;
-
 #ifdef HAVE_PULSE
 #include "output/plugins/PulseOutputPlugin.hxx"
 
@@ -115,10 +113,10 @@ int main(int argc, gcc_unused char **argv)
 	g_thread_init(NULL);
 #endif
 
-	main_loop = new EventLoop;
+	EventLoop event_loop;
 
 	Error error;
-	Mixer *mixer = mixer_new(&alsa_mixer_plugin, nullptr,
+	Mixer *mixer = mixer_new(event_loop, &alsa_mixer_plugin, nullptr,
 				 config_param(), error);
 	if (mixer == NULL) {
 		LogError(error, "mixer_new() failed");
@@ -135,8 +133,6 @@ int main(int argc, gcc_unused char **argv)
 	mixer_close(mixer);
 	mixer_free(mixer);
 
-	delete main_loop;
-
 	assert(volume >= -1 && volume <= 100);
 
 	if (volume < 0) {
diff --git a/test/run_output.cxx b/test/run_output.cxx
index 23fd1ad3a..6a6400477 100644
--- a/test/run_output.cxx
+++ b/test/run_output.cxx
@@ -45,8 +45,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-EventLoop *main_loop;
-
 void
 GlobalEvents::Emit(gcc_unused Event event)
 {
@@ -80,7 +78,7 @@ PlayerControl::PlayerControl(gcc_unused MultipleOutputs &_outputs,
 PlayerControl::~PlayerControl() {}
 
 static AudioOutput *
-load_audio_output(const char *name)
+load_audio_output(EventLoop &event_loop, const char *name)
 {
 	const struct config_param *param;
 
@@ -95,7 +93,8 @@ load_audio_output(const char *name)
 
 	Error error;
 	AudioOutput *ao =
-		audio_output_new(*param, dummy_player_control, error);
+		audio_output_new(event_loop, *param, dummy_player_control,
+				 error);
 	if (ao == nullptr)
 		LogError(error);
 
@@ -189,14 +188,14 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	main_loop = new EventLoop();
+	EventLoop event_loop;
 
 	io_thread_init();
 	io_thread_start();
 
 	/* initialize the audio output */
 
-	AudioOutput *ao = load_audio_output(argv[2]);
+	AudioOutput *ao = load_audio_output(event_loop, argv[2]);
 	if (ao == NULL)
 		return 1;
 
@@ -219,8 +218,6 @@ int main(int argc, char **argv)
 
 	io_thread_deinit();
 
-	delete main_loop;
-
 	config_global_finish();
 
 	return success ? EXIT_SUCCESS : EXIT_FAILURE;