From 188f9e663cbc109e2dc367eb7995dd8dd3fdf90f Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Sun, 25 Jan 2009 17:38:02 +0100
Subject: [PATCH] mixer: configure legacy mixer before the audio outputs

Reimplemented the legacy mixer configuration: copy the deprecated
configuration values into the audio_output section.  Don't configure
the mixers twice (once for the audio_output, and a second time for the
legacy values).

This requires volume_init() to be called before initAudioDriver().
---
 src/main.c   |  2 +-
 src/volume.c | 92 +++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 71 insertions(+), 23 deletions(-)

diff --git a/src/main.c b/src/main.c
index f82ea596a..e872d3d91 100644
--- a/src/main.c
+++ b/src/main.c
@@ -246,9 +246,9 @@ int main(int argc, char *argv[])
 
 	command_init();
 	initialize_decoder_and_player();
+	volume_init();
 	initAudioConfig();
 	initAudioDriver();
-	volume_init();
 	client_manager_init();
 	replay_gain_global_init();
 	initNormalization();
diff --git a/src/volume.c b/src/volume.c
index ce6e38dc1..6f7c922c0 100644
--- a/src/volume.c
+++ b/src/volume.c
@@ -47,32 +47,80 @@ void volume_finish(void)
 {
 }
 
-static void
-mixer_reconfigure(char *driver)
+/**
+ * Finds the first audio_output configuration section with the
+ * specified type.
+ */
+static struct config_param *
+find_output_config(const char *type)
 {
-	struct config_param *newparam, *param;
+	struct config_param *param = NULL;
 
-	//create parameter list
-	newparam = newConfigParam(NULL, -1);
+	while ((param = config_get_next_param(CONF_AUDIO_OUTPUT,
+					      param)) != NULL) {
+		const char *param_type =
+			config_get_block_string(param, "type", NULL);
+		if (param_type != NULL && strcmp(param_type, type) == 0)
+			return param;
+	}
 
-	param = config_get_param(CONF_MIXER_DEVICE);
-	if (param) {
-		g_warning("deprecated option mixer_device found, translating to %s config section\n", driver);
-		addBlockParam(newparam, "mixer_device", param->value, -1);
+	return NULL;
+}
+
+/**
+ * Copy a (top-level) legacy mixer configuration parameter to the
+ * audio_output section.
+ */
+static void
+mixer_copy_legacy_param(const char *type, const char *name)
+{
+	const struct config_param *param;
+	struct config_param *output;
+	const struct block_param *bp;
+
+	/* see if the deprecated configuration exists */
+
+	param = config_get_param(name);
+	if (param == NULL)
+		return;
+
+	g_warning("deprecated option '%s' found, moving to '%s' audio output",
+		  name, type);
+
+	/* determine the configuration section */
+
+	output = find_output_config(type);
+	if (output == NULL) {
+		/* if there is no output configuration at all, create
+		   a new and empty configuration section for the
+		   legacy mixer */
+
+		if (config_get_next_param(CONF_AUDIO_OUTPUT, NULL) != NULL)
+			/* there is an audio_output configuration, but
+			   it does not match the mixer_type setting */
+			g_error("no '%s' audio output found", type);
+
+		output = newConfigParam(NULL, param->line);
+		addBlockParam(output, "type", type, param->line);
+		addBlockParam(output, "name", type, param->line);
+		config_add_param(CONF_AUDIO_OUTPUT, output);
 	}
-	param = config_get_param(CONF_MIXER_CONTROL);
-	if (param) {
-		g_warning("deprecated option mixer_control found, translating to %s config section\n", driver);
-		addBlockParam(newparam, "mixer_control", param->value, -1);
-	}
-	if (newparam->num_block_params > 0) {
-		//call configure method of corrensponding mixer
-		if (!mixer_configure_legacy(driver, newparam)) {
-			g_error("Using mixer_type '%s' with not enabled %s output", driver, driver);
-		}
-	}
-	//free parameter list
-	config_param_free(newparam, NULL);
+
+	bp = getBlockParam(output, name);
+	if (bp != NULL)
+		g_error("the '%s' audio output already has a '%s' setting",
+			type, name);
+
+	/* duplicate the parameter in the configuration section */
+
+	addBlockParam(output, name, param->value, param->line);
+}
+
+static void
+mixer_reconfigure(const char *type)
+{
+	mixer_copy_legacy_param(type, CONF_MIXER_DEVICE);
+	mixer_copy_legacy_param(type, CONF_MIXER_CONTROL);
 }
 
 void volume_init(void)