decoder_list.c 6 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

20
#include "config.h"
21
#include "decoder_list.h"
22
#include "decoder_plugin.h"
23
#include "utils.h"
24
#include "conf.h"
25
#include "mpd_error.h"
26
#include "decoder/pcm_decoder_plugin.h"
27 28

#include <glib.h>
29

30 31
#include <string.h>

32
extern const struct decoder_plugin mad_decoder_plugin;
33
extern const struct decoder_plugin mpg123_decoder_plugin;
Max Kellermann's avatar
Max Kellermann committed
34
extern const struct decoder_plugin vorbis_decoder_plugin;
Max Kellermann's avatar
Max Kellermann committed
35 36
extern const struct decoder_plugin flac_decoder_plugin;
extern const struct decoder_plugin oggflac_decoder_plugin;
37
extern const struct decoder_plugin sndfile_decoder_plugin;
38
extern const struct decoder_plugin audiofile_decoder_plugin;
39
extern const struct decoder_plugin mp4ff_decoder_plugin;
40
extern const struct decoder_plugin faad_decoder_plugin;
41
extern const struct decoder_plugin mpcdec_decoder_plugin;
42 43
extern const struct decoder_plugin wavpack_decoder_plugin;
extern const struct decoder_plugin modplug_decoder_plugin;
44
extern const struct decoder_plugin mikmod_decoder_plugin;
45
extern const struct decoder_plugin sidplay_decoder_plugin;
46
extern const struct decoder_plugin wildmidi_decoder_plugin;
47
extern const struct decoder_plugin fluidsynth_decoder_plugin;
48
extern const struct decoder_plugin ffmpeg_decoder_plugin;
49
extern const struct decoder_plugin gme_decoder_plugin;
50

51
const struct decoder_plugin *const decoder_plugins[] = {
52
#ifdef HAVE_MAD
53
	&mad_decoder_plugin,
54
#endif
55 56 57
#ifdef HAVE_MPG123
	&mpg123_decoder_plugin,
#endif
58
#ifdef ENABLE_VORBIS_DECODER
Max Kellermann's avatar
Max Kellermann committed
59
	&vorbis_decoder_plugin,
60
#endif
61
#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
Max Kellermann's avatar
Max Kellermann committed
62
	&oggflac_decoder_plugin,
63 64
#endif
#ifdef HAVE_FLAC
Max Kellermann's avatar
Max Kellermann committed
65
	&flac_decoder_plugin,
66
#endif
67 68 69
#ifdef ENABLE_SNDFILE
	&sndfile_decoder_plugin,
#endif
70
#ifdef HAVE_AUDIOFILE
71
	&audiofile_decoder_plugin,
72 73
#endif
#ifdef HAVE_FAAD
74
	&faad_decoder_plugin,
75
#endif
76
#ifdef HAVE_MP4
77
	&mp4ff_decoder_plugin,
78
#endif
79
#ifdef HAVE_MPCDEC
80
	&mpcdec_decoder_plugin,
81 82
#endif
#ifdef HAVE_WAVPACK
83
	&wavpack_decoder_plugin,
84
#endif
85
#ifdef HAVE_MODPLUG
86
	&modplug_decoder_plugin,
87
#endif
88
#ifdef ENABLE_MIKMOD_DECODER
89
	&mikmod_decoder_plugin,
90
#endif
91 92 93
#ifdef ENABLE_SIDPLAY
	&sidplay_decoder_plugin,
#endif
94 95 96
#ifdef ENABLE_WILDMIDI
	&wildmidi_decoder_plugin,
#endif
97 98 99
#ifdef ENABLE_FLUIDSYNTH
	&fluidsynth_decoder_plugin,
#endif
100
#ifdef HAVE_FFMPEG
101
	&ffmpeg_decoder_plugin,
102 103 104
#endif
#ifdef HAVE_GME
	&gme_decoder_plugin,
105
#endif
106
	&pcm_decoder_plugin,
107
	NULL
108
};
109

110
enum {
111
	num_decoder_plugins = G_N_ELEMENTS(decoder_plugins) - 1,
112
};
113

114
/** which plugins have been initialized successfully? */
115
bool decoder_plugins_enabled[num_decoder_plugins];
116

117 118
static unsigned
decoder_plugin_index(const struct decoder_plugin *plugin)
Avuton Olrich's avatar
Avuton Olrich committed
119
{
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	unsigned i = 0;

	while (decoder_plugins[i] != plugin)
		++i;

	return i;
}

static unsigned
decoder_plugin_next_index(const struct decoder_plugin *plugin)
{
	return plugin == 0
		? 0 /* start with first plugin */
		: decoder_plugin_index(plugin) + 1;
}
Avuton Olrich's avatar
Avuton Olrich committed
135

136 137 138 139
const struct decoder_plugin *
decoder_plugin_from_suffix(const char *suffix,
			   const struct decoder_plugin *plugin)
{
Avuton Olrich's avatar
Avuton Olrich committed
140 141
	if (suffix == NULL)
		return NULL;
142

143 144 145
	for (unsigned i = decoder_plugin_next_index(plugin);
	     decoder_plugins[i] != NULL; ++i) {
		plugin = decoder_plugins[i];
146
		if (decoder_plugins_enabled[i] &&
147
		    decoder_plugin_supports_suffix(plugin, suffix))
148 149 150 151 152 153
			return plugin;
	}

	return NULL;
}

154 155
const struct decoder_plugin *
decoder_plugin_from_mime_type(const char *mimeType, unsigned int next)
Avuton Olrich's avatar
Avuton Olrich committed
156
{
157
	static unsigned i = num_decoder_plugins;
Avuton Olrich's avatar
Avuton Olrich committed
158 159 160

	if (mimeType == NULL)
		return NULL;
161

162 163
	if (!next)
		i = 0;
164
	for (; decoder_plugins[i] != NULL; ++i) {
165
		const struct decoder_plugin *plugin = decoder_plugins[i];
166
		if (decoder_plugins_enabled[i] &&
167
		    decoder_plugin_supports_mime_type(plugin, mimeType)) {
168
			++i;
169 170 171 172 173 174 175
			return plugin;
		}
	}

	return NULL;
}

176 177
const struct decoder_plugin *
decoder_plugin_from_name(const char *name)
Avuton Olrich's avatar
Avuton Olrich committed
178
{
179
	for (unsigned i = 0; decoder_plugins[i] != NULL; ++i) {
180 181 182 183 184
		const struct decoder_plugin *plugin = decoder_plugins[i];
		if (decoder_plugins_enabled[i] &&
		    strcmp(plugin->name, name) == 0)
			return plugin;
	}
185

186
	return NULL;
187 188
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
/**
 * Find the "decoder" configuration block for the specified plugin.
 *
 * @param plugin_name the name of the decoder plugin
 * @return the configuration block, or NULL if none was configured
 */
static const struct config_param *
decoder_plugin_config(const char *plugin_name)
{
	const struct config_param *param = NULL;

	while ((param = config_get_next_param(CONF_DECODER, param)) != NULL) {
		const char *name =
			config_get_block_string(param, "plugin", NULL);
		if (name == NULL)
204 205
			MPD_ERROR("decoder configuration without 'plugin' name in line %d",
				  param->line);
206 207 208 209 210 211 212 213

		if (strcmp(name, plugin_name) == 0)
			return param;
	}

	return NULL;
}

214
void decoder_plugin_init_all(void)
Avuton Olrich's avatar
Avuton Olrich committed
215
{
216
	for (unsigned i = 0; decoder_plugins[i] != NULL; ++i) {
217
		const struct decoder_plugin *plugin = decoder_plugins[i];
218 219
		const struct config_param *param =
			decoder_plugin_config(plugin->name);
220

221 222 223 224
		if (!config_get_block_bool(param, "enabled", true))
			/* the plugin is disabled in mpd.conf */
			continue;

225
		if (decoder_plugin_init(plugin, param))
226 227
			decoder_plugins_enabled[i] = true;
	}
228 229
}

230
void decoder_plugin_deinit_all(void)
Avuton Olrich's avatar
Avuton Olrich committed
231
{
232
	for (unsigned i = 0; decoder_plugins[i] != NULL; ++i) {
233
		const struct decoder_plugin *plugin = decoder_plugins[i];
234 235 236

		if (decoder_plugins_enabled[i])
			decoder_plugin_finish(plugin);
237
	}
238
}