diff --git a/src/output/Finish.cxx b/src/output/Finish.cxx
index b3f94fe31..be2ca463e 100644
--- a/src/output/Finish.cxx
+++ b/src/output/Finish.cxx
@@ -25,19 +25,18 @@
 
 #include <assert.h>
 
-void
-ao_base_finish(AudioOutput *ao)
+AudioOutput::~AudioOutput()
 {
-	assert(!ao->open);
-	assert(!ao->fail_timer.IsDefined());
-	assert(!ao->thread.IsDefined());
+	assert(!open);
+	assert(!fail_timer.IsDefined());
+	assert(!thread.IsDefined());
 
-	if (ao->mixer != nullptr)
-		mixer_free(ao->mixer);
+	if (mixer != nullptr)
+		mixer_free(mixer);
 
-	delete ao->replay_gain_filter;
-	delete ao->other_replay_gain_filter;
-	delete ao->filter;
+	delete replay_gain_filter;
+	delete other_replay_gain_filter;
+	delete filter;
 }
 
 void
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index 29c7137d9..52ff14b58 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -46,6 +46,20 @@
 #define AUDIO_OUTPUT_FORMAT	"format"
 #define AUDIO_FILTERS		"filters"
 
+AudioOutput::AudioOutput()
+	:enabled(true), really_enabled(false),
+	 open(false),
+	 pause(false),
+	 allow_play(true),
+	 in_playback_loop(false),
+	 woken_for_play(false),
+	 filter(nullptr),
+	 replay_gain_filter(nullptr),
+	 other_replay_gain_filter(nullptr),
+	 command(AO_COMMAND_NONE)
+{
+}
+
 static const AudioOutputPlugin *
 audio_output_detect(Error &error)
 {
@@ -166,12 +180,6 @@ ao_base_init(AudioOutput *ao,
 	ao->tags = param.GetBlockValue("tags", true);
 	ao->always_on = param.GetBlockValue("always_on", false);
 	ao->enabled = param.GetBlockValue("enabled", true);
-	ao->really_enabled = false;
-	ao->open = false;
-	ao->pause = false;
-	ao->allow_play = true;
-	ao->in_playback_loop = false;
-	ao->woken_for_play = false;
 
 	/* set up the filter chain */
 
@@ -202,12 +210,6 @@ ao_base_init(AudioOutput *ao,
 			    "Failed to initialize filter chain for '%s'",
 			    ao->name);
 
-	ao->command = AO_COMMAND_NONE;
-
-	ao->mixer = nullptr;
-	ao->replay_gain_filter = nullptr;
-	ao->other_replay_gain_filter = nullptr;
-
 	/* done */
 
 	return true;
diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx
index 31b6fd7c7..cb6904d68 100644
--- a/src/output/Internal.hxx
+++ b/src/output/Internal.hxx
@@ -263,6 +263,9 @@ struct AudioOutput {
 	 * Has the output finished playing #chunk?
 	 */
 	bool chunk_finished;
+
+	AudioOutput();
+	~AudioOutput();
 };
 
 /**
@@ -293,9 +296,6 @@ ao_base_init(AudioOutput *ao,
 	     const AudioOutputPlugin *plugin,
 	     const config_param &param, Error &error);
 
-void
-ao_base_finish(AudioOutput *ao);
-
 void
 audio_output_free(AudioOutput *ao);
 
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index d88fe9f5e..0c1bd37c3 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -126,10 +126,6 @@ struct AlsaOutput {
 		return ao_base_init(&base, &alsa_output_plugin,
 				    param, error);
 	}
-
-	void Deinit() {
-		ao_base_finish(&base);
-	}
 };
 
 static constexpr Domain alsa_output_domain("alsa_output");
@@ -189,7 +185,6 @@ alsa_finish(AudioOutput *ao)
 {
 	AlsaOutput *ad = (AlsaOutput *)ao;
 
-	ad->Deinit();
 	delete ad;
 
 	/* free libasound's config cache */
diff --git a/src/output/plugins/AoOutputPlugin.cxx b/src/output/plugins/AoOutputPlugin.cxx
index 8205e2fd6..62902fd0c 100644
--- a/src/output/plugins/AoOutputPlugin.cxx
+++ b/src/output/plugins/AoOutputPlugin.cxx
@@ -47,10 +47,6 @@ struct AoOutput {
 				    error);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	bool Configure(const config_param &param, Error &error);
 };
 
@@ -163,7 +159,6 @@ ao_output_init(const config_param &param, Error &error)
 	}
 
 	if (!ad->Configure(param, error)) {
-		ad->Deinitialize();
 		delete ad;
 		return nullptr;
 	}
@@ -177,7 +172,6 @@ ao_output_finish(AudioOutput *ao)
 	AoOutput *ad = (AoOutput *)ao;
 
 	ao_free_options(ad->options);
-	ad->Deinitialize();
 	delete ad;
 
 	ao_output_ref--;
diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx
index 2f839af22..b4e649130 100644
--- a/src/output/plugins/FifoOutputPlugin.cxx
+++ b/src/output/plugins/FifoOutputPlugin.cxx
@@ -55,10 +55,6 @@ struct FifoOutput {
 				    error);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	bool Create(Error &error);
 	bool Check(Error &error);
 	void Delete();
@@ -195,7 +191,6 @@ fifo_output_init(const config_param &param, Error &error)
 	}
 
 	if (!fifo_open(fd, error)) {
-		fd->Deinitialize();
 		delete fd;
 		return nullptr;
 	}
@@ -209,7 +204,6 @@ fifo_output_finish(AudioOutput *ao)
 	FifoOutput *fd = (FifoOutput *)ao;
 
 	fd->Close();
-	fd->Deinitialize();
 	delete fd;
 }
 
diff --git a/src/output/plugins/HttpdInternal.hxx b/src/output/plugins/HttpdInternal.hxx
index ad728949f..a4c0477f0 100644
--- a/src/output/plugins/HttpdInternal.hxx
+++ b/src/output/plugins/HttpdInternal.hxx
@@ -169,10 +169,6 @@ public:
 
 	bool Init(const config_param &param, Error &error);
 
-	void Finish() {
-		ao_base_finish(&base);
-	}
-
 	bool Configure(const config_param &param, Error &error);
 
 	AudioOutput *InitAndConfigure(const config_param &param,
@@ -180,10 +176,8 @@ public:
 		if (!Init(param, error))
 			return nullptr;
 
-		if (!Configure(param, error)) {
-			Finish();
+		if (!Configure(param, error))
 			return nullptr;
-		}
 
 		return &base;
 	}
diff --git a/src/output/plugins/HttpdOutputPlugin.cxx b/src/output/plugins/HttpdOutputPlugin.cxx
index 042b040a1..30bf607d9 100644
--- a/src/output/plugins/HttpdOutputPlugin.cxx
+++ b/src/output/plugins/HttpdOutputPlugin.cxx
@@ -156,7 +156,6 @@ httpd_output_finish(AudioOutput *ao)
 {
 	HttpdOutput *httpd = HttpdOutput::Cast(ao);
 
-	httpd->Finish();
 	delete httpd;
 }
 
diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx
index fcbe2b75b..c3a96741c 100644
--- a/src/output/plugins/JackOutputPlugin.cxx
+++ b/src/output/plugins/JackOutputPlugin.cxx
@@ -83,10 +83,6 @@ struct JackOutput {
 		return ao_base_init(&base, &jack_output_plugin, param,
 				    error_r);
 	}
-
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
 };
 
 static constexpr Domain jack_output_domain("jack_output");
@@ -399,7 +395,6 @@ mpd_jack_finish(AudioOutput *ao)
 	for (unsigned i = 0; i < jd->num_destination_ports; ++i)
 		g_free(jd->destination_ports[i]);
 
-	jd->Deinitialize();
 	delete jd;
 }
 
diff --git a/src/output/plugins/NullOutputPlugin.cxx b/src/output/plugins/NullOutputPlugin.cxx
index c5dff894c..7babce042 100644
--- a/src/output/plugins/NullOutputPlugin.cxx
+++ b/src/output/plugins/NullOutputPlugin.cxx
@@ -33,10 +33,6 @@ struct NullOutput {
 		return ao_base_init(&base, &null_output_plugin, param,
 				    error);
 	}
-
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
 };
 
 static AudioOutput *
@@ -59,7 +55,6 @@ null_finish(AudioOutput *ao)
 {
 	NullOutput *nd = (NullOutput *)ao;
 
-	nd->Deinitialize();
 	delete nd;
 }
 
diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx
index 13b4ec209..d40d0737e 100644
--- a/src/output/plugins/OpenALOutputPlugin.cxx
+++ b/src/output/plugins/OpenALOutputPlugin.cxx
@@ -52,10 +52,6 @@ struct OpenALOutput {
 		return ao_base_init(&base, &openal_output_plugin, param,
 				    error_r);
 	}
-
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
 };
 
 static constexpr Domain openal_output_domain("openal_output");
@@ -157,7 +153,6 @@ openal_finish(AudioOutput *ao)
 {
 	OpenALOutput *od = (OpenALOutput *)ao;
 
-	od->Deinitialize();
 	delete od;
 }
 
diff --git a/src/output/plugins/OssOutputPlugin.cxx b/src/output/plugins/OssOutputPlugin.cxx
index 001f97463..4924661bb 100644
--- a/src/output/plugins/OssOutputPlugin.cxx
+++ b/src/output/plugins/OssOutputPlugin.cxx
@@ -84,10 +84,6 @@ struct OssOutput {
 		return ao_base_init(&base, &oss_output_plugin, param,
 				    error_r);
 	}
-
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
 };
 
 static constexpr Domain oss_output_domain("oss_output");
@@ -222,7 +218,6 @@ oss_output_finish(AudioOutput *ao)
 {
 	OssOutput *od = (OssOutput *)ao;
 
-	ao_base_finish(&od->base);
 	delete od;
 }
 
diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx
index b872614ea..7bdc61051 100644
--- a/src/output/plugins/PipeOutputPlugin.cxx
+++ b/src/output/plugins/PipeOutputPlugin.cxx
@@ -39,10 +39,6 @@ struct PipeOutput {
 				    error);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	bool Configure(const config_param &param, Error &error);
 };
 
@@ -72,7 +68,6 @@ pipe_output_init(const config_param &param, Error &error)
 	}
 
 	if (!pd->Configure(param, error)) {
-		pd->Deinitialize();
 		delete pd;
 		return nullptr;
 	}
@@ -85,7 +80,6 @@ pipe_output_finish(AudioOutput *ao)
 {
 	PipeOutput *pd = (PipeOutput *)ao;
 
-	pd->Deinitialize();
 	delete pd;
 }
 
diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx
index b8957a563..e83083372 100644
--- a/src/output/plugins/PulseOutputPlugin.cxx
+++ b/src/output/plugins/PulseOutputPlugin.cxx
@@ -353,7 +353,6 @@ pulse_output_finish(AudioOutput *ao)
 {
 	PulseOutput *po = (PulseOutput *)ao;
 
-	ao_base_finish(&po->base);
 	delete po;
 }
 
diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx
index 632f2b718..ea208622a 100644
--- a/src/output/plugins/RecorderOutputPlugin.cxx
+++ b/src/output/plugins/RecorderOutputPlugin.cxx
@@ -62,10 +62,6 @@ struct RecorderOutput {
 				    error_r);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	bool Configure(const config_param &param, Error &error);
 
 	bool WriteToFile(const void *data, size_t length, Error &error);
@@ -118,7 +114,6 @@ recorder_output_init(const config_param &param, Error &error)
 	}
 
 	if (!recorder->Configure(param, error)) {
-		recorder->Deinitialize();
 		delete recorder;
 		return nullptr;
 	}
@@ -132,7 +127,6 @@ recorder_output_finish(AudioOutput *ao)
 	RecorderOutput *recorder = (RecorderOutput *)ao;
 
 	encoder_finish(recorder->encoder);
-	recorder->Deinitialize();
 	delete recorder;
 }
 
diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx
index 9b7a342e5..98cede62c 100644
--- a/src/output/plugins/RoarOutputPlugin.cxx
+++ b/src/output/plugins/RoarOutputPlugin.cxx
@@ -61,10 +61,6 @@ public:
 				    error);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	void Configure(const config_param &param);
 
 	bool Open(AudioFormat &audio_format, Error &error);
@@ -155,7 +151,6 @@ roar_finish(AudioOutput *ao)
 {
 	RoarOutput *self = (RoarOutput *)ao;
 
-	self->Deinitialize();
 	delete self;
 }
 
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index 8682226b9..1f60f72a1 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -72,10 +72,6 @@ struct ShoutOutput final {
 				    error);
 	}
 
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
-
 	bool Configure(const config_param &param, Error &error);
 };
 
@@ -285,7 +281,6 @@ my_shout_init_driver(const config_param &param, Error &error)
 	}
 
 	if (!sd->Configure(param, error)) {
-		sd->Deinitialize();
 		delete sd;
 		return nullptr;
 	}
@@ -369,7 +364,6 @@ my_shout_finish_driver(AudioOutput *ao)
 
 	encoder_finish(sd->encoder);
 
-	sd->Deinitialize();
 	delete sd;
 
 	shout_init_count--;
diff --git a/src/output/plugins/SolarisOutputPlugin.cxx b/src/output/plugins/SolarisOutputPlugin.cxx
index 70c3b7493..781aff2e3 100644
--- a/src/output/plugins/SolarisOutputPlugin.cxx
+++ b/src/output/plugins/SolarisOutputPlugin.cxx
@@ -61,10 +61,6 @@ struct SolarisOutput {
 		return ao_base_init(&base, &solaris_output_plugin, param,
 				    error_r);
 	}
-
-	void Deinitialize() {
-		ao_base_finish(&base);
-	}
 };
 
 static bool
@@ -95,7 +91,6 @@ solaris_output_finish(AudioOutput *ao)
 {
 	SolarisOutput *so = (SolarisOutput *)ao;
 
-	so->Deinitialize();
 	delete so;
 }
 
diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx
index 699993905..16ba7a4f7 100644
--- a/src/output/plugins/WinmmOutputPlugin.cxx
+++ b/src/output/plugins/WinmmOutputPlugin.cxx
@@ -119,7 +119,6 @@ winmm_output_init(const config_param &param, Error &error)
 
 	const char *device = param.GetBlockValue("device");
 	if (!get_device_id(device, &wo->device_id, error)) {
-		ao_base_finish(&wo->base);
 		delete wo;
 		return nullptr;
 	}
@@ -132,7 +131,6 @@ winmm_output_finish(AudioOutput *ao)
 {
 	WinmmOutput *wo = (WinmmOutput *)ao;
 
-	ao_base_finish(&wo->base);
 	delete wo;
 }