aboutsummaryrefslogtreecommitdiffstats
path: root/src/filter_config.c
blob: 6eecdbfb1533d1b9a903499ca2f1b765e826f447 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 * http://www.musicpd.org
 *
 * 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.
 *
 * 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.
 */

#include "filter_config.h"
#include "config.h"
#include "conf.h"
#include "filter/chain_filter_plugin.h"
#include "filter_plugin.h"
#include "filter_internal.h"
#include "filter_registry.h"

#include <string.h>


static GQuark
filter_quark(void)
{
	return g_quark_from_static_string("filter");
}

/**
 * Find the "filter" configuration block for the specified name.
 *
 * @param filter_template_name the name of the filter template
 * @param error_r space to return an error description
 * @return the configuration block, or NULL if none was configured
 */
static const struct config_param *
filter_plugin_config(const char *filter_template_name, GError **error_r)
{
	const struct config_param *param = NULL;

	while ((param = config_get_next_param(CONF_AUDIO_FILTER, param)) != NULL) {
		const char *name =
			config_get_block_string(param, "name", NULL);
		if (name == NULL) {
			g_set_error(error_r, filter_quark(), 1,
				    "filter configuration without 'name' name in line %d",
				    param->line);
			return NULL;
		}

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

	g_set_error(error_r, filter_quark(), 1,
		    "filter template not found: %s",
		    filter_template_name);

	return NULL;
}

/**
 * Builds a filter chain from a configuration string on the form
 * "name1, name2, name3, ..." by looking up each name among the
 * configured filter sections.
 * @param chain the chain to append filters on
 * @param spec the filter chain specification
 * @param error_r space to return an error description
 * @return the number of filters which were successfully added
 */
unsigned int
filter_chain_parse(struct filter *chain, const char *spec, GError **error_r)
{

	// Split on comma
	gchar** tokens = g_strsplit_set(spec, ",", 255);

	int added_filters = 0;

	// Add each name to the filter chain by instantiating an actual filter
	char **template_names = tokens;
	while (*template_names != NULL) {
		const char *plugin_name;
		const struct filter_plugin *fp;
		struct filter *f;
		const struct config_param *cfg;

		// Squeeze whitespace
		g_strstrip(*template_names);

		cfg = filter_plugin_config(*template_names, error_r);
		if (cfg == NULL) {
			// The error has already been set, just stop.
			break;
		}

		// Figure out what kind of a plugin that is
		plugin_name = config_get_block_string(cfg, "plugin", NULL);
		if (plugin_name == NULL) {
			g_set_error(error_r, filter_quark(), 1,
				    "filter configuration without 'plugin' at line %d",
				cfg->line);
			break;
		}

		// Instantiate one of those filter plugins with the template name as a hint
		fp = filter_plugin_by_name(plugin_name);
		if (fp == NULL) {
			g_set_error(error_r, filter_quark(), 2,
				    "filter plugin not found: %s",
				plugin_name);
			break;
		}

		f = filter_new(fp, cfg, NULL);
		if (f == NULL) {
			g_set_error(error_r, filter_quark(), 3,
				    "filter plugin initialization failed: %s",
				plugin_name);
			break;
		}

		filter_chain_append(chain, f);
		++added_filters;

		++template_names;
	}

	g_strfreev(tokens);

	return added_filters;
}