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"
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
;
50 g_warning("Attempt to detect audio output device");
52 audio_output_plugins_for_each(plugin
, i
) {
53 if (plugin
->test_default_device
== NULL
)
56 g_warning("Attempting to detect a %s audio device",
58 if (ao_plugin_test_default_device(plugin
))
62 g_set_error(error
, audio_output_quark(), 0,
63 "Unable to detect an audio device");
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
);
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
88 return mixer_type_parse(config_get_string("mixer_type", "hardware"));
92 audio_output_load_mixer(const struct config_param
*param
,
93 const struct mixer_plugin
*plugin
,
94 struct filter
*filter_chain
)
98 switch (audio_output_mixer_type(param
)) {
100 case MIXER_TYPE_UNKNOWN
:
103 case MIXER_TYPE_HARDWARE
:
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
));
123 audio_output_init(struct audio_output
*ao
, const struct config_param
*param
,
126 const struct audio_output_plugin
*plugin
= NULL
;
131 p
= config_get_block_string(param
, AUDIO_OUTPUT_TYPE
, NULL
);
133 g_set_error(error
, audio_output_quark(), 0,
134 "Missing \"type\" configuration");
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
);
145 ao
->name
= config_get_block_string(param
, AUDIO_OUTPUT_NAME
,
147 if (ao
->name
== NULL
) {
148 g_set_error(error
, audio_output_quark(), 0,
149 "Missing \"name\" configuration");
153 p
= config_get_block_string(param
, AUDIO_OUTPUT_FORMAT
,
155 ao
->config_audio_format
= p
!= NULL
;
158 audio_format_parse(&ao
->out_audio_format
,
164 g_warning("No \"%s\" defined in config file\n",
167 plugin
= audio_output_detect(error
);
171 g_message("Successfully detected a %s audio device",
174 ao
->name
= "default detected output";
175 ao
->config_audio_format
= false;
179 ao
->enabled
= config_get_block_bool(param
, "enabled", true);
181 ao
->fail_timer
= NULL
;
183 /* set up the filter chain */
185 ao
->filter
= filter_chain_new();
186 assert(ao
->filter
!= 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
,
197 if (ao
->data
== NULL
)
200 ao
->mixer
= audio_output_load_mixer(param
, plugin
->mixer_plugin
,
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
);