doc: Remove superfluous comment already described in footnotes.
[mpd-mk.git] / src / output_init.c
blob08873ac2073fd5a2f412a90a8812e4de090910c2
1 /*
2 * Copyright (C) 2003-2009 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "output_control.h"
21 #include "output_api.h"
22 #include "output_internal.h"
23 #include "output_list.h"
24 #include "audio_parser.h"
25 #include "mixer_control.h"
26 #include "mixer_type.h"
27 #include "mixer_list.h"
28 #include "mixer/software_mixer_plugin.h"
29 #include "filter_plugin.h"
30 #include "filter_registry.h"
31 #include "filter/chain_filter_plugin.h"
33 #include <glib.h>
35 #include <assert.h>
37 #undef G_LOG_DOMAIN
38 #define G_LOG_DOMAIN "output"
40 #define AUDIO_OUTPUT_TYPE "type"
41 #define AUDIO_OUTPUT_NAME "name"
42 #define AUDIO_OUTPUT_FORMAT "format"
44 static const struct audio_output_plugin *
45 audio_output_detect(GError **error)
47 const struct audio_output_plugin *plugin;
48 unsigned i;
50 g_warning("Attempt to detect audio output device");
52 audio_output_plugins_for_each(plugin, i) {
53 if (plugin->test_default_device == NULL)
54 continue;
56 g_warning("Attempting to detect a %s audio device",
57 plugin->name);
58 if (ao_plugin_test_default_device(plugin))
59 return plugin;
62 g_set_error(error, audio_output_quark(), 0,
63 "Unable to detect an audio device");
64 return NULL;
67 /**
68 * Determines the mixer type which should be used for the specified
69 * configuration block.
71 * This handles the deprecated options mixer_type (global) and
72 * mixer_enabled, if the mixer_type setting is not configured.
74 static enum mixer_type
75 audio_output_mixer_type(const struct config_param *param)
77 /* read the local "mixer_type" setting */
78 const char *p = config_get_block_string(param, "mixer_type", NULL);
79 if (p != NULL)
80 return mixer_type_parse(p);
82 /* try the local "mixer_enabled" setting next (deprecated) */
83 if (!config_get_block_bool(param, "mixer_enabled", true))
84 return MIXER_TYPE_NONE;
86 /* fall back to the global "mixer_type" setting (also
87 deprecated) */
88 return mixer_type_parse(config_get_string("mixer_type", "hardware"));
91 static struct mixer *
92 audio_output_load_mixer(const struct config_param *param,
93 const struct mixer_plugin *plugin,
94 struct filter *filter_chain)
96 struct mixer *mixer;
98 switch (audio_output_mixer_type(param)) {
99 case MIXER_TYPE_NONE:
100 case MIXER_TYPE_UNKNOWN:
101 return NULL;
103 case MIXER_TYPE_HARDWARE:
104 if (plugin == NULL)
105 return NULL;
107 return mixer_new(plugin, param);
109 case MIXER_TYPE_SOFTWARE:
110 mixer = mixer_new(&software_mixer_plugin, NULL);
111 assert(mixer != NULL);
113 filter_chain_append(filter_chain,
114 software_mixer_get_filter(mixer));
115 return mixer;
118 assert(false);
119 return NULL;
122 bool
123 audio_output_init(struct audio_output *ao, const struct config_param *param,
124 GError **error)
126 const struct audio_output_plugin *plugin = NULL;
128 if (param) {
129 const char *p;
131 p = config_get_block_string(param, AUDIO_OUTPUT_TYPE, NULL);
132 if (p == NULL) {
133 g_set_error(error, audio_output_quark(), 0,
134 "Missing \"type\" configuration");
135 return false;
138 plugin = audio_output_plugin_get(p);
139 if (plugin == NULL) {
140 g_set_error(error, audio_output_quark(), 0,
141 "No such audio output plugin: %s", p);
142 return false;
145 ao->name = config_get_block_string(param, AUDIO_OUTPUT_NAME,
146 NULL);
147 if (ao->name == NULL) {
148 g_set_error(error, audio_output_quark(), 0,
149 "Missing \"name\" configuration");
150 return false;
153 p = config_get_block_string(param, AUDIO_OUTPUT_FORMAT,
154 NULL);
155 ao->config_audio_format = p != NULL;
156 if (p != NULL) {
157 bool success =
158 audio_format_parse(&ao->out_audio_format,
159 p, error);
160 if (!success)
161 return false;
163 } else {
164 g_warning("No \"%s\" defined in config file\n",
165 CONF_AUDIO_OUTPUT);
167 plugin = audio_output_detect(error);
168 if (plugin == NULL)
169 return false;
171 g_message("Successfully detected a %s audio device",
172 plugin->name);
174 ao->name = "default detected output";
175 ao->config_audio_format = false;
178 ao->plugin = plugin;
179 ao->enabled = config_get_block_bool(param, "enabled", true);
180 ao->open = false;
181 ao->fail_timer = NULL;
183 /* set up the filter chain */
185 ao->filter = filter_chain_new();
186 assert(ao->filter != NULL);
188 ao->thread = NULL;
189 notify_init(&ao->notify);
190 ao->command = AO_COMMAND_NONE;
191 ao->mutex = g_mutex_new();
193 ao->data = ao_plugin_init(plugin,
194 ao->config_audio_format
195 ? &ao->out_audio_format : NULL,
196 param, error);
197 if (ao->data == NULL)
198 return false;
200 ao->mixer = audio_output_load_mixer(param, plugin->mixer_plugin,
201 ao->filter);
203 /* the "convert" filter must be the last one in the chain */
205 ao->convert_filter = filter_new(&convert_filter_plugin, NULL, NULL);
206 assert(ao->convert_filter != NULL);
208 filter_chain_append(ao->filter, ao->convert_filter);
210 /* done */
212 return true;