2 * Copyright (C) 2003-2010 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.
21 #include "output_control.h"
22 #include "output_api.h"
23 #include "output_internal.h"
24 #include "output_list.h"
25 #include "audio_parser.h"
26 #include "mixer_control.h"
27 #include "mixer_type.h"
28 #include "mixer_list.h"
29 #include "mixer/software_mixer_plugin.h"
30 #include "filter_plugin.h"
31 #include "filter_registry.h"
32 #include "filter_config.h"
33 #include "filter/chain_filter_plugin.h"
34 #include "filter/autoconvert_filter_plugin.h"
35 #include "filter/replay_gain_filter_plugin.h"
42 #define G_LOG_DOMAIN "output"
44 #define AUDIO_OUTPUT_TYPE "type"
45 #define AUDIO_OUTPUT_NAME "name"
46 #define AUDIO_OUTPUT_FORMAT "format"
47 #define AUDIO_FILTERS "filters"
49 static const struct audio_output_plugin
*
50 audio_output_detect(GError
**error
)
52 const struct audio_output_plugin
*plugin
;
55 g_warning("Attempt to detect audio output device");
57 audio_output_plugins_for_each(plugin
, i
) {
58 if (plugin
->test_default_device
== NULL
)
61 g_warning("Attempting to detect a %s audio device",
63 if (ao_plugin_test_default_device(plugin
))
67 g_set_error(error
, audio_output_quark(), 0,
68 "Unable to detect an audio device");
73 * Determines the mixer type which should be used for the specified
74 * configuration block.
76 * This handles the deprecated options mixer_type (global) and
77 * mixer_enabled, if the mixer_type setting is not configured.
79 static enum mixer_type
80 audio_output_mixer_type(const struct config_param
*param
)
82 /* read the local "mixer_type" setting */
83 const char *p
= config_get_block_string(param
, "mixer_type", NULL
);
85 return mixer_type_parse(p
);
87 /* try the local "mixer_enabled" setting next (deprecated) */
88 if (!config_get_block_bool(param
, "mixer_enabled", true))
89 return MIXER_TYPE_NONE
;
91 /* fall back to the global "mixer_type" setting (also
93 return mixer_type_parse(config_get_string("mixer_type", "hardware"));
97 audio_output_load_mixer(void *ao
, const struct config_param
*param
,
98 const struct mixer_plugin
*plugin
,
99 struct filter
*filter_chain
,
104 switch (audio_output_mixer_type(param
)) {
105 case MIXER_TYPE_NONE
:
106 case MIXER_TYPE_UNKNOWN
:
109 case MIXER_TYPE_HARDWARE
:
113 return mixer_new(plugin
, ao
, param
, error_r
);
115 case MIXER_TYPE_SOFTWARE
:
116 mixer
= mixer_new(&software_mixer_plugin
, NULL
, NULL
, NULL
);
117 assert(mixer
!= NULL
);
119 filter_chain_append(filter_chain
,
120 software_mixer_get_filter(mixer
));
129 audio_output_init(struct audio_output
*ao
, const struct config_param
*param
,
132 const struct audio_output_plugin
*plugin
= NULL
;
133 GError
*error
= NULL
;
138 p
= config_get_block_string(param
, AUDIO_OUTPUT_TYPE
, NULL
);
140 g_set_error(error_r
, audio_output_quark(), 0,
141 "Missing \"type\" configuration");
145 plugin
= audio_output_plugin_get(p
);
146 if (plugin
== NULL
) {
147 g_set_error(error_r
, audio_output_quark(), 0,
148 "No such audio output plugin: %s", p
);
152 ao
->name
= config_get_block_string(param
, AUDIO_OUTPUT_NAME
,
154 if (ao
->name
== NULL
) {
155 g_set_error(error_r
, audio_output_quark(), 0,
156 "Missing \"name\" configuration");
160 p
= config_get_block_string(param
, AUDIO_OUTPUT_FORMAT
,
164 audio_format_parse(&ao
->config_audio_format
,
169 audio_format_clear(&ao
->config_audio_format
);
171 g_warning("No \"%s\" defined in config file\n",
174 plugin
= audio_output_detect(error_r
);
178 g_message("Successfully detected a %s audio device",
181 ao
->name
= "default detected output";
183 audio_format_clear(&ao
->config_audio_format
);
187 ao
->always_on
= config_get_block_bool(param
, "always_on", false);
188 ao
->enabled
= config_get_block_bool(param
, "enabled", true);
189 ao
->really_enabled
= false;
192 ao
->fail_timer
= NULL
;
194 /* set up the filter chain */
196 ao
->filter
= filter_chain_new();
197 assert(ao
->filter
!= NULL
);
199 /* create the replay_gain filter */
201 const char *replay_gain_handler
=
202 config_get_block_string(param
, "replay_gain_handler",
205 if (strcmp(replay_gain_handler
, "none") != 0) {
206 ao
->replay_gain_filter
= filter_new(&replay_gain_filter_plugin
,
208 assert(ao
->replay_gain_filter
!= NULL
);
210 filter_chain_append(ao
->filter
, ao
->replay_gain_filter
);
211 ao
->replay_gain_serial
= 0;
213 ao
->replay_gain_filter
= NULL
;
215 /* create the normalization filter (if configured) */
217 if (config_get_bool(CONF_VOLUME_NORMALIZATION
, false)) {
218 struct filter
*normalize_filter
=
219 filter_new(&normalize_filter_plugin
, NULL
, NULL
);
220 assert(normalize_filter
!= NULL
);
222 filter_chain_append(ao
->filter
,
223 autoconvert_filter_new(normalize_filter
));
226 filter_chain_parse(ao
->filter
,
227 config_get_block_string(param
, AUDIO_FILTERS
, ""),
231 // It's not really fatal - Part of the filter chain has been set up already
232 // and even an empty one will work (if only with unexpected behaviour)
234 g_warning("Failed to initialize filter chain for '%s': %s",
235 ao
->name
, error
->message
);
240 ao
->command
= AO_COMMAND_NONE
;
241 ao
->mutex
= g_mutex_new();
242 ao
->cond
= g_cond_new();
244 ao
->data
= ao_plugin_init(plugin
,
245 &ao
->config_audio_format
,
247 if (ao
->data
== NULL
)
250 ao
->mixer
= audio_output_load_mixer(ao
->data
, param
,
251 plugin
->mixer_plugin
,
253 if (ao
->mixer
== NULL
&& error
!= NULL
) {
254 g_warning("Failed to initialize hardware mixer for '%s': %s",
255 ao
->name
, error
->message
);
259 /* use the hardware mixer for replay gain? */
261 if (strcmp(replay_gain_handler
, "mixer") == 0) {
262 if (ao
->mixer
!= NULL
)
263 replay_gain_filter_set_mixer(ao
->replay_gain_filter
,
266 g_warning("No such mixer for output '%s'", ao
->name
);
267 } else if (strcmp(replay_gain_handler
, "software") != 0 &&
268 ao
->replay_gain_filter
!= NULL
) {
269 g_set_error(error_r
, audio_output_quark(), 0,
270 "Invalid \"replay_gain_handler\" value");
274 /* the "convert" filter must be the last one in the chain */
276 ao
->convert_filter
= filter_new(&convert_filter_plugin
, NULL
, NULL
);
277 assert(ao
->convert_filter
!= NULL
);
279 filter_chain_append(ao
->filter
, ao
->convert_filter
);