diff options
Diffstat (limited to '')
-rw-r--r-- | src/conf.h | 3 | ||||
-rw-r--r-- | src/filter/chain_filter_plugin.c | 99 | ||||
-rw-r--r-- | src/filter/chain_filter_plugin.h | 12 | ||||
-rw-r--r-- | src/output_init.c | 4 |
4 files changed, 118 insertions, 0 deletions
diff --git a/src/conf.h b/src/conf.h index 7dd12afda..049c980ec 100644 --- a/src/conf.h +++ b/src/conf.h @@ -42,6 +42,7 @@ #define CONF_PASSWORD "password" #define CONF_DEFAULT_PERMS "default_permissions" #define CONF_AUDIO_OUTPUT "audio_output" +#define CONF_AUDIO_FILTER "filter" #define CONF_AUDIO_OUTPUT_FORMAT "audio_output_format" #define CONF_MIXER_TYPE "mixer_type" #define CONF_REPLAYGAIN "replaygain" @@ -73,6 +74,8 @@ #define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) #define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS false +#define MAX_FILTER_CHAIN_LENGTH 255 + struct block_param { char *name; char *value; diff --git a/src/filter/chain_filter_plugin.c b/src/filter/chain_filter_plugin.c index 5cd8aa014..5f9544b50 100644 --- a/src/filter/chain_filter_plugin.c +++ b/src/filter/chain_filter_plugin.c @@ -18,12 +18,14 @@ */ #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 <assert.h> +#include <string.h> struct filter_chain { /** the base class */ @@ -176,3 +178,100 @@ filter_chain_append(struct filter *_chain, struct filter *filter) chain->children = g_slist_append(chain->children, filter); } + +/** + * Find the "filter" configuration block for the specified name. + * + * @param filter_template_name the name of the filter template + * @return the configuration block, or NULL if none was configured + */ +static const struct config_param * +filter_plugin_config(const char *filter_template_name) +{ + 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_error("filter configuration without 'name' name in line %d", + param->line); + + if (strcmp(name, filter_template_name) == 0) + return param; + } + + 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 + * @return the number of filters which were successfully added + */ +unsigned int +filter_chain_parse(struct filter *chain, const char *spec) { + + // 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); + if (cfg == NULL) { + g_error("Unable to locate filter template %s", + *template_names); + ++template_names; + continue; + } + + // Figure out what kind of a plugin that is + plugin_name = config_get_block_string(cfg, "plugin", NULL); + if (plugin_name == NULL) { + g_error("filter configuration without 'plugin' at line %d", + cfg->line); + ++template_names; + continue; + } + + // Instantiate one of those filter plugins with the template name as a hint + fp = filter_plugin_by_name(plugin_name); + if (fp == NULL) { + g_error("filter plugin not found: %s", + plugin_name); + ++template_names; + continue; + } + + f = filter_new(fp, cfg, NULL); + if (f == NULL) { + g_error("filter plugin initialization failed: %s", + plugin_name); + ++template_names; + continue; + } + + filter_chain_append(chain, f); + ++added_filters; + + ++template_names; + } + + g_strfreev(tokens); + + return added_filters; +} diff --git a/src/filter/chain_filter_plugin.h b/src/filter/chain_filter_plugin.h index f8462b22d..54e07081d 100644 --- a/src/filter/chain_filter_plugin.h +++ b/src/filter/chain_filter_plugin.h @@ -45,4 +45,16 @@ filter_chain_new(void); void filter_chain_append(struct filter *chain, struct filter *filter); +/** + * Builds a filter chain from a configuration string on the form + * "name1, name2, name3, ..." by looking up each name among the + * configured filter sections. If no filters are specified, a + * null filter is automatically appended. + * @param chain the chain to append filters on + * @param spec the filter chain specification + * @return the number of filters which were successfully added + */ +unsigned int +filter_chain_parse(struct filter *chain, const char *spec); + #endif diff --git a/src/output_init.c b/src/output_init.c index a1b79c994..6ca190fd0 100644 --- a/src/output_init.c +++ b/src/output_init.c @@ -41,6 +41,7 @@ #define AUDIO_OUTPUT_TYPE "type" #define AUDIO_OUTPUT_NAME "name" #define AUDIO_OUTPUT_FORMAT "format" +#define AUDIO_FILTERS "filters" static const struct audio_output_plugin * audio_output_detect(GError **error) @@ -190,6 +191,9 @@ audio_output_init(struct audio_output *ao, const struct config_param *param, ao->filter = filter_chain_new(); assert(ao->filter != NULL); + filter_chain_parse(ao->filter, + config_get_block_string(param, AUDIO_FILTERS, "") + ); ao->thread = NULL; ao->command = AO_COMMAND_NONE; |